From python-checkins at python.org Wed Jul 1 00:19:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 30 Jun 2015 22:19:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDAw?= =?utf-8?q?=3A_Remove_inspect=2Eisawaitable=28=29=2E?= Message-ID: <20150630221931.26909.28513@psf.io> https://hg.python.org/cpython/rev/e20c197f19d6 changeset: 96728:e20c197f19d6 branch: 3.5 parent: 96726:73c7d29a8c10 user: Yury Selivanov date: Tue Jun 30 18:19:01 2015 -0400 summary: Issue #24400: Remove inspect.isawaitable(). isawaitable() was added before collections.abc.Awaitable; now, with Awaitable, it is no longer needed (we don't have ishashable() or isiterable() methods in the inspect module either). files: Doc/library/inspect.rst | 10 ---------- Doc/whatsnew/3.5.rst | 5 ++--- Lib/inspect.py | 4 ---- Lib/test/test_inspect.py | 25 ------------------------- 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -303,16 +303,6 @@ .. versionadded:: 3.5 -.. function:: isawaitable(object) - - Return true if the object can be used in :keyword:`await` - expression. - - See also :class:`collections.abc.Awaitable`. - - .. versionadded:: 3.5 - - .. function:: istraceback(object) Return true if the object is a traceback. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -527,9 +527,8 @@ * New argument ``follow_wrapped`` for :func:`inspect.signature`. (Contributed by Yury Selivanov in :issue:`20691`.) -* New :func:`~inspect.iscoroutine`, :func:`~inspect.iscoroutinefunction`, - and :func:`~inspect.isawaitable` functions. (Contributed by Yury Selivanov - in :issue:`24017`.) +* New :func:`~inspect.iscoroutine` and :func:`~inspect.iscoroutinefunction` + functions. (Contributed by Yury Selivanov in :issue:`24017`.) * New :func:`~inspect.getcoroutinelocals` and :func:`~inspect.getcoroutinestate` functions. (Contributed by Yury Selivanov in :issue:`24400`.) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -186,10 +186,6 @@ return bool((isfunction(object) or ismethod(object)) and object.__code__.co_flags & CO_COROUTINE) -def isawaitable(object): - """Return true if the object can be used in "await" expression.""" - return isinstance(object, collections.abc.Awaitable) - def isgenerator(object): """Return true if the object is a generator. 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 @@ -159,31 +159,6 @@ coro.close(); gen_coro.close() # silence warnings - def test_isawaitable(self): - def gen(): yield - self.assertFalse(inspect.isawaitable(gen())) - - coro = coroutine_function_example(1) - gen_coro = gen_coroutine_function_example(1) - - self.assertTrue( - inspect.isawaitable(coro)) - self.assertTrue( - inspect.isawaitable(gen_coro)) - - class Future: - def __await__(): - pass - self.assertTrue(inspect.isawaitable(Future())) - self.assertFalse(inspect.isawaitable(Future)) - - class NotFuture: pass - not_fut = NotFuture() - not_fut.__await__ = lambda: None - self.assertFalse(inspect.isawaitable(not_fut)) - - coro.close(); gen_coro.close() # silence warnings - def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) self.assertTrue(inspect.isroutine([].count)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 00:19:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 30 Jun 2015 22:19:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0MDAp?= Message-ID: <20150630221931.13084.4339@psf.io> https://hg.python.org/cpython/rev/800bf6a0e0d5 changeset: 96729:800bf6a0e0d5 parent: 96727:5d43f103f66b parent: 96728:e20c197f19d6 user: Yury Selivanov date: Tue Jun 30 18:19:18 2015 -0400 summary: Merge 3.5 (Issue #24400) files: Doc/library/inspect.rst | 10 ---------- Doc/whatsnew/3.5.rst | 5 ++--- Lib/inspect.py | 4 ---- Lib/test/test_inspect.py | 25 ------------------------- 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -303,16 +303,6 @@ .. versionadded:: 3.5 -.. function:: isawaitable(object) - - Return true if the object can be used in :keyword:`await` - expression. - - See also :class:`collections.abc.Awaitable`. - - .. versionadded:: 3.5 - - .. function:: istraceback(object) Return true if the object is a traceback. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -527,9 +527,8 @@ * New argument ``follow_wrapped`` for :func:`inspect.signature`. (Contributed by Yury Selivanov in :issue:`20691`.) -* New :func:`~inspect.iscoroutine`, :func:`~inspect.iscoroutinefunction`, - and :func:`~inspect.isawaitable` functions. (Contributed by Yury Selivanov - in :issue:`24017`.) +* New :func:`~inspect.iscoroutine` and :func:`~inspect.iscoroutinefunction` + functions. (Contributed by Yury Selivanov in :issue:`24017`.) * New :func:`~inspect.getcoroutinelocals` and :func:`~inspect.getcoroutinestate` functions. (Contributed by Yury Selivanov in :issue:`24400`.) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -186,10 +186,6 @@ return bool((isfunction(object) or ismethod(object)) and object.__code__.co_flags & CO_COROUTINE) -def isawaitable(object): - """Return true if the object can be used in "await" expression.""" - return isinstance(object, collections.abc.Awaitable) - def isgenerator(object): """Return true if the object is a generator. 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 @@ -159,31 +159,6 @@ coro.close(); gen_coro.close() # silence warnings - def test_isawaitable(self): - def gen(): yield - self.assertFalse(inspect.isawaitable(gen())) - - coro = coroutine_function_example(1) - gen_coro = gen_coroutine_function_example(1) - - self.assertTrue( - inspect.isawaitable(coro)) - self.assertTrue( - inspect.isawaitable(gen_coro)) - - class Future: - def __await__(): - pass - self.assertTrue(inspect.isawaitable(Future())) - self.assertFalse(inspect.isawaitable(Future)) - - class NotFuture: pass - not_fut = NotFuture() - not_fut.__await__ = lambda: None - self.assertFalse(inspect.isawaitable(not_fut)) - - coro.close(); gen_coro.close() # silence warnings - def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) self.assertTrue(inspect.isroutine([].count)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 00:26:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 30 Jun 2015 22:26:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChORVdTKQ==?= Message-ID: <20150630222559.89409.14689@psf.io> https://hg.python.org/cpython/rev/e858afe55ce9 changeset: 96731:e858afe55ce9 parent: 96729:800bf6a0e0d5 parent: 96730:f22a0358418e user: Yury Selivanov date: Tue Jun 30 18:25:55 2015 -0400 summary: Merge 3.5 (NEWS) files: Misc/NEWS | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -46,7 +46,8 @@ works only for 'async def' coroutines; inspect.iscoroutine no longer uses collections.abc.Coroutine, it's intended to test for pure 'async def' coroutines only; add new opcode: GET_YIELD_FROM_ITER; fix generators wrapper - used in types.coroutine to be instance of collections.abc.Generator. + used in types.coroutine to be instance of collections.abc.Generator; + inspect.isawaitable was removed (use collections.abc.Awaitable). Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 00:26:01 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 30 Jun 2015 22:26:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Note_removal_o?= =?utf-8?q?f_inspect=2Eisawaitable=28=29_in_the_NEWS_file?= Message-ID: <20150630222558.106268.14502@psf.io> https://hg.python.org/cpython/rev/f22a0358418e changeset: 96730:f22a0358418e branch: 3.5 parent: 96728:e20c197f19d6 user: Yury Selivanov date: Tue Jun 30 18:25:36 2015 -0400 summary: Note removal of inspect.isawaitable() in the NEWS file files: Misc/NEWS | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,7 +24,8 @@ works only for 'async def' coroutines; inspect.iscoroutine no longer uses collections.abc.Coroutine, it's intended to test for pure 'async def' coroutines only; add new opcode: GET_YIELD_FROM_ITER; fix generators wrapper - used in types.coroutine to be instance of collections.abc.Generator. + used in types.coroutine to be instance of collections.abc.Generator; + inspect.isawaitable was removed (use collections.abc.Awaitable). Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 00:30:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 30 Jun 2015 22:30:45 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_inspect=2Eisawait?= =?utf-8?q?able_is_dead=2C_long_live_abc=2EAwaitable=2E?= Message-ID: <20150630223045.20146.68534@psf.io> https://hg.python.org/peps/rev/201dce690493 changeset: 5901:201dce690493 user: Yury Selivanov date: Tue Jun 30 18:30:43 2015 -0400 summary: pep-0492: inspect.isawaitable is dead, long live abc.Awaitable. files: pep-0492.txt | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -701,9 +701,6 @@ * ``inspect.iscoroutinefunction(obj)`` returns ``True`` if ``obj`` is a *native coroutine function*. -* ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` can be used - in ``await`` expression. See `Await Expression`_ for details. - * ``inspect.getcoroutinestate(coro)`` returns the current state of a *native coroutine object* (mirrors ``inspect.getfgeneratorstate(gen)``). @@ -1360,8 +1357,8 @@ 6. New functions: ``sys.set_coroutine_wrapper(callback)``, ``sys.get_coroutine_wrapper()``, ``types.coroutine(gen)``, ``inspect.iscoroutinefunction(func)``, ``inspect.iscoroutine(obj)``, - ``inspect.isawaitable(obj)``, ``inspect.getcoroutinestate(coro)``, - and ``inspect.getcoroutinelocals(coro)``. + ``inspect.getcoroutinestate(coro)``, and + ``inspect.getcoroutinelocals(coro)``. 7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Jul 1 03:19:04 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 01:19:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDAw?= =?utf-8?q?=3A_Fix_failing_unittest?= Message-ID: <20150701011904.28405.67573@psf.io> https://hg.python.org/cpython/rev/0b7c313851ca changeset: 96732:0b7c313851ca branch: 3.5 parent: 96730:f22a0358418e user: Yury Selivanov date: Tue Jun 30 21:18:27 2015 -0400 summary: Issue #24400: Fix failing unittest files: Lib/test/test_inspect.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -95,7 +95,7 @@ count = len([x for x in dir(inspect) if x.startswith('is')]) # This test is here for remember you to update Doc/library/inspect.rst # which claims there are 16 such functions - expected = 19 + expected = 18 err_msg = "There are %d (not %d) is* functions" % (count, expected) self.assertEqual(count, expected, err_msg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 03:19:04 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 01:19:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0MDAp?= Message-ID: <20150701011904.87143.48454@psf.io> https://hg.python.org/cpython/rev/8c85291e86bf changeset: 96733:8c85291e86bf parent: 96731:e858afe55ce9 parent: 96732:0b7c313851ca user: Yury Selivanov date: Tue Jun 30 21:19:00 2015 -0400 summary: Merge 3.5 (Issue #24400) files: Lib/test/test_inspect.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -95,7 +95,7 @@ count = len([x for x in dir(inspect) if x.startswith('is')]) # This test is here for remember you to update Doc/library/inspect.rst # which claims there are 16 such functions - expected = 19 + expected = 18 err_msg = "There are %d (not %d) is* functions" % (count, expected) self.assertEqual(count, expected, err_msg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 03:45:19 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 01:45:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTQx?= =?utf-8?q?=3A_Update_comment_in_test=5Finspect=2Etest=5Feightteen?= Message-ID: <20150701014519.12875.31802@psf.io> https://hg.python.org/cpython/rev/a5c6eaa7d733 changeset: 96734:a5c6eaa7d733 branch: 3.5 parent: 96732:0b7c313851ca user: Yury Selivanov date: Tue Jun 30 21:44:52 2015 -0400 summary: Issue #24541: Update comment in test_inspect.test_eightteen files: Lib/test/test_inspect.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -94,7 +94,7 @@ def test_eightteen(self): count = len([x for x in dir(inspect) if x.startswith('is')]) # This test is here for remember you to update Doc/library/inspect.rst - # which claims there are 16 such functions + # which claims there are 18 such functions expected = 18 err_msg = "There are %d (not %d) is* functions" % (count, expected) self.assertEqual(count, expected, err_msg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 03:45:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 01:45:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150701014519.65316.78685@psf.io> https://hg.python.org/cpython/rev/df310e5ac015 changeset: 96735:df310e5ac015 parent: 96733:8c85291e86bf parent: 96734:a5c6eaa7d733 user: Yury Selivanov date: Tue Jun 30 21:45:03 2015 -0400 summary: Merge 3.5 files: Lib/test/test_inspect.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -94,7 +94,7 @@ def test_eightteen(self): count = len([x for x in dir(inspect) if x.startswith('is')]) # This test is here for remember you to update Doc/library/inspect.rst - # which claims there are 16 such functions + # which claims there are 18 such functions expected = 18 err_msg = "There are %d (not %d) is* functions" % (count, expected) self.assertEqual(count, expected, err_msg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 04:07:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 02:07:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTQx?= =?utf-8?q?=3A_Drop_test=5Finspect=2Etest=5Feightteen_unittest=3B_update_d?= =?utf-8?q?ocs?= Message-ID: <20150701020700.21113.41052@psf.io> https://hg.python.org/cpython/rev/bd45435fd081 changeset: 96736:bd45435fd081 branch: 3.5 parent: 96734:a5c6eaa7d733 user: Yury Selivanov date: Tue Jun 30 22:06:42 2015 -0400 summary: Issue #24541: Drop test_inspect.test_eightteen unittest; update docs Suggested by Martin Panter. files: Doc/library/inspect.rst | 2 +- Lib/test/test_inspect.py | 8 -------- 2 files changed, 1 insertions(+), 9 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -28,7 +28,7 @@ ----------------- The :func:`getmembers` function retrieves the members of an object such as a -class or module. The sixteen functions whose names begin with "is" are mainly +class or module. The functions whose names begin with "is" are mainly provided as convenient choices for the second argument to :func:`getmembers`. They also help you determine when you can expect to find the following special attributes: 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 @@ -91,14 +91,6 @@ class TestPredicates(IsTestBase): - def test_eightteen(self): - count = len([x for x in dir(inspect) if x.startswith('is')]) - # This test is here for remember you to update Doc/library/inspect.rst - # which claims there are 18 such functions - expected = 18 - err_msg = "There are %d (not %d) is* functions" % (count, expected) - self.assertEqual(count, expected, err_msg) - def test_excluding_predicates(self): global tb -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 04:07:01 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 02:07:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150701020700.24410.70095@psf.io> https://hg.python.org/cpython/rev/1b87b31434d8 changeset: 96737:1b87b31434d8 parent: 96735:df310e5ac015 parent: 96736:bd45435fd081 user: Yury Selivanov date: Tue Jun 30 22:06:55 2015 -0400 summary: Merge 3.5 files: Doc/library/inspect.rst | 2 +- Lib/test/test_inspect.py | 8 -------- 2 files changed, 1 insertions(+), 9 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -28,7 +28,7 @@ ----------------- The :func:`getmembers` function retrieves the members of an object such as a -class or module. The sixteen functions whose names begin with "is" are mainly +class or module. The functions whose names begin with "is" are mainly provided as convenient choices for the second argument to :func:`getmembers`. They also help you determine when you can expect to find the following special attributes: 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 @@ -91,14 +91,6 @@ class TestPredicates(IsTestBase): - def test_eightteen(self): - count = len([x for x in dir(inspect) if x.startswith('is')]) - # This test is here for remember you to update Doc/library/inspect.rst - # which claims there are 18 such functions - expected = 18 - err_msg = "There are %d (not %d) is* functions" % (count, expected) - self.assertEqual(count, expected, err_msg) - def test_excluding_predicates(self): global tb -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 04:14:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 02:14:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0ODcp?= Message-ID: <20150701021413.27321.88841@psf.io> https://hg.python.org/cpython/rev/3dc2a113e8a7 changeset: 96739:3dc2a113e8a7 parent: 96737:1b87b31434d8 parent: 96738:1b3be273e327 user: Yury Selivanov date: Tue Jun 30 22:13:56 2015 -0400 summary: Merge 3.5 (Issue #24487) files: Doc/library/asyncio-dev.rst | 12 ++++++------ Doc/library/asyncio-eventloop.rst | 2 +- Doc/library/asyncio-protocol.rst | 6 +++--- Doc/library/asyncio-task.rst | 6 +++--- 4 files changed, 13 insertions(+), 13 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 @@ -99,7 +99,7 @@ :meth:`BaseEventLoop.call_soon_threadsafe` method should be used. Example to schedule a coroutine from a different thread:: - loop.call_soon_threadsafe(asyncio.async, coro_func()) + loop.call_soon_threadsafe(asyncio.ensure_future, 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 @@ -162,10 +162,10 @@ ---------------------------------------- When a coroutine function is called and its result is not passed to -:func:`async` or to the :meth:`BaseEventLoop.create_task` method, the execution -of the coroutine object will never be scheduled which is probably a bug. -:ref:`Enable the debug mode of asyncio ` to :ref:`log a -warning ` to detect it. +:func:`ensure_future` or to the :meth:`BaseEventLoop.create_task` method, +the execution of the coroutine object will never be scheduled which is +probably a bug. :ref:`Enable the debug mode of asyncio ` +to :ref:`log a warning ` to detect it. Example with the bug:: @@ -184,7 +184,7 @@ File "test.py", line 7, in test() -The fix is to call the :func:`async` function or the +The fix is to call the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method with the coroutine object. .. seealso:: 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 @@ -36,7 +36,7 @@ Run until the :class:`Future` is done. If the argument is a :ref:`coroutine object `, it is wrapped by - :func:`async`. + :func:`ensure_future`. Return the Future's result, or raise its exception. 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 @@ -448,9 +448,9 @@ Coroutines and protocols ------------------------ -Coroutines can be scheduled in a protocol method using :func:`async`, but there -is no guarantee made about the execution order. Protocols are not aware of -coroutines created in protocol methods and so will not wait for them. +Coroutines can be scheduled in a protocol method using :func:`ensure_future`, +but there is no guarantee made about the execution order. Protocols are not +aware of coroutines created in protocol methods and so will not wait for them. To have a reliable execution order, use :ref:`stream objects ` in a coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain` 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 @@ -59,7 +59,7 @@ schedule its execution. There are two basic ways to start it running: call ``await coroutine`` or ``yield from coroutine`` from another coroutine (assuming the other coroutine is already running!), or schedule its execution -using the :func:`async` function or the :meth:`BaseEventLoop.create_task` +using the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method. @@ -85,7 +85,7 @@ 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`. + used in a callback-style code, wrap its result with :func:`ensure_future`. .. _asyncio-hello-world-coroutine: @@ -394,7 +394,7 @@ ` did not complete. It is probably a bug and a warning is logged: see :ref:`Pending task destroyed `. - Don't directly create :class:`Task` instances: use the :func:`async` + Don't directly create :class:`Task` instances: use the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method. This class is :ref:`not thread safe `. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 04:14:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 02:14:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDg3?= =?utf-8?q?=3A_Rename_async=28=29_-=3E_ensure=5Ffuture=28=29_in_asyncio_do?= =?utf-8?b?Y3Mu?= Message-ID: <20150701021412.85260.26502@psf.io> https://hg.python.org/cpython/rev/1b3be273e327 changeset: 96738:1b3be273e327 branch: 3.5 parent: 96736:bd45435fd081 user: Yury Selivanov date: Tue Jun 30 22:13:22 2015 -0400 summary: Issue #24487: Rename async() -> ensure_future() in asyncio docs. Patch by Martin Panter. files: Doc/library/asyncio-dev.rst | 12 ++++++------ Doc/library/asyncio-eventloop.rst | 2 +- Doc/library/asyncio-protocol.rst | 6 +++--- Doc/library/asyncio-task.rst | 6 +++--- 4 files changed, 13 insertions(+), 13 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 @@ -99,7 +99,7 @@ :meth:`BaseEventLoop.call_soon_threadsafe` method should be used. Example to schedule a coroutine from a different thread:: - loop.call_soon_threadsafe(asyncio.async, coro_func()) + loop.call_soon_threadsafe(asyncio.ensure_future, 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 @@ -162,10 +162,10 @@ ---------------------------------------- When a coroutine function is called and its result is not passed to -:func:`async` or to the :meth:`BaseEventLoop.create_task` method, the execution -of the coroutine object will never be scheduled which is probably a bug. -:ref:`Enable the debug mode of asyncio ` to :ref:`log a -warning ` to detect it. +:func:`ensure_future` or to the :meth:`BaseEventLoop.create_task` method, +the execution of the coroutine object will never be scheduled which is +probably a bug. :ref:`Enable the debug mode of asyncio ` +to :ref:`log a warning ` to detect it. Example with the bug:: @@ -184,7 +184,7 @@ File "test.py", line 7, in test() -The fix is to call the :func:`async` function or the +The fix is to call the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method with the coroutine object. .. seealso:: 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 @@ -36,7 +36,7 @@ Run until the :class:`Future` is done. If the argument is a :ref:`coroutine object `, it is wrapped by - :func:`async`. + :func:`ensure_future`. Return the Future's result, or raise its exception. 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 @@ -448,9 +448,9 @@ Coroutines and protocols ------------------------ -Coroutines can be scheduled in a protocol method using :func:`async`, but there -is no guarantee made about the execution order. Protocols are not aware of -coroutines created in protocol methods and so will not wait for them. +Coroutines can be scheduled in a protocol method using :func:`ensure_future`, +but there is no guarantee made about the execution order. Protocols are not +aware of coroutines created in protocol methods and so will not wait for them. To have a reliable execution order, use :ref:`stream objects ` in a coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain` 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 @@ -59,7 +59,7 @@ schedule its execution. There are two basic ways to start it running: call ``await coroutine`` or ``yield from coroutine`` from another coroutine (assuming the other coroutine is already running!), or schedule its execution -using the :func:`async` function or the :meth:`BaseEventLoop.create_task` +using the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method. @@ -85,7 +85,7 @@ 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`. + used in a callback-style code, wrap its result with :func:`ensure_future`. .. _asyncio-hello-world-coroutine: @@ -394,7 +394,7 @@ ` did not complete. It is probably a bug and a warning is logged: see :ref:`Pending task destroyed `. - Don't directly create :class:`Task` instances: use the :func:`async` + Don't directly create :class:`Task` instances: use the :func:`ensure_future` function or the :meth:`BaseEventLoop.create_task` method. This class is :ref:`not thread safe `. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed Jul 1 10:46:03 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 01 Jul 2015 08:46:03 +0000 Subject: [Python-checkins] Daily reference leaks (3dc2a113e8a7): sum=7 Message-ID: <20150701084603.3300.75405@psf.io> results for 3dc2a113e8a7 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogrt3cUA', '--timeout', '7200'] From python-checkins at python.org Wed Jul 1 17:31:57 2015 From: python-checkins at python.org (donald.stufft) Date: Wed, 01 Jul 2015 15:31:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Update_setupto?= =?utf-8?q?ols_to_18=2E0=2E1_and_pip_to_7=2E1=2E0?= Message-ID: <20150701153153.109639.79609@psf.io> https://hg.python.org/cpython/rev/814965258782 changeset: 96741:814965258782 branch: 3.4 parent: 96721:75571407dcd3 user: Donald Stufft date: Wed Jul 01 11:30:50 2015 -0400 summary: Update setuptools to 18.0.1 and pip to 7.1.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "17.0" +_SETUPTOOLS_VERSION = "18.0.1" -_PIP_VERSION = "7.0.3" +_PIP_VERSION = "7.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl deleted file mode 100644 index bb0cb3138ba4ade7fa5ba3285d04f70d439f490f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76fcad1c7efb6223b049967e84fda31f9fd68dfc GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl deleted file mode 100644 index a1d3561bad9c3709196b6481dd2e540b0914129b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..67aaca50a921a164fac7d721bc2aa80735c5515e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 17:44:59 2015 From: python-checkins at python.org (donald.stufft) Date: Wed, 01 Jul 2015 15:44:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_in_setuptools/pip_update?= Message-ID: <20150701153153.14971.69049@psf.io> https://hg.python.org/cpython/rev/5d1e16be1af6 changeset: 96742:5d1e16be1af6 branch: 3.5 parent: 96738:1b3be273e327 parent: 96741:814965258782 user: Donald Stufft date: Wed Jul 01 11:31:13 2015 -0400 summary: merge in setuptools/pip update files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "17.0" +_SETUPTOOLS_VERSION = "18.0.1" -_PIP_VERSION = "7.0.3" +_PIP_VERSION = "7.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl deleted file mode 100644 index bb0cb3138ba4ade7fa5ba3285d04f70d439f490f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76fcad1c7efb6223b049967e84fda31f9fd68dfc GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl deleted file mode 100644 index a1d3561bad9c3709196b6481dd2e540b0914129b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..67aaca50a921a164fac7d721bc2aa80735c5515e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 18:34:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 16:34:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDAw?= =?utf-8?q?=3A_Add_one_more_unittest_for_CoroutineType=2E=5F=5Fawait=5F=5F?= Message-ID: <20150701163444.18679.67580@psf.io> https://hg.python.org/cpython/rev/a9d38701536d changeset: 96744:a9d38701536d branch: 3.5 parent: 96742:5d1e16be1af6 user: Yury Selivanov date: Wed Jul 01 12:29:55 2015 -0400 summary: Issue #24400: Add one more unittest for CoroutineType.__await__ files: Lib/test/test_coroutines.py | 34 +++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -519,6 +519,40 @@ run_async(foo()) + def test_await_14(self): + class Wrapper: + # Forces the interpreter to use CoroutineType.__await__ + def __init__(self, coro): + assert coro.__class__ is types.CoroutineType + self.coro = coro + def __await__(self): + return self.coro.__await__() + + class FutureLike: + def __await__(self): + return (yield) + + class Marker(Exception): + pass + + async def coro1(): + try: + return await FutureLike() + except ZeroDivisionError: + raise Marker + async def coro2(): + return await Wrapper(coro1()) + + c = coro2() + c.send(None) + with self.assertRaisesRegex(StopIteration, 'spam'): + c.send('spam') + + c = coro2() + c.send(None) + with self.assertRaises(Marker): + c.throw(ZeroDivisionError) + def test_with_1(self): class Manager: def __init__(self, name): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 18:34:47 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 16:34:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150701163444.110093.33140@psf.io> https://hg.python.org/cpython/rev/ac4581bad6ef changeset: 96745:ac4581bad6ef parent: 96743:53975668c9e9 parent: 96744:a9d38701536d user: Yury Selivanov date: Wed Jul 01 12:30:26 2015 -0400 summary: Merge 3.5 files: Lib/test/test_coroutines.py | 34 +++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -519,6 +519,40 @@ run_async(foo()) + def test_await_14(self): + class Wrapper: + # Forces the interpreter to use CoroutineType.__await__ + def __init__(self, coro): + assert coro.__class__ is types.CoroutineType + self.coro = coro + def __await__(self): + return self.coro.__await__() + + class FutureLike: + def __await__(self): + return (yield) + + class Marker(Exception): + pass + + async def coro1(): + try: + return await FutureLike() + except ZeroDivisionError: + raise Marker + async def coro2(): + return await Wrapper(coro1()) + + c = coro2() + c.send(None) + with self.assertRaisesRegex(StopIteration, 'spam'): + c.send('spam') + + c = coro2() + c.send(None) + with self.assertRaises(Marker): + c.throw(ZeroDivisionError) + def test_with_1(self): class Manager: def __init__(self, name): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 18:49:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 16:49:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZSAjMjQ0MDAp?= Message-ID: <20150701164921.13068.18949@psf.io> https://hg.python.org/cpython/rev/4bf1d332fe73 changeset: 96747:4bf1d332fe73 parent: 96745:ac4581bad6ef parent: 96746:b2a3baa1c2b0 user: Yury Selivanov date: Wed Jul 01 12:49:17 2015 -0400 summary: Merge 3.5 (issue #24400) files: Doc/conf.py | 2 +- Doc/library/collections.abc.rst | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -44,7 +44,7 @@ # ----------------------- # Use our custom theme. -html_theme = 'pydoctheme' +html_theme = 'classic' html_theme_path = ['tools'] html_theme_options = {'collapsiblesidebar': True} diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -161,6 +161,12 @@ :term:`Coroutine` objects and instances of the :class:`~collections.abc.Coroutine` ABC are all instances of this ABC. + .. note:: + In CPython, generator-based coroutines are *awaitables*, even though + they do not have an :meth:`__await__` method. This ABC + implements an :meth:`~class.__instancecheck__` method to make them + instances of itself. + .. versionadded:: 3.5 .. class:: Coroutine @@ -172,6 +178,12 @@ :meth:`__await__`. All :class:`Coroutine` instances are also instances of :class:`Awaitable`. See also the definition of :term:`coroutine`. + .. note:: + In CPython, generator-based coroutines are *awaitables* and *coroutines*, + even though they do not have an :meth:`__await__` method. This ABC + implements an :meth:`~class.__instancecheck__` method to make them + instances of itself. + .. versionadded:: 3.5 .. class:: AsyncIterable -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 18:49:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 01 Jul 2015 16:49:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDAw?= =?utf-8?q?=3A_Mention_that_=5F=5Finstancecheck=5F=5F_is_used_in_abc=2EAwa?= =?utf-8?q?itable_and?= Message-ID: <20150701164921.13068.11467@psf.io> https://hg.python.org/cpython/rev/b2a3baa1c2b0 changeset: 96746:b2a3baa1c2b0 branch: 3.5 parent: 96744:a9d38701536d user: Yury Selivanov date: Wed Jul 01 12:49:00 2015 -0400 summary: Issue #24400: Mention that __instancecheck__ is used in abc.Awaitable and Coroutine files: Doc/conf.py | 2 +- Doc/library/collections.abc.rst | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -44,7 +44,7 @@ # ----------------------- # Use our custom theme. -html_theme = 'pydoctheme' +html_theme = 'classic' html_theme_path = ['tools'] html_theme_options = {'collapsiblesidebar': True} diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -161,6 +161,12 @@ :term:`Coroutine` objects and instances of the :class:`~collections.abc.Coroutine` ABC are all instances of this ABC. + .. note:: + In CPython, generator-based coroutines are *awaitables*, even though + they do not have an :meth:`__await__` method. This ABC + implements an :meth:`~class.__instancecheck__` method to make them + instances of itself. + .. versionadded:: 3.5 .. class:: Coroutine @@ -172,6 +178,12 @@ :meth:`__await__`. All :class:`Coroutine` instances are also instances of :class:`Awaitable`. See also the definition of :term:`coroutine`. + .. note:: + In CPython, generator-based coroutines are *awaitables* and *coroutines*, + even though they do not have an :meth:`__await__` method. This ABC + implements an :meth:`~class.__instancecheck__` method to make them + instances of itself. + .. versionadded:: 3.5 .. class:: AsyncIterable -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 19:04:30 2015 From: python-checkins at python.org (donald.stufft) Date: Wed, 01 Jul 2015 17:04:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge_in_setuptools/pip_update?= Message-ID: <20150701153154.130183.97996@psf.io> https://hg.python.org/cpython/rev/53975668c9e9 changeset: 96743:53975668c9e9 parent: 96739:3dc2a113e8a7 parent: 96742:5d1e16be1af6 user: Donald Stufft date: Wed Jul 01 11:31:38 2015 -0400 summary: merge in setuptools/pip update files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "17.0" +_SETUPTOOLS_VERSION = "18.0.1" -_PIP_VERSION = "7.0.3" +_PIP_VERSION = "7.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl deleted file mode 100644 index bb0cb3138ba4ade7fa5ba3285d04f70d439f490f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76fcad1c7efb6223b049967e84fda31f9fd68dfc GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl deleted file mode 100644 index a1d3561bad9c3709196b6481dd2e540b0914129b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..67aaca50a921a164fac7d721bc2aa80735c5515e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 1 22:06:56 2015 From: python-checkins at python.org (donald.stufft) Date: Wed, 01 Jul 2015 20:06:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_setupto?= =?utf-8?q?ols_to_18=2E0=2E1_and_pip_to_7=2E1=2E0?= Message-ID: <20150701153153.21513.79899@psf.io> https://hg.python.org/cpython/rev/b295b2286697 changeset: 96740:b295b2286697 branch: 2.7 parent: 96717:a887ce8611d2 user: Donald Stufft date: Wed Jul 01 11:29:34 2015 -0400 summary: Update setuptools to 18.0.1 and pip to 7.1.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "17.0" +_SETUPTOOLS_VERSION = "18.0.1" -_PIP_VERSION = "7.0.3" +_PIP_VERSION = "7.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl deleted file mode 100644 index bb0cb3138ba4ade7fa5ba3285d04f70d439f490f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76fcad1c7efb6223b049967e84fda31f9fd68dfc GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl deleted file mode 100644 index a1d3561bad9c3709196b6481dd2e540b0914129b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..67aaca50a921a164fac7d721bc2aa80735c5515e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 03:07:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 02 Jul 2015 01:07:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jcy9jb25mOiBV?= =?utf-8?q?ndo_changes_in_b2a3baa1c2b0=3B_issue_=2324400?= Message-ID: <20150702010723.20146.30295@psf.io> https://hg.python.org/cpython/rev/68996acdec6f changeset: 96748:68996acdec6f branch: 3.5 parent: 96746:b2a3baa1c2b0 user: Yury Selivanov date: Wed Jul 01 21:06:59 2015 -0400 summary: docs/conf: Undo changes in b2a3baa1c2b0; issue #24400 files: Doc/conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -44,7 +44,7 @@ # ----------------------- # Use our custom theme. -html_theme = 'classic' +html_theme = 'pydoctheme' html_theme_path = ['tools'] html_theme_options = {'collapsiblesidebar': True} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 03:07:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 02 Jul 2015 01:07:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150702010723.99345.27933@psf.io> https://hg.python.org/cpython/rev/67ae0fd72370 changeset: 96749:67ae0fd72370 parent: 96747:4bf1d332fe73 parent: 96748:68996acdec6f user: Yury Selivanov date: Wed Jul 01 21:07:20 2015 -0400 summary: Merge 3.5 files: Doc/conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -44,7 +44,7 @@ # ----------------------- # Use our custom theme. -html_theme = 'classic' +html_theme = 'pydoctheme' html_theme_path = ['tools'] html_theme_options = {'collapsiblesidebar': True} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 05:52:22 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 03:52:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150702033642.36294.21526@psf.io> https://hg.python.org/cpython/rev/dbb4fb46fc1d changeset: 96752:dbb4fb46fc1d parent: 96749:67ae0fd72370 parent: 96751:00d706bebc7b user: Benjamin Peterson date: Wed Jul 01 22:36:37 2015 -0500 summary: merge 3.5 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 @@ -1123,7 +1123,7 @@ .. _whatsnew-multiprocessing-no-fork: On Unix two new :ref:`start methods `, -(``spawn`` and ``forkserver``, have been added for starting processes using +``spawn`` and ``forkserver``, have been added for starting processes using :mod:`multiprocessing`. These make the mixing of processes with threads more robust, and the ``spawn`` method matches the semantics that multiprocessing has always used on Windows. New function -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 05:52:22 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 03:52:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_stray_?= =?utf-8?b?JygnIChjbG9zZXMgIzI0NTQ3KQ==?= Message-ID: <20150702033641.130183.30856@psf.io> https://hg.python.org/cpython/rev/74e75a9aa562 changeset: 96750:74e75a9aa562 branch: 3.4 parent: 96741:814965258782 user: Benjamin Peterson date: Wed Jul 01 22:36:21 2015 -0500 summary: remove stray '(' (closes #24547) 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 @@ -1123,7 +1123,7 @@ .. _whatsnew-multiprocessing-no-fork: On Unix two new :ref:`start methods `, -(``spawn`` and ``forkserver``, have been added for starting processes using +``spawn`` and ``forkserver``, have been added for starting processes using :mod:`multiprocessing`. These make the mixing of processes with threads more robust, and the ``spawn`` method matches the semantics that multiprocessing has always used on Windows. New function -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 06:41:41 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 04:41:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150702033641.21568.26594@psf.io> https://hg.python.org/cpython/rev/00d706bebc7b changeset: 96751:00d706bebc7b branch: 3.5 parent: 96748:68996acdec6f parent: 96750:74e75a9aa562 user: Benjamin Peterson date: Wed Jul 01 22:36:29 2015 -0500 summary: Merge 3.4 files: Doc/whatsnew/3.4.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1123,7 +1123,7 @@ .. _whatsnew-multiprocessing-no-fork: On Unix two new :ref:`start methods `, -(``spawn`` and ``forkserver``, have been added for starting processes using +``spawn`` and ``forkserver``, have been added for starting processes using :mod:`multiprocessing`. These make the mixing of processes with threads more robust, and the ``spawn`` method matches the semantics that multiprocessing has always used on Windows. New function -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Jul 2 10:44:55 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 02 Jul 2015 08:44:55 +0000 Subject: [Python-checkins] Daily reference leaks (dbb4fb46fc1d): sum=4 Message-ID: <20150702084455.28944.88968@psf.io> results for dbb4fb46fc1d on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogutPvOi', '--timeout', '7200'] From python-checkins at python.org Thu Jul 2 19:44:33 2015 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 02 Jul 2015 17:44:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NTE0?= =?utf-8?q?=3A_tarfile_now_tolerates_number_fields_consisting_of_only_whit?= =?utf-8?q?espace=2E?= Message-ID: <20150702174432.22264.26396@psf.io> https://hg.python.org/cpython/rev/301d7efac3de changeset: 96753:301d7efac3de branch: 2.7 parent: 96740:b295b2286697 user: Lars Gust?bel date: Thu Jul 02 19:37:08 2015 +0200 summary: Issue #24514: tarfile now tolerates number fields consisting of only whitespace. files: Lib/tarfile.py | 2 +- Lib/test/test_tarfile.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -186,7 +186,7 @@ # itn() below. if s[0] != chr(0200): try: - n = int(nts(s) or "0", 8) + n = int(nts(s).strip() or "0", 8) except ValueError: raise InvalidHeaderError("invalid header") else: 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 @@ -1566,6 +1566,14 @@ tarinfo.tobuf(tarfile.PAX_FORMAT) +class MiscTest(unittest.TestCase): + + def test_read_number_fields(self): + # Issue 24514: Test if empty number fields are converted to zero. + self.assertEqual(tarfile.nti("\0"), 0) + self.assertEqual(tarfile.nti(" \0"), 0) + + class ContextManagerTest(unittest.TestCase): def test_basic(self): @@ -1730,6 +1738,7 @@ PaxUnicodeTest, AppendTest, LimitsTest, + MiscTest, ContextManagerTest, ] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #24514: tarfile now tolerates number fields consisting of only + whitespace. + - Issue #20387: Restore semantic round-trip correctness in tokenize/untokenize for tab-indented blocks. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 19:44:33 2015 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 02 Jul 2015 17:44:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NTE0?= =?utf-8?q?=3A_tarfile_now_tolerates_number_fields_consisting_of_only_whit?= =?utf-8?q?espace=2E?= Message-ID: <20150702174433.24661.70056@psf.io> https://hg.python.org/cpython/rev/140b4b7b84bd changeset: 96754:140b4b7b84bd branch: 3.4 parent: 96750:74e75a9aa562 user: Lars Gust?bel date: Thu Jul 02 19:38:38 2015 +0200 summary: Issue #24514: tarfile now tolerates number fields consisting of only whitespace. files: Lib/tarfile.py | 3 ++- Lib/test/test_tarfile.py | 4 ++++ Misc/NEWS | 3 +++ 3 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -178,7 +178,8 @@ n = -(256 ** (len(s) - 1) - n) else: try: - n = int(nts(s, "ascii", "strict") or "0", 8) + s = nts(s, "ascii", "strict") + n = int(s.strip() or "0", 8) except ValueError: raise InvalidHeaderError("invalid header") return n 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 @@ -1842,6 +1842,10 @@ self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"), -0x100000000000000) + # Issue 24514: Test if empty number fields are converted to zero. + self.assertEqual(tarfile.nti(b"\0"), 0) + self.assertEqual(tarfile.nti(b" \0"), 0) + def test_write_number_fields(self): self.assertEqual(tarfile.itn(1), b"0000001\x00") self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,9 @@ Library ------- +- Issue #24514: tarfile now tolerates number fields consisting of only + whitespace. + - Issue #19176: Fixed doctype() related bugs in C implementation of ElementTree. A deprecation warning no longer issued by XMLParser subclass with default doctype() method. Direct call of doctype() now issues a warning. Parser's -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 19:44:35 2015 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 02 Jul 2015 17:44:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5=3A_Issue_=2324514=3A_tarfile_now_tolera?= =?utf-8?q?tes_number_fields_consisting_of?= Message-ID: <20150702174433.12463.10060@psf.io> https://hg.python.org/cpython/rev/08fad9037206 changeset: 96756:08fad9037206 parent: 96752:dbb4fb46fc1d parent: 96755:1692065524cc user: Lars Gust?bel date: Thu Jul 02 19:42:09 2015 +0200 summary: Merge with 3.5: Issue #24514: tarfile now tolerates number fields consisting of only whitespace. files: Lib/tarfile.py | 3 ++- Lib/test/test_tarfile.py | 4 ++++ Misc/NEWS | 3 +++ 3 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -178,7 +178,8 @@ n = -(256 ** (len(s) - 1) - n) else: try: - n = int(nts(s, "ascii", "strict") or "0", 8) + s = nts(s, "ascii", "strict") + n = int(s.strip() or "0", 8) except ValueError: raise InvalidHeaderError("invalid header") return n 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 @@ -1952,6 +1952,10 @@ self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"), -0x100000000000000) + # Issue 24514: Test if empty number fields are converted to zero. + self.assertEqual(tarfile.nti(b"\0"), 0) + self.assertEqual(tarfile.nti(b" \0"), 0) + def test_write_number_fields(self): self.assertEqual(tarfile.itn(1), b"0000001\x00") self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,9 @@ Library ------- +- Issue #24514: tarfile now tolerates number fields consisting of only + whitespace. + - Issue #19176: Fixed doctype() related bugs in C implementation of ElementTree. A deprecation warning no longer issued by XMLParser subclass with default doctype() method. Direct call of doctype() now issues a warning. Parser's -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 19:44:35 2015 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 02 Jul 2015 17:44:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4=3A_Issue_=2324514=3A_tarfile_now_tolerates_nu?= =?utf-8?q?mber_fields_consisting_of?= Message-ID: <20150702174433.99807.20489@psf.io> https://hg.python.org/cpython/rev/1692065524cc changeset: 96755:1692065524cc branch: 3.5 parent: 96751:00d706bebc7b parent: 96754:140b4b7b84bd user: Lars Gust?bel date: Thu Jul 02 19:41:03 2015 +0200 summary: Merge with 3.4: Issue #24514: tarfile now tolerates number fields consisting of only whitespace. files: Lib/tarfile.py | 3 ++- Lib/test/test_tarfile.py | 4 ++++ Misc/NEWS | 3 +++ 3 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -178,7 +178,8 @@ n = -(256 ** (len(s) - 1) - n) else: try: - n = int(nts(s, "ascii", "strict") or "0", 8) + s = nts(s, "ascii", "strict") + n = int(s.strip() or "0", 8) except ValueError: raise InvalidHeaderError("invalid header") return n 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 @@ -1952,6 +1952,10 @@ self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"), -0x100000000000000) + # Issue 24514: Test if empty number fields are converted to zero. + self.assertEqual(tarfile.nti(b"\0"), 0) + self.assertEqual(tarfile.nti(b" \0"), 0) + def test_write_number_fields(self): self.assertEqual(tarfile.itn(1), b"0000001\x00") self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,9 @@ Library ------- +- Issue #24514: tarfile now tolerates number fields consisting of only + whitespace. + - Issue #19176: Fixed doctype() related bugs in C implementation of ElementTree. A deprecation warning no longer issued by XMLParser subclass with default doctype() method. Direct call of doctype() now issues a warning. Parser's -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 20:30:59 2015 From: python-checkins at python.org (stefan.krah) Date: Thu, 02 Jul 2015 18:30:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUgKCMyNDU0Myku?= Message-ID: <20150702183059.2656.70701@psf.io> https://hg.python.org/cpython/rev/8f30776602b4 changeset: 96758:8f30776602b4 parent: 96756:08fad9037206 parent: 96757:2be983173f45 user: Stefan Krah date: Thu Jul 02 20:28:45 2015 +0200 summary: Merge from 3.5 (#24543). files: configure | 15 +++++++++------ configure.ac | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -13397,12 +13397,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_x64=yes else have_gcc_asm_for_x64=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x64" >&5 $as_echo "$have_gcc_asm_for_x64" >&6; } if test "$have_gcc_asm_for_x64" = yes @@ -13573,12 +13574,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_x87=yes else have_gcc_asm_for_x87=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x87" >&5 $as_echo "$have_gcc_asm_for_x87" >&6; } if test "$have_gcc_asm_for_x87" = yes @@ -13605,12 +13607,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_mc68881=yes else have_gcc_asm_for_mc68881=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_mc68881" >&5 $as_echo "$have_gcc_asm_for_mc68881" >&6; } if test "$have_gcc_asm_for_mc68881" = yes diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3910,7 +3910,7 @@ # ************************************** AC_MSG_CHECKING(for x64 gcc inline assembler) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ __asm__ __volatile__ ("movq %rcx, %rax"); ]])],[have_gcc_asm_for_x64=yes],[have_gcc_asm_for_x64=no]) AC_MSG_RESULT($have_gcc_asm_for_x64) @@ -4008,7 +4008,7 @@ # so we try it on all platforms. AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set x87 control word) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); __asm__ __volatile__ ("fldcw %0" : : "m" (cw)); @@ -4021,7 +4021,7 @@ fi AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set mc68881 fpcr) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned int fpcr; __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=g" (fpcr)); __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "g" (fpcr)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 20:31:03 2015 From: python-checkins at python.org (stefan.krah) Date: Thu, 02 Jul 2015 18:31:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTQz?= =?utf-8?q?=3A_Use_AC=5FLINK_instead_of_AC=5FCOMPILE_in_order_to_prevent_f?= =?utf-8?q?alse?= Message-ID: <20150702183059.86858.44518@psf.io> https://hg.python.org/cpython/rev/2be983173f45 changeset: 96757:2be983173f45 branch: 3.5 parent: 96755:1692065524cc user: Stefan Krah date: Thu Jul 02 20:27:56 2015 +0200 summary: Issue #24543: Use AC_LINK instead of AC_COMPILE in order to prevent false positives with the -flto option (gcc >= 4.9.0 and clang). files: configure | 15 +++++++++------ configure.ac | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -13397,12 +13397,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_x64=yes else have_gcc_asm_for_x64=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x64" >&5 $as_echo "$have_gcc_asm_for_x64" >&6; } if test "$have_gcc_asm_for_x64" = yes @@ -13573,12 +13574,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_x87=yes else have_gcc_asm_for_x87=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x87" >&5 $as_echo "$have_gcc_asm_for_x87" >&6; } if test "$have_gcc_asm_for_x87" = yes @@ -13605,12 +13607,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_mc68881=yes else have_gcc_asm_for_mc68881=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_mc68881" >&5 $as_echo "$have_gcc_asm_for_mc68881" >&6; } if test "$have_gcc_asm_for_mc68881" = yes diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3910,7 +3910,7 @@ # ************************************** AC_MSG_CHECKING(for x64 gcc inline assembler) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ __asm__ __volatile__ ("movq %rcx, %rax"); ]])],[have_gcc_asm_for_x64=yes],[have_gcc_asm_for_x64=no]) AC_MSG_RESULT($have_gcc_asm_for_x64) @@ -4008,7 +4008,7 @@ # so we try it on all platforms. AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set x87 control word) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); __asm__ __volatile__ ("fldcw %0" : : "m" (cw)); @@ -4021,7 +4021,7 @@ fi AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set mc68881 fpcr) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned int fpcr; __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=g" (fpcr)); __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "g" (fpcr)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:19:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:19:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_fix_use_after_?= =?utf-8?q?free_=28closes_=2324552=29?= Message-ID: <20150702211940.15337.9357@psf.io> https://hg.python.org/cpython/rev/24ce32d76376 changeset: 96759:24ce32d76376 branch: 3.4 parent: 96754:140b4b7b84bd user: Benjamin Peterson date: Thu Jul 02 16:18:38 2015 -0500 summary: fix use after free (closes #24552) files: Lib/test/pickletester.py | 12 ++++++++++++ Misc/NEWS | 2 ++ Modules/_pickle.c | 2 +- 3 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1039,6 +1039,18 @@ self.assertEqual(B(x), B(y), detail) self.assertEqual(x.__dict__, y.__dict__, detail) + def test_newobj_not_class(self): + # Issue 24552 + global SimpleNewObj + save = SimpleNewObj + o = object.__new__(SimpleNewObj) + b = self.dumps(o, 4) + try: + SimpleNewObj = 42 + self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b) + finally: + SimpleNewObj = save + # Register a type with copyreg, with extension code extcode. Pickle # an object of that type. Check that the resulting pickle uses opcode # (EXT[124]) under proto 2, and not in proto 1. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,8 @@ Library ------- +- Issue #24552: Fix use after free in an error case of the _pickle module. + - Issue #24514: tarfile now tolerates number fields consisting of only whitespace. diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -5210,10 +5210,10 @@ if (!PyType_Check(cls)) { Py_DECREF(kwargs); Py_DECREF(args); - Py_DECREF(cls); PyErr_Format(st->UnpicklingError, "NEWOBJ_EX class argument must be a type, not %.200s", Py_TYPE(cls)->tp_name); + Py_DECREF(cls); return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:19:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:19:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQ1NTIp?= Message-ID: <20150702211940.1304.55551@psf.io> https://hg.python.org/cpython/rev/32486bb59e7e changeset: 96761:32486bb59e7e parent: 96758:8f30776602b4 parent: 96760:24197b5f7126 user: Benjamin Peterson date: Thu Jul 02 16:19:05 2015 -0500 summary: merge 3.5 (#24552) files: Lib/test/pickletester.py | 12 ++++++++++++ Misc/NEWS | 2 ++ Modules/_pickle.c | 2 +- 3 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1039,6 +1039,18 @@ self.assertEqual(B(x), B(y), detail) self.assertEqual(x.__dict__, y.__dict__, detail) + def test_newobj_not_class(self): + # Issue 24552 + global SimpleNewObj + save = SimpleNewObj + o = object.__new__(SimpleNewObj) + b = self.dumps(o, 4) + try: + SimpleNewObj = 42 + self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b) + finally: + SimpleNewObj = save + # Register a type with copyreg, with extension code extcode. Pickle # an object of that type. Check that the resulting pickle uses opcode # (EXT[124]) under proto 2, and not in proto 1. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,8 @@ Library ------- +- Issue #24552: Fix use after free in an error case of the _pickle module. + - Issue #24514: tarfile now tolerates number fields consisting of only whitespace. diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -5279,10 +5279,10 @@ if (!PyType_Check(cls)) { Py_DECREF(kwargs); Py_DECREF(args); - Py_DECREF(cls); PyErr_Format(st->UnpicklingError, "NEWOBJ_EX class argument must be a type, not %.200s", Py_TYPE(cls)->tp_name); + Py_DECREF(cls); return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:19:42 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:19:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4_=28=2324552=29?= Message-ID: <20150702211940.27321.77170@psf.io> https://hg.python.org/cpython/rev/24197b5f7126 changeset: 96760:24197b5f7126 branch: 3.5 parent: 96757:2be983173f45 parent: 96759:24ce32d76376 user: Benjamin Peterson date: Thu Jul 02 16:18:58 2015 -0500 summary: merge 3.4 (#24552) files: Lib/test/pickletester.py | 12 ++++++++++++ Misc/NEWS | 2 ++ Modules/_pickle.c | 2 +- 3 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1039,6 +1039,18 @@ self.assertEqual(B(x), B(y), detail) self.assertEqual(x.__dict__, y.__dict__, detail) + def test_newobj_not_class(self): + # Issue 24552 + global SimpleNewObj + save = SimpleNewObj + o = object.__new__(SimpleNewObj) + b = self.dumps(o, 4) + try: + SimpleNewObj = 42 + self.assertRaises((TypeError, pickle.UnpicklingError), self.loads, b) + finally: + SimpleNewObj = save + # Register a type with copyreg, with extension code extcode. Pickle # an object of that type. Check that the resulting pickle uses opcode # (EXT[124]) under proto 2, and not in proto 1. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,8 @@ Library ------- +- Issue #24552: Fix use after free in an error case of the _pickle module. + - Issue #24514: tarfile now tolerates number fields consisting of only whitespace. diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -5279,10 +5279,10 @@ if (!PyType_Check(cls)) { Py_DECREF(kwargs); Py_DECREF(args); - Py_DECREF(cls); PyErr_Format(st->UnpicklingError, "NEWOBJ_EX class argument must be a type, not %.200s", Py_TYPE(cls)->tp_name); + Py_DECREF(cls); return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:59:17 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:59:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_use_correct_?= =?utf-8?b?X19uZXdfXyBtZXRob2QgKGNsb3NlcyAjMjQ1NTIp?= Message-ID: <20150702215916.66728.17581@psf.io> https://hg.python.org/cpython/rev/978bc1ff43a7 changeset: 96762:978bc1ff43a7 branch: 3.4 parent: 96759:24ce32d76376 user: Benjamin Peterson date: Thu Jul 02 16:58:22 2015 -0500 summary: use correct __new__ method (closes #24552) files: Lib/test/pickletester.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1043,7 +1043,7 @@ # Issue 24552 global SimpleNewObj save = SimpleNewObj - o = object.__new__(SimpleNewObj) + o = SimpleNewObj.__new__(SimpleNewObj) b = self.dumps(o, 4) try: SimpleNewObj = 42 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:59:17 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:59:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150702215917.111341.81089@psf.io> https://hg.python.org/cpython/rev/14be2ab42294 changeset: 96764:14be2ab42294 parent: 96761:32486bb59e7e parent: 96763:b1caa38c81ab user: Benjamin Peterson date: Thu Jul 02 16:58:38 2015 -0500 summary: merge 3.5 files: Lib/test/pickletester.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1043,7 +1043,7 @@ # Issue 24552 global SimpleNewObj save = SimpleNewObj - o = object.__new__(SimpleNewObj) + o = SimpleNewObj.__new__(SimpleNewObj) b = self.dumps(o, 4) try: SimpleNewObj = 42 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 2 23:59:17 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Jul 2015 21:59:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150702215916.32358.65377@psf.io> https://hg.python.org/cpython/rev/b1caa38c81ab changeset: 96763:b1caa38c81ab branch: 3.5 parent: 96760:24197b5f7126 parent: 96762:978bc1ff43a7 user: Benjamin Peterson date: Thu Jul 02 16:58:31 2015 -0500 summary: merge 3.4 files: Lib/test/pickletester.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1043,7 +1043,7 @@ # Issue 24552 global SimpleNewObj save = SimpleNewObj - o = object.__new__(SimpleNewObj) + o = SimpleNewObj.__new__(SimpleNewObj) b = self.dumps(o, 4) try: SimpleNewObj = 42 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:24:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:24:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0NTAp?= Message-ID: <20150703042423.32451.10257@psf.io> https://hg.python.org/cpython/rev/f4058528ab8c changeset: 96766:f4058528ab8c parent: 96764:14be2ab42294 parent: 96765:84eb9a020011 user: Yury Selivanov date: Fri Jul 03 00:24:14 2015 -0400 summary: Merge 3.5 (Issue #24450) files: Doc/library/inspect.rst | 7 ++++ Doc/whatsnew/3.5.rst | 3 ++ Lib/test/test_coroutines.py | 30 ++++++++++++++++++++ Lib/test/test_generators.py | 37 ++++++++++++++++++++++++- Misc/NEWS | 3 ++ Objects/genobject.c | 22 ++++++++++++++ 6 files changed, 101 insertions(+), 1 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -182,12 +182,19 @@ +-----------+-----------------+---------------------------+ | | __qualname__ | qualified name | +-----------+-----------------+---------------------------+ +| | cr_await | object being awaited on, | +| | | or ``None`` | ++-----------+-----------------+---------------------------+ | | cr_frame | frame | +-----------+-----------------+---------------------------+ | | cr_running | is the coroutine running? | +-----------+-----------------+---------------------------+ | | cr_code | code | +-----------+-----------------+---------------------------+ +| | gi_yieldfrom | object being iterated by | +| | | ``yield from``, or | +| | | ``None`` | ++-----------+-----------------+---------------------------+ | builtin | __doc__ | documentation string | +-----------+-----------------+---------------------------+ | | __name__ | original name of this | diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -84,6 +84,9 @@ * ``b'\xf0\x9f\x90\x8d'.hex()``, ``bytearray(b'\xf0\x9f\x90\x8d').hex()``, ``memoryview(b'\xf0\x9f\x90\x8d').hex()``: :issue:`9951` - A ``hex`` method has been added to bytes, bytearray, and memoryview. +* Generators have new ``gi_yieldfrom`` attribute, which returns the + object being iterated by ``yield from`` expressions. (Contributed + by Benno Leslie and Yury Selivanov in :issue:`24450`.) Implementation improvements: diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -350,6 +350,36 @@ "coroutine ignored GeneratorExit"): c.close() + def test_cr_await(self): + @types.coroutine + def a(): + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING) + self.assertIsNone(coro_b.cr_await) + yield + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING) + self.assertIsNone(coro_b.cr_await) + + async def c(): + await a() + + async def b(): + self.assertIsNone(coro_b.cr_await) + await c() + self.assertIsNone(coro_b.cr_await) + + coro_b = b() + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CREATED) + self.assertIsNone(coro_b.cr_await) + + coro_b.send(None) + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_SUSPENDED) + self.assertEqual(coro_b.cr_await.cr_await.gi_code.co_name, 'a') + + with self.assertRaises(StopIteration): + coro_b.send(None) # complete coroutine + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CLOSED) + self.assertIsNone(coro_b.cr_await) + def test_corotype_1(self): ct = types.CoroutineType self.assertIn('into coroutine', ct.send.__doc__) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -3,6 +3,8 @@ import unittest import warnings import weakref +import inspect +import types from test import support @@ -259,6 +261,39 @@ next(g) +class YieldFromTests(unittest.TestCase): + def test_generator_gi_yieldfrom(self): + def a(): + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING) + self.assertIsNone(gen_b.gi_yieldfrom) + yield + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING) + self.assertIsNone(gen_b.gi_yieldfrom) + + def b(): + self.assertIsNone(gen_b.gi_yieldfrom) + yield from a() + self.assertIsNone(gen_b.gi_yieldfrom) + yield + self.assertIsNone(gen_b.gi_yieldfrom) + + gen_b = b() + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CREATED) + self.assertIsNone(gen_b.gi_yieldfrom) + + gen_b.send(None) + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED) + self.assertEqual(gen_b.gi_yieldfrom.gi_code.co_name, 'a') + + gen_b.send(None) + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED) + self.assertIsNone(gen_b.gi_yieldfrom) + + [] = gen_b # Exhaust generator + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CLOSED) + self.assertIsNone(gen_b.gi_yieldfrom) + + tutorial_tests = """ Let's try a simple generator: @@ -624,7 +659,7 @@ >>> type(i) >>> [s for s in dir(i) if not s.startswith('_')] -['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw'] +['close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw'] >>> from test.support import HAVE_DOCSTRINGS >>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).') Implement next(self). diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,9 @@ used in types.coroutine to be instance of collections.abc.Generator; inspect.isawaitable was removed (use collections.abc.Awaitable). +- Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. + Contributed by Benno Leslie and Yury Selivanov. + Library ------- diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -552,11 +552,22 @@ return 0; } +static PyObject * +gen_getyieldfrom(PyGenObject *gen) +{ + PyObject *yf = gen_yf(gen); + if (yf == NULL) + Py_RETURN_NONE; + return yf; +} + static PyGetSetDef gen_getsetlist[] = { {"__name__", (getter)gen_get_name, (setter)gen_set_name, PyDoc_STR("name of the generator")}, {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, PyDoc_STR("qualified name of the generator")}, + {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL, + PyDoc_STR("object being iterated by yield from, or None")}, {NULL} /* Sentinel */ }; @@ -776,11 +787,22 @@ return (PyObject *)cw; } +static PyObject * +coro_get_cr_await(PyCoroObject *coro) +{ + PyObject *yf = gen_yf((PyGenObject *) coro); + if (yf == NULL) + Py_RETURN_NONE; + return yf; +} + static PyGetSetDef coro_getsetlist[] = { {"__name__", (getter)gen_get_name, (setter)gen_set_name, PyDoc_STR("name of the coroutine")}, {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, PyDoc_STR("qualified name of the coroutine")}, + {"cr_await", (getter)coro_get_cr_await, NULL, + PyDoc_STR("object being awaited on, or None")}, {NULL} /* Sentinel */ }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:24:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:24:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDUw?= =?utf-8?q?=3A_Add_gi=5Fyieldfrom_to_generators=3B_cr=5Fawait_to_coroutine?= =?utf-8?q?s=2E?= Message-ID: <20150703042423.106268.39153@psf.io> https://hg.python.org/cpython/rev/84eb9a020011 changeset: 96765:84eb9a020011 branch: 3.5 parent: 96763:b1caa38c81ab user: Yury Selivanov date: Fri Jul 03 00:23:30 2015 -0400 summary: Issue #24450: Add gi_yieldfrom to generators; cr_await to coroutines. Patch by Benno Leslie and Yury Selivanov. files: Doc/library/inspect.rst | 7 ++++ Doc/whatsnew/3.5.rst | 3 ++ Lib/test/test_coroutines.py | 30 ++++++++++++++++++++ Lib/test/test_generators.py | 37 ++++++++++++++++++++++++- Misc/NEWS | 3 ++ Objects/genobject.c | 22 ++++++++++++++ 6 files changed, 101 insertions(+), 1 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -182,12 +182,19 @@ +-----------+-----------------+---------------------------+ | | __qualname__ | qualified name | +-----------+-----------------+---------------------------+ +| | cr_await | object being awaited on, | +| | | or ``None`` | ++-----------+-----------------+---------------------------+ | | cr_frame | frame | +-----------+-----------------+---------------------------+ | | cr_running | is the coroutine running? | +-----------+-----------------+---------------------------+ | | cr_code | code | +-----------+-----------------+---------------------------+ +| | gi_yieldfrom | object being iterated by | +| | | ``yield from``, or | +| | | ``None`` | ++-----------+-----------------+---------------------------+ | builtin | __doc__ | documentation string | +-----------+-----------------+---------------------------+ | | __name__ | original name of this | diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -84,6 +84,9 @@ * ``b'\xf0\x9f\x90\x8d'.hex()``, ``bytearray(b'\xf0\x9f\x90\x8d').hex()``, ``memoryview(b'\xf0\x9f\x90\x8d').hex()``: :issue:`9951` - A ``hex`` method has been added to bytes, bytearray, and memoryview. +* Generators have new ``gi_yieldfrom`` attribute, which returns the + object being iterated by ``yield from`` expressions. (Contributed + by Benno Leslie and Yury Selivanov in :issue:`24450`.) Implementation improvements: diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -350,6 +350,36 @@ "coroutine ignored GeneratorExit"): c.close() + def test_cr_await(self): + @types.coroutine + def a(): + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING) + self.assertIsNone(coro_b.cr_await) + yield + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING) + self.assertIsNone(coro_b.cr_await) + + async def c(): + await a() + + async def b(): + self.assertIsNone(coro_b.cr_await) + await c() + self.assertIsNone(coro_b.cr_await) + + coro_b = b() + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CREATED) + self.assertIsNone(coro_b.cr_await) + + coro_b.send(None) + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_SUSPENDED) + self.assertEqual(coro_b.cr_await.cr_await.gi_code.co_name, 'a') + + with self.assertRaises(StopIteration): + coro_b.send(None) # complete coroutine + self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CLOSED) + self.assertIsNone(coro_b.cr_await) + def test_corotype_1(self): ct = types.CoroutineType self.assertIn('into coroutine', ct.send.__doc__) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -3,6 +3,8 @@ import unittest import warnings import weakref +import inspect +import types from test import support @@ -259,6 +261,39 @@ next(g) +class YieldFromTests(unittest.TestCase): + def test_generator_gi_yieldfrom(self): + def a(): + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING) + self.assertIsNone(gen_b.gi_yieldfrom) + yield + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING) + self.assertIsNone(gen_b.gi_yieldfrom) + + def b(): + self.assertIsNone(gen_b.gi_yieldfrom) + yield from a() + self.assertIsNone(gen_b.gi_yieldfrom) + yield + self.assertIsNone(gen_b.gi_yieldfrom) + + gen_b = b() + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CREATED) + self.assertIsNone(gen_b.gi_yieldfrom) + + gen_b.send(None) + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED) + self.assertEqual(gen_b.gi_yieldfrom.gi_code.co_name, 'a') + + gen_b.send(None) + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED) + self.assertIsNone(gen_b.gi_yieldfrom) + + [] = gen_b # Exhaust generator + self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CLOSED) + self.assertIsNone(gen_b.gi_yieldfrom) + + tutorial_tests = """ Let's try a simple generator: @@ -624,7 +659,7 @@ >>> type(i) >>> [s for s in dir(i) if not s.startswith('_')] -['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw'] +['close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw'] >>> from test.support import HAVE_DOCSTRINGS >>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).') Implement next(self). diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ used in types.coroutine to be instance of collections.abc.Generator; inspect.isawaitable was removed (use collections.abc.Awaitable). +- Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. + Contributed by Benno Leslie and Yury Selivanov. + Library ------- diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -552,11 +552,22 @@ return 0; } +static PyObject * +gen_getyieldfrom(PyGenObject *gen) +{ + PyObject *yf = gen_yf(gen); + if (yf == NULL) + Py_RETURN_NONE; + return yf; +} + static PyGetSetDef gen_getsetlist[] = { {"__name__", (getter)gen_get_name, (setter)gen_set_name, PyDoc_STR("name of the generator")}, {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, PyDoc_STR("qualified name of the generator")}, + {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL, + PyDoc_STR("object being iterated by yield from, or None")}, {NULL} /* Sentinel */ }; @@ -776,11 +787,22 @@ return (PyObject *)cw; } +static PyObject * +coro_get_cr_await(PyCoroObject *coro) +{ + PyObject *yf = gen_yf((PyGenObject *) coro); + if (yf == NULL) + Py_RETURN_NONE; + return yf; +} + static PyGetSetDef coro_getsetlist[] = { {"__name__", (getter)gen_get_name, (setter)gen_set_name, PyDoc_STR("name of the coroutine")}, {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, PyDoc_STR("qualified name of the coroutine")}, + {"cr_await", (getter)coro_get_cr_await, NULL, + PyDoc_STR("object being awaited on, or None")}, {NULL} /* Sentinel */ }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:35:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:35:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDUw?= =?utf-8?q?=3A_Proxy_cr=5Fawait_and_gi=5Fyieldfrom_in_=40types=2Ecoroutine?= Message-ID: <20150703043546.3167.59526@psf.io> https://hg.python.org/cpython/rev/9bae275e99b3 changeset: 96767:9bae275e99b3 branch: 3.5 parent: 96765:84eb9a020011 user: Yury Selivanov date: Fri Jul 03 00:35:02 2015 -0400 summary: Issue #24450: Proxy cr_await and gi_yieldfrom in @types.coroutine files: Lib/test/test_types.py | 7 +++++-- Lib/types.py | 4 ++++ 2 files changed, 9 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 @@ -1295,8 +1295,8 @@ self.assertIs(wrapper.__name__, gen.__name__) # Test AttributeErrors - for name in {'gi_running', 'gi_frame', 'gi_code', - 'cr_running', 'cr_frame', 'cr_code'}: + for name in {'gi_running', 'gi_frame', 'gi_code', 'gi_yieldfrom', + 'cr_running', 'cr_frame', 'cr_code', 'cr_await'}: with self.assertRaises(AttributeError): getattr(wrapper, name) @@ -1304,12 +1304,15 @@ gen.gi_running = object() gen.gi_frame = object() gen.gi_code = object() + gen.gi_yieldfrom = object() self.assertIs(wrapper.gi_running, gen.gi_running) self.assertIs(wrapper.gi_frame, gen.gi_frame) self.assertIs(wrapper.gi_code, gen.gi_code) + self.assertIs(wrapper.gi_yieldfrom, gen.gi_yieldfrom) self.assertIs(wrapper.cr_running, gen.gi_running) self.assertIs(wrapper.cr_frame, gen.gi_frame) self.assertIs(wrapper.cr_code, gen.gi_code) + self.assertIs(wrapper.cr_await, gen.gi_yieldfrom) wrapper.close() gen.close.assert_called_once_with() diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -188,9 +188,13 @@ @property def gi_running(self): return self.__wrapped.gi_running + @property + def gi_yieldfrom(self): + return self.__wrapped.gi_yieldfrom cr_code = gi_code cr_frame = gi_frame cr_running = gi_running + cr_await = gi_yieldfrom def __next__(self): return next(self.__wrapped) def __iter__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:35:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:35:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0NTAp?= Message-ID: <20150703043546.29010.89839@psf.io> https://hg.python.org/cpython/rev/4d3bd9b82a62 changeset: 96768:4d3bd9b82a62 parent: 96766:f4058528ab8c parent: 96767:9bae275e99b3 user: Yury Selivanov date: Fri Jul 03 00:35:29 2015 -0400 summary: Merge 3.5 (Issue #24450) files: Lib/test/test_types.py | 7 +++++-- Lib/types.py | 4 ++++ 2 files changed, 9 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 @@ -1295,8 +1295,8 @@ self.assertIs(wrapper.__name__, gen.__name__) # Test AttributeErrors - for name in {'gi_running', 'gi_frame', 'gi_code', - 'cr_running', 'cr_frame', 'cr_code'}: + for name in {'gi_running', 'gi_frame', 'gi_code', 'gi_yieldfrom', + 'cr_running', 'cr_frame', 'cr_code', 'cr_await'}: with self.assertRaises(AttributeError): getattr(wrapper, name) @@ -1304,12 +1304,15 @@ gen.gi_running = object() gen.gi_frame = object() gen.gi_code = object() + gen.gi_yieldfrom = object() self.assertIs(wrapper.gi_running, gen.gi_running) self.assertIs(wrapper.gi_frame, gen.gi_frame) self.assertIs(wrapper.gi_code, gen.gi_code) + self.assertIs(wrapper.gi_yieldfrom, gen.gi_yieldfrom) self.assertIs(wrapper.cr_running, gen.gi_running) self.assertIs(wrapper.cr_frame, gen.gi_frame) self.assertIs(wrapper.cr_code, gen.gi_code) + self.assertIs(wrapper.cr_await, gen.gi_yieldfrom) wrapper.close() gen.close.assert_called_once_with() diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -188,9 +188,13 @@ @property def gi_running(self): return self.__wrapped.gi_running + @property + def gi_yieldfrom(self): + return self.__wrapped.gi_yieldfrom cr_code = gi_code cr_frame = gi_frame cr_running = gi_running + cr_await = gi_yieldfrom def __next__(self): return next(self.__wrapped) def __iter__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:42:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:42:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NDUw?= =?utf-8?q?=3A_Proxy_gi=5Fyieldfrom_=26_cr=5Fawait_in_asyncio=2ECoroWrappe?= =?utf-8?q?r?= Message-ID: <20150703044213.89409.96125@psf.io> https://hg.python.org/cpython/rev/34460219c0e0 changeset: 96769:34460219c0e0 branch: 3.4 parent: 96762:978bc1ff43a7 user: Yury Selivanov date: Fri Jul 03 00:41:16 2015 -0400 summary: Issue #24450: Proxy gi_yieldfrom & cr_await in asyncio.CoroWrapper files: Lib/asyncio/coroutines.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -145,6 +145,14 @@ __await__ = __iter__ # make compatible with 'await' expression @property + def gi_yieldfrom(self): + return self.gen.gi_yieldfrom + + @property + def cr_await(self): + return self.gen.cr_await + + @property def cr_running(self): return self.gen.cr_running -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:42:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:42:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0NTAp?= Message-ID: <20150703044213.6456.79456@psf.io> https://hg.python.org/cpython/rev/5e9f794fd776 changeset: 96771:5e9f794fd776 parent: 96768:4d3bd9b82a62 parent: 96770:3555f7b5eac6 user: Yury Selivanov date: Fri Jul 03 00:42:01 2015 -0400 summary: Merge 3.5 (Issue #24450) files: Lib/asyncio/coroutines.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -145,6 +145,14 @@ __await__ = __iter__ # make compatible with 'await' expression @property + def gi_yieldfrom(self): + return self.gen.gi_yieldfrom + + @property + def cr_await(self): + return self.gen.cr_await + + @property def cr_running(self): return self.gen.cr_running -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 06:42:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 04:42:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28Issue_=2324450=29?= Message-ID: <20150703044213.23315.50701@psf.io> https://hg.python.org/cpython/rev/3555f7b5eac6 changeset: 96770:3555f7b5eac6 branch: 3.5 parent: 96767:9bae275e99b3 parent: 96769:34460219c0e0 user: Yury Selivanov date: Fri Jul 03 00:41:40 2015 -0400 summary: Merge 3.4 (Issue #24450) files: Lib/asyncio/coroutines.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -145,6 +145,14 @@ __await__ = __iter__ # make compatible with 'await' expression @property + def gi_yieldfrom(self): + return self.gen.gi_yieldfrom + + @property + def cr_await(self): + return self.gen.cr_await + + @property def cr_running(self): return self.gen.cr_running -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 07:12:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 05:12:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMTkyMzUp?= Message-ID: <20150703051241.108523.84358@psf.io> https://hg.python.org/cpython/rev/749d74e5dfa7 changeset: 96773:749d74e5dfa7 parent: 96771:5e9f794fd776 parent: 96772:a795cf73ce6f user: Yury Selivanov date: Fri Jul 03 01:10:11 2015 -0400 summary: Merge 3.5 (Issue #19235) files: Doc/c-api/exceptions.rst | 12 ++++++-- Doc/library/exceptions.rst | 10 ++++++ Doc/library/pickle.rst | 2 +- Doc/whatsnew/3.5.rst | 2 + Include/ceval.h | 6 ++-- Include/pyerrors.h | 1 + Lib/ctypes/test/test_as_parameter.py | 2 +- Lib/test/exception_hierarchy.txt | 1 + Lib/test/list_tests.py | 2 +- Lib/test/test_class.py | 4 +- Lib/test/test_compile.py | 2 +- Lib/test/test_copy.py | 6 ++-- Lib/test/test_descr.py | 6 ++-- Lib/test/test_dictviews.py | 2 +- Lib/test/test_exceptions.py | 13 ++++---- Lib/test/test_isinstance.py | 10 +++--- Lib/test/test_json/test_recursion.py | 12 ++++---- Lib/test/test_pickle.py | 3 +- Lib/test/test_richcmp.py | 24 ++++++++-------- Lib/test/test_runpy.py | 2 +- Lib/test/test_sys.py | 6 ++-- Lib/test/test_threading.py | 2 +- Misc/NEWS | 2 + Modules/_pickle.c | 2 +- Modules/_sre.c | 3 +- Objects/exceptions.c | 19 ++++++++---- Objects/typeobject.c | 2 +- Python/ceval.c | 2 +- Python/errors.c | 2 +- Python/symtable.c | 4 +- Tools/scripts/find_recursionlimit.py | 4 +- 31 files changed, 101 insertions(+), 69 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 @@ -683,12 +683,12 @@ sets a :exc:`MemoryError` and returns a nonzero value. The function then checks if the recursion limit is reached. If this is the - case, a :exc:`RuntimeError` is set and a nonzero value is returned. + case, a :exc:`RecursionError` is set and a nonzero value is returned. Otherwise, zero is returned. *where* should be a string such as ``" in instance check"`` to be - concatenated to the :exc:`RuntimeError` message caused by the recursion depth - limit. + concatenated to the :exc:`RecursionError` message caused by the recursion + depth limit. .. c:function:: void Py_LeaveRecursiveCall() @@ -800,6 +800,8 @@ +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_ProcessLookupError` | :exc:`ProcessLookupError` | | +-----------------------------------------+---------------------------------+----------+ +| :c:data:`PyExc_RecursionError` | :exc:`RecursionError` | | ++-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_ReferenceError` | :exc:`ReferenceError` | \(2) | +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_RuntimeError` | :exc:`RuntimeError` | | @@ -829,6 +831,9 @@ :c:data:`PyExc_PermissionError`, :c:data:`PyExc_ProcessLookupError` and :c:data:`PyExc_TimeoutError` were introduced following :pep:`3151`. +.. versionadded:: 3.5 + :c:data:`PyExc_RecursionError`. + These are compatibility aliases to :c:data:`PyExc_OSError`: @@ -877,6 +882,7 @@ single: PyExc_OverflowError single: PyExc_PermissionError single: PyExc_ProcessLookupError + single: PyExc_RecursionError single: PyExc_ReferenceError single: PyExc_RuntimeError single: PyExc_SyntaxError diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -282,6 +282,16 @@ handling in C, most floating point operations are not checked. +.. exception:: RecursionError + + This exception is derived from :exc:`RuntimeError`. It is raised when the + interpreter detects that the maximum recursion depth (see + :func:`sys.getrecursionlimit`) is exceeded. + + .. versionadded:: 3.5 + Previously, a plain :exc:`RuntimeError` was raised. + + .. exception:: ReferenceError This exception is raised when a weak reference proxy, created by the diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -425,7 +425,7 @@ Attempts to pickle unpicklable objects will raise the :exc:`PicklingError` exception; when this happens, an unspecified number of bytes may have already been written to the underlying file. Trying to pickle a highly recursive data -structure may exceed the maximum recursion depth, a :exc:`RuntimeError` will be +structure may exceed the maximum recursion depth, a :exc:`RecursionError` will be raised in this case. You can carefully raise this limit with :func:`sys.setrecursionlimit`. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -87,6 +87,8 @@ * Generators have new ``gi_yieldfrom`` attribute, which returns the object being iterated by ``yield from`` expressions. (Contributed by Benno Leslie and Yury Selivanov in :issue:`24450`.) +* New :exc:`RecursionError` exception. (Contributed by Georg Brandl + in :issue:`19235`.) Implementation improvements: diff --git a/Include/ceval.h b/Include/ceval.h --- a/Include/ceval.h +++ b/Include/ceval.h @@ -48,16 +48,16 @@ In Python 3.0, this protection has two levels: * normal anti-recursion protection is triggered when the recursion level - exceeds the current recursion limit. It raises a RuntimeError, and sets + exceeds the current recursion limit. It raises a RecursionError, and sets the "overflowed" flag in the thread state structure. This flag temporarily *disables* the normal protection; this allows cleanup code to potentially outgrow the recursion limit while processing the - RuntimeError. + RecursionError. * "last chance" anti-recursion protection is triggered when the recursion level exceeds "current recursion limit + 50". By construction, this protection can only be triggered when the "overflowed" flag is set. It means the cleanup code has itself gone into an infinite loop, or the - RuntimeError has been mistakingly ignored. When this protection is + RecursionError has been mistakingly ignored. When this protection is triggered, the interpreter aborts with a Fatal Error. In addition, the "overflowed" flag is automatically reset when the diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -167,6 +167,7 @@ PyAPI_DATA(PyObject *) PyExc_NameError; PyAPI_DATA(PyObject *) PyExc_OverflowError; PyAPI_DATA(PyObject *) PyExc_RuntimeError; +PyAPI_DATA(PyObject *) PyExc_RecursionError; PyAPI_DATA(PyObject *) PyExc_NotImplementedError; PyAPI_DATA(PyObject *) PyExc_SyntaxError; PyAPI_DATA(PyObject *) PyExc_IndentationError; diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py --- a/Lib/ctypes/test/test_as_parameter.py +++ b/Lib/ctypes/test/test_as_parameter.py @@ -194,7 +194,7 @@ a = A() a._as_parameter_ = a - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): c_int.from_param(a) diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -39,6 +39,7 @@ +-- ReferenceError +-- RuntimeError | +-- NotImplementedError + | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -56,7 +56,7 @@ l0 = [] for i in range(sys.getrecursionlimit() + 100): l0 = [l0] - self.assertRaises(RuntimeError, repr, l0) + self.assertRaises(RecursionError, repr, l0) def test_print(self): d = self.type2test(range(200)) diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -500,10 +500,10 @@ try: a() # This should not segfault - except RuntimeError: + except RecursionError: pass else: - self.fail("Failed to raise RuntimeError") + self.fail("Failed to raise RecursionError") def testForExceptionsRaisedInInstanceGetattr2(self): # Tests for exceptions raised in instance_getattr2(). diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -534,7 +534,7 @@ broken = prefix + repeated * fail_depth details = "Compiling ({!r} + {!r} * {})".format( prefix, repeated, fail_depth) - with self.assertRaises(RuntimeError, msg=details): + with self.assertRaises(RecursionError, msg=details): self.compile_single(broken) check_limit("a", "()") 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 @@ -327,7 +327,7 @@ x.append(x) y = copy.deepcopy(x) for op in comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIs(y[0], y) self.assertEqual(len(y), 1) @@ -354,7 +354,7 @@ x[0].append(x) y = copy.deepcopy(x) for op in comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIsNot(y[0], x[0]) self.assertIs(y[0][0], y) @@ -373,7 +373,7 @@ for op in order_comparisons: self.assertRaises(TypeError, op, y, x) for op in equality_comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIs(y['foo'], y) self.assertEqual(len(y), 1) 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 @@ -3342,7 +3342,7 @@ A.__call__ = A() try: A()() - except RuntimeError: + except RecursionError: pass else: self.fail("Recursion limit should have been reached for __call__()") @@ -4317,8 +4317,8 @@ pass Foo.__repr__ = Foo.__str__ foo = Foo() - self.assertRaises(RuntimeError, str, foo) - self.assertRaises(RuntimeError, repr, foo) + self.assertRaises(RecursionError, str, foo) + self.assertRaises(RecursionError, repr, foo) def test_mixing_slot_wrappers(self): class X(dict): diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -196,7 +196,7 @@ def test_recursive_repr(self): d = {} d[42] = d.values() - self.assertRaises(RuntimeError, repr, d) + self.assertRaises(RecursionError, repr, d) def test_abc_registry(self): d = dict(a=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 @@ -84,6 +84,7 @@ x += x # this simply shouldn't blow up self.raise_catch(RuntimeError, "RuntimeError") + self.raise_catch(RecursionError, "RecursionError") self.raise_catch(SyntaxError, "SyntaxError") try: exec('/\n') @@ -474,14 +475,14 @@ def testInfiniteRecursion(self): def f(): return f() - self.assertRaises(RuntimeError, f) + self.assertRaises(RecursionError, f) def g(): try: return g() except ValueError: return -1 - self.assertRaises(RuntimeError, g) + self.assertRaises(RecursionError, g) def test_str(self): # Make sure both instances and classes have a str representation. @@ -887,10 +888,10 @@ def g(): try: return g() - except RuntimeError: + except RecursionError: return sys.exc_info() e, v, tb = g() - self.assertTrue(isinstance(v, RuntimeError), type(v)) + self.assertTrue(isinstance(v, RecursionError), type(v)) self.assertIn("maximum recursion depth exceeded", str(v)) @@ -989,10 +990,10 @@ # We cannot use assertRaises since it manually deletes the traceback try: inner() - except RuntimeError as e: + except RecursionError as e: self.assertNotEqual(wr(), None) else: - self.fail("RuntimeError not raised") + self.fail("RecursionError not raised") self.assertEqual(wr(), None) def test_errno_ENOTDIR(self): diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -258,18 +258,18 @@ self.assertEqual(True, issubclass(str, (str, (Child, NewChild, str)))) def test_subclass_recursion_limit(self): - # make sure that issubclass raises RuntimeError before the C stack is + # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RuntimeError, blowstack, issubclass, str, str) + self.assertRaises(RecursionError, blowstack, issubclass, str, str) def test_isinstance_recursion_limit(self): - # make sure that issubclass raises RuntimeError before the C stack is + # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RuntimeError, blowstack, isinstance, '', str) + self.assertRaises(RecursionError, blowstack, isinstance, '', str) def blowstack(fxn, arg, compare_to): # Make sure that calling isinstance with a deeply nested tuple for its - # argument will raise RuntimeError eventually. + # argument will raise RecursionError eventually. tuple_arg = (compare_to,) for cnt in range(sys.getrecursionlimit()+5): tuple_arg = (tuple_arg,) diff --git a/Lib/test/test_json/test_recursion.py b/Lib/test/test_json/test_recursion.py --- a/Lib/test/test_json/test_recursion.py +++ b/Lib/test/test_json/test_recursion.py @@ -68,11 +68,11 @@ def test_highly_nested_objects_decoding(self): # test that loading highly-nested objects doesn't segfault when C # accelerations are used. See #12017 - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('{"a":' * 100000 + '1' + '}' * 100000) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('{"a":' * 100000 + '[1]' + '}' * 100000) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('[' * 100000 + '1' + ']' * 100000) def test_highly_nested_objects_encoding(self): @@ -80,9 +80,9 @@ l, d = [], {} for x in range(100000): l, d = [l], {'k':d} - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.dumps(l) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.dumps(d) def test_endless_recursion(self): @@ -92,7 +92,7 @@ """If check_circular is False, this will keep adding another list.""" return [o] - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): EndlessJSONEncoder(check_circular=False).encode(5j) diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -353,7 +353,8 @@ with self.subTest(name): if exc in (BlockingIOError, ResourceWarning, - StopAsyncIteration): + StopAsyncIteration, + RecursionError): continue if exc is not OSError and issubclass(exc, OSError): self.assertEqual(reverse_mapping('builtins', name), diff --git a/Lib/test/test_richcmp.py b/Lib/test/test_richcmp.py --- a/Lib/test/test_richcmp.py +++ b/Lib/test/test_richcmp.py @@ -228,25 +228,25 @@ b = UserList() a.append(b) b.append(a) - self.assertRaises(RuntimeError, operator.eq, a, b) - self.assertRaises(RuntimeError, operator.ne, a, b) - self.assertRaises(RuntimeError, operator.lt, a, b) - self.assertRaises(RuntimeError, operator.le, a, b) - self.assertRaises(RuntimeError, operator.gt, a, b) - self.assertRaises(RuntimeError, operator.ge, a, b) + self.assertRaises(RecursionError, operator.eq, a, b) + self.assertRaises(RecursionError, operator.ne, a, b) + self.assertRaises(RecursionError, operator.lt, a, b) + self.assertRaises(RecursionError, operator.le, a, b) + self.assertRaises(RecursionError, operator.gt, a, b) + self.assertRaises(RecursionError, operator.ge, a, b) b.append(17) # Even recursive lists of different lengths are different, # but they cannot be ordered self.assertTrue(not (a == b)) self.assertTrue(a != b) - self.assertRaises(RuntimeError, operator.lt, a, b) - self.assertRaises(RuntimeError, operator.le, a, b) - self.assertRaises(RuntimeError, operator.gt, a, b) - self.assertRaises(RuntimeError, operator.ge, a, b) + self.assertRaises(RecursionError, operator.lt, a, b) + self.assertRaises(RecursionError, operator.le, a, b) + self.assertRaises(RecursionError, operator.gt, a, b) + self.assertRaises(RecursionError, operator.ge, a, b) a.append(17) - self.assertRaises(RuntimeError, operator.eq, a, b) - self.assertRaises(RuntimeError, operator.ne, a, b) + self.assertRaises(RecursionError, operator.eq, a, b) + self.assertRaises(RecursionError, operator.ne, a, b) a.insert(0, 11) b.insert(0, 12) self.assertTrue(not (a == b)) diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -673,7 +673,7 @@ script_name = self._make_test_script(script_dir, mod_name, source) zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name) msg = "recursion depth exceeded" - self.assertRaisesRegex(RuntimeError, msg, run_path, zip_name) + self.assertRaisesRegex(RecursionError, msg, run_path, zip_name) def test_encoding(self): with temp_dir() as script_dir: 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 @@ -211,8 +211,8 @@ for i in (50, 1000): # Issue #5392: stack overflow after hitting recursion limit twice sys.setrecursionlimit(i) - self.assertRaises(RuntimeError, f) - self.assertRaises(RuntimeError, f) + self.assertRaises(RecursionError, f) + self.assertRaises(RecursionError, f) finally: sys.setrecursionlimit(oldlimit) @@ -225,7 +225,7 @@ def f(): try: f() - except RuntimeError: + except RecursionError: f() sys.setrecursionlimit(%d) 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 @@ -945,7 +945,7 @@ def outer(): try: recurse() - except RuntimeError: + except RecursionError: pass w = threading.Thread(target=outer) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,8 @@ - Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. Contributed by Benno Leslie and Yury Selivanov. +- Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. + Library ------- diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -3622,7 +3622,7 @@ >>> pickle.dumps(1+2j) Traceback (most recent call last): ... - RuntimeError: maximum recursion depth exceeded + RecursionError: maximum recursion depth exceeded Removing the complex class from copyreg.dispatch_table made the __reduce_ex__() method emit another complex object: diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -497,8 +497,9 @@ { switch (status) { case SRE_ERROR_RECURSION_LIMIT: + /* This error code seems to be unused. */ PyErr_SetString( - PyExc_RuntimeError, + PyExc_RecursionError, "maximum recursion limit exceeded" ); break; diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1231,6 +1231,11 @@ SimpleExtendsException(PyExc_Exception, RuntimeError, "Unspecified run-time error."); +/* + * RecursionError extends RuntimeError + */ +SimpleExtendsException(PyExc_RuntimeError, RecursionError, + "Recursion limit exceeded."); /* * NotImplementedError extends RuntimeError @@ -2380,7 +2385,7 @@ -/* Pre-computed RuntimeError instance for when recursion depth is reached. +/* Pre-computed RecursionError instance for when recursion depth is reached. Meant to be used when normalizing the exception for exceeding the recursion depth will cause its own infinite recursion. */ @@ -2484,6 +2489,7 @@ PRE_INIT(OSError) PRE_INIT(EOFError) PRE_INIT(RuntimeError) + PRE_INIT(RecursionError) PRE_INIT(NotImplementedError) PRE_INIT(NameError) PRE_INIT(UnboundLocalError) @@ -2560,6 +2566,7 @@ #endif POST_INIT(EOFError) POST_INIT(RuntimeError) + POST_INIT(RecursionError) POST_INIT(NotImplementedError) POST_INIT(NameError) POST_INIT(UnboundLocalError) @@ -2643,9 +2650,9 @@ preallocate_memerrors(); if (!PyExc_RecursionErrorInst) { - PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RuntimeError, NULL, NULL); + PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RecursionError, NULL, NULL); if (!PyExc_RecursionErrorInst) - Py_FatalError("Cannot pre-allocate RuntimeError instance for " + Py_FatalError("Cannot pre-allocate RecursionError instance for " "recursion errors"); else { PyBaseExceptionObject *err_inst = @@ -2654,15 +2661,15 @@ PyObject *exc_message; exc_message = PyUnicode_FromString("maximum recursion depth exceeded"); if (!exc_message) - Py_FatalError("cannot allocate argument for RuntimeError " + Py_FatalError("cannot allocate argument for RecursionError " "pre-allocation"); args_tuple = PyTuple_Pack(1, exc_message); if (!args_tuple) - Py_FatalError("cannot allocate tuple for RuntimeError " + Py_FatalError("cannot allocate tuple for RecursionError " "pre-allocation"); Py_DECREF(exc_message); if (BaseException_init(err_inst, args_tuple, NULL)) - Py_FatalError("init of pre-allocated RuntimeError failed"); + Py_FatalError("init of pre-allocated RecursionError failed"); Py_DECREF(args_tuple); } } diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4142,7 +4142,7 @@ * were implemented in the same function: * - trying to pickle an object with a custom __reduce__ method that * fell back to object.__reduce__ in certain circumstances led to - * infinite recursion at Python level and eventual RuntimeError. + * infinite recursion at Python level and eventual RecursionError. * - Pickling objects that lied about their type by overwriting the * __class__ descriptor could lead to infinite recursion at C level * and eventual segfault. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -737,7 +737,7 @@ if (tstate->recursion_depth > recursion_limit) { --tstate->recursion_depth; tstate->overflowed = 1; - PyErr_Format(PyExc_RuntimeError, + PyErr_Format(PyExc_RecursionError, "maximum recursion depth exceeded%s", where); return -1; diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -319,7 +319,7 @@ Py_DECREF(*exc); Py_DECREF(*val); /* ... and use the recursion error instead */ - *exc = PyExc_RuntimeError; + *exc = PyExc_RecursionError; *val = PyExc_RecursionErrorInst; Py_INCREF(*exc); Py_INCREF(*val); diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1135,7 +1135,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) { if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RuntimeError, + PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during compilation"); VISIT_QUIT(st, 0); } @@ -1357,7 +1357,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) { if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RuntimeError, + PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during compilation"); VISIT_QUIT(st, 0); } diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -92,7 +92,7 @@ def test_compiler_recursion(): # The compiler uses a scaling factor to support additional levels # of recursion. This is a sanity check of that scaling to ensure - # it still raises RuntimeError even at higher recursion limits + # it still raises RecursionError even at higher recursion limits compile("()" * (10 * sys.getrecursionlimit()), "", "single") def check_limit(n, test_func_name): @@ -107,7 +107,7 @@ # AttributeError can be raised because of the way e.g. PyDict_GetItem() # silences all exceptions and returns NULL, which is usually interpreted # as "missing attribute". - except (RuntimeError, AttributeError): + except (RecursionError, AttributeError): pass else: print("Yikes!") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 07:12:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 05:12:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE5MjM1?= =?utf-8?q?=3A_Add_new_RecursionError_exception=2E_Patch_by_Georg_Brandl?= =?utf-8?q?=2E?= Message-ID: <20150703051241.53360.31879@psf.io> https://hg.python.org/cpython/rev/a795cf73ce6f changeset: 96772:a795cf73ce6f branch: 3.5 parent: 96770:3555f7b5eac6 user: Yury Selivanov date: Fri Jul 03 01:04:23 2015 -0400 summary: Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. files: Doc/c-api/exceptions.rst | 12 ++++++-- Doc/library/exceptions.rst | 10 ++++++ Doc/library/pickle.rst | 2 +- Doc/whatsnew/3.5.rst | 2 + Include/ceval.h | 6 ++-- Include/pyerrors.h | 1 + Lib/ctypes/test/test_as_parameter.py | 2 +- Lib/test/exception_hierarchy.txt | 1 + Lib/test/list_tests.py | 2 +- Lib/test/test_class.py | 4 +- Lib/test/test_compile.py | 2 +- Lib/test/test_copy.py | 6 ++-- Lib/test/test_descr.py | 6 ++-- Lib/test/test_dictviews.py | 2 +- Lib/test/test_exceptions.py | 13 ++++---- Lib/test/test_isinstance.py | 10 +++--- Lib/test/test_json/test_recursion.py | 12 ++++---- Lib/test/test_pickle.py | 3 +- Lib/test/test_richcmp.py | 24 ++++++++-------- Lib/test/test_runpy.py | 2 +- Lib/test/test_sys.py | 6 ++-- Lib/test/test_threading.py | 2 +- Misc/NEWS | 2 + Modules/_pickle.c | 2 +- Modules/_sre.c | 3 +- Objects/exceptions.c | 19 ++++++++---- Objects/typeobject.c | 2 +- Python/ceval.c | 2 +- Python/errors.c | 2 +- Python/symtable.c | 4 +- Tools/scripts/find_recursionlimit.py | 4 +- 31 files changed, 101 insertions(+), 69 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 @@ -683,12 +683,12 @@ sets a :exc:`MemoryError` and returns a nonzero value. The function then checks if the recursion limit is reached. If this is the - case, a :exc:`RuntimeError` is set and a nonzero value is returned. + case, a :exc:`RecursionError` is set and a nonzero value is returned. Otherwise, zero is returned. *where* should be a string such as ``" in instance check"`` to be - concatenated to the :exc:`RuntimeError` message caused by the recursion depth - limit. + concatenated to the :exc:`RecursionError` message caused by the recursion + depth limit. .. c:function:: void Py_LeaveRecursiveCall() @@ -800,6 +800,8 @@ +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_ProcessLookupError` | :exc:`ProcessLookupError` | | +-----------------------------------------+---------------------------------+----------+ +| :c:data:`PyExc_RecursionError` | :exc:`RecursionError` | | ++-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_ReferenceError` | :exc:`ReferenceError` | \(2) | +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_RuntimeError` | :exc:`RuntimeError` | | @@ -829,6 +831,9 @@ :c:data:`PyExc_PermissionError`, :c:data:`PyExc_ProcessLookupError` and :c:data:`PyExc_TimeoutError` were introduced following :pep:`3151`. +.. versionadded:: 3.5 + :c:data:`PyExc_RecursionError`. + These are compatibility aliases to :c:data:`PyExc_OSError`: @@ -877,6 +882,7 @@ single: PyExc_OverflowError single: PyExc_PermissionError single: PyExc_ProcessLookupError + single: PyExc_RecursionError single: PyExc_ReferenceError single: PyExc_RuntimeError single: PyExc_SyntaxError diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -282,6 +282,16 @@ handling in C, most floating point operations are not checked. +.. exception:: RecursionError + + This exception is derived from :exc:`RuntimeError`. It is raised when the + interpreter detects that the maximum recursion depth (see + :func:`sys.getrecursionlimit`) is exceeded. + + .. versionadded:: 3.5 + Previously, a plain :exc:`RuntimeError` was raised. + + .. exception:: ReferenceError This exception is raised when a weak reference proxy, created by the diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -425,7 +425,7 @@ Attempts to pickle unpicklable objects will raise the :exc:`PicklingError` exception; when this happens, an unspecified number of bytes may have already been written to the underlying file. Trying to pickle a highly recursive data -structure may exceed the maximum recursion depth, a :exc:`RuntimeError` will be +structure may exceed the maximum recursion depth, a :exc:`RecursionError` will be raised in this case. You can carefully raise this limit with :func:`sys.setrecursionlimit`. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -87,6 +87,8 @@ * Generators have new ``gi_yieldfrom`` attribute, which returns the object being iterated by ``yield from`` expressions. (Contributed by Benno Leslie and Yury Selivanov in :issue:`24450`.) +* New :exc:`RecursionError` exception. (Contributed by Georg Brandl + in :issue:`19235`.) Implementation improvements: diff --git a/Include/ceval.h b/Include/ceval.h --- a/Include/ceval.h +++ b/Include/ceval.h @@ -48,16 +48,16 @@ In Python 3.0, this protection has two levels: * normal anti-recursion protection is triggered when the recursion level - exceeds the current recursion limit. It raises a RuntimeError, and sets + exceeds the current recursion limit. It raises a RecursionError, and sets the "overflowed" flag in the thread state structure. This flag temporarily *disables* the normal protection; this allows cleanup code to potentially outgrow the recursion limit while processing the - RuntimeError. + RecursionError. * "last chance" anti-recursion protection is triggered when the recursion level exceeds "current recursion limit + 50". By construction, this protection can only be triggered when the "overflowed" flag is set. It means the cleanup code has itself gone into an infinite loop, or the - RuntimeError has been mistakingly ignored. When this protection is + RecursionError has been mistakingly ignored. When this protection is triggered, the interpreter aborts with a Fatal Error. In addition, the "overflowed" flag is automatically reset when the diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -167,6 +167,7 @@ PyAPI_DATA(PyObject *) PyExc_NameError; PyAPI_DATA(PyObject *) PyExc_OverflowError; PyAPI_DATA(PyObject *) PyExc_RuntimeError; +PyAPI_DATA(PyObject *) PyExc_RecursionError; PyAPI_DATA(PyObject *) PyExc_NotImplementedError; PyAPI_DATA(PyObject *) PyExc_SyntaxError; PyAPI_DATA(PyObject *) PyExc_IndentationError; diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py --- a/Lib/ctypes/test/test_as_parameter.py +++ b/Lib/ctypes/test/test_as_parameter.py @@ -194,7 +194,7 @@ a = A() a._as_parameter_ = a - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): c_int.from_param(a) diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -39,6 +39,7 @@ +-- ReferenceError +-- RuntimeError | +-- NotImplementedError + | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -56,7 +56,7 @@ l0 = [] for i in range(sys.getrecursionlimit() + 100): l0 = [l0] - self.assertRaises(RuntimeError, repr, l0) + self.assertRaises(RecursionError, repr, l0) def test_print(self): d = self.type2test(range(200)) diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -500,10 +500,10 @@ try: a() # This should not segfault - except RuntimeError: + except RecursionError: pass else: - self.fail("Failed to raise RuntimeError") + self.fail("Failed to raise RecursionError") def testForExceptionsRaisedInInstanceGetattr2(self): # Tests for exceptions raised in instance_getattr2(). diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -534,7 +534,7 @@ broken = prefix + repeated * fail_depth details = "Compiling ({!r} + {!r} * {})".format( prefix, repeated, fail_depth) - with self.assertRaises(RuntimeError, msg=details): + with self.assertRaises(RecursionError, msg=details): self.compile_single(broken) check_limit("a", "()") 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 @@ -327,7 +327,7 @@ x.append(x) y = copy.deepcopy(x) for op in comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIs(y[0], y) self.assertEqual(len(y), 1) @@ -354,7 +354,7 @@ x[0].append(x) y = copy.deepcopy(x) for op in comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIsNot(y[0], x[0]) self.assertIs(y[0][0], y) @@ -373,7 +373,7 @@ for op in order_comparisons: self.assertRaises(TypeError, op, y, x) for op in equality_comparisons: - self.assertRaises(RuntimeError, op, y, x) + self.assertRaises(RecursionError, op, y, x) self.assertIsNot(y, x) self.assertIs(y['foo'], y) self.assertEqual(len(y), 1) 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 @@ -3342,7 +3342,7 @@ A.__call__ = A() try: A()() - except RuntimeError: + except RecursionError: pass else: self.fail("Recursion limit should have been reached for __call__()") @@ -4317,8 +4317,8 @@ pass Foo.__repr__ = Foo.__str__ foo = Foo() - self.assertRaises(RuntimeError, str, foo) - self.assertRaises(RuntimeError, repr, foo) + self.assertRaises(RecursionError, str, foo) + self.assertRaises(RecursionError, repr, foo) def test_mixing_slot_wrappers(self): class X(dict): diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -195,7 +195,7 @@ def test_recursive_repr(self): d = {} d[42] = d.values() - self.assertRaises(RuntimeError, repr, d) + self.assertRaises(RecursionError, repr, d) if __name__ == "__main__": 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 @@ -84,6 +84,7 @@ x += x # this simply shouldn't blow up self.raise_catch(RuntimeError, "RuntimeError") + self.raise_catch(RecursionError, "RecursionError") self.raise_catch(SyntaxError, "SyntaxError") try: exec('/\n') @@ -474,14 +475,14 @@ def testInfiniteRecursion(self): def f(): return f() - self.assertRaises(RuntimeError, f) + self.assertRaises(RecursionError, f) def g(): try: return g() except ValueError: return -1 - self.assertRaises(RuntimeError, g) + self.assertRaises(RecursionError, g) def test_str(self): # Make sure both instances and classes have a str representation. @@ -887,10 +888,10 @@ def g(): try: return g() - except RuntimeError: + except RecursionError: return sys.exc_info() e, v, tb = g() - self.assertTrue(isinstance(v, RuntimeError), type(v)) + self.assertTrue(isinstance(v, RecursionError), type(v)) self.assertIn("maximum recursion depth exceeded", str(v)) @@ -989,10 +990,10 @@ # We cannot use assertRaises since it manually deletes the traceback try: inner() - except RuntimeError as e: + except RecursionError as e: self.assertNotEqual(wr(), None) else: - self.fail("RuntimeError not raised") + self.fail("RecursionError not raised") self.assertEqual(wr(), None) def test_errno_ENOTDIR(self): diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -258,18 +258,18 @@ self.assertEqual(True, issubclass(str, (str, (Child, NewChild, str)))) def test_subclass_recursion_limit(self): - # make sure that issubclass raises RuntimeError before the C stack is + # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RuntimeError, blowstack, issubclass, str, str) + self.assertRaises(RecursionError, blowstack, issubclass, str, str) def test_isinstance_recursion_limit(self): - # make sure that issubclass raises RuntimeError before the C stack is + # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RuntimeError, blowstack, isinstance, '', str) + self.assertRaises(RecursionError, blowstack, isinstance, '', str) def blowstack(fxn, arg, compare_to): # Make sure that calling isinstance with a deeply nested tuple for its - # argument will raise RuntimeError eventually. + # argument will raise RecursionError eventually. tuple_arg = (compare_to,) for cnt in range(sys.getrecursionlimit()+5): tuple_arg = (tuple_arg,) diff --git a/Lib/test/test_json/test_recursion.py b/Lib/test/test_json/test_recursion.py --- a/Lib/test/test_json/test_recursion.py +++ b/Lib/test/test_json/test_recursion.py @@ -68,11 +68,11 @@ def test_highly_nested_objects_decoding(self): # test that loading highly-nested objects doesn't segfault when C # accelerations are used. See #12017 - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('{"a":' * 100000 + '1' + '}' * 100000) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('{"a":' * 100000 + '[1]' + '}' * 100000) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.loads('[' * 100000 + '1' + ']' * 100000) def test_highly_nested_objects_encoding(self): @@ -80,9 +80,9 @@ l, d = [], {} for x in range(100000): l, d = [l], {'k':d} - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.dumps(l) - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): self.dumps(d) def test_endless_recursion(self): @@ -92,7 +92,7 @@ """If check_circular is False, this will keep adding another list.""" return [o] - with self.assertRaises(RuntimeError): + with self.assertRaises(RecursionError): EndlessJSONEncoder(check_circular=False).encode(5j) diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -353,7 +353,8 @@ with self.subTest(name): if exc in (BlockingIOError, ResourceWarning, - StopAsyncIteration): + StopAsyncIteration, + RecursionError): continue if exc is not OSError and issubclass(exc, OSError): self.assertEqual(reverse_mapping('builtins', name), diff --git a/Lib/test/test_richcmp.py b/Lib/test/test_richcmp.py --- a/Lib/test/test_richcmp.py +++ b/Lib/test/test_richcmp.py @@ -228,25 +228,25 @@ b = UserList() a.append(b) b.append(a) - self.assertRaises(RuntimeError, operator.eq, a, b) - self.assertRaises(RuntimeError, operator.ne, a, b) - self.assertRaises(RuntimeError, operator.lt, a, b) - self.assertRaises(RuntimeError, operator.le, a, b) - self.assertRaises(RuntimeError, operator.gt, a, b) - self.assertRaises(RuntimeError, operator.ge, a, b) + self.assertRaises(RecursionError, operator.eq, a, b) + self.assertRaises(RecursionError, operator.ne, a, b) + self.assertRaises(RecursionError, operator.lt, a, b) + self.assertRaises(RecursionError, operator.le, a, b) + self.assertRaises(RecursionError, operator.gt, a, b) + self.assertRaises(RecursionError, operator.ge, a, b) b.append(17) # Even recursive lists of different lengths are different, # but they cannot be ordered self.assertTrue(not (a == b)) self.assertTrue(a != b) - self.assertRaises(RuntimeError, operator.lt, a, b) - self.assertRaises(RuntimeError, operator.le, a, b) - self.assertRaises(RuntimeError, operator.gt, a, b) - self.assertRaises(RuntimeError, operator.ge, a, b) + self.assertRaises(RecursionError, operator.lt, a, b) + self.assertRaises(RecursionError, operator.le, a, b) + self.assertRaises(RecursionError, operator.gt, a, b) + self.assertRaises(RecursionError, operator.ge, a, b) a.append(17) - self.assertRaises(RuntimeError, operator.eq, a, b) - self.assertRaises(RuntimeError, operator.ne, a, b) + self.assertRaises(RecursionError, operator.eq, a, b) + self.assertRaises(RecursionError, operator.ne, a, b) a.insert(0, 11) b.insert(0, 12) self.assertTrue(not (a == b)) diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -673,7 +673,7 @@ script_name = self._make_test_script(script_dir, mod_name, source) zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name) msg = "recursion depth exceeded" - self.assertRaisesRegex(RuntimeError, msg, run_path, zip_name) + self.assertRaisesRegex(RecursionError, msg, run_path, zip_name) def test_encoding(self): with temp_dir() as script_dir: 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 @@ -211,8 +211,8 @@ for i in (50, 1000): # Issue #5392: stack overflow after hitting recursion limit twice sys.setrecursionlimit(i) - self.assertRaises(RuntimeError, f) - self.assertRaises(RuntimeError, f) + self.assertRaises(RecursionError, f) + self.assertRaises(RecursionError, f) finally: sys.setrecursionlimit(oldlimit) @@ -225,7 +225,7 @@ def f(): try: f() - except RuntimeError: + except RecursionError: f() sys.setrecursionlimit(%d) 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 @@ -945,7 +945,7 @@ def outer(): try: recurse() - except RuntimeError: + except RecursionError: pass w = threading.Thread(target=outer) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,8 @@ - Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. Contributed by Benno Leslie and Yury Selivanov. +- Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. + Library ------- diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -3622,7 +3622,7 @@ >>> pickle.dumps(1+2j) Traceback (most recent call last): ... - RuntimeError: maximum recursion depth exceeded + RecursionError: maximum recursion depth exceeded Removing the complex class from copyreg.dispatch_table made the __reduce_ex__() method emit another complex object: diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -500,8 +500,9 @@ { switch (status) { case SRE_ERROR_RECURSION_LIMIT: + /* This error code seems to be unused. */ PyErr_SetString( - PyExc_RuntimeError, + PyExc_RecursionError, "maximum recursion limit exceeded" ); break; diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1231,6 +1231,11 @@ SimpleExtendsException(PyExc_Exception, RuntimeError, "Unspecified run-time error."); +/* + * RecursionError extends RuntimeError + */ +SimpleExtendsException(PyExc_RuntimeError, RecursionError, + "Recursion limit exceeded."); /* * NotImplementedError extends RuntimeError @@ -2380,7 +2385,7 @@ -/* Pre-computed RuntimeError instance for when recursion depth is reached. +/* Pre-computed RecursionError instance for when recursion depth is reached. Meant to be used when normalizing the exception for exceeding the recursion depth will cause its own infinite recursion. */ @@ -2484,6 +2489,7 @@ PRE_INIT(OSError) PRE_INIT(EOFError) PRE_INIT(RuntimeError) + PRE_INIT(RecursionError) PRE_INIT(NotImplementedError) PRE_INIT(NameError) PRE_INIT(UnboundLocalError) @@ -2560,6 +2566,7 @@ #endif POST_INIT(EOFError) POST_INIT(RuntimeError) + POST_INIT(RecursionError) POST_INIT(NotImplementedError) POST_INIT(NameError) POST_INIT(UnboundLocalError) @@ -2643,9 +2650,9 @@ preallocate_memerrors(); if (!PyExc_RecursionErrorInst) { - PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RuntimeError, NULL, NULL); + PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RecursionError, NULL, NULL); if (!PyExc_RecursionErrorInst) - Py_FatalError("Cannot pre-allocate RuntimeError instance for " + Py_FatalError("Cannot pre-allocate RecursionError instance for " "recursion errors"); else { PyBaseExceptionObject *err_inst = @@ -2654,15 +2661,15 @@ PyObject *exc_message; exc_message = PyUnicode_FromString("maximum recursion depth exceeded"); if (!exc_message) - Py_FatalError("cannot allocate argument for RuntimeError " + Py_FatalError("cannot allocate argument for RecursionError " "pre-allocation"); args_tuple = PyTuple_Pack(1, exc_message); if (!args_tuple) - Py_FatalError("cannot allocate tuple for RuntimeError " + Py_FatalError("cannot allocate tuple for RecursionError " "pre-allocation"); Py_DECREF(exc_message); if (BaseException_init(err_inst, args_tuple, NULL)) - Py_FatalError("init of pre-allocated RuntimeError failed"); + Py_FatalError("init of pre-allocated RecursionError failed"); Py_DECREF(args_tuple); } } diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4142,7 +4142,7 @@ * were implemented in the same function: * - trying to pickle an object with a custom __reduce__ method that * fell back to object.__reduce__ in certain circumstances led to - * infinite recursion at Python level and eventual RuntimeError. + * infinite recursion at Python level and eventual RecursionError. * - Pickling objects that lied about their type by overwriting the * __class__ descriptor could lead to infinite recursion at C level * and eventual segfault. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -737,7 +737,7 @@ if (tstate->recursion_depth > recursion_limit) { --tstate->recursion_depth; tstate->overflowed = 1; - PyErr_Format(PyExc_RuntimeError, + PyErr_Format(PyExc_RecursionError, "maximum recursion depth exceeded%s", where); return -1; diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -319,7 +319,7 @@ Py_DECREF(*exc); Py_DECREF(*val); /* ... and use the recursion error instead */ - *exc = PyExc_RuntimeError; + *exc = PyExc_RecursionError; *val = PyExc_RecursionErrorInst; Py_INCREF(*exc); Py_INCREF(*val); diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1135,7 +1135,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) { if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RuntimeError, + PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during compilation"); VISIT_QUIT(st, 0); } @@ -1357,7 +1357,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) { if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RuntimeError, + PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during compilation"); VISIT_QUIT(st, 0); } diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -92,7 +92,7 @@ def test_compiler_recursion(): # The compiler uses a scaling factor to support additional levels # of recursion. This is a sanity check of that scaling to ensure - # it still raises RuntimeError even at higher recursion limits + # it still raises RecursionError even at higher recursion limits compile("()" * (10 * sys.getrecursionlimit()), "", "single") def check_limit(n, test_func_name): @@ -107,7 +107,7 @@ # AttributeError can be raised because of the way e.g. PyDict_GetItem() # silences all exceptions and returns NULL, which is usually interpreted # as "missing attribute". - except (RuntimeError, AttributeError): + except (RecursionError, AttributeError): pass else: print("Yikes!") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 07:16:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 05:16:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Add_a_rudiment?= =?utf-8?q?ary_test_for_StopAsyncIteration_in_test=5Fexceptions=2E?= Message-ID: <20150703051624.37559.23445@psf.io> https://hg.python.org/cpython/rev/7edbbcbf5936 changeset: 96774:7edbbcbf5936 branch: 3.5 parent: 96772:a795cf73ce6f user: Yury Selivanov date: Fri Jul 03 01:16:04 2015 -0400 summary: Add a rudimentary test for StopAsyncIteration in test_exceptions. files: Lib/test/test_exceptions.py | 2 ++ 1 files changed, 2 insertions(+), 0 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 @@ -118,6 +118,8 @@ try: x = 1/0 except Exception as e: pass + self.raise_catch(StopAsyncIteration, "StopAsyncIteration") + def testSyntaxErrorMessage(self): # make sure the right exception message is raised for each of # these code fragments -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 07:16:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 05:16:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150703051624.9573.86048@psf.io> https://hg.python.org/cpython/rev/09b223827f63 changeset: 96775:09b223827f63 parent: 96773:749d74e5dfa7 parent: 96774:7edbbcbf5936 user: Yury Selivanov date: Fri Jul 03 01:16:20 2015 -0400 summary: Merge 3.5 files: Lib/test/test_exceptions.py | 2 ++ 1 files changed, 2 insertions(+), 0 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 @@ -118,6 +118,8 @@ try: x = 1/0 except Exception as e: pass + self.raise_catch(StopAsyncIteration, "StopAsyncIteration") + def testSyntaxErrorMessage(self): # make sure the right exception message is raised for each of # these code fragments -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri Jul 3 10:45:44 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 03 Jul 2015 08:45:44 +0000 Subject: [Python-checkins] Daily reference leaks (09b223827f63): sum=-1 Message-ID: <20150703084544.26750.81937@psf.io> results for 09b223827f63 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [-6, 0, 0] references, sum=-6 test_collections leaked [-3, 1, 0] memory blocks, sum=-2 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog7TgXcD', '--timeout', '7200'] From python-checkins at python.org Fri Jul 3 11:52:15 2015 From: python-checkins at python.org (nick.coghlan) Date: Fri, 03 Jul 2015 09:52:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_fix_for_=2324458_from_3=2E5?= Message-ID: <20150703095215.19983.17210@psf.io> https://hg.python.org/cpython/rev/86daa37c1cc9 changeset: 96777:86daa37c1cc9 parent: 96775:09b223827f63 parent: 96776:bad92d696866 user: Nick Coghlan date: Fri Jul 03 19:52:05 2015 +1000 summary: Merge fix for #24458 from 3.5 files: Doc/c-api/init.rst | 2 + Doc/c-api/module.rst | 320 ++++++++++++++++++----- Doc/extending/building.rst | 63 +++- Doc/extending/extending.rst | 7 + Doc/extending/windows.rst | 5 +- Doc/whatsnew/3.5.rst | 4 +- Misc/NEWS | 15 +- 7 files changed, 312 insertions(+), 104 deletions(-) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -873,6 +873,8 @@ instead. +.. _sub-interpreter-support: + Sub-interpreter support ======================= 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 @@ -82,6 +82,18 @@ Similar to :c:func:`PyModule_GetNameObject` but return the name encoded to ``'utf-8'``. +.. c:function:: void* PyModule_GetState(PyObject *module) + + Return the "state" of the module, that is, a pointer to the block of memory + allocated at module creation time, or *NULL*. See + :c:member:`PyModuleDef.m_size`. + + +.. c:function:: PyModuleDef* PyModule_GetDef(PyObject *module) + + Return a pointer to the :c:type:`PyModuleDef` struct from which the module was + created, or *NULL* if the module wasn't created from a definition. + .. c:function:: PyObject* PyModule_GetFilenameObject(PyObject *module) @@ -107,57 +119,25 @@ unencodable filenames, use :c:func:`PyModule_GetFilenameObject` instead. -Per-interpreter module state -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Single-phase initialization creates singleton modules that can store additional -information as part of the interpreter, allow that state to be retrieved later -with only a reference to the module definition, rather than to the module -itself. - -.. c:function:: void* PyModule_GetState(PyObject *module) - - Return the "state" of the module, that is, a pointer to the block of memory - allocated at module creation time, or *NULL*. See - :c:member:`PyModuleDef.m_size`. - - -.. c:function:: PyModuleDef* PyModule_GetDef(PyObject *module) - - 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`. - -.. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) - - Returns the module object that was created from *def* for the current interpreter. - This method requires that the module object has been attached to the interpreter state with - :c:func:`PyState_AddModule` beforehand. In case the corresponding module object is not - found or has not been attached to the interpreter state yet, it returns NULL. - -.. c:function:: int PyState_AddModule(PyObject *module, PyModuleDef *def) - - Attaches the module object passed to the function to the interpreter state. This allows - the module object to be accessible via - :c:func:`PyState_FindModule`. - - .. versionadded:: 3.3 - -.. c:function:: int PyState_RemoveModule(PyModuleDef *def) - - Removes the module object created from *def* from the interpreter state. - - .. versionadded:: 3.3 +.. _initializing-modules: Initializing C modules ^^^^^^^^^^^^^^^^^^^^^^ +Modules objects are usually created from extension modules (shared libraries +which export an initialization function), or compiled-in modules +(where the initialization function is added using :c:func:`PyImport_AppendInittab`). +See :ref:`building` or :ref:`extending-with-embedding` for details. + +The initialization function can either pass pass a module definition instance +to :c:func:`PyModule_Create`, and return the resulting module object, +or request "multi-phase initialization" by returning the definition struct itself. + .. c:type:: PyModuleDef - This struct holds all information that is needed to create a module object. - There is usually only one static variable of that type for each module, which - is statically initialized and then passed to :c:func:`PyModule_Create` in the - module initialization function. + The module definition struct, which holds all information needed to create + a module object. There is usually only one statically initialized variable + of this type for each module. .. c:member:: PyModuleDef_Base m_base @@ -174,19 +154,21 @@ .. c:member:: Py_ssize_t m_size - Some modules allow re-initialization (calling their ``PyInit_*`` function - more than once). These modules should keep their state in a per-module - memory area that can be retrieved with :c:func:`PyModule_GetState`. + Module state may be kept in a per-module memory area that can be + retrieved with :c:func:`PyModule_GetState`, rather than in static globals. + This makes modules safe for use in multiple sub-interpreters. - This memory should be used, rather than static globals, to hold per-module - state, since it is then safe for use in multiple sub-interpreters. It is - freed when the module object is deallocated, after the :c:member:`m_free` - function has been called, if present. + This memory area is allocated based on *m_size* on module creation, + and freed when the module object is deallocated, after the + :c:member:`m_free` function has been called, if present. - Setting ``m_size`` to ``-1`` means that the module can not be - re-initialized because it has global state. Setting it to a non-negative - value means that the module can be re-initialized and specifies the - additional amount of memory it requires for its state. + Setting ``m_size`` to ``-1`` means that the module does not support + sub-interpreters, because it has global state. + + Setting it to a non-negative value means that the module can be + re-initialized and specifies the additional amount of memory it requires + for its state. Non-negative ``m_size`` is required for multi-phase + initialization. See :PEP:`3121` for more details. @@ -198,7 +180,15 @@ .. c:member:: PyModuleDef_Slot* m_slots An array of slot definitions for multi-phase initialization, terminated by - a *NULL* entry. + a ``{0, NULL}`` entry. + When using single-phase initialization, *m_slots* must be *NULL*. + + .. versionchanged:: 3.5 + + Prior to version 3.5, this member was always set to *NULL*, + and was defined as: + + .. c:member:: inquiry m_reload .. c:member:: traverseproc m_traverse @@ -215,20 +205,23 @@ A function to call during deallocation of the module object, or *NULL* if not needed. +Single-phase initialization +........................... + The module initialization function may create and return the module object directly. This is referred to as "single-phase initialization", and uses one of the following two module creation functions: -.. c:function:: PyObject* PyModule_Create(PyModuleDef *module) +.. c:function:: PyObject* PyModule_Create(PyModuleDef *def) - Create a new module object, given the definition in *module*. This behaves + Create a new module object, given the definition in *def*. This behaves like :c:func:`PyModule_Create2` with *module_api_version* set to :const:`PYTHON_API_VERSION`. -.. c:function:: PyObject* PyModule_Create2(PyModuleDef *module, int module_api_version) +.. c:function:: PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) - Create a new module object, given the definition in *module*, assuming the + Create a new module object, given the definition in *def*, assuming the API version *module_api_version*. If that version does not match the version of the running interpreter, a :exc:`RuntimeWarning` is emitted. @@ -237,39 +230,179 @@ Most uses of this function should be using :c:func:`PyModule_Create` instead; only use this if you are sure you need it. +Before it is returned from in the initialization function, the resulting module +object is typically populated using functions like :c:func:`PyModule_AddObject`. -Alternatively, the module initialization function may instead return a -:c:type:`PyModuleDef` instance with a non-empty ``m_slots`` array. This is -referred to as "multi-phase initialization", and ``PyModuleDef`` instance -should be initialized with the following function: +.. _multi-phase-initialization: -.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *module) +Multi-phase initialization +.......................... + +An alternate way to specify extensions is to request "multi-phase initialization". +Extension modules created this way behave more like Python modules: the +initialization is split between the *creation phase*, when the module object +is created, and the *execution phase*, when it is populated. +The distinction is similar to the :py:meth:`__new__` and :py:meth:`__init__` methods +of classes. + +Unlike modules created using single-phase initialization, these modules are not +singletons: if the *sys.modules* entry is removed and the module is re-imported, +a new module object is created, and the old module is subject to normal garbage +collection -- as with Python modules. +By default, multiple modules created from the same definition should be +independent: changes to one should not affect the others. +This means that all state should be specific to the module object (using e.g. +using :c:func:`PyModule_GetState`), or its contents (such as the module's +:attr:`__dict__` or individual classes created with :c:func:`PyType_FromSpec`). + +All modules created using multi-phase initialization are expected to support +:ref:`sub-interpreters `. Making sure multiple modules +are independent is typically enough to achieve this. + +To request multi-phase initialization, the initialization function +(PyInit_modulename) returns a :c:type:`PyModuleDef` instance with non-empty +:c:member:`~PyModuleDef.m_slots`. Before it is returned, the ``PyModuleDef`` +instance must be initialized with the following function: + +.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *def) Ensures a module definition is a properly initialized Python object that correctly reports its type and reference count. -.. XXX (ncoghlan): It's not clear if it makes sense to document PyModule_ExecDef - PyModule_FromDefAndSpec or PyModule_FromDefAndSpec2 here, as end user code - generally shouldn't be calling those. + Returns *def* cast to ``PyObject*``, or *NULL* if an error occurred. -The module initialization function (if using single phase initialization) or -a function called from a module execution slot (if using multiphase -initialization), can use the following functions to help initialize the module -state: + .. versionadded:: 3.5 + +The *m_slots* member of the module definition must point to an array of +``PyModuleDef_Slot`` structures: + +.. c:type:: PyModuleDef_Slot + + .. c:member:: int slot + + A slot ID, chosen from the available values explained below. + + .. c:member:: void* value + + Value of the slot, whose meaning depends on the slot ID. + + .. versionadded:: 3.5 + +The *m_slots* array must be terminated by a slot with id 0. + +The available slot types are: + +.. c:var:: Py_mod_create + + Specifies a function that is called to create the module object itself. + The *value* pointer of this slot must point to a function of the signature: + + .. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def) + + The function receives a :py:class:`~importlib.machinery.ModuleSpec` + instance, as defined in :PEP:`451`, and the module definition. + It should return a new module object, or set an error + and return *NULL*. + + This function should be kept minimal. In particular, it should not + call arbitrary Python code, as trying to import the same module again may + result in an infinite loop. + + Multiple ``Py_mod_create`` slots may not be specified in one module + definition. + + If ``Py_mod_create`` is not specified, the import machinery will create + a normal module object using :c:func:`PyModule_New`. The name is taken from + *spec*, not the definition, to allow extension modules to dynamically adjust + to their place in the module hierarchy and be imported under different + names through symlinks, all while sharing a single module definition. + + There is no requirement for the returned object to be an instance of + :c:type:`PyModule_Type`. Any type can be used, as long as it supports + setting and getting import-related attributes. + However, only ``PyModule_Type`` instances may be returned if the + ``PyModuleDef`` has non-*NULL* ``m_methods``, ``m_traverse``, ``m_clear``, + ``m_free``; non-zero ``m_size``; or slots other than ``Py_mod_create``. + +.. c:var:: Py_mod_exec + + Specifies a function that is called to *execute* the module. + This is equivalent to executing the code of a Python module: typically, + this function adds classes and constants to the module. + The signature of the function is: + + .. c:function:: int exec_module(PyObject* module) + + If multiple ``Py_mod_exec`` slots are specified, they are processed in the + order they appear in the *m_slots* array. + +See :PEP:`489` for more details on multi-phase initialization. + +Low-level module creation functions +................................... + +The following functions are called under the hood when using multi-phase +initialization. They can be used directly, for example when creating module +objects dynamically. Note that both ``PyModule_FromDefAndSpec`` and +``PyModule_ExecDef`` must be called to fully initialize a module. + +.. c:function:: PyObject * PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec) + + Create a new module object, given the definition in *module* and the + ModuleSpec *spec*. This behaves like :c:func:`PyModule_FromDefAndSpec2` + with *module_api_version* set to :const:`PYTHON_API_VERSION`. + + .. versionadded:: 3.5 + +.. c:function:: PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version) + + Create a new module object, given the definition in *module* and the + ModuleSpec *spec*, assuming the API version *module_api_version*. + If that version does not match the version of the running interpreter, + a :exc:`RuntimeWarning` is emitted. + + .. note:: + + Most uses of this function should be using :c:func:`PyModule_FromDefAndSpec` + instead; only use this if you are sure you need it. + + .. versionadded:: 3.5 + +.. c:function:: int PyModule_ExecDef(PyObject *module, PyModuleDef *def) + + Process any execution slots (:c:data:`Py_mod_exec`) given in *def*. + + .. versionadded:: 3.5 .. c:function:: int PyModule_SetDocString(PyObject *module, const char *docstring) - Set the docstring for *module* to *docstring*. Return ``-1`` on error, ``0`` - on success. + Set the docstring for *module* to *docstring*. + This function is called automatically when creating a module from + ``PyModuleDef``, using either ``PyModule_Create`` or + ``PyModule_FromDefAndSpec``. + + .. versionadded:: 3.5 .. c:function:: int PyModule_AddFunctions(PyObject *module, PyMethodDef *functions) - Add the functions from the ``NULL`` terminated *functions* array to *module*. + Add the functions from the *NULL* terminated *functions* array to *module*. Refer to the :c:type:`PyMethodDef` documentation for details on individual entries (due to the lack of a shared module namespace, module level "functions" implemented in C typically receive the module as their first parameter, making them similar to instance methods on Python classes). + This function is called automatically when creating a module from + ``PyModuleDef``, using either ``PyModule_Create`` or + ``PyModule_FromDefAndSpec``. + .. versionadded:: 3.5 + +Support functions +................. + +The module initialization function (if using single phase initialization) or +a function called from a module execution slot (if using multi-phase +initialization), can use the following functions to help initialize the module +state: .. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value) @@ -288,7 +421,7 @@ Add a string constant to *module* as *name*. This convenience function can be used from the module's initialization function. The string *value* must be - null-terminated. Return ``-1`` on error, ``0`` on success. + *NULL*-terminated. Return ``-1`` on error, ``0`` on success. .. c:function:: int PyModule_AddIntMacro(PyObject *module, macro) @@ -302,3 +435,36 @@ .. c:function:: int PyModule_AddStringMacro(PyObject *module, macro) Add a string constant to *module*. + + +Module lookup +^^^^^^^^^^^^^ + +Single-phase initialization creates singleton modules that can be looked up +in the context of the current interpreter. This allows the module object to be +retrieved later with only a reference to the module definition. + +These functions will not work on modules created using multi-phase initialization, +since multiple such modules can be created from a single definition. + +.. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) + + Returns the module object that was created from *def* for the current interpreter. + This method requires that the module object has been attached to the interpreter state with + :c:func:`PyState_AddModule` beforehand. In case the corresponding module object is not + found or has not been attached to the interpreter state yet, it returns *NULL*. + +.. c:function:: int PyState_AddModule(PyObject *module, PyModuleDef *def) + + Attaches the module object passed to the function to the interpreter state. This allows + the module object to be accessible via :c:func:`PyState_FindModule`. + + Only effective on modules created using single-phase initialization. + + .. versionadded:: 3.3 + +.. c:function:: int PyState_RemoveModule(PyModuleDef *def) + + Removes the module object created from *def* from the interpreter state. + + .. versionadded:: 3.3 diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -1,27 +1,58 @@ .. highlightlang:: c - .. _building: -******************************************** +***************************** +Building C and C++ Extensions +***************************** + +A C extension for CPython is a shared library (e.g. a ``.so`` file on Linux, +``.pyd`` on Windows), which exports an *initialization function*. + +To be importable, the shared library must be available on :envvar:`PYTHONPATH`, +and must be named after the module name, with an appropriate extension. +When using distutils, the correct filename is generated automatically. + +The initialization function has the signature: + +.. c:function:: PyObject* PyInit_modulename(void) + +It returns either a fully-initialized module, or a :c:type:`PyModuleDef` +instance. See :ref:`initializing-modules` for details. + +.. highlightlang:: python + +For modules with ASCII-only names, the function must be named +``PyInit_``, with ```` replaced by the name of the +module. When using :ref:`multi-phase-initialization`, non-ASCII module names +are allowed. In this case, the initialization function name is +``PyInitU_``, with ```` encoded using Python's +*punycode* encoding with hyphens replaced by underscores. In Python:: + + def initfunc_name(name): + try: + suffix = b'_' + name.encode('ascii') + except UnicodeEncodeError: + suffix = b'U_' + name.encode('punycode').replace(b'-', b'_') + return b'PyInit' + suffix + +It is possible to export multiple modules from a single shared library by +defining multiple initialization functions. However, importing them requires +using symbolic links or a custom importer, because by default only the +function corresponding to the filename is found. +See :PEP:`489#multiple-modules-in-one-library` for details. + + +.. highlightlang:: c + Building C and C++ Extensions with distutils -******************************************** +============================================ .. sectionauthor:: Martin v. L?wis - -Starting in Python 1.4, Python provides, on Unix, a special make file for -building make files for building dynamically-linked extensions and custom -interpreters. Starting with Python 2.0, this mechanism (known as related to -Makefile.pre.in, and Setup files) is no longer supported. Building custom -interpreters was rarely used, and extension modules can be built using -distutils. - -Building an extension module using distutils requires that distutils is -installed on the build machine, which is included in Python 2.x and available -separately for Python 1.5. Since distutils also supports creation of binary -packages, users don't necessarily need a compiler and distutils to install the -extension. +Extension modules can be built using distutils, which is included in Python. +Since distutils also supports creation of binary packages, users don't +necessarily need a compiler and distutils to install the extension. A distutils package contains a driver script, :file:`setup.py`. This is a plain Python file, which, in the most simple case, could look like this:: diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -413,6 +413,13 @@ as :file:`Modules/xxmodule.c`. This file may be used as a template or simply read as an example. +.. note:: + + Unlike our ``spam`` example, ``xxmodule`` uses *multi-phase initialization* + (new in Python 3.5), where a PyModuleDef structure is returned from + ``PyInit_spam``, and creation of the module is left to the import machinery. + For details on multi-phase initialization, see :PEP:`489`. + .. _compilation: diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -98,9 +98,8 @@ it. Copy your C sources into it. Note that the module source file name does not necessarily have to match the module name, but the name of the initialization function should match the module name --- you can only import a - module :mod:`spam` if its initialization function is called :c:func:`initspam`, - and it should call :c:func:`Py_InitModule` with the string ``"spam"`` as its - first argument (use the minimal :file:`example.c` in this directory as a guide). + module :mod:`spam` if its initialization function is called :c:func:`PyInit_spam`, + (see :ref:`building`, or use the minimal :file:`Modules/xxmodule.c` as a guide). By convention, it lives in a file called :file:`spam.c` or :file:`spammodule.c`. The output file should be called :file:`spam.pyd` (in Release mode) or :file:`spam_d.pyd` (in Debug mode). The extension :file:`.pyd` was chosen diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -283,7 +283,7 @@ This change brings the import semantics of extension modules that opt-in to using the new mechanism much closer to those of Python source and bytecode -modules, including the ability to any valid identifier as a module name, +modules, including the ability to use any valid identifier as a module name, rather than being restricted to ASCII. .. seealso:: @@ -763,7 +763,7 @@ ----------- * The :mod:`unicodedata` module now uses data from `Unicode 8.0.0 -`_. + `_. wsgiref diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,12 +17,6 @@ for patterns that starts with capturing groups. Fast searching optimization now can't be disabled at compile time. -Documentation -------------- - -- Issue #24351: Clarify what is meant by "identifier" in the context of - string.Template instances. - What's New in Python 3.5.0 beta 3? ================================== @@ -111,6 +105,15 @@ tp_finalize to avoid reference leaks encountered when combining tp_dealloc with PyType_FromSpec (see issue #16690 for details) +Documentation +------------- + +- Issue #24458: Update documentation to cover multi-phase initialization for + extension modules (PEP 489). Patch by Petr Viktorin. + +- Issue #24351: Clarify what is meant by "identifier" in the context of + string.Template instances. + What's New in Python 3.5.0 beta 2? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 11:52:15 2015 From: python-checkins at python.org (nick.coghlan) Date: Fri, 03 Jul 2015 09:52:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogQ2xvc2UgIzI0NDU4?= =?utf-8?q?=3A_PEP_489_documentation?= Message-ID: <20150703095215.17196.61460@psf.io> https://hg.python.org/cpython/rev/bad92d696866 changeset: 96776:bad92d696866 branch: 3.5 parent: 96774:7edbbcbf5936 user: Nick Coghlan date: Fri Jul 03 19:49:15 2015 +1000 summary: Close #24458: PEP 489 documentation Patch by Petr Viktorin. files: Doc/c-api/init.rst | 2 + Doc/c-api/module.rst | 320 ++++++++++++++++++----- Doc/extending/building.rst | 63 +++- Doc/extending/extending.rst | 7 + Doc/extending/windows.rst | 5 +- Doc/whatsnew/3.5.rst | 4 +- Misc/NEWS | 3 + 7 files changed, 306 insertions(+), 98 deletions(-) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -873,6 +873,8 @@ instead. +.. _sub-interpreter-support: + Sub-interpreter support ======================= 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 @@ -82,6 +82,18 @@ Similar to :c:func:`PyModule_GetNameObject` but return the name encoded to ``'utf-8'``. +.. c:function:: void* PyModule_GetState(PyObject *module) + + Return the "state" of the module, that is, a pointer to the block of memory + allocated at module creation time, or *NULL*. See + :c:member:`PyModuleDef.m_size`. + + +.. c:function:: PyModuleDef* PyModule_GetDef(PyObject *module) + + Return a pointer to the :c:type:`PyModuleDef` struct from which the module was + created, or *NULL* if the module wasn't created from a definition. + .. c:function:: PyObject* PyModule_GetFilenameObject(PyObject *module) @@ -107,57 +119,25 @@ unencodable filenames, use :c:func:`PyModule_GetFilenameObject` instead. -Per-interpreter module state -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Single-phase initialization creates singleton modules that can store additional -information as part of the interpreter, allow that state to be retrieved later -with only a reference to the module definition, rather than to the module -itself. - -.. c:function:: void* PyModule_GetState(PyObject *module) - - Return the "state" of the module, that is, a pointer to the block of memory - allocated at module creation time, or *NULL*. See - :c:member:`PyModuleDef.m_size`. - - -.. c:function:: PyModuleDef* PyModule_GetDef(PyObject *module) - - 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`. - -.. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) - - Returns the module object that was created from *def* for the current interpreter. - This method requires that the module object has been attached to the interpreter state with - :c:func:`PyState_AddModule` beforehand. In case the corresponding module object is not - found or has not been attached to the interpreter state yet, it returns NULL. - -.. c:function:: int PyState_AddModule(PyObject *module, PyModuleDef *def) - - Attaches the module object passed to the function to the interpreter state. This allows - the module object to be accessible via - :c:func:`PyState_FindModule`. - - .. versionadded:: 3.3 - -.. c:function:: int PyState_RemoveModule(PyModuleDef *def) - - Removes the module object created from *def* from the interpreter state. - - .. versionadded:: 3.3 +.. _initializing-modules: Initializing C modules ^^^^^^^^^^^^^^^^^^^^^^ +Modules objects are usually created from extension modules (shared libraries +which export an initialization function), or compiled-in modules +(where the initialization function is added using :c:func:`PyImport_AppendInittab`). +See :ref:`building` or :ref:`extending-with-embedding` for details. + +The initialization function can either pass pass a module definition instance +to :c:func:`PyModule_Create`, and return the resulting module object, +or request "multi-phase initialization" by returning the definition struct itself. + .. c:type:: PyModuleDef - This struct holds all information that is needed to create a module object. - There is usually only one static variable of that type for each module, which - is statically initialized and then passed to :c:func:`PyModule_Create` in the - module initialization function. + The module definition struct, which holds all information needed to create + a module object. There is usually only one statically initialized variable + of this type for each module. .. c:member:: PyModuleDef_Base m_base @@ -174,19 +154,21 @@ .. c:member:: Py_ssize_t m_size - Some modules allow re-initialization (calling their ``PyInit_*`` function - more than once). These modules should keep their state in a per-module - memory area that can be retrieved with :c:func:`PyModule_GetState`. + Module state may be kept in a per-module memory area that can be + retrieved with :c:func:`PyModule_GetState`, rather than in static globals. + This makes modules safe for use in multiple sub-interpreters. - This memory should be used, rather than static globals, to hold per-module - state, since it is then safe for use in multiple sub-interpreters. It is - freed when the module object is deallocated, after the :c:member:`m_free` - function has been called, if present. + This memory area is allocated based on *m_size* on module creation, + and freed when the module object is deallocated, after the + :c:member:`m_free` function has been called, if present. - Setting ``m_size`` to ``-1`` means that the module can not be - re-initialized because it has global state. Setting it to a non-negative - value means that the module can be re-initialized and specifies the - additional amount of memory it requires for its state. + Setting ``m_size`` to ``-1`` means that the module does not support + sub-interpreters, because it has global state. + + Setting it to a non-negative value means that the module can be + re-initialized and specifies the additional amount of memory it requires + for its state. Non-negative ``m_size`` is required for multi-phase + initialization. See :PEP:`3121` for more details. @@ -198,7 +180,15 @@ .. c:member:: PyModuleDef_Slot* m_slots An array of slot definitions for multi-phase initialization, terminated by - a *NULL* entry. + a ``{0, NULL}`` entry. + When using single-phase initialization, *m_slots* must be *NULL*. + + .. versionchanged:: 3.5 + + Prior to version 3.5, this member was always set to *NULL*, + and was defined as: + + .. c:member:: inquiry m_reload .. c:member:: traverseproc m_traverse @@ -215,20 +205,23 @@ A function to call during deallocation of the module object, or *NULL* if not needed. +Single-phase initialization +........................... + The module initialization function may create and return the module object directly. This is referred to as "single-phase initialization", and uses one of the following two module creation functions: -.. c:function:: PyObject* PyModule_Create(PyModuleDef *module) +.. c:function:: PyObject* PyModule_Create(PyModuleDef *def) - Create a new module object, given the definition in *module*. This behaves + Create a new module object, given the definition in *def*. This behaves like :c:func:`PyModule_Create2` with *module_api_version* set to :const:`PYTHON_API_VERSION`. -.. c:function:: PyObject* PyModule_Create2(PyModuleDef *module, int module_api_version) +.. c:function:: PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) - Create a new module object, given the definition in *module*, assuming the + Create a new module object, given the definition in *def*, assuming the API version *module_api_version*. If that version does not match the version of the running interpreter, a :exc:`RuntimeWarning` is emitted. @@ -237,39 +230,179 @@ Most uses of this function should be using :c:func:`PyModule_Create` instead; only use this if you are sure you need it. +Before it is returned from in the initialization function, the resulting module +object is typically populated using functions like :c:func:`PyModule_AddObject`. -Alternatively, the module initialization function may instead return a -:c:type:`PyModuleDef` instance with a non-empty ``m_slots`` array. This is -referred to as "multi-phase initialization", and ``PyModuleDef`` instance -should be initialized with the following function: +.. _multi-phase-initialization: -.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *module) +Multi-phase initialization +.......................... + +An alternate way to specify extensions is to request "multi-phase initialization". +Extension modules created this way behave more like Python modules: the +initialization is split between the *creation phase*, when the module object +is created, and the *execution phase*, when it is populated. +The distinction is similar to the :py:meth:`__new__` and :py:meth:`__init__` methods +of classes. + +Unlike modules created using single-phase initialization, these modules are not +singletons: if the *sys.modules* entry is removed and the module is re-imported, +a new module object is created, and the old module is subject to normal garbage +collection -- as with Python modules. +By default, multiple modules created from the same definition should be +independent: changes to one should not affect the others. +This means that all state should be specific to the module object (using e.g. +using :c:func:`PyModule_GetState`), or its contents (such as the module's +:attr:`__dict__` or individual classes created with :c:func:`PyType_FromSpec`). + +All modules created using multi-phase initialization are expected to support +:ref:`sub-interpreters `. Making sure multiple modules +are independent is typically enough to achieve this. + +To request multi-phase initialization, the initialization function +(PyInit_modulename) returns a :c:type:`PyModuleDef` instance with non-empty +:c:member:`~PyModuleDef.m_slots`. Before it is returned, the ``PyModuleDef`` +instance must be initialized with the following function: + +.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *def) Ensures a module definition is a properly initialized Python object that correctly reports its type and reference count. -.. XXX (ncoghlan): It's not clear if it makes sense to document PyModule_ExecDef - PyModule_FromDefAndSpec or PyModule_FromDefAndSpec2 here, as end user code - generally shouldn't be calling those. + Returns *def* cast to ``PyObject*``, or *NULL* if an error occurred. -The module initialization function (if using single phase initialization) or -a function called from a module execution slot (if using multiphase -initialization), can use the following functions to help initialize the module -state: + .. versionadded:: 3.5 + +The *m_slots* member of the module definition must point to an array of +``PyModuleDef_Slot`` structures: + +.. c:type:: PyModuleDef_Slot + + .. c:member:: int slot + + A slot ID, chosen from the available values explained below. + + .. c:member:: void* value + + Value of the slot, whose meaning depends on the slot ID. + + .. versionadded:: 3.5 + +The *m_slots* array must be terminated by a slot with id 0. + +The available slot types are: + +.. c:var:: Py_mod_create + + Specifies a function that is called to create the module object itself. + The *value* pointer of this slot must point to a function of the signature: + + .. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def) + + The function receives a :py:class:`~importlib.machinery.ModuleSpec` + instance, as defined in :PEP:`451`, and the module definition. + It should return a new module object, or set an error + and return *NULL*. + + This function should be kept minimal. In particular, it should not + call arbitrary Python code, as trying to import the same module again may + result in an infinite loop. + + Multiple ``Py_mod_create`` slots may not be specified in one module + definition. + + If ``Py_mod_create`` is not specified, the import machinery will create + a normal module object using :c:func:`PyModule_New`. The name is taken from + *spec*, not the definition, to allow extension modules to dynamically adjust + to their place in the module hierarchy and be imported under different + names through symlinks, all while sharing a single module definition. + + There is no requirement for the returned object to be an instance of + :c:type:`PyModule_Type`. Any type can be used, as long as it supports + setting and getting import-related attributes. + However, only ``PyModule_Type`` instances may be returned if the + ``PyModuleDef`` has non-*NULL* ``m_methods``, ``m_traverse``, ``m_clear``, + ``m_free``; non-zero ``m_size``; or slots other than ``Py_mod_create``. + +.. c:var:: Py_mod_exec + + Specifies a function that is called to *execute* the module. + This is equivalent to executing the code of a Python module: typically, + this function adds classes and constants to the module. + The signature of the function is: + + .. c:function:: int exec_module(PyObject* module) + + If multiple ``Py_mod_exec`` slots are specified, they are processed in the + order they appear in the *m_slots* array. + +See :PEP:`489` for more details on multi-phase initialization. + +Low-level module creation functions +................................... + +The following functions are called under the hood when using multi-phase +initialization. They can be used directly, for example when creating module +objects dynamically. Note that both ``PyModule_FromDefAndSpec`` and +``PyModule_ExecDef`` must be called to fully initialize a module. + +.. c:function:: PyObject * PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec) + + Create a new module object, given the definition in *module* and the + ModuleSpec *spec*. This behaves like :c:func:`PyModule_FromDefAndSpec2` + with *module_api_version* set to :const:`PYTHON_API_VERSION`. + + .. versionadded:: 3.5 + +.. c:function:: PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version) + + Create a new module object, given the definition in *module* and the + ModuleSpec *spec*, assuming the API version *module_api_version*. + If that version does not match the version of the running interpreter, + a :exc:`RuntimeWarning` is emitted. + + .. note:: + + Most uses of this function should be using :c:func:`PyModule_FromDefAndSpec` + instead; only use this if you are sure you need it. + + .. versionadded:: 3.5 + +.. c:function:: int PyModule_ExecDef(PyObject *module, PyModuleDef *def) + + Process any execution slots (:c:data:`Py_mod_exec`) given in *def*. + + .. versionadded:: 3.5 .. c:function:: int PyModule_SetDocString(PyObject *module, const char *docstring) - Set the docstring for *module* to *docstring*. Return ``-1`` on error, ``0`` - on success. + Set the docstring for *module* to *docstring*. + This function is called automatically when creating a module from + ``PyModuleDef``, using either ``PyModule_Create`` or + ``PyModule_FromDefAndSpec``. + + .. versionadded:: 3.5 .. c:function:: int PyModule_AddFunctions(PyObject *module, PyMethodDef *functions) - Add the functions from the ``NULL`` terminated *functions* array to *module*. + Add the functions from the *NULL* terminated *functions* array to *module*. Refer to the :c:type:`PyMethodDef` documentation for details on individual entries (due to the lack of a shared module namespace, module level "functions" implemented in C typically receive the module as their first parameter, making them similar to instance methods on Python classes). + This function is called automatically when creating a module from + ``PyModuleDef``, using either ``PyModule_Create`` or + ``PyModule_FromDefAndSpec``. + .. versionadded:: 3.5 + +Support functions +................. + +The module initialization function (if using single phase initialization) or +a function called from a module execution slot (if using multi-phase +initialization), can use the following functions to help initialize the module +state: .. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value) @@ -288,7 +421,7 @@ Add a string constant to *module* as *name*. This convenience function can be used from the module's initialization function. The string *value* must be - null-terminated. Return ``-1`` on error, ``0`` on success. + *NULL*-terminated. Return ``-1`` on error, ``0`` on success. .. c:function:: int PyModule_AddIntMacro(PyObject *module, macro) @@ -302,3 +435,36 @@ .. c:function:: int PyModule_AddStringMacro(PyObject *module, macro) Add a string constant to *module*. + + +Module lookup +^^^^^^^^^^^^^ + +Single-phase initialization creates singleton modules that can be looked up +in the context of the current interpreter. This allows the module object to be +retrieved later with only a reference to the module definition. + +These functions will not work on modules created using multi-phase initialization, +since multiple such modules can be created from a single definition. + +.. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) + + Returns the module object that was created from *def* for the current interpreter. + This method requires that the module object has been attached to the interpreter state with + :c:func:`PyState_AddModule` beforehand. In case the corresponding module object is not + found or has not been attached to the interpreter state yet, it returns *NULL*. + +.. c:function:: int PyState_AddModule(PyObject *module, PyModuleDef *def) + + Attaches the module object passed to the function to the interpreter state. This allows + the module object to be accessible via :c:func:`PyState_FindModule`. + + Only effective on modules created using single-phase initialization. + + .. versionadded:: 3.3 + +.. c:function:: int PyState_RemoveModule(PyModuleDef *def) + + Removes the module object created from *def* from the interpreter state. + + .. versionadded:: 3.3 diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -1,27 +1,58 @@ .. highlightlang:: c - .. _building: -******************************************** +***************************** +Building C and C++ Extensions +***************************** + +A C extension for CPython is a shared library (e.g. a ``.so`` file on Linux, +``.pyd`` on Windows), which exports an *initialization function*. + +To be importable, the shared library must be available on :envvar:`PYTHONPATH`, +and must be named after the module name, with an appropriate extension. +When using distutils, the correct filename is generated automatically. + +The initialization function has the signature: + +.. c:function:: PyObject* PyInit_modulename(void) + +It returns either a fully-initialized module, or a :c:type:`PyModuleDef` +instance. See :ref:`initializing-modules` for details. + +.. highlightlang:: python + +For modules with ASCII-only names, the function must be named +``PyInit_``, with ```` replaced by the name of the +module. When using :ref:`multi-phase-initialization`, non-ASCII module names +are allowed. In this case, the initialization function name is +``PyInitU_``, with ```` encoded using Python's +*punycode* encoding with hyphens replaced by underscores. In Python:: + + def initfunc_name(name): + try: + suffix = b'_' + name.encode('ascii') + except UnicodeEncodeError: + suffix = b'U_' + name.encode('punycode').replace(b'-', b'_') + return b'PyInit' + suffix + +It is possible to export multiple modules from a single shared library by +defining multiple initialization functions. However, importing them requires +using symbolic links or a custom importer, because by default only the +function corresponding to the filename is found. +See :PEP:`489#multiple-modules-in-one-library` for details. + + +.. highlightlang:: c + Building C and C++ Extensions with distutils -******************************************** +============================================ .. sectionauthor:: Martin v. L?wis - -Starting in Python 1.4, Python provides, on Unix, a special make file for -building make files for building dynamically-linked extensions and custom -interpreters. Starting with Python 2.0, this mechanism (known as related to -Makefile.pre.in, and Setup files) is no longer supported. Building custom -interpreters was rarely used, and extension modules can be built using -distutils. - -Building an extension module using distutils requires that distutils is -installed on the build machine, which is included in Python 2.x and available -separately for Python 1.5. Since distutils also supports creation of binary -packages, users don't necessarily need a compiler and distutils to install the -extension. +Extension modules can be built using distutils, which is included in Python. +Since distutils also supports creation of binary packages, users don't +necessarily need a compiler and distutils to install the extension. A distutils package contains a driver script, :file:`setup.py`. This is a plain Python file, which, in the most simple case, could look like this:: diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -413,6 +413,13 @@ as :file:`Modules/xxmodule.c`. This file may be used as a template or simply read as an example. +.. note:: + + Unlike our ``spam`` example, ``xxmodule`` uses *multi-phase initialization* + (new in Python 3.5), where a PyModuleDef structure is returned from + ``PyInit_spam``, and creation of the module is left to the import machinery. + For details on multi-phase initialization, see :PEP:`489`. + .. _compilation: diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -98,9 +98,8 @@ it. Copy your C sources into it. Note that the module source file name does not necessarily have to match the module name, but the name of the initialization function should match the module name --- you can only import a - module :mod:`spam` if its initialization function is called :c:func:`initspam`, - and it should call :c:func:`Py_InitModule` with the string ``"spam"`` as its - first argument (use the minimal :file:`example.c` in this directory as a guide). + module :mod:`spam` if its initialization function is called :c:func:`PyInit_spam`, + (see :ref:`building`, or use the minimal :file:`Modules/xxmodule.c` as a guide). By convention, it lives in a file called :file:`spam.c` or :file:`spammodule.c`. The output file should be called :file:`spam.pyd` (in Release mode) or :file:`spam_d.pyd` (in Debug mode). The extension :file:`.pyd` was chosen diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -283,7 +283,7 @@ This change brings the import semantics of extension modules that opt-in to using the new mechanism much closer to those of Python source and bytecode -modules, including the ability to any valid identifier as a module name, +modules, including the ability to use any valid identifier as a module name, rather than being restricted to ASCII. .. seealso:: @@ -763,7 +763,7 @@ ----------- * The :mod:`unicodedata` module now uses data from `Unicode 8.0.0 -`_. + `_. wsgiref diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -92,6 +92,9 @@ Documentation ------------- +- Issue #24458: Update documentation to cover multi-phase initialization for + extension modules (PEP 489). Patch by Petr Viktorin. + - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 15:31:30 2015 From: python-checkins at python.org (stefan.krah) Date: Fri, 03 Jul 2015 13:31:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NTQz?= =?utf-8?q?=3A_Use_AC=5FLINK_instead_of_AC=5FCOMPILE_in_order_to_prevent_f?= =?utf-8?q?alse?= Message-ID: <20150703133130.11325.54868@psf.io> https://hg.python.org/cpython/rev/2a3c0ad52b99 changeset: 96778:2a3c0ad52b99 branch: 2.7 parent: 96753:301d7efac3de user: Stefan Krah date: Fri Jul 03 15:30:54 2015 +0200 summary: Issue #24543: Use AC_LINK instead of AC_COMPILE in order to prevent false positives with the -flto option (gcc >= 4.9.0 and clang). files: configure | 5 +++-- configure.ac | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -12747,12 +12747,13 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : have_gcc_asm_for_x87=yes else have_gcc_asm_for_x87=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x87" >&5 $as_echo "$have_gcc_asm_for_x87" >&6; } if test "$have_gcc_asm_for_x87" = yes diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3723,7 +3723,7 @@ # so we try it on all platforms. AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set x87 control word) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); __asm__ __volatile__ ("fldcw %0" : : "m" (cw)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 19:12:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 17:12:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ0MDAp?= Message-ID: <20150703171159.86787.68666@psf.io> https://hg.python.org/cpython/rev/a14f6a70d013 changeset: 96780:a14f6a70d013 parent: 96777:86daa37c1cc9 parent: 96779:cb1aafc9ad7e user: Yury Selivanov date: Fri Jul 03 13:11:54 2015 -0400 summary: Merge 3.5 (Issue #24400) files: Doc/library/collections.abc.rst | 18 +++++++++------- Doc/library/inspect.rst | 19 +++++++++++++++++ Doc/whatsnew/3.5.rst | 5 ++- Lib/_collections_abc.py | 17 +-------------- Lib/inspect.py | 7 ++++++ Lib/test/test_collections.py | 12 +++++++--- Lib/test/test_inspect.py | 23 +++++++++++++++++++++ Lib/test/test_types.py | 16 +++++++++++-- Lib/types.py | 10 ++++---- Misc/NEWS | 4 ++- 10 files changed, 92 insertions(+), 39 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -162,10 +162,11 @@ :class:`~collections.abc.Coroutine` ABC are all instances of this ABC. .. note:: - In CPython, generator-based coroutines are *awaitables*, even though - they do not have an :meth:`__await__` method. This ABC - implements an :meth:`~class.__instancecheck__` method to make them - instances of itself. + In CPython, generator-based coroutines (generators decorated with + :func:`types.coroutine` or :func:`asyncio.coroutine`) are + *awaitables*, even though they do not have an :meth:`__await__` method. + Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``. + Use :func:`inspect.isawaitable` to detect them. .. versionadded:: 3.5 @@ -179,10 +180,11 @@ :class:`Awaitable`. See also the definition of :term:`coroutine`. .. note:: - In CPython, generator-based coroutines are *awaitables* and *coroutines*, - even though they do not have an :meth:`__await__` method. This ABC - implements an :meth:`~class.__instancecheck__` method to make them - instances of itself. + In CPython, generator-based coroutines (generators decorated with + :func:`types.coroutine` or :func:`asyncio.coroutine`) are + *awaitables*, even though they do not have an :meth:`__await__` method. + Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``. + Use :func:`inspect.isawaitable` to detect them. .. versionadded:: 3.5 diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -310,6 +310,25 @@ .. versionadded:: 3.5 +.. function:: isawaitable(object) + + Return true if the object can be used in :keyword:`await` expression. + + Can also be used to distinguish generator-based coroutines from regular + generators:: + + def gen(): + yield + @types.coroutine + def gen_coro(): + yield + + assert not isawaitable(gen()) + assert isawaitable(gen_coro()) + + .. versionadded:: 3.5 + + .. function:: istraceback(object) Return true if the object is a traceback. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -532,8 +532,9 @@ * New argument ``follow_wrapped`` for :func:`inspect.signature`. (Contributed by Yury Selivanov in :issue:`20691`.) -* New :func:`~inspect.iscoroutine` and :func:`~inspect.iscoroutinefunction` - functions. (Contributed by Yury Selivanov in :issue:`24017`.) +* New :func:`~inspect.iscoroutine`, :func:`~inspect.iscoroutinefunction` + and :func:`~inspect.isawaitable` functions. (Contributed by + Yury Selivanov in :issue:`24017`.) * New :func:`~inspect.getcoroutinelocals` and :func:`~inspect.getcoroutinestate` functions. (Contributed by Yury Selivanov in :issue:`24400`.) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -81,22 +81,7 @@ return NotImplemented -class _AwaitableMeta(ABCMeta): - - def __instancecheck__(cls, instance): - # This hook is needed because we can't add - # '__await__' method to generator objects, and - # we can't register GeneratorType on Awaitable. - # NB: 0x100 = CO_ITERABLE_COROUTINE - # (We don't want to import 'inspect' module, as - # a dependency for 'collections.abc') - if (instance.__class__ is generator and - instance.gi_code.co_flags & 0x100): - return True - return super().__instancecheck__(instance) - - -class Awaitable(metaclass=_AwaitableMeta): +class Awaitable(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -207,6 +207,13 @@ """Return true if the object is a coroutine.""" return isinstance(object, types.CoroutineType) +def isawaitable(object): + """Return true is object can be passed to an ``await`` expression.""" + return (isinstance(object, types.CoroutineType) or + isinstance(object, types.GeneratorType) and + object.gi_code.co_flags & CO_ITERABLE_COROUTINE or + isinstance(object, collections.abc.Awaitable)) + def istraceback(object): """Return true if the object is a traceback. 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 @@ -511,8 +511,10 @@ self.assertTrue(issubclass(type(x), Awaitable)) c = coro() - self.assertIsInstance(c, Awaitable) - c.close() # awoid RuntimeWarning that coro() was not awaited + # Iterable coroutines (generators with CO_ITERABLE_COROUTINE + # flag don't have '__await__' method, hence can't be instances + # of Awaitable. Use inspect.isawaitable to detect them. + self.assertNotIsInstance(c, Awaitable) c = new_coro() self.assertIsInstance(c, Awaitable) @@ -559,8 +561,10 @@ self.assertTrue(issubclass(type(x), Awaitable)) c = coro() - self.assertIsInstance(c, Coroutine) - c.close() # awoid RuntimeWarning that coro() was not awaited + # Iterable coroutines (generators with CO_ITERABLE_COROUTINE + # flag don't have '__await__' method, hence can't be instances + # of Coroutine. Use inspect.isawaitable to detect them. + self.assertNotIsInstance(c, Coroutine) c = new_coro() self.assertIsInstance(c, Coroutine) 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 @@ -151,6 +151,29 @@ coro.close(); gen_coro.close() # silence warnings + def test_isawaitable(self): + def gen(): yield + self.assertFalse(inspect.isawaitable(gen())) + + coro = coroutine_function_example(1) + gen_coro = gen_coroutine_function_example(1) + + self.assertTrue(inspect.isawaitable(coro)) + self.assertTrue(inspect.isawaitable(gen_coro)) + + class Future: + def __await__(): + pass + self.assertTrue(inspect.isawaitable(Future())) + self.assertFalse(inspect.isawaitable(Future)) + + class NotFuture: pass + not_fut = NotFuture() + not_fut.__await__ = lambda: None + self.assertFalse(inspect.isawaitable(not_fut)) + + coro.close(); gen_coro.close() # silence warnings + def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) self.assertTrue(inspect.isroutine([].count)) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1447,6 +1447,19 @@ with self.assertRaisesRegex(Exception, 'ham'): wrapper.throw(Exception, Exception('ham')) + def test_returning_itercoro(self): + @types.coroutine + def gen(): + yield + + gencoro = gen() + + @types.coroutine + def foo(): + return gencoro + + self.assertIs(foo(), gencoro) + def test_genfunc(self): def gen(): yield self.assertIs(types.coroutine(gen), gen) @@ -1457,9 +1470,6 @@ g = gen() self.assertTrue(g.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE) self.assertFalse(g.gi_code.co_flags & inspect.CO_COROUTINE) - self.assertIsInstance(g, collections.abc.Coroutine) - self.assertIsInstance(g, collections.abc.Awaitable) - g.close() # silence warning self.assertIs(types.coroutine(gen), gen) diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -241,12 +241,12 @@ @_functools.wraps(func) def wrapped(*args, **kwargs): coro = func(*args, **kwargs) - if coro.__class__ is CoroutineType: - # 'coro' is a native coroutine object. + if (coro.__class__ is CoroutineType or + coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100): + # 'coro' is a native coroutine object or an iterable coroutine return coro - if (coro.__class__ is GeneratorType or - (isinstance(coro, _collections_abc.Generator) and - not isinstance(coro, _collections_abc.Coroutine))): + if (isinstance(coro, _collections_abc.Generator) and + not isinstance(coro, _collections_abc.Coroutine)): # 'coro' is either a pure Python generator iterator, or it # implements collections.abc.Generator (and does not implement # collections.abc.Coroutine). diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,7 +41,9 @@ uses collections.abc.Coroutine, it's intended to test for pure 'async def' coroutines only; add new opcode: GET_YIELD_FROM_ITER; fix generators wrapper used in types.coroutine to be instance of collections.abc.Generator; - inspect.isawaitable was removed (use collections.abc.Awaitable). + collections.abc.Awaitable and collections.abc.Coroutine can no longer + be used to detect generator-based coroutines--use inspect.isawaitable + instead. - Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. Contributed by Benno Leslie and Yury Selivanov. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 19:11:59 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 03 Jul 2015 17:11:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDAw?= =?utf-8?q?=3A_Resurrect_inspect=2Eisawaitable=28=29?= Message-ID: <20150703171159.23315.29860@psf.io> https://hg.python.org/cpython/rev/cb1aafc9ad7e changeset: 96779:cb1aafc9ad7e branch: 3.5 parent: 96776:bad92d696866 user: Yury Selivanov date: Fri Jul 03 13:11:35 2015 -0400 summary: Issue #24400: Resurrect inspect.isawaitable() collections.abc.Awaitable and collections.abc.Coroutine no longer use __instancecheck__ hook to detect generator-based coroutines. inspect.isawaitable() can be used to detect generator-based coroutines and to distinguish them from regular generator objects. files: Doc/library/collections.abc.rst | 18 +++++++++------- Doc/library/inspect.rst | 19 +++++++++++++++++ Doc/whatsnew/3.5.rst | 5 ++- Lib/_collections_abc.py | 17 +-------------- Lib/inspect.py | 7 ++++++ Lib/test/test_collections.py | 12 +++++++--- Lib/test/test_inspect.py | 23 +++++++++++++++++++++ Lib/test/test_types.py | 16 +++++++++++-- Lib/types.py | 10 ++++---- Misc/NEWS | 4 ++- 10 files changed, 92 insertions(+), 39 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -162,10 +162,11 @@ :class:`~collections.abc.Coroutine` ABC are all instances of this ABC. .. note:: - In CPython, generator-based coroutines are *awaitables*, even though - they do not have an :meth:`__await__` method. This ABC - implements an :meth:`~class.__instancecheck__` method to make them - instances of itself. + In CPython, generator-based coroutines (generators decorated with + :func:`types.coroutine` or :func:`asyncio.coroutine`) are + *awaitables*, even though they do not have an :meth:`__await__` method. + Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``. + Use :func:`inspect.isawaitable` to detect them. .. versionadded:: 3.5 @@ -179,10 +180,11 @@ :class:`Awaitable`. See also the definition of :term:`coroutine`. .. note:: - In CPython, generator-based coroutines are *awaitables* and *coroutines*, - even though they do not have an :meth:`__await__` method. This ABC - implements an :meth:`~class.__instancecheck__` method to make them - instances of itself. + In CPython, generator-based coroutines (generators decorated with + :func:`types.coroutine` or :func:`asyncio.coroutine`) are + *awaitables*, even though they do not have an :meth:`__await__` method. + Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``. + Use :func:`inspect.isawaitable` to detect them. .. versionadded:: 3.5 diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -310,6 +310,25 @@ .. versionadded:: 3.5 +.. function:: isawaitable(object) + + Return true if the object can be used in :keyword:`await` expression. + + Can also be used to distinguish generator-based coroutines from regular + generators:: + + def gen(): + yield + @types.coroutine + def gen_coro(): + yield + + assert not isawaitable(gen()) + assert isawaitable(gen_coro()) + + .. versionadded:: 3.5 + + .. function:: istraceback(object) Return true if the object is a traceback. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -532,8 +532,9 @@ * New argument ``follow_wrapped`` for :func:`inspect.signature`. (Contributed by Yury Selivanov in :issue:`20691`.) -* New :func:`~inspect.iscoroutine` and :func:`~inspect.iscoroutinefunction` - functions. (Contributed by Yury Selivanov in :issue:`24017`.) +* New :func:`~inspect.iscoroutine`, :func:`~inspect.iscoroutinefunction` + and :func:`~inspect.isawaitable` functions. (Contributed by + Yury Selivanov in :issue:`24017`.) * New :func:`~inspect.getcoroutinelocals` and :func:`~inspect.getcoroutinestate` functions. (Contributed by Yury Selivanov in :issue:`24400`.) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -81,22 +81,7 @@ return NotImplemented -class _AwaitableMeta(ABCMeta): - - def __instancecheck__(cls, instance): - # This hook is needed because we can't add - # '__await__' method to generator objects, and - # we can't register GeneratorType on Awaitable. - # NB: 0x100 = CO_ITERABLE_COROUTINE - # (We don't want to import 'inspect' module, as - # a dependency for 'collections.abc') - if (instance.__class__ is generator and - instance.gi_code.co_flags & 0x100): - return True - return super().__instancecheck__(instance) - - -class Awaitable(metaclass=_AwaitableMeta): +class Awaitable(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -207,6 +207,13 @@ """Return true if the object is a coroutine.""" return isinstance(object, types.CoroutineType) +def isawaitable(object): + """Return true is object can be passed to an ``await`` expression.""" + return (isinstance(object, types.CoroutineType) or + isinstance(object, types.GeneratorType) and + object.gi_code.co_flags & CO_ITERABLE_COROUTINE or + isinstance(object, collections.abc.Awaitable)) + def istraceback(object): """Return true if the object is a traceback. 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 @@ -511,8 +511,10 @@ self.assertTrue(issubclass(type(x), Awaitable)) c = coro() - self.assertIsInstance(c, Awaitable) - c.close() # awoid RuntimeWarning that coro() was not awaited + # Iterable coroutines (generators with CO_ITERABLE_COROUTINE + # flag don't have '__await__' method, hence can't be instances + # of Awaitable. Use inspect.isawaitable to detect them. + self.assertNotIsInstance(c, Awaitable) c = new_coro() self.assertIsInstance(c, Awaitable) @@ -559,8 +561,10 @@ self.assertTrue(issubclass(type(x), Awaitable)) c = coro() - self.assertIsInstance(c, Coroutine) - c.close() # awoid RuntimeWarning that coro() was not awaited + # Iterable coroutines (generators with CO_ITERABLE_COROUTINE + # flag don't have '__await__' method, hence can't be instances + # of Coroutine. Use inspect.isawaitable to detect them. + self.assertNotIsInstance(c, Coroutine) c = new_coro() self.assertIsInstance(c, Coroutine) 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 @@ -151,6 +151,29 @@ coro.close(); gen_coro.close() # silence warnings + def test_isawaitable(self): + def gen(): yield + self.assertFalse(inspect.isawaitable(gen())) + + coro = coroutine_function_example(1) + gen_coro = gen_coroutine_function_example(1) + + self.assertTrue(inspect.isawaitable(coro)) + self.assertTrue(inspect.isawaitable(gen_coro)) + + class Future: + def __await__(): + pass + self.assertTrue(inspect.isawaitable(Future())) + self.assertFalse(inspect.isawaitable(Future)) + + class NotFuture: pass + not_fut = NotFuture() + not_fut.__await__ = lambda: None + self.assertFalse(inspect.isawaitable(not_fut)) + + coro.close(); gen_coro.close() # silence warnings + def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) self.assertTrue(inspect.isroutine([].count)) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1447,6 +1447,19 @@ with self.assertRaisesRegex(Exception, 'ham'): wrapper.throw(Exception, Exception('ham')) + def test_returning_itercoro(self): + @types.coroutine + def gen(): + yield + + gencoro = gen() + + @types.coroutine + def foo(): + return gencoro + + self.assertIs(foo(), gencoro) + def test_genfunc(self): def gen(): yield self.assertIs(types.coroutine(gen), gen) @@ -1457,9 +1470,6 @@ g = gen() self.assertTrue(g.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE) self.assertFalse(g.gi_code.co_flags & inspect.CO_COROUTINE) - self.assertIsInstance(g, collections.abc.Coroutine) - self.assertIsInstance(g, collections.abc.Awaitable) - g.close() # silence warning self.assertIs(types.coroutine(gen), gen) diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -241,12 +241,12 @@ @_functools.wraps(func) def wrapped(*args, **kwargs): coro = func(*args, **kwargs) - if coro.__class__ is CoroutineType: - # 'coro' is a native coroutine object. + if (coro.__class__ is CoroutineType or + coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100): + # 'coro' is a native coroutine object or an iterable coroutine return coro - if (coro.__class__ is GeneratorType or - (isinstance(coro, _collections_abc.Generator) and - not isinstance(coro, _collections_abc.Coroutine))): + if (isinstance(coro, _collections_abc.Generator) and + not isinstance(coro, _collections_abc.Coroutine)): # 'coro' is either a pure Python generator iterator, or it # implements collections.abc.Generator (and does not implement # collections.abc.Coroutine). diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,7 +25,9 @@ uses collections.abc.Coroutine, it's intended to test for pure 'async def' coroutines only; add new opcode: GET_YIELD_FROM_ITER; fix generators wrapper used in types.coroutine to be instance of collections.abc.Generator; - inspect.isawaitable was removed (use collections.abc.Awaitable). + collections.abc.Awaitable and collections.abc.Coroutine can no longer + be used to detect generator-based coroutines--use inspect.isawaitable + instead. - Issue #24450: Add gi_yieldfrom to generators and cr_await to coroutines. Contributed by Benno Leslie and Yury Selivanov. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 21:21:47 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 19:21:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixes_warnings_when_building_python3=2Edll_due_to_the_?= =?utf-8?q?=2Edef_file_accumulating?= Message-ID: <20150703192147.21360.37016@psf.io> https://hg.python.org/cpython/rev/e5082ddfbb60 changeset: 96782:e5082ddfbb60 parent: 96780:a14f6a70d013 parent: 96781:1d0ec12b1e03 user: Steve Dower date: Fri Jul 03 12:21:29 2015 -0700 summary: Fixes warnings when building python3.dll due to the .def file accumulating multiple copies of each line. Adds shebang line to prepare_ssl so it will run with py.exe. files: PCbuild/prepare_ssl.py | 1 + PCbuild/python3dll.vcxproj | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # Script for preparing OpenSSL for building on Windows. # Uses Perl to create nmake makefiles and otherwise prepare the way # for building on 32 or 64 bit platforms. diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -109,7 +109,7 @@ - + @@ -132,7 +132,7 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> - + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 3 21:21:47 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 19:21:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixes_warnings?= =?utf-8?q?_when_building_python3=2Edll_due_to_the_=2Edef_file_accumulatin?= =?utf-8?q?g?= Message-ID: <20150703192147.20885.15326@psf.io> https://hg.python.org/cpython/rev/1d0ec12b1e03 changeset: 96781:1d0ec12b1e03 branch: 3.5 parent: 96779:cb1aafc9ad7e user: Steve Dower date: Fri Jul 03 09:08:47 2015 -0700 summary: Fixes warnings when building python3.dll due to the .def file accumulating multiple copies of each line. Adds shebang line to prepare_ssl so it will run with py.exe. files: PCbuild/prepare_ssl.py | 1 + PCbuild/python3dll.vcxproj | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # Script for preparing OpenSSL for building on Windows. # Uses Perl to create nmake makefiles and otherwise prepare the way # for building on 32 or 64 bit platforms. diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -109,7 +109,7 @@ - + @@ -132,7 +132,7 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> - + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 00:17:58 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 22:17:58 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NDMy?= =?utf-8?q?=3A_Update_Windows_builds_to_use_OpenSSL_1=2E0=2E2c=2E?= Message-ID: <20150703221758.10428.71942@psf.io> https://hg.python.org/cpython/rev/6fd63f0a0026 changeset: 96783:6fd63f0a0026 branch: 3.4 parent: 96769:34460219c0e0 user: Steve Dower date: Fri Jul 03 15:13:48 2015 -0700 summary: Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. files: Misc/NEWS | 2 ++ PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -343,6 +343,8 @@ - Issue #23686: Update OS X 10.5 installer and Windows builds to use OpenSSL 1.0.2a. +- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. + C API ----- diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-8.6.1.0 tk-8.6.1.0 tix-8.4.3.4 diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -20,7 +20,7 @@ $(externalsDir)\sqlite-3.8.3.1 $(externalsDir)\bzip2-1.0.6 $(externalsDir)\xz-5.0.5 - $(externalsDir)\openssl-1.0.2a + $(externalsDir)\openssl-1.0.2c $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,7 +171,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2a of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 00:17:58 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 22:17:58 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324432=3A_Update_Windows_builds_to_use_OpenSSL_1=2E0?= =?utf-8?q?=2E2c=2E?= Message-ID: <20150703221758.24661.71566@psf.io> https://hg.python.org/cpython/rev/ebc8559b2e57 changeset: 96784:ebc8559b2e57 branch: 3.5 parent: 96781:1d0ec12b1e03 parent: 96783:6fd63f0a0026 user: Steve Dower date: Fri Jul 03 15:16:37 2015 -0700 summary: Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. files: Misc/NEWS | 5 +++++ PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -100,6 +100,11 @@ - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. +Build +----- + +- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. + What's New in Python 3.5.0 beta 2? ================================== diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)openssl-1.0.2c\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.1j of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 00:17:58 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 22:17:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324432=3A_Update_Windows_builds_to_use_OpenSSL_1?= =?utf-8?b?LjAuMmMu?= Message-ID: <20150703221758.30594.7072@psf.io> https://hg.python.org/cpython/rev/91c5097bca2b changeset: 96785:91c5097bca2b parent: 96782:e5082ddfbb60 parent: 96784:ebc8559b2e57 user: Steve Dower date: Fri Jul 03 15:17:17 2015 -0700 summary: Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. files: Misc/NEWS | 5 +++++ PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -116,6 +116,11 @@ - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. +Build +----- + +- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. + What's New in Python 3.5.0 beta 2? ================================== diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)openssl-1.0.2c\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.1j of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 00:19:51 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 03 Jul 2015 22:19:51 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NDMy?= =?utf-8?q?=3A_Update_Windows_builds_to_use_OpenSSL_1=2E0=2E2c=2E?= Message-ID: <20150703221951.736.51669@psf.io> https://hg.python.org/cpython/rev/c49d2ea5e48a changeset: 96786:c49d2ea5e48a branch: 2.7 parent: 96778:2a3c0ad52b99 user: Steve Dower date: Fri Jul 03 15:19:38 2015 -0700 summary: Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. files: Misc/NEWS | 6 ++++++ PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.vsprops | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -92,6 +92,12 @@ - Issue #24134: Reverted issue #24134 changes. +Build +----- + +- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. + + IDLE ---- diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,7 +55,7 @@ bzip2-1.0.6 db-4.7.25.0 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-8.5.15.0 tk-8.5.15.0 tix-8.4.3.5 diff --git a/PCbuild/pyproject.vsprops b/PCbuild/pyproject.vsprops --- a/PCbuild/pyproject.vsprops +++ b/PCbuild/pyproject.vsprops @@ -82,7 +82,7 @@ /> https://hg.python.org/cpython/rev/25985b0c4dbf changeset: 96787:25985b0c4dbf branch: 2.7 user: Terry Jan Reedy date: Fri Jul 03 19:10:14 2015 -0400 summary: Issue #24525: Add missing word. Patch by Vincent Legoll. files: Doc/library/urllib.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst --- a/Doc/library/urllib.rst +++ b/Doc/library/urllib.rst @@ -296,7 +296,7 @@ .. note:: urllib also exposes certain utility functions like splittype, splithost and others parsing url into various components. But it is recommended to use - :mod:`urlparse` for parsing urls than using these functions directly. + :mod:`urlparse` for parsing urls rather than using these functions directly. Python 3 does not expose these helper functions from :mod:`urllib.parse` module. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 02:21:22 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 00:21:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Move_insertion_resize_logi?= =?utf-8?b?YyBpbnRvIHNldF9pbnNlcnRfa2V5KCku?= Message-ID: <20150704002122.124440.41373@psf.io> https://hg.python.org/cpython/rev/1fa89f685c4b changeset: 96788:1fa89f685c4b parent: 96785:91c5097bca2b user: Raymond Hettinger date: Fri Jul 03 17:21:17 2015 -0700 summary: Move insertion resize logic into set_insert_key(). Simplifies the code a little bit and does the resize check only when a new key is added (giving a small speed up in the case where the key already exists). Fixes possible bug in set_merge() where the set_insert_key() call relies on a big resize at the start to make enough room for the keys but is vulnerable to a comparision callback that could cause the table to shrink in the middle of the merge. Also, changed the resize threshold from two-thirds of the mask+1 to just two-thirds. The plus one offset gave no real benefit (afterall, the two-thirds mark is just a heuristic and isn't a precise cut-off). files: Objects/setobject.c | 75 +++++++++++--------------------- 1 files changed, 27 insertions(+), 48 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -125,6 +125,8 @@ } } +static int set_table_resize(PySetObject *, Py_ssize_t); + static int set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) { @@ -139,7 +141,7 @@ entry = &table[i]; if (entry->key == NULL) - goto found_null_first; + goto found_unused; freeslot = NULL; perturb = hash; @@ -173,7 +175,7 @@ for (j = 0 ; j < LINEAR_PROBES ; j++) { entry++; if (entry->hash == 0 && entry->key == NULL) - goto found_null; + goto found_unused_or_dummy; if (entry->hash == hash) { PyObject *startkey = entry->key; assert(startkey != dummy); @@ -204,30 +206,27 @@ entry = &table[i]; if (entry->key == NULL) - goto found_null; + goto found_unused_or_dummy; } - found_null_first: + found_unused_or_dummy: + if (freeslot == NULL) + goto found_unused; + Py_INCREF(key); + so->used++; + freeslot->key = key; + freeslot->hash = hash; + return 0; + + found_unused: Py_INCREF(key); so->fill++; so->used++; entry->key = key; entry->hash = hash; - return 0; - - found_null: - Py_INCREF(key); - if (freeslot == NULL) { - /* UNUSED */ - so->fill++; - } else { - /* DUMMY */ - entry = freeslot; - } - so->used++; - entry->key = key; - entry->hash = hash; - return 0; + if ((size_t)so->fill*3 < mask*2) + return 0; + return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); found_active: return 0; @@ -366,28 +365,15 @@ return 0; } -/* CAUTION: set_add_key/entry() must guarantee it won't resize the table */ - static int set_add_entry(PySetObject *so, setentry *entry) { - Py_ssize_t n_used; - PyObject *key = entry->key; - Py_hash_t hash = entry->hash; - - assert(so->fill <= so->mask); /* at least one empty slot */ - n_used = so->used; - if (set_insert_key(so, key, hash)) - return -1; - if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) - return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + return set_insert_key(so, entry->key, entry->hash); } static int set_add_key(PySetObject *so, PyObject *key) { - setentry entry; Py_hash_t hash; if (!PyUnicode_CheckExact(key) || @@ -396,9 +382,7 @@ if (hash == -1) return -1; } - entry.key = key; - entry.hash = hash; - return set_add_entry(so, &entry); + return set_insert_key(so, key, hash); } #define DISCARD_NOTFOUND 0 @@ -631,7 +615,7 @@ * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. */ - if ((so->fill + other->used)*3 >= (so->mask+1)*2) { + if ((so->fill + other->used)*3 >= so->mask*2) { if (set_table_resize(so, (so->used + other->used)*2) != 0) return -1; } @@ -979,16 +963,12 @@ */ if (dictsize == -1) return -1; - if ((so->fill + dictsize)*3 >= (so->mask+1)*2) { + if ((so->fill + dictsize)*3 >= so->mask*2) { if (set_table_resize(so, (so->used + dictsize)*2) != 0) return -1; } while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - setentry an_entry; - - an_entry.hash = hash; - an_entry.key = key; - if (set_add_entry(so, &an_entry)) + if (set_insert_key(so, key, hash)) return -1; } return 0; @@ -1583,17 +1563,16 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { - setentry entrycopy; + PyObject *key = entry->key; + Py_hash_t hash = entry->hash; int rv; - entrycopy.hash = entry->hash; - entrycopy.key = entry->key; - rv = _PyDict_Contains(other, entry->key, entry->hash); + rv = _PyDict_Contains(other, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (!rv) { - if (set_add_entry((PySetObject *)result, &entrycopy)) { + if (set_insert_key((PySetObject *)result, key, hash)) { Py_DECREF(result); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 03:31:15 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 01:31:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Call_set=5Flookkey=28=29_d?= =?utf-8?q?irectly_to_avoid_unnecessary_memory_spills_and_reloads=2E?= Message-ID: <20150704013115.17013.25590@psf.io> https://hg.python.org/cpython/rev/fa3ed4e75ccd changeset: 96789:fa3ed4e75ccd user: Raymond Hettinger date: Fri Jul 03 18:31:09 2015 -0700 summary: Call set_lookkey() directly to avoid unnecessary memory spills and reloads. files: Objects/setobject.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -678,7 +678,7 @@ static int set_contains_key(PySetObject *so, PyObject *key) { - setentry entry; + setentry *entry; Py_hash_t hash; if (!PyUnicode_CheckExact(key) || @@ -687,9 +687,10 @@ if (hash == -1) return -1; } - entry.key = key; - entry.hash = hash; - return set_contains_entry(so, &entry); + entry = set_lookkey(so, key, hash); + if (entry == NULL) + return -1; + return entry->key != NULL; } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 05:00:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 03:00:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_factoring=3A__move_r?= =?utf-8?q?edundant_resize_scaling_logic_into_the_resize_function=2E?= Message-ID: <20150704030007.13199.52503@psf.io> https://hg.python.org/cpython/rev/596ca185e3dc changeset: 96790:596ca185e3dc user: Raymond Hettinger date: Fri Jul 03 20:00:03 2015 -0700 summary: Minor factoring: move redundant resize scaling logic into the resize function. files: Objects/setobject.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -226,7 +226,7 @@ entry->hash = hash; if ((size_t)so->fill*3 < mask*2) return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + return set_table_resize(so, so->used); found_active: return 0; @@ -290,6 +290,7 @@ setentry small_copy[PySet_MINSIZE]; assert(minused >= 0); + minused = (minused > 50000) ? minused * 2 : minused * 4; /* Find the smallest table size > minused. */ /* XXX speed-up with intrinsics */ @@ -616,7 +617,7 @@ * that there will be no (or few) overlapping keys. */ if ((so->fill + other->used)*3 >= so->mask*2) { - if (set_table_resize(so, (so->used + other->used)*2) != 0) + if (set_table_resize(so, so->used + other->used) != 0) return -1; } so_entry = so->table; @@ -965,7 +966,7 @@ if (dictsize == -1) return -1; if ((so->fill + dictsize)*3 >= so->mask*2) { - if (set_table_resize(so, (so->used + dictsize)*2) != 0) + if (set_table_resize(so, so->used + dictsize) != 0) return -1; } while (_PyDict_Next(other, &pos, &key, &value, &hash)) { @@ -1508,7 +1509,7 @@ /* If more than 1/5 are dummies, then resize them away. */ if ((so->fill - so->used) * 5 < so->mask) return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + return set_table_resize(so, so->used); } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:37:22 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 06:37:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_nit=3A__Make_the_sty?= =?utf-8?q?le_of_checking_error_return_values_more_consistent=2E?= Message-ID: <20150704063722.87143.99275@psf.io> https://hg.python.org/cpython/rev/6c58b5b82505 changeset: 96791:6c58b5b82505 user: Raymond Hettinger date: Fri Jul 03 23:37:16 2015 -0700 summary: Minor nit: Make the style of checking error return values more consistent. files: Objects/setobject.c | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1270,7 +1270,7 @@ while (set_next((PySetObject *)other, &pos, &entry)) { int rv = set_contains_entry(so, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(result); return NULL; } @@ -1304,7 +1304,7 @@ entry.hash = hash; entry.key = key; rv = set_contains_entry(so, &entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); @@ -1431,7 +1431,7 @@ } while (set_next((PySetObject *)other, &pos, &entry)) { int rv = set_contains_entry(so, entry); - if (rv == -1) + if (rv < 0) return NULL; if (rv) Py_RETURN_FALSE; @@ -1486,7 +1486,7 @@ Py_ssize_t pos = 0; while (set_next((PySetObject *)other, &pos, &entry)) - if (set_discard_entry(so, entry) == -1) + if (set_discard_entry(so, entry) < 0) return -1; } else { PyObject *key, *it; @@ -1495,7 +1495,7 @@ return -1; while ((key = PyIter_Next(it)) != NULL) { - if (set_discard_key(so, key) == -1) { + if (set_discard_key(so, key) < 0) { Py_DECREF(it); Py_DECREF(key); return -1; @@ -1536,7 +1536,7 @@ result = set_copy(so); if (result == NULL) return NULL; - if (set_difference_update_internal((PySetObject *) result, other) != -1) + if (set_difference_update_internal((PySetObject *) result, other) == 0) return result; Py_DECREF(result); return NULL; @@ -1586,7 +1586,7 @@ /* Iterate over so, checking for common elements in other. */ while (set_next(so, &pos, &entry)) { int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(result); return NULL; } @@ -1670,7 +1670,7 @@ an_entry.key = key; rv = set_discard_entry(so, &an_entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(key); return NULL; } @@ -1696,7 +1696,7 @@ while (set_next(otherset, &pos, &entry)) { int rv = set_discard_entry(so, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(otherset); return NULL; } @@ -1778,7 +1778,7 @@ while (set_next(so, &pos, &entry)) { int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) + if (rv < 0) return NULL; if (!rv) Py_RETURN_FALSE; @@ -1869,7 +1869,7 @@ int rv; rv = set_contains_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return -1; PyErr_Clear(); @@ -1888,7 +1888,7 @@ long result; result = set_contains(so, key); - if (result == -1) + if (result < 0) return NULL; return PyBool_FromLong(result); } @@ -1902,7 +1902,7 @@ int rv; rv = set_discard_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; PyErr_Clear(); @@ -1911,7 +1911,7 @@ return NULL; rv = set_discard_key(so, tmpkey); Py_DECREF(tmpkey); - if (rv == -1) + if (rv < 0) return NULL; } @@ -1934,7 +1934,7 @@ int rv; rv = set_discard_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; PyErr_Clear(); @@ -1943,7 +1943,7 @@ return NULL; rv = set_discard_key(so, tmpkey); Py_DECREF(tmpkey); - if (rv == -1) + if (rv < 0) return NULL; } Py_RETURN_NONE; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:47:38 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:47:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NDMy?= =?utf-8?q?=3A_Update_OS_X_10=2E5+_installer_builds_to_use_OpenSSL_1=2E0?= =?utf-8?q?=2E2c=2E?= Message-ID: <20150704064738.17013.93329@psf.io> https://hg.python.org/cpython/rev/4b52fce3753d changeset: 96793:4b52fce3753d branch: 3.4 parent: 96783:6fd63f0a0026 user: Ned Deily date: Fri Jul 03 23:35:00 2015 -0700 summary: Issue #24432: Update OS X 10.5+ installer builds to use OpenSSL 1.0.2c. files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 6 ++---- 3 files changed, 6 insertions(+), 8 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -340,10 +340,8 @@ - Issue #23445: pydebug builds now use "gcc -Og" where possible, to make the resulting executable faster. -- Issue #23686: Update OS X 10.5 installer and Windows builds to use - OpenSSL 1.0.2a. - -- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. C API ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:47:38 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:47:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NDMy?= =?utf-8?q?=3A_Update_OS_X_10=2E5+_installer_builds_to_use_OpenSSL_1=2E0?= =?utf-8?q?=2E2c=2E?= Message-ID: <20150704064738.97844.13472@psf.io> https://hg.python.org/cpython/rev/695bbbaf2478 changeset: 96792:695bbbaf2478 branch: 2.7 parent: 96787:25985b0c4dbf user: Ned Deily date: Fri Jul 03 23:32:44 2015 -0700 summary: Issue #24432: Update OS X 10.5+ installer builds to use OpenSSL 1.0.2c. files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 4 ++-- 3 files changed, 6 insertions(+), 6 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -95,8 +95,8 @@ Build ----- -- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. - +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. IDLE ---- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:47:43 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:47:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324432=3A_Update_OS_X_10=2E5+_installer_builds_to_use_?= =?utf-8?b?T3BlblNTTCAxLjAuMmMu?= Message-ID: <20150704064743.63903.26828@psf.io> https://hg.python.org/cpython/rev/bbf4e35ed69e changeset: 96794:bbf4e35ed69e branch: 3.5 parent: 96784:ebc8559b2e57 parent: 96793:4b52fce3753d user: Ned Deily date: Fri Jul 03 23:43:22 2015 -0700 summary: Issue #24432: Update OS X 10.5+ installer builds to use OpenSSL 1.0.2c. files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 3 ++- 3 files changed, 6 insertions(+), 5 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,7 +103,8 @@ Build ----- -- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. What's New in Python 3.5.0 beta 2? -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:47:43 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:47:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324432=3A_merge_from_3=2E5?= Message-ID: <20150704064743.15337.93840@psf.io> https://hg.python.org/cpython/rev/fbb9ac8aebfd changeset: 96795:fbb9ac8aebfd parent: 96791:6c58b5b82505 parent: 96794:bbf4e35ed69e user: Ned Deily date: Fri Jul 03 23:47:02 2015 -0700 summary: Issue #24432: merge from 3.5 files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 3 ++- 3 files changed, 6 insertions(+), 5 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -119,7 +119,8 @@ Build ----- -- Issue #24432: Update Windows builds to use OpenSSL 1.0.2c. +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. What's New in Python 3.5.0 beta 2? -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:55:59 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:55:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Updates_to_the_OS_X_installer_=28merge_from_3=2E5=29?= Message-ID: <20150704065559.15337.80058@psf.io> https://hg.python.org/cpython/rev/1d7496eff907 changeset: 96797:1d7496eff907 parent: 96795:fbb9ac8aebfd parent: 96796:212a436483d6 user: Ned Deily date: Fri Jul 03 23:55:23 2015 -0700 summary: Updates to the OS X installer (merge from 3.5) files: Mac/BuildScript/resources/ReadMe.rtf | 69 +++++++++- Mac/BuildScript/scripts/postflight.ensurepip | 10 +- Mac/BuildScript/scripts/postflight.framework | 16 +- 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -24,7 +24,7 @@ \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL \i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. -\b \ul \ulc0 \ +\b \ul \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ @@ -36,6 +36,71 @@ \i0 for this version of Python and of Mac OS X.\ \b \ul \ +Certificate verification and OpenSSL\ + +\b0 \ulnone \ +Python 3.5 includes a number of network security enhancements that were released in Python 3.4.3 and Python 2.7.10. {\field{\*\fldinst{HYPERLINK "https://www.python.org/dev/peps/pep-0476/"}}{\fldrslt PEP 476}} changes several standard library modules, like +\i httplib +\i0 , +\i urllib +\i0 , and +\i xmlrpclib +\i0 , to by default verify certificates presented by servers over secure (TLS) connections. The verification is performed by the OpenSSL libraries that Python is linked to. Prior to 3.4.3, both python.org installers dynamically linked with Apple-supplied OpenSSL libraries shipped with OS X. OS X provides a multiple level security framework that stores trust certificates in system and user keychains managed by the +\i Keychain Access +\i0 application and the +\i security +\i0 command line utility.\ +\ +For OS X 10.5, Apple provides +\i OpenSSL 0.9.7 +\i0 libraries. This version of Apple's OpenSSL +\b does not +\b0 use the certificates from the system security framework, even when used on newer versions of OS X. Instead it consults a traditional OpenSSL concatenated certificate file ( +\i cafile +\i0 ) or certificate directory ( +\i capath +\i0 ), located in +\f1 /System/Library/OpenSSL +\f0 . These directories are typically empty and not managed by OS X; you must manage them yourself or supply your own SSL contexts. OpenSSL 0.9.7 is obsolete by current security standards, lacking a number of important features found in later versions. Among the problems this causes is the inability to verify higher-security certificates now used by python.org services, including +\i t{\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi"}}{\fldrslt he Python Package Index, PyPI}} +\i0 . To solve this problem, the +\i 10.5+ 32-bit-only python.org variant +\i0 is linked with a private copy of +\i OpenSSL 1.0.2 +\i0 ; it consults the same default certificate directory, +\f1 /System/Library/OpenSSL +\f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt +\f1 py2app}}, you may now need to bundle CA certificates in them or otherwise supply non-default SSL contexts.\ +\ +For OS X 10.6+, Apple also provides +\i OpenSSL +\i0 +\i 0.9.8 libraries +\i0 . Apple's 0.9.8 version includes an important additional feature: if a certificate cannot be verified using the manually administered certificates in +\f1 /System/Library/OpenSSL +\f0 , the certificates managed by the system security framework In the user and system keychains are also consulted (using Apple private APIs). For this reason, the +\i 64-bit/32-bit 10.6+ python.org variant +\i0 continues to be dynamically linked with Apple's OpenSSL 0.9.8 since it was felt that the loss of the system-provided certificates and management tools outweighs the additional security features provided by newer versions of OpenSSL. This will likely change in future releases of the python.org installers as Apple has deprecated use of the system-supplied OpenSSL libraries. If you do need features from newer versions of OpenSSL, there are third-party OpenSSL wrapper packages available through +\i PyPI +\i0 .\ +\ +The bundled +\f1 pip +\f0 included with the Python 3.5 installers has its own default certificate store for verifying download connections.\ +\ + +\b \ul Other changes\ + +\b0 \ulnone \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural +\cf0 For other changes in this release, see the +\i What's new +\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its +\i Release Notes +\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural + +\b \cf0 \ul \ Python 3 and Python 2 Co-existence\ \b0 \ulnone \ diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -10,15 +10,15 @@ umask 022 -"${FWK}/bin/python${PYVER}" -m ensurepip --upgrade +"${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade -"${FWK}/bin/python${PYVER}" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python${PYVER}" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework --- a/Mac/BuildScript/scripts/postflight.framework +++ b/Mac/BuildScript/scripts/postflight.framework @@ -6,23 +6,23 @@ PYVER="@PYVER@" FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 08:55:59 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 06:55:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Updates_to_the?= =?utf-8?q?_OS_X_installer_for_3=2E5=2E0b3=3A?= Message-ID: <20150704065559.14764.71239@psf.io> https://hg.python.org/cpython/rev/212a436483d6 changeset: 96796:212a436483d6 branch: 3.5 parent: 96794:bbf4e35ed69e user: Ned Deily date: Fri Jul 03 23:53:51 2015 -0700 summary: Updates to the OS X installer for 3.5.0b3: - update installer ReadMe file - suppress installer per-file byte-compilation messages to system log - speed up installer byte-compilation - isolate ensurepip install from user site-packages files: Mac/BuildScript/resources/ReadMe.rtf | 69 +++++++++- Mac/BuildScript/scripts/postflight.ensurepip | 10 +- Mac/BuildScript/scripts/postflight.framework | 16 +- 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -24,7 +24,7 @@ \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL \i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. -\b \ul \ulc0 \ +\b \ul \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ @@ -36,6 +36,71 @@ \i0 for this version of Python and of Mac OS X.\ \b \ul \ +Certificate verification and OpenSSL\ + +\b0 \ulnone \ +Python 3.5 includes a number of network security enhancements that were released in Python 3.4.3 and Python 2.7.10. {\field{\*\fldinst{HYPERLINK "https://www.python.org/dev/peps/pep-0476/"}}{\fldrslt PEP 476}} changes several standard library modules, like +\i httplib +\i0 , +\i urllib +\i0 , and +\i xmlrpclib +\i0 , to by default verify certificates presented by servers over secure (TLS) connections. The verification is performed by the OpenSSL libraries that Python is linked to. Prior to 3.4.3, both python.org installers dynamically linked with Apple-supplied OpenSSL libraries shipped with OS X. OS X provides a multiple level security framework that stores trust certificates in system and user keychains managed by the +\i Keychain Access +\i0 application and the +\i security +\i0 command line utility.\ +\ +For OS X 10.5, Apple provides +\i OpenSSL 0.9.7 +\i0 libraries. This version of Apple's OpenSSL +\b does not +\b0 use the certificates from the system security framework, even when used on newer versions of OS X. Instead it consults a traditional OpenSSL concatenated certificate file ( +\i cafile +\i0 ) or certificate directory ( +\i capath +\i0 ), located in +\f1 /System/Library/OpenSSL +\f0 . These directories are typically empty and not managed by OS X; you must manage them yourself or supply your own SSL contexts. OpenSSL 0.9.7 is obsolete by current security standards, lacking a number of important features found in later versions. Among the problems this causes is the inability to verify higher-security certificates now used by python.org services, including +\i t{\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi"}}{\fldrslt he Python Package Index, PyPI}} +\i0 . To solve this problem, the +\i 10.5+ 32-bit-only python.org variant +\i0 is linked with a private copy of +\i OpenSSL 1.0.2 +\i0 ; it consults the same default certificate directory, +\f1 /System/Library/OpenSSL +\f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt +\f1 py2app}}, you may now need to bundle CA certificates in them or otherwise supply non-default SSL contexts.\ +\ +For OS X 10.6+, Apple also provides +\i OpenSSL +\i0 +\i 0.9.8 libraries +\i0 . Apple's 0.9.8 version includes an important additional feature: if a certificate cannot be verified using the manually administered certificates in +\f1 /System/Library/OpenSSL +\f0 , the certificates managed by the system security framework In the user and system keychains are also consulted (using Apple private APIs). For this reason, the +\i 64-bit/32-bit 10.6+ python.org variant +\i0 continues to be dynamically linked with Apple's OpenSSL 0.9.8 since it was felt that the loss of the system-provided certificates and management tools outweighs the additional security features provided by newer versions of OpenSSL. This will likely change in future releases of the python.org installers as Apple has deprecated use of the system-supplied OpenSSL libraries. If you do need features from newer versions of OpenSSL, there are third-party OpenSSL wrapper packages available through +\i PyPI +\i0 .\ +\ +The bundled +\f1 pip +\f0 included with the Python 3.5 installers has its own default certificate store for verifying download connections.\ +\ + +\b \ul Other changes\ + +\b0 \ulnone \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural +\cf0 For other changes in this release, see the +\i What's new +\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its +\i Release Notes +\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural + +\b \cf0 \ul \ Python 3 and Python 2 Co-existence\ \b0 \ulnone \ diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -10,15 +10,15 @@ umask 022 -"${FWK}/bin/python${PYVER}" -m ensurepip --upgrade +"${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade -"${FWK}/bin/python${PYVER}" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python${PYVER}" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework --- a/Mac/BuildScript/scripts/postflight.framework +++ b/Mac/BuildScript/scripts/postflight.framework @@ -6,23 +6,23 @@ PYVER="@PYVER@" FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Jul 4 10:45:31 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 04 Jul 2015 08:45:31 +0000 Subject: [Python-checkins] Daily reference leaks (596ca185e3dc): sum=4 Message-ID: <20150704084531.23363.11129@psf.io> results for 596ca185e3dc on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogjZemfX', '--timeout', '7200'] From python-checkins at python.org Sat Jul 4 17:46:36 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 15:46:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_cleanup=2E?= Message-ID: <20150704154636.113878.27734@psf.io> https://hg.python.org/cpython/rev/7ed4503b73a7 changeset: 96798:7ed4503b73a7 user: Raymond Hettinger date: Sat Jul 04 08:46:31 2015 -0700 summary: Minor cleanup. files: Objects/setobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -963,7 +963,7 @@ * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. */ - if (dictsize == -1) + if (dictsize < 0) return -1; if ((so->fill + dictsize)*3 >= so->mask*2) { if (set_table_resize(so, so->used + dictsize) != 0) @@ -1457,7 +1457,7 @@ entry.key = key; rv = set_contains_entry(so, &entry); Py_DECREF(key); - if (rv == -1) { + if (rv < 0) { Py_DECREF(it); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 20:28:39 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 18:28:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Make_sure_the_dummy_percen?= =?utf-8?q?tage_calculation_won=27t_overflow=2E?= Message-ID: <20150704182839.15859.17933@psf.io> https://hg.python.org/cpython/rev/9ac2169463b7 changeset: 96799:9ac2169463b7 user: Raymond Hettinger date: Sat Jul 04 11:28:35 2015 -0700 summary: Make sure the dummy percentage calculation won't overflow. files: Objects/setobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1506,8 +1506,8 @@ if (PyErr_Occurred()) return -1; } - /* If more than 1/5 are dummies, then resize them away. */ - if ((so->fill - so->used) * 5 < so->mask) + /* If more than 1/4th are dummies, then resize them away. */ + if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4) return 0; return set_table_resize(so, so->used); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 20:49:35 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 04 Jul 2015 18:49:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Ignore_user_en?= =?utf-8?q?vironment/site-packages_for_ensurepip_and_compile=5Fall?= Message-ID: <20150704184935.64447.3731@psf.io> https://hg.python.org/cpython/rev/ff1b9f0cf9ee changeset: 96800:ff1b9f0cf9ee branch: 3.5 parent: 96796:212a436483d6 user: Steve Dower date: Sat Jul 04 11:48:37 2015 -0700 summary: Ignore user environment/site-packages for ensurepip and compile_all Remove build condition to prevent old strings hanging around Add -h option to build.bat files: Tools/msi/build.bat | 16 ++++++++- Tools/msi/bundle/packagegroups/postinstall.wxs | 2 +- Tools/msi/msi.targets | 2 +- Tools/msi/pip/pip.wxs | 4 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,9 +8,10 @@ set BUILDDOC= :CheckOpts -if '%1'=='-x86' (set BUILDX86=1) && shift && goto CheckOpts -if '%1'=='-x64' (set BUILDX64=1) && shift && goto CheckOpts -if '%1'=='--doc' (set BUILDDOC=1) && shift && goto CheckOpts +if "%1" EQU "-h" goto Help +if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -44,3 +45,12 @@ msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 if errorlevel 1 goto :eof ) + +exit /B 0 + +:Help +echo build.bat [-x86] [-x64] [--doc] [-h] +echo. +echo -x86 Build x86 installers +echo -x64 Build x64 installers +echo --doc Build CHM documentation diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -36,7 +36,7 @@ - + - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) diff --git a/Tools/msi/pip/pip.wxs b/Tools/msi/pip/pip.wxs --- a/Tools/msi/pip/pip.wxs +++ b/Tools/msi/pip/pip.wxs @@ -27,8 +27,8 @@ - - + + (&DefaultFeature=3) AND NOT (!DefaultFeature=3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 20:49:35 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 04 Jul 2015 18:49:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Ignore_user_environment/site-packages_for_ensurepip_and_?= =?utf-8?q?compile=5Fall?= Message-ID: <20150704184935.4356.54504@psf.io> https://hg.python.org/cpython/rev/aadf3f60a9ef changeset: 96801:aadf3f60a9ef parent: 96799:9ac2169463b7 parent: 96800:ff1b9f0cf9ee user: Steve Dower date: Sat Jul 04 11:48:59 2015 -0700 summary: Ignore user environment/site-packages for ensurepip and compile_all Remove build condition to prevent old strings hanging around Add -h option to build.bat files: Tools/msi/build.bat | 16 ++++++++- Tools/msi/bundle/packagegroups/postinstall.wxs | 2 +- Tools/msi/msi.targets | 2 +- Tools/msi/pip/pip.wxs | 4 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,9 +8,10 @@ set BUILDDOC= :CheckOpts -if '%1'=='-x86' (set BUILDX86=1) && shift && goto CheckOpts -if '%1'=='-x64' (set BUILDX64=1) && shift && goto CheckOpts -if '%1'=='--doc' (set BUILDDOC=1) && shift && goto CheckOpts +if "%1" EQU "-h" goto Help +if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -44,3 +45,12 @@ msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 if errorlevel 1 goto :eof ) + +exit /B 0 + +:Help +echo build.bat [-x86] [-x64] [--doc] [-h] +echo. +echo -x86 Build x86 installers +echo -x64 Build x64 installers +echo --doc Build CHM documentation diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -36,7 +36,7 @@ - + - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) diff --git a/Tools/msi/pip/pip.wxs b/Tools/msi/pip/pip.wxs --- a/Tools/msi/pip/pip.wxs +++ b/Tools/msi/pip/pip.wxs @@ -27,8 +27,8 @@ - - + + (&DefaultFeature=3) AND NOT (!DefaultFeature=3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 21:46:29 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 04 Jul 2015 19:46:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge=3A_=2324584=3A_replace_dead_link_with_pointer_to_archive?= =?utf-8?b?Lm9yZy4=?= Message-ID: <20150704194629.107534.24084@psf.io> https://hg.python.org/cpython/rev/51e05ee9848a changeset: 96803:51e05ee9848a branch: 3.5 parent: 96800:ff1b9f0cf9ee parent: 96802:050a941f69fb user: R David Murray date: Sat Jul 04 15:45:41 2015 -0400 summary: Merge: #24584: replace dead link with pointer to archive.org. files: Doc/library/unittest.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 21:46:29 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 04 Jul 2015 19:46:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzI0NTg0OiByZXBs?= =?utf-8?q?ace_dead_link_with_pointer_to_archive=2Eorg=2E?= Message-ID: <20150704194629.68844.96938@psf.io> https://hg.python.org/cpython/rev/050a941f69fb changeset: 96802:050a941f69fb branch: 3.4 parent: 96793:4b52fce3753d user: R David Murray date: Sat Jul 04 15:44:14 2015 -0400 summary: #24584: replace dead link with pointer to archive.org. files: Doc/library/unittest.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 21:46:29 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 04 Jul 2015 19:46:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2324584=3A_replace_dead_link_with_pointer_to_a?= =?utf-8?q?rchive=2Eorg=2E?= Message-ID: <20150704194629.130183.14298@psf.io> https://hg.python.org/cpython/rev/631ef17fc772 changeset: 96804:631ef17fc772 parent: 96801:aadf3f60a9ef parent: 96803:51e05ee9848a user: R David Murray date: Sat Jul 04 15:46:14 2015 -0400 summary: Merge: #24584: replace dead link with pointer to archive.org. files: Doc/library/unittest.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 4 21:50:38 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 04 Jul 2015 19:50:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzI0NTQ4OiByZXBs?= =?utf-8?q?ace_dead_link_with_pointer_to_archive=2Eorg=2E?= Message-ID: <20150704195038.102267.6742@psf.io> https://hg.python.org/cpython/rev/5f279db087e7 changeset: 96805:5f279db087e7 branch: 2.7 parent: 96792:695bbbaf2478 user: R David Murray date: Sat Jul 04 15:50:30 2015 -0400 summary: #24548: replace dead link with pointer to archive.org. files: Doc/library/unittest.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -83,7 +83,7 @@ discovery. unittest2 allows you to use these features with earlier versions of Python. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 00:07:05 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 22:07:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324330=3A_merge_from_3=2E5?= Message-ID: <20150704220704.19983.95993@psf.io> https://hg.python.org/cpython/rev/055ddc0e713b changeset: 96809:055ddc0e713b parent: 96804:631ef17fc772 parent: 96808:2dfdbbe0701b user: Ned Deily date: Sat Jul 04 15:06:43 2015 -0700 summary: Issue #24330: merge from 3.5 files: Doc/library/idle.rst | 3 ++- Lib/idlelib/help.txt | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 00:07:04 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 22:07:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MzMw?= =?utf-8?q?=3A_Update_IDLE_doc_and_help_to_note_=22Configure_IDLE=22_diffe?= =?utf-8?q?rence?= Message-ID: <20150704220704.8473.28121@psf.io> https://hg.python.org/cpython/rev/64b42ec6ef42 changeset: 96806:64b42ec6ef42 branch: 2.7 user: Ned Deily date: Sat Jul 04 15:04:42 2015 -0700 summary: Issue #24330: Update IDLE doc and help to note "Configure IDLE" difference on OS X. Original patch by Andr? Freitas. files: Doc/library/idle.rst | 3 ++- Lib/idlelib/help.txt | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -90,10 +90,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and Additional Help - Sources can be specified. - - On OS X this menu is not present, use - menu 'IDLE -> Preferences...' instead. + Sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context -- Open a pane at the top of the edit window which shows the block context of the section of code -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 00:07:04 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 22:07:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324330=3A_merge_from_3=2E4?= Message-ID: <20150704220704.1848.51980@psf.io> https://hg.python.org/cpython/rev/2dfdbbe0701b changeset: 96808:2dfdbbe0701b branch: 3.5 parent: 96803:51e05ee9848a parent: 96807:b9460ee09228 user: Ned Deily date: Sat Jul 04 15:06:21 2015 -0700 summary: Issue #24330: merge from 3.4 files: Doc/library/idle.rst | 3 ++- Lib/idlelib/help.txt | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 00:07:04 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 04 Jul 2015 22:07:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MzMw?= =?utf-8?q?=3A_Update_IDLE_doc_and_help_to_note_=22Configure_IDLE=22_diffe?= =?utf-8?q?rence?= Message-ID: <20150704220704.113878.76254@psf.io> https://hg.python.org/cpython/rev/b9460ee09228 changeset: 96807:b9460ee09228 branch: 3.4 parent: 96802:050a941f69fb user: Ned Deily date: Sat Jul 04 15:05:07 2015 -0700 summary: Issue #24330: Update IDLE doc and help to note "Configure IDLE" difference on OS X. Original patch by Andr? Freitas. files: Doc/library/idle.rst | 3 ++- Lib/idlelib/help.txt | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 01:04:50 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 04 Jul 2015 23:04:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Make_the_unicode_equality_?= =?utf-8?q?test_an_external_function_rather_than_in-lining_it=2E?= Message-ID: <20150704230449.9573.83416@psf.io> https://hg.python.org/cpython/rev/7900983373f0 changeset: 96810:7900983373f0 user: Raymond Hettinger date: Sat Jul 04 16:04:44 2015 -0700 summary: Make the unicode equality test an external function rather than in-lining it. The real benefit of the unicode specialized function comes from bypassing the overhead of PyObject_RichCompareBool() and not from being in-lined (especially since there was almost no shared data between the caller and callee). Also, the in-lining was having a negative effect on code generation for the callee. files: Include/unicodeobject.h | 4 ++++ Objects/setobject.c | 9 ++++----- Objects/unicodeobject.c | 7 +++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -2261,6 +2261,10 @@ /* Clear all static strings. */ PyAPI_FUNC(void) _PyUnicode_ClearStaticStrings(void); +/* Fast equality check when the inputs are known to be exact unicode types + and where the hash values are equal (i.e. a very probable match) */ +PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *); + #ifdef __cplusplus } #endif diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -29,7 +29,6 @@ #include "Python.h" #include "structmember.h" -#include "stringlib/eq.h" /* Object used as dummy key to fill deleted entries */ static PyObject _dummy_struct; @@ -74,7 +73,7 @@ return entry; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) return entry; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -100,7 +99,7 @@ return entry; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) return entry; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -155,7 +154,7 @@ goto found_active; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) goto found_active; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -183,7 +182,7 @@ goto found_active; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) goto found_active; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -42,6 +42,7 @@ #include "Python.h" #include "ucnhash.h" #include "bytes_methods.h" +#include "stringlib/eq.h" #ifdef MS_WINDOWS #include @@ -10887,6 +10888,12 @@ } int +_PyUnicode_EQ(PyObject *aa, PyObject *bb) +{ + return unicode_eq(aa, bb); +} + +int PyUnicode_Contains(PyObject *container, PyObject *element) { PyObject *str, *sub; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:13 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQ0MDcp?= Message-ID: <20150705035413.19423.16654@psf.io> https://hg.python.org/cpython/rev/88814ddd5e9e changeset: 96814:88814ddd5e9e parent: 96780:a14f6a70d013 parent: 96813:6a7ee97cb0b1 user: Benjamin Peterson date: Sat Jul 04 19:59:50 2015 -0500 summary: merge 3.5 (#24407) files: Lib/test/test_dict.py | 14 ++++++++++++++ Misc/NEWS | 2 ++ Objects/dictobject.c | 26 +++++++++++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -937,6 +937,20 @@ d.popitem() self.check_reentrant_insertion(mutate) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return 0 + + def __eq__(self, o): + other.clear() + return False + + l = [(i,0) for i in range(1, 1337)] + other = dict(l) + other[X()] = 0 + d = {X(): 0, 1: 1} + self.assertRaises(RuntimeError, d.update, other) from test import mapping_tests diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,8 @@ - Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. +- Issue #24407: Fix crash when dict is mutated while being updated. + Library ------- diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2039,20 +2039,32 @@ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { - PyObject *value; + PyObject *key, *value; + Py_hash_t hash; entry = &other->ma_keys->dk_entries[i]; + key = entry->me_key; + hash = entry->me_hash; if (other->ma_values) value = other->ma_values[i]; else value = entry->me_value; - if (value != NULL && - (override || - PyDict_GetItem(a, entry->me_key) == NULL)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) + if (value != NULL) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override || PyDict_GetItem(a, key) == NULL) + err = insertdict(mp, key, hash, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) return -1; + + if (n != DK_SIZE(other->ma_keys)) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; + } } } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:13 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3_=28=2324407=29?= Message-ID: <20150705035413.105249.58401@psf.io> https://hg.python.org/cpython/rev/75da5acbfbe4 changeset: 96812:75da5acbfbe4 branch: 3.4 parent: 96769:34460219c0e0 parent: 96811:37fed8b02f00 user: Benjamin Peterson date: Sat Jul 04 19:58:11 2015 -0500 summary: merge 3.3 (#24407) files: Lib/test/test_dict.py | 14 ++++++++++++++ Misc/NEWS | 2 ++ Objects/dictobject.c | 26 +++++++++++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -937,6 +937,20 @@ d.popitem() self.check_reentrant_insertion(mutate) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return 0 + + def __eq__(self, o): + other.clear() + return False + + l = [(i,0) for i in range(1, 1337)] + other = dict(l) + other[X()] = 0 + d = {X(): 0, 1: 1} + self.assertRaises(RuntimeError, d.update, other) from test import mapping_tests diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,8 @@ - Issue #23757: PySequence_Tuple() incorrectly called the concrete list API when the data was a list subclass. +- Issue #24407: Fix crash when dict is mutated while being updated. + - Issue #24096: Make warnings.warn_explicit more robust against mutation of the warnings.filters list. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1973,20 +1973,32 @@ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { - PyObject *value; + PyObject *key, *value; + Py_hash_t hash; entry = &other->ma_keys->dk_entries[i]; + key = entry->me_key; + hash = entry->me_hash; if (other->ma_values) value = other->ma_values[i]; else value = entry->me_value; - if (value != NULL && - (override || - PyDict_GetItem(a, entry->me_key) == NULL)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) + if (value != NULL) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override || PyDict_GetItem(a, key) == NULL) + err = insertdict(mp, key, hash, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) return -1; + + if (n != DK_SIZE(other->ma_keys)) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; + } } } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:13 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4_=28=2324407=29?= Message-ID: <20150705035413.27420.84815@psf.io> https://hg.python.org/cpython/rev/6a7ee97cb0b1 changeset: 96813:6a7ee97cb0b1 branch: 3.5 parent: 96779:cb1aafc9ad7e parent: 96812:75da5acbfbe4 user: Benjamin Peterson date: Sat Jul 04 19:59:24 2015 -0500 summary: merge 3.4 (#24407) files: Lib/test/test_dict.py | 14 ++++++++++++++ Misc/NEWS | 2 ++ Objects/dictobject.c | 26 +++++++++++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -937,6 +937,20 @@ d.popitem() self.check_reentrant_insertion(mutate) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return 0 + + def __eq__(self, o): + other.clear() + return False + + l = [(i,0) for i in range(1, 1337)] + other = dict(l) + other[X()] = 0 + d = {X(): 0, 1: 1} + self.assertRaises(RuntimeError, d.update, other) from test import mapping_tests diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ - Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. +- Issue #24407: Fix crash when dict is mutated while being updated. + Library ------- diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2039,20 +2039,32 @@ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { - PyObject *value; + PyObject *key, *value; + Py_hash_t hash; entry = &other->ma_keys->dk_entries[i]; + key = entry->me_key; + hash = entry->me_hash; if (other->ma_values) value = other->ma_values[i]; else value = entry->me_value; - if (value != NULL && - (override || - PyDict_GetItem(a, entry->me_key) == NULL)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) + if (value != NULL) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override || PyDict_GetItem(a, key) == NULL) + err = insertdict(mp, key, hash, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) return -1; + + if (n != DK_SIZE(other->ma_keys)) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; + } } } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:13 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_protect_agains?= =?utf-8?q?t_mutation_of_the_dict_during_insertion_=28closes_=2324407=29?= Message-ID: <20150705035413.22962.35239@psf.io> https://hg.python.org/cpython/rev/37fed8b02f00 changeset: 96811:37fed8b02f00 branch: 3.3 parent: 96688:8daf7b74462a user: Benjamin Peterson date: Sat Jul 04 19:55:16 2015 -0500 summary: protect against mutation of the dict during insertion (closes #24407) files: Lib/test/test_dict.py | 15 +++++++++++++++ Misc/NEWS | 2 ++ Objects/dictobject.c | 26 +++++++++++++++++++------- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -906,6 +906,21 @@ f.a = 'a' self.assertEqual(f.__dict__, {1:1, 'a':'a'}) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return 0 + + def __eq__(self, o): + other.clear() + return False + + l = [(i,0) for i in range(1, 1337)] + other = dict(l) + other[X()] = 0 + d = {X(): 0, 1: 1} + self.assertRaises(RuntimeError, d.update, other) + from test import mapping_tests class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24407: Fix crash when dict is mutated while being updated. + - Issue #24096: Make warnings.warn_explicit more robust against mutation of the warnings.filters list. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1941,20 +1941,32 @@ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { - PyObject *value; + PyObject *key, *value; + Py_hash_t hash; entry = &other->ma_keys->dk_entries[i]; + key = entry->me_key; + hash = entry->me_hash; if (other->ma_values) value = other->ma_values[i]; else value = entry->me_value; - if (value != NULL && - (override || - PyDict_GetItem(a, entry->me_key) == NULL)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) + if (value != NULL) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override || PyDict_GetItem(a, key) == NULL) + err = insertdict(mp, key, hash, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) return -1; + + if (n != DK_SIZE(other->ma_keys)) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; + } } } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_merge_heads?= Message-ID: <20150705035414.15972.24288@psf.io> https://hg.python.org/cpython/rev/725131a5f6cf changeset: 96815:725131a5f6cf branch: 3.4 parent: 96812:75da5acbfbe4 parent: 96807:b9460ee09228 user: Benjamin Peterson date: Sat Jul 04 22:52:33 2015 -0500 summary: merge heads files: Doc/library/idle.rst | 3 ++- Doc/library/unittest.rst | 2 +- Lib/idlelib/help.txt | 4 +++- Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 4 ++-- PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.props | 2 +- PCbuild/readme.txt | 2 +- 9 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -342,8 +342,8 @@ - Issue #23445: pydebug builds now use "gcc -Og" where possible, to make the resulting executable faster. -- Issue #23686: Update OS X 10.5 installer and Windows builds to use - OpenSSL 1.0.2a. +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. C API ----- diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-8.6.1.0 tk-8.6.1.0 tix-8.4.3.4 diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -20,7 +20,7 @@ $(externalsDir)\sqlite-3.8.3.1 $(externalsDir)\bzip2-1.0.6 $(externalsDir)\xz-5.0.5 - $(externalsDir)\openssl-1.0.2a + $(externalsDir)\openssl-1.0.2c $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,7 +171,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2a of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150705035414.24661.88841@psf.io> https://hg.python.org/cpython/rev/74f55f8d8982 changeset: 96817:74f55f8d8982 branch: 3.5 parent: 96816:3c5af1b5a64b parent: 96815:725131a5f6cf user: Benjamin Peterson date: Sat Jul 04 22:53:37 2015 -0500 summary: merge 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_merge_heads?= Message-ID: <20150705035414.18857.22655@psf.io> https://hg.python.org/cpython/rev/3c5af1b5a64b changeset: 96816:3c5af1b5a64b branch: 3.5 parent: 96813:6a7ee97cb0b1 parent: 96808:2dfdbbe0701b user: Benjamin Peterson date: Sat Jul 04 22:53:11 2015 -0500 summary: merge heads files: Doc/library/idle.rst | 3 +- Doc/library/unittest.rst | 2 +- Lib/idlelib/help.txt | 4 +- Mac/BuildScript/build-installer.py | 6 +- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Mac/BuildScript/resources/ReadMe.rtf | 69 +++++++++- Mac/BuildScript/scripts/postflight.ensurepip | 10 +- Mac/BuildScript/scripts/postflight.framework | 16 +- Misc/NEWS | 6 + PCbuild/get_externals.bat | 2 +- PCbuild/prepare_ssl.py | 1 + PCbuild/python.props | 2 +- PCbuild/python3dll.vcxproj | 4 +- PCbuild/readme.txt | 2 +- Tools/msi/build.bat | 16 +- Tools/msi/bundle/packagegroups/postinstall.wxs | 2 +- Tools/msi/msi.targets | 2 +- Tools/msi/pip/pip.wxs | 4 +- 18 files changed, 119 insertions(+), 34 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -24,7 +24,7 @@ \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL \i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. -\b \ul \ulc0 \ +\b \ul \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ @@ -36,6 +36,71 @@ \i0 for this version of Python and of Mac OS X.\ \b \ul \ +Certificate verification and OpenSSL\ + +\b0 \ulnone \ +Python 3.5 includes a number of network security enhancements that were released in Python 3.4.3 and Python 2.7.10. {\field{\*\fldinst{HYPERLINK "https://www.python.org/dev/peps/pep-0476/"}}{\fldrslt PEP 476}} changes several standard library modules, like +\i httplib +\i0 , +\i urllib +\i0 , and +\i xmlrpclib +\i0 , to by default verify certificates presented by servers over secure (TLS) connections. The verification is performed by the OpenSSL libraries that Python is linked to. Prior to 3.4.3, both python.org installers dynamically linked with Apple-supplied OpenSSL libraries shipped with OS X. OS X provides a multiple level security framework that stores trust certificates in system and user keychains managed by the +\i Keychain Access +\i0 application and the +\i security +\i0 command line utility.\ +\ +For OS X 10.5, Apple provides +\i OpenSSL 0.9.7 +\i0 libraries. This version of Apple's OpenSSL +\b does not +\b0 use the certificates from the system security framework, even when used on newer versions of OS X. Instead it consults a traditional OpenSSL concatenated certificate file ( +\i cafile +\i0 ) or certificate directory ( +\i capath +\i0 ), located in +\f1 /System/Library/OpenSSL +\f0 . These directories are typically empty and not managed by OS X; you must manage them yourself or supply your own SSL contexts. OpenSSL 0.9.7 is obsolete by current security standards, lacking a number of important features found in later versions. Among the problems this causes is the inability to verify higher-security certificates now used by python.org services, including +\i t{\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi"}}{\fldrslt he Python Package Index, PyPI}} +\i0 . To solve this problem, the +\i 10.5+ 32-bit-only python.org variant +\i0 is linked with a private copy of +\i OpenSSL 1.0.2 +\i0 ; it consults the same default certificate directory, +\f1 /System/Library/OpenSSL +\f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt +\f1 py2app}}, you may now need to bundle CA certificates in them or otherwise supply non-default SSL contexts.\ +\ +For OS X 10.6+, Apple also provides +\i OpenSSL +\i0 +\i 0.9.8 libraries +\i0 . Apple's 0.9.8 version includes an important additional feature: if a certificate cannot be verified using the manually administered certificates in +\f1 /System/Library/OpenSSL +\f0 , the certificates managed by the system security framework In the user and system keychains are also consulted (using Apple private APIs). For this reason, the +\i 64-bit/32-bit 10.6+ python.org variant +\i0 continues to be dynamically linked with Apple's OpenSSL 0.9.8 since it was felt that the loss of the system-provided certificates and management tools outweighs the additional security features provided by newer versions of OpenSSL. This will likely change in future releases of the python.org installers as Apple has deprecated use of the system-supplied OpenSSL libraries. If you do need features from newer versions of OpenSSL, there are third-party OpenSSL wrapper packages available through +\i PyPI +\i0 .\ +\ +The bundled +\f1 pip +\f0 included with the Python 3.5 installers has its own default certificate store for verifying download connections.\ +\ + +\b \ul Other changes\ + +\b0 \ulnone \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural +\cf0 For other changes in this release, see the +\i What's new +\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its +\i Release Notes +\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural + +\b \cf0 \ul \ Python 3 and Python 2 Co-existence\ \b0 \ulnone \ diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -10,15 +10,15 @@ umask 022 -"${FWK}/bin/python${PYVER}" -m ensurepip --upgrade +"${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade -"${FWK}/bin/python${PYVER}" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python${PYVER}" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework --- a/Mac/BuildScript/scripts/postflight.framework +++ b/Mac/BuildScript/scripts/postflight.framework @@ -6,23 +6,23 @@ PYVER="@PYVER@" FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -102,6 +102,12 @@ - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. +Build +----- + +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. + What's New in Python 3.5.0 beta 2? ================================== diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # Script for preparing OpenSSL for building on Windows. # Uses Perl to create nmake makefiles and otherwise prepare the way # for building on 32 or 64 bit platforms. diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)openssl-1.0.2c\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -109,7 +109,7 @@ - + @@ -132,7 +132,7 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> - + diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.1j of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,9 +8,10 @@ set BUILDDOC= :CheckOpts -if '%1'=='-x86' (set BUILDX86=1) && shift && goto CheckOpts -if '%1'=='-x64' (set BUILDX64=1) && shift && goto CheckOpts -if '%1'=='--doc' (set BUILDDOC=1) && shift && goto CheckOpts +if "%1" EQU "-h" goto Help +if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -44,3 +45,12 @@ msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 if errorlevel 1 goto :eof ) + +exit /B 0 + +:Help +echo build.bat [-x86] [-x64] [--doc] [-h] +echo. +echo -x86 Build x86 installers +echo -x64 Build x64 installers +echo --doc Build CHM documentation diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -36,7 +36,7 @@ - + - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) diff --git a/Tools/msi/pip/pip.wxs b/Tools/msi/pip/pip.wxs --- a/Tools/msi/pip/pip.wxs +++ b/Tools/msi/pip/pip.wxs @@ -27,8 +27,8 @@ - - + + (&DefaultFeature=3) AND NOT (!DefaultFeature=3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150705035419.26537.976@psf.io> https://hg.python.org/cpython/rev/fdad98dde75a changeset: 96819:fdad98dde75a parent: 96818:f4e6e96adcdf parent: 96817:74f55f8d8982 user: Benjamin Peterson date: Sat Jul 04 22:53:55 2015 -0500 summary: merge 3.5 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 05:54:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 03:54:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <20150705035419.87143.41096@psf.io> https://hg.python.org/cpython/rev/f4e6e96adcdf changeset: 96818:f4e6e96adcdf parent: 96814:88814ddd5e9e parent: 96810:7900983373f0 user: Benjamin Peterson date: Sat Jul 04 22:53:45 2015 -0500 summary: merge heads files: Doc/library/idle.rst | 3 +- Doc/library/unittest.rst | 2 +- Include/unicodeobject.h | 4 + Lib/idlelib/help.txt | 4 +- Mac/BuildScript/build-installer.py | 6 +- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Mac/BuildScript/resources/ReadMe.rtf | 69 ++++- Mac/BuildScript/scripts/postflight.ensurepip | 10 +- Mac/BuildScript/scripts/postflight.framework | 16 +- Misc/NEWS | 6 + Objects/setobject.c | 140 ++++----- Objects/unicodeobject.c | 7 + PCbuild/get_externals.bat | 2 +- PCbuild/prepare_ssl.py | 1 + PCbuild/python.props | 2 +- PCbuild/python3dll.vcxproj | 4 +- PCbuild/readme.txt | 2 +- Tools/msi/build.bat | 16 +- Tools/msi/bundle/packagegroups/postinstall.wxs | 2 +- Tools/msi/msi.targets | 2 +- Tools/msi/pip/pip.wxs | 4 +- 21 files changed, 190 insertions(+), 114 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -47,7 +47,7 @@ Module :mod:`doctest` Another test-support module with a very different flavor. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -2261,6 +2261,10 @@ /* Clear all static strings. */ PyAPI_FUNC(void) _PyUnicode_ClearStaticStrings(void); +/* Fast equality check when the inputs are known to be exact unicode types + and where the hash values are equal (i.e. a very probable match) */ +PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *); + #ifdef __cplusplus } #endif diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -129,7 +129,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and additional Help - sources can be specified. + sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context (toggle) -- Open a pane at the top of the edit window 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -24,7 +24,7 @@ \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL \i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. -\b \ul \ulc0 \ +\b \ul \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ @@ -36,6 +36,71 @@ \i0 for this version of Python and of Mac OS X.\ \b \ul \ +Certificate verification and OpenSSL\ + +\b0 \ulnone \ +Python 3.5 includes a number of network security enhancements that were released in Python 3.4.3 and Python 2.7.10. {\field{\*\fldinst{HYPERLINK "https://www.python.org/dev/peps/pep-0476/"}}{\fldrslt PEP 476}} changes several standard library modules, like +\i httplib +\i0 , +\i urllib +\i0 , and +\i xmlrpclib +\i0 , to by default verify certificates presented by servers over secure (TLS) connections. The verification is performed by the OpenSSL libraries that Python is linked to. Prior to 3.4.3, both python.org installers dynamically linked with Apple-supplied OpenSSL libraries shipped with OS X. OS X provides a multiple level security framework that stores trust certificates in system and user keychains managed by the +\i Keychain Access +\i0 application and the +\i security +\i0 command line utility.\ +\ +For OS X 10.5, Apple provides +\i OpenSSL 0.9.7 +\i0 libraries. This version of Apple's OpenSSL +\b does not +\b0 use the certificates from the system security framework, even when used on newer versions of OS X. Instead it consults a traditional OpenSSL concatenated certificate file ( +\i cafile +\i0 ) or certificate directory ( +\i capath +\i0 ), located in +\f1 /System/Library/OpenSSL +\f0 . These directories are typically empty and not managed by OS X; you must manage them yourself or supply your own SSL contexts. OpenSSL 0.9.7 is obsolete by current security standards, lacking a number of important features found in later versions. Among the problems this causes is the inability to verify higher-security certificates now used by python.org services, including +\i t{\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi"}}{\fldrslt he Python Package Index, PyPI}} +\i0 . To solve this problem, the +\i 10.5+ 32-bit-only python.org variant +\i0 is linked with a private copy of +\i OpenSSL 1.0.2 +\i0 ; it consults the same default certificate directory, +\f1 /System/Library/OpenSSL +\f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt +\f1 py2app}}, you may now need to bundle CA certificates in them or otherwise supply non-default SSL contexts.\ +\ +For OS X 10.6+, Apple also provides +\i OpenSSL +\i0 +\i 0.9.8 libraries +\i0 . Apple's 0.9.8 version includes an important additional feature: if a certificate cannot be verified using the manually administered certificates in +\f1 /System/Library/OpenSSL +\f0 , the certificates managed by the system security framework In the user and system keychains are also consulted (using Apple private APIs). For this reason, the +\i 64-bit/32-bit 10.6+ python.org variant +\i0 continues to be dynamically linked with Apple's OpenSSL 0.9.8 since it was felt that the loss of the system-provided certificates and management tools outweighs the additional security features provided by newer versions of OpenSSL. This will likely change in future releases of the python.org installers as Apple has deprecated use of the system-supplied OpenSSL libraries. If you do need features from newer versions of OpenSSL, there are third-party OpenSSL wrapper packages available through +\i PyPI +\i0 .\ +\ +The bundled +\f1 pip +\f0 included with the Python 3.5 installers has its own default certificate store for verifying download connections.\ +\ + +\b \ul Other changes\ + +\b0 \ulnone \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural +\cf0 For other changes in this release, see the +\i What's new +\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its +\i Release Notes +\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural + +\b \cf0 \ul \ Python 3 and Python 2 Co-existence\ \b0 \ulnone \ diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -10,15 +10,15 @@ umask 022 -"${FWK}/bin/python${PYVER}" -m ensurepip --upgrade +"${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade -"${FWK}/bin/python${PYVER}" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python${PYVER}" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python${PYVER}" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework --- a/Mac/BuildScript/scripts/postflight.framework +++ b/Mac/BuildScript/scripts/postflight.framework @@ -6,23 +6,23 @@ PYVER="@PYVER@" FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ "${FWK}/lib/python${PYVER}" -"${FWK}/bin/python at PYVER@" -Wi \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" -"${FWK}/bin/python at PYVER@" -Wi -O \ - "${FWK}/lib/python${PYVER}/compileall.py" \ +"${FWK}/bin/python at PYVER@" -E -s -Wi -O \ + "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ "${FWK}/lib/python${PYVER}/site-packages" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -118,6 +118,12 @@ - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. +Build +----- + +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. + What's New in Python 3.5.0 beta 2? ================================== diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -29,7 +29,6 @@ #include "Python.h" #include "structmember.h" -#include "stringlib/eq.h" /* Object used as dummy key to fill deleted entries */ static PyObject _dummy_struct; @@ -74,7 +73,7 @@ return entry; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) return entry; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -100,7 +99,7 @@ return entry; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) return entry; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -125,6 +124,8 @@ } } +static int set_table_resize(PySetObject *, Py_ssize_t); + static int set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) { @@ -139,7 +140,7 @@ entry = &table[i]; if (entry->key == NULL) - goto found_null_first; + goto found_unused; freeslot = NULL; perturb = hash; @@ -153,7 +154,7 @@ goto found_active; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) goto found_active; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -173,7 +174,7 @@ for (j = 0 ; j < LINEAR_PROBES ; j++) { entry++; if (entry->hash == 0 && entry->key == NULL) - goto found_null; + goto found_unused_or_dummy; if (entry->hash == hash) { PyObject *startkey = entry->key; assert(startkey != dummy); @@ -181,7 +182,7 @@ goto found_active; if (PyUnicode_CheckExact(startkey) && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) + && _PyUnicode_EQ(startkey, key)) goto found_active; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); @@ -204,30 +205,27 @@ entry = &table[i]; if (entry->key == NULL) - goto found_null; + goto found_unused_or_dummy; } - found_null_first: + found_unused_or_dummy: + if (freeslot == NULL) + goto found_unused; + Py_INCREF(key); + so->used++; + freeslot->key = key; + freeslot->hash = hash; + return 0; + + found_unused: Py_INCREF(key); so->fill++; so->used++; entry->key = key; entry->hash = hash; - return 0; - - found_null: - Py_INCREF(key); - if (freeslot == NULL) { - /* UNUSED */ - so->fill++; - } else { - /* DUMMY */ - entry = freeslot; - } - so->used++; - entry->key = key; - entry->hash = hash; - return 0; + if ((size_t)so->fill*3 < mask*2) + return 0; + return set_table_resize(so, so->used); found_active: return 0; @@ -291,6 +289,7 @@ setentry small_copy[PySet_MINSIZE]; assert(minused >= 0); + minused = (minused > 50000) ? minused * 2 : minused * 4; /* Find the smallest table size > minused. */ /* XXX speed-up with intrinsics */ @@ -366,28 +365,15 @@ return 0; } -/* CAUTION: set_add_key/entry() must guarantee it won't resize the table */ - static int set_add_entry(PySetObject *so, setentry *entry) { - Py_ssize_t n_used; - PyObject *key = entry->key; - Py_hash_t hash = entry->hash; - - assert(so->fill <= so->mask); /* at least one empty slot */ - n_used = so->used; - if (set_insert_key(so, key, hash)) - return -1; - if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) - return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + return set_insert_key(so, entry->key, entry->hash); } static int set_add_key(PySetObject *so, PyObject *key) { - setentry entry; Py_hash_t hash; if (!PyUnicode_CheckExact(key) || @@ -396,9 +382,7 @@ if (hash == -1) return -1; } - entry.key = key; - entry.hash = hash; - return set_add_entry(so, &entry); + return set_insert_key(so, key, hash); } #define DISCARD_NOTFOUND 0 @@ -631,8 +615,8 @@ * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. */ - if ((so->fill + other->used)*3 >= (so->mask+1)*2) { - if (set_table_resize(so, (so->used + other->used)*2) != 0) + if ((so->fill + other->used)*3 >= so->mask*2) { + if (set_table_resize(so, so->used + other->used) != 0) return -1; } so_entry = so->table; @@ -694,7 +678,7 @@ static int set_contains_key(PySetObject *so, PyObject *key) { - setentry entry; + setentry *entry; Py_hash_t hash; if (!PyUnicode_CheckExact(key) || @@ -703,9 +687,10 @@ if (hash == -1) return -1; } - entry.key = key; - entry.hash = hash; - return set_contains_entry(so, &entry); + entry = set_lookkey(so, key, hash); + if (entry == NULL) + return -1; + return entry->key != NULL; } static PyObject * @@ -977,18 +962,14 @@ * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. */ - if (dictsize == -1) + if (dictsize < 0) return -1; - if ((so->fill + dictsize)*3 >= (so->mask+1)*2) { - if (set_table_resize(so, (so->used + dictsize)*2) != 0) + if ((so->fill + dictsize)*3 >= so->mask*2) { + if (set_table_resize(so, so->used + dictsize) != 0) return -1; } while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - setentry an_entry; - - an_entry.hash = hash; - an_entry.key = key; - if (set_add_entry(so, &an_entry)) + if (set_insert_key(so, key, hash)) return -1; } return 0; @@ -1288,7 +1269,7 @@ while (set_next((PySetObject *)other, &pos, &entry)) { int rv = set_contains_entry(so, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(result); return NULL; } @@ -1322,7 +1303,7 @@ entry.hash = hash; entry.key = key; rv = set_contains_entry(so, &entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); @@ -1449,7 +1430,7 @@ } while (set_next((PySetObject *)other, &pos, &entry)) { int rv = set_contains_entry(so, entry); - if (rv == -1) + if (rv < 0) return NULL; if (rv) Py_RETURN_FALSE; @@ -1475,7 +1456,7 @@ entry.key = key; rv = set_contains_entry(so, &entry); Py_DECREF(key); - if (rv == -1) { + if (rv < 0) { Py_DECREF(it); return NULL; } @@ -1504,7 +1485,7 @@ Py_ssize_t pos = 0; while (set_next((PySetObject *)other, &pos, &entry)) - if (set_discard_entry(so, entry) == -1) + if (set_discard_entry(so, entry) < 0) return -1; } else { PyObject *key, *it; @@ -1513,7 +1494,7 @@ return -1; while ((key = PyIter_Next(it)) != NULL) { - if (set_discard_key(so, key) == -1) { + if (set_discard_key(so, key) < 0) { Py_DECREF(it); Py_DECREF(key); return -1; @@ -1524,10 +1505,10 @@ if (PyErr_Occurred()) return -1; } - /* If more than 1/5 are dummies, then resize them away. */ - if ((so->fill - so->used) * 5 < so->mask) + /* If more than 1/4th are dummies, then resize them away. */ + if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4) return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + return set_table_resize(so, so->used); } static PyObject * @@ -1554,7 +1535,7 @@ result = set_copy(so); if (result == NULL) return NULL; - if (set_difference_update_internal((PySetObject *) result, other) != -1) + if (set_difference_update_internal((PySetObject *) result, other) == 0) return result; Py_DECREF(result); return NULL; @@ -1583,17 +1564,16 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { - setentry entrycopy; + PyObject *key = entry->key; + Py_hash_t hash = entry->hash; int rv; - entrycopy.hash = entry->hash; - entrycopy.key = entry->key; - rv = _PyDict_Contains(other, entry->key, entry->hash); + rv = _PyDict_Contains(other, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (!rv) { - if (set_add_entry((PySetObject *)result, &entrycopy)) { + if (set_insert_key((PySetObject *)result, key, hash)) { Py_DECREF(result); return NULL; } @@ -1605,7 +1585,7 @@ /* Iterate over so, checking for common elements in other. */ while (set_next(so, &pos, &entry)) { int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(result); return NULL; } @@ -1689,7 +1669,7 @@ an_entry.key = key; rv = set_discard_entry(so, &an_entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(key); return NULL; } @@ -1715,7 +1695,7 @@ while (set_next(otherset, &pos, &entry)) { int rv = set_discard_entry(so, entry); - if (rv == -1) { + if (rv < 0) { Py_DECREF(otherset); return NULL; } @@ -1797,7 +1777,7 @@ while (set_next(so, &pos, &entry)) { int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) + if (rv < 0) return NULL; if (!rv) Py_RETURN_FALSE; @@ -1888,7 +1868,7 @@ int rv; rv = set_contains_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return -1; PyErr_Clear(); @@ -1907,7 +1887,7 @@ long result; result = set_contains(so, key); - if (result == -1) + if (result < 0) return NULL; return PyBool_FromLong(result); } @@ -1921,7 +1901,7 @@ int rv; rv = set_discard_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; PyErr_Clear(); @@ -1930,7 +1910,7 @@ return NULL; rv = set_discard_key(so, tmpkey); Py_DECREF(tmpkey); - if (rv == -1) + if (rv < 0) return NULL; } @@ -1953,7 +1933,7 @@ int rv; rv = set_discard_key(so, key); - if (rv == -1) { + if (rv < 0) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; PyErr_Clear(); @@ -1962,7 +1942,7 @@ return NULL; rv = set_discard_key(so, tmpkey); Py_DECREF(tmpkey); - if (rv == -1) + if (rv < 0) return NULL; } Py_RETURN_NONE; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -42,6 +42,7 @@ #include "Python.h" #include "ucnhash.h" #include "bytes_methods.h" +#include "stringlib/eq.h" #ifdef MS_WINDOWS #include @@ -10887,6 +10888,12 @@ } int +_PyUnicode_EQ(PyObject *aa, PyObject *bb) +{ + return unicode_eq(aa, bb); +} + +int PyUnicode_Contains(PyObject *container, PyObject *element) { PyObject *str, *sub; diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # Script for preparing OpenSSL for building on Windows. # Uses Perl to create nmake makefiles and otherwise prepare the way # for building on 32 or 64 bit platforms. diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)openssl-1.0.2c\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -109,7 +109,7 @@ - + @@ -132,7 +132,7 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> - + diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.1j of the OpenSSL secure sockets + Python wrapper for version 1.0.2c of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,9 +8,10 @@ set BUILDDOC= :CheckOpts -if '%1'=='-x86' (set BUILDX86=1) && shift && goto CheckOpts -if '%1'=='-x64' (set BUILDX64=1) && shift && goto CheckOpts -if '%1'=='--doc' (set BUILDDOC=1) && shift && goto CheckOpts +if "%1" EQU "-h" goto Help +if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -44,3 +45,12 @@ msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 if errorlevel 1 goto :eof ) + +exit /B 0 + +:Help +echo build.bat [-x86] [-x64] [--doc] [-h] +echo. +echo -x86 Build x86 installers +echo -x64 Build x64 installers +echo --doc Build CHM documentation diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -36,7 +36,7 @@ - + - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) diff --git a/Tools/msi/pip/pip.wxs b/Tools/msi/pip/pip.wxs --- a/Tools/msi/pip/pip.wxs +++ b/Tools/msi/pip/pip.wxs @@ -27,8 +27,8 @@ - - + + (&DefaultFeature=3) AND NOT (!DefaultFeature=3) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Jul 5 10:46:16 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 05 Jul 2015 08:46:16 +0000 Subject: [Python-checkins] Daily reference leaks (fdad98dde75a): sum=4 Message-ID: <20150705084616.32451.37194@psf.io> results for fdad98dde75a on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog68XswJ', '--timeout', '7200'] From python-checkins at python.org Sun Jul 5 16:43:54 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 05 Jul 2015 14:43:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixes_rebuild_?= =?utf-8?q?of_strings_for_Windows_installer=2E?= Message-ID: <20150705144354.7863.9433@psf.io> https://hg.python.org/cpython/rev/60b84c6751d3 changeset: 96820:60b84c6751d3 branch: 3.5 parent: 96817:74f55f8d8982 user: Steve Dower date: Sun Jul 05 07:24:17 2015 -0700 summary: Fixes rebuild of strings for Windows installer. files: Tools/msi/msi.targets | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.targets b/Tools/msi/msi.targets --- a/Tools/msi/msi.targets +++ b/Tools/msi/msi.targets @@ -24,7 +24,7 @@ - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 16:43:54 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 05 Jul 2015 14:43:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixes_rebuild_of_strings_for_Windows_installer=2E?= Message-ID: <20150705144354.19972.68776@psf.io> https://hg.python.org/cpython/rev/1cb6f2031970 changeset: 96821:1cb6f2031970 parent: 96819:fdad98dde75a parent: 96820:60b84c6751d3 user: Steve Dower date: Sun Jul 05 07:24:47 2015 -0700 summary: Fixes rebuild of strings for Windows installer. files: Tools/msi/msi.targets | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.targets b/Tools/msi/msi.targets --- a/Tools/msi/msi.targets +++ b/Tools/msi/msi.targets @@ -24,7 +24,7 @@ - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_add_news_secti?= =?utf-8?q?on_for_next_beta?= Message-ID: <20150705153927.66728.25606@psf.io> https://hg.python.org/cpython/rev/9e428956245a changeset: 96822:9e428956245a branch: 3.5 parent: 96817:74f55f8d8982 user: Benjamin Peterson date: Sun Jul 05 10:37:00 2015 -0500 summary: add news section for next beta files: Misc/NEWS | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 beta 4? +================================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_set_items_in_d?= =?utf-8?q?ict_displays_from_left_to_right_=28closes_=2324569=29?= Message-ID: <20150705153927.99345.95665@psf.io> https://hg.python.org/cpython/rev/a4df0fe62b46 changeset: 96823:a4df0fe62b46 branch: 3.5 user: Benjamin Peterson date: Sun Jul 05 10:37:25 2015 -0500 summary: set items in dict displays from left to right (closes #24569) files: Lib/test/test_unpack_ex.py | 3 +++ Misc/NEWS | 2 ++ Python/ceval.c | 15 +++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -128,6 +128,9 @@ ... for i in range(1000)) + "}")) 1000 + >>> {0:1, **{0:2}, 0:3, 0:4} + {0: 4} + List comprehension element unpacking >>> a, b, c = [0, 1, 2], 3, 4 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24569: Make PEP 448 dictionary evaluation more consistent. + Library ------- diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2561,22 +2561,25 @@ } TARGET(BUILD_MAP) { + int i; PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); if (map == NULL) goto error; - while (--oparg >= 0) { + for (i = oparg; i > 0; i--) { int err; - PyObject *value = TOP(); - PyObject *key = SECOND(); - STACKADJ(-2); + PyObject *key = PEEK(2*i); + PyObject *value = PEEK(2*i - 1); err = PyDict_SetItem(map, key, value); - Py_DECREF(value); - Py_DECREF(key); if (err != 0) { Py_DECREF(map); goto error; } } + + while (oparg--) { + Py_DECREF(POP()); + Py_DECREF(POP()); + } PUSH(map); DISPATCH(); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQ1Njkp?= Message-ID: <20150705153927.3167.38063@psf.io> https://hg.python.org/cpython/rev/75852d90c225 changeset: 96824:75852d90c225 parent: 96819:fdad98dde75a parent: 96823:a4df0fe62b46 user: Benjamin Peterson date: Sun Jul 05 10:38:05 2015 -0500 summary: merge 3.5 (#24569) files: Lib/test/test_unpack_ex.py | 3 +++ Misc/NEWS | 14 ++++++++++++++ Python/ceval.c | 15 +++++++++------ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -128,6 +128,9 @@ ... for i in range(1000)) + "}")) 1000 + >>> {0:1, **{0:2}, 0:3, 0:4} + {0: 4} + List comprehension element unpacking >>> a, b, c = [0, 1, 2], 3, 4 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,20 @@ now can't be disabled at compile time. +What's New in Python 3.5.0 beta 4? +================================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +- Issue #24569: Make PEP 448 dictionary evaluation more consistent. + +Library +------- + + What's New in Python 3.5.0 beta 3? ================================== diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2561,22 +2561,25 @@ } TARGET(BUILD_MAP) { + int i; PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); if (map == NULL) goto error; - while (--oparg >= 0) { + for (i = oparg; i > 0; i--) { int err; - PyObject *value = TOP(); - PyObject *key = SECOND(); - STACKADJ(-2); + PyObject *key = PEEK(2*i); + PyObject *value = PEEK(2*i - 1); err = PyDict_SetItem(map, key, value); - Py_DECREF(value); - Py_DECREF(key); if (err != 0) { Py_DECREF(map); goto error; } } + + while (oparg--) { + Py_DECREF(POP()); + Py_DECREF(POP()); + } PUSH(map); DISPATCH(); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_merge_heads?= Message-ID: <20150705153927.9956.69889@psf.io> https://hg.python.org/cpython/rev/4623c0edc5e6 changeset: 96825:4623c0edc5e6 branch: 3.5 parent: 96823:a4df0fe62b46 parent: 96820:60b84c6751d3 user: Benjamin Peterson date: Sun Jul 05 10:39:13 2015 -0500 summary: merge heads files: Tools/msi/msi.targets | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.targets b/Tools/msi/msi.targets --- a/Tools/msi/msi.targets +++ b/Tools/msi/msi.targets @@ -24,7 +24,7 @@ - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <20150705153927.10165.44055@psf.io> https://hg.python.org/cpython/rev/0023993b93ea changeset: 96826:0023993b93ea parent: 96824:75852d90c225 parent: 96821:1cb6f2031970 user: Benjamin Peterson date: Sun Jul 05 10:39:18 2015 -0500 summary: merge heads files: Tools/msi/msi.targets | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.targets b/Tools/msi/msi.targets --- a/Tools/msi/msi.targets +++ b/Tools/msi/msi.targets @@ -24,7 +24,7 @@ - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150705153928.27420.83938@psf.io> https://hg.python.org/cpython/rev/834fcda98ed9 changeset: 96827:834fcda98ed9 parent: 96826:0023993b93ea parent: 96825:4623c0edc5e6 user: Benjamin Peterson date: Sun Jul 05 10:39:22 2015 -0500 summary: merge 3.5 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:39:55 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:39:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogJ2ZyZWUtYWZ0ZXIt?= =?utf-8?q?use=27_is_not_a_bug_=3A=29_=28closes_=2324568=29?= Message-ID: <20150705153955.20181.56112@psf.io> https://hg.python.org/cpython/rev/5097c91cdc2d changeset: 96828:5097c91cdc2d branch: 2.7 parent: 96692:4f48b1e982ca user: Benjamin Peterson date: Sun Jul 05 10:39:47 2015 -0500 summary: 'free-after-use' is not a bug :) (closes #24568) 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 @@ -138,7 +138,7 @@ - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. -- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup +- Issues #24099, #24100, and #24101: Fix use-after-use bug in heapq's siftup and siftdown functions. - Backport collections.deque fixes from Python 3.5. Prevents reentrant badness -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 17:40:01 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Jul 2015 15:40:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Merge_heads?= Message-ID: <20150705154001.17196.13439@psf.io> https://hg.python.org/cpython/rev/756876e059cb changeset: 96829:756876e059cb branch: 2.7 parent: 96828:5097c91cdc2d parent: 96806:64b42ec6ef42 user: Benjamin Peterson date: Sun Jul 05 10:39:53 2015 -0500 summary: Merge heads files: Doc/library/idle.rst | 3 +- Doc/library/unittest.rst | 2 +- Doc/library/urllib.rst | 2 +- Lib/ensurepip/__init__.py | 4 +- Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/idlelib/help.txt | 7 +- Lib/tarfile.py | 2 +- Lib/test/test_audioop.py | 15 +++ Lib/test/test_bytes.py | 19 ++++- Lib/test/test_contextlib.py | 8 ++ Lib/test/test_tarfile.py | 9 ++ Lib/test/test_tokenize.py | 20 +++++- Lib/tokenize.py | 17 ++++ Mac/BuildScript/build-installer.py | 6 +- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 20 +++++ Modules/audioop.c | 38 +++++++-- Objects/bytearrayobject.c | 4 +- PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.vsprops | 2 +- PCbuild/readme.txt | 2 +- configure | 5 +- configure.ac | 2 +- 26 files changed, 160 insertions(+), 31 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -248,7 +248,8 @@ help sources can be specified. Non-default user setting are saved in a .idlerc directory in the user's home directory. Problems caused by bad user configuration files are solved by editing or deleting one or more of the - files in .idlerc. + files in .idlerc. On OS X, open the configuration dialog by selecting + Preferences in the application menu. Configure Extensions Open a configuration dialog for setting preferences for extensions diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -83,7 +83,7 @@ discovery. unittest2 allows you to use these features with earlier versions of Python. - `Simple Smalltalk Testing: With Patterns `_ + `Simple Smalltalk Testing: With Patterns `_ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst --- a/Doc/library/urllib.rst +++ b/Doc/library/urllib.rst @@ -296,7 +296,7 @@ .. note:: urllib also exposes certain utility functions like splittype, splithost and others parsing url into various components. But it is recommended to use - :mod:`urlparse` for parsing urls than using these functions directly. + :mod:`urlparse` for parsing urls rather than using these functions directly. Python 3 does not expose these helper functions from :mod:`urllib.parse` module. diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "17.0" +_SETUPTOOLS_VERSION = "18.0.1" -_PIP_VERSION = "7.0.3" +_PIP_VERSION = "7.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.3-py2.py3-none-any.whl deleted file mode 100644 index bb0cb3138ba4ade7fa5ba3285d04f70d439f490f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76fcad1c7efb6223b049967e84fda31f9fd68dfc GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-17.0-py2.py3-none-any.whl deleted file mode 100644 index a1d3561bad9c3709196b6481dd2e540b0914129b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..67aaca50a921a164fac7d721bc2aa80735c5515e GIT binary patch [stripped] diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -90,10 +90,9 @@ Configure IDLE -- Open a configuration dialog. Fonts, indentation, keybindings, and color themes may be altered. Startup Preferences may be set, and Additional Help - Sources can be specified. - - On OS X this menu is not present, use - menu 'IDLE -> Preferences...' instead. + Sources can be specified. On OS X, open the + configuration dialog by selecting Preferences + in the application menu. --- Code Context -- Open a pane at the top of the edit window which shows the block context of the section of code diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -186,7 +186,7 @@ # itn() below. if s[0] != chr(0200): try: - n = int(nts(s) or "0", 8) + n = int(nts(s).strip() or "0", 8) except ValueError: raise InvalidHeaderError("invalid header") else: diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -210,6 +210,21 @@ self.assertEqual(audioop.lin2adpcm(b'\0' * w * 10, w, None), (b'\0' * 5, (0, 0))) + def test_invalid_adpcm_state(self): + # state must be a tuple or None, not an integer + self.assertRaises(TypeError, audioop.adpcm2lin, b'\0', 1, 555) + self.assertRaises(TypeError, audioop.lin2adpcm, b'\0', 1, 555) + # Issues #24456, #24457: index out of range + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, -1)) + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, 89)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, -1)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, 89)) + # value out of range + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (-0x8001, 0)) + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0x8000, 0)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (-0x8001, 0)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0x8000, 0)) + def test_lin2alaw(self): self.assertEqual(audioop.lin2alaw(datas[1], 1), b'\xd5\x87\xa4\x24\xaa\x2a\x5a') diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -722,10 +722,27 @@ for i in range(100): b += b"x" alloc = b.__alloc__() - self.assertTrue(alloc >= len(b)) + self.assertGreater(alloc, len(b)) # including trailing null byte if alloc not in seq: seq.append(alloc) + def test_init_alloc(self): + b = bytearray() + def g(): + for i in range(1, 100): + yield i + a = list(b) + self.assertEqual(a, list(range(1, len(a)+1))) + self.assertEqual(len(b), len(a)) + self.assertLessEqual(len(b), i) + alloc = b.__alloc__() + self.assertGreater(alloc, len(b)) # including trailing null byte + b.__init__(g()) + self.assertEqual(list(b), list(range(1, 100))) + self.assertEqual(len(b), 99) + alloc = b.__alloc__() + self.assertGreater(alloc, len(b)) + def test_extend(self): orig = b'hello' a = bytearray(orig) diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -106,6 +106,14 @@ baz = self._create_contextmanager_attribs() self.assertEqual(baz.__doc__, "Whee!") + def test_keywords(self): + # Ensure no keyword arguments are inhibited + @contextmanager + def woohoo(self, func, args, kwds): + yield (self, func, args, kwds) + with woohoo(self=11, func=22, args=33, kwds=44) as target: + self.assertEqual(target, (11, 22, 33, 44)) + class NestedTestCase(unittest.TestCase): # XXX This needs more work 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 @@ -1566,6 +1566,14 @@ tarinfo.tobuf(tarfile.PAX_FORMAT) +class MiscTest(unittest.TestCase): + + def test_read_number_fields(self): + # Issue 24514: Test if empty number fields are converted to zero. + self.assertEqual(tarfile.nti("\0"), 0) + self.assertEqual(tarfile.nti(" \0"), 0) + + class ContextManagerTest(unittest.TestCase): def test_basic(self): @@ -1730,6 +1738,7 @@ PaxUnicodeTest, AppendTest, LimitsTest, + MiscTest, ContextManagerTest, ] 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,7 +559,7 @@ from test import test_support from tokenize import (untokenize, generate_tokens, NUMBER, NAME, OP, - STRING, ENDMARKER, tok_name, Untokenizer) + STRING, ENDMARKER, tok_name, Untokenizer, tokenize) from StringIO import StringIO import os from unittest import TestCase @@ -650,12 +650,30 @@ self.assertEqual(u.untokenize(iter([token])), 'Hello ') +class TestRoundtrip(TestCase): + def roundtrip(self, code): + if isinstance(code, str): + code = code.encode('utf-8') + tokens = generate_tokens(StringIO(code).readline) + return untokenize(tokens).decode('utf-8') + + def test_indentation_semantics_retained(self): + """ + Ensure that although whitespace might be mutated in a roundtrip, + the semantic meaning of the indentation remains consistent. + """ + code = "if False:\n\tx=3\n\tx=3\n" + codelines = self.roundtrip(code).split('\n') + self.assertEqual(codelines[1], codelines[2]) + + __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) + test_support.run_unittest(TestRoundtrip) if __name__ == "__main__": test_main() diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -198,6 +198,8 @@ def untokenize(self, iterable): it = iter(iterable) + indents = [] + startline = False for t in it: if len(t) == 2: self.compat(t, it) @@ -205,6 +207,21 @@ tok_type, token, start, end, line = t if tok_type == ENDMARKER: break + if tok_type == INDENT: + indents.append(token) + continue + elif tok_type == DEDENT: + indents.pop() + self.prev_row, self.prev_col = end + continue + elif tok_type in (NEWLINE, NL): + startline = True + elif startline and indents: + indent = indents[-1] + if start[1] >= len(indent): + self.tokens.append(indent) + self.prev_col = len(indent) + startline = False self.add_whitespace(start) self.tokens.append(token) self.prev_row, self.prev_col = end 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2a", - url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz", - checksum='a06c547dac9044161a477211049f60ef', + name="OpenSSL 1.0.2c", + url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", + checksum='8c8d81a9ae7005276e486702edbcd4b6', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2a +# using openssl 1.0.2c # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24467: Fixed possible buffer over-read in bytearray. The bytearray + object now always allocates place for trailing null byte and it's buffer now + is always null-terminated. + - Issue #19543: encode() and decode() methods and constructors of str, unicode and bytearray classes now emit deprecation warning for known non-text encodings when Python is ran with the -3 option. @@ -30,6 +34,16 @@ Library ------- +- Issue #24514: tarfile now tolerates number fields consisting of only + whitespace. + +- Issue #20387: Restore semantic round-trip correctness in tokenize/untokenize + for tab-indented blocks. + +- Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm() + functions of the audioop module. Fixed SystemError when the state is not a + tuple. Fixed possible memory leak. + - Issue #24481: Fix possible memory corruption with large profiler info strings in hotshot. @@ -78,6 +92,12 @@ - Issue #24134: Reverted issue #24134 changes. +Build +----- + +- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2c. + IDLE ---- diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1420,18 +1420,29 @@ if (!audioop_check_parameters(len, size)) return NULL; - str = PyString_FromStringAndSize(NULL, len/(size*2)); - if ( str == 0 ) - return 0; - ncp = (signed char *)PyString_AsString(str); - /* Decode state, should have (value, step) */ if ( state == Py_None ) { /* First time, it seems. Set defaults */ valpred = 0; index = 0; - } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) + } + else if (!PyTuple_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); + return NULL; + } + else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) { + return NULL; + } + else if (valpred >= 0x8000 || valpred < -0x8000 || + (size_t)index >= sizeof(stepsizeTable)/sizeof(stepsizeTable[0])) { + PyErr_SetString(PyExc_ValueError, "bad state"); + return NULL; + } + + str = PyString_FromStringAndSize(NULL, len/(size*2)); + if ( str == 0 ) return 0; + ncp = (signed char *)PyString_AsString(str); step = stepsizeTable[index]; bufferstep = 1; @@ -1529,8 +1540,19 @@ /* First time, it seems. Set defaults */ valpred = 0; index = 0; - } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) - return 0; + } + else if (!PyTuple_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); + return NULL; + } + else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) { + return NULL; + } + else if (valpred >= 0x8000 || valpred < -0x8000 || + (size_t)index >= sizeof(stepsizeTable)/sizeof(stepsizeTable[0])) { + PyErr_SetString(PyExc_ValueError, "bad state"); + return NULL; + } if (len > (INT_MAX/2)/size) { PyErr_SetString(PyExc_MemoryError, diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -897,8 +897,10 @@ goto error; /* Append the byte */ - if (Py_SIZE(self) < self->ob_alloc) + if (Py_SIZE(self) + 1 < self->ob_alloc) { Py_SIZE(self)++; + PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0'; + } else if (PyByteArray_Resize((PyObject *)self, Py_SIZE(self)+1) < 0) goto error; self->ob_bytes[Py_SIZE(self)-1] = value; diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,7 +55,7 @@ bzip2-1.0.6 db-4.7.25.0 nasm-2.11.06 - openssl-1.0.2a + openssl-1.0.2c tcl-8.5.15.0 tk-8.5.15.0 tix-8.4.3.5 diff --git a/PCbuild/pyproject.vsprops b/PCbuild/pyproject.vsprops --- a/PCbuild/pyproject.vsprops +++ b/PCbuild/pyproject.vsprops @@ -82,7 +82,7 @@ /> &5 $as_echo "$have_gcc_asm_for_x87" >&6; } if test "$have_gcc_asm_for_x87" = yes diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3723,7 +3723,7 @@ # so we try it on all platforms. AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set x87 control word) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); __asm__ __volatile__ ("fldcw %0" : : "m" (cw)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:03:25 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 05 Jul 2015 17:03:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Clean-up_call_patterns_for?= =?utf-8?q?_add/contains/discard_to_better_match_the_caller=27s?= Message-ID: <20150705170325.20885.63092@psf.io> https://hg.python.org/cpython/rev/a4be0cab2e24 changeset: 96830:a4be0cab2e24 parent: 96827:834fcda98ed9 user: Raymond Hettinger date: Sun Jul 05 10:03:20 2015 -0700 summary: Clean-up call patterns for add/contains/discard to better match the caller's needs. files: Objects/setobject.c | 73 +++++++++++++++----------------- 1 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -127,7 +127,7 @@ static int set_table_resize(PySetObject *, Py_ssize_t); static int -set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) +set_add_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; setentry *freeslot; @@ -162,7 +162,7 @@ if (cmp < 0) /* unlikely */ return -1; if (table != so->table || entry->key != startkey) /* unlikely */ - return set_insert_key(so, key, hash); + return set_add_key_hash(so, key, hash); if (cmp > 0) /* likely */ goto found_active; mask = so->mask; /* help avoid a register spill */ @@ -190,7 +190,7 @@ if (cmp < 0) return -1; if (table != so->table || entry->key != startkey) - return set_insert_key(so, key, hash); + return set_add_key_hash(so, key, hash); if (cmp > 0) goto found_active; mask = so->mask; @@ -368,7 +368,7 @@ static int set_add_entry(PySetObject *so, setentry *entry) { - return set_insert_key(so, entry->key, entry->hash); + return set_add_key_hash(so, entry->key, entry->hash); } static int @@ -382,19 +382,19 @@ if (hash == -1) return -1; } - return set_insert_key(so, key, hash); + return set_add_key_hash(so, key, hash); } #define DISCARD_NOTFOUND 0 #define DISCARD_FOUND 1 static int -set_discard_entry(PySetObject *so, setentry *oldentry) +set_discard_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *entry; PyObject *old_key; - entry = set_lookkey(so, oldentry->key, oldentry->hash); + entry = set_lookkey(so, key, hash); if (entry == NULL) return -1; if (entry->key == NULL) @@ -408,9 +408,14 @@ } static int +set_discard_entry(PySetObject *so, setentry *entry) +{ + return set_discard_key_hash(so, entry->key, entry->hash); +} + +static int set_discard_key(PySetObject *so, PyObject *key) { - setentry entry; Py_hash_t hash; assert (PyAnySet_Check(so)); @@ -421,9 +426,7 @@ if (hash == -1) return -1; } - entry.key = key; - entry.hash = hash; - return set_discard_entry(so, &entry); + return set_discard_key_hash(so, key, hash); } static void @@ -655,7 +658,7 @@ for (i = 0; i <= other->mask; i++, other_entry++) { key = other_entry->key; if (key != NULL && key != dummy) { - if (set_insert_key(so, key, other_entry->hash)) + if (set_add_key_hash(so, key, other_entry->hash)) return -1; } } @@ -663,16 +666,20 @@ } static int +set_contains_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) +{ + setentry *lu_entry; + + lu_entry = set_lookkey(so, key, hash); + if (lu_entry != NULL) + return lu_entry->key != NULL; + return -1; +} + +static int set_contains_entry(PySetObject *so, setentry *entry) { - PyObject *key; - setentry *lu_entry; - - lu_entry = set_lookkey(so, entry->key, entry->hash); - if (lu_entry == NULL) - return -1; - key = lu_entry->key; - return key != NULL; + return set_contains_key_hash(so, entry->key, entry->hash); } static int @@ -969,7 +976,7 @@ return -1; } while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - if (set_insert_key(so, key, hash)) + if (set_add_key_hash(so, key, hash)) return -1; } return 0; @@ -1291,7 +1298,6 @@ while ((key = PyIter_Next(it)) != NULL) { int rv; - setentry entry; Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { @@ -1300,9 +1306,7 @@ Py_DECREF(key); return NULL; } - entry.hash = hash; - entry.key = key; - rv = set_contains_entry(so, &entry); + rv = set_contains_key_hash(so, key, hash); if (rv < 0) { Py_DECREF(it); Py_DECREF(result); @@ -1310,7 +1314,7 @@ return NULL; } if (rv) { - if (set_add_entry(result, &entry)) { + if (set_add_key_hash(result, key, hash)) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); @@ -1444,7 +1448,6 @@ while ((key = PyIter_Next(it)) != NULL) { int rv; - setentry entry; Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { @@ -1452,9 +1455,7 @@ Py_DECREF(it); return NULL; } - entry.hash = hash; - entry.key = key; - rv = set_contains_entry(so, &entry); + rv = set_contains_key_hash(so, key, hash); Py_DECREF(key); if (rv < 0) { Py_DECREF(it); @@ -1573,7 +1574,7 @@ return NULL; } if (!rv) { - if (set_insert_key((PySetObject *)result, key, hash)) { + if (set_add_key_hash((PySetObject *)result, key, hash)) { Py_DECREF(result); return NULL; } @@ -1662,19 +1663,15 @@ int rv; Py_hash_t hash; while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - setentry an_entry; + Py_INCREF(key); - Py_INCREF(key); - an_entry.hash = hash; - an_entry.key = key; - - rv = set_discard_entry(so, &an_entry); + rv = set_discard_key_hash(so, key, hash); if (rv < 0) { Py_DECREF(key); return NULL; } if (rv == DISCARD_NOTFOUND) { - if (set_add_entry(so, &an_entry)) { + if (set_add_key_hash(so, key, hash)) { Py_DECREF(key); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:31:36 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 05 Jul 2015 17:31:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Version_bump_f?= =?utf-8?q?or_Python_3=2E5=2E0b3_release=2E?= Message-ID: <20150705173136.87143.81896@psf.io> https://hg.python.org/cpython/rev/0035fcd9b924 changeset: 96832:0035fcd9b924 branch: 3.5 tag: v3.5.0b3 user: Larry Hastings date: Sat Jul 04 19:13:02 2015 -0700 summary: Version bump for Python 3.5.0b3 release. files: Include/patchlevel.h | 4 ++-- README | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_SERIAL 3 /* Version as a string */ -#define PY_VERSION "3.5.0b2+" +#define PY_VERSION "3.5.0b3" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.5.0 beta 2 +This is Python version 3.5.0 beta 3 =================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:31:37 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 05 Jul 2015 17:31:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_tag_v3?= =?utf-8?q?=2E5=2E0b3_for_changeset_0035fcd9b924?= Message-ID: <20150705173136.99345.65438@psf.io> https://hg.python.org/cpython/rev/00a10c5ffd45 changeset: 96833:00a10c5ffd45 branch: 3.5 user: Larry Hastings date: Sat Jul 04 19:13:23 2015 -0700 summary: Added tag v3.5.0b3 for changeset 0035fcd9b924 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -150,3 +150,4 @@ 413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 +0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:31:37 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 05 Jul 2015 17:31:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Post-release_f?= =?utf-8?q?ixes_for_Python_3=2E5=2E0b3=2E?= Message-ID: <20150705173137.93104.49367@psf.io> https://hg.python.org/cpython/rev/1463f1d51782 changeset: 96834:1463f1d51782 branch: 3.5 user: Larry Hastings date: Sun Jul 05 10:26:00 2015 -0700 summary: Post-release fixes for Python 3.5.0b3. 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 3 /* Version as a string */ -#define PY_VERSION "3.5.0b3" +#define PY_VERSION "3.5.0b3+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 beta 4? +================================== + +Release date: 2015-07-26 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:31:37 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 05 Jul 2015 17:31:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_ongoing_work_in_3=2E5_branch=2E?= Message-ID: <20150705173137.91470.36763@psf.io> https://hg.python.org/cpython/rev/190f25b7e799 changeset: 96835:190f25b7e799 branch: 3.5 parent: 96834:1463f1d51782 parent: 96825:4623c0edc5e6 user: Larry Hastings date: Sun Jul 05 10:31:09 2015 -0700 summary: Merge with ongoing work in 3.5 branch. files: Lib/test/test_dict.py | 14 ++++++++++++++ Lib/test/test_unpack_ex.py | 3 +++ Misc/NEWS | 4 ++++ Objects/dictobject.c | 26 +++++++++++++++++++------- Python/ceval.c | 15 +++++++++------ Tools/msi/msi.targets | 2 +- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -937,6 +937,20 @@ d.popitem() self.check_reentrant_insertion(mutate) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return 0 + + def __eq__(self, o): + other.clear() + return False + + l = [(i,0) for i in range(1, 1337)] + other = dict(l) + other[X()] = 0 + d = {X(): 0, 1: 1} + self.assertRaises(RuntimeError, d.update, other) from test import mapping_tests diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -128,6 +128,9 @@ ... for i in range(1000)) + "}")) 1000 + >>> {0:1, **{0:2}, 0:3, 0:4} + {0: 4} + List comprehension element unpacking >>> a, b, c = [0, 1, 2], 3, 4 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24569: Make PEP 448 dictionary evaluation more consistent. + +- Issue #24407: Fix crash when dict is mutated while being updated. + Library ------- diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2039,20 +2039,32 @@ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { - PyObject *value; + PyObject *key, *value; + Py_hash_t hash; entry = &other->ma_keys->dk_entries[i]; + key = entry->me_key; + hash = entry->me_hash; if (other->ma_values) value = other->ma_values[i]; else value = entry->me_value; - if (value != NULL && - (override || - PyDict_GetItem(a, entry->me_key) == NULL)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) + if (value != NULL) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override || PyDict_GetItem(a, key) == NULL) + err = insertdict(mp, key, hash, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) return -1; + + if (n != DK_SIZE(other->ma_keys)) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; + } } } } diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2561,22 +2561,25 @@ } TARGET(BUILD_MAP) { + int i; PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); if (map == NULL) goto error; - while (--oparg >= 0) { + for (i = oparg; i > 0; i--) { int err; - PyObject *value = TOP(); - PyObject *key = SECOND(); - STACKADJ(-2); + PyObject *key = PEEK(2*i); + PyObject *value = PEEK(2*i - 1); err = PyDict_SetItem(map, key, value); - Py_DECREF(value); - Py_DECREF(key); if (err != 0) { Py_DECREF(map); goto error; } } + + while (oparg--) { + Py_DECREF(POP()); + Py_DECREF(POP()); + } PUSH(map); DISPATCH(); } diff --git a/Tools/msi/msi.targets b/Tools/msi/msi.targets --- a/Tools/msi/msi.targets +++ b/Tools/msi/msi.targets @@ -24,7 +24,7 @@ - + <_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`)) <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 19:31:36 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 05 Jul 2015 17:31:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Documentation_?= =?utf-8?q?fixes_for_3=2E5=2E0b3=2E?= Message-ID: <20150705173136.28944.62540@psf.io> https://hg.python.org/cpython/rev/b71dbd77a444 changeset: 96831:b71dbd77a444 branch: 3.5 parent: 96808:2dfdbbe0701b user: Larry Hastings date: Sat Jul 04 19:11:41 2015 -0700 summary: Documentation fixes for 3.5.0b3. files: Doc/tools/susp-ignored.csv | 3 ++- Lib/pydoc_data/topics.py | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -163,7 +163,6 @@ library/pyexpat,,:elem1, library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/smtplib,,:port,method must support that as well as a regular host:port -library/socket,,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" library/socket,,:len,fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) @@ -290,3 +289,5 @@ library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a" library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing" library/stdtypes,3767,::,>>> m[::2].tolist() +library/sys,1115,`,# `wrapper` creates a `wrap(coro)` coroutine: +tutorial/venv,77,:c7b9645a6f35,"Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)" 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 May 30 16:57:51 2015 +# Autogenerated by Sphinx on Sat Jul 4 19:11:05 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -18,8 +18,8 @@ 'callable-types': u'\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n', 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n', - 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', - 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*.) "await" expressions, "async for" and "async\nwith" can only be used in their bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in coroutines.\n\nNew in version 3.5.\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nNew in version 3.5.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nNew in version 3.5.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and "{2,3}" are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', + 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\nHowever, to simplify the parser, these keywords cannot be used on the\nsame line as a function or coroutine ("def" statement) header.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', 'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works as follows:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string as a\nleft argument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', @@ -42,7 +42,7 @@ 'if': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', 'imaginary': u'\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules are\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause, loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is stored in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe wild card form of import --- "from module import *" --- is only\nallowed at the module level. Attempting to use it in class or\nfunction definitions will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine dynamically the modules to be loaded.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python where the feature\nbecomes standard.\n\nThe future statement is intended to ease migration to future versions\nof Python that introduce incompatible changes to the language. It\nallows use of the new features on a per-module basis before the\nrelease in which the feature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', - 'in': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', + 'in': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and "{2,3}" are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', 'integers': u'\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0xdeadbeef\n', 'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) are used to create\nanonymous functions. The expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n', @@ -66,9 +66,9 @@ 'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription\n(lists or dictionaries for example). User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', 'try': u'\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods\n should return this value if they do not implement the operation for\n the operands provided. (The interpreter will then try the\n reflected operation, or some other fallback, depending on the\n operator.) Its truth value is true.\n\n See *Implementing the arithmetic operations* for more details.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode code\n points. All the code points in the range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "char"\n type; instead, every code point in the string is represented\n as a string object with length "1". The built-in function\n "ord()" converts a code point from its string form to an\n integer in the range "0 - 10FFFF"; "chr()" converts an\n integer in the range "0 - 10FFFF" to the corresponding length\n "1" string object. "str.encode()" can be used to convert a\n "str" to "bytes" using the given text encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable; not inherited by | |\n | | subclasses | |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value | |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | | contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | and "\'return\'" for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Coroutine functions\n A function or method which is defined using "async def" is\n called a *coroutine function*. Such a function, when called,\n returns a *coroutine* object. It may contain "await"\n expressions, as well as "async with" and "async for" statements.\n See also *Coroutines* section.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Frame objects support one method:\n\n frame.clear()\n\n This method clears all references to local variables held by\n the frame. Also, if the frame belonged to a generator, the\n generator is finalized. This helps break reference cycles\n involving frame objects (for example when catching an\n exception and storing its traceback for later use).\n\n "RuntimeError" is raised if the frame is currently executing.\n\n New in version 3.4.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by "sys.exc_info()". When the program contains no\n suitable handler, the stack trace is written (nicely formatted)\n to the standard error stream; if the interpreter is interactive,\n it is also made available to the user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in the\n stack trace (towards the frame where the exception occurred), or\n "None" if there is no next level; "tb_frame" points to the\n execution frame of the current level; "tb_lineno" gives the line\n number where the exception occurred; "tb_lasti" indicates the\n precise instruction. The line number and last instruction in\n the traceback may differ from the line number of its frame\n object if the exception occurred in a "try" statement with no\n matching except clause or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', + 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods\n should return this value if they do not implement the operation for\n the operands provided. (The interpreter will then try the\n reflected operation, or some other fallback, depending on the\n operator.) Its truth value is true.\n\n See *Implementing the arithmetic operations* for more details.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode code\n points. All the code points in the range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "char"\n type; instead, every code point in the string is represented\n as a string object with length "1". The built-in function\n "ord()" converts a code point from its string form to an\n integer in the range "0 - 10FFFF"; "chr()" converts an\n integer in the range "0 - 10FFFF" to the corresponding length\n "1" string object. "str.encode()" can be used to convert a\n "str" to "bytes" using the given text encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable; not inherited by | |\n | | subclasses | |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value | |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | | contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | and "\'return\'" for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Coroutine functions\n A function or method which is defined using "async def" is\n called a *coroutine function*. Such a function, when called,\n returns a *coroutine* object. It may contain "await"\n expressions, as well as "async with" and "async for" statements.\n See also the *Coroutine Objects* section.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Frame objects support one method:\n\n frame.clear()\n\n This method clears all references to local variables held by\n the frame. Also, if the frame belonged to a generator, the\n generator is finalized. This helps break reference cycles\n involving frame objects (for example when catching an\n exception and storing its traceback for later use).\n\n "RuntimeError" is raised if the frame is currently executing.\n\n New in version 3.4.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by "sys.exc_info()". When the program contains no\n suitable handler, the stack trace is written (nicely formatted)\n to the standard error stream; if the interpreter is interactive,\n it is also made available to the user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in the\n stack trace (towards the frame where the exception occurred), or\n "None" if there is no next level; "tb_frame" points to the\n execution frame of the current level; "tb_lineno" gives the line\n number where the exception occurred; "tb_lasti" indicates the\n precise instruction. The line number and last instruction in\n the traceback may differ from the line number of its frame\n object if the exception occurred in a "try" statement with no\n matching except clause or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', 'typesfunctions': u'\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', - 'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()" and *key*\n is not present, the "d[key]" operation calls that method with\n the key *key* as argument. The "d[key]" operation then returns\n or raises whatever is returned or raised by the\n "__missing__(key)" call. No other operations or methods invoke\n "__missing__()". If "__missing__()" is not defined, "KeyError"\n is raised. "__missing__()" must be a method; it cannot be an\n instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n The example above shows part of the implementation of\n "collections.Counter". A different "__missing__" method is used\n by "collections.defaultdict".\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', + 'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()" and *key*\n is not present, the "d[key]" operation calls that method with\n the key *key* as argument. The "d[key]" operation then returns\n or raises whatever is returned or raised by the\n "__missing__(key)" call. No other operations or methods invoke\n "__missing__()". If "__missing__()" is not defined, "KeyError"\n is raised. "__missing__()" must be a method; it cannot be an\n instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n The example above shows part of the implementation of\n "collections.Counter". A different "__missing__" method is used\n by "collections.defaultdict".\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\n Dictionaries compare equal if and only if they have the same "(key,\n value)" pairs. Order comparisons (\'<\', \'<=\', \'>=\', \'>\') raise\n "TypeError".\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', 'typesmethods': u'\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the "self"\nargument to the argument list. Bound methods have two special read-\nonly attributes: "m.__self__" is the object on which the method\noperates, and "m.__func__" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)".\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.__func__"), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an "AttributeError" being raised. In\norder to set a method attribute, you need to explicitly set it on the\nunderlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', 'typesmodules': u'\nModules\n*******\n\nThe only special operation on a module is attribute access: "m.name",\nwhere *m* is a module and *name* accesses a name defined in *m*\'s\nsymbol table. Module attributes can be assigned to. (Note that the\n"import" statement is not, strictly speaking, an operation on a module\nobject; "import foo" does not require a module object named *foo* to\nexist, rather it requires an (external) *definition* for a module\nnamed *foo* somewhere.)\n\nA special attribute of every module is "__dict__". This is the\ndictionary containing the module\'s symbol table. Modifying this\ndictionary will actually change the module\'s symbol table, but direct\nassignment to the "__dict__" attribute is not possible (you can write\n"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but you can\'t\nwrite "m.__dict__ = {}"). Modifying "__dict__" directly is not\nrecommended.\n\nModules built into the interpreter are written like this: "". If loaded from a file, they are written as\n"".\n', 'typesseq': u'\nSequence Types --- "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.\nIn the table, *s* and *t* are sequences of the same type, *n*, *i*,\n*j* and *k* are integers and *x* is an arbitrary object that meets any\ntype and value restrictions 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| | 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\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| "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" (same | (5) |\n| | 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\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', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 20:18:39 2015 From: python-checkins at python.org (ned.deily) Date: Sun, 05 Jul 2015 18:18:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge_3=2E5=2E0b3_changes_from_3=2E5?= Message-ID: <20150705181839.4356.93433@psf.io> https://hg.python.org/cpython/rev/6905a7f8c7ac changeset: 96836:6905a7f8c7ac parent: 96830:a4be0cab2e24 parent: 96835:190f25b7e799 user: Ned Deily date: Sun Jul 05 11:17:43 2015 -0700 summary: merge 3.5.0b3 changes from 3.5 files: .hgtags | 1 + Doc/tools/susp-ignored.csv | 3 ++- Misc/NEWS | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -150,3 +150,4 @@ 413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 +0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -163,7 +163,6 @@ library/pyexpat,,:elem1, library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/smtplib,,:port,method must support that as well as a regular host:port -library/socket,,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" library/socket,,:len,fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) @@ -290,3 +289,5 @@ library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a" library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing" library/stdtypes,3767,::,>>> m[::2].tolist() +library/sys,1115,`,# `wrapper` creates a `wrap(coro)` coroutine: +tutorial/venv,77,:c7b9645a6f35,"Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,13 +21,15 @@ What's New in Python 3.5.0 beta 4? ================================== -*Release date: XXXX-XX-XX* +Release date: 2015-07-26 Core and Builtins ----------------- - Issue #24569: Make PEP 448 dictionary evaluation more consistent. +- Issue #24407: Fix crash when dict is mutated while being updated. + Library ------- @@ -64,8 +66,6 @@ - Issue #19235: Add new RecursionError exception. Patch by Georg Brandl. -- Issue #24407: Fix crash when dict is mutated while being updated. - Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 20:46:37 2015 From: python-checkins at python.org (ned.deily) Date: Sun, 05 Jul 2015 18:46:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NTQw?= =?utf-8?q?=3A_fix_typo_in_json=2Edumps_docstring?= Message-ID: <20150705184636.20378.86312@psf.io> https://hg.python.org/cpython/rev/0deca75537ec changeset: 96838:0deca75537ec branch: 3.4 parent: 96815:725131a5f6cf user: Ned Deily date: Sun Jul 05 11:45:01 2015 -0700 summary: Issue #24540: fix typo in json.dumps docstring files: Lib/json/__init__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -184,7 +184,7 @@ default=None, sort_keys=False, **kw): """Serialize ``obj`` to a JSON formatted ``str``. - If ``skipkeys`` is false then ``dict`` keys that are not basic types + If ``skipkeys`` is true then ``dict`` keys that are not basic types (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 20:46:36 2015 From: python-checkins at python.org (ned.deily) Date: Sun, 05 Jul 2015 18:46:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NTQw?= =?utf-8?q?=3A_fix_typo_in_json=2Edumps_docstring?= Message-ID: <20150705184636.89409.83232@psf.io> https://hg.python.org/cpython/rev/803520a8db94 changeset: 96837:803520a8db94 branch: 2.7 parent: 96829:756876e059cb user: Ned Deily date: Sun Jul 05 11:43:59 2015 -0700 summary: Issue #24540: fix typo in json.dumps docstring files: Lib/json/__init__.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -195,10 +195,11 @@ encoding='utf-8', default=None, sort_keys=False, **kw): """Serialize ``obj`` to a JSON formatted ``str``. - If ``skipkeys`` is false then ``dict`` keys that are not basic types + If ``skipkeys`` is true then ``dict`` keys that are not basic types (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. + If ``ensure_ascii`` is false, all non-ASCII characters are not escaped, and the return value may be a ``unicode`` instance. See ``dump`` for details. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 20:46:37 2015 From: python-checkins at python.org (ned.deily) Date: Sun, 05 Jul 2015 18:46:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324540=3A_merger_from_3=2E4?= Message-ID: <20150705184637.86787.57478@psf.io> https://hg.python.org/cpython/rev/038b4f61d9b7 changeset: 96839:038b4f61d9b7 branch: 3.5 parent: 96835:190f25b7e799 parent: 96838:0deca75537ec user: Ned Deily date: Sun Jul 05 11:45:31 2015 -0700 summary: Issue #24540: merger from 3.4 files: Lib/json/__init__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -184,7 +184,7 @@ default=None, sort_keys=False, **kw): """Serialize ``obj`` to a JSON formatted ``str``. - If ``skipkeys`` is false then ``dict`` keys that are not basic types + If ``skipkeys`` is true then ``dict`` keys that are not basic types (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 5 20:46:37 2015 From: python-checkins at python.org (ned.deily) Date: Sun, 05 Jul 2015 18:46:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324540=3A_merger_from_3=2E5?= Message-ID: <20150705184637.48009.9677@psf.io> https://hg.python.org/cpython/rev/55755b2079fb changeset: 96840:55755b2079fb parent: 96836:6905a7f8c7ac parent: 96839:038b4f61d9b7 user: Ned Deily date: Sun Jul 05 11:46:12 2015 -0700 summary: Issue #24540: merger from 3.5 files: Lib/json/__init__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -184,7 +184,7 @@ default=None, sort_keys=False, **kw): """Serialize ``obj`` to a JSON formatted ``str``. - If ``skipkeys`` is false then ``dict`` keys that are not basic types + If ``skipkeys`` is true then ``dict`` keys that are not basic types (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 01:06:15 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 05 Jul 2015 23:06:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Change_add/contains/discar?= =?utf-8?q?d_calls_to_pass_the_key_and_hash_instead_of_an_entry?= Message-ID: <20150705230615.26537.40002@psf.io> https://hg.python.org/cpython/rev/8701abeeb674 changeset: 96841:8701abeeb674 user: Raymond Hettinger date: Sun Jul 05 16:06:10 2015 -0700 summary: Change add/contains/discard calls to pass the key and hash instead of an entry struct. files: Objects/setobject.c | 94 ++++++++++++++------------------ 1 files changed, 42 insertions(+), 52 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -127,7 +127,7 @@ static int set_table_resize(PySetObject *, Py_ssize_t); static int -set_add_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) +set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; setentry *freeslot; @@ -162,7 +162,7 @@ if (cmp < 0) /* unlikely */ return -1; if (table != so->table || entry->key != startkey) /* unlikely */ - return set_add_key_hash(so, key, hash); + return set_add_entry(so, key, hash); if (cmp > 0) /* likely */ goto found_active; mask = so->mask; /* help avoid a register spill */ @@ -190,7 +190,7 @@ if (cmp < 0) return -1; if (table != so->table || entry->key != startkey) - return set_add_key_hash(so, key, hash); + return set_add_entry(so, key, hash); if (cmp > 0) goto found_active; mask = so->mask; @@ -366,12 +366,6 @@ } static int -set_add_entry(PySetObject *so, setentry *entry) -{ - return set_add_key_hash(so, entry->key, entry->hash); -} - -static int set_add_key(PySetObject *so, PyObject *key) { Py_hash_t hash; @@ -382,14 +376,14 @@ if (hash == -1) return -1; } - return set_add_key_hash(so, key, hash); + return set_add_entry(so, key, hash); } #define DISCARD_NOTFOUND 0 #define DISCARD_FOUND 1 static int -set_discard_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) +set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *entry; PyObject *old_key; @@ -408,12 +402,6 @@ } static int -set_discard_entry(PySetObject *so, setentry *entry) -{ - return set_discard_key_hash(so, entry->key, entry->hash); -} - -static int set_discard_key(PySetObject *so, PyObject *key) { Py_hash_t hash; @@ -426,7 +414,7 @@ if (hash == -1) return -1; } - return set_discard_key_hash(so, key, hash); + return set_discard_entry(so, key, hash); } static void @@ -658,7 +646,7 @@ for (i = 0; i <= other->mask; i++, other_entry++) { key = other_entry->key; if (key != NULL && key != dummy) { - if (set_add_key_hash(so, key, other_entry->hash)) + if (set_add_entry(so, key, other_entry->hash)) return -1; } } @@ -666,7 +654,7 @@ } static int -set_contains_key_hash(PySetObject *so, PyObject *key, Py_hash_t hash) +set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *lu_entry; @@ -677,12 +665,6 @@ } static int -set_contains_entry(PySetObject *so, setentry *entry) -{ - return set_contains_key_hash(so, entry->key, entry->hash); -} - -static int set_contains_key(PySetObject *so, PyObject *key) { setentry *entry; @@ -976,7 +958,7 @@ return -1; } while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - if (set_add_key_hash(so, key, hash)) + if (set_add_entry(so, key, hash)) return -1; } return 0; @@ -1256,6 +1238,8 @@ { PySetObject *result; PyObject *key, *it, *tmp; + Py_hash_t hash; + int rv; if ((PyObject *)so == other) return set_copy(so); @@ -1275,13 +1259,15 @@ } while (set_next((PySetObject *)other, &pos, &entry)) { - int rv = set_contains_entry(so, entry); + key = entry->key; + hash = entry->hash; + rv = set_contains_entry(so, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (rv) { - if (set_add_entry(result, entry)) { + if (set_add_entry(result, key, hash)) { Py_DECREF(result); return NULL; } @@ -1297,16 +1283,14 @@ } while ((key = PyIter_Next(it)) != NULL) { - int rv; - Py_hash_t hash = PyObject_Hash(key); - + hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); return NULL; } - rv = set_contains_key_hash(so, key, hash); + rv = set_contains_entry(so, key, hash); if (rv < 0) { Py_DECREF(it); Py_DECREF(result); @@ -1314,7 +1298,7 @@ return NULL; } if (rv) { - if (set_add_key_hash(result, key, hash)) { + if (set_add_entry(result, key, hash)) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); @@ -1415,6 +1399,7 @@ set_isdisjoint(PySetObject *so, PyObject *other) { PyObject *key, *it, *tmp; + int rv; if ((PyObject *)so == other) { if (PySet_GET_SIZE(so) == 0) @@ -1433,7 +1418,7 @@ other = tmp; } while (set_next((PySetObject *)other, &pos, &entry)) { - int rv = set_contains_entry(so, entry); + rv = set_contains_entry(so, entry->key, entry->hash); if (rv < 0) return NULL; if (rv) @@ -1447,7 +1432,6 @@ return NULL; while ((key = PyIter_Next(it)) != NULL) { - int rv; Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { @@ -1455,7 +1439,7 @@ Py_DECREF(it); return NULL; } - rv = set_contains_key_hash(so, key, hash); + rv = set_contains_entry(so, key, hash); Py_DECREF(key); if (rv < 0) { Py_DECREF(it); @@ -1486,7 +1470,7 @@ Py_ssize_t pos = 0; while (set_next((PySetObject *)other, &pos, &entry)) - if (set_discard_entry(so, entry) < 0) + if (set_discard_entry(so, entry->key, entry->hash) < 0) return -1; } else { PyObject *key, *it; @@ -1546,8 +1530,11 @@ set_difference(PySetObject *so, PyObject *other) { PyObject *result; + PyObject *key; + Py_hash_t hash; setentry *entry; Py_ssize_t pos = 0; + int rv; if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { return set_copy_and_difference(so, other); @@ -1565,16 +1552,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { - PyObject *key = entry->key; - Py_hash_t hash = entry->hash; - int rv; + key = entry->key; + hash = entry->hash; rv = _PyDict_Contains(other, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (!rv) { - if (set_add_key_hash((PySetObject *)result, key, hash)) { + if (set_add_entry((PySetObject *)result, key, hash)) { Py_DECREF(result); return NULL; } @@ -1585,13 +1571,15 @@ /* Iterate over so, checking for common elements in other. */ while (set_next(so, &pos, &entry)) { - int rv = set_contains_entry((PySetObject *)other, entry); + key = entry->key; + hash = entry->hash; + rv = set_contains_entry((PySetObject *)other, key, hash); if (rv < 0) { Py_DECREF(result); return NULL; } if (!rv) { - if (set_add_entry((PySetObject *)result, entry)) { + if (set_add_entry((PySetObject *)result, key, hash)) { Py_DECREF(result); return NULL; } @@ -1653,25 +1641,24 @@ PySetObject *otherset; PyObject *key; Py_ssize_t pos = 0; + Py_hash_t hash; setentry *entry; + int rv; if ((PyObject *)so == other) return set_clear(so); if (PyDict_CheckExact(other)) { PyObject *value; - int rv; - Py_hash_t hash; while (_PyDict_Next(other, &pos, &key, &value, &hash)) { Py_INCREF(key); - - rv = set_discard_key_hash(so, key, hash); + rv = set_discard_entry(so, key, hash); if (rv < 0) { Py_DECREF(key); return NULL; } if (rv == DISCARD_NOTFOUND) { - if (set_add_key_hash(so, key, hash)) { + if (set_add_entry(so, key, hash)) { Py_DECREF(key); return NULL; } @@ -1691,13 +1678,15 @@ } while (set_next(otherset, &pos, &entry)) { - int rv = set_discard_entry(so, entry); + key = entry->key; + hash = entry->hash; + rv = set_discard_entry(so, key, hash); if (rv < 0) { Py_DECREF(otherset); return NULL; } if (rv == DISCARD_NOTFOUND) { - if (set_add_entry(so, entry)) { + if (set_add_entry(so, key, hash)) { Py_DECREF(otherset); return NULL; } @@ -1759,6 +1748,7 @@ { setentry *entry; Py_ssize_t pos = 0; + int rv; if (!PyAnySet_Check(other)) { PyObject *tmp, *result; @@ -1773,7 +1763,7 @@ Py_RETURN_FALSE; while (set_next(so, &pos, &entry)) { - int rv = set_contains_entry((PySetObject *)other, entry); + rv = set_contains_entry((PySetObject *)other, entry->key, entry->hash); if (rv < 0) return NULL; if (!rv) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 01:27:49 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 05 Jul 2015 23:27:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Bring_related_functions_ad?= =?utf-8?q?d/contains/discard_together_in_the_code=2E?= Message-ID: <20150705232749.84918.53139@psf.io> https://hg.python.org/cpython/rev/afba0ea40e5a changeset: 96842:afba0ea40e5a user: Raymond Hettinger date: Sun Jul 05 16:27:44 2015 -0700 summary: Bring related functions add/contains/discard together in the code. files: Objects/setobject.c | 74 +++++++++++++++----------------- 1 files changed, 34 insertions(+), 40 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -366,17 +366,14 @@ } static int -set_add_key(PySetObject *so, PyObject *key) +set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { - Py_hash_t hash; + setentry *entry; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - return set_add_entry(so, key, hash); + entry = set_lookkey(so, key, hash); + if (entry != NULL) + return entry->key != NULL; + return -1; } #define DISCARD_NOTFOUND 0 @@ -402,12 +399,38 @@ } static int +set_add_key(PySetObject *so, PyObject *key) +{ + Py_hash_t hash; + + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + return set_add_entry(so, key, hash); +} + +static int +set_contains_key(PySetObject *so, PyObject *key) +{ + Py_hash_t hash; + + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + return set_contains_entry(so, key, hash); +} + +static int set_discard_key(PySetObject *so, PyObject *key) { Py_hash_t hash; - assert (PyAnySet_Check(so)); - if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { hash = PyObject_Hash(key); @@ -653,35 +676,6 @@ return 0; } -static int -set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash) -{ - setentry *lu_entry; - - lu_entry = set_lookkey(so, key, hash); - if (lu_entry != NULL) - return lu_entry->key != NULL; - return -1; -} - -static int -set_contains_key(PySetObject *so, PyObject *key) -{ - setentry *entry; - Py_hash_t hash; - - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - entry = set_lookkey(so, key, hash); - if (entry == NULL) - return -1; - return entry->key != NULL; -} - static PyObject * set_pop(PySetObject *so) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 02:45:18 2015 From: python-checkins at python.org (nick.coghlan) Date: Mon, 06 Jul 2015 00:45:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_simplify_detection?= =?utf-8?q?_of_the_capability?= Message-ID: <20150706004516.46013.46992@psf.io> https://hg.python.org/peps/rev/5f8f19025e19 changeset: 5902:5f8f19025e19 user: Nick Coghlan date: Mon Jul 06 10:45:09 2015 +1000 summary: PEP 493: simplify detection of the capability files: pep-0493.txt | 75 ++++++++++++++++++++++++++++++++------- 1 files changed, 61 insertions(+), 14 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -72,6 +72,25 @@ Foundation or by a redistributor). +Requirements for capability detection +===================================== + +As these recommendations are intended to cover backports to earlier Python +versions, the Python version number cannot be used as a reliable means for +detecting them. Instead, the recommendations are defined to allow the presence +or absence of the feature to be determined using the following technique:: + + python -c "import ssl; ssl._relevant_attribute" + +This will fail with `AttributeError` (and hence a non-zero return code) if the +relevant capability is not available. + +The marker attributes are prefixed with an underscore to indicate the +implementation dependent nature of these capabilities - not all Python +distributions will offer them, only those that are providing a multi-stage +migration process from the legacy HTTPS handling to the new default behaviour. + + Recommendation for an environment variable based security downgrade =================================================================== @@ -91,6 +110,19 @@ including those that advertise themselves as providing Python 2.7.9 or later. +Required marker attribute +------------------------- + +The required marker attribute on the ``ssl`` module when implementing this +recommendation is:: + + _https_verify_envvar = 'PYTHONHTTPSVERIFY' + +This not only makes it straightforward to detect the presence (or absence) of +the capability, it also makes it possible to programmatically determine the +relevant environment variable name. + + Recommended modifications to the Python standard library -------------------------------------------------------- @@ -112,8 +144,10 @@ :: + _https_verify_envvar = 'PYTHONHTTPSVERIFY' + def _get_https_context_factory(): - config_setting = os.environ.get('PYTHONHTTPSVERIFY') + config_setting = os.environ.get(_https_verify_envvar) if config_setting == '0': return _create_unverified_context return create_default_context @@ -128,13 +162,10 @@ does introduce a new downgrade attack against the default security settings that potentially allows a sufficiently determined attacker to revert Python to the vulnerable configuration used in CPython 2.7.8 and earlier releases. -Such an attack requires the ability to modify the execution environment of -a Python process prior to the import of the ``ssl`` module. - -Redistributors should balance this marginal increase in risk against the -ability to offer a smoother migration path to their users when deciding whether -or not it is appropriate for them to implement this per-application "opt out" -model. +However, such an attack requires the ability to modify the execution +environment of a Python process prior to the import of the ``ssl`` module, +and any attacker with such access would already be able to modify the +behaviour of the underlying OpenSSL implementation. Recommendation for backporting to earlier Python versions @@ -161,6 +192,19 @@ certificates by default. +Required marker attribute +------------------------- + +The required marker attribute on the ``ssl`` module when implementing this +recommendation is:: + + _cert_verification_config = '' + +This not only makes it straightforward to detect the presence (or absence) of +the capability, it also makes it possible to programmatically determine the +relevant configuration file name. + + Recommended modifications to the Python standard library -------------------------------------------------------- @@ -218,9 +262,10 @@ :: + _cert_verification_config = '/etc/python/cert-verification.cfg' + def _get_https_context_factory(): # Check for a system-wide override of the default behaviour - config_file = '/etc/python/cert-verification.cfg' context_factories = { 'enable': create_default_context, 'disable': _create_unverified_context, @@ -228,7 +273,7 @@ } import ConfigParser config = ConfigParser.RawConfigParser() - config.read(config_file) + config.read(_cert_verification_config) try: verify_mode = config.get('https', 'verify') except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): @@ -268,7 +313,7 @@ (at least for the time being) Using an administrator controlled configuration file rather than an environment -variable has the essential feature of providing a smoother migraiton path, even +variable has the essential feature of providing a smoother migration path, even for applications being run with the ``-E`` switch. @@ -289,16 +334,18 @@ :: + _https_verify_envvar = 'PYTHONHTTPSVERIFY' + _cert_verification_config = '/etc/python/cert-verification.cfg' + def _get_https_context_factory(): # Check for am environmental override of the default behaviour - config_setting = os.environ.get('PYTHONHTTPSVERIFY') + config_setting = os.environ.get(_https_verify_envvar) if config_setting is not None: if config_setting == '0': return _create_unverified_context return create_default_context # Check for a system-wide override of the default behaviour - config_file = '/etc/python/cert-verification.cfg' context_factories = { 'enable': create_default_context, 'disable': _create_unverified_context, @@ -306,7 +353,7 @@ } import ConfigParser config = ConfigParser.RawConfigParser() - config.read(config_file) + config.read(_cert_verification_config) try: verify_mode = config.get('https', 'verify') except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Jul 6 05:55:14 2015 From: python-checkins at python.org (nick.coghlan) Date: Mon, 06 Jul 2015 03:55:14 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_Add_post_date?= Message-ID: <20150706035513.86638.95247@psf.io> https://hg.python.org/peps/rev/3578d137e5e3 changeset: 5903:3578d137e5e3 user: Nick Coghlan date: Mon Jul 06 13:55:05 2015 +1000 summary: PEP 493: Add post date files: pep-0493.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -7,6 +7,7 @@ Type: Informational Content-Type: text/x-rst Created: 10-May-2015 +Posted: 06-Jul-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Jul 6 06:01:03 2015 From: python-checkins at python.org (nick.coghlan) Date: Mon, 06 Jul 2015 04:01:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_Credit_MAL_as_a_co?= =?utf-8?q?-author=2C_fix_headers?= Message-ID: <20150706040103.97044.20473@psf.io> https://hg.python.org/peps/rev/5a7affe76e1f changeset: 5904:5a7affe76e1f user: Nick Coghlan date: Mon Jul 06 14:00:55 2015 +1000 summary: PEP 493: Credit MAL as a co-author, fix headers files: pep-0493.txt | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -2,12 +2,14 @@ Title: HTTPS verification recommendations for Python 2.7 redistributors Version: $Revision$ Last-Modified: $Date$ -Author: Nick Coghlan , Robert Kuska +Author: Nick Coghlan , + Robert Kuska , + Marc-Andr? Lemburg Status: Draft Type: Informational Content-Type: text/x-rst Created: 10-May-2015 -Posted: 06-Jul-2015 +Post-History: 06-Jul-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Jul 6 07:08:26 2015 From: python-checkins at python.org (zach.ware) Date: Mon, 06 Jul 2015 05:08:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_Docs/to?= =?utf-8?q?ols/susp-ignored=2Ecsv?= Message-ID: <20150706050826.12463.84768@psf.io> https://hg.python.org/cpython/rev/79ed3573b977 changeset: 96843:79ed3573b977 branch: 2.7 parent: 96837:803520a8db94 user: Zachary Ware date: Mon Jul 06 00:08:15 2015 -0500 summary: Update Docs/tools/susp-ignored.csv files: Doc/tools/susp-ignored.csv | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -102,7 +102,6 @@ library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/smtplib,,:port,method must support that as well as a regular host:port library/socket,,::,'5aef:2b::8' -library/socket,,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" library/sqlite3,,:memory, library/sqlite3,,:who,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})" library/sqlite3,,:age,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})" @@ -128,6 +127,16 @@ library/urllib2,,:password,"""joe:password at python.org""" library/urllib2,,:close,Connection:close library/uuid,,:uuid,urn:uuid:12345678-1234-5678-1234-567812345678 +library/xml.etree.elementtree,,:sometag,prefix:sometag +library/xml.etree.elementtree,,:fictional,"Lancelot +library/xml.etree.elementtree,,:character,Archie Leach +library/xml.etree.elementtree,,:character,Sir Robin +library/xml.etree.elementtree,,:character,Gunther +library/xml.etree.elementtree,,:character,Commander Clement +library/xml.etree.elementtree,,:actor,"for actor in root.findall('real_person:actor', ns):" +library/xml.etree.elementtree,,:name,"name = actor.find('real_person:name', ns)" +library/xml.etree.elementtree,,:character,"for char in actor.findall('role:character', ns):" library/xmlrpclib,,:pass,http://user:pass at host:port/path library/xmlrpclib,,:pass,user:pass library/xmlrpclib,,:port,http://user:pass at host:port/path @@ -179,8 +188,8 @@ whatsnew/2.5,,:memory,:memory: whatsnew/2.5,,:step,[start:stop:step] whatsnew/2.5,,:stop,[start:stop:step] -whatsnew/2.7,735,:Sunday,'2009:4:Sunday' -whatsnew/2.7,862,::,"export PYTHONWARNINGS=all,error:::Cookie:0" -whatsnew/2.7,862,:Cookie,"export PYTHONWARNINGS=all,error:::Cookie:0" +whatsnew/2.7,,:Sunday,'2009:4:Sunday' +whatsnew/2.7,,::,"export PYTHONWARNINGS=all,error:::Cookie:0" +whatsnew/2.7,,:Cookie,"export PYTHONWARNINGS=all,error:::Cookie:0" whatsnew/2.7,,::,>>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo') whatsnew/2.7,,::,"ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]'," -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 09:33:11 2015 From: python-checkins at python.org (lars.gustaebel) Date: Mon, 06 Jul 2015 07:33:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MjU5?= =?utf-8?q?=3A_tarfile_now_raises_a_ReadError_if_an_archive_is_truncated_i?= =?utf-8?q?nside?= Message-ID: <20150706073310.30651.74344@psf.io> https://hg.python.org/cpython/rev/372aa98eb72e changeset: 96844:372aa98eb72e branch: 2.7 user: Lars Gust?bel date: Mon Jul 06 09:23:04 2015 +0200 summary: Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. files: Lib/tarfile.py | 17 ++++++++++++++--- Lib/test/test_tarfile.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -744,12 +744,18 @@ else: return self.readsparse(size) + def __read(self, size): + buf = self.fileobj.read(size) + if len(buf) != size: + raise ReadError("unexpected end of data") + return buf + def readnormal(self, size): """Read operation for regular files. """ self.fileobj.seek(self.offset + self.position) self.position += size - return self.fileobj.read(size) + return self.__read(size) def readsparse(self, size): """Read operation for sparse files. @@ -777,7 +783,7 @@ realpos = section.realpos + self.position - section.offset self.fileobj.seek(self.offset + realpos) self.position += size - return self.fileobj.read(size) + return self.__read(size) else: self.position += size return NUL * size @@ -2336,8 +2342,13 @@ self.firstmember = None return m + # Advance the file pointer. + if self.offset != self.fileobj.tell(): + self.fileobj.seek(self.offset - 1) + if not self.fileobj.read(1): + raise ReadError("unexpected end of data") + # Read the next block. - self.fileobj.seek(self.offset) tarinfo = None while True: try: 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 @@ -285,6 +285,30 @@ "ignore_zeros=True should have skipped the %r-blocks" % char) tar.close() + def test_premature_end_of_archive(self): + for size in (512, 600, 1024, 1200): + with tarfile.open(tmpname, "w:") as tar: + t = tarfile.TarInfo("foo") + t.size = 1024 + tar.addfile(t, StringIO.StringIO("a" * 1024)) + + with open(tmpname, "r+b") as fobj: + fobj.truncate(size) + + with tarfile.open(tmpname) as tar: + with self.assertRaisesRegexp(tarfile.ReadError, "unexpected end of data"): + for t in tar: + pass + + with tarfile.open(tmpname) as tar: + t = tar.next() + + with self.assertRaisesRegexp(tarfile.ReadError, "unexpected end of data"): + tar.extract(t, TEMPDIR) + + with self.assertRaisesRegexp(tarfile.ReadError, "unexpected end of data"): + tar.extractfile(t).read() + class MiscReadTest(CommonReadTest): taropen = tarfile.TarFile.taropen diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #24259: tarfile now raises a ReadError if an archive is truncated + inside a data segment. + - Issue #24514: tarfile now tolerates number fields consisting of only whitespace. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 09:33:11 2015 From: python-checkins at python.org (lars.gustaebel) Date: Mon, 06 Jul 2015 07:33:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4=3A_Issue_=2324259=3A_tarfile_now_raises_a_Rea?= =?utf-8?q?dError_if_an_archive_is?= Message-ID: <20150706073310.20885.50842@psf.io> https://hg.python.org/cpython/rev/59cbdc9eb3d9 changeset: 96846:59cbdc9eb3d9 branch: 3.5 parent: 96839:038b4f61d9b7 parent: 96845:c7f4f61697b7 user: Lars Gust?bel date: Mon Jul 06 09:29:41 2015 +0200 summary: Merge with 3.4: Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. files: Lib/tarfile.py | 22 +++++++++++++++------- Lib/test/test_tarfile.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -225,7 +225,7 @@ signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf)) return unsigned_chksum, signed_chksum -def copyfileobj(src, dst, length=None): +def copyfileobj(src, dst, length=None, exception=OSError): """Copy length bytes from fileobj src to fileobj dst. If length is None, copy the entire content. """ @@ -240,13 +240,13 @@ for b in range(blocks): buf = src.read(BUFSIZE) if len(buf) < BUFSIZE: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) if remainder != 0: buf = src.read(remainder) if len(buf) < remainder: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) return @@ -690,7 +690,10 @@ length = min(size, stop - self.position) if data: self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) + b = self.fileobj.read(length) + if len(b) != length: + raise ReadError("unexpected end of data") + buf += b else: buf += NUL * length size -= length @@ -2150,9 +2153,9 @@ if tarinfo.sparse is not None: for offset, size in tarinfo.sparse: target.seek(offset) - copyfileobj(source, target, size) + copyfileobj(source, target, size, ReadError) else: - copyfileobj(source, target, tarinfo.size) + copyfileobj(source, target, tarinfo.size, ReadError) target.seek(tarinfo.size) target.truncate() @@ -2267,8 +2270,13 @@ self.firstmember = None return m + # Advance the file pointer. + if self.offset != self.fileobj.tell(): + self.fileobj.seek(self.offset - 1) + if not self.fileobj.read(1): + raise ReadError("unexpected end of data") + # Read the next block. - self.fileobj.seek(self.offset) tarinfo = None while True: try: 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 @@ -364,6 +364,29 @@ finally: tar.close() + def test_premature_end_of_archive(self): + for size in (512, 600, 1024, 1200): + with tarfile.open(tmpname, "w:") as tar: + t = tarfile.TarInfo("foo") + t.size = 1024 + tar.addfile(t, io.BytesIO(b"a" * 1024)) + + with open(tmpname, "r+b") as fobj: + fobj.truncate(size) + + with tarfile.open(tmpname) as tar: + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + for t in tar: + pass + + with tarfile.open(tmpname) as tar: + t = tar.next() + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extract(t, TEMPDIR) + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extractfile(t).read() class MiscReadTestBase(CommonReadTest): def requires_name_attribute(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,9 @@ Library ------- +- Issue #24259: tarfile now raises a ReadError if an archive is truncated + inside a data segment. + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 09:33:11 2015 From: python-checkins at python.org (lars.gustaebel) Date: Mon, 06 Jul 2015 07:33:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5=3A_Issue_=2324259=3A_tarfile_now_raises?= =?utf-8?q?_a_ReadError_if_an_archive_is?= Message-ID: <20150706073311.8446.90869@psf.io> https://hg.python.org/cpython/rev/6be8fa47c002 changeset: 96847:6be8fa47c002 parent: 96842:afba0ea40e5a parent: 96846:59cbdc9eb3d9 user: Lars Gust?bel date: Mon Jul 06 09:32:05 2015 +0200 summary: Merge with 3.5: Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. files: Lib/tarfile.py | 22 +++++++++++++++------- Lib/test/test_tarfile.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -225,7 +225,7 @@ signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf)) return unsigned_chksum, signed_chksum -def copyfileobj(src, dst, length=None): +def copyfileobj(src, dst, length=None, exception=OSError): """Copy length bytes from fileobj src to fileobj dst. If length is None, copy the entire content. """ @@ -240,13 +240,13 @@ for b in range(blocks): buf = src.read(BUFSIZE) if len(buf) < BUFSIZE: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) if remainder != 0: buf = src.read(remainder) if len(buf) < remainder: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) return @@ -690,7 +690,10 @@ length = min(size, stop - self.position) if data: self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) + b = self.fileobj.read(length) + if len(b) != length: + raise ReadError("unexpected end of data") + buf += b else: buf += NUL * length size -= length @@ -2150,9 +2153,9 @@ if tarinfo.sparse is not None: for offset, size in tarinfo.sparse: target.seek(offset) - copyfileobj(source, target, size) + copyfileobj(source, target, size, ReadError) else: - copyfileobj(source, target, tarinfo.size) + copyfileobj(source, target, tarinfo.size, ReadError) target.seek(tarinfo.size) target.truncate() @@ -2267,8 +2270,13 @@ self.firstmember = None return m + # Advance the file pointer. + if self.offset != self.fileobj.tell(): + self.fileobj.seek(self.offset - 1) + if not self.fileobj.read(1): + raise ReadError("unexpected end of data") + # Read the next block. - self.fileobj.seek(self.offset) tarinfo = None while True: try: 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 @@ -364,6 +364,29 @@ finally: tar.close() + def test_premature_end_of_archive(self): + for size in (512, 600, 1024, 1200): + with tarfile.open(tmpname, "w:") as tar: + t = tarfile.TarInfo("foo") + t.size = 1024 + tar.addfile(t, io.BytesIO(b"a" * 1024)) + + with open(tmpname, "r+b") as fobj: + fobj.truncate(size) + + with tarfile.open(tmpname) as tar: + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + for t in tar: + pass + + with tarfile.open(tmpname) as tar: + t = tar.next() + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extract(t, TEMPDIR) + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extractfile(t).read() class MiscReadTestBase(CommonReadTest): def requires_name_attribute(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,9 @@ Library ------- +- Issue #24259: tarfile now raises a ReadError if an archive is truncated + inside a data segment. + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 09:33:11 2015 From: python-checkins at python.org (lars.gustaebel) Date: Mon, 06 Jul 2015 07:33:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjU5?= =?utf-8?q?=3A_tarfile_now_raises_a_ReadError_if_an_archive_is_truncated_i?= =?utf-8?q?nside?= Message-ID: <20150706073310.31722.38618@psf.io> https://hg.python.org/cpython/rev/c7f4f61697b7 changeset: 96845:c7f4f61697b7 branch: 3.4 parent: 96838:0deca75537ec user: Lars Gust?bel date: Mon Jul 06 09:27:24 2015 +0200 summary: Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. files: Lib/tarfile.py | 22 +++++++++++++++------- Lib/test/test_tarfile.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -225,7 +225,7 @@ signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf)) return unsigned_chksum, signed_chksum -def copyfileobj(src, dst, length=None): +def copyfileobj(src, dst, length=None, exception=OSError): """Copy length bytes from fileobj src to fileobj dst. If length is None, copy the entire content. """ @@ -240,13 +240,13 @@ for b in range(blocks): buf = src.read(BUFSIZE) if len(buf) < BUFSIZE: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) if remainder != 0: buf = src.read(remainder) if len(buf) < remainder: - raise OSError("end of file reached") + raise exception("unexpected end of data") dst.write(buf) return @@ -690,7 +690,10 @@ length = min(size, stop - self.position) if data: self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) + b = self.fileobj.read(length) + if len(b) != length: + raise ReadError("unexpected end of data") + buf += b else: buf += NUL * length size -= length @@ -2132,9 +2135,9 @@ if tarinfo.sparse is not None: for offset, size in tarinfo.sparse: target.seek(offset) - copyfileobj(source, target, size) + copyfileobj(source, target, size, ReadError) else: - copyfileobj(source, target, tarinfo.size) + copyfileobj(source, target, tarinfo.size, ReadError) target.seek(tarinfo.size) target.truncate() @@ -2244,8 +2247,13 @@ self.firstmember = None return m + # Advance the file pointer. + if self.offset != self.fileobj.tell(): + self.fileobj.seek(self.offset - 1) + if not self.fileobj.read(1): + raise ReadError("unexpected end of data") + # Read the next block. - self.fileobj.seek(self.offset) tarinfo = None while True: try: 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 @@ -349,6 +349,29 @@ finally: tar.close() + def test_premature_end_of_archive(self): + for size in (512, 600, 1024, 1200): + with tarfile.open(tmpname, "w:") as tar: + t = tarfile.TarInfo("foo") + t.size = 1024 + tar.addfile(t, io.BytesIO(b"a" * 1024)) + + with open(tmpname, "r+b") as fobj: + fobj.truncate(size) + + with tarfile.open(tmpname) as tar: + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + for t in tar: + pass + + with tarfile.open(tmpname) as tar: + t = tar.next() + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extract(t, TEMPDIR) + + with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): + tar.extractfile(t).read() class MiscReadTestBase(CommonReadTest): def requires_name_attribute(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #24259: tarfile now raises a ReadError if an archive is truncated + inside a data segment. + - Issue #24552: Fix use after free in an error case of the _pickle module. - Issue #24514: tarfile now tolerates number fields consisting of only -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Jul 6 10:43:51 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 06 Jul 2015 08:43:51 +0000 Subject: [Python-checkins] Daily reference leaks (afba0ea40e5a): sum=7 Message-ID: <20150706084351.86369.70785@psf.io> results for afba0ea40e5a on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghcizvG', '--timeout', '7200'] From python-checkins at python.org Mon Jul 6 13:23:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 11:23:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE4Njg0?= =?utf-8?q?=3A_Fixed_reading_out_of_the_buffer_in_the_re_module=2E?= Message-ID: <20150706112356.2656.76244@psf.io> https://hg.python.org/cpython/rev/389795b7c703 changeset: 96849:389795b7c703 branch: 3.4 parent: 96845:c7f4f61697b7 user: Serhiy Storchaka date: Mon Jul 06 13:58:33 2015 +0300 summary: Issue #18684: Fixed reading out of the buffer in the re module. files: Misc/NEWS | 2 ++ Modules/_sre.c | 26 +++++++++++++++++++++----- Modules/sre_lib.h | 29 ++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #18684: Fixed reading out of the buffer in the re module. + - Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -883,7 +883,7 @@ } if (state.start == state.ptr) { - if (last == state.end) + if (last == state.end || state.ptr == state.end) break; /* skip one character */ state.start = (void*) ((char*) state.ptr + state.charsize); @@ -1081,6 +1081,8 @@ next: /* move on */ + if (state.ptr == state.end) + break; if (state.ptr == state.start) state.start = (void*) ((char*) state.ptr + state.charsize); else @@ -2567,6 +2569,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2578,10 +2583,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } @@ -2594,6 +2603,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2605,10 +2617,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h --- a/Modules/sre_lib.h +++ b/Modules/sre_lib.h @@ -30,7 +30,7 @@ SRE_IS_LINEBREAK((int) ptr[-1])); case SRE_AT_END: - return (((void*) (ptr+1) == state->end && + return (((SRE_CHAR *)state->end - ptr == 1 && SRE_IS_LINEBREAK((int) ptr[0])) || ((void*) ptr == state->end)); @@ -1093,9 +1093,9 @@ /* */ TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); + if (ctx->ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)ctx->pattern[1]) + RETURN_FAILURE; state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr < state->beginning) - RETURN_FAILURE; DO_JUMP0(JUMP_ASSERT, jump_assert, ctx->pattern+2); RETURN_ON_FAILURE(ret); ctx->pattern += ctx->pattern[0]; @@ -1106,8 +1106,8 @@ /* */ TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); - state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr >= state->beginning) { + if (ctx->ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)ctx->pattern[1]) { + state->ptr = ctx->ptr - ctx->pattern[1]; DO_JUMP0(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2); if (ret) { RETURN_ON_ERROR(ret); @@ -1199,12 +1199,20 @@ SRE_CODE* overlap = NULL; int flags = 0; + if (ptr > end) + return 0; + if (pattern[0] == SRE_OP_INFO) { /* optimization info block */ /* <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> */ flags = pattern[2]; + if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) { + TRACE(("reject (got %u chars, need %u)\n", + (unsigned int)(end - ptr), pattern[3])); + return 0; + } if (pattern[3] > 1) { /* adjust end point (but make sure we leave at least one character in there, so literal search will work) */ @@ -1322,15 +1330,18 @@ break; ptr++; } - } else + } else { /* general case */ - while (ptr <= end) { + assert(ptr <= end); + while (1) { TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); - state->start = state->ptr = ptr++; + state->start = state->ptr = ptr; status = SRE(match)(state, pattern, 0); - if (status != 0) + if (status != 0 || ptr >= end) break; + ptr++; } + } return status; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 13:23:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 11:23:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2318684=3A_Fixed_reading_out_of_the_buffer_in_the_re_mo?= =?utf-8?q?dule=2E?= Message-ID: <20150706112356.3300.40740@psf.io> https://hg.python.org/cpython/rev/5adf995d443f changeset: 96850:5adf995d443f branch: 3.5 parent: 96846:59cbdc9eb3d9 parent: 96849:389795b7c703 user: Serhiy Storchaka date: Mon Jul 06 14:03:01 2015 +0300 summary: Issue #18684: Fixed reading out of the buffer in the re module. files: Misc/NEWS | 2 ++ Modules/_sre.c | 26 +++++++++++++++++++++----- Modules/sre_lib.h | 29 ++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ Library ------- +- Issue #18684: Fixed reading out of the buffer in the re module. + - Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -994,7 +994,7 @@ } if (state.start == state.ptr) { - if (last == state.end) + if (last == state.end || state.ptr == state.end) break; /* skip one character */ state.start = (void*) ((char*) state.ptr + state.charsize); @@ -1191,6 +1191,8 @@ next: /* move on */ + if (state.ptr == state.end) + break; if (state.ptr == state.start) state.start = (void*) ((char*) state.ptr + state.charsize); else @@ -2564,6 +2566,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2575,10 +2580,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } @@ -2597,6 +2606,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2608,10 +2620,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h --- a/Modules/sre_lib.h +++ b/Modules/sre_lib.h @@ -30,7 +30,7 @@ SRE_IS_LINEBREAK((int) ptr[-1])); case SRE_AT_END: - return (((void*) (ptr+1) == state->end && + return (((SRE_CHAR *)state->end - ptr == 1 && SRE_IS_LINEBREAK((int) ptr[0])) || ((void*) ptr == state->end)); @@ -1109,9 +1109,9 @@ /* */ TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); + if (ctx->ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)ctx->pattern[1]) + RETURN_FAILURE; state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr < state->beginning) - RETURN_FAILURE; DO_JUMP0(JUMP_ASSERT, jump_assert, ctx->pattern+2); RETURN_ON_FAILURE(ret); ctx->pattern += ctx->pattern[0]; @@ -1122,8 +1122,8 @@ /* */ TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); - state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr >= state->beginning) { + if (ctx->ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)ctx->pattern[1]) { + state->ptr = ctx->ptr - ctx->pattern[1]; DO_JUMP0(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2); if (ret) { RETURN_ON_ERROR(ret); @@ -1215,12 +1215,20 @@ SRE_CODE* overlap = NULL; int flags = 0; + if (ptr > end) + return 0; + if (pattern[0] == SRE_OP_INFO) { /* optimization info block */ /* <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> */ flags = pattern[2]; + if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) { + TRACE(("reject (got %u chars, need %u)\n", + (unsigned int)(end - ptr), pattern[3])); + return 0; + } if (pattern[3] > 1) { /* adjust end point (but make sure we leave at least one character in there, so literal search will work) */ @@ -1338,15 +1346,18 @@ break; ptr++; } - } else + } else { /* general case */ - while (ptr <= end) { + assert(ptr <= end); + while (1) { TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); - state->start = state->ptr = ptr++; + state->start = state->ptr = ptr; status = SRE(match)(state, pattern, 0); - if (status != 0) + if (status != 0 || ptr >= end) break; + ptr++; } + } return status; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 13:23:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 11:23:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2318684=3A_Fixed_reading_out_of_the_buffer_in_the?= =?utf-8?q?_re_module=2E?= Message-ID: <20150706112356.8271.70592@psf.io> https://hg.python.org/cpython/rev/bb9fc884a838 changeset: 96851:bb9fc884a838 parent: 96847:6be8fa47c002 parent: 96850:5adf995d443f user: Serhiy Storchaka date: Mon Jul 06 14:23:04 2015 +0300 summary: Issue #18684: Fixed reading out of the buffer in the re module. files: Misc/NEWS | 2 ++ Modules/_sre.c | 26 +++++++++++++++++++++----- Modules/sre_lib.h | 29 ++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,8 @@ Library ------- +- Issue #18684: Fixed reading out of the buffer in the re module. + - Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -991,7 +991,7 @@ } if (state.start == state.ptr) { - if (last == state.end) + if (last == state.end || state.ptr == state.end) break; /* skip one character */ state.start = (void*) ((char*) state.ptr + state.charsize); @@ -1188,6 +1188,8 @@ next: /* move on */ + if (state.ptr == state.end) + break; if (state.ptr == state.start) state.start = (void*) ((char*) state.ptr + state.charsize); else @@ -2561,6 +2563,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2572,10 +2577,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } @@ -2594,6 +2603,9 @@ PyObject* match; Py_ssize_t status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -2605,10 +2617,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h --- a/Modules/sre_lib.h +++ b/Modules/sre_lib.h @@ -30,7 +30,7 @@ SRE_IS_LINEBREAK((int) ptr[-1])); case SRE_AT_END: - return (((void*) (ptr+1) == state->end && + return (((SRE_CHAR *)state->end - ptr == 1 && SRE_IS_LINEBREAK((int) ptr[0])) || ((void*) ptr == state->end)); @@ -1109,9 +1109,9 @@ /* */ TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); + if (ctx->ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)ctx->pattern[1]) + RETURN_FAILURE; state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr < state->beginning) - RETURN_FAILURE; DO_JUMP0(JUMP_ASSERT, jump_assert, ctx->pattern+2); RETURN_ON_FAILURE(ret); ctx->pattern += ctx->pattern[0]; @@ -1122,8 +1122,8 @@ /* */ TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); - state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr >= state->beginning) { + if (ctx->ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)ctx->pattern[1]) { + state->ptr = ctx->ptr - ctx->pattern[1]; DO_JUMP0(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2); if (ret) { RETURN_ON_ERROR(ret); @@ -1215,12 +1215,20 @@ SRE_CODE* overlap = NULL; int flags = 0; + if (ptr > end) + return 0; + if (pattern[0] == SRE_OP_INFO) { /* optimization info block */ /* <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> */ flags = pattern[2]; + if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) { + TRACE(("reject (got %u chars, need %u)\n", + (unsigned int)(end - ptr), pattern[3])); + return 0; + } if (pattern[3] > 1) { /* adjust end point (but make sure we leave at least one character in there, so literal search will work) */ @@ -1339,15 +1347,18 @@ break; ptr++; } - } else + } else { /* general case */ - while (ptr <= end) { + assert(ptr <= end); + while (1) { TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); - state->start = state->ptr = ptr++; + state->start = state->ptr = ptr; status = SRE(match)(state, pattern, 0); - if (status != 0) + if (status != 0 || ptr >= end) break; + ptr++; } + } return status; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 13:23:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 11:23:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE4Njg0?= =?utf-8?q?=3A_Fixed_reading_out_of_the_buffer_in_the_re_module=2E?= Message-ID: <20150706112356.103090.9446@psf.io> https://hg.python.org/cpython/rev/0007031e0452 changeset: 96848:0007031e0452 branch: 2.7 parent: 96844:372aa98eb72e user: Serhiy Storchaka date: Mon Jul 06 13:58:24 2015 +0300 summary: Issue #18684: Fixed reading out of the buffer in the re module. files: Misc/NEWS | 2 + Modules/_sre.c | 55 ++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #18684: Fixed reading out of the buffer in the re module. + - Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment. diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -351,7 +351,7 @@ SRE_IS_LINEBREAK((int) ptr[-1])); case SRE_AT_END: - return (((void*) (ptr+1) == state->end && + return (((SRE_CHAR *)state->end - ptr == 1 && SRE_IS_LINEBREAK((int) ptr[0])) || ((void*) ptr == state->end)); @@ -1404,9 +1404,9 @@ /* */ TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); + if (ctx->ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)ctx->pattern[1]) + RETURN_FAILURE; state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr < state->beginning) - RETURN_FAILURE; DO_JUMP(JUMP_ASSERT, jump_assert, ctx->pattern+2); RETURN_ON_FAILURE(ret); ctx->pattern += ctx->pattern[0]; @@ -1417,8 +1417,8 @@ /* */ TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern, ctx->ptr, ctx->pattern[1])); - state->ptr = ctx->ptr - ctx->pattern[1]; - if (state->ptr >= state->beginning) { + if (ctx->ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)ctx->pattern[1]) { + state->ptr = ctx->ptr - ctx->pattern[1]; DO_JUMP(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2); if (ret) { RETURN_ON_ERROR(ret); @@ -1510,12 +1510,20 @@ SRE_CODE* overlap = NULL; int flags = 0; + if (ptr > end) + return 0; + if (pattern[0] == SRE_OP_INFO) { /* optimization info block */ /* <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> */ flags = pattern[2]; + if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) { + TRACE(("reject (got %u chars, need %u)\n", + (unsigned int)(end - ptr), pattern[3])); + return 0; + } if (pattern[3] > 1) { /* adjust end point (but make sure we leave at least one character in there, so literal search will work) */ @@ -1614,15 +1622,18 @@ break; ptr++; } - } else + } else { /* general case */ - while (ptr <= end) { + assert(ptr <= end); + while (1) { TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); - state->start = state->ptr = ptr++; + state->start = state->ptr = ptr; status = SRE_MATCH(state, pattern); - if (status != 0) + if (status != 0 || ptr >= end) break; + ptr++; } + } return status; } @@ -2295,7 +2306,7 @@ } if (state.start == state.ptr) { - if (last == state.end) + if (last == state.end || state.ptr == state.end) break; /* skip one character */ state.start = (void*) ((char*) state.ptr + state.charsize); @@ -2497,6 +2508,8 @@ next: /* move on */ + if (state.ptr == state.end) + break; if (state.ptr == state.start) state.start = (void*) ((char*) state.ptr + state.charsize); else @@ -3843,6 +3856,9 @@ PyObject* match; int status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -3860,10 +3876,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } @@ -3876,6 +3896,9 @@ PyObject* match; int status; + if (state->start == NULL) + Py_RETURN_NONE; + state_reset(state); state->ptr = state->start; @@ -3893,10 +3916,14 @@ match = pattern_new_match((PatternObject*) self->pattern, state, status); - if (status == 0 || state->ptr == state->start) + if (status == 0) + state->start = NULL; + else if (state->ptr != state->start) + state->start = state->ptr; + else if (state->ptr != state->end) state->start = (void*) ((char*) state->ptr + state->charsize); else - state->start = state->ptr; + state->start = NULL; return match; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 16:41:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 14:41:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_tighten_warnin?= =?utf-8?q?g?= Message-ID: <20150706144140.6282.18948@psf.io> https://hg.python.org/cpython/rev/0a849e812332 changeset: 96853:0a849e812332 branch: 2.7 parent: 96848:0007031e0452 user: Benjamin Peterson date: Mon Jul 06 09:40:43 2015 -0500 summary: tighten warning files: Doc/library/pickle.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -27,9 +27,9 @@ .. warning:: - The :mod:`pickle` module is not intended to be secure against erroneous or - maliciously constructed data. Never unpickle data received from an untrusted - or unauthenticated source. + The :mod:`pickle` module is secure against erroneous or maliciously + constructed data. Never unpickle data received from an untrusted or + unauthenticated source. Relationship to other Python modules -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 16:41:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 14:41:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150706144140.14890.67260@psf.io> https://hg.python.org/cpython/rev/31015ca8091a changeset: 96855:31015ca8091a parent: 96851:bb9fc884a838 parent: 96854:4e81960d89aa user: Benjamin Peterson date: Mon Jul 06 09:41:20 2015 -0500 summary: merge 3.5 files: Doc/library/pickle.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,9 +26,9 @@ .. warning:: - The :mod:`pickle` module is not intended to be secure against erroneous or - maliciously constructed data. Never unpickle data received from an untrusted - or unauthenticated source. + The :mod:`pickle` module is secure against erroneous or maliciously + constructed data. Never unpickle data received from an untrusted or + unauthenticated source. Relationship to other Python modules -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 16:41:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 14:41:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_tighten_warnin?= =?utf-8?q?g?= Message-ID: <20150706144140.9720.87678@psf.io> https://hg.python.org/cpython/rev/94e0b89591ff changeset: 96852:94e0b89591ff branch: 3.4 parent: 96849:389795b7c703 user: Benjamin Peterson date: Mon Jul 06 09:40:43 2015 -0500 summary: tighten warning files: Doc/library/pickle.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,9 +26,9 @@ .. warning:: - The :mod:`pickle` module is not intended to be secure against erroneous or - maliciously constructed data. Never unpickle data received from an untrusted - or unauthenticated source. + The :mod:`pickle` module is secure against erroneous or maliciously + constructed data. Never unpickle data received from an untrusted or + unauthenticated source. Relationship to other Python modules -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 16:41:44 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 14:41:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150706144140.7742.69780@psf.io> https://hg.python.org/cpython/rev/4e81960d89aa changeset: 96854:4e81960d89aa branch: 3.5 parent: 96850:5adf995d443f parent: 96852:94e0b89591ff user: Benjamin Peterson date: Mon Jul 06 09:41:07 2015 -0500 summary: merge 3.4 files: Doc/library/pickle.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,9 +26,9 @@ .. warning:: - The :mod:`pickle` module is not intended to be secure against erroneous or - maliciously constructed data. Never unpickle data received from an untrusted - or unauthenticated source. + The :mod:`pickle` module is secure against erroneous or maliciously + constructed data. Never unpickle data received from an untrusted or + unauthenticated source. Relationship to other Python modules -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 17:53:56 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 06 Jul 2015 15:53:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Tighten-up_code_in_set=5Fn?= =?utf-8?q?ext=28=29_to_use_an_entry_pointer_rather_than_indexing=2E?= Message-ID: <20150706154342.28324.37557@psf.io> https://hg.python.org/cpython/rev/e0b398869e16 changeset: 96856:e0b398869e16 user: Raymond Hettinger date: Mon Jul 06 08:43:37 2015 -0700 summary: Tighten-up code in set_next() to use an entry pointer rather than indexing. files: Objects/setobject.c | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -518,20 +518,22 @@ { Py_ssize_t i; Py_ssize_t mask; - setentry *table; + setentry *entry; assert (PyAnySet_Check(so)); i = *pos_ptr; assert(i >= 0); - table = so->table; mask = so->mask; - while (i <= mask && (table[i].key == NULL || table[i].key == dummy)) + entry = &so->table[i]; + while (i <= mask && (entry->key == NULL || entry->key == dummy)) { i++; + entry++; + } *pos_ptr = i+1; if (i > mask) return 0; - assert(table[i].key != NULL); - *entry_ptr = &table[i]; + assert(entry != NULL); + *entry_ptr = entry; return 1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 18:29:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 16:29:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogJ25vdCcgaXMgdmVy?= =?utf-8?q?y_important_here?= Message-ID: <20150706162906.15330.78802@psf.io> https://hg.python.org/cpython/rev/80e28c4ed30b changeset: 96858:80e28c4ed30b branch: 2.7 parent: 96853:0a849e812332 user: Benjamin Peterson date: Mon Jul 06 11:28:07 2015 -0500 summary: 'not' is very important here files: Doc/library/pickle.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -27,7 +27,7 @@ .. warning:: - The :mod:`pickle` module is secure against erroneous or maliciously + The :mod:`pickle` module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 18:29:08 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 16:29:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150706162906.12463.61676@psf.io> https://hg.python.org/cpython/rev/8681d2fa6a4d changeset: 96860:8681d2fa6a4d parent: 96856:e0b398869e16 parent: 96859:5adb9e5c2d9b user: Benjamin Peterson date: Mon Jul 06 11:28:47 2015 -0500 summary: merge 3.5 files: Doc/library/pickle.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,7 +26,7 @@ .. warning:: - The :mod:`pickle` module is secure against erroneous or maliciously + The :mod:`pickle` module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 18:29:08 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 16:29:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150706162906.29596.96779@psf.io> https://hg.python.org/cpython/rev/5adb9e5c2d9b changeset: 96859:5adb9e5c2d9b branch: 3.5 parent: 96854:4e81960d89aa parent: 96857:a42dbb9ebda4 user: Benjamin Peterson date: Mon Jul 06 11:28:40 2015 -0500 summary: merge 3.4 files: Doc/library/pickle.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,7 +26,7 @@ .. warning:: - The :mod:`pickle` module is secure against erroneous or maliciously + The :mod:`pickle` module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 18:29:08 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Jul 2015 16:29:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogJ25vdCcgaXMgdmVy?= =?utf-8?q?y_important_here?= Message-ID: <20150706162905.116441.24142@psf.io> https://hg.python.org/cpython/rev/a42dbb9ebda4 changeset: 96857:a42dbb9ebda4 branch: 3.4 parent: 96852:94e0b89591ff user: Benjamin Peterson date: Mon Jul 06 11:28:07 2015 -0500 summary: 'not' is very important here files: Doc/library/pickle.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -26,7 +26,7 @@ .. warning:: - The :mod:`pickle` module is secure against erroneous or maliciously + The :mod:`pickle` module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 19:05:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 17:05:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Corrected_empt?= =?utf-8?q?y_lines_and_removed_BOM_in_Misc/NEWS=2E?= Message-ID: <20150706170528.7742.78639@psf.io> https://hg.python.org/cpython/rev/4796dec0a7d0 changeset: 96861:4796dec0a7d0 branch: 2.7 parent: 96858:80e28c4ed30b user: Serhiy Storchaka date: Mon Jul 06 19:47:12 2015 +0300 summary: Corrected empty lines and removed BOM in Misc/NEWS. files: Misc/NEWS | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -?+++++++++++ ++++++++++++ Python News +++++++++++ @@ -126,6 +126,7 @@ - Issue #22931: Allow '[' and ']' in cookie values. + What's New in Python 2.7.10 release candidate 1? ================================================ @@ -828,7 +829,6 @@ - Issue #22644: The bundled version of OpenSSL has been updated to 1.0.1j. - What's New in Python 2.7.8? =========================== @@ -981,6 +981,7 @@ - Issue #21671, CVE-2014-0224: The bundled version of OpenSSL has been updated to 1.0.1h. + What's New in Python 2.7.7 ========================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 19:05:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 17:05:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Corrected_empty_lines_in_Misc/NEWS=2E?= Message-ID: <20150706170528.130183.13163@psf.io> https://hg.python.org/cpython/rev/78dc519d055c changeset: 96863:78dc519d055c branch: 3.5 parent: 96859:5adb9e5c2d9b parent: 96862:4fee906b9e9e user: Serhiy Storchaka date: Mon Jul 06 20:02:50 2015 +0300 summary: Corrected empty lines in Misc/NEWS. files: Misc/NEWS | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -626,7 +626,6 @@ - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. - Build ----- @@ -1624,6 +1623,7 @@ - Issue #23392: Added tests for marshal C API that works with FILE*. + - Issue #10510: distutils register and upload methods now use HTML standards compliant CRLF line endings. @@ -2812,6 +2812,7 @@ - Issue #22980: .pyd files with a version and platform tag (for example, ".cp35-win32.pyd") will now be loaded in preference to those without tags. + What's New in Python 3.4.0? =========================== @@ -3447,6 +3448,7 @@ - Issue #12837: Silence a tautological comparison warning on OS X under Clang in socketmodule.c. + What's New in Python 3.4.0 Beta 2? ================================== @@ -3822,6 +3824,7 @@ - Issue #19976: Argument Clinic METH_NOARGS functions now always take two parameters. + What's New in Python 3.4.0 Beta 1? ================================== @@ -4292,6 +4295,7 @@ - Issue #19390: Argument Clinic no longer accepts malformed Python and C ids. + What's New in Python 3.4.0 Alpha 4? =================================== @@ -4521,6 +4525,7 @@ options like -fwrapv were overridden and thus not used, which could result in broken interpreters when building with clang. + What's New in Python 3.4.0 Alpha 3? =================================== @@ -4905,6 +4910,7 @@ - Issue #18922: Now The Lib/smtpd.py and Tools/i18n/msgfmt.py scripts write their version strings to stdout, and not to sderr. + What's New in Python 3.4.0 Alpha 1? =================================== @@ -5474,6 +5480,7 @@ when \r\n appears at end of 65535 bytes without other newlines. - Issue #18076: Introduce importlib.util.decode_source(). + - Issue #18357: add tests for dictview set difference. Patch by Fraser Tweedale. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 19:05:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 17:05:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Corrected_empt?= =?utf-8?q?y_lines_in_Misc/NEWS=2E?= Message-ID: <20150706170528.29384.55681@psf.io> https://hg.python.org/cpython/rev/4fee906b9e9e changeset: 96862:4fee906b9e9e branch: 3.4 parent: 96857:a42dbb9ebda4 user: Serhiy Storchaka date: Mon Jul 06 19:58:11 2015 +0300 summary: Corrected empty lines in Misc/NEWS. files: Misc/NEWS | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -778,14 +778,12 @@ - Issue #22644: The bundled version of OpenSSL has been updated to 1.0.1j. + What's New in Python 3.4.2? =========================== Release date: 2014-10-06 -Core and Builtins ------------------ - Library ------- @@ -1523,6 +1521,7 @@ ----------------- - Issue #21276: posixmodule: Don't define USE_XATTRS on KFreeBSD and the Hurd. + - Issue #21226: Set up modules properly in PyImport_ExecCodeModuleObject (and friends). @@ -2259,6 +2258,7 @@ - Issue #12837: Silence a tautological comparison warning on OS X under Clang in socketmodule.c. + What's New in Python 3.4.0 Beta 2? ================================== @@ -2634,6 +2634,7 @@ - Issue #19976: Argument Clinic METH_NOARGS functions now always take two parameters. + What's New in Python 3.4.0 Beta 1? ================================== @@ -3104,6 +3105,7 @@ - Issue #19390: Argument Clinic no longer accepts malformed Python and C ids. + What's New in Python 3.4.0 Alpha 4? =================================== @@ -3333,6 +3335,7 @@ options like -fwrapv were overridden and thus not used, which could result in broken interpreters when building with clang. + What's New in Python 3.4.0 Alpha 3? =================================== @@ -3717,6 +3720,7 @@ - Issue #18922: Now The Lib/smtpd.py and Tools/i18n/msgfmt.py scripts write their version strings to stdout, and not to sderr. + What's New in Python 3.4.0 Alpha 1? =================================== @@ -4286,6 +4290,7 @@ when \r\n appears at end of 65535 bytes without other newlines. - Issue #18076: Introduce importlib.util.decode_source(). + - Issue #18357: add tests for dictview set difference. Patch by Fraser Tweedale. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 6 19:05:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Jul 2015 17:05:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Corrected_empty_lines_in_Misc/NEWS=2E?= Message-ID: <20150706170528.10165.18026@psf.io> https://hg.python.org/cpython/rev/7c74ece3bb16 changeset: 96864:7c74ece3bb16 parent: 96860:8681d2fa6a4d parent: 96863:78dc519d055c user: Serhiy Storchaka date: Mon Jul 06 20:04:21 2015 +0300 summary: Corrected empty lines in Misc/NEWS. files: Misc/NEWS | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -645,7 +645,6 @@ - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. - Build ----- @@ -1643,6 +1642,7 @@ - Issue #23392: Added tests for marshal C API that works with FILE*. + - Issue #10510: distutils register and upload methods now use HTML standards compliant CRLF line endings. @@ -2831,6 +2831,7 @@ - Issue #22980: .pyd files with a version and platform tag (for example, ".cp35-win32.pyd") will now be loaded in preference to those without tags. + What's New in Python 3.4.0? =========================== @@ -3466,6 +3467,7 @@ - Issue #12837: Silence a tautological comparison warning on OS X under Clang in socketmodule.c. + What's New in Python 3.4.0 Beta 2? ================================== @@ -3841,6 +3843,7 @@ - Issue #19976: Argument Clinic METH_NOARGS functions now always take two parameters. + What's New in Python 3.4.0 Beta 1? ================================== @@ -4311,6 +4314,7 @@ - Issue #19390: Argument Clinic no longer accepts malformed Python and C ids. + What's New in Python 3.4.0 Alpha 4? =================================== @@ -4540,6 +4544,7 @@ options like -fwrapv were overridden and thus not used, which could result in broken interpreters when building with clang. + What's New in Python 3.4.0 Alpha 3? =================================== @@ -4924,6 +4929,7 @@ - Issue #18922: Now The Lib/smtpd.py and Tools/i18n/msgfmt.py scripts write their version strings to stdout, and not to sderr. + What's New in Python 3.4.0 Alpha 1? =================================== @@ -5493,6 +5499,7 @@ when \r\n appears at end of 65535 bytes without other newlines. - Issue #18076: Introduce importlib.util.decode_source(). + - Issue #18357: add tests for dictview set difference. Patch by Fraser Tweedale. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 04:03:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 07 Jul 2015 02:03:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Tighten-up_code_in_the_set?= =?utf-8?q?_iterator_to_use_an_entry_pointer_rather_than?= Message-ID: <20150707020307.11325.89553@psf.io> https://hg.python.org/cpython/rev/c9782a9ac031 changeset: 96865:c9782a9ac031 user: Raymond Hettinger date: Mon Jul 06 19:03:01 2015 -0700 summary: Tighten-up code in the set iterator to use an entry pointer rather than indexing. files: Objects/setobject.c | 35 ++++++++++++-------------------- 1 files changed, 13 insertions(+), 22 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -766,8 +766,8 @@ PyObject_HEAD PySetObject *si_set; /* Set to NULL when iterator is exhausted */ Py_ssize_t si_used; - Py_ssize_t si_pos; Py_ssize_t len; + setentry *entry; } setiterobject; static void @@ -845,8 +845,6 @@ static PyObject *setiter_iternext(setiterobject *si) { - PyObject *key; - Py_ssize_t i, mask; setentry *entry; PySetObject *so = si->si_set; @@ -860,25 +858,18 @@ si->si_used = -1; /* Make this state sticky */ return NULL; } - - i = si->si_pos; - assert(i>=0); - entry = so->table; - mask = so->mask; - while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) - i++; - si->si_pos = i+1; - if (i > mask) - goto fail; + if (si->len <= 0) { + Py_DECREF(so); + si->si_set = NULL; + return NULL; + } + entry = si->entry; + while (entry->key == NULL || entry->key == dummy) + entry++; si->len--; - key = entry[i].key; - Py_INCREF(key); - return key; - -fail: - Py_DECREF(so); - si->si_set = NULL; - return NULL; + si->entry = entry + 1; + Py_INCREF(entry->key); + return entry->key; } PyTypeObject PySetIter_Type = { @@ -923,8 +914,8 @@ Py_INCREF(so); si->si_set = so; si->si_used = so->used; - si->si_pos = 0; si->len = so->used; + si->entry = so->table; _PyObject_GC_TRACK(si); return (PyObject *)si; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 04:08:53 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 07 Jul 2015 02:08:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_bit_of_factoring-out?= =?utf-8?q?_common_code=2E?= Message-ID: <20150707020853.20885.2805@psf.io> https://hg.python.org/cpython/rev/5088f2cd6293 changeset: 96866:5088f2cd6293 user: Raymond Hettinger date: Mon Jul 06 19:08:49 2015 -0700 summary: Minor bit of factoring-out common code. files: Objects/setobject.c | 29 +++++++++++------------------ 1 files changed, 11 insertions(+), 18 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1271,26 +1271,14 @@ while ((key = PyIter_Next(it)) != NULL) { hash = PyObject_Hash(key); - if (hash == -1) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } + if (hash == -1) + goto error; rv = set_contains_entry(so, key, hash); - if (rv < 0) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } + if (rv < 0) + goto error; if (rv) { - if (set_add_entry(result, key, hash)) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } + if (set_add_entry(result, key, hash)) + goto error; } Py_DECREF(key); } @@ -1300,6 +1288,11 @@ return NULL; } return (PyObject *)result; + error: + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 06:33:43 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 04:33:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150707043343.27420.64626@psf.io> https://hg.python.org/cpython/rev/74b1a0001dc8 changeset: 96868:74b1a0001dc8 branch: 3.5 parent: 96863:78dc519d055c parent: 96867:0f5a57b822c2 user: Zachary Ware date: Mon Jul 06 23:30:16 2015 -0500 summary: Merge 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 06:33:43 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 04:33:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150707043343.44850.65081@psf.io> https://hg.python.org/cpython/rev/91681c1524da changeset: 96869:91681c1524da parent: 96866:5088f2cd6293 parent: 96868:74b1a0001dc8 user: Zachary Ware date: Mon Jul 06 23:33:33 2015 -0500 summary: Merge 3.5 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 06:33:43 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 04:33:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_suspicious?= =?utf-8?q?_markup?= Message-ID: <20150707043343.130183.13462@psf.io> https://hg.python.org/cpython/rev/0f5a57b822c2 changeset: 96867:0f5a57b822c2 branch: 3.4 parent: 96862:4fee906b9e9e user: Zachary Ware date: Mon Jul 06 23:27:15 2015 -0500 summary: Fix suspicious markup files: Doc/c-api/structures.rst | 2 +- Doc/library/unittest.mock.rst | 2 +- Doc/tools/susp-ignored.csv | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -44,7 +44,7 @@ PyObject ob_base; - See documentation of :c:type::`PyObject` above. + See documentation of :c:type:`PyObject` above. .. c:macro:: PyObject_VAR_HEAD 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 @@ -1587,7 +1587,7 @@ * Context manager: ``__enter__`` and ``__exit__`` * Unary numeric methods: ``__neg__``, ``__pos__`` and ``__invert__`` * The numeric methods (including right hand and in-place variants): - ``__add__``, ``__sub__``, ``__mul__``, ``__div__``,``__truediv__``, + ``__add__``, ``__sub__``, ``__mul__``, ``__div__``, ``__truediv__``, ``__floordiv__``, ``__mod__``, ``__divmod__``, ``__lshift__``, ``__rshift__``, ``__and__``, ``__xor__``, ``__or__``, and ``__pow__`` * Numeric conversion methods: ``__complex__``, ``__int__``, ``__float__`` diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -136,12 +136,11 @@ library/ipaddress,,::,2001:db00::0/ffff:ff00:: library/itertools,,:step,elements from seq[start:stop:step] library/itertools,,:stop,elements from seq[start:stop:step] -library/linecache,,:sys,"sys:x:3:3:sys:/dev:/bin/sh" library/logging.handlers,,:port,host:port library/mmap,,:i2,obj[i1:i2] library/multiprocessing,,`,# Add more tasks using `put()` library/multiprocessing,,`,">>> l._callmethod('__getitem__', (20,)) # equiv to `l[20]`" -library/multiprocessing,,`,">>> l._callmethod('__getslice__', (2, 7)) # equiv to `l[2:7]`" +library/multiprocessing,,`,">>> l._callmethod('__getitem__', (slice(2, 7),)) # equiv to `l[2:7]`" library/multiprocessing,,:queue,">>> QueueManager.register('get_queue', callable=lambda:queue)" library/multiprocessing,,`,# register the Foo class; make `f()` and `g()` accessible via proxy library/multiprocessing,,`,# register the Foo class; make `g()` and `_h()` accessible via proxy @@ -164,7 +163,6 @@ library/pyexpat,,:elem1, library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/smtplib,,:port,method must support that as well as a regular host:port -library/socket,,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" library/socket,,:len,fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) @@ -210,6 +208,16 @@ library/venv,,:param,":param progress: If setuptools or pip are installed, the progress of the" library/venv,,:param,":param nopip: If True, pip is not installed into the created" library/venv,,:param,:param context: The information for the environment creation request +library/xml.etree.elementtree,,:sometag,prefix:sometag +library/xml.etree.elementtree,,:fictional,"Lancelot +library/xml.etree.elementtree,,:character,Archie Leach +library/xml.etree.elementtree,,:character,Sir Robin +library/xml.etree.elementtree,,:character,Gunther +library/xml.etree.elementtree,,:character,Commander Clement +library/xml.etree.elementtree,,:actor,"for actor in root.findall('real_person:actor', ns):" +library/xml.etree.elementtree,,:name,"name = actor.find('real_person:name', ns)" +library/xml.etree.elementtree,,:character,"for char in actor.findall('role:character', ns):" library/xmlrpc.client,,:pass,http://user:pass at host:port/path library/xmlrpc.client,,:pass,user:pass library/xmlrpc.client,,:port,http://user:pass at host:port/path @@ -236,6 +244,7 @@ tutorial/stdlib2,,:start,"fields = struct.unpack(' https://hg.python.org/cpython/rev/938fe6ce92a7 changeset: 96871:938fe6ce92a7 branch: 3.5 parent: 96868:74b1a0001dc8 parent: 96870:ed6ec65f50d2 user: Zachary Ware date: Tue Jul 07 00:00:43 2015 -0500 summary: Merge 3.4 files: Doc/c-api/structures.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -60,7 +60,7 @@ .. c:macro:: Py_TYPE(o) - This macro is used to access the `ob_type` member of a Python object. + This macro is used to access the :attr:`ob_type` member of a Python object. It expands to:: (((PyObject*)(o))->ob_type) @@ -68,7 +68,8 @@ .. c:macro:: Py_REFCNT(o) - This macro is used to access the `ob_refcnt` member of a Python object. + This macro is used to access the :attr:`ob_refcnt` member of a Python + object. It expands to:: (((PyObject*)(o))->ob_refcnt) @@ -76,7 +77,7 @@ .. c:macro:: Py_SIZE(o) - This macro is used to access the `ob_size` member of a Python object. + This macro is used to access the :attr:`ob_size` member of a Python object. It expands to:: (((PyVarObject*)(o))->ob_size) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:11:57 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fix_usage_of_t?= =?utf-8?q?he_default_role=2E?= Message-ID: <20150707051157.108523.55641@psf.io> https://hg.python.org/cpython/rev/39d7b41c04f6 changeset: 96872:39d7b41c04f6 branch: 3.5 user: Zachary Ware date: Tue Jul 07 00:07:25 2015 -0500 summary: Fix usage of the default role. files: Doc/library/sys.rst | 2 +- Doc/library/test.rst | 6 +++--- Doc/whatsnew/3.5.rst | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1100,7 +1100,7 @@ pass # The following line will fail with a RuntimeError, because - # `wrapper` creates a `wrap(coro)` coroutine: + # ``wrapper`` creates a ``wrap(coro)`` coroutine: foo() See also :func:`get_coroutine_wrapper`. diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -570,9 +570,9 @@ .. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()): - Returns the set of attributes, functions or methods of `ref_api` not - found on `other_api`, except for a defined list of items to be - ignored in this check specified in `ignore`. + Returns the set of attributes, functions or methods of *ref_api* not + found on *other_api*, except for a defined list of items to be + ignored in this check specified in *ignore*. By default this skips private attributes beginning with '_' but includes all magic methods, i.e. those starting and ending in '__'. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1086,7 +1086,7 @@ * The :mod:`socket` module now exports the CAN_RAW_FD_FRAMES constant on linux 3.6 and greater. -* The `pygettext.py` Tool now uses the standard +NNNN format for timezones in +* The ``pygettext.py`` Tool now uses the standard +NNNN format for timezones in the POT-Creation-Date header. * The :mod:`smtplib` module now uses :data:`sys.stderr` instead of previous -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:11:57 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150707051157.15517.45779@psf.io> https://hg.python.org/cpython/rev/87853f158042 changeset: 96873:87853f158042 parent: 96869:91681c1524da parent: 96872:39d7b41c04f6 user: Zachary Ware date: Tue Jul 07 00:08:50 2015 -0500 summary: Merge 3.5 files: Doc/c-api/structures.rst | 7 ++++--- Doc/library/sys.rst | 2 +- Doc/library/test.rst | 6 +++--- Doc/whatsnew/3.5.rst | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -60,7 +60,7 @@ .. c:macro:: Py_TYPE(o) - This macro is used to access the `ob_type` member of a Python object. + This macro is used to access the :attr:`ob_type` member of a Python object. It expands to:: (((PyObject*)(o))->ob_type) @@ -68,7 +68,8 @@ .. c:macro:: Py_REFCNT(o) - This macro is used to access the `ob_refcnt` member of a Python object. + This macro is used to access the :attr:`ob_refcnt` member of a Python + object. It expands to:: (((PyObject*)(o))->ob_refcnt) @@ -76,7 +77,7 @@ .. c:macro:: Py_SIZE(o) - This macro is used to access the `ob_size` member of a Python object. + This macro is used to access the :attr:`ob_size` member of a Python object. It expands to:: (((PyVarObject*)(o))->ob_size) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1100,7 +1100,7 @@ pass # The following line will fail with a RuntimeError, because - # `wrapper` creates a `wrap(coro)` coroutine: + # ``wrapper`` creates a ``wrap(coro)`` coroutine: foo() See also :func:`get_coroutine_wrapper`. diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -570,9 +570,9 @@ .. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()): - Returns the set of attributes, functions or methods of `ref_api` not - found on `other_api`, except for a defined list of items to be - ignored in this check specified in `ignore`. + Returns the set of attributes, functions or methods of *ref_api* not + found on *other_api*, except for a defined list of items to be + ignored in this check specified in *ignore*. By default this skips private attributes beginning with '_' but includes all magic methods, i.e. those starting and ending in '__'. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1086,7 +1086,7 @@ * The :mod:`socket` module now exports the CAN_RAW_FD_FRAMES constant on linux 3.6 and greater. -* The `pygettext.py` Tool now uses the standard +NNNN format for timezones in +* The ``pygettext.py`` Tool now uses the standard +NNNN format for timezones in the POT-Creation-Date header. * The :mod:`smtplib` module now uses :data:`sys.stderr` instead of previous -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:11:57 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_usage_of_t?= =?utf-8?q?he_default_role=2E?= Message-ID: <20150707051157.102195.56679@psf.io> https://hg.python.org/cpython/rev/ed6ec65f50d2 changeset: 96870:ed6ec65f50d2 branch: 3.4 parent: 96867:0f5a57b822c2 user: Zachary Ware date: Mon Jul 06 23:58:12 2015 -0500 summary: Fix usage of the default role. The changes to Doc/library/unittest.mock.rst are almost entirely a selective backport of the 3.5 page. files: Doc/c-api/structures.rst | 7 +- Doc/library/unittest.mock.rst | 86 +++++++++++----------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -60,7 +60,7 @@ .. c:macro:: Py_TYPE(o) - This macro is used to access the `ob_type` member of a Python object. + This macro is used to access the :attr:`ob_type` member of a Python object. It expands to:: (((PyObject*)(o))->ob_type) @@ -68,7 +68,8 @@ .. c:macro:: Py_REFCNT(o) - This macro is used to access the `ob_refcnt` member of a Python object. + This macro is used to access the :attr:`ob_refcnt` member of a Python + object. It expands to:: (((PyObject*)(o))->ob_refcnt) @@ -76,7 +77,7 @@ .. c:macro:: Py_SIZE(o) - This macro is used to access the `ob_size` member of a Python object. + This macro is used to access the :attr:`ob_size` member of a Python object. It expands to:: (((PyVarObject*)(o))->ob_size) 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 @@ -181,71 +181,71 @@ -------------- -`Mock` is a flexible mock object intended to replace the use of stubs and +:class:`Mock` is a flexible mock object intended to replace the use of stubs and test doubles throughout your code. Mocks are callable and create attributes as new mocks when you access them [#]_. Accessing the same attribute will always return the same mock. Mocks record how you use them, allowing you to make assertions about what your code has done to them. -:class:`MagicMock` is a subclass of `Mock` with all the magic methods +:class:`MagicMock` is a subclass of :class:`Mock` with all the magic methods pre-created and ready to use. There are also non-callable variants, useful when you are mocking out objects that aren't callable: :class:`NonCallableMock` and :class:`NonCallableMagicMock` The :func:`patch` decorators makes it easy to temporarily replace classes -in a particular module with a `Mock` object. By default `patch` will create -a `MagicMock` for you. You can specify an alternative class of `Mock` using -the `new_callable` argument to `patch`. +in a particular module with a :class:`Mock` object. By default :func:`patch` will create +a :class:`MagicMock` for you. You can specify an alternative class of :class:`Mock` using +the *new_callable* argument to :func:`patch`. .. class:: Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs) - Create a new `Mock` object. `Mock` takes several optional arguments + Create a new :class:`Mock` object. :class:`Mock` takes several optional arguments that specify the behaviour of the Mock object: - * `spec`: This can be either a list of strings or an existing object (a + * *spec*: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). - Accessing any attribute not in this list will raise an `AttributeError`. - - If `spec` is an object (rather than a list of strings) then + Accessing any attribute not in this list will raise an :exc:`AttributeError`. + + If *spec* is an object (rather than a list of strings) then :attr:`~instance.__class__` returns the class of the spec object. This - allows mocks to pass `isinstance` tests. - - * `spec_set`: A stricter variant of `spec`. If used, attempting to *set* + allows mocks to pass :func:`isinstance` tests. + + * *spec_set*: A stricter variant of *spec*. If used, attempting to *set* or get an attribute on the mock that isn't on the object passed as - `spec_set` will raise an `AttributeError`. - - * `side_effect`: A function to be called whenever the Mock is called. See + *spec_set* will raise an :exc:`AttributeError`. + + * *side_effect*: A function to be called whenever the Mock is called. See the :attr:`~Mock.side_effect` attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns :data:`DEFAULT`, the return value of this function is used as the return value. - Alternatively `side_effect` can be an exception class or instance. In + Alternatively *side_effect* can be an exception class or instance. In this case the exception will be raised when the mock is called. - If `side_effect` is an iterable then each call to the mock will return + If *side_effect* is an iterable then each call to the mock will return the next value from the iterable. - A `side_effect` can be cleared by setting it to `None`. - - * `return_value`: The value returned when the mock is called. By default + A *side_effect* can be cleared by setting it to ``None``. + + * *return_value*: The value returned when the mock is called. By default this is a new Mock (created on first access). See the :attr:`return_value` attribute. - * `wraps`: Item for the mock object to wrap. If `wraps` is not None then + * *wraps*: Item for the mock object to wrap. If *wraps* is not None then calling the Mock will pass the call through to the wrapped object (returning the real result). Attribute access on the mock will return a Mock object that wraps the corresponding attribute of the wrapped object (so attempting to access an attribute that doesn't exist will - raise an `AttributeError`). - - If the mock has an explicit `return_value` set then calls are not passed - to the wrapped object and the `return_value` is returned instead. - - * `name`: If the mock has a name then it will be used in the repr of the + raise an :exc:`AttributeError`). + + If the mock has an explicit *return_value* set then calls are not passed + to the wrapped object and the *return_value* is returned instead. + + * *name*: If the mock has a name then it will be used in the repr of the mock. This can be useful for debugging. The name is propagated to child mocks. @@ -1032,25 +1032,25 @@ default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! - Patch can be used as a `TestCase` class decorator. It works by + Patch can be used as a :class:`TestCase` class decorator. It works by decorating each test method in the class. This reduces the boilerplate - code when your test methods share a common patchings set. `patch` finds - tests by looking for method names that start with `patch.TEST_PREFIX`. - By default this is `test`, which matches the way `unittest` finds tests. - You can specify an alternative prefix by setting `patch.TEST_PREFIX`. + code when your test methods share a common patchings set. :func:`patch` finds + tests by looking for method names that start with ``patch.TEST_PREFIX``. + By default this is ``'test'``, which matches the way :mod:`unittest` finds tests. + You can specify an alternative prefix by setting ``patch.TEST_PREFIX``. Patch can be used as a context manager, with the with statement. Here the patching applies to the indented block after the with statement. If you use "as" then the patched object will be bound to the name after the - "as"; very useful if `patch` is creating a mock object for you. - - `patch` takes arbitrary keyword arguments. These will be passed to - the `Mock` (or `new_callable`) on construction. - - `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are + "as"; very useful if :func:`patch` is creating a mock object for you. + + :func:`patch` takes arbitrary keyword arguments. These will be passed to + the :class:`Mock` (or *new_callable*) on construction. + + ``patch.dict(...)``, ``patch.multiple(...)`` and ``patch.object(...)`` are available for alternate use-cases. -`patch` as function decorator, creating the mock for you and passing it into +:func:`patch` as function decorator, creating the mock for you and passing it into the decorated function: >>> @patch('__main__.SomeClass') @@ -1392,15 +1392,15 @@ ... assert package.module.Class is self.MockClass ... - As an added bonus you no longer need to keep a reference to the `patcher` + As an added bonus you no longer need to keep a reference to the ``patcher`` object. It is also possible to stop all patches which have been started by using -`patch.stopall`. +:func:`patch.stopall`. .. function:: patch.stopall - Stop all active patches. Only stops patches started with `start`. + Stop all active patches. Only stops patches started with ``start``. TEST_PREFIX -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:11:57 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fix_versioncha?= =?utf-8?q?nged_directives?= Message-ID: <20150707051157.8143.94055@psf.io> https://hg.python.org/cpython/rev/60a4a9ea887d changeset: 96874:60a4a9ea887d branch: 3.5 parent: 96872:39d7b41c04f6 user: Zachary Ware date: Tue Jul 07 00:11:36 2015 -0500 summary: Fix versionchanged directives files: Doc/distutils/builtdist.rst | 2 +- Doc/distutils/sourcedist.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/distutils/builtdist.rst b/Doc/distutils/builtdist.rst --- a/Doc/distutils/builtdist.rst +++ b/Doc/distutils/builtdist.rst @@ -100,7 +100,7 @@ | ``msi`` | Microsoft Installer. | | +-------------+------------------------------+---------+ -.. versionchanged: 3.5 +.. versionchanged:: 3.5 Added support for the ``xztar`` format. diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -41,7 +41,7 @@ | ``tar`` | tar file (:file:`.tar`) | | +-----------+-------------------------+---------+ -.. versionchanged: 3.5 +.. versionchanged:: 3.5 Added support for the ``xztar`` format. Notes: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:11:57 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150707051157.30594.78714@psf.io> https://hg.python.org/cpython/rev/ce0bb740d295 changeset: 96875:ce0bb740d295 parent: 96873:87853f158042 parent: 96874:60a4a9ea887d user: Zachary Ware date: Tue Jul 07 00:11:49 2015 -0500 summary: Merge 3.5 files: Doc/distutils/builtdist.rst | 2 +- Doc/distutils/sourcedist.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/distutils/builtdist.rst b/Doc/distutils/builtdist.rst --- a/Doc/distutils/builtdist.rst +++ b/Doc/distutils/builtdist.rst @@ -100,7 +100,7 @@ | ``msi`` | Microsoft Installer. | | +-------------+------------------------------+---------+ -.. versionchanged: 3.5 +.. versionchanged:: 3.5 Added support for the ``xztar`` format. diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -41,7 +41,7 @@ | ``tar`` | tar file (:file:`.tar`) | | +-----------+-------------------------+---------+ -.. versionchanged: 3.5 +.. versionchanged:: 3.5 Added support for the ``xztar`` format. Notes: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:34:43 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:34:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150707053443.79698.51554@psf.io> https://hg.python.org/cpython/rev/2f86a69c3220 changeset: 96877:2f86a69c3220 parent: 96875:ce0bb740d295 parent: 96876:24cb8e3f98de user: Zachary Ware date: Tue Jul 07 00:34:37 2015 -0500 summary: Merge 3.5 files: Doc/tools/susp-ignored.csv | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -289,5 +289,5 @@ library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a" library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing" library/stdtypes,3767,::,>>> m[::2].tolist() -library/sys,1115,`,# `wrapper` creates a `wrap(coro)` coroutine: +library/sys,1115,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine: tutorial/venv,77,:c7b9645a6f35,"Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 7 07:34:43 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 07 Jul 2015 05:34:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Update_ignored?= =?utf-8?q?_suspicious_markup?= Message-ID: <20150707053443.14247.36174@psf.io> https://hg.python.org/cpython/rev/24cb8e3f98de changeset: 96876:24cb8e3f98de branch: 3.5 parent: 96874:60a4a9ea887d user: Zachary Ware date: Tue Jul 07 00:34:25 2015 -0500 summary: Update ignored suspicious markup files: Doc/tools/susp-ignored.csv | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -289,5 +289,5 @@ library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a" library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing" library/stdtypes,3767,::,>>> m[::2].tolist() -library/sys,1115,`,# `wrapper` creates a `wrap(coro)` coroutine: +library/sys,1115,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine: tutorial/venv,77,:c7b9645a6f35,"Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)" -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue Jul 7 10:44:32 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 07 Jul 2015 08:44:32 +0000 Subject: [Python-checkins] Daily reference leaks (2f86a69c3220): sum=7 Message-ID: <20150707084432.8857.30425@psf.io> results for 2f86a69c3220 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogALCj0R', '--timeout', '7200'] From python-checkins at python.org Wed Jul 8 00:29:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 07 Jul 2015 22:29:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24581=3A_Revert_c978?= =?utf-8?q?2a9ac031_pending_a_stronger_test_for_mutation_during?= Message-ID: <20150707222930.130183.42959@psf.io> https://hg.python.org/cpython/rev/648c9fb3bdf5 changeset: 96878:648c9fb3bdf5 user: Raymond Hettinger date: Tue Jul 07 15:29:24 2015 -0700 summary: Issue 24581: Revert c9782a9ac031 pending a stronger test for mutation during iteration. files: Objects/setobject.c | 35 ++++++++++++++++++++------------ 1 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -766,8 +766,8 @@ PyObject_HEAD PySetObject *si_set; /* Set to NULL when iterator is exhausted */ Py_ssize_t si_used; + Py_ssize_t si_pos; Py_ssize_t len; - setentry *entry; } setiterobject; static void @@ -845,6 +845,8 @@ static PyObject *setiter_iternext(setiterobject *si) { + PyObject *key; + Py_ssize_t i, mask; setentry *entry; PySetObject *so = si->si_set; @@ -858,18 +860,25 @@ si->si_used = -1; /* Make this state sticky */ return NULL; } - if (si->len <= 0) { - Py_DECREF(so); - si->si_set = NULL; - return NULL; - } - entry = si->entry; - while (entry->key == NULL || entry->key == dummy) - entry++; + + i = si->si_pos; + assert(i>=0); + entry = so->table; + mask = so->mask; + while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) + i++; + si->si_pos = i+1; + if (i > mask) + goto fail; si->len--; - si->entry = entry + 1; - Py_INCREF(entry->key); - return entry->key; + key = entry[i].key; + Py_INCREF(key); + return key; + +fail: + Py_DECREF(so); + si->si_set = NULL; + return NULL; } PyTypeObject PySetIter_Type = { @@ -914,8 +923,8 @@ Py_INCREF(so); si->si_set = so; si->si_used = so->used; + si->si_pos = 0; si->len = so->used; - si->entry = so->table; _PyObject_GC_TRACK(si); return (PyObject *)si; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 05:48:10 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 08 Jul 2015 03:48:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Closes_24584?= =?utf-8?q?=3A_Windows_installer_incorrectly_detects_CRT_version_on_Window?= =?utf-8?q?s_10?= Message-ID: <20150708034810.13199.81360@psf.io> https://hg.python.org/cpython/rev/60eb61d6fdb4 changeset: 96879:60eb61d6fdb4 branch: 3.5 parent: 96876:24cb8e3f98de user: Steve Dower date: Tue Jul 07 20:47:28 2015 -0700 summary: Closes 24584: Windows installer incorrectly detects CRT version on Windows 10 files: Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -2399,10 +2399,10 @@ return FALSE; } - // Check whether at least CRT v10.0.9924.0 is available. + // Check whether at least CRT v10.0.10137.0 is available. // It should only be installed as a Windows Update package, which means // we don't need to worry about 32-bit/64-bit. - LPCWSTR crtFile = L"api-ms-win-crt-runtime-l1-1-0.dll"; + LPCWSTR crtFile = L"ucrtbase.dll"; DWORD cbVer = GetFileVersionInfoSizeW(crtFile, nullptr); if (!cbVer) { @@ -2427,7 +2427,7 @@ BOOL result = FALSE; if (VerQueryValueW(pData, L"\\", (LPVOID*)&ffi, &cb) && - ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x26C40000) { + ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x27990000) { result = TRUE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 05:48:13 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 08 Jul 2015 03:48:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_24584=3A_Windows_installer_incorrectly_detects_CR?= =?utf-8?q?T_version_on_Windows_10?= Message-ID: <20150708034810.23227.5004@psf.io> https://hg.python.org/cpython/rev/877f47ca3b79 changeset: 96880:877f47ca3b79 parent: 96878:648c9fb3bdf5 parent: 96879:60eb61d6fdb4 user: Steve Dower date: Tue Jul 07 20:47:49 2015 -0700 summary: Closes 24584: Windows installer incorrectly detects CRT version on Windows 10 files: Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -2399,10 +2399,10 @@ return FALSE; } - // Check whether at least CRT v10.0.9924.0 is available. + // Check whether at least CRT v10.0.10137.0 is available. // It should only be installed as a Windows Update package, which means // we don't need to worry about 32-bit/64-bit. - LPCWSTR crtFile = L"api-ms-win-crt-runtime-l1-1-0.dll"; + LPCWSTR crtFile = L"ucrtbase.dll"; DWORD cbVer = GetFileVersionInfoSizeW(crtFile, nullptr); if (!cbVer) { @@ -2427,7 +2427,7 @@ BOOL result = FALSE; if (VerQueryValueW(pData, L"\\", (LPVOID*)&ffi, &cb) && - ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x26C40000) { + ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x27990000) { result = TRUE; } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed Jul 8 10:45:11 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 08 Jul 2015 08:45:11 +0000 Subject: [Python-checkins] Daily reference leaks (877f47ca3b79): sum=5 Message-ID: <20150708084503.12463.96779@psf.io> results for 877f47ca3b79 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_smtplib leaked [0, 0, 1] references, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogxS5T53', '--timeout', '7200'] From python-checkins at python.org Wed Jul 8 20:52:44 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 08 Jul 2015 18:52:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Neaten-up_a_little_bit=2E?= Message-ID: <20150708185231.110676.57293@psf.io> https://hg.python.org/cpython/rev/d95cdd5b4ffb changeset: 96881:d95cdd5b4ffb user: Raymond Hettinger date: Wed Jul 08 11:52:27 2015 -0700 summary: Neaten-up a little bit. files: Objects/setobject.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -902,7 +902,7 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)setiter_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -2145,7 +2145,7 @@ copy_doc}, {"difference", (PyCFunction)set_difference_multi, METH_VARARGS, difference_doc}, - {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS, + {"intersection", (PyCFunction)set_intersection_multi, METH_VARARGS, intersection_doc}, {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, isdisjoint_doc}, @@ -2216,7 +2216,7 @@ (traverseproc)set_traverse, /* tp_traverse */ (inquiry)set_clear_internal, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ - offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ + offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ frozenset_methods, /* tp_methods */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 22:03:35 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 08 Jul 2015 20:03:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Added_regression_test_for_issue24581=2E?= Message-ID: <20150708200335.3102.72096@psf.io> https://hg.python.org/cpython/rev/844bd42326fa changeset: 96884:844bd42326fa branch: 3.5 parent: 96879:60eb61d6fdb4 parent: 96882:8644744f53ce user: Serhiy Storchaka date: Wed Jul 08 23:02:18 2015 +0300 summary: Added regression test for issue24581. files: Lib/test/test_set.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1731,6 +1731,17 @@ be_bad = True set1.symmetric_difference_update(dict2) + def test_iter_and_mutate(self): + # Issue #24581 + s = set(range(100)) + s.clear() + s.update(range(100)) + si = iter(s) + s.clear() + a = list(range(100)) + s.update(range(100)) + list(si) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 22:03:35 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 08 Jul 2015 20:03:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Added_regression_test_for_issue24581=2E?= Message-ID: <20150708200335.6282.82563@psf.io> https://hg.python.org/cpython/rev/9d296d5b6941 changeset: 96885:9d296d5b6941 parent: 96881:d95cdd5b4ffb parent: 96884:844bd42326fa user: Serhiy Storchaka date: Wed Jul 08 23:02:51 2015 +0300 summary: Added regression test for issue24581. files: Lib/test/test_set.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1731,6 +1731,17 @@ be_bad = True set1.symmetric_difference_update(dict2) + def test_iter_and_mutate(self): + # Issue #24581 + s = set(range(100)) + s.clear() + s.update(range(100)) + si = iter(s) + s.clear() + a = list(range(100)) + s.update(range(100)) + list(si) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 22:03:36 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 08 Jul 2015 20:03:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_regressi?= =?utf-8?q?on_test_for_issue24581=2E?= Message-ID: <20150708200335.110093.12200@psf.io> https://hg.python.org/cpython/rev/cfb84be6c7fc changeset: 96883:cfb84be6c7fc branch: 2.7 parent: 96861:4796dec0a7d0 user: Serhiy Storchaka date: Wed Jul 08 22:58:55 2015 +0300 summary: Added regression test for issue24581. files: Lib/test/test_set.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1648,6 +1648,17 @@ be_bad = True set1.symmetric_difference_update(dict2) + def test_iter_and_mutate(self): + # Issue #24581 + s = set(range(100)) + s.clear() + s.update(range(100)) + si = iter(s) + s.clear() + a = list(range(100)) + s.update(range(100)) + list(si) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 8 22:03:36 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 08 Jul 2015 20:03:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Added_regressi?= =?utf-8?q?on_test_for_issue24581=2E?= Message-ID: <20150708200334.7742.64975@psf.io> https://hg.python.org/cpython/rev/8644744f53ce changeset: 96882:8644744f53ce branch: 3.4 parent: 96870:ed6ec65f50d2 user: Serhiy Storchaka date: Wed Jul 08 22:58:55 2015 +0300 summary: Added regression test for issue24581. files: Lib/test/test_set.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1731,6 +1731,17 @@ be_bad = True set1.symmetric_difference_update(dict2) + def test_iter_and_mutate(self): + # Issue #24581 + s = set(range(100)) + s.clear() + s.update(range(100)) + si = iter(s) + s.clear() + a = list(range(100)) + s.update(range(100)) + list(si) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 9 05:19:45 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 09 Jul 2015 03:19:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTg1?= =?utf-8?q?=3A_Enables_build-to-build_upgrades_that_preserve_settings=2E?= Message-ID: <20150709031945.10428.23510@psf.io> https://hg.python.org/cpython/rev/8e18d615988e changeset: 96886:8e18d615988e branch: 3.5 parent: 96884:844bd42326fa user: Steve Dower date: Wed Jul 08 20:18:44 2015 -0700 summary: Issue #24585: Enables build-to-build upgrades that preserve settings. Rather than using Burn "Persisted" variables we now add registry keys for each added feature. These can be detected by the installer regardless of which version installed them, and we use this for Modify and Upgrade. In particular, Upgrades can't access the Persisted variables, but can find well-known registry keys. There are also some changes to the bootstrap app to properly handle upgrades. Finally, a few minor improvements to the Windows build to keep things tidier. files: PCbuild/build.bat | 27 +- PCbuild/python.props | 39 +- Tools/msi/build.bat | 8 +- Tools/msi/bundle/Default.thm | 13 +- Tools/msi/bundle/Default.wxl | 14 +- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 367 +++++++-- Tools/msi/bundle/bootstrap/pythonba.vcxproj | 2 +- Tools/msi/bundle/bundle.wxs | 40 +- Tools/msi/bundle/packagegroups/core.wxs | 6 + Tools/msi/bundle/packagegroups/dev.wxs | 4 + Tools/msi/bundle/packagegroups/doc.wxs | 2 + Tools/msi/bundle/packagegroups/exe.wxs | 6 + Tools/msi/bundle/packagegroups/lib.wxs | 6 + Tools/msi/bundle/packagegroups/postinstall.wxs | 4 + Tools/msi/bundle/packagegroups/tcltk.wxs | 6 + Tools/msi/bundle/packagegroups/test.wxs | 6 + Tools/msi/bundle/packagegroups/tools.wxs | 2 + Tools/msi/common.wxs | 9 + Tools/msi/core/core_d.wxs | 1 + Tools/msi/core/core_pdb.wxs | 1 + Tools/msi/dev/dev.wxs | 1 + Tools/msi/doc/doc.wxs | 5 +- Tools/msi/exe/exe.wxs | 2 + Tools/msi/exe/exe_files.wxs | 1 + Tools/msi/launcher/launcher_files.wxs | 5 +- Tools/msi/launcher/launcher_reg.wxs | 2 +- Tools/msi/lib/lib.wxs | 1 + Tools/msi/msi.props | 6 +- Tools/msi/path/path.wxs | 8 +- Tools/msi/pip/pip.wxs | 4 +- Tools/msi/tcltk/tcltk.wxs | 1 + Tools/msi/test/test.wxs | 1 + Tools/msi/tools/tools.wxs | 1 + 33 files changed, 461 insertions(+), 140 deletions(-) diff --git a/PCbuild/build.bat b/PCbuild/build.bat --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -25,16 +25,17 @@ set kill= :CheckOpts -if '%1'=='-c' (set conf=%2) & shift & shift & goto CheckOpts -if '%1'=='-p' (set platf=%2) & shift & shift & goto CheckOpts -if '%1'=='-r' (set target=Rebuild) & shift & goto CheckOpts -if '%1'=='-t' (set target=%2) & shift & shift & goto CheckOpts -if '%1'=='-d' (set conf=Debug) & shift & goto CheckOpts -if '%1'=='-e' call "%dir%get_externals.bat" & shift & goto CheckOpts -if '%1'=='-m' (set parallel=/m) & shift & goto CheckOpts -if '%1'=='-M' (set parallel=) & shift & goto CheckOpts -if '%1'=='-v' (set verbose=/v:n) & shift & goto CheckOpts -if '%1'=='-k' (set kill=true) & shift & goto CheckOpts +if '%~1'=='-c' (set conf=%2) & shift & shift & goto CheckOpts +if '%~1'=='-p' (set platf=%2) & shift & shift & goto CheckOpts +if '%~1'=='-r' (set target=Rebuild) & shift & goto CheckOpts +if '%~1'=='-t' (set target=%2) & shift & shift & goto CheckOpts +if '%~1'=='-d' (set conf=Debug) & shift & goto CheckOpts +if '%~1'=='-e' call "%dir%get_externals.bat" & shift & goto CheckOpts +if '%~1'=='-m' (set parallel=/m) & shift & goto CheckOpts +if '%~1'=='-M' (set parallel=) & shift & goto CheckOpts +if '%~1'=='-v' (set verbose=/v:n) & shift & goto CheckOpts +if '%~1'=='-k' (set kill=true) & shift & goto CheckOpts +if '%~1'=='-V' shift & goto Version if '%platf%'=='x64' (set vs_platf=x86_amd64) @@ -50,3 +51,9 @@ rem batch is, shall we say, "lackluster" echo on msbuild "%dir%pcbuild.proj" /t:%target% %parallel% %verbose% /p:Configuration=%conf% /p:Platform=%platf% %1 %2 %3 %4 %5 %6 %7 %8 %9 + + at goto :eof + +:Version +rem Display the current build version information +msbuild "%dir%python.props" /t:ShowVersionInfo /v:m /nologo %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -42,7 +42,9 @@ $(BuildPath)python$(PyDebugExt).exe - + + + + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[2].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[3].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[4].Value) + <_ReleaseLevel>$([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[5].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[6].Value) + 0 + 15 + 10 + 11 + 12 + + + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber) $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)$(ReleaseLevelName) $([msbuild]::BitwiseOr( @@ -110,7 +145,7 @@ - + diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,10 +8,10 @@ set BUILDDOC= :CheckOpts -if "%1" EQU "-h" goto Help -if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts -if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts -if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "-h" goto Help +if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,13 +21,24 @@ #(loc.InstallMessage) - + #(loc.ShortPrependPathLabel) + + #(loc.InstallUpgradeHeader) + + + #(loc.InstallUpgradeMessage) + + + + + + #(loc.InstallHeader) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -21,6 +21,8 @@ Install [WixBundleName] Select Install Now to install Python with default settings, or choose Customize to enable or disable features. Version [WixBundleVersion] + Upgrade to [WixBundleName] + Select Upgrade Now to keep your current settings, or choose Customize to enable or disable features. Are you sure you want to cancel? Previous version Setup Help @@ -40,8 +42,8 @@ Logs to a specific file. By default, log files are created in %TEMP%. [WixBundleName] <a href="#">license terms</a>. I &agree to the license terms and conditions - &Install Now - [DefaultJustForMeTargetDir] + &Install Now + [DefaultJustForMeTargetDir] Includes IDLE, pip and documentation Creates shortcuts and file associations @@ -49,6 +51,13 @@ Choose location and features &Install Uses setting preselected by your administrator + &Upgrade Now + [TargetDir] + +Replaces your existing installation without changing settings. +Select Customize to review current options. + C&ustomize installation + Choose location and features Optional Features Advanced Options Customize install location @@ -107,4 +116,5 @@ One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. You must restart your computer to complete the rollback of the software. &Restart + Unable to install [WixBundleName] due to an existing install. Use Programs and Features to modify, repair or remove [WixBundleName]. diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -47,6 +47,7 @@ PAGE_LOADING, PAGE_HELP, PAGE_INSTALL, + PAGE_UPGRADE, PAGE_SIMPLE_INSTALL, PAGE_CUSTOM1, PAGE_CUSTOM2, @@ -63,6 +64,7 @@ L"Loading", L"Help", L"Install", + L"Upgrade", L"SimpleInstall", L"Custom1", L"Custom2", @@ -79,10 +81,11 @@ ID_MINIMIZE_BUTTON, // Welcome page - ID_INSTALL_ALL_USERS_BUTTON, - ID_INSTALL_JUST_FOR_ME_BUTTON, + ID_INSTALL_BUTTON, ID_INSTALL_CUSTOM_BUTTON, ID_INSTALL_SIMPLE_BUTTON, + ID_INSTALL_UPGRADE_BUTTON, + ID_INSTALL_UPGRADE_CUSTOM_BUTTON, ID_INSTALL_CANCEL_BUTTON, // Customize Page @@ -141,10 +144,11 @@ { ID_CLOSE_BUTTON, L"CloseButton" }, { ID_MINIMIZE_BUTTON, L"MinimizeButton" }, - { ID_INSTALL_ALL_USERS_BUTTON, L"InstallAllUsersButton" }, - { ID_INSTALL_JUST_FOR_ME_BUTTON, L"InstallJustForMeButton" }, + { ID_INSTALL_BUTTON, L"InstallButton" }, { ID_INSTALL_CUSTOM_BUTTON, L"InstallCustomButton" }, { ID_INSTALL_SIMPLE_BUTTON, L"InstallSimpleButton" }, + { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" }, + { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" }, { ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" }, { ID_TARGETDIR_EDITBOX, L"TargetDir" }, @@ -191,13 +195,35 @@ { ID_FAILURE_CANCEL_BUTTON, L"FailureCancelButton" }, }; +static struct { LPCWSTR regName; LPCWSTR variableName; } OPTIONAL_FEATURES[] = { + { L"core_d", L"Include_debug" }, + { L"core_pdb", L"Include_symbols" }, + { L"dev", L"Include_dev" }, + { L"doc", L"Include_doc" }, + { L"exe", L"Include_exe" }, + { L"lib", L"Include_lib" }, + { L"path", L"PrependPath" }, + { L"pip", L"Include_pip" }, + { L"tcltk", L"Include_tcltk" }, + { L"test", L"Include_test" }, + { L"tools", L"Include_tools" }, + { L"Shortcuts", L"Shortcuts" }, + // Include_launcher and AssociateFiles are handled separately and so do + // not need to be included in this list. + { nullptr, nullptr } +}; + + + class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { void ShowPage(DWORD newPageId) { // Process each control for special handling in the new page. ProcessPageControls(ThemeGetPage(_theme, newPageId)); // Enable disable controls per-page. - if (_pageIds[PAGE_INSTALL] == newPageId || _pageIds[PAGE_SIMPLE_INSTALL] == newPageId) { + if (_pageIds[PAGE_INSTALL] == newPageId || + _pageIds[PAGE_SIMPLE_INSTALL] == newPageId || + _pageIds[PAGE_UPGRADE] == newPageId) { InstallPage_Show(); } else if (_pageIds[PAGE_CUSTOM1] == newPageId) { Custom1Page_Show(); @@ -222,7 +248,7 @@ // On the install page set the focus to the install button or // the next enabled control if install is disabled if (_pageIds[PAGE_INSTALL] == newPageId) { - ThemeSetFocus(_theme, ID_INSTALL_ALL_USERS_BUTTON); + ThemeSetFocus(_theme, ID_INSTALL_BUTTON); } else if (_pageIds[PAGE_SIMPLE_INSTALL] == newPageId) { ThemeSetFocus(_theme, ID_INSTALL_SIMPLE_BUTTON); } @@ -234,7 +260,7 @@ void OnCommand(CONTROL_ID id) { LPWSTR defaultDir = nullptr; LPWSTR targetDir = nullptr; - LONGLONG elevated, crtInstalled; + LONGLONG elevated, crtInstalled, installAllUsers; BOOL checked; WCHAR wzPath[MAX_PATH] = { }; BROWSEINFOW browseInfo = { }; @@ -247,87 +273,42 @@ break; // Install commands - case ID_INSTALL_SIMPLE_BUTTON: - hr = BalGetStringVariable(L"TargetDir", &targetDir); - if (FAILED(hr) || !targetDir || !*targetDir) { - LONGLONG installAll; - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) { - hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default all users install directory"); - } else { - hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default per-user install directory"); - } - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); - } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); - ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); - } else { - ReleaseStr(targetDir); - } - - OnPlan(BOOTSTRAPPER_ACTION_INSTALL); - break; - - case ID_INSTALL_ALL_USERS_BUTTON: - SavePageSettings(); - - hr = _engine->SetVariableNumeric(L"InstallAllUsers", 1); - ExitOnFailure(hr, L"Failed to set install scope"); - - hr = _engine->SetVariableNumeric(L"CompileAll", 1); - ExitOnFailure(hr, L"Failed to set compile all setting"); - - hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default all users install directory"); - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); - } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); - ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); - - OnPlan(BOOTSTRAPPER_ACTION_INSTALL); - break; - - case ID_INSTALL_JUST_FOR_ME_BUTTON: + case ID_INSTALL_SIMPLE_BUTTON: __fallthrough; + case ID_INSTALL_UPGRADE_BUTTON: __fallthrough; + case ID_INSTALL_BUTTON: SavePageSettings(); if (!QueryElevateForCrtInstall()) { break; } - hr = _engine->SetVariableNumeric(L"InstallAllUsers", 0); - ExitOnFailure(hr, L"Failed to set install scope"); - - hr = _engine->SetVariableNumeric(L"CompileAll", 0); - ExitOnFailure(hr, L"Failed to unset CompileAll"); - - hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default per-user install directory"); - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); + hr = BalGetNumericVariable(L"InstallAllUsers", &installAllUsers); + ExitOnFailure(hr, L"Failed to get install scope"); + + hr = _engine->SetVariableNumeric(L"CompileAll", installAllUsers); + ExitOnFailure(hr, L"Failed to update CompileAll"); + + hr = BalGetStringVariable(L"TargetDir", &targetDir); + if (FAILED(hr) || !targetDir || !targetDir[0]) { + ReleaseStr(targetDir); + + hr = BalGetStringVariable( + installAllUsers ? L"DefaultAllUsersTargetDir" : L"DefaultJustForMeTargetDir", + &defaultDir + ); + BalExitOnFailure(hr, "Failed to get the default install directory"); + + if (!defaultDir || !defaultDir[0]) { + BalLogError(E_INVALIDARG, "Default install directory is blank"); + } + + hr = BalFormatString(defaultDir, &targetDir); + BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); + + hr = _engine->SetVariableString(L"TargetDir", targetDir); + BalExitOnFailure(hr, "Failed to set install target directory"); } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); OnPlan(BOOTSTRAPPER_ACTION_INSTALL); break; @@ -342,6 +323,7 @@ break; case ID_INSTALL_CUSTOM_BUTTON: __fallthrough; + case ID_INSTALL_UPGRADE_CUSTOM_BUTTON: __fallthrough; case ID_CUSTOM2_BACK_BUTTON: SavePageSettings(); GoToPage(PAGE_CUSTOM1); @@ -460,10 +442,11 @@ elevated = 0; } - ThemeControlElevates(_theme, ID_INSTALL_ALL_USERS_BUTTON, !elevated); - - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) { - ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, !elevated); + + if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) { + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE); + ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE); + ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE); } } @@ -667,7 +650,34 @@ // Remember when our bundle would cause a downgrade. if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) { - _downgrading = TRUE; + _downgradingOtherVersion = TRUE; + } else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) { + _upgradingOldVersion = TRUE; + + // Assume we don't want the launcher or file associations, and if + // they have already been installed then loading the state will + // reactivate these settings. + _engine->SetVariableNumeric(L"Include_launcher", 0); + _engine->SetVariableNumeric(L"AssociateFiles", 0); + auto hr = LoadLauncherStateFromKey(_engine, HKEY_CURRENT_USER); + if (hr == S_FALSE) { + hr = LoadLauncherStateFromKey(_engine, HKEY_LOCAL_MACHINE); + } + } else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == operation) { + if (_command.action == BOOTSTRAPPER_ACTION_INSTALL) { + LOC_STRING *pLocString = nullptr; + if (SUCCEEDED(LocGetString(_wixLoc, L"#(loc.FailureExistingInstall)", &pLocString)) && pLocString) { + BalFormatString(pLocString->wzText, &_failedMessage); + } else { + BalFormatString(L"Cannot install [WixBundleName] because it is already installed.", &_failedMessage); + } + BalLog( + BOOTSTRAPPER_LOG_LEVEL_ERROR, + "Related bundle %ls is preventing install", + wzBundleId + ); + SetState(PYBA_STATE_FAILED, E_WIXSTDBA_CONDITION_FAILED); + } } return CheckCanceled() ? IDCANCEL : IDOK; @@ -1969,7 +1979,7 @@ BalExitOnFailure(hr, "Failed to update strings"); // If we are going to apply a downgrade, bail. - if (_downgrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) { + if (_downgradingOtherVersion && BOOTSTRAPPER_ACTION_UNINSTALL < action) { if (_suppressDowngradeFailure) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); } else { @@ -2354,7 +2364,9 @@ if (_installPage == PAGE_LOADING) { switch (_command.action) { case BOOTSTRAPPER_ACTION_INSTALL: - if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) { + if (_upgradingOldVersion) { + _installPage = PAGE_UPGRADE; + } else if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) { _installPage = PAGE_SIMPLE_INSTALL; } else { _installPage = PAGE_INSTALL; @@ -2608,6 +2620,179 @@ } } + static bool IsTargetPlatformx64(__in IBootstrapperEngine* pEngine) { + WCHAR platform[8]; + DWORD platformLen = 8; + + if (FAILED(pEngine->GetVariableString(L"TargetPlatform", platform, &platformLen))) { + return S_FALSE; + } + + return ::CompareStringW(LOCALE_NEUTRAL, 0, platform, -1, L"x64", -1) == CSTR_EQUAL; + } + + static HRESULT LoadOptionalFeatureStatesFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive, + __in LPCWSTR subkey + ) { + HKEY hKey; + LRESULT res; + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + for (auto p = OPTIONAL_FEATURES; p->regName; ++p) { + res = RegQueryValueExW(hKey, p->regName, nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(p->variableName, 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(p->variableName, 1); + } else { + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(res); + } + } + + RegCloseKey(hKey); + return S_OK; + } + + static HRESULT LoadTargetDirFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive, + __in LPCWSTR subkey + ) { + HKEY hKey; + LRESULT res; + DWORD dataType; + BYTE buffer[1024]; + DWORD bufferLen = sizeof(buffer); + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + res = RegQueryValueExW(hKey, nullptr, nullptr, &dataType, buffer, &bufferLen); + if (res == ERROR_SUCCESS && dataType == REG_SZ && bufferLen < sizeof(buffer)) { + pEngine->SetVariableString(L"TargetDir", reinterpret_cast(buffer)); + } + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(res); + } + + static HRESULT LoadLauncherStateFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive + ) { + const LPCWSTR subkey = L"Software\\Python\\PyLauncher"; + HKEY hKey; + LRESULT res; + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + res = RegQueryValueExW(hKey, nullptr, nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(L"Include_launcher", 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(L"Include_launcher", 1); + } + + res = RegQueryValueExW(hKey, L"AssociateFiles", nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(L"AssociateFiles", 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(L"AssociateFiles", 1); + } + + RegCloseKey(hKey); + return S_OK; + } + + static void LoadOptionalFeatureStates(__in IBootstrapperEngine* pEngine) { + WCHAR subkeyFmt[256]; + WCHAR subkey[256]; + DWORD subkeyLen; + HRESULT hr; + HKEY hkHive; + + // The launcher installation is separate from the Python install, so we + // check its state later. This also checks the file association option. + + // Get the registry key from the bundle, to save having to duplicate it + // in multiple places. + subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); + hr = pEngine->GetVariableString(L"OptionalFeaturesRegistryKey", subkeyFmt, &subkeyLen); + BalExitOnFailure(hr, "Failed to locate registry key"); + subkeyLen = sizeof(subkey) / sizeof(subkey[0]); + hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); + BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); + + // Check the current user's registry for existing features + hkHive = HKEY_CURRENT_USER; + hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); + BalExitOnFailure1(hr, "Failed to read from HKCU\\%ls", subkey); + if (hr == S_FALSE) { + // Now check the local machine registry + hkHive = HKEY_LOCAL_MACHINE; + hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); + BalExitOnFailure1(hr, "Failed to read from HKLM\\%ls", subkey); + if (hr == S_OK) { + // Found a system-wide install, so enable these settings. + pEngine->SetVariableNumeric(L"InstallAllUsers", 1); + pEngine->SetVariableNumeric(L"CompileAll", 1); + } + } + + if (hr == S_OK) { + // Cannot change InstallAllUsersState when upgrading. While there's + // no good reason to not allow installing a per-user and an all-user + // version simultaneously, Burn can't handle the state management + // and will need to uninstall the old one. + pEngine->SetVariableString(L"InstallAllUsersState", L"disable"); + + // Get the previous install directory. This can be changed by the + // user. + subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); + hr = pEngine->GetVariableString(L"TargetDirRegistryKey", subkeyFmt, &subkeyLen); + BalExitOnFailure(hr, "Failed to locate registry key"); + subkeyLen = sizeof(subkey) / sizeof(subkey[0]); + hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); + BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); + LoadTargetDirFromKey(pEngine, hkHive, subkey); + } + + LExit: + return; + } public: // @@ -2667,7 +2852,8 @@ _installPage = PAGE_LOADING; _hrFinal = hrHostInitialization; - _downgrading = FALSE; + _downgradingOtherVersion = FALSE; + _upgradingOldVersion = FALSE; _restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; _restartRequired = FALSE; _allowRestart = FALSE; @@ -2690,6 +2876,8 @@ _hBAFModule = nullptr; _baFunction = nullptr; + + LoadOptionalFeatureStates(pEngine); } @@ -2748,7 +2936,8 @@ DWORD _calculatedCacheProgress; DWORD _calculatedExecuteProgress; - BOOL _downgrading; + BOOL _downgradingOtherVersion; + BOOL _upgradingOldVersion; BOOTSTRAPPER_APPLY_RESTART _restartResult; BOOL _restartRequired; BOOL _allowRestart; diff --git a/Tools/msi/bundle/bootstrap/pythonba.vcxproj b/Tools/msi/bundle/bootstrap/pythonba.vcxproj --- a/Tools/msi/bundle/bootstrap/pythonba.vcxproj +++ b/Tools/msi/bundle/bootstrap/pythonba.vcxproj @@ -31,7 +31,7 @@ DynamicLibrary Unicode - $(ProjectDir)..\..\obj\$(Configuration)_Bootstrap\ + $(PySourcePath)PCBuild\obj\$(Configuration)_$(Platform)_Setup\Bootstrap\ $(IntDir) diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -23,14 +23,18 @@ - - + + + + + + $(BuildPath)python$(PyDebugExt).exe - + + + + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[2].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[3].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[4].Value) + <_ReleaseLevel>$([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[5].Value) + $([System.Text.RegularExpressions.Regex]::Match($(OverrideVersion), `(\d+)\.(\d+)\.(\d+)((a|b|rc)(\d))?`).Groups[6].Value) + 0 + 15 + 10 + 11 + 12 + + + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber) $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)$(ReleaseLevelName) $([msbuild]::BitwiseOr( @@ -110,7 +145,7 @@ - + diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -8,10 +8,10 @@ set BUILDDOC= :CheckOpts -if "%1" EQU "-h" goto Help -if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts -if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts -if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "-h" goto Help +if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,13 +21,24 @@ #(loc.InstallMessage) - + #(loc.ShortPrependPathLabel) + + #(loc.InstallUpgradeHeader) + + + #(loc.InstallUpgradeMessage) + + + + + + #(loc.InstallHeader) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -21,6 +21,8 @@ Install [WixBundleName] Select Install Now to install Python with default settings, or choose Customize to enable or disable features. Version [WixBundleVersion] + Upgrade to [WixBundleName] + Select Upgrade Now to keep your current settings, or choose Customize to enable or disable features. Are you sure you want to cancel? Previous version Setup Help @@ -40,8 +42,8 @@ Logs to a specific file. By default, log files are created in %TEMP%. [WixBundleName] <a href="#">license terms</a>. I &agree to the license terms and conditions - &Install Now - [DefaultJustForMeTargetDir] + &Install Now + [DefaultJustForMeTargetDir] Includes IDLE, pip and documentation Creates shortcuts and file associations @@ -49,6 +51,13 @@ Choose location and features &Install Uses setting preselected by your administrator + &Upgrade Now + [TargetDir] + +Replaces your existing installation without changing settings. +Select Customize to review current options. + C&ustomize installation + Choose location and features Optional Features Advanced Options Customize install location @@ -107,4 +116,5 @@ One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. You must restart your computer to complete the rollback of the software. &Restart + Unable to install [WixBundleName] due to an existing install. Use Programs and Features to modify, repair or remove [WixBundleName]. diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -47,6 +47,7 @@ PAGE_LOADING, PAGE_HELP, PAGE_INSTALL, + PAGE_UPGRADE, PAGE_SIMPLE_INSTALL, PAGE_CUSTOM1, PAGE_CUSTOM2, @@ -63,6 +64,7 @@ L"Loading", L"Help", L"Install", + L"Upgrade", L"SimpleInstall", L"Custom1", L"Custom2", @@ -79,10 +81,11 @@ ID_MINIMIZE_BUTTON, // Welcome page - ID_INSTALL_ALL_USERS_BUTTON, - ID_INSTALL_JUST_FOR_ME_BUTTON, + ID_INSTALL_BUTTON, ID_INSTALL_CUSTOM_BUTTON, ID_INSTALL_SIMPLE_BUTTON, + ID_INSTALL_UPGRADE_BUTTON, + ID_INSTALL_UPGRADE_CUSTOM_BUTTON, ID_INSTALL_CANCEL_BUTTON, // Customize Page @@ -141,10 +144,11 @@ { ID_CLOSE_BUTTON, L"CloseButton" }, { ID_MINIMIZE_BUTTON, L"MinimizeButton" }, - { ID_INSTALL_ALL_USERS_BUTTON, L"InstallAllUsersButton" }, - { ID_INSTALL_JUST_FOR_ME_BUTTON, L"InstallJustForMeButton" }, + { ID_INSTALL_BUTTON, L"InstallButton" }, { ID_INSTALL_CUSTOM_BUTTON, L"InstallCustomButton" }, { ID_INSTALL_SIMPLE_BUTTON, L"InstallSimpleButton" }, + { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" }, + { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" }, { ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" }, { ID_TARGETDIR_EDITBOX, L"TargetDir" }, @@ -191,13 +195,35 @@ { ID_FAILURE_CANCEL_BUTTON, L"FailureCancelButton" }, }; +static struct { LPCWSTR regName; LPCWSTR variableName; } OPTIONAL_FEATURES[] = { + { L"core_d", L"Include_debug" }, + { L"core_pdb", L"Include_symbols" }, + { L"dev", L"Include_dev" }, + { L"doc", L"Include_doc" }, + { L"exe", L"Include_exe" }, + { L"lib", L"Include_lib" }, + { L"path", L"PrependPath" }, + { L"pip", L"Include_pip" }, + { L"tcltk", L"Include_tcltk" }, + { L"test", L"Include_test" }, + { L"tools", L"Include_tools" }, + { L"Shortcuts", L"Shortcuts" }, + // Include_launcher and AssociateFiles are handled separately and so do + // not need to be included in this list. + { nullptr, nullptr } +}; + + + class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { void ShowPage(DWORD newPageId) { // Process each control for special handling in the new page. ProcessPageControls(ThemeGetPage(_theme, newPageId)); // Enable disable controls per-page. - if (_pageIds[PAGE_INSTALL] == newPageId || _pageIds[PAGE_SIMPLE_INSTALL] == newPageId) { + if (_pageIds[PAGE_INSTALL] == newPageId || + _pageIds[PAGE_SIMPLE_INSTALL] == newPageId || + _pageIds[PAGE_UPGRADE] == newPageId) { InstallPage_Show(); } else if (_pageIds[PAGE_CUSTOM1] == newPageId) { Custom1Page_Show(); @@ -222,7 +248,7 @@ // On the install page set the focus to the install button or // the next enabled control if install is disabled if (_pageIds[PAGE_INSTALL] == newPageId) { - ThemeSetFocus(_theme, ID_INSTALL_ALL_USERS_BUTTON); + ThemeSetFocus(_theme, ID_INSTALL_BUTTON); } else if (_pageIds[PAGE_SIMPLE_INSTALL] == newPageId) { ThemeSetFocus(_theme, ID_INSTALL_SIMPLE_BUTTON); } @@ -234,7 +260,7 @@ void OnCommand(CONTROL_ID id) { LPWSTR defaultDir = nullptr; LPWSTR targetDir = nullptr; - LONGLONG elevated, crtInstalled; + LONGLONG elevated, crtInstalled, installAllUsers; BOOL checked; WCHAR wzPath[MAX_PATH] = { }; BROWSEINFOW browseInfo = { }; @@ -247,87 +273,42 @@ break; // Install commands - case ID_INSTALL_SIMPLE_BUTTON: - hr = BalGetStringVariable(L"TargetDir", &targetDir); - if (FAILED(hr) || !targetDir || !*targetDir) { - LONGLONG installAll; - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) { - hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default all users install directory"); - } else { - hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default per-user install directory"); - } - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); - } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); - ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); - } else { - ReleaseStr(targetDir); - } - - OnPlan(BOOTSTRAPPER_ACTION_INSTALL); - break; - - case ID_INSTALL_ALL_USERS_BUTTON: - SavePageSettings(); - - hr = _engine->SetVariableNumeric(L"InstallAllUsers", 1); - ExitOnFailure(hr, L"Failed to set install scope"); - - hr = _engine->SetVariableNumeric(L"CompileAll", 1); - ExitOnFailure(hr, L"Failed to set compile all setting"); - - hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default all users install directory"); - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); - } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); - ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); - - OnPlan(BOOTSTRAPPER_ACTION_INSTALL); - break; - - case ID_INSTALL_JUST_FOR_ME_BUTTON: + case ID_INSTALL_SIMPLE_BUTTON: __fallthrough; + case ID_INSTALL_UPGRADE_BUTTON: __fallthrough; + case ID_INSTALL_BUTTON: SavePageSettings(); if (!QueryElevateForCrtInstall()) { break; } - hr = _engine->SetVariableNumeric(L"InstallAllUsers", 0); - ExitOnFailure(hr, L"Failed to set install scope"); - - hr = _engine->SetVariableNumeric(L"CompileAll", 0); - ExitOnFailure(hr, L"Failed to unset CompileAll"); - - hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir); - BalExitOnFailure(hr, "Failed to get the default per-user install directory"); - - if (!defaultDir || !*defaultDir) { - BalLogError(E_INVALIDARG, "Default install directory is blank"); + hr = BalGetNumericVariable(L"InstallAllUsers", &installAllUsers); + ExitOnFailure(hr, L"Failed to get install scope"); + + hr = _engine->SetVariableNumeric(L"CompileAll", installAllUsers); + ExitOnFailure(hr, L"Failed to update CompileAll"); + + hr = BalGetStringVariable(L"TargetDir", &targetDir); + if (FAILED(hr) || !targetDir || !targetDir[0]) { + ReleaseStr(targetDir); + + hr = BalGetStringVariable( + installAllUsers ? L"DefaultAllUsersTargetDir" : L"DefaultJustForMeTargetDir", + &defaultDir + ); + BalExitOnFailure(hr, "Failed to get the default install directory"); + + if (!defaultDir || !defaultDir[0]) { + BalLogError(E_INVALIDARG, "Default install directory is blank"); + } + + hr = BalFormatString(defaultDir, &targetDir); + BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); + + hr = _engine->SetVariableString(L"TargetDir", targetDir); + BalExitOnFailure(hr, "Failed to set install target directory"); } - - hr = BalFormatString(defaultDir, &targetDir); - BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir); - - hr = _engine->SetVariableString(L"TargetDir", targetDir); ReleaseStr(targetDir); - BalExitOnFailure(hr, "Failed to set install target directory"); OnPlan(BOOTSTRAPPER_ACTION_INSTALL); break; @@ -342,6 +323,7 @@ break; case ID_INSTALL_CUSTOM_BUTTON: __fallthrough; + case ID_INSTALL_UPGRADE_CUSTOM_BUTTON: __fallthrough; case ID_CUSTOM2_BACK_BUTTON: SavePageSettings(); GoToPage(PAGE_CUSTOM1); @@ -460,10 +442,11 @@ elevated = 0; } - ThemeControlElevates(_theme, ID_INSTALL_ALL_USERS_BUTTON, !elevated); - - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) { - ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, !elevated); + + if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) { + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE); + ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE); + ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE); } } @@ -667,7 +650,34 @@ // Remember when our bundle would cause a downgrade. if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) { - _downgrading = TRUE; + _downgradingOtherVersion = TRUE; + } else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) { + _upgradingOldVersion = TRUE; + + // Assume we don't want the launcher or file associations, and if + // they have already been installed then loading the state will + // reactivate these settings. + _engine->SetVariableNumeric(L"Include_launcher", 0); + _engine->SetVariableNumeric(L"AssociateFiles", 0); + auto hr = LoadLauncherStateFromKey(_engine, HKEY_CURRENT_USER); + if (hr == S_FALSE) { + hr = LoadLauncherStateFromKey(_engine, HKEY_LOCAL_MACHINE); + } + } else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == operation) { + if (_command.action == BOOTSTRAPPER_ACTION_INSTALL) { + LOC_STRING *pLocString = nullptr; + if (SUCCEEDED(LocGetString(_wixLoc, L"#(loc.FailureExistingInstall)", &pLocString)) && pLocString) { + BalFormatString(pLocString->wzText, &_failedMessage); + } else { + BalFormatString(L"Cannot install [WixBundleName] because it is already installed.", &_failedMessage); + } + BalLog( + BOOTSTRAPPER_LOG_LEVEL_ERROR, + "Related bundle %ls is preventing install", + wzBundleId + ); + SetState(PYBA_STATE_FAILED, E_WIXSTDBA_CONDITION_FAILED); + } } return CheckCanceled() ? IDCANCEL : IDOK; @@ -1969,7 +1979,7 @@ BalExitOnFailure(hr, "Failed to update strings"); // If we are going to apply a downgrade, bail. - if (_downgrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) { + if (_downgradingOtherVersion && BOOTSTRAPPER_ACTION_UNINSTALL < action) { if (_suppressDowngradeFailure) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); } else { @@ -2354,7 +2364,9 @@ if (_installPage == PAGE_LOADING) { switch (_command.action) { case BOOTSTRAPPER_ACTION_INSTALL: - if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) { + if (_upgradingOldVersion) { + _installPage = PAGE_UPGRADE; + } else if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) { _installPage = PAGE_SIMPLE_INSTALL; } else { _installPage = PAGE_INSTALL; @@ -2608,6 +2620,179 @@ } } + static bool IsTargetPlatformx64(__in IBootstrapperEngine* pEngine) { + WCHAR platform[8]; + DWORD platformLen = 8; + + if (FAILED(pEngine->GetVariableString(L"TargetPlatform", platform, &platformLen))) { + return S_FALSE; + } + + return ::CompareStringW(LOCALE_NEUTRAL, 0, platform, -1, L"x64", -1) == CSTR_EQUAL; + } + + static HRESULT LoadOptionalFeatureStatesFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive, + __in LPCWSTR subkey + ) { + HKEY hKey; + LRESULT res; + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + for (auto p = OPTIONAL_FEATURES; p->regName; ++p) { + res = RegQueryValueExW(hKey, p->regName, nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(p->variableName, 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(p->variableName, 1); + } else { + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(res); + } + } + + RegCloseKey(hKey); + return S_OK; + } + + static HRESULT LoadTargetDirFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive, + __in LPCWSTR subkey + ) { + HKEY hKey; + LRESULT res; + DWORD dataType; + BYTE buffer[1024]; + DWORD bufferLen = sizeof(buffer); + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + res = RegQueryValueExW(hKey, nullptr, nullptr, &dataType, buffer, &bufferLen); + if (res == ERROR_SUCCESS && dataType == REG_SZ && bufferLen < sizeof(buffer)) { + pEngine->SetVariableString(L"TargetDir", reinterpret_cast(buffer)); + } + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(res); + } + + static HRESULT LoadLauncherStateFromKey( + __in IBootstrapperEngine* pEngine, + __in HKEY hkHive + ) { + const LPCWSTR subkey = L"Software\\Python\\PyLauncher"; + HKEY hKey; + LRESULT res; + + if (IsTargetPlatformx64(pEngine)) { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + } else { + res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + } + + if (res == ERROR_FILE_NOT_FOUND) { + return S_FALSE; + } + if (res != ERROR_SUCCESS) { + return HRESULT_FROM_WIN32(res); + } + + res = RegQueryValueExW(hKey, nullptr, nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(L"Include_launcher", 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(L"Include_launcher", 1); + } + + res = RegQueryValueExW(hKey, L"AssociateFiles", nullptr, nullptr, nullptr, nullptr); + if (res == ERROR_FILE_NOT_FOUND) { + pEngine->SetVariableNumeric(L"AssociateFiles", 0); + } else if (res == ERROR_SUCCESS) { + pEngine->SetVariableNumeric(L"AssociateFiles", 1); + } + + RegCloseKey(hKey); + return S_OK; + } + + static void LoadOptionalFeatureStates(__in IBootstrapperEngine* pEngine) { + WCHAR subkeyFmt[256]; + WCHAR subkey[256]; + DWORD subkeyLen; + HRESULT hr; + HKEY hkHive; + + // The launcher installation is separate from the Python install, so we + // check its state later. This also checks the file association option. + + // Get the registry key from the bundle, to save having to duplicate it + // in multiple places. + subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); + hr = pEngine->GetVariableString(L"OptionalFeaturesRegistryKey", subkeyFmt, &subkeyLen); + BalExitOnFailure(hr, "Failed to locate registry key"); + subkeyLen = sizeof(subkey) / sizeof(subkey[0]); + hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); + BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); + + // Check the current user's registry for existing features + hkHive = HKEY_CURRENT_USER; + hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); + BalExitOnFailure1(hr, "Failed to read from HKCU\\%ls", subkey); + if (hr == S_FALSE) { + // Now check the local machine registry + hkHive = HKEY_LOCAL_MACHINE; + hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); + BalExitOnFailure1(hr, "Failed to read from HKLM\\%ls", subkey); + if (hr == S_OK) { + // Found a system-wide install, so enable these settings. + pEngine->SetVariableNumeric(L"InstallAllUsers", 1); + pEngine->SetVariableNumeric(L"CompileAll", 1); + } + } + + if (hr == S_OK) { + // Cannot change InstallAllUsersState when upgrading. While there's + // no good reason to not allow installing a per-user and an all-user + // version simultaneously, Burn can't handle the state management + // and will need to uninstall the old one. + pEngine->SetVariableString(L"InstallAllUsersState", L"disable"); + + // Get the previous install directory. This can be changed by the + // user. + subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); + hr = pEngine->GetVariableString(L"TargetDirRegistryKey", subkeyFmt, &subkeyLen); + BalExitOnFailure(hr, "Failed to locate registry key"); + subkeyLen = sizeof(subkey) / sizeof(subkey[0]); + hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); + BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); + LoadTargetDirFromKey(pEngine, hkHive, subkey); + } + + LExit: + return; + } public: // @@ -2667,7 +2852,8 @@ _installPage = PAGE_LOADING; _hrFinal = hrHostInitialization; - _downgrading = FALSE; + _downgradingOtherVersion = FALSE; + _upgradingOldVersion = FALSE; _restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; _restartRequired = FALSE; _allowRestart = FALSE; @@ -2690,6 +2876,8 @@ _hBAFModule = nullptr; _baFunction = nullptr; + + LoadOptionalFeatureStates(pEngine); } @@ -2748,7 +2936,8 @@ DWORD _calculatedCacheProgress; DWORD _calculatedExecuteProgress; - BOOL _downgrading; + BOOL _downgradingOtherVersion; + BOOL _upgradingOldVersion; BOOTSTRAPPER_APPLY_RESTART _restartResult; BOOL _restartRequired; BOOL _allowRestart; diff --git a/Tools/msi/bundle/bootstrap/pythonba.vcxproj b/Tools/msi/bundle/bootstrap/pythonba.vcxproj --- a/Tools/msi/bundle/bootstrap/pythonba.vcxproj +++ b/Tools/msi/bundle/bootstrap/pythonba.vcxproj @@ -31,7 +31,7 @@ DynamicLibrary Unicode - $(ProjectDir)..\..\obj\$(Configuration)_Bootstrap\ + $(PySourcePath)PCBuild\obj\$(Configuration)_$(Platform)_Setup\Bootstrap\ $(IntDir) diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -23,14 +23,18 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props new file mode 100644 --- /dev/null +++ b/PCbuild/openssl.props @@ -0,0 +1,75 @@ +? + + + + + StaticLibrary + $(opensslDir)tmp\$(ArchName)_$(Configuration)\$(ProjectName)\ + $(opensslDir)tmp\$(ArchName)\$(ProjectName)\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_PreprocessorDefinitionList>@(PreprocessorDefinitions) + + + + + + 4244;4267 + $(opensslDir);$(opensslDir)include;$(opensslDir)crypto;$(opensslDir)crypto\asn1;$(opensslDir)crypto\evp;$(opensslDir)crypto\modes + $(_PreprocessorDefinitionList);%(PreprocessorDefinitions) + + + + + + nasm.exe -f win32 + nasm.exe -f win64 -DNEAR -Ox -g + + + + + + + + + + + diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj new file mode 100644 --- /dev/null +++ b/PCbuild/pcbuild.proj @@ -0,0 +1,77 @@ +? + + + {CC9B93A2-439D-4058-9D29-6DCF43774405} + Win32 + Release + true + true + true + + + + + $(Platform) + $(Configuration) + + Build + Clean + CleanAll + true + + + + + + + false + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -1,136 +1,65 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} = {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_versioninfo", "make_versioninfo.vcproj", "{F0E0541E-F17D-430B-97C4-93ADF0DD284E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" - ProjectSection(ProjectDependencies) = postProject - {F0E0541E-F17D-430B-97C4-93ADF0DD284E} = {F0E0541E-F17D-430B-97C4-93ADF0DD284E} - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} = {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} - {C73F0EC1-358B-4177-940F-0846AC8B04CD} = {C73F0EC1-358B-4177-940F-0846AC8B04CD} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw", "pythonw.vcproj", "{F4229CC3-873C-49AE-9729-DD308ED4CD4A}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "w9xpopen", "w9xpopen.vcproj", "{E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}" - ProjectSection(ProjectDependencies) = postProject - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} = {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_buildinfo", "make_buildinfo.vcproj", "{C73F0EC1-358B-4177-940F-0846AC8B04CD}" -EndProject +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}" ProjectSection(SolutionItems) = preProject ..\Modules\getbuildinfo.c = ..\Modules\getbuildinfo.c - readme.txt = readme.txt EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winsound", "winsound.vcproj", "{28B5D777-DDF2-4B6B-B34F-31D938813856}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcxproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_bsddb", "_bsddb.vcproj", "{B4D38F3F-68FB-42EC-A45D-E00657BB3627}" - ProjectSection(ProjectDependencies) = postProject - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} = {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcxproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes", "_ctypes.vcproj", "{0E9791DB-593A-465F-98BC-681011311618}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw", "pythonw.vcxproj", "{F4229CC3-873C-49AE-9729-DD308ED4CD4A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_test.vcproj", "{9EC7190A-249F-4180-A900-548FDCF3055F}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "w9xpopen", "w9xpopen.vcxproj", "{E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcproj", "{17E1E049-C309-4D79-843F-AE483C264AEA}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winsound", "winsound.vcxproj", "{28B5D777-DDF2-4B6B-B34F-31D938813856}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi.vcproj", "{31FFC478-7B4A-43E8-9954-8D03E2187E9C}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_bsddb", "_bsddb.vcxproj", "{B4D38F3F-68FB-42EC-A45D-E00657BB3627}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket.vcproj", "{86937F53-C189-40EF-8CE8-8759D8E7D480}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes", "_ctypes.vcxproj", "{0E9791DB-593A-465F-98BC-681011311618}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcproj", "{13CECB97-4119-4316-9D42-8534019A5A44}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - {A1A295E5-463C-437F-81CA-1F32367685DA} = {A1A295E5-463C-437F-81CA-1F32367685DA} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_test.vcxproj", "{9EC7190A-249F-4180-A900-548FDCF3055F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ssl", "_ssl.vcproj", "{C6E20F84-3247-4AD6-B051-B073268F73BA}" - ProjectSection(ProjectDependencies) = postProject - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9} = {B11D750F-CD1F-4A96-85CE-E69A5C5259F9} - {86937F53-C189-40EF-8CE8-8759D8E7D480} = {86937F53-C189-40EF-8CE8-8759D8E7D480} - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcxproj", "{17E1E049-C309-4D79-843F-AE483C264AEA}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testcapi", "_testcapi.vcproj", "{6901D91C-6E48-4BB7-9FEC-700C8131DF1D}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi.vcxproj", "{31FFC478-7B4A-43E8-9954-8D03E2187E9C}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_tkinter", "_tkinter.vcproj", "{4946ECAC-2E69-4BF8-A90A-F5136F5094DF}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket.vcxproj", "{86937F53-C189-40EF-8CE8-8759D8E7D480}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bz2", "bz2.vcproj", "{73FCD2BD-F133-46B7-8EC1-144CD82A59D5}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcxproj", "{13CECB97-4119-4316-9D42-8534019A5A44}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "select", "select.vcproj", "{18CAE28C-B454-46C1-87A0-493D91D97F03}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ssl", "_ssl.vcxproj", "{C6E20F84-3247-4AD6-B051-B073268F73BA}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicodedata", "unicodedata.vcproj", "{ECC7CEAC-A5E5-458E-BB9E-2413CC847881}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testcapi", "_testcapi.vcxproj", "{6901D91C-6E48-4BB7-9FEC-700C8131DF1D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyexpat", "pyexpat.vcproj", "{D06B6426-4762-44CC-8BAD-D79052507F2F}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_tkinter", "_tkinter.vcxproj", "{4946ECAC-2E69-4BF8-A90A-F5136F5094DF}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bdist_wininst", "bdist_wininst.vcproj", "{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bz2", "bz2.vcxproj", "{73FCD2BD-F133-46B7-8EC1-144CD82A59D5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_hashlib", "_hashlib.vcproj", "{447F05A8-F581-4CAC-A466-5AC7936E207E}" - ProjectSection(ProjectDependencies) = postProject - {B11D750F-CD1F-4A96-85CE-E69A5C5259F9} = {B11D750F-CD1F-4A96-85CE-E69A5C5259F9} - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "select", "select.vcxproj", "{18CAE28C-B454-46C1-87A0-493D91D97F03}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite3", "sqlite3.vcproj", "{A1A295E5-463C-437F-81CA-1F32367685DA}" - ProjectSection(ProjectDependencies) = postProject - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} = {6DE10744-E396-40A5-B4E2-1B69AA7C8D31} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicodedata", "unicodedata.vcxproj", "{ECC7CEAC-A5E5-458E-BB9E-2413CC847881}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_multiprocessing", "_multiprocessing.vcproj", "{9E48B300-37D1-11DD-8C41-005056C00008}" - ProjectSection(ProjectDependencies) = postProject - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyexpat", "pyexpat.vcxproj", "{D06B6426-4762-44CC-8BAD-D79052507F2F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kill_python", "kill_python.vcproj", "{6DE10744-E396-40A5-B4E2-1B69AA7C8D31}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bdist_wininst", "..\PC\bdist_wininst\bdist_wininst.vcxproj", "{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_hashlib", "_hashlib.vcxproj", "{447F05A8-F581-4CAC-A466-5AC7936E207E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite3", "sqlite3.vcxproj", "{A1A295E5-463C-437F-81CA-1F32367685DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_multiprocessing", "_multiprocessing.vcxproj", "{9E48B300-37D1-11DD-8C41-005056C00008}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcl", "tcl.vcxproj", "{B5FD6F1D-129E-4BFF-9340-03606FAC7283}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tix", "tix.vcxproj", "{C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tk", "tk.vcxproj", "{7E85ECCF-A72C-4DA4-9E52-884508E80BA1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libeay", "libeay.vcxproj", "{E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssleay", "ssleay.vcxproj", "{10615B24-73BF-4EFA-93AA-236916321317}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -160,22 +89,6 @@ {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|Win32.Build.0 = Release|Win32 {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|x64.ActiveCfg = Release|x64 {B11D750F-CD1F-4A96-85CE-E69A5C5259F9}.Release|x64.Build.0 = Release|x64 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|Win32.ActiveCfg = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|Win32.Build.0 = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|x64.ActiveCfg = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Debug|x64.Build.0 = Debug|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGInstrument|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGInstrument|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGInstrument|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGInstrument|x64.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGUpdate|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGUpdate|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGUpdate|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.PGUpdate|x64.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|Win32.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|Win32.Build.0 = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|x64.ActiveCfg = Release|Win32 - {F0E0541E-F17D-430B-97C4-93ADF0DD284E}.Release|x64.Build.0 = Release|Win32 {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|Win32.ActiveCfg = Debug|Win32 {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|Win32.Build.0 = Debug|Win32 {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}.Debug|x64.ActiveCfg = Debug|x64 @@ -196,14 +109,14 @@ {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|Win32.Build.0 = Debug|Win32 {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|x64.ActiveCfg = Debug|x64 {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Debug|x64.Build.0 = Debug|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|Win32.Build.0 = Release|Win32 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|x64.ActiveCfg = Release|x64 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGInstrument|x64.Build.0 = Release|x64 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|Win32.Build.0 = Release|Win32 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|x64.ActiveCfg = Release|x64 + {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.PGUpdate|x64.Build.0 = Release|x64 {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|Win32.ActiveCfg = Release|Win32 {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|Win32.Build.0 = Release|Win32 {F4229CC3-873C-49AE-9729-DD308ED4CD4A}.Release|x64.ActiveCfg = Release|x64 @@ -292,14 +205,14 @@ {9EC7190A-249F-4180-A900-548FDCF3055F}.Debug|Win32.Build.0 = Debug|Win32 {9EC7190A-249F-4180-A900-548FDCF3055F}.Debug|x64.ActiveCfg = Debug|x64 {9EC7190A-249F-4180-A900-548FDCF3055F}.Debug|x64.Build.0 = Debug|x64 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|Win32.Build.0 = Release|Win32 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|x64.ActiveCfg = Release|x64 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGInstrument|x64.Build.0 = Release|x64 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|Win32.Build.0 = Release|Win32 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|x64.ActiveCfg = Release|x64 + {9EC7190A-249F-4180-A900-548FDCF3055F}.PGUpdate|x64.Build.0 = Release|x64 {9EC7190A-249F-4180-A900-548FDCF3055F}.Release|Win32.ActiveCfg = Release|Win32 {9EC7190A-249F-4180-A900-548FDCF3055F}.Release|Win32.Build.0 = Release|Win32 {9EC7190A-249F-4180-A900-548FDCF3055F}.Release|x64.ActiveCfg = Release|x64 @@ -536,22 +449,86 @@ {9E48B300-37D1-11DD-8C41-005056C00008}.Release|Win32.Build.0 = Release|Win32 {9E48B300-37D1-11DD-8C41-005056C00008}.Release|x64.ActiveCfg = Release|x64 {9E48B300-37D1-11DD-8C41-005056C00008}.Release|x64.Build.0 = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Debug|Win32.Build.0 = Debug|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Debug|x64.ActiveCfg = Debug|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Debug|x64.Build.0 = Debug|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGInstrument|Win32.ActiveCfg = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGInstrument|Win32.Build.0 = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGInstrument|x64.ActiveCfg = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGInstrument|x64.Build.0 = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGUpdate|Win32.ActiveCfg = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGUpdate|Win32.Build.0 = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGUpdate|x64.ActiveCfg = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.PGUpdate|x64.Build.0 = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Release|Win32.ActiveCfg = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Release|Win32.Build.0 = Release|Win32 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Release|x64.ActiveCfg = Release|x64 - {6DE10744-E396-40A5-B4E2-1B69AA7C8D31}.Release|x64.Build.0 = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.ActiveCfg = Debug|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.Build.0 = Debug|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|x64.ActiveCfg = Debug|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|x64.Build.0 = Debug|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGInstrument|Win32.Build.0 = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGInstrument|x64.ActiveCfg = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGInstrument|x64.Build.0 = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGUpdate|Win32.Build.0 = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGUpdate|x64.ActiveCfg = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.PGUpdate|x64.Build.0 = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Release|Win32.ActiveCfg = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Release|Win32.Build.0 = Release|Win32 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Release|x64.ActiveCfg = Release|x64 + {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Release|x64.Build.0 = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Debug|Win32.ActiveCfg = Debug|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Debug|Win32.Build.0 = Debug|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Debug|x64.ActiveCfg = Debug|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Debug|x64.Build.0 = Debug|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGInstrument|Win32.Build.0 = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGInstrument|x64.ActiveCfg = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGInstrument|x64.Build.0 = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGUpdate|Win32.Build.0 = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGUpdate|x64.ActiveCfg = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.PGUpdate|x64.Build.0 = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Release|Win32.ActiveCfg = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Release|Win32.Build.0 = Release|Win32 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Release|x64.ActiveCfg = Release|x64 + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}.Release|x64.Build.0 = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Debug|Win32.ActiveCfg = Debug|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Debug|Win32.Build.0 = Debug|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Debug|x64.ActiveCfg = Debug|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Debug|x64.Build.0 = Debug|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGInstrument|Win32.Build.0 = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGInstrument|x64.ActiveCfg = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGInstrument|x64.Build.0 = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGUpdate|Win32.Build.0 = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGUpdate|x64.ActiveCfg = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.PGUpdate|x64.Build.0 = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Release|Win32.ActiveCfg = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Release|Win32.Build.0 = Release|Win32 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Release|x64.ActiveCfg = Release|x64 + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1}.Release|x64.Build.0 = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Debug|Win32.ActiveCfg = Debug|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Debug|Win32.Build.0 = Debug|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Debug|x64.ActiveCfg = Debug|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Debug|x64.Build.0 = Debug|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGInstrument|Win32.Build.0 = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGInstrument|x64.ActiveCfg = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGInstrument|x64.Build.0 = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGUpdate|Win32.Build.0 = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGUpdate|x64.ActiveCfg = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.PGUpdate|x64.Build.0 = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Release|Win32.ActiveCfg = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Release|Win32.Build.0 = Release|Win32 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Release|x64.ActiveCfg = Release|x64 + {E5B04CC0-EB4C-42AB-B4DC-18EF95F864B0}.Release|x64.Build.0 = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.Debug|Win32.ActiveCfg = Debug|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.Debug|Win32.Build.0 = Debug|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.Debug|x64.ActiveCfg = Debug|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.Debug|x64.Build.0 = Debug|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.PGInstrument|Win32.Build.0 = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.PGInstrument|x64.ActiveCfg = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.PGInstrument|x64.Build.0 = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.PGUpdate|Win32.Build.0 = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.PGUpdate|x64.ActiveCfg = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.PGUpdate|x64.Build.0 = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.Release|Win32.ActiveCfg = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.Release|Win32.Build.0 = Release|Win32 + {10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.ActiveCfg = Release|x64 + {10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PCbuild/pyexpat.vcxproj b/PCbuild/pyexpat.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/pyexpat.vcxproj @@ -0,0 +1,84 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + <_ProjectFileVersion>10.0.30319.1 + {D06B6426-4762-44CC-8BAD-D79052507F2F} + pyexpat + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + + $(PySourcePath)Modules\expat;%(AdditionalIncludeDirectories) + PYEXPAT_EXPORTS;HAVE_EXPAT_H;XML_NS;XML_DTD;BYTEORDER=1234;XML_CONTEXT_BYTES=1024;XML_STATIC;HAVE_MEMMOVE;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/pyexpat.vcxproj.filters b/PCbuild/pyexpat.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/pyexpat.vcxproj.filters @@ -0,0 +1,33 @@ +? + + + + {ddae77a6-7ca0-4a1b-b71c-deea5f4025de} + + + {5af9d40c-fc46-4640-ad84-3d1dd34a71d7} + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props new file mode 100644 --- /dev/null +++ b/PCbuild/pyproject.props @@ -0,0 +1,159 @@ +? + + + <_ProjectFileVersion>10.0.30319.1 + 10.0 + $(BuildPath) + $(SolutionDir)obj\$(ArchName)_$(Configuration)\$(ProjectName)\ + $(SolutionDir)obj\$(ArchName)\$(ProjectName)\ + $(ProjectName) + $(TargetName)$(PyDebugExt) + false + false + + true + true + true + true + false + false + + + + <_DebugPreprocessorDefinition>NDEBUG; + <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG; + <_PlatformPreprocessorDefinition>_WIN32; + <_PlatformPreprocessorDefinition Condition="$(Platform) == 'x64'">_WIN64;_M_X64; + <_PydPreprocessorDefinition Condition="$(TargetExt) == '.pyd'">Py_BUILD_CORE_MODULE; + + + + $(PySourcePath)Include;$(PySourcePath)PC;%(AdditionalIncludeDirectories) + WIN32;$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions) + + MaxSpeed + true + true + + MultiThreadedDLL + true + Level3 + ProgramDatabase + Default + true + true + + + Disabled + false + MultiThreadedDebugDLL + + + $(OutDir);%(AdditionalLibraryDirectories) + true + $(OutDir)$(TargetName).pdb + Windows + true + true + true + LIBC;%(IgnoreSpecificDefaultLibraries) + MachineX86 + MachineX64 + $(OutDir)$(TargetName).pgd + UseLinkTimeCodeGeneration + PGInstrument + PGUpdate + + + true + true + true + + + $(PySourcePath)PC;$(PySourcePath)Include;%(AdditionalIncludeDirectories) + $(_DebugPreprocessorDefinition)%(PreprocessorDefinitions) + 0x0409 + + + $(_DebugPreprocessorDefinition)%(PreprocessorDefinitions) + true + true + Win32 + X64 + $(OutDir)wininst.tlb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots at KitsRoot81)\bin\x86\signtool.exe + $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots at KitsRoot)\bin\x86\signtool.exe + $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A at InstallationFolder)\Bin\signtool.exe + <_SignCommand Condition="Exists($(SignToolPath))">"$(SignToolPath)" sign /q /n "$(SigningCertificate)" /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)" + + + + + + + diff --git a/PCbuild/python.props b/PCbuild/python.props new file mode 100644 --- /dev/null +++ b/PCbuild/python.props @@ -0,0 +1,112 @@ +? + + + Win32 + Release + + v90 + + + amd64 + win32 + $(ArchName)-pgo + + + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)\..\)) + $(PySourcePath)\ + + + $(PySourcePath)PCBuild\ + $(BuildPath)\$(ArchName)\ + $(BuildPath)\ + + + $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) + $(ExternalsDir)sqlite-3.6.21\ + $(ExternalsDir)bzip2-1.0.6\ + $(ExternalsDir)db-4.7.25.0 + $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)\nasm-2.11.06\ + + + _d + + + $(BuildPath)python$(PyDebugExt).exe + + + <_PatchLevelContent>$([System.IO.File]::ReadAllText(`$(PySourcePath)Include\patchlevel.h`)) + $([System.Text.RegularExpressions.Regex]::Match($(_PatchLevelContent), `define\s+PY_MAJOR_VERSION\s+(\d+)`).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(_PatchLevelContent), `define\s+PY_MINOR_VERSION\s+(\d+)`).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(_PatchLevelContent), `define\s+PY_MICRO_VERSION\s+(\d+)`).Groups[1].Value) + <_ReleaseLevel>$([System.Text.RegularExpressions.Regex]::Match($(_PatchLevelContent), `define\s+PY_RELEASE_LEVEL\s+PY_RELEASE_LEVEL_(\w+)`).Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(_PatchLevelContent), `define\s+PY_RELEASE_SERIAL\s+(\d+)`).Groups[1].Value) + 15 + 10 + 11 + 12 + a$(ReleaseSerial) + b$(ReleaseSerial) + rc$(ReleaseSerial) + + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber) + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)$(ReleaseLevelName) + $([msbuild]::BitwiseOr( + $([msbuild]::Multiply($(MajorVersionNumber), 16777216)), + $([msbuild]::BitwiseOr( + $([msbuild]::Multiply($(MinorVersionNumber), 65536)), + $([msbuild]::BitwiseOr( + $([msbuild]::Multiply($(MicroVersionNumber), 256)), + $([msbuild]::BitwiseOr( + $([msbuild]::Multiply($(ReleaseLevelNumber), 16)), + $(ReleaseSerial) + )) + )) + )) + )) + $([msbuild]::Add( + $(ReleaseSerial), + $([msbuild]::Add( + $([msbuild]::Multiply($(ReleaseLevelNumber), 10)), + $([msbuild]::Multiply($(MicroVersionNumber), 1000)) + )) + )) + + + python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt) + + + .cp$(MajorVersionNumber)$(MinorVersionNumber)-win32 + .cp$(MajorVersionNumber)$(MinorVersionNumber)-win_amd64 + + + $(MajorVersionNumber).$(MinorVersionNumber) + $(SysWinVer)-32 + + + + + + + + + + diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/python.vcxproj @@ -0,0 +1,106 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {B11D750F-CD1F-4A96-85CE-E69A5C5259F9} + ClCompile + + + + + Application + false + MultiByte + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + _CONSOLE;%(PreprocessorDefinitions) + + + Console + 2000000 + 0x1d000000 + + + + + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + {e9e0a1f6-0009-4e8c-b8f8-1b8f5d49a058} + false + + + + + + + + <_Content>@rem This script invokes the most recently built Python with all arguments + at rem passed through to the interpreter. This file is generated by the + at rem build process and any changes *will* be thrown away by the next + at rem rebuild. + at rem This is only meant as a convenience for developing CPython + at rem and using it outside of that context is ill-advised. + at echo Running $(Configuration)^|$(Platform) interpreter... +@"$(OutDir)python$(PyDebugExt).exe" %* + + <_ExistingContent Condition="Exists('$(PySourcePath)python.bat')">$([System.IO.File]::ReadAllText('$(PySourcePath)python.bat')) + + + + diff --git a/PCbuild/python.vcxproj.filters b/PCbuild/python.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/python.vcxproj.filters @@ -0,0 +1,26 @@ +? + + + + {2d690795-de83-4a33-8235-3c5dafe45efa} + + + {8b010a19-5b29-45f1-a8a0-f672e2bbb11a} + + + + + Resource Files + + + + + Resource Files + + + + + Source Files + + + diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/pythoncore.vcxproj @@ -0,0 +1,408 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + pythoncore + + + + + DynamicLibrary + false + + + + + + ClCompile + true + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PyDllName) + + + Link + + + + /Zm200 %(AdditionalOptions) + $(PySourcePath)Python;$(PySourcePath)Modules\zlib;%(AdditionalIncludeDirectories) + _USRDLL;Py_BUILD_CORE;Py_ENABLE_SHARED;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions) + + + ws2_32.lib;%(AdditionalDependencies) + 0x1e000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $([System.IO.File]::ReadAllText('$(IntDir)hgbranch.txt').Trim()) + $([System.IO.File]::ReadAllText('$(IntDir)hgversion.txt').Trim()) + $([System.IO.File]::ReadAllText('$(IntDir)hgtag.txt').Trim()) + + + + HGVERSION="$(HgVersion)";HGTAG="$(HgTag)";HGBRANCH="$(HgBranch)";%(PreprocessorDefinitions) + + + + + + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/pythoncore.vcxproj.filters @@ -0,0 +1,953 @@ +? + + + + {086b0afb-270c-4603-a02a-63d46f0b2b92} + + + {8e81609f-13ca-4eae-9fdb-f8af20c710c7} + + + {8787c5bb-bab6-4586-a42e-4a27c7b3ffb6} + + + {5d6d2d6c-9e61-4a1d-b0b2-5cc2f446d69e} + + + {9f12c4b1-322e-431e-abf1-e02550f50032} + + + {ab29a558-143d-4fe7-a039-b431fb429856} + + + {97349fee-0abf-48b0-a8f5-771bf39b8aee} + + + {ea21fc98-de89-4746-a979-c5616964329a} + + + {f2696406-14bc-48bd-90c5-e93ab82a21ac} + + + {c3e03a5c-56c7-45fd-8543-e5d2326b907d} + + + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Modules + + + Modules + + + Modules + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\_io + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Parser + + + Parser + + + PC + + + PC + + + Python + + + Python + + + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\zlib + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\cjkcodecs + + + Modules\_io + + + Modules\_io + + + Modules\_io + + + Modules\_io + + + Modules\_io + + + Modules\_io + + + Modules\_io + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Objects + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + PC + + + PC + + + PC + + + PC + + + PC + + + PC + + + PC + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + Python + + + + + Resource Files + + + diff --git a/PCbuild/pythonw.vcxproj b/PCbuild/pythonw.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/pythonw.vcxproj @@ -0,0 +1,80 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {F4229CC3-873C-49AE-9729-DD308ED4CD4A} + ClCompile + false + + + + + Application + false + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + 2000000 + 0x1d000000 + + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/pythonw.vcxproj.filters b/PCbuild/pythonw.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/pythonw.vcxproj.filters @@ -0,0 +1,21 @@ +? + + + + {0434cf11-a311-4a92-8a6c-4164aa79a7f2} + + + {e1d8ea6b-c65d-42f4-9eed-6010846ed378} + + + + + Resource Files + + + + + Source Files + + + diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -1,15 +1,29 @@ -Building Python using VC++ 9.0 ------------------------------- +Building Python using MSVC 9.0 via MSBuild +------------------------------------------ This directory is used to build Python for Win32 and x64 platforms, e.g. -Windows 2000, XP, Vista and Windows Server 2008. In order to build 32-bit -debug and release executables, Microsoft Visual C++ 2008 Express Edition is -required at the very least. In order to build 64-bit debug and release -executables, Visual Studio 2008 Standard Edition is required at the very -least. In order to build all of the above, as well as generate release builds -that make use of Profile Guided Optimisation (PG0), Visual Studio 2008 -Professional Edition is required at the very least. The official Python -releases are built with this version of Visual Studio. +Windows 2000 and later. In order to use the project files in this +directory, you must have installed the MSVC 9.0 compilers, the v90 +PlatformToolset project files for MSBuild, and MSBuild version 4.0 or later. +The easiest way to make sure you have all of these components is to install +Visual Studio 2008 and Visual Studio 2010. Another configuration proven +to work is Visual Studio 2008, Windows SDK 7.1, and Visual Studio 2013. + +If you only have Visual Studio 2008 available, use the project files in +../PC/VS9.0 which are fully supported and specifically for VS 2008. + +If you do not have Visual Studio 2008 available, you can use these project +files to build using a different version of MSVC. For example, use + + PCbuild\build.bat "/p:PlatformToolset=v100" + +to build using MSVC10 (Visual Studio 2010). + +***WARNING*** +Building Python 2.7 for Windows using any toolchain that doesn't link +against MSVCRT90.dll is *unsupported* as the resulting python.exe will +not be able to use precompiled extension modules that do link against +MSVCRT90.dll. For other Windows platforms and compilers, see ../PC/readme.txt. diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat --- a/PCbuild/rt.bat +++ b/PCbuild/rt.bat @@ -32,21 +32,19 @@ set suffix= set qmode= set dashO= -set tcltk=tcltk :CheckOpts if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts -if "%1"=="-x64" (set prefix=%prefix%amd64) & (set tcltk=tcltk64) & shift & goto CheckOpts +if "%1"=="-x64" (set prefix=%pcbuild%amd64\) & shift & goto CheckOpts -PATH %PATH%;%pcbuild%..\externals\%tcltk%\bin -set exe="%prefix%\python%suffix%" -set cmd=%exe% %dashO% -Wd -3 -E -tt "%pcbuild%\..\Lib\test\regrtest.py" %1 %2 %3 %4 %5 %6 %7 %8 %9 +set exe=%prefix%\python%suffix% +set cmd="%exe%" %dashO% -Wd -3 -E -tt "%pcbuild%..\Lib\test\regrtest.py" %1 %2 %3 %4 %5 %6 %7 %8 %9 if defined qmode goto Qmode echo Deleting .pyc/.pyo files ... -%exe% "%pcbuild%\rmpyc.py" +"%exe%" "%pcbuild%rmpyc.py" echo on %cmd% diff --git a/PCbuild/select.vcxproj b/PCbuild/select.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/select.vcxproj @@ -0,0 +1,79 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {18CAE28C-B454-46C1-87A0-493D91D97F03} + select + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + ws2_32.lib;%(AdditionalDependencies) + 0x1D110000 + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/select.vcxproj.filters b/PCbuild/select.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/select.vcxproj.filters @@ -0,0 +1,13 @@ +? + + + + {98346077-900c-4c7a-852f-a23470e37b40} + + + + + Source Files + + + diff --git a/PCbuild/sqlite3.vcxproj b/PCbuild/sqlite3.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/sqlite3.vcxproj @@ -0,0 +1,77 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {A1A295E5-463C-437F-81CA-1F32367685DA} + sqlite3 + .pyd + false + + + + + DynamicLibrary + NotSet + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + $(sqlite3Dir);%(AdditionalIncludeDirectories) + SQLITE_API=__declspec(dllexport);%(PreprocessorDefinitions) + Level1 + + + + + + + + + + + + + diff --git a/PCbuild/sqlite3.vcxproj.filters b/PCbuild/sqlite3.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/sqlite3.vcxproj.filters @@ -0,0 +1,24 @@ +? + + + + {ce5b649d-a6f7-4459-9425-c883795d79df} + + + {0e842fe2-176b-4e83-9d1f-0ad13a859efd} + + + + + Header Files + + + Header Files + + + + + Source Files + + + diff --git a/PCbuild/ssleay.vcxproj b/PCbuild/ssleay.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/ssleay.vcxproj @@ -0,0 +1,119 @@ +? + + + + Debug + Win32 + + + Release + Win32 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Debug + x64 + + + Release + x64 + + + + {10615B24-73BF-4EFA-93AA-236916321317} + ssleay + + + + + + + StaticLibrary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/tcl.vcxproj @@ -0,0 +1,90 @@ +? + + + + Debug + Win32 + + + Release + Win32 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Debug + x64 + + + Release + x64 + + + + {B5FD6F1D-129E-4BFF-9340-03606FAC7283} + + + + + + + + Makefile + $(tcltkDir) + $(OutDir)bin\$(tclDLLName) + + + + + + + + + + symbols + INSTALLDIR="$(OutDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" + DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" + setlocal +@(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' +') +goto :eof +:build +set VCINSTALLDIR=$(VCInstallDir) +cd /D "$(tclDir)win" +nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) core shell dlls +nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) install-binaries install-libraries + + + + + + + + + + + + + + + diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props new file mode 100644 --- /dev/null +++ b/PCbuild/tcltk.props @@ -0,0 +1,43 @@ +? + + + + 8 + 5 + 15 + 0 + $(TclMajorVersion) + $(TclMinorVersion) + $(TclPatchLevel) + $(TclRevision) + 8 + 4 + 3 + 5 + $(ExternalsDir)tcl-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ + $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ + $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ + $(ExternalsDir)tcltk\ + $(ExternalsDir)tcltk64\ + g + tcl$(TclMajorVersion)$(TclMinorVersion)$(TclDebugExt).dll + tcl$(TclMajorVersion)$(TclMinorVersion)$(TclDebugExt).lib + tclsh$(TclMajorVersion)$(TclMinorVersion)$(TclDebugExt).exe + tk$(TkMajorVersion)$(TkMinorVersion)$(TclDebugExt).dll + tk$(TkMajorVersion)$(TkMinorVersion)$(TclDebugExt).lib + tix$(TixMajorVersion)$(TixMinorVersion)$(TclDebugExt).dll + $(tcltkDir)lib\tix$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel)\$(tixDLLName) + $(tcltkDir)lib\tcl$(TclMajorVersion)$(TclMinorVersion)$(TclDebugExt).lib;$(tcltkDir)lib\tk$(TkMajorVersion)$(TkMinorVersion)$(TclDebugExt).lib + IX86 + AMD64 + TCL_MAJOR_VERSION=$(TclMajorVersion) TCL_MINOR_VERSION=$(TclMinorVersion) TCL_PATCH_LEVEL=$(TclPatchLevel) + TCL_MAJOR=$(TclMajorVersion) TCL_MINOR=$(TclMinorVersion) TCL_PATCH=$(TclPatchLevel) + TK_MAJOR_VERSION=$(TkMajorVersion) TK_MINOR_VERSION=$(TkMinorVersion) TK_PATCH_LEVEL=$(TkPatchLevel) + + Release + Debug + $(BuildDirTop)_$(TclMachine) + + $(BuildDirTop)_VC9 + + diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/tix.vcxproj @@ -0,0 +1,94 @@ +? + + + + Debug + Win32 + + + Release + Win32 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Debug + x64 + + + Release + x64 + + + + {C5A3E7FB-9695-4B2E-960B-1D9F43F1E555} + tix + + + + + + + + Makefile + $(tcltkDir) + $(tixDLLPath) + + + + + + + + + + msvcrt + symbols,msvcrt + BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" + DEBUG=1 NODEBUG=0 TCL_DBGX=g DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" + DEBUG=0 NODEBUG=1 + setlocal +@(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' +') +goto :eof +:build +set VCINSTALLDIR=$(VCInstallDir) +cd /D "$(tixDir)win" +nmake /nologo -f makefile.vc MACHINE=$(TclMachine) $(DebugFlags) $(TclShortVersions) $(TixDirs) all install + + rmdir /q/s "$(OutDir.TrimEnd(`\`))" + + + + + {b5fd6f1d-129e-4bff-9340-03606fac7283} + false + + + {7e85eccf-a72c-4da4-9e52-884508e80ba1} + false + + + + + + + + + + + diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/tk.vcxproj @@ -0,0 +1,95 @@ +? + + + + Debug + Win32 + + + Release + Win32 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Debug + x64 + + + Release + x64 + + + + {7E85ECCF-A72C-4DA4-9E52-884508E80BA1} + tk + + + + + + + + Makefile + $(tcltkDir) + $(OutDir)bin\$(tkDLLName) + + + + + + + + + + msvcrt + symbols,msvcrt + TCLDIR="$(tclDir.TrimEnd(`\`))" INSTALLDIR="$(OutDir.TrimEnd(`\`))" + DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" + setlocal +@(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' +') +goto :eof +:build +set VCINSTALLDIR=$(VCInstallDir) +cd /D "$(tkDir)win" +nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) all +nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) install-binaries install-libraries + + + + + {b5fd6f1d-129e-4bff-9340-03606fac7283} + false + + + + + + + + + + + + + + diff --git a/PCbuild/unicodedata.vcxproj b/PCbuild/unicodedata.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/unicodedata.vcxproj @@ -0,0 +1,83 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {ECC7CEAC-A5E5-458E-BB9E-2413CC847881} + unicodedata + Win32Proj + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + 0x1D120000 + + + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/unicodedata.vcxproj.filters b/PCbuild/unicodedata.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/unicodedata.vcxproj.filters @@ -0,0 +1,24 @@ +? + + + + {b939a8f1-ccd7-420a-974a-243606dccd74} + + + {e2c055bb-ec62-4bbc-aa1c-d88da4d4ad1c} + + + + + Header Files + + + Header Files + + + + + Source Files + + + diff --git a/PCbuild/w9xpopen.vcxproj b/PCbuild/w9xpopen.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/w9xpopen.vcxproj @@ -0,0 +1,77 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} + w9xpopen + Win32Proj + false + + + + + Application + false + MultiByte + + + + + + + + + + + + _CONSOLE;%(PreprocessorDefinitions) + MaxSpeed + OnlyExplicitInline + true + MultiThreaded + true + + + Console + + + + + + + + + diff --git a/PCbuild/w9xpopen.vcxproj.filters b/PCbuild/w9xpopen.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/w9xpopen.vcxproj.filters @@ -0,0 +1,13 @@ +? + + + + {abc2dffd-3f2a-47bd-b89b-0314c99ef21e} + + + + + Source Files + + + diff --git a/PCbuild/winsound.vcxproj b/PCbuild/winsound.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/winsound.vcxproj @@ -0,0 +1,79 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {28B5D777-DDF2-4B6B-B34F-31D938813856} + winsound + Win32Proj + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + winmm.lib;%(AdditionalDependencies) + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/winsound.vcxproj.filters b/PCbuild/winsound.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/winsound.vcxproj.filters @@ -0,0 +1,14 @@ +? + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -15,4 +15,4 @@ @rem 4) re-comment, commit and push again @rem Do the build -call "%~dp0..\..\PCbuild\build.bat" -e -d -k %* +call "%~dp0..\..\PCbuild\build.bat" -v -e -d -k %* -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 08:54:18 2015 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 16 Jul 2015 06:54:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150716065418.14728.13721@psf.io> https://hg.python.org/cpython/rev/7f28068196b5 changeset: 96918:7f28068196b5 parent: 96914:0b04e5689c33 parent: 96917:5c3812412b6f user: Raymond Hettinger date: Wed Jul 15 23:52:29 2015 -0700 summary: merge files: Lib/test/test_set.py | 13 +++++++++++++ Misc/NEWS | 2 ++ Objects/setobject.c | 3 ++- 3 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1742,6 +1742,19 @@ s.update(range(100)) list(si) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return hash(0) + def __eq__(self, o): + other.clear() + return False + + other = set() + other = {X() for i in range(10)} + s = {0} + s.update(other) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ - Issue #24569: Make PEP 448 dictionary evaluation more consistent. +- Issue #24583: Fix crash when set is mutated while being updated. + - Issue #24407: Fix crash when dict is mutated while being updated. Library diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -668,7 +668,8 @@ } /* We can't assure there are no duplicates, so do normal insertions */ - for (i = 0; i <= other->mask; i++, other_entry++) { + for (i = 0; i <= other->mask; i++) { + other_entry = &other->table[i]; key = other_entry->key; if (key != NULL && key != dummy) { if (set_add_entry(so, key, other_entry->hash)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 08:54:18 2015 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 16 Jul 2015 06:54:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTgz?= =?utf-8?q?=3A_Fix_crash_when_set_is_mutated_while_being_updated=2E?= Message-ID: <20150716065418.30189.2548@psf.io> https://hg.python.org/cpython/rev/5c3812412b6f changeset: 96917:5c3812412b6f branch: 3.5 parent: 96913:fce682a493e7 user: Raymond Hettinger date: Wed Jul 15 23:50:14 2015 -0700 summary: Issue #24583: Fix crash when set is mutated while being updated. files: Lib/test/test_set.py | 13 +++++++++++++ Misc/NEWS | 2 ++ Objects/setobject.c | 3 ++- 3 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1742,6 +1742,19 @@ s.update(range(100)) list(si) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return hash(0) + def __eq__(self, o): + other.clear() + return False + + other = set() + other = {X() for i in range(10)} + s = {0} + s.update(other) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ - Issue #24569: Make PEP 448 dictionary evaluation more consistent. +- Issue #24583: Fix crash when set is mutated while being updated. + - Issue #24407: Fix crash when dict is mutated while being updated. Library diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -600,7 +600,8 @@ } /* We can't assure there are no duplicates, so do normal insertions */ - for (i = 0; i <= other->mask; i++, other_entry++) { + for (i = 0; i <= other->mask; i++) { + other_entry = &other->table[i]; key = other_entry->key; if (key != NULL && key != dummy) { Py_INCREF(key); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 08:54:18 2015 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 16 Jul 2015 06:54:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324583=3A_Fix_cras?= =?utf-8?q?h_when_set_is_mutated_while_being_updated=2E?= Message-ID: <20150716065418.18740.86395@psf.io> https://hg.python.org/cpython/rev/05cb67dab161 changeset: 96919:05cb67dab161 user: Raymond Hettinger date: Wed Jul 15 23:54:02 2015 -0700 summary: Issue #24583: Fix crash when set is mutated while being updated. files: Objects/setobject.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -127,7 +127,7 @@ static int set_table_resize(PySetObject *, Py_ssize_t); static int -set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) +_set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; setentry *freeslot; @@ -162,7 +162,7 @@ if (cmp < 0) /* unlikely */ return -1; if (table != so->table || entry->key != startkey) /* unlikely */ - return set_add_entry(so, key, hash); + return _set_add_entry(so, key, hash); if (cmp > 0) /* likely */ goto found_active; mask = so->mask; /* help avoid a register spill */ @@ -190,7 +190,7 @@ if (cmp < 0) return -1; if (table != so->table || entry->key != startkey) - return set_add_entry(so, key, hash); + return _set_add_entry(so, key, hash); if (cmp > 0) goto found_active; mask = so->mask; @@ -211,14 +211,12 @@ found_unused_or_dummy: if (freeslot == NULL) goto found_unused; - Py_INCREF(key); so->used++; freeslot->key = key; freeslot->hash = hash; return 0; found_unused: - Py_INCREF(key); so->fill++; so->used++; entry->key = key; @@ -231,6 +229,16 @@ return 0; } +static int +set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) +{ + Py_INCREF(key); + if (!_set_add_entry(so, key, hash)) + return 0; + Py_DECREF(key); + return -1; +} + /* Internal routine used by set_table_resize() to insert an item which is known to be absent from the set. This routine also assumes that -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 09:45:02 2015 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 16 Jul 2015 07:45:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_Python-Version_header=3B_?= =?utf-8?q?some_formatting_fixes=2E?= Message-ID: <20150716074502.23355.39458@psf.io> https://hg.python.org/peps/rev/b0072164ba27 changeset: 5905:b0072164ba27 user: Guido van Rossum date: Thu Jul 16 09:44:36 2015 +0200 summary: Add Python-Version header; some formatting fixes. files: pep-0484.txt | 27 ++++++++++++++------------- 1 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -9,6 +9,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 29-Sep-2014 +Python-Version: 3.5 Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015,22-May-2015 Resolution: https://mail.python.org/pipermail/python-dev/2015-May/140104.html @@ -85,7 +86,7 @@ --------- While the proposed typing module will contain some building blocks for -runtime type checking -- in particular the `get_type_hints()` +runtime type checking -- in particular the ``get_type_hints()`` function -- third party packages would have to be developed to implement specific runtime type checking functionality, for example using decorators or metaclasses. Using type hints for performance @@ -262,10 +263,10 @@ specifying callback signatures with a variable number of argument of a specific type. -Because `typing.Callable` does double-duty as a replacement for -`collections.abc.Callable`, `isinstance(x, typing.Callable)` is -implemented by deferring to `isinstance(x, collections.abc.Callable)`. -However, `isinstance(x, typing.Callable[...])` is not supported. +Because ``typing.Callable`` does double-duty as a replacement for +``collections.abc.Callable``, ``isinstance(x, typing.Callable)`` is +implemented by deferring to ```isinstance(x, collections.abc.Callable)``. +However, ``isinstance(x, typing.Callable[...])`` is not supported. Generics @@ -413,7 +414,7 @@ Subclassing a generic class without specifying type parameters assumes ``Any`` for each position. In the following example, ``MyIterable`` -is not generic but implicitly inherits from ``Iterable[Any]``: +is not generic but implicitly inherits from ``Iterable[Any]``:: from typing import Iterable @@ -441,20 +442,20 @@ inferred by a type checker may be different depending on the form we use. The first way is to give the value of the type parameter explicitly -- this overrides whatever type inference the type -checker would otherwise perform: +checker would otherwise perform:: x = Node[T]() # The type inferred for x is Node[T]. y = Node[int]() # The type inferred for y is Node[int]. If no explicit types are given, the type checker is given some -freedom. Consider this code: +freedom. Consider this code:: x = Node() The inferred type could be ``Node[Any]``, as there isn't enough context to infer a more precise type. Alternatively, a type checker -may reject the line and require an explicit annotation, like this: +may reject the line and require an explicit annotation, like this:: x = Node() # type: Node[int] # Inferred type is Node[int]. @@ -943,7 +944,7 @@ stream = ... # type: IO[str] -In non-stub code, there is a similar special case: +In non-stub code, there is a similar special case:: from typing import IO @@ -986,7 +987,7 @@ return cast(str, a[index]) Some type checkers may not be able to infer that the type of -``a[index]`` is ``str`` and only infer ``object`` or ``Any``", but we +``a[index]`` is ``str`` and only infer ``object`` or ``Any``, but we know that (if the code gets to that point) it must be a string. The ``cast(t, x)`` call tells the type checker that we are confident that the type of ``x`` is ``t``. At runtime a cast always returns the @@ -1110,7 +1111,7 @@ A constrained ``TypeVar`` type can often be used instead of using the ``@overload`` decorator. For example, the definitions of ``concat1`` -and ``concat2`` in this stub file are equivalent: +and ``concat2`` in this stub file are equivalent:: from typing import TypeVar @@ -1133,7 +1134,7 @@ and using ``@overload`` is that the prior can also be used to define constraints for generic class type parameters. For example, the type parameter of the generic class ``typing.IO`` is constrained (only -``IO[str]``, ``IO[bytes]`` and ``IO[Any]`` are valid): +``IO[str]``, ``IO[bytes]`` and ``IO[Any]`` are valid):: class IO(Generic[AnyStr]): ... -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Thu Jul 16 11:43:09 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 16 Jul 2015 09:43:09 +0000 Subject: [Python-checkins] Daily reference leaks (0b04e5689c33): sum=4 Message-ID: <20150716084309.43269.72721@psf.io> results for 0b04e5689c33 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogZMGRYU', '--timeout', '7200'] From python-checkins at python.org Thu Jul 16 22:22:55 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 16 Jul 2015 20:22:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150716202255.18740.65054@psf.io> https://hg.python.org/cpython/rev/6cc38d283577 changeset: 96921:6cc38d283577 branch: 3.5 parent: 96917:5c3812412b6f parent: 96920:35a6fe0e2b27 user: Victor Stinner date: Thu Jul 16 22:20:19 2015 +0200 summary: Merge 3.4 files: Lib/test/multibytecodec_support.py | 7 +++++++ Misc/NEWS | 2 ++ Modules/cjkcodecs/multibytecodec.c | 3 +++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Lib/test/multibytecodec_support.py b/Lib/test/multibytecodec_support.py --- a/Lib/test/multibytecodec_support.py +++ b/Lib/test/multibytecodec_support.py @@ -270,6 +270,13 @@ self.assertEqual(ostream.getvalue(), self.tstring[0]) + def test_streamwriter_reset_no_pending(self): + # Issue #23247: Calling reset() on a fresh StreamWriter instance + # (without pending data) must not crash + stream = BytesIO() + writer = self.writer(stream) + writer.reset() + class TestBase_Mapping(unittest.TestCase): pass_enctest = [] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -169,6 +169,8 @@ Library ------- +- Issue #23247: Fix a crash in the StreamWriter.reset() of CJK codecs. + - Issue #24270: Add math.isclose() and cmath.isclose() functions as per PEP 485. Contributed by Chris Barker and Tal Einat. diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1685,6 +1685,9 @@ { PyObject *pwrt; + if (!self->pending) + Py_RETURN_NONE; + pwrt = multibytecodec_encode(self->codec, &self->state, self->pending, NULL, self->errors, MBENC_FLUSH | MBENC_RESET); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 22:22:55 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 16 Jul 2015 20:22:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogQ2xvc2VzICMyMzI0?= =?utf-8?q?7=3A_Fix_a_crash_in_the_StreamWriter=2Ereset=28=29_of_CJK_codec?= =?utf-8?q?s?= Message-ID: <20150716202255.30183.7222@psf.io> https://hg.python.org/cpython/rev/35a6fe0e2b27 changeset: 96920:35a6fe0e2b27 branch: 3.4 parent: 96910:4c8cb603ab42 user: Victor Stinner date: Thu Jul 16 22:17:31 2015 +0200 summary: Closes #23247: Fix a crash in the StreamWriter.reset() of CJK codecs files: Lib/test/multibytecodec_support.py | 7 +++++++ Misc/NEWS | 2 ++ Modules/cjkcodecs/multibytecodec.c | 3 +++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Lib/test/multibytecodec_support.py b/Lib/test/multibytecodec_support.py --- a/Lib/test/multibytecodec_support.py +++ b/Lib/test/multibytecodec_support.py @@ -270,6 +270,13 @@ self.assertEqual(ostream.getvalue(), self.tstring[0]) + def test_streamwriter_reset_no_pending(self): + # Issue #23247: Calling reset() on a fresh StreamWriter instance + # (without pending data) must not crash + stream = BytesIO() + writer = self.writer(stream) + writer.reset() + class TestBase_Mapping(unittest.TestCase): pass_enctest = [] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #23247: Fix a crash in the StreamWriter.reset() of CJK codecs. + - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. Patch from Nicola Palumbo and Laurent De Buyst. diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1629,6 +1629,9 @@ { PyObject *pwrt; + if (!self->pending) + Py_RETURN_NONE; + pwrt = multibytecodec_encode(self->codec, &self->state, self->pending, NULL, self->errors, MBENC_FLUSH | MBENC_RESET); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 16 22:22:58 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 16 Jul 2015 20:22:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150716202255.28222.16917@psf.io> https://hg.python.org/cpython/rev/b9ada88cb189 changeset: 96922:b9ada88cb189 parent: 96919:05cb67dab161 parent: 96921:6cc38d283577 user: Victor Stinner date: Thu Jul 16 22:21:11 2015 +0200 summary: Merge 3.5 files: Lib/test/multibytecodec_support.py | 7 +++++++ Misc/NEWS | 2 ++ Modules/cjkcodecs/multibytecodec.c | 3 +++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Lib/test/multibytecodec_support.py b/Lib/test/multibytecodec_support.py --- a/Lib/test/multibytecodec_support.py +++ b/Lib/test/multibytecodec_support.py @@ -270,6 +270,13 @@ self.assertEqual(ostream.getvalue(), self.tstring[0]) + def test_streamwriter_reset_no_pending(self): + # Issue #23247: Calling reset() on a fresh StreamWriter instance + # (without pending data) must not crash + stream = BytesIO() + writer = self.writer(stream) + writer.reset() + class TestBase_Mapping(unittest.TestCase): pass_enctest = [] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -185,6 +185,8 @@ Library ------- +- Issue #23247: Fix a crash in the StreamWriter.reset() of CJK codecs. + - Issue #24270: Add math.isclose() and cmath.isclose() functions as per PEP 485. Contributed by Chris Barker and Tal Einat. diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1685,6 +1685,9 @@ { PyObject *pwrt; + if (!self->pending) + Py_RETURN_NONE; + pwrt = multibytecodec_encode(self->codec, &self->state, self->pending, NULL, self->errors, MBENC_FLUSH | MBENC_RESET); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 01:34:48 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 16 Jul 2015 23:34:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Adds_option_to?= =?utf-8?q?_install_launcher_for_all_users_even_when_installing_Python?= Message-ID: <20150716233447.120877.55787@psf.io> https://hg.python.org/cpython/rev/1ec07f0d118a changeset: 96923:1ec07f0d118a branch: 3.5 parent: 96921:6cc38d283577 user: Steve Dower date: Thu Jul 16 16:33:55 2015 -0700 summary: Adds option to install launcher for all users even when installing Python just-for-me. This helps mitigate issues when the incompatible Python 3.4 launcher is installed. Enables installer builds with the the text marker. Allows simple installs to include a custom description. files: Doc/using/win_installer.png | Bin Doc/using/windows.rst | 12 +- Tools/msi/build.bat | 14 +- Tools/msi/bundle/Default.thm | 10 +- Tools/msi/bundle/Default.wxl | 8 +- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 106 +++++++-- Tools/msi/bundle/bundle.targets | 2 +- Tools/msi/bundle/bundle.wxs | 10 +- Tools/msi/bundle/packagegroups/launcher.wxs | 4 +- Tools/msi/common.wxs | 2 +- Tools/msi/launcher/launcher_files.wxs | 8 +- Tools/msi/launcher/launcher_reg.wxs | 2 +- Tools/msi/msi.props | 4 +- 13 files changed, 127 insertions(+), 55 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index 8e258927c32ad46be2125cae89f90a770a8c34ba..e5d5e07a1433bc0b9c7ed8929cc8d95437249855 GIT binary patch [stripped] diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -130,6 +130,9 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_launcher | Install :ref:`launcher`. | 1 | +---------------------------+--------------------------------------+--------------------------+ +| InstallLauncherAllUsers | Installs :ref:`launcher` for all | 1 | +| | users. | | ++---------------------------+--------------------------------------+--------------------------+ | Include_lib | Install standard library and | 1 | | | extension modules | | +---------------------------+--------------------------------------+--------------------------+ @@ -145,6 +148,9 @@ +---------------------------+--------------------------------------+--------------------------+ | SimpleInstall | Disable most install UI | 0 | +---------------------------+--------------------------------------+--------------------------+ +| SimpleInstallDescription | A custom message to display when the | (empty) | +| | simplified install UI is used. | | ++---------------------------+--------------------------------------+--------------------------+ For example, to silently install a default, system-wide Python installation, you could use the following command (from an elevated command prompt):: @@ -152,9 +158,11 @@ python-3.5.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 To allow users to easily install a personal copy of Python without the test -suite, you could provide a shortcut with the following command:: +suite, you could provide a shortcut with the following command. This will +display a simplified initial page and disallow customization:: - python-3.5.0.exe /passive InstallAllUsers=0 Include_launcher=0 Include_test=0 SimpleInstall=1 + python-3.5.0.exe InstallAllUsers=0 Include_launcher=0 Include_test=0 + SimpleInstall=1 SimpleInstallDescription="Just for me, no test suite." (Note that omitting the launcher also omits file associations, and is only recommended for per-user installs when there is also a system-wide installation diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -6,12 +6,14 @@ set BUILDX86= set BUILDX64= set BUILDDOC= +set BUILDPX= :CheckOpts if "%~1" EQU "-h" goto Help if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "--test-marker" (set BUILDPX=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -35,22 +37,28 @@ if errorlevel 1 goto :eof ) +set BUILD_CMD="%D%bundle\snapshot.wixproj" +if defined BUILDPX ( + set BUILD_CMD=%BUILD_CMD% /p:UseTestMarker=true +) + if defined BUILDX86 ( "%PCBUILD%win32\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" + msbuild %BUILD_CMD% if errorlevel 1 goto :eof ) if defined BUILDX64 ( "%PCBUILD%amd64\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 + msbuild /p:Platform=x64 %BUILD_CMD% if errorlevel 1 goto :eof ) exit /B 0 :Help -echo build.bat [-x86] [-x64] [--doc] [-h] +echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] echo. echo -x86 Build x86 installers echo -x64 Build x64 installers echo --doc Build CHM documentation +echo --test-marker Build installers with 'x' markers diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,10 +21,11 @@ #(loc.InstallMessage) - - + + #(loc.ShortPrependPathLabel) + #(loc.ShortInstallLauncherAllUsersLabel) @@ -43,7 +44,7 @@ #(loc.InstallHeader) - + @@ -63,7 +64,8 @@ #(loc.Include_testLabel) #(loc.Include_testHelpLabel) - #(loc.Include_launcherLabel) + #(loc.Include_launcherLabel) + #(loc.InstallLauncherAllUsersLabel) #(loc.Include_launcherHelpLabel) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -50,7 +50,9 @@ C&ustomize installation Choose location and features &Install - Uses setting preselected by your administrator + Use settings preselected by your administrator + +[SimpleInstallDescription] &Upgrade Now [TargetDir] @@ -81,7 +83,9 @@ Create shortcuts for installed applications Add Python to &environment variables Add &Python [ShortVersion] to PATH - Install as &Administrator + Install for &all users + for &all users (requires elevation) + Install &launcher for all users (recommended) &Precompile standard library Install debugging &symbols Install debu&g binaries (requires VS 2015 or later) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -87,11 +87,13 @@ ID_INSTALL_UPGRADE_BUTTON, ID_INSTALL_UPGRADE_CUSTOM_BUTTON, ID_INSTALL_CANCEL_BUTTON, - + ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, + // Customize Page ID_TARGETDIR_EDITBOX, ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, + ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, ID_CUSTOM_COMPILE_ALL_CHECKBOX, ID_CUSTOM_BROWSE_BUTTON, ID_CUSTOM_BROWSE_BUTTON_LABEL, @@ -150,10 +152,12 @@ { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" }, { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" }, { ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" }, + { ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"InstallLauncherAllUsers" }, { ID_TARGETDIR_EDITBOX, L"TargetDir" }, { ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L"AssociateFiles" }, { ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L"InstallAllUsers" }, + { ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"CustomInstallLauncherAllUsers" }, { ID_CUSTOM_COMPILE_ALL_CHECKBOX, L"CompileAll" }, { ID_CUSTOM_BROWSE_BUTTON, L"CustomBrowseButton" }, { ID_CUSTOM_BROWSE_BUTTON_LABEL, L"CustomBrowseButtonLabel" }, @@ -261,10 +265,11 @@ LPWSTR defaultDir = nullptr; LPWSTR targetDir = nullptr; LONGLONG elevated, crtInstalled, installAllUsers; - BOOL checked; + BOOL checked, launcherChecked; WCHAR wzPath[MAX_PATH] = { }; BROWSEINFOW browseInfo = { }; PIDLIST_ABSOLUTE pidl = nullptr; + DWORD pageId; HRESULT hr = S_OK; switch(id) { @@ -278,7 +283,7 @@ case ID_INSTALL_BUTTON: SavePageSettings(); - if (!QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } @@ -344,18 +349,32 @@ ReleaseStr(targetDir); } - checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - if (!checked && !QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } OnPlan(_command.action); break; + case ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, WillElevate()); + break; + + case ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); + break; + case ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX: - hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); + _engine->SetVariableNumeric(L"InstallAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); ThemeControlEnable(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked); if (checked) { _engine->SetVariableNumeric(L"CompileAll", 1); @@ -416,6 +435,7 @@ case ID_MODIFY_BUTTON: // Some variables cannot be modified _engine->SetVariableString(L"InstallAllUsersState", L"disable"); + _engine->SetVariableString(L"InstallLauncherAllUsersState", L"disable"); _engine->SetVariableString(L"TargetDirState", L"disable"); _engine->SetVariableString(L"CustomBrowseButtonState", L"disable"); _modifying = TRUE; @@ -437,35 +457,36 @@ void InstallPage_Show() { // Ensure the All Users install button has a UAC shield - LONGLONG elevated, installAll; - - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + BOOL elevated = WillElevate(); + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, elevated); + } + + void Custom1Page_Show() { + LONGLONG installLauncherAllUsers; + + if (FAILED(BalGetNumericVariable(L"InstallLauncherAllUsers", &installLauncherAllUsers))) { + installLauncherAllUsers = 0; } - - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) { - ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE); - } - } - - void Custom1Page_Show() { + ThemeSendControlMessage(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, BM_SETCHECK, + installLauncherAllUsers ? BST_CHECKED : BST_UNCHECKED, 0); } void Custom2Page_Show() { HRESULT hr; - LONGLONG installAll, elevated, includeLauncher; + LONGLONG installAll, includeLauncher; - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + if (FAILED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { + installAll = 0; } - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, installAll && !elevated); + + if (WillElevate()) { + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, TRUE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_HIDE); } else { - installAll = 0; + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, FALSE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_SHOW); } @@ -1839,8 +1860,8 @@ COLORREF fg = fnt->crForeground, bg = fnt->crBackground; *brush = fnt->hBackground; RemapColor(&fg, &bg, brush); - SetTextColor(hDC, fg); - SetBkColor(hDC, bg); + ::SetTextColor(hDC, fg); + ::SetBkColor(hDC, bg); return TRUE; } @@ -2080,6 +2101,7 @@ for (DWORD i = 0; i < pPage->cControlIndices; ++i) { THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices[i]; + BOOL enableControl = TRUE; // If this is a named control, try to set its default state. if (pControl->sczName && *pControl->sczName) { @@ -2091,7 +2113,7 @@ // If the control value isn't set then disable it. if (!SUCCEEDED(hr)) { - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else { ThemeSendControlMessage( _theme, @@ -2110,13 +2132,25 @@ LPWSTR controlState = nullptr; hr = BalGetStringVariable(controlName, &controlState); if (SUCCEEDED(hr) && controlState && *controlState) { + if (controlState[0] == '[') { + LPWSTR formatted = nullptr; + if (SUCCEEDED(BalFormatString(controlState, &formatted))) { + StrFree(controlState); + controlState = formatted; + } + } + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"disable", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"hide", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); // TODO: This doesn't work ThemeShowControl(_theme, pControl->wId, SW_HIDE); + } else { + // An explicit state can override the lack of a + // backing variable. + enableControl = TRUE; } } StrFree(controlState); @@ -2124,6 +2158,8 @@ StrFree(controlName); } + ThemeControlEnable(_theme, pControl->wId, enableControl); + // Format the text in each of the new page's controls if (pControl->sczText && *pControl->sczText) { // If the wix developer is showing a hidden variable @@ -2405,6 +2441,16 @@ } } + BOOL WillElevate() { + static BAL_CONDITION WILL_ELEVATE_CONDITION = { + L"not WixBundleElevated and (InstallAllUsers or (InstallLauncherAllUsers and Include_launcher))", + L"" + }; + BOOL result; + + return SUCCEEDED(BalConditionEvaluate(&WILL_ELEVATE_CONDITION, _engine, &result, nullptr)) && result; + } + BOOL IsCrtInstalled() { if (_crtInstalledToken > 0) { return TRUE; diff --git a/Tools/msi/bundle/bundle.targets b/Tools/msi/bundle/bundle.targets --- a/Tools/msi/bundle/bundle.targets +++ b/Tools/msi/bundle/bundle.targets @@ -88,7 +88,7 @@ - diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -24,15 +24,16 @@ + - + - + - + @@ -45,6 +46,8 @@ + + @@ -67,6 +70,7 @@ + diff --git a/Tools/msi/bundle/packagegroups/launcher.wxs b/Tools/msi/bundle/packagegroups/launcher.wxs --- a/Tools/msi/bundle/packagegroups/launcher.wxs +++ b/Tools/msi/bundle/packagegroups/launcher.wxs @@ -9,7 +9,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_launcher" /> + InstallCondition="(InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> + InstallCondition="not (InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> \ No newline at end of file diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs --- a/Tools/msi/common.wxs +++ b/Tools/msi/common.wxs @@ -103,7 +103,7 @@ - + diff --git a/Tools/msi/launcher/launcher_files.wxs b/Tools/msi/launcher/launcher_files.wxs --- a/Tools/msi/launcher/launcher_files.wxs +++ b/Tools/msi/launcher/launcher_files.wxs @@ -3,22 +3,22 @@ - + - + NOT ALLUSERS=1 - + ALLUSERS=1 - + diff --git a/Tools/msi/launcher/launcher_reg.wxs b/Tools/msi/launcher/launcher_reg.wxs --- a/Tools/msi/launcher/launcher_reg.wxs +++ b/Tools/msi/launcher/launcher_reg.wxs @@ -3,7 +3,7 @@ - + diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -81,10 +81,10 @@ $(DefineConstants);CRTRedist=$(CRTRedist); - + $(DefineConstants);TestPrefix=;FileExtension=py; - + $(DefineConstants);TestPrefix=x;FileExtension=px; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 01:40:23 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 16 Jul 2015 23:40:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Adds_option_to?= =?utf-8?q?_install_launcher_for_all_users_even_when_installing_Python?= Message-ID: <20150716233447.120877.55787@psf.io> https://hg.python.org/cpython/rev/1ec07f0d118a changeset: 96923:1ec07f0d118a branch: 3.5 parent: 96921:6cc38d283577 user: Steve Dower date: Thu Jul 16 16:33:55 2015 -0700 summary: Adds option to install launcher for all users even when installing Python just-for-me. This helps mitigate issues when the incompatible Python 3.4 launcher is installed. Enables installer builds with the the text marker. Allows simple installs to include a custom description. files: Doc/using/win_installer.png | Bin Doc/using/windows.rst | 12 +- Tools/msi/build.bat | 14 +- Tools/msi/bundle/Default.thm | 10 +- Tools/msi/bundle/Default.wxl | 8 +- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 106 +++++++-- Tools/msi/bundle/bundle.targets | 2 +- Tools/msi/bundle/bundle.wxs | 10 +- Tools/msi/bundle/packagegroups/launcher.wxs | 4 +- Tools/msi/common.wxs | 2 +- Tools/msi/launcher/launcher_files.wxs | 8 +- Tools/msi/launcher/launcher_reg.wxs | 2 +- Tools/msi/msi.props | 4 +- 13 files changed, 127 insertions(+), 55 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index 8e258927c32ad46be2125cae89f90a770a8c34ba..e5d5e07a1433bc0b9c7ed8929cc8d95437249855 GIT binary patch [stripped] diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -130,6 +130,9 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_launcher | Install :ref:`launcher`. | 1 | +---------------------------+--------------------------------------+--------------------------+ +| InstallLauncherAllUsers | Installs :ref:`launcher` for all | 1 | +| | users. | | ++---------------------------+--------------------------------------+--------------------------+ | Include_lib | Install standard library and | 1 | | | extension modules | | +---------------------------+--------------------------------------+--------------------------+ @@ -145,6 +148,9 @@ +---------------------------+--------------------------------------+--------------------------+ | SimpleInstall | Disable most install UI | 0 | +---------------------------+--------------------------------------+--------------------------+ +| SimpleInstallDescription | A custom message to display when the | (empty) | +| | simplified install UI is used. | | ++---------------------------+--------------------------------------+--------------------------+ For example, to silently install a default, system-wide Python installation, you could use the following command (from an elevated command prompt):: @@ -152,9 +158,11 @@ python-3.5.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 To allow users to easily install a personal copy of Python without the test -suite, you could provide a shortcut with the following command:: +suite, you could provide a shortcut with the following command. This will +display a simplified initial page and disallow customization:: - python-3.5.0.exe /passive InstallAllUsers=0 Include_launcher=0 Include_test=0 SimpleInstall=1 + python-3.5.0.exe InstallAllUsers=0 Include_launcher=0 Include_test=0 + SimpleInstall=1 SimpleInstallDescription="Just for me, no test suite." (Note that omitting the launcher also omits file associations, and is only recommended for per-user installs when there is also a system-wide installation diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -6,12 +6,14 @@ set BUILDX86= set BUILDX64= set BUILDDOC= +set BUILDPX= :CheckOpts if "%~1" EQU "-h" goto Help if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "--test-marker" (set BUILDPX=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -35,22 +37,28 @@ if errorlevel 1 goto :eof ) +set BUILD_CMD="%D%bundle\snapshot.wixproj" +if defined BUILDPX ( + set BUILD_CMD=%BUILD_CMD% /p:UseTestMarker=true +) + if defined BUILDX86 ( "%PCBUILD%win32\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" + msbuild %BUILD_CMD% if errorlevel 1 goto :eof ) if defined BUILDX64 ( "%PCBUILD%amd64\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 + msbuild /p:Platform=x64 %BUILD_CMD% if errorlevel 1 goto :eof ) exit /B 0 :Help -echo build.bat [-x86] [-x64] [--doc] [-h] +echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] echo. echo -x86 Build x86 installers echo -x64 Build x64 installers echo --doc Build CHM documentation +echo --test-marker Build installers with 'x' markers diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,10 +21,11 @@ #(loc.InstallMessage) - - + + #(loc.ShortPrependPathLabel) + #(loc.ShortInstallLauncherAllUsersLabel) @@ -43,7 +44,7 @@ #(loc.InstallHeader) - + @@ -63,7 +64,8 @@ #(loc.Include_testLabel) #(loc.Include_testHelpLabel) - #(loc.Include_launcherLabel) + #(loc.Include_launcherLabel) + #(loc.InstallLauncherAllUsersLabel) #(loc.Include_launcherHelpLabel) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -50,7 +50,9 @@ C&ustomize installation Choose location and features &Install - Uses setting preselected by your administrator + Use settings preselected by your administrator + +[SimpleInstallDescription] &Upgrade Now [TargetDir] @@ -81,7 +83,9 @@ Create shortcuts for installed applications Add Python to &environment variables Add &Python [ShortVersion] to PATH - Install as &Administrator + Install for &all users + for &all users (requires elevation) + Install &launcher for all users (recommended) &Precompile standard library Install debugging &symbols Install debu&g binaries (requires VS 2015 or later) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -87,11 +87,13 @@ ID_INSTALL_UPGRADE_BUTTON, ID_INSTALL_UPGRADE_CUSTOM_BUTTON, ID_INSTALL_CANCEL_BUTTON, - + ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, + // Customize Page ID_TARGETDIR_EDITBOX, ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, + ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, ID_CUSTOM_COMPILE_ALL_CHECKBOX, ID_CUSTOM_BROWSE_BUTTON, ID_CUSTOM_BROWSE_BUTTON_LABEL, @@ -150,10 +152,12 @@ { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" }, { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" }, { ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" }, + { ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"InstallLauncherAllUsers" }, { ID_TARGETDIR_EDITBOX, L"TargetDir" }, { ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L"AssociateFiles" }, { ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L"InstallAllUsers" }, + { ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"CustomInstallLauncherAllUsers" }, { ID_CUSTOM_COMPILE_ALL_CHECKBOX, L"CompileAll" }, { ID_CUSTOM_BROWSE_BUTTON, L"CustomBrowseButton" }, { ID_CUSTOM_BROWSE_BUTTON_LABEL, L"CustomBrowseButtonLabel" }, @@ -261,10 +265,11 @@ LPWSTR defaultDir = nullptr; LPWSTR targetDir = nullptr; LONGLONG elevated, crtInstalled, installAllUsers; - BOOL checked; + BOOL checked, launcherChecked; WCHAR wzPath[MAX_PATH] = { }; BROWSEINFOW browseInfo = { }; PIDLIST_ABSOLUTE pidl = nullptr; + DWORD pageId; HRESULT hr = S_OK; switch(id) { @@ -278,7 +283,7 @@ case ID_INSTALL_BUTTON: SavePageSettings(); - if (!QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } @@ -344,18 +349,32 @@ ReleaseStr(targetDir); } - checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - if (!checked && !QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } OnPlan(_command.action); break; + case ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, WillElevate()); + break; + + case ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); + break; + case ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX: - hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); + _engine->SetVariableNumeric(L"InstallAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); ThemeControlEnable(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked); if (checked) { _engine->SetVariableNumeric(L"CompileAll", 1); @@ -416,6 +435,7 @@ case ID_MODIFY_BUTTON: // Some variables cannot be modified _engine->SetVariableString(L"InstallAllUsersState", L"disable"); + _engine->SetVariableString(L"InstallLauncherAllUsersState", L"disable"); _engine->SetVariableString(L"TargetDirState", L"disable"); _engine->SetVariableString(L"CustomBrowseButtonState", L"disable"); _modifying = TRUE; @@ -437,35 +457,36 @@ void InstallPage_Show() { // Ensure the All Users install button has a UAC shield - LONGLONG elevated, installAll; - - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + BOOL elevated = WillElevate(); + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, elevated); + } + + void Custom1Page_Show() { + LONGLONG installLauncherAllUsers; + + if (FAILED(BalGetNumericVariable(L"InstallLauncherAllUsers", &installLauncherAllUsers))) { + installLauncherAllUsers = 0; } - - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) { - ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE); - } - } - - void Custom1Page_Show() { + ThemeSendControlMessage(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, BM_SETCHECK, + installLauncherAllUsers ? BST_CHECKED : BST_UNCHECKED, 0); } void Custom2Page_Show() { HRESULT hr; - LONGLONG installAll, elevated, includeLauncher; + LONGLONG installAll, includeLauncher; - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + if (FAILED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { + installAll = 0; } - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, installAll && !elevated); + + if (WillElevate()) { + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, TRUE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_HIDE); } else { - installAll = 0; + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, FALSE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_SHOW); } @@ -1839,8 +1860,8 @@ COLORREF fg = fnt->crForeground, bg = fnt->crBackground; *brush = fnt->hBackground; RemapColor(&fg, &bg, brush); - SetTextColor(hDC, fg); - SetBkColor(hDC, bg); + ::SetTextColor(hDC, fg); + ::SetBkColor(hDC, bg); return TRUE; } @@ -2080,6 +2101,7 @@ for (DWORD i = 0; i < pPage->cControlIndices; ++i) { THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices[i]; + BOOL enableControl = TRUE; // If this is a named control, try to set its default state. if (pControl->sczName && *pControl->sczName) { @@ -2091,7 +2113,7 @@ // If the control value isn't set then disable it. if (!SUCCEEDED(hr)) { - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else { ThemeSendControlMessage( _theme, @@ -2110,13 +2132,25 @@ LPWSTR controlState = nullptr; hr = BalGetStringVariable(controlName, &controlState); if (SUCCEEDED(hr) && controlState && *controlState) { + if (controlState[0] == '[') { + LPWSTR formatted = nullptr; + if (SUCCEEDED(BalFormatString(controlState, &formatted))) { + StrFree(controlState); + controlState = formatted; + } + } + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"disable", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"hide", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); // TODO: This doesn't work ThemeShowControl(_theme, pControl->wId, SW_HIDE); + } else { + // An explicit state can override the lack of a + // backing variable. + enableControl = TRUE; } } StrFree(controlState); @@ -2124,6 +2158,8 @@ StrFree(controlName); } + ThemeControlEnable(_theme, pControl->wId, enableControl); + // Format the text in each of the new page's controls if (pControl->sczText && *pControl->sczText) { // If the wix developer is showing a hidden variable @@ -2405,6 +2441,16 @@ } } + BOOL WillElevate() { + static BAL_CONDITION WILL_ELEVATE_CONDITION = { + L"not WixBundleElevated and (InstallAllUsers or (InstallLauncherAllUsers and Include_launcher))", + L"" + }; + BOOL result; + + return SUCCEEDED(BalConditionEvaluate(&WILL_ELEVATE_CONDITION, _engine, &result, nullptr)) && result; + } + BOOL IsCrtInstalled() { if (_crtInstalledToken > 0) { return TRUE; diff --git a/Tools/msi/bundle/bundle.targets b/Tools/msi/bundle/bundle.targets --- a/Tools/msi/bundle/bundle.targets +++ b/Tools/msi/bundle/bundle.targets @@ -88,7 +88,7 @@ - diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -24,15 +24,16 @@ + - + - + - + @@ -45,6 +46,8 @@ + + @@ -67,6 +70,7 @@ + diff --git a/Tools/msi/bundle/packagegroups/launcher.wxs b/Tools/msi/bundle/packagegroups/launcher.wxs --- a/Tools/msi/bundle/packagegroups/launcher.wxs +++ b/Tools/msi/bundle/packagegroups/launcher.wxs @@ -9,7 +9,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_launcher" /> + InstallCondition="(InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> + InstallCondition="not (InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> \ No newline at end of file diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs --- a/Tools/msi/common.wxs +++ b/Tools/msi/common.wxs @@ -103,7 +103,7 @@ - + diff --git a/Tools/msi/launcher/launcher_files.wxs b/Tools/msi/launcher/launcher_files.wxs --- a/Tools/msi/launcher/launcher_files.wxs +++ b/Tools/msi/launcher/launcher_files.wxs @@ -3,22 +3,22 @@ - + - + NOT ALLUSERS=1 - + ALLUSERS=1 - + diff --git a/Tools/msi/launcher/launcher_reg.wxs b/Tools/msi/launcher/launcher_reg.wxs --- a/Tools/msi/launcher/launcher_reg.wxs +++ b/Tools/msi/launcher/launcher_reg.wxs @@ -3,7 +3,7 @@ - + diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -81,10 +81,10 @@ $(DefineConstants);CRTRedist=$(CRTRedist); - + $(DefineConstants);TestPrefix=;FileExtension=py; - + $(DefineConstants);TestPrefix=x;FileExtension=px; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 01:40:23 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 16 Jul 2015 23:40:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150716233447.120877.72299@psf.io> https://hg.python.org/cpython/rev/2854dba70ee7 changeset: 96924:2854dba70ee7 parent: 96922:b9ada88cb189 parent: 96923:1ec07f0d118a user: Steve Dower date: Thu Jul 16 16:34:09 2015 -0700 summary: Merge with 3.5 files: Doc/using/win_installer.png | Bin Doc/using/windows.rst | 12 +- Tools/msi/build.bat | 14 +- Tools/msi/bundle/Default.thm | 10 +- Tools/msi/bundle/Default.wxl | 8 +- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 106 +++++++-- Tools/msi/bundle/bundle.targets | 2 +- Tools/msi/bundle/bundle.wxs | 10 +- Tools/msi/bundle/packagegroups/launcher.wxs | 4 +- Tools/msi/common.wxs | 2 +- Tools/msi/launcher/launcher_files.wxs | 8 +- Tools/msi/launcher/launcher_reg.wxs | 2 +- Tools/msi/msi.props | 4 +- 13 files changed, 127 insertions(+), 55 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index 8e258927c32ad46be2125cae89f90a770a8c34ba..e5d5e07a1433bc0b9c7ed8929cc8d95437249855 GIT binary patch [stripped] diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -130,6 +130,9 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_launcher | Install :ref:`launcher`. | 1 | +---------------------------+--------------------------------------+--------------------------+ +| InstallLauncherAllUsers | Installs :ref:`launcher` for all | 1 | +| | users. | | ++---------------------------+--------------------------------------+--------------------------+ | Include_lib | Install standard library and | 1 | | | extension modules | | +---------------------------+--------------------------------------+--------------------------+ @@ -145,6 +148,9 @@ +---------------------------+--------------------------------------+--------------------------+ | SimpleInstall | Disable most install UI | 0 | +---------------------------+--------------------------------------+--------------------------+ +| SimpleInstallDescription | A custom message to display when the | (empty) | +| | simplified install UI is used. | | ++---------------------------+--------------------------------------+--------------------------+ For example, to silently install a default, system-wide Python installation, you could use the following command (from an elevated command prompt):: @@ -152,9 +158,11 @@ python-3.5.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 To allow users to easily install a personal copy of Python without the test -suite, you could provide a shortcut with the following command:: +suite, you could provide a shortcut with the following command. This will +display a simplified initial page and disallow customization:: - python-3.5.0.exe /passive InstallAllUsers=0 Include_launcher=0 Include_test=0 SimpleInstall=1 + python-3.5.0.exe InstallAllUsers=0 Include_launcher=0 Include_test=0 + SimpleInstall=1 SimpleInstallDescription="Just for me, no test suite." (Note that omitting the launcher also omits file associations, and is only recommended for per-user installs when there is also a system-wide installation diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -6,12 +6,14 @@ set BUILDX86= set BUILDX64= set BUILDDOC= +set BUILDPX= :CheckOpts if "%~1" EQU "-h" goto Help if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "--test-marker" (set BUILDPX=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -35,22 +37,28 @@ if errorlevel 1 goto :eof ) +set BUILD_CMD="%D%bundle\snapshot.wixproj" +if defined BUILDPX ( + set BUILD_CMD=%BUILD_CMD% /p:UseTestMarker=true +) + if defined BUILDX86 ( "%PCBUILD%win32\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" + msbuild %BUILD_CMD% if errorlevel 1 goto :eof ) if defined BUILDX64 ( "%PCBUILD%amd64\python.exe" "%D%get_wix.py" - msbuild "%D%bundle\snapshot.wixproj" /p:Platform=x64 + msbuild /p:Platform=x64 %BUILD_CMD% if errorlevel 1 goto :eof ) exit /B 0 :Help -echo build.bat [-x86] [-x64] [--doc] [-h] +echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] echo. echo -x86 Build x86 installers echo -x64 Build x64 installers echo --doc Build CHM documentation +echo --test-marker Build installers with 'x' markers diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,10 +21,11 @@ #(loc.InstallMessage) - - + + #(loc.ShortPrependPathLabel) + #(loc.ShortInstallLauncherAllUsersLabel) @@ -43,7 +44,7 @@ #(loc.InstallHeader) - + @@ -63,7 +64,8 @@ #(loc.Include_testLabel) #(loc.Include_testHelpLabel) - #(loc.Include_launcherLabel) + #(loc.Include_launcherLabel) + #(loc.InstallLauncherAllUsersLabel) #(loc.Include_launcherHelpLabel) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -50,7 +50,9 @@ C&ustomize installation Choose location and features &Install - Uses setting preselected by your administrator + Use settings preselected by your administrator + +[SimpleInstallDescription] &Upgrade Now [TargetDir] @@ -81,7 +83,9 @@ Create shortcuts for installed applications Add Python to &environment variables Add &Python [ShortVersion] to PATH - Install as &Administrator + Install for &all users + for &all users (requires elevation) + Install &launcher for all users (recommended) &Precompile standard library Install debugging &symbols Install debu&g binaries (requires VS 2015 or later) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -87,11 +87,13 @@ ID_INSTALL_UPGRADE_BUTTON, ID_INSTALL_UPGRADE_CUSTOM_BUTTON, ID_INSTALL_CANCEL_BUTTON, - + ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, + // Customize Page ID_TARGETDIR_EDITBOX, ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, + ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, ID_CUSTOM_COMPILE_ALL_CHECKBOX, ID_CUSTOM_BROWSE_BUTTON, ID_CUSTOM_BROWSE_BUTTON_LABEL, @@ -150,10 +152,12 @@ { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" }, { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" }, { ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" }, + { ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"InstallLauncherAllUsers" }, { ID_TARGETDIR_EDITBOX, L"TargetDir" }, { ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L"AssociateFiles" }, { ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L"InstallAllUsers" }, + { ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"CustomInstallLauncherAllUsers" }, { ID_CUSTOM_COMPILE_ALL_CHECKBOX, L"CompileAll" }, { ID_CUSTOM_BROWSE_BUTTON, L"CustomBrowseButton" }, { ID_CUSTOM_BROWSE_BUTTON_LABEL, L"CustomBrowseButtonLabel" }, @@ -261,10 +265,11 @@ LPWSTR defaultDir = nullptr; LPWSTR targetDir = nullptr; LONGLONG elevated, crtInstalled, installAllUsers; - BOOL checked; + BOOL checked, launcherChecked; WCHAR wzPath[MAX_PATH] = { }; BROWSEINFOW browseInfo = { }; PIDLIST_ABSOLUTE pidl = nullptr; + DWORD pageId; HRESULT hr = S_OK; switch(id) { @@ -278,7 +283,7 @@ case ID_INSTALL_BUTTON: SavePageSettings(); - if (!QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } @@ -344,18 +349,32 @@ ReleaseStr(targetDir); } - checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - if (!checked && !QueryElevateForCrtInstall()) { + if (!WillElevate() && !QueryElevateForCrtInstall()) { break; } OnPlan(_command.action); break; + case ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, WillElevate()); + break; + + case ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX: + checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX); + _engine->SetVariableNumeric(L"InstallLauncherAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); + break; + case ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX: - hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); + _engine->SetVariableNumeric(L"InstallAllUsers", checked); + + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, WillElevate()); ThemeControlEnable(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked); if (checked) { _engine->SetVariableNumeric(L"CompileAll", 1); @@ -416,6 +435,7 @@ case ID_MODIFY_BUTTON: // Some variables cannot be modified _engine->SetVariableString(L"InstallAllUsersState", L"disable"); + _engine->SetVariableString(L"InstallLauncherAllUsersState", L"disable"); _engine->SetVariableString(L"TargetDirState", L"disable"); _engine->SetVariableString(L"CustomBrowseButtonState", L"disable"); _modifying = TRUE; @@ -437,35 +457,36 @@ void InstallPage_Show() { // Ensure the All Users install button has a UAC shield - LONGLONG elevated, installAll; - - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + BOOL elevated = WillElevate(); + ThemeControlElevates(_theme, ID_INSTALL_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, elevated); + ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, elevated); + } + + void Custom1Page_Show() { + LONGLONG installLauncherAllUsers; + + if (FAILED(BalGetNumericVariable(L"InstallLauncherAllUsers", &installLauncherAllUsers))) { + installLauncherAllUsers = 0; } - - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) { - ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE); - ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE); - } - } - - void Custom1Page_Show() { + ThemeSendControlMessage(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, BM_SETCHECK, + installLauncherAllUsers ? BST_CHECKED : BST_UNCHECKED, 0); } void Custom2Page_Show() { HRESULT hr; - LONGLONG installAll, elevated, includeLauncher; + LONGLONG installAll, includeLauncher; - if (FAILED(BalGetNumericVariable(L"WixBundleElevated", &elevated))) { - elevated = 0; + if (FAILED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { + installAll = 0; } - if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { - ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, installAll && !elevated); + + if (WillElevate()) { + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, TRUE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_HIDE); } else { - installAll = 0; + ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, FALSE); ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_SHOW); } @@ -1839,8 +1860,8 @@ COLORREF fg = fnt->crForeground, bg = fnt->crBackground; *brush = fnt->hBackground; RemapColor(&fg, &bg, brush); - SetTextColor(hDC, fg); - SetBkColor(hDC, bg); + ::SetTextColor(hDC, fg); + ::SetBkColor(hDC, bg); return TRUE; } @@ -2080,6 +2101,7 @@ for (DWORD i = 0; i < pPage->cControlIndices; ++i) { THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices[i]; + BOOL enableControl = TRUE; // If this is a named control, try to set its default state. if (pControl->sczName && *pControl->sczName) { @@ -2091,7 +2113,7 @@ // If the control value isn't set then disable it. if (!SUCCEEDED(hr)) { - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else { ThemeSendControlMessage( _theme, @@ -2110,13 +2132,25 @@ LPWSTR controlState = nullptr; hr = BalGetStringVariable(controlName, &controlState); if (SUCCEEDED(hr) && controlState && *controlState) { + if (controlState[0] == '[') { + LPWSTR formatted = nullptr; + if (SUCCEEDED(BalFormatString(controlState, &formatted))) { + StrFree(controlState); + controlState = formatted; + } + } + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"disable", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); - ThemeControlEnable(_theme, pControl->wId, FALSE); + enableControl = FALSE; } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"hide", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); // TODO: This doesn't work ThemeShowControl(_theme, pControl->wId, SW_HIDE); + } else { + // An explicit state can override the lack of a + // backing variable. + enableControl = TRUE; } } StrFree(controlState); @@ -2124,6 +2158,8 @@ StrFree(controlName); } + ThemeControlEnable(_theme, pControl->wId, enableControl); + // Format the text in each of the new page's controls if (pControl->sczText && *pControl->sczText) { // If the wix developer is showing a hidden variable @@ -2405,6 +2441,16 @@ } } + BOOL WillElevate() { + static BAL_CONDITION WILL_ELEVATE_CONDITION = { + L"not WixBundleElevated and (InstallAllUsers or (InstallLauncherAllUsers and Include_launcher))", + L"" + }; + BOOL result; + + return SUCCEEDED(BalConditionEvaluate(&WILL_ELEVATE_CONDITION, _engine, &result, nullptr)) && result; + } + BOOL IsCrtInstalled() { if (_crtInstalledToken > 0) { return TRUE; diff --git a/Tools/msi/bundle/bundle.targets b/Tools/msi/bundle/bundle.targets --- a/Tools/msi/bundle/bundle.targets +++ b/Tools/msi/bundle/bundle.targets @@ -88,7 +88,7 @@ - diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -24,15 +24,16 @@ + - + - + - + @@ -45,6 +46,8 @@ + + @@ -67,6 +70,7 @@ + diff --git a/Tools/msi/bundle/packagegroups/launcher.wxs b/Tools/msi/bundle/packagegroups/launcher.wxs --- a/Tools/msi/bundle/packagegroups/launcher.wxs +++ b/Tools/msi/bundle/packagegroups/launcher.wxs @@ -9,7 +9,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_launcher" /> + InstallCondition="(InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> + InstallCondition="not (InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" /> \ No newline at end of file diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs --- a/Tools/msi/common.wxs +++ b/Tools/msi/common.wxs @@ -103,7 +103,7 @@ - + diff --git a/Tools/msi/launcher/launcher_files.wxs b/Tools/msi/launcher/launcher_files.wxs --- a/Tools/msi/launcher/launcher_files.wxs +++ b/Tools/msi/launcher/launcher_files.wxs @@ -3,22 +3,22 @@ - + - + NOT ALLUSERS=1 - + ALLUSERS=1 - + diff --git a/Tools/msi/launcher/launcher_reg.wxs b/Tools/msi/launcher/launcher_reg.wxs --- a/Tools/msi/launcher/launcher_reg.wxs +++ b/Tools/msi/launcher/launcher_reg.wxs @@ -3,7 +3,7 @@ - + diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -81,10 +81,10 @@ $(DefineConstants);CRTRedist=$(CRTRedist); - + $(DefineConstants);TestPrefix=;FileExtension=py; - + $(DefineConstants);TestPrefix=x;FileExtension=px; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 10:11:10 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 08:11:10 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321750=3A_mock=5Fopen=2Eread=5Fdata_can_now_be_read_fr?= =?utf-8?q?om_each_instance=2C_as_it?= Message-ID: <20150717081110.29569.62467@psf.io> https://hg.python.org/cpython/rev/0da764c58322 changeset: 96926:0da764c58322 branch: 3.5 parent: 96923:1ec07f0d118a parent: 96925:41d55ac50dea user: Robert Collins date: Fri Jul 17 20:10:23 2015 +1200 summary: Issue #21750: mock_open.read_data can now be read from each instance, as it could in Python 3.3. files: Lib/unittest/mock.py | 70 +++++++------ Lib/unittest/test/testmock/testmock.py | 5 + Lib/unittest/test/testmock/testwith.py | 18 +++- Misc/NEWS | 3 + 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2286,6 +2286,7 @@ for line in data_as_list: yield line + def mock_open(mock=None, read_data=''): """ A helper function to create a mock to replace the use of `open`. It works @@ -2298,24 +2299,6 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - global file_spec if file_spec is None: import _io @@ -2324,21 +2307,42 @@ if mock is None: mock = MagicMock(name='open', spec=open) - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - - mock.return_value = handle + def make_handle(*args, **kwargs): + # Arg checking is handled by __call__ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + _check_and_set_parent(mock, handle, None, '()') + return handle + + mock.side_effect = make_handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1371,6 +1371,11 @@ self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()]) self.assertEqual(m.method_calls, []) + def test_mock_open_reuse_issue_21750(self): + mocked_open = mock.mock_open(read_data='data') + f1 = mocked_open('a-name') + f2 = mocked_open('another-name') + self.assertEqual(f1.read(), f2.read()) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,7 +141,6 @@ def test_mock_open_context_manager(self): mock = mock_open() - handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -149,8 +148,23 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - self.assertIs(f, handle) + # mock_open.return_value is no longer static, because + # readline support requires that it mutate state + def test_mock_open_context_manager_multiple_times(self): + mock = mock_open() + with patch('%s.open' % __name__, mock, create=True): + with open('foo') as f: + f.read() + with open('bar') as f: + f.read() + + expected_calls = [ + call('foo'), call().__enter__(), call().read(), + call().__exit__(None, None, None), + call('bar'), call().__enter__(), call().read(), + call().__exit__(None, None, None)] + self.assertEqual(mock.mock_calls, expected_calls) def test_explicit_mock(self): mock = MagicMock() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -73,6 +73,9 @@ Library ------- +- Issue #21750: mock_open.read_data can now be read from each instance, as it + could in Python 3.3. + - Issue #24552: Fix use after free in an error case of the _pickle module. - Issue #24514: tarfile now tolerates number fields consisting of only -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 10:11:10 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 08:11:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321750=3A_mock=5Fopen=2Eread=5Fdata_can_now_be_r?= =?utf-8?q?ead_from_each_instance=2C_as_it?= Message-ID: <20150717081110.41999.34776@psf.io> https://hg.python.org/cpython/rev/92a90e469424 changeset: 96927:92a90e469424 parent: 96924:2854dba70ee7 parent: 96926:0da764c58322 user: Robert Collins date: Fri Jul 17 20:10:57 2015 +1200 summary: Issue #21750: mock_open.read_data can now be read from each instance, as it could in Python 3.3. files: Lib/unittest/mock.py | 70 +++++++------ Lib/unittest/test/testmock/testmock.py | 5 + Lib/unittest/test/testmock/testwith.py | 18 +++- Misc/NEWS | 3 + 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2286,6 +2286,7 @@ for line in data_as_list: yield line + def mock_open(mock=None, read_data=''): """ A helper function to create a mock to replace the use of `open`. It works @@ -2298,24 +2299,6 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - global file_spec if file_spec is None: import _io @@ -2324,21 +2307,42 @@ if mock is None: mock = MagicMock(name='open', spec=open) - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - - mock.return_value = handle + def make_handle(*args, **kwargs): + # Arg checking is handled by __call__ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + _check_and_set_parent(mock, handle, None, '()') + return handle + + mock.side_effect = make_handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1371,6 +1371,11 @@ self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()]) self.assertEqual(m.method_calls, []) + def test_mock_open_reuse_issue_21750(self): + mocked_open = mock.mock_open(read_data='data') + f1 = mocked_open('a-name') + f2 = mocked_open('another-name') + self.assertEqual(f1.read(), f2.read()) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,7 +141,6 @@ def test_mock_open_context_manager(self): mock = mock_open() - handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -149,8 +148,23 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - self.assertIs(f, handle) + # mock_open.return_value is no longer static, because + # readline support requires that it mutate state + def test_mock_open_context_manager_multiple_times(self): + mock = mock_open() + with patch('%s.open' % __name__, mock, create=True): + with open('foo') as f: + f.read() + with open('bar') as f: + f.read() + + expected_calls = [ + call('foo'), call().__enter__(), call().read(), + call().__exit__(None, None, None), + call('bar'), call().__enter__(), call().read(), + call().__exit__(None, None, None)] + self.assertEqual(mock.mock_calls, expected_calls) def test_explicit_mock(self): mock = MagicMock() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -89,6 +89,9 @@ Library ------- +- Issue #21750: mock_open.read_data can now be read from each instance, as it + could in Python 3.3. + - Issue #24552: Fix use after free in an error case of the _pickle module. - Issue #24514: tarfile now tolerates number fields consisting of only -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 10:11:09 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 08:11:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNzUw?= =?utf-8?q?=3A_mock=5Fopen=2Eread=5Fdata_can_now_be_read_from_each_instanc?= =?utf-8?q?e=2C_as_it?= Message-ID: <20150717081109.29268.14462@psf.io> https://hg.python.org/cpython/rev/41d55ac50dea changeset: 96925:41d55ac50dea branch: 3.4 parent: 96920:35a6fe0e2b27 user: Robert Collins date: Fri Jul 17 20:08:45 2015 +1200 summary: Issue #21750: mock_open.read_data can now be read from each instance, as it could in Python 3.3. files: Lib/unittest/mock.py | 70 +++++++------ Lib/unittest/test/testmock/testmock.py | 5 + Lib/unittest/test/testmock/testwith.py | 18 +++- Misc/NEWS | 3 + 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2265,6 +2265,7 @@ for line in data_as_list: yield line + def mock_open(mock=None, read_data=''): """ A helper function to create a mock to replace the use of `open`. It works @@ -2277,24 +2278,6 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - global file_spec if file_spec is None: import _io @@ -2303,21 +2286,42 @@ if mock is None: mock = MagicMock(name='open', spec=open) - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - - mock.return_value = handle + def make_handle(*args, **kwargs): + # Arg checking is handled by __call__ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + _check_and_set_parent(mock, handle, None, '()') + return handle + + mock.side_effect = make_handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1326,6 +1326,11 @@ self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()]) self.assertEqual(m.method_calls, []) + def test_mock_open_reuse_issue_21750(self): + mocked_open = mock.mock_open(read_data='data') + f1 = mocked_open('a-name') + f2 = mocked_open('another-name') + self.assertEqual(f1.read(), f2.read()) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,7 +141,6 @@ def test_mock_open_context_manager(self): mock = mock_open() - handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -149,8 +148,23 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - self.assertIs(f, handle) + # mock_open.return_value is no longer static, because + # readline support requires that it mutate state + def test_mock_open_context_manager_multiple_times(self): + mock = mock_open() + with patch('%s.open' % __name__, mock, create=True): + with open('foo') as f: + f.read() + with open('bar') as f: + f.read() + + expected_calls = [ + call('foo'), call().__enter__(), call().read(), + call().__exit__(None, None, None), + call('bar'), call().__enter__(), call().read(), + call().__exit__(None, None, None)] + self.assertEqual(mock.mock_calls, expected_calls) def test_explicit_mock(self): mock = MagicMock() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #21750: mock_open.read_data can now be read from each instance, as it + could in Python 3.3. + - Issue #23247: Fix a crash in the StreamWriter.reset() of CJK codecs. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri Jul 17 11:05:01 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 17 Jul 2015 09:05:01 +0000 Subject: [Python-checkins] Daily reference leaks (2854dba70ee7): sum=4670028 Message-ID: <20150717085454.14698.38848@psf.io> results for 2854dba70ee7 on branch "default" -------------------------------------------- test_dict leaked [8, 8, 8] references, sum=24 test_dict leaked [2, 2, 2] memory blocks, sum=6 test_builtin leaked [6, 6, 6] references, sum=18 test_doctest leaked [49, 49, 49] references, sum=147 test_abc leaked [2, 2, 2] references, sum=6 test_argparse leaked [6891, 6891, 6891] references, sum=20673 test_argparse leaked [1499, 1501, 1501] memory blocks, sum=4501 test_ast leaked [465, 465, 465] references, sum=1395 test_ast leaked [7, 8, 8] memory blocks, sum=23 test_asyncio leaked [4142, 4189, 4167] references, sum=12498 test_asyncio leaked [18, 19, 19] memory blocks, sum=56 test_atexit leaked [242, 242, 242] references, sum=726 test_atexit leaked [6, 6, 6] memory blocks, sum=18 test_bigmem leaked [20586, 20586, 20586] references, sum=61758 test_bytes leaked [6504, 6504, 6504] references, sum=19512 test_bytes leaked [6504, 6506, 6506] memory blocks, sum=19516 test_capi leaked [123, 123, 123] references, sum=369 test_capi leaked [3, 3, 3] memory blocks, sum=9 test_cgi leaked [5, 5, 5] references, sum=15 test_cgi leaked [3, 3, 3] memory blocks, sum=9 test_cmd leaked [2, 2, 2] references, sum=6 test_cmd leaked [2, 2, 2] memory blocks, sum=6 test_codecs leaked [42, 42, 42] references, sum=126 test_codecs leaked [42, 42, 42] memory blocks, sum=126 test_collections leaked [345, 366, 340] references, sum=1051 test_collections leaked [98, 99, 99] memory blocks, sum=296 test_compile leaked [32, 32, 32] references, sum=96 test_concurrent_futures leaked [50, 50, 50] references, sum=150 test_concurrent_futures leaked [26, 26, 26] memory blocks, sum=78 test_configparser leaked [84, 84, 84] references, sum=252 test_configparser leaked [72, 72, 72] memory blocks, sum=216 test_decimal leaked [19, 19, 19] references, sum=57 test_decimal leaked [6, 6, 6] memory blocks, sum=18 test_dictviews leaked [24, 24, 24] references, sum=72 test_dictviews leaked [6, 6, 6] memory blocks, sum=18 test_distutils leaked [26, 26, 26] references, sum=78 test_distutils leaked [23, 23, 23] memory blocks, sum=69 test_email leaked [1189, 1189, 1189] references, sum=3567 test_enum leaked [1718, 1718, 1718] references, sum=5154 test_enumerate leaked [10004, 10004, 10004] references, sum=30012 test_enumerate leaked [10004, 10006, 10006] memory blocks, sum=30016 test_functools leaked [0, 2, 2] memory blocks, sum=4 test_generators leaked [1, 1, 1] references, sum=3 test_hash leaked [4678, 4678, 4678] references, sum=14034 test_hashlib leaked [444, 444, 444] references, sum=1332 test_hashlib leaked [222, 223, 223] memory blocks, sum=668 test_imp leaked [12, 12, 12] references, sum=36 test_importlib leaked [10, 10, 10] references, sum=30 test_importlib leaked [10, 10, 10] memory blocks, sum=30 test_inspect leaked [10, 10, 10] references, sum=30 test_ipaddress leaked [1962, 1962, 1962] references, sum=5886 test_ipaddress leaked [6, 7, 7] memory blocks, sum=20 test_itertools leaked [1274006, 1274006, 1274006] references, sum=3822018 test_itertools leaked [110, 111, 111] memory blocks, sum=332 test_lib2to3 leaked [81118, 81118, 81118] references, sum=243354 test_lib2to3 leaked [71752, 71754, 71754] memory blocks, sum=215260 test_listcomps leaked [3, 3, 3] references, sum=9 test_logging leaked [28, 28, 28] references, sum=84 test_macpath leaked [1, 1, 1] references, sum=3 test_mailbox leaked [2, 2, 2] references, sum=6 test_marshal leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] memory blocks, sum=30 test_multiprocessing_fork leaked [1, 1, 1] references, sum=3 test_multiprocessing_forkserver leaked [1, 1, 1] references, sum=3 test_multiprocessing_spawn leaked [1, 1, 1] references, sum=3 test_ntpath leaked [153, 153, 153] references, sum=459 test_ntpath leaked [45, 45, 45] memory blocks, sum=135 test_numeric_tower leaked [1, 1, 1] references, sum=3 test_peepholer leaked [5, 5, 5] references, sum=15 test_pep277 leaked [206, 206, 206] references, sum=618 test_pep277 leaked [134, 134, 134] memory blocks, sum=402 test_pep352 leaked [2, 2, 2] references, sum=6 test_pep352 leaked [2, 2, 2] memory blocks, sum=6 test_pickle leaked [292, 292, 292] references, sum=876 test_posix leaked [1, 1, 1] references, sum=3 test_posixpath leaked [43, 43, 43] references, sum=129 test_pulldom leaked [4, 4, 4] references, sum=12 test_pydoc leaked [7, 7, 7] references, sum=21 test_pyexpat leaked [1, 1, 1] references, sum=3 test_random leaked [588, 588, 588] references, sum=1764 test_random leaked [392, 394, 394] memory blocks, sum=1180 test_regrtest leaked [1621, 1621, 1621] references, sum=4863 test_regrtest leaked [319, 321, 321] memory blocks, sum=961 test_scope leaked [2, 2, 2] references, sum=6 test_set leaked [23761, 23761, 24961] references, sum=72483 test_set leaked [785, 787, 787] memory blocks, sum=2359 test_setcomps leaked [36, 36, 36] references, sum=108 test_smtpd leaked [3167, 3167, 3167] references, sum=9501 test_smtplib leaked [20, 20, 20] references, sum=60 test_socket leaked [3, 3, 3] references, sum=9 test_socket leaked [3, 3, 3] memory blocks, sum=9 test_ssl leaked [26, 26, 26] references, sum=78 test_statistics leaked [781, 781, 781] references, sum=2343 test_string leaked [5, 5, 5] references, sum=15 test_strptime leaked [32, 32, 32] references, sum=96 test_sys leaked [5, 5, 5] references, sum=15 test_threading leaked [246, 246, 246] references, sum=738 test_threading leaked [6, 6, 6] memory blocks, sum=18 test_timeit leaked [3, 3, 3] references, sum=9 test_trace leaked [95, 95, 95] references, sum=285 test_trace leaked [2, 2, 2] memory blocks, sum=6 test_traceback leaked [252, 252, 252] references, sum=756 test_typechecks leaked [8, 8, 8] references, sum=24 test_unicode leaked [3264, 3264, 3264] references, sum=9792 test_unicode leaked [3252, 3254, 3254] memory blocks, sum=9760 test_unpack_ex leaked [1, 1, 1] references, sum=3 test_urllib2 leaked [1, 1, 1] references, sum=3 test_urllibnet leaked [1, 1, 1] references, sum=3 test_userstring leaked [3252, 3252, 3252] references, sum=9756 test_userstring leaked [3252, 3254, 3254] memory blocks, sum=9760 test_weakref leaked [1, 1, 1] references, sum=3 test_weakset leaked [53, 53, 53] references, sum=159 test_weakset leaked [53, 53, 53] memory blocks, sum=159 test_wsgiref leaked [6, 6, 6] references, sum=18 test_xml_etree leaked [3508, 3508, 3508] references, sum=10524 test_xml_etree leaked [1206, 1208, 1208] memory blocks, sum=3622 test_zipimport_support leaked [37, 37, 37] references, sum=111 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog80Rjv3', '--timeout', '7200'] From python-checkins at python.org Fri Jul 17 12:01:00 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 10:01:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Typo_fix_in_mock=2Epatch=2E?= Message-ID: <20150717100059.30201.45487@psf.io> https://hg.python.org/cpython/rev/c635242ca3f0 changeset: 96930:c635242ca3f0 parent: 96927:92a90e469424 parent: 96929:1c2c989082b0 user: Robert Collins date: Fri Jul 17 22:00:45 2015 +1200 summary: Typo fix in mock.patch. Patch from https://github.com/testing-cabal/mock/issues/215 files: Lib/unittest/mock.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1480,7 +1480,7 @@ used. A more powerful form of `spec` is `autospec`. If you set `autospec=True` - then the mock with be created with a spec from the object being replaced. + then the mock will be created with a spec from the object being replaced. All attributes of the mock will also have the spec of the corresponding attribute of the object being replaced. Methods and functions being mocked will have their arguments checked and will raise a `TypeError` if -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 12:00:59 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 10:00:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Typo_fix_in_mo?= =?utf-8?b?Y2sucGF0Y2gu?= Message-ID: <20150717100059.18730.10847@psf.io> https://hg.python.org/cpython/rev/5439faa1f604 changeset: 96928:5439faa1f604 branch: 3.4 parent: 96925:41d55ac50dea user: Robert Collins date: Fri Jul 17 21:58:36 2015 +1200 summary: Typo fix in mock.patch. Patch from https://github.com/testing-cabal/mock/issues/215 files: Lib/unittest/mock.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1462,7 +1462,7 @@ used. A more powerful form of `spec` is `autospec`. If you set `autospec=True` - then the mock with be created with a spec from the object being replaced. + then the mock will be created with a spec from the object being replaced. All attributes of the mock will also have the spec of the corresponding attribute of the object being replaced. Methods and functions being mocked will have their arguments checked and will raise a `TypeError` if -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 12:01:01 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 17 Jul 2015 10:01:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Typo_fix_in_mock=2Epatch=2E?= Message-ID: <20150717100059.28232.98426@psf.io> https://hg.python.org/cpython/rev/1c2c989082b0 changeset: 96929:1c2c989082b0 branch: 3.5 parent: 96926:0da764c58322 parent: 96928:5439faa1f604 user: Robert Collins date: Fri Jul 17 22:00:28 2015 +1200 summary: Typo fix in mock.patch. Patch from https://github.com/testing-cabal/mock/issues/215 files: Lib/unittest/mock.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1480,7 +1480,7 @@ used. A more powerful form of `spec` is `autospec`. If you set `autospec=True` - then the mock with be created with a spec from the object being replaced. + then the mock will be created with a spec from the object being replaced. All attributes of the mock will also have the spec of the corresponding attribute of the object being replaced. Methods and functions being mocked will have their arguments checked and will raise a `TypeError` if -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 21:00:41 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 17 Jul 2015 19:00:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Removes_my_use?= =?utf-8?q?rname_from_the_documentation=2E?= Message-ID: <20150717190028.130423.29143@psf.io> https://hg.python.org/cpython/rev/efac259881a9 changeset: 96932:efac259881a9 branch: 3.5 user: Steve Dower date: Fri Jul 17 11:59:35 2015 -0700 summary: Removes my username from the documentation. files: Doc/using/win_installer.png | Bin 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index e5d5e07a1433bc0b9c7ed8929cc8d95437249855..00c88a830febd622082fae5a2c93657586b96fde GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 21:00:41 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 17 Jul 2015 19:00:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogRml4ZXMgc3lzLnBh?= =?utf-8?q?th_for_applocal_environments=2E?= Message-ID: <20150717190028.85835.96223@psf.io> https://hg.python.org/cpython/rev/829a5523c837 changeset: 96931:829a5523c837 branch: 3.5 parent: 96929:1c2c989082b0 user: Steve Dower date: Fri Jul 17 11:59:21 2015 -0700 summary: Fixes sys.path for applocal environments. files: Lib/site.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/site.py b/Lib/site.py --- a/Lib/site.py +++ b/Lib/site.py @@ -476,6 +476,12 @@ system_site = value.lower() elif key == 'home': sys._home = value + elif key == 'applocal' and value.lower() == 'true': + # App-local installs use the exe_dir as prefix, + # not one level higher, and do not use system + # site packages. + site_prefix = exe_dir + system_site = 'false' sys.prefix = sys.exec_prefix = site_prefix -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 21:00:41 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 17 Jul 2015 19:00:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150717190028.85841.33773@psf.io> https://hg.python.org/cpython/rev/b2a1fe8f1b11 changeset: 96933:b2a1fe8f1b11 parent: 96930:c635242ca3f0 parent: 96932:efac259881a9 user: Steve Dower date: Fri Jul 17 11:59:57 2015 -0700 summary: Merge with 3.5 files: Doc/using/win_installer.png | Bin Lib/site.py | 6 ++++++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index e5d5e07a1433bc0b9c7ed8929cc8d95437249855..00c88a830febd622082fae5a2c93657586b96fde GIT binary patch [stripped] diff --git a/Lib/site.py b/Lib/site.py --- a/Lib/site.py +++ b/Lib/site.py @@ -476,6 +476,12 @@ system_site = value.lower() elif key == 'home': sys._home = value + elif key == 'applocal' and value.lower() == 'true': + # App-local installs use the exe_dir as prefix, + # not one level higher, and do not use system + # site packages. + site_prefix = exe_dir + system_site = 'false' sys.prefix = sys.exec_prefix = site_prefix -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 17 23:31:01 2015 From: python-checkins at python.org (thomas.wouters) Date: Fri, 17 Jul 2015 21:31:01 +0000 Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Add_a_few_missing_LICEN?= =?utf-8?q?SE_files_for_third-party_projects=2E?= Message-ID: <20150717213101.18730.46317@psf.io> https://hg.python.org/benchmarks/rev/2979f5ce6a0c changeset: 220:2979f5ce6a0c user: Thomas Wouters date: Fri Jul 17 14:29:12 2015 -0700 summary: Add a few missing LICENSE files for third-party projects. files: lib/2to3/LICENSE | 48 ++++++ lib/html5lib/LICENSE | 34 ++++ lib/tornado-3.1.1/LICENSE | 202 ++++++++++++++++++++++++++ lib3/2to3/LICENSE | 48 ++++++ 4 files changed, 332 insertions(+), 0 deletions(-) diff --git a/lib/2to3/LICENSE b/lib/2to3/LICENSE new file mode 100644 --- /dev/null +++ b/lib/2to3/LICENSE @@ -0,0 +1,48 @@ +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative +version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/lib/html5lib/LICENSE b/lib/html5lib/LICENSE new file mode 100644 --- /dev/null +++ b/lib/html5lib/LICENSE @@ -0,0 +1,34 @@ +Copyright (c) 2006-2011 The Authors + +Contributors: +James Graham - jg307 at cam.ac.uk +Anne van Kesteren - annevankesteren at gmail.com +Lachlan Hunt - lachlan.hunt at lachy.id.au +Matt McDonald - kanashii at kanashii.ca +Sam Ruby - rubys at intertwingly.net +Ian Hickson (Google) - ian at hixie.ch +Thomas Broyer - t.broyer at ltgt.net +Jacques Distler - distler at golem.ph.utexas.edu +Henri Sivonen - hsivonen at iki.fi +Adam Barth - abarth at webkit.org +Eric Seidel - eric at webkit.org +The Mozilla Foundation (contributions from Henri Sivonen since 2008) +David Flanagan (Mozilla) - dflanagan at mozilla.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/lib/tornado-3.1.1/LICENSE b/lib/tornado-3.1.1/LICENSE new file mode 100644 --- /dev/null +++ b/lib/tornado-3.1.1/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib3/2to3/LICENSE b/lib3/2to3/LICENSE new file mode 100644 --- /dev/null +++ b/lib3/2to3/LICENSE @@ -0,0 +1,48 @@ +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative +version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. -- Repository URL: https://hg.python.org/benchmarks From python-checkins at python.org Sat Jul 18 01:49:52 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 17 Jul 2015 23:49:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324642=3A_Adds_installer_notes_and_links_to_What?= =?utf-8?q?=27s_New_for_3=2E5?= Message-ID: <20150717234952.18742.98862@psf.io> https://hg.python.org/cpython/rev/d6c91b8242d2 changeset: 96935:d6c91b8242d2 parent: 96933:b2a1fe8f1b11 parent: 96934:06600287f11f user: Steve Dower date: Fri Jul 17 16:49:24 2015 -0700 summary: Issue #24642: Adds installer notes and links to What's New for 3.5 files: Doc/whatsnew/3.5.rst | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -117,6 +117,14 @@ * None yet. +Windows improvements: + +* A new installer for Windows has replaced the old MSI. See :ref:`using-on-windows` + for more information. +* Windows builds now use Microsoft Visual C++ 14.0, and extension modules + should use the same. + + Please read on for a comprehensive list of user-facing changes. @@ -850,6 +858,8 @@ * :c:func:`PyObject_Calloc` * :c:func:`_PyObject_GC_Calloc` +* Windows builds now require Microsoft Visual C++ 14.0, which + is available as part of `Visual Studio 2015 `_. Deprecated ========== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 01:49:52 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 17 Jul 2015 23:49:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjQy?= =?utf-8?q?=3A_Adds_installer_notes_and_links_to_What=27s_New_for_3=2E5?= Message-ID: <20150717234952.18716.65029@psf.io> https://hg.python.org/cpython/rev/06600287f11f changeset: 96934:06600287f11f branch: 3.5 parent: 96932:efac259881a9 user: Steve Dower date: Fri Jul 17 16:48:48 2015 -0700 summary: Issue #24642: Adds installer notes and links to What's New for 3.5 files: Doc/whatsnew/3.5.rst | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -117,6 +117,14 @@ * None yet. +Windows improvements: + +* A new installer for Windows has replaced the old MSI. See :ref:`using-on-windows` + for more information. +* Windows builds now use Microsoft Visual C++ 14.0, and extension modules + should use the same. + + Please read on for a comprehensive list of user-facing changes. @@ -850,6 +858,8 @@ * :c:func:`PyObject_Calloc` * :c:func:`_PyObject_GC_Calloc` +* Windows builds now require Microsoft Visual C++ 14.0, which + is available as part of `Visual Studio 2015 `_. Deprecated ========== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 08:37:07 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 18 Jul 2015 06:37:07 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Update_benchmark_c?= =?utf-8?q?ode?= Message-ID: <20150718063707.130421.20289@psf.io> https://hg.python.org/peps/rev/7ad183c1d9be changeset: 5906:7ad183c1d9be user: Yury Selivanov date: Sat Jul 18 09:37:02 2015 +0300 summary: pep-492: Update benchmark code Since coroutines now have a distinct type, they do not support iteration. Instead of doing 'list(o)', we now do 'o.send(None)' until StopIteration. Note, that the updated timings are due to the difference of doing a loop in Python vs doing it in C ('list()' vs 'while True'). files: pep-0492.txt | 24 ++++++++++++++++-------- 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1310,21 +1310,29 @@ r = await abinary(n - 1) return l + 1 + r - def timeit(gen, depth, repeat): + def timeit(func, depth, repeat): t0 = time.time() for _ in range(repeat): - list(gen(depth)) + o = func(depth) + try: + while True: + o.send(None) + except StopIteration: + pass t1 = time.time() print('{}({}) * {}: total {:.3f}s'.format( - gen.__name__, depth, repeat, t1-t0)) + func.__name__, depth, repeat, t1-t0)) -The result is that there is no observable performance difference. -Minimum timing of 3 runs +The result is that there is no observable performance difference:: -:: + binary(19) * 30: total 53.321s + abinary(19) * 30: total 55.073s - abinary(19) * 30: total 12.985s - binary(19) * 30: total 12.953s + binary(19) * 30: total 53.361s + abinary(19) * 30: total 51.360s + + binary(19) * 30: total 49.438s + abinary(19) * 30: total 51.047s Note that depth of 19 means 1,048,575 calls. -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Sat Jul 18 10:51:08 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 18 Jul 2015 08:51:08 +0000 Subject: [Python-checkins] Daily reference leaks (d6c91b8242d2): sum=4671285 Message-ID: <20150718085108.30207.56978@psf.io> results for d6c91b8242d2 on branch "default" -------------------------------------------- test_dict leaked [8, 8, 8] references, sum=24 test_dict leaked [2, 2, 2] memory blocks, sum=6 test_builtin leaked [6, 6, 6] references, sum=18 test_doctest leaked [49, 49, 49] references, sum=147 test_abc leaked [2, 2, 2] references, sum=6 test_argparse leaked [6891, 6891, 6891] references, sum=20673 test_argparse leaked [1499, 1501, 1501] memory blocks, sum=4501 test_ast leaked [465, 465, 465] references, sum=1395 test_ast leaked [7, 8, 8] memory blocks, sum=23 test_asyncio leaked [4189, 4164, 4164] references, sum=12517 test_asyncio leaked [18, 19, 19] memory blocks, sum=56 test_atexit leaked [242, 242, 242] references, sum=726 test_atexit leaked [6, 6, 6] memory blocks, sum=18 test_bigmem leaked [20586, 20586, 20586] references, sum=61758 test_bytes leaked [6504, 6504, 6504] references, sum=19512 test_bytes leaked [6504, 6506, 6506] memory blocks, sum=19516 test_capi leaked [123, 123, 123] references, sum=369 test_capi leaked [3, 3, 3] memory blocks, sum=9 test_cgi leaked [5, 5, 5] references, sum=15 test_cgi leaked [3, 3, 3] memory blocks, sum=9 test_cmd leaked [2, 2, 2] references, sum=6 test_cmd leaked [2, 2, 2] memory blocks, sum=6 test_codecs leaked [42, 42, 42] references, sum=126 test_codecs leaked [42, 42, 42] memory blocks, sum=126 test_collections leaked [340, 369, 347] references, sum=1056 test_collections leaked [98, 99, 99] memory blocks, sum=296 test_compile leaked [32, 32, 32] references, sum=96 test_concurrent_futures leaked [50, 50, 50] references, sum=150 test_concurrent_futures leaked [26, 26, 26] memory blocks, sum=78 test_configparser leaked [84, 84, 84] references, sum=252 test_configparser leaked [72, 72, 72] memory blocks, sum=216 test_decimal leaked [19, 19, 19] references, sum=57 test_decimal leaked [6, 6, 6] memory blocks, sum=18 test_dictviews leaked [24, 24, 24] references, sum=72 test_dictviews leaked [6, 6, 6] memory blocks, sum=18 test_distutils leaked [26, 26, 26] references, sum=78 test_distutils leaked [23, 23, 23] memory blocks, sum=69 test_email leaked [1190, 1190, 1190] references, sum=3570 test_enum leaked [1718, 1718, 1718] references, sum=5154 test_enumerate leaked [10004, 10004, 10004] references, sum=30012 test_enumerate leaked [10004, 10006, 10006] memory blocks, sum=30016 test_functools leaked [0, 2, 2] memory blocks, sum=4 test_generators leaked [1, 1, 1] references, sum=3 test_hash leaked [4688, 4688, 4688] references, sum=14064 test_hashlib leaked [444, 444, 444] references, sum=1332 test_hashlib leaked [222, 223, 223] memory blocks, sum=668 test_imp leaked [12, 12, 12] references, sum=36 test_importlib leaked [10, 10, 10] references, sum=30 test_importlib leaked [10, 10, 10] memory blocks, sum=30 test_inspect leaked [10, 10, 10] references, sum=30 test_ipaddress leaked [1962, 1962, 1962] references, sum=5886 test_ipaddress leaked [6, 7, 7] memory blocks, sum=20 test_itertools leaked [1274006, 1274006, 1274006] references, sum=3822018 test_itertools leaked [110, 111, 111] memory blocks, sum=332 test_lib2to3 leaked [81118, 81118, 81118] references, sum=243354 test_lib2to3 leaked [71752, 71754, 71754] memory blocks, sum=215260 test_listcomps leaked [3, 3, 3] references, sum=9 test_logging leaked [28, 28, 28] references, sum=84 test_macpath leaked [1, 1, 1] references, sum=3 test_mailbox leaked [2, 2, 2] references, sum=6 test_marshal leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] memory blocks, sum=30 test_multiprocessing_fork leaked [1, 1, 1] references, sum=3 test_multiprocessing_forkserver leaked [1, 1, 1] references, sum=3 test_multiprocessing_spawn leaked [1, 1, 1] references, sum=3 test_ntpath leaked [153, 153, 153] references, sum=459 test_ntpath leaked [45, 45, 45] memory blocks, sum=135 test_numeric_tower leaked [1, 1, 1] references, sum=3 test_peepholer leaked [5, 5, 5] references, sum=15 test_pep277 leaked [206, 206, 206] references, sum=618 test_pep277 leaked [134, 134, 134] memory blocks, sum=402 test_pep352 leaked [2, 2, 2] references, sum=6 test_pep352 leaked [2, 2, 2] memory blocks, sum=6 test_pickle leaked [292, 292, 292] references, sum=876 test_posix leaked [1, 1, 1] references, sum=3 test_posixpath leaked [43, 43, 43] references, sum=129 test_pulldom leaked [4, 4, 4] references, sum=12 test_pydoc leaked [7, 7, 7] references, sum=21 test_pyexpat leaked [1, 1, 1] references, sum=3 test_random leaked [588, 588, 588] references, sum=1764 test_random leaked [392, 394, 394] memory blocks, sum=1180 test_regrtest leaked [1621, 1621, 1621] references, sum=4863 test_regrtest leaked [319, 321, 321] memory blocks, sum=961 test_scope leaked [2, 2, 2] references, sum=6 test_set leaked [24961, 25161, 23561] references, sum=73683 test_set leaked [785, 787, 787] memory blocks, sum=2359 test_setcomps leaked [36, 36, 36] references, sum=108 test_smtpd leaked [3167, 3167, 3167] references, sum=9501 test_smtplib leaked [20, 20, 20] references, sum=60 test_socket leaked [3, 3, 3] references, sum=9 test_socket leaked [3, 3, 3] memory blocks, sum=9 test_ssl leaked [26, 26, 26] references, sum=78 test_statistics leaked [781, 781, 781] references, sum=2343 test_string leaked [5, 5, 5] references, sum=15 test_strptime leaked [32, 32, 32] references, sum=96 test_sys leaked [5, 5, 5] references, sum=15 test_threading leaked [246, 246, 246] references, sum=738 test_threading leaked [6, 6, 6] memory blocks, sum=18 test_timeit leaked [3, 3, 3] references, sum=9 test_trace leaked [95, 95, 95] references, sum=285 test_trace leaked [2, 2, 2] memory blocks, sum=6 test_traceback leaked [252, 252, 252] references, sum=756 test_typechecks leaked [8, 8, 8] references, sum=24 test_unicode leaked [3264, 3264, 3264] references, sum=9792 test_unicode leaked [3252, 3254, 3254] memory blocks, sum=9760 test_unpack_ex leaked [1, 1, 1] references, sum=3 test_urllib2 leaked [1, 1, 1] references, sum=3 test_urllibnet leaked [1, 1, 1] references, sum=3 test_userstring leaked [3252, 3252, 3252] references, sum=9756 test_userstring leaked [3252, 3254, 3254] memory blocks, sum=9760 test_weakref leaked [1, 1, 1] references, sum=3 test_weakset leaked [53, 53, 53] references, sum=159 test_weakset leaked [53, 53, 53] memory blocks, sum=159 test_wsgiref leaked [6, 6, 6] references, sum=18 test_xml_etree leaked [3508, 3508, 3508] references, sum=10524 test_xml_etree leaked [1206, 1208, 1208] memory blocks, sum=3622 test_zipimport_support leaked [37, 37, 37] references, sum=111 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogSOt9Sl', '--timeout', '7200'] From python-checkins at python.org Sat Jul 18 18:30:09 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 18 Jul 2015 16:30:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjQy?= =?utf-8?q?=3A_Improves_help_text_displayed_in_the_Windows_installer=2E?= Message-ID: <20150718163009.10007.77180@psf.io> https://hg.python.org/cpython/rev/9f60ec6d6586 changeset: 96938:9f60ec6d6586 branch: 3.5 user: Steve Dower date: Sat Jul 18 09:28:41 2015 -0700 summary: Issue #24642: Improves help text displayed in the Windows installer. files: Tools/msi/bundle/Default.wxl | 19 +++++++++---------- 1 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -26,20 +26,19 @@ Are you sure you want to cancel? Previous version Setup Help - /uninstall - Uninstalls Python without prompting for confirmation. + Visit <a href="http://docs.python.org/[ShortVersion]/using/windows.html">docs.python.org/[ShortVersion]/using/windows.html</a> for the full list of options, including the ability to enable and disable specific features. -/layout [\[]directory[\]] - Downloads all components for offline installation. +"/passive" to display progress without requiring user interaction -/passive - Displays progress without requiring user interaction. +"/quiet" to install/uninstall without displaying any UI -/quiet - Performs the requested action without displaying any UI. +"/simple" to prevent user customization -/log [\[]filename[\]] - Logs to a specific file. By default, log files are created in %TEMP%. +"/uninstall" to remove Python (without confirmation) + +"/layout [\[]directory[\]]" to pre-download all components + +"/log [\[]filename[\]]" to specify log files location [WixBundleName] <a href="#">license terms</a>. I &agree to the license terms and conditions &Install Now -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 18:30:09 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 18 Jul 2015 16:30:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Adds_support_f?= =?utf-8?q?or_an_unattend=2Exml_file_to_control_the_Windows_installer_opti?= =?utf-8?q?ons=2E?= Message-ID: <20150718163008.9943.86939@psf.io> https://hg.python.org/cpython/rev/d41944d15256 changeset: 96937:d41944d15256 branch: 3.5 user: Steve Dower date: Sat Jul 18 09:28:19 2015 -0700 summary: Adds support for an unattend.xml file to control the Windows installer options. files: Doc/using/windows.rst | 14 + Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 93 +++++++++- 2 files changed, 106 insertions(+), 1 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -171,6 +171,20 @@ recommended for per-user installs when there is also a system-wide installation that included the launcher.) +The options listed above can also be provided in a file named ``unattend.xml`` +alongside the executable. This file specifies a list of options and values. +When a value is provided as an attribute, it will be converted to a number if +possible. Values provided as element text are always left as strings. This +example file sets the same options and the previous example:: + + + + + .. _install-layout-option: Installing Without Downloading diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -1249,6 +1249,92 @@ return hr; } + // + // ParseVariablesFromUnattendXml - reads options from unattend.xml if it + // exists + // + HRESULT ParseVariablesFromUnattendXml() { + HRESULT hr = S_OK; + LPWSTR sczUnattendXmlPath = nullptr; + IXMLDOMDocument *pixdUnattend = nullptr; + IXMLDOMNodeList *pNodes = nullptr; + IXMLDOMNode *pNode = nullptr; + long cNodes; + DWORD dwAttr; + LPWSTR scz = nullptr; + BOOL bValue; + int iValue; + BOOL tryConvert; + BSTR bstrValue = nullptr; + + hr = BalFormatString(L"[WixBundleOriginalSourceFolder]unattend.xml", &sczUnattendXmlPath); + BalExitOnFailure(hr, "Failed to calculate path to unattend.xml"); + + if (!FileExistsEx(sczUnattendXmlPath, &dwAttr)) { + BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Did not find %ls", sczUnattendXmlPath); + hr = S_FALSE; + goto LExit; + } + + hr = XmlLoadDocumentFromFile(sczUnattendXmlPath, &pixdUnattend); + BalExitOnFailure1(hr, "Failed to read %ls", sczUnattendXmlPath); + + // get the list of variables users have overridden + hr = XmlSelectNodes(pixdUnattend, L"/Options/Option", &pNodes); + if (S_FALSE == hr) { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to select option nodes."); + + hr = pNodes->get_length((long*)&cNodes); + BalExitOnFailure(hr, "Failed to get option node count."); + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Reading settings from %ls", sczUnattendXmlPath); + + for (DWORD i = 0; i < cNodes; ++i) { + hr = XmlNextElement(pNodes, &pNode, nullptr); + BalExitOnFailure(hr, "Failed to get next node."); + + // @Name + hr = XmlGetAttributeEx(pNode, L"Name", &scz); + BalExitOnFailure(hr, "Failed to get @Name."); + + tryConvert = TRUE; + hr = XmlGetAttribute(pNode, L"Value", &bstrValue); + if (FAILED(hr) || !bstrValue || !*bstrValue) { + hr = XmlGetText(pNode, &bstrValue); + tryConvert = FALSE; + } + BalExitOnFailure(hr, "Failed to get @Value."); + + if (tryConvert && + CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, bstrValue, -1, L"yes", -1)) { + _engine->SetVariableNumeric(scz, 1); + } else if (tryConvert && + CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, bstrValue, -1, L"no", -1)) { + _engine->SetVariableNumeric(scz, 0); + } else if (tryConvert && ::StrToIntExW(bstrValue, STIF_DEFAULT, &iValue)) { + _engine->SetVariableNumeric(scz, iValue); + } else { + _engine->SetVariableString(scz, bstrValue); + } + + ReleaseNullBSTR(bstrValue); + ReleaseNullStr(scz); + ReleaseNullObject(pNode); + } + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Finished reading from %ls", sczUnattendXmlPath); + + LExit: + ReleaseObject(pNode); + ReleaseObject(pNodes); + ReleaseObject(pixdUnattend); + ReleaseStr(sczUnattendXmlPath); + + return hr; + } + // // InitializeData - initializes all the package information. @@ -1264,6 +1350,9 @@ hr = ParseOverridableVariablesFromXml(pixdManifest); BalExitOnFailure(hr, "Failed to read overridable variables."); + hr = ParseVariablesFromUnattendXml(); + ExitOnFailure(hr, "Failed to read unattend.ini file."); + hr = ProcessCommandLine(&_language); ExitOnFailure(hr, "Unknown commandline parameters."); @@ -1323,7 +1412,9 @@ hr = StrAllocString(psczLanguage, &argv[i][0], 0); BalExitOnFailure(hr, "Failed to copy language."); - } + } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"simple", -1)) { + _engine->SetVariableNumeric(L"SimpleInstall", 1); + } } else if (_overridableVariables) { int value; const wchar_t* pwc = wcschr(argv[i], L'='); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 18:30:08 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 18 Jul 2015 16:30:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Adds_option_to?= =?utf-8?q?_only_install_the_launcher=2E?= Message-ID: <20150718163008.85849.60220@psf.io> https://hg.python.org/cpython/rev/9ddd6809be70 changeset: 96936:9ddd6809be70 branch: 3.5 parent: 96934:06600287f11f user: Steve Dower date: Sat Jul 18 09:27:52 2015 -0700 summary: Adds option to only install the launcher. files: Doc/using/windows.rst | 3 ++ Tools/msi/bundle/Default.thm | 2 +- Tools/msi/bundle/bundle.wxs | 2 + Tools/msi/bundle/packagegroups/core.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/crt.wxs | 4 +- Tools/msi/bundle/packagegroups/dev.wxs | 8 +++--- Tools/msi/bundle/packagegroups/doc.wxs | 4 +- Tools/msi/bundle/packagegroups/exe.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/lib.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/postinstall.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/tcltk.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/test.wxs | 12 +++++----- Tools/msi/bundle/packagegroups/tools.wxs | 4 +- 13 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -146,6 +146,9 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_tools | Install utility scripts | 1 | +---------------------------+--------------------------------------+--------------------------+ +| LauncherOnly | Only installs the launcher. This | 0 | +| | will override most other options. | | ++---------------------------+--------------------------------------+--------------------------+ | SimpleInstall | Disable most install UI | 0 | +---------------------------+--------------------------------------+--------------------------+ | SimpleInstallDescription | A custom message to display when the | (empty) | diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -12,7 +12,7 @@ #(loc.HelpHeader) - #(loc.HelpText) + #(loc.HelpText) diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -64,6 +64,8 @@ + + diff --git a/Tools/msi/bundle/packagegroups/core.wxs b/Tools/msi/bundle/packagegroups/core.wxs --- a/Tools/msi/bundle/packagegroups/core.wxs +++ b/Tools/msi/bundle/packagegroups/core.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/crt.wxs b/Tools/msi/bundle/packagegroups/crt.wxs --- a/Tools/msi/bundle/packagegroups/crt.wxs +++ b/Tools/msi/bundle/packagegroups/crt.wxs @@ -31,7 +31,7 @@ Description="!(loc.CRTDescription)" Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not CRTInstalled and VersionNT = $(var.ver) and not VersionNT64 and (Include_core or Include_exe or Include_launcher or Include_pip)" /> + InstallCondition="not CRTInstalled and VersionNT = $(var.ver) and not VersionNT64 and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly" /> + InstallCondition="not CRTInstalled and VersionNT64 = $(var.ver) and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly" /> diff --git a/Tools/msi/bundle/packagegroups/dev.wxs b/Tools/msi/bundle/packagegroups/dev.wxs --- a/Tools/msi/bundle/packagegroups/dev.wxs +++ b/Tools/msi/bundle/packagegroups/dev.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_dev"> + InstallCondition="InstallAllUsers and Include_dev and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_dev and Include_debug"> + InstallCondition="InstallAllUsers and Include_dev and Include_debug and not LauncherOnly"> @@ -26,7 +26,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_dev"> + InstallCondition="not InstallAllUsers and Include_dev and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_dev and Include_debug"> + InstallCondition="not InstallAllUsers and Include_dev and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/doc.wxs b/Tools/msi/bundle/packagegroups/doc.wxs --- a/Tools/msi/bundle/packagegroups/doc.wxs +++ b/Tools/msi/bundle/packagegroups/doc.wxs @@ -8,7 +8,7 @@ DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_doc"> + InstallCondition="InstallAllUsers and Include_doc and not LauncherOnly"> @@ -19,7 +19,7 @@ DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_doc"> + InstallCondition="not InstallAllUsers and Include_doc and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/exe.wxs b/Tools/msi/bundle/packagegroups/exe.wxs --- a/Tools/msi/bundle/packagegroups/exe.wxs +++ b/Tools/msi/bundle/packagegroups/exe.wxs @@ -8,7 +8,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip)"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -17,7 +17,7 @@ ForcePerMachine="yes" Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -26,7 +26,7 @@ ForcePerMachine="yes" Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> @@ -37,7 +37,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip)"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -46,7 +46,7 @@ ForcePerMachine="no" Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -55,7 +55,7 @@ ForcePerMachine="no" Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/lib.wxs b/Tools/msi/bundle/packagegroups/lib.wxs --- a/Tools/msi/bundle/packagegroups/lib.wxs +++ b/Tools/msi/bundle/packagegroups/lib.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib"> + InstallCondition="InstallAllUsers and Include_lib and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib and Include_symbols"> + InstallCondition="InstallAllUsers and Include_lib and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib and Include_debug"> + InstallCondition="InstallAllUsers and Include_lib and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib"> + InstallCondition="not InstallAllUsers and Include_lib and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_lib and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib and Include_debug"> + InstallCondition="not InstallAllUsers and Include_lib and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_pip"> + InstallCondition="InstallAllUsers and Include_pip and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_pip"> + InstallCondition="not InstallAllUsers and Include_pip and not LauncherOnly"> @@ -26,7 +26,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and PrependPath"> + InstallCondition="InstallAllUsers and PrependPath and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and PrependPath"> + InstallCondition="not InstallAllUsers and PrependPath and not LauncherOnly"> @@ -50,7 +50,7 @@ Permanent="yes" PerMachine="yes" Vital="no" - InstallCondition="InstallAllUsers and CompileAll" /> + InstallCondition="InstallAllUsers and CompileAll and not LauncherOnly" /> + InstallCondition="not InstallAllUsers and CompileAll and not LauncherOnly" /> \ No newline at end of file diff --git a/Tools/msi/bundle/packagegroups/tcltk.wxs b/Tools/msi/bundle/packagegroups/tcltk.wxs --- a/Tools/msi/bundle/packagegroups/tcltk.wxs +++ b/Tools/msi/bundle/packagegroups/tcltk.wxs @@ -8,7 +8,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk"> + InstallCondition="InstallAllUsers and Include_tcltk and not LauncherOnly"> @@ -18,7 +18,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk and Include_symbols"> + InstallCondition="InstallAllUsers and Include_tcltk and Include_symbols and not LauncherOnly"> @@ -28,7 +28,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk and Include_debug"> + InstallCondition="InstallAllUsers and Include_tcltk and Include_debug and not LauncherOnly"> @@ -39,7 +39,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk"> + InstallCondition="not InstallAllUsers and Include_tcltk and not LauncherOnly"> @@ -49,7 +49,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_tcltk and Include_symbols and not LauncherOnly"> @@ -59,7 +59,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk and Include_debug"> + InstallCondition="not InstallAllUsers and Include_tcltk and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/test.wxs b/Tools/msi/bundle/packagegroups/test.wxs --- a/Tools/msi/bundle/packagegroups/test.wxs +++ b/Tools/msi/bundle/packagegroups/test.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test"> + InstallCondition="InstallAllUsers and Include_test and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test and Include_symbols"> + InstallCondition="InstallAllUsers and Include_test and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test and Include_debug"> + InstallCondition="InstallAllUsers and Include_test and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test"> + InstallCondition="not InstallAllUsers and Include_test and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_test and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test and Include_debug"> + InstallCondition="not InstallAllUsers and Include_test and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/tools.wxs b/Tools/msi/bundle/packagegroups/tools.wxs --- a/Tools/msi/bundle/packagegroups/tools.wxs +++ b/Tools/msi/bundle/packagegroups/tools.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_tools"> + InstallCondition="InstallAllUsers and Include_tools and not LauncherOnly"> @@ -17,7 +17,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_tools"> + InstallCondition="not InstallAllUsers and Include_tools and not LauncherOnly"> -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 18:30:09 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 18 Jul 2015 16:30:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150718163009.87944.22143@psf.io> https://hg.python.org/cpython/rev/21839c82419b changeset: 96939:21839c82419b parent: 96935:d6c91b8242d2 parent: 96938:9f60ec6d6586 user: Steve Dower date: Sat Jul 18 09:29:03 2015 -0700 summary: Merge with 3.5 files: Doc/using/windows.rst | 17 + Tools/msi/bundle/Default.thm | 2 +- Tools/msi/bundle/Default.wxl | 19 +- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 93 +++++++++- Tools/msi/bundle/bundle.wxs | 2 + Tools/msi/bundle/packagegroups/core.wxs | 12 +- Tools/msi/bundle/packagegroups/crt.wxs | 4 +- Tools/msi/bundle/packagegroups/dev.wxs | 8 +- Tools/msi/bundle/packagegroups/doc.wxs | 4 +- Tools/msi/bundle/packagegroups/exe.wxs | 12 +- Tools/msi/bundle/packagegroups/lib.wxs | 12 +- Tools/msi/bundle/packagegroups/postinstall.wxs | 12 +- Tools/msi/bundle/packagegroups/tcltk.wxs | 12 +- Tools/msi/bundle/packagegroups/test.wxs | 12 +- Tools/msi/bundle/packagegroups/tools.wxs | 4 +- 15 files changed, 167 insertions(+), 58 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -146,6 +146,9 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_tools | Install utility scripts | 1 | +---------------------------+--------------------------------------+--------------------------+ +| LauncherOnly | Only installs the launcher. This | 0 | +| | will override most other options. | | ++---------------------------+--------------------------------------+--------------------------+ | SimpleInstall | Disable most install UI | 0 | +---------------------------+--------------------------------------+--------------------------+ | SimpleInstallDescription | A custom message to display when the | (empty) | @@ -168,6 +171,20 @@ recommended for per-user installs when there is also a system-wide installation that included the launcher.) +The options listed above can also be provided in a file named ``unattend.xml`` +alongside the executable. This file specifies a list of options and values. +When a value is provided as an attribute, it will be converted to a number if +possible. Values provided as element text are always left as strings. This +example file sets the same options and the previous example:: + + + + + .. _install-layout-option: Installing Without Downloading diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -12,7 +12,7 @@ #(loc.HelpHeader) - #(loc.HelpText) + #(loc.HelpText) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -26,20 +26,19 @@ Are you sure you want to cancel? Previous version Setup Help - /uninstall - Uninstalls Python without prompting for confirmation. + Visit <a href="http://docs.python.org/[ShortVersion]/using/windows.html">docs.python.org/[ShortVersion]/using/windows.html</a> for the full list of options, including the ability to enable and disable specific features. -/layout [\[]directory[\]] - Downloads all components for offline installation. +"/passive" to display progress without requiring user interaction -/passive - Displays progress without requiring user interaction. +"/quiet" to install/uninstall without displaying any UI -/quiet - Performs the requested action without displaying any UI. +"/simple" to prevent user customization -/log [\[]filename[\]] - Logs to a specific file. By default, log files are created in %TEMP%. +"/uninstall" to remove Python (without confirmation) + +"/layout [\[]directory[\]]" to pre-download all components + +"/log [\[]filename[\]]" to specify log files location [WixBundleName] <a href="#">license terms</a>. I &agree to the license terms and conditions &Install Now diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -1249,6 +1249,92 @@ return hr; } + // + // ParseVariablesFromUnattendXml - reads options from unattend.xml if it + // exists + // + HRESULT ParseVariablesFromUnattendXml() { + HRESULT hr = S_OK; + LPWSTR sczUnattendXmlPath = nullptr; + IXMLDOMDocument *pixdUnattend = nullptr; + IXMLDOMNodeList *pNodes = nullptr; + IXMLDOMNode *pNode = nullptr; + long cNodes; + DWORD dwAttr; + LPWSTR scz = nullptr; + BOOL bValue; + int iValue; + BOOL tryConvert; + BSTR bstrValue = nullptr; + + hr = BalFormatString(L"[WixBundleOriginalSourceFolder]unattend.xml", &sczUnattendXmlPath); + BalExitOnFailure(hr, "Failed to calculate path to unattend.xml"); + + if (!FileExistsEx(sczUnattendXmlPath, &dwAttr)) { + BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Did not find %ls", sczUnattendXmlPath); + hr = S_FALSE; + goto LExit; + } + + hr = XmlLoadDocumentFromFile(sczUnattendXmlPath, &pixdUnattend); + BalExitOnFailure1(hr, "Failed to read %ls", sczUnattendXmlPath); + + // get the list of variables users have overridden + hr = XmlSelectNodes(pixdUnattend, L"/Options/Option", &pNodes); + if (S_FALSE == hr) { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to select option nodes."); + + hr = pNodes->get_length((long*)&cNodes); + BalExitOnFailure(hr, "Failed to get option node count."); + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Reading settings from %ls", sczUnattendXmlPath); + + for (DWORD i = 0; i < cNodes; ++i) { + hr = XmlNextElement(pNodes, &pNode, nullptr); + BalExitOnFailure(hr, "Failed to get next node."); + + // @Name + hr = XmlGetAttributeEx(pNode, L"Name", &scz); + BalExitOnFailure(hr, "Failed to get @Name."); + + tryConvert = TRUE; + hr = XmlGetAttribute(pNode, L"Value", &bstrValue); + if (FAILED(hr) || !bstrValue || !*bstrValue) { + hr = XmlGetText(pNode, &bstrValue); + tryConvert = FALSE; + } + BalExitOnFailure(hr, "Failed to get @Value."); + + if (tryConvert && + CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, bstrValue, -1, L"yes", -1)) { + _engine->SetVariableNumeric(scz, 1); + } else if (tryConvert && + CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, bstrValue, -1, L"no", -1)) { + _engine->SetVariableNumeric(scz, 0); + } else if (tryConvert && ::StrToIntExW(bstrValue, STIF_DEFAULT, &iValue)) { + _engine->SetVariableNumeric(scz, iValue); + } else { + _engine->SetVariableString(scz, bstrValue); + } + + ReleaseNullBSTR(bstrValue); + ReleaseNullStr(scz); + ReleaseNullObject(pNode); + } + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Finished reading from %ls", sczUnattendXmlPath); + + LExit: + ReleaseObject(pNode); + ReleaseObject(pNodes); + ReleaseObject(pixdUnattend); + ReleaseStr(sczUnattendXmlPath); + + return hr; + } + // // InitializeData - initializes all the package information. @@ -1264,6 +1350,9 @@ hr = ParseOverridableVariablesFromXml(pixdManifest); BalExitOnFailure(hr, "Failed to read overridable variables."); + hr = ParseVariablesFromUnattendXml(); + ExitOnFailure(hr, "Failed to read unattend.ini file."); + hr = ProcessCommandLine(&_language); ExitOnFailure(hr, "Unknown commandline parameters."); @@ -1323,7 +1412,9 @@ hr = StrAllocString(psczLanguage, &argv[i][0], 0); BalExitOnFailure(hr, "Failed to copy language."); - } + } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"simple", -1)) { + _engine->SetVariableNumeric(L"SimpleInstall", 1); + } } else if (_overridableVariables) { int value; const wchar_t* pwc = wcschr(argv[i], L'='); diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -64,6 +64,8 @@ + + diff --git a/Tools/msi/bundle/packagegroups/core.wxs b/Tools/msi/bundle/packagegroups/core.wxs --- a/Tools/msi/bundle/packagegroups/core.wxs +++ b/Tools/msi/bundle/packagegroups/core.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/crt.wxs b/Tools/msi/bundle/packagegroups/crt.wxs --- a/Tools/msi/bundle/packagegroups/crt.wxs +++ b/Tools/msi/bundle/packagegroups/crt.wxs @@ -31,7 +31,7 @@ Description="!(loc.CRTDescription)" Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not CRTInstalled and VersionNT = $(var.ver) and not VersionNT64 and (Include_core or Include_exe or Include_launcher or Include_pip)" /> + InstallCondition="not CRTInstalled and VersionNT = $(var.ver) and not VersionNT64 and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly" /> + InstallCondition="not CRTInstalled and VersionNT64 = $(var.ver) and (Include_core or Include_exe or Include_launcher or Include_pip) and not LauncherOnly" /> diff --git a/Tools/msi/bundle/packagegroups/dev.wxs b/Tools/msi/bundle/packagegroups/dev.wxs --- a/Tools/msi/bundle/packagegroups/dev.wxs +++ b/Tools/msi/bundle/packagegroups/dev.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_dev"> + InstallCondition="InstallAllUsers and Include_dev and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_dev and Include_debug"> + InstallCondition="InstallAllUsers and Include_dev and Include_debug and not LauncherOnly"> @@ -26,7 +26,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_dev"> + InstallCondition="not InstallAllUsers and Include_dev and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_dev and Include_debug"> + InstallCondition="not InstallAllUsers and Include_dev and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/doc.wxs b/Tools/msi/bundle/packagegroups/doc.wxs --- a/Tools/msi/bundle/packagegroups/doc.wxs +++ b/Tools/msi/bundle/packagegroups/doc.wxs @@ -8,7 +8,7 @@ DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_doc"> + InstallCondition="InstallAllUsers and Include_doc and not LauncherOnly"> @@ -19,7 +19,7 @@ DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_doc"> + InstallCondition="not InstallAllUsers and Include_doc and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/exe.wxs b/Tools/msi/bundle/packagegroups/exe.wxs --- a/Tools/msi/bundle/packagegroups/exe.wxs +++ b/Tools/msi/bundle/packagegroups/exe.wxs @@ -8,7 +8,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip)"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -17,7 +17,7 @@ ForcePerMachine="yes" Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -26,7 +26,7 @@ ForcePerMachine="yes" Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> @@ -37,7 +37,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip)"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and not LauncherOnly"> @@ -46,7 +46,7 @@ ForcePerMachine="no" Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols and not LauncherOnly"> @@ -55,7 +55,7 @@ ForcePerMachine="no" Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" - InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug"> + InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/lib.wxs b/Tools/msi/bundle/packagegroups/lib.wxs --- a/Tools/msi/bundle/packagegroups/lib.wxs +++ b/Tools/msi/bundle/packagegroups/lib.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib"> + InstallCondition="InstallAllUsers and Include_lib and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib and Include_symbols"> + InstallCondition="InstallAllUsers and Include_lib and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_lib and Include_debug"> + InstallCondition="InstallAllUsers and Include_lib and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib"> + InstallCondition="not InstallAllUsers and Include_lib and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_lib and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_lib and Include_debug"> + InstallCondition="not InstallAllUsers and Include_lib and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_pip"> + InstallCondition="InstallAllUsers and Include_pip and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_pip"> + InstallCondition="not InstallAllUsers and Include_pip and not LauncherOnly"> @@ -26,7 +26,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and PrependPath"> + InstallCondition="InstallAllUsers and PrependPath and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and PrependPath"> + InstallCondition="not InstallAllUsers and PrependPath and not LauncherOnly"> @@ -50,7 +50,7 @@ Permanent="yes" PerMachine="yes" Vital="no" - InstallCondition="InstallAllUsers and CompileAll" /> + InstallCondition="InstallAllUsers and CompileAll and not LauncherOnly" /> + InstallCondition="not InstallAllUsers and CompileAll and not LauncherOnly" /> \ No newline at end of file diff --git a/Tools/msi/bundle/packagegroups/tcltk.wxs b/Tools/msi/bundle/packagegroups/tcltk.wxs --- a/Tools/msi/bundle/packagegroups/tcltk.wxs +++ b/Tools/msi/bundle/packagegroups/tcltk.wxs @@ -8,7 +8,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk"> + InstallCondition="InstallAllUsers and Include_tcltk and not LauncherOnly"> @@ -18,7 +18,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk and Include_symbols"> + InstallCondition="InstallAllUsers and Include_tcltk and Include_symbols and not LauncherOnly"> @@ -28,7 +28,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" EnableFeatureSelection="yes" - InstallCondition="InstallAllUsers and Include_tcltk and Include_debug"> + InstallCondition="InstallAllUsers and Include_tcltk and Include_debug and not LauncherOnly"> @@ -39,7 +39,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk"> + InstallCondition="not InstallAllUsers and Include_tcltk and not LauncherOnly"> @@ -49,7 +49,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_tcltk and Include_symbols and not LauncherOnly"> @@ -59,7 +59,7 @@ DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" EnableFeatureSelection="yes" - InstallCondition="not InstallAllUsers and Include_tcltk and Include_debug"> + InstallCondition="not InstallAllUsers and Include_tcltk and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/test.wxs b/Tools/msi/bundle/packagegroups/test.wxs --- a/Tools/msi/bundle/packagegroups/test.wxs +++ b/Tools/msi/bundle/packagegroups/test.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test"> + InstallCondition="InstallAllUsers and Include_test and not LauncherOnly"> @@ -16,7 +16,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test and Include_symbols"> + InstallCondition="InstallAllUsers and Include_test and Include_symbols and not LauncherOnly"> @@ -25,7 +25,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_test and Include_debug"> + InstallCondition="InstallAllUsers and Include_test and Include_debug and not LauncherOnly"> @@ -35,7 +35,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test"> + InstallCondition="not InstallAllUsers and Include_test and not LauncherOnly"> @@ -44,7 +44,7 @@ Compressed="$(var.CompressPDB)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test and Include_symbols"> + InstallCondition="not InstallAllUsers and Include_test and Include_symbols and not LauncherOnly"> @@ -53,7 +53,7 @@ Compressed="$(var.CompressMSI_D)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_test and Include_debug"> + InstallCondition="not InstallAllUsers and Include_test and Include_debug and not LauncherOnly"> diff --git a/Tools/msi/bundle/packagegroups/tools.wxs b/Tools/msi/bundle/packagegroups/tools.wxs --- a/Tools/msi/bundle/packagegroups/tools.wxs +++ b/Tools/msi/bundle/packagegroups/tools.wxs @@ -7,7 +7,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="yes" - InstallCondition="InstallAllUsers and Include_tools"> + InstallCondition="InstallAllUsers and Include_tools and not LauncherOnly"> @@ -17,7 +17,7 @@ Compressed="$(var.CompressMSI)" DownloadUrl="$(var.DownloadUrl)" ForcePerMachine="no" - InstallCondition="not InstallAllUsers and Include_tools"> + InstallCondition="not InstallAllUsers and Include_tools and not LauncherOnly"> -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 20:01:22 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 18 Jul 2015 18:01:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_improve_style_?= =?utf-8?q?of_the_convert_macro_=28=2324655=29?= Message-ID: <20150718180122.23371.46624@psf.io> https://hg.python.org/cpython/rev/e4f9562d625d changeset: 96943:e4f9562d625d branch: 2.7 parent: 96916:ca78b9449e04 user: Benjamin Peterson date: Sat Jul 18 10:59:13 2015 -0700 summary: improve style of the convert macro (#24655) Patch by Brian Cain. files: Modules/_ssl.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3426,19 +3426,19 @@ PyObject *odir_env = NULL; PyObject *odir = NULL; -#define convert(info, target) { \ +#define CONVERT(info, target) { \ const char *tmp = (info); \ target = NULL; \ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ else { target = PyBytes_FromString(tmp); } \ if (!target) goto error; \ - } while(0) - - convert(X509_get_default_cert_file_env(), ofile_env); - convert(X509_get_default_cert_file(), ofile); - convert(X509_get_default_cert_dir_env(), odir_env); - convert(X509_get_default_cert_dir(), odir); -#undef convert + } + + CONVERT(X509_get_default_cert_file_env(), ofile_env); + CONVERT(X509_get_default_cert_file(), ofile); + CONVERT(X509_get_default_cert_dir_env(), odir_env); + CONVERT(X509_get_default_cert_dir(), odir); +#undef CONVERT return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 20:01:22 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 18 Jul 2015 18:01:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4_=28=2324655=29?= Message-ID: <20150718180122.14726.97634@psf.io> https://hg.python.org/cpython/rev/bffa3b5fd2d8 changeset: 96941:bffa3b5fd2d8 branch: 3.5 parent: 96938:9f60ec6d6586 parent: 96940:24cf6b4d72c2 user: Benjamin Peterson date: Sat Jul 18 11:00:00 2015 -0700 summary: merge 3.4 (#24655) files: Modules/_ssl.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3963,20 +3963,20 @@ PyObject *odir_env = NULL; PyObject *odir = NULL; -#define convert(info, target) { \ +#define CONVERT(info, target) { \ const char *tmp = (info); \ target = NULL; \ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \ target = PyBytes_FromString(tmp); } \ if (!target) goto error; \ - } while(0) - - convert(X509_get_default_cert_file_env(), ofile_env); - convert(X509_get_default_cert_file(), ofile); - convert(X509_get_default_cert_dir_env(), odir_env); - convert(X509_get_default_cert_dir(), odir); -#undef convert + } + + CONVERT(X509_get_default_cert_file_env(), ofile_env); + CONVERT(X509_get_default_cert_file(), ofile); + CONVERT(X509_get_default_cert_dir_env(), odir_env); + CONVERT(X509_get_default_cert_dir(), odir); +#undef CONVERT return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 20:01:22 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 18 Jul 2015 18:01:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_improve_style_?= =?utf-8?q?of_the_convert_macro_=28=2324655=29?= Message-ID: <20150718180122.85847.57742@psf.io> https://hg.python.org/cpython/rev/24cf6b4d72c2 changeset: 96940:24cf6b4d72c2 branch: 3.4 parent: 96928:5439faa1f604 user: Benjamin Peterson date: Sat Jul 18 10:59:13 2015 -0700 summary: improve style of the convert macro (#24655) Patch by Brian Cain. files: Modules/_ssl.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3372,20 +3372,20 @@ PyObject *odir_env = NULL; PyObject *odir = NULL; -#define convert(info, target) { \ +#define CONVERT(info, target) { \ const char *tmp = (info); \ target = NULL; \ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \ target = PyBytes_FromString(tmp); } \ if (!target) goto error; \ - } while(0) - - convert(X509_get_default_cert_file_env(), ofile_env); - convert(X509_get_default_cert_file(), ofile); - convert(X509_get_default_cert_dir_env(), odir_env); - convert(X509_get_default_cert_dir(), odir); -#undef convert + } + + CONVERT(X509_get_default_cert_file_env(), ofile_env); + CONVERT(X509_get_default_cert_file(), ofile); + CONVERT(X509_get_default_cert_dir_env(), odir_env); + CONVERT(X509_get_default_cert_dir(), odir); +#undef CONVERT return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 20:01:32 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 18 Jul 2015 18:01:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQ2NTUp?= Message-ID: <20150718180122.18734.2884@psf.io> https://hg.python.org/cpython/rev/35d6606b2480 changeset: 96942:35d6606b2480 parent: 96939:21839c82419b parent: 96941:bffa3b5fd2d8 user: Benjamin Peterson date: Sat Jul 18 11:00:19 2015 -0700 summary: merge 3.5 (#24655) files: Modules/_ssl.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3963,20 +3963,20 @@ PyObject *odir_env = NULL; PyObject *odir = NULL; -#define convert(info, target) { \ +#define CONVERT(info, target) { \ const char *tmp = (info); \ target = NULL; \ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \ target = PyBytes_FromString(tmp); } \ if (!target) goto error; \ - } while(0) - - convert(X509_get_default_cert_file_env(), ofile_env); - convert(X509_get_default_cert_file(), ofile); - convert(X509_get_default_cert_dir_env(), odir_env); - convert(X509_get_default_cert_dir(), odir); -#undef convert + } + + CONVERT(X509_get_default_cert_file_env(), ofile_env); + CONVERT(X509_get_default_cert_file(), ofile); + CONVERT(X509_get_default_cert_dir_env(), odir_env); + CONVERT(X509_get_default_cert_dir(), odir); +#undef CONVERT return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:22:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:22:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixed_typos_in?= =?utf-8?q?_Misc/NEWS=2E?= Message-ID: <20150718202238.70539.89477@psf.io> https://hg.python.org/cpython/rev/a7b226f94ed1 changeset: 96944:a7b226f94ed1 branch: 3.5 parent: 96941:bffa3b5fd2d8 user: Serhiy Storchaka date: Sat Jul 18 23:18:33 2015 +0300 summary: Fixed typos in Misc/NEWS. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,7 +19,7 @@ Library ------- -- Issue #24631: Fixed regression in the timeit modulu with multyline setup. +- Issue #24631: Fixed regression in the timeit module with multiline setup. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. Patch from Nicola Palumbo and Laurent De Buyst. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:22:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:22:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixed_typos_in_Misc/NEWS=2E?= Message-ID: <20150718202238.130421.21976@psf.io> https://hg.python.org/cpython/rev/2a9f4b9484b1 changeset: 96945:2a9f4b9484b1 parent: 96942:35d6606b2480 parent: 96944:a7b226f94ed1 user: Serhiy Storchaka date: Sat Jul 18 23:18:49 2015 +0300 summary: Fixed typos in Misc/NEWS. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,7 +41,7 @@ Library ------- -- Issue #24631: Fixed regression in the timeit modulu with multyline setup. +- Issue #24631: Fixed regression in the timeit module with multiline setup. - Issue #24608: chunk.Chunk.read() now always returns bytes, not str. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:22:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:22:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjA2?= =?utf-8?b?OiBGaXhlZCBfX2VxX18gYW5kIF9fbmVfXyBtZXRob2RzIG9mIGluc3BlY3Qg?= =?utf-8?q?classes=2E?= Message-ID: <20150718202238.29254.91787@psf.io> https://hg.python.org/cpython/rev/5ec2bfbe8115 changeset: 96946:5ec2bfbe8115 branch: 3.4 parent: 96940:24cf6b4d72c2 user: Serhiy Storchaka date: Sat Jul 18 23:19:05 2015 +0300 summary: Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. files: Lib/inspect.py | 26 +++----- Lib/test/test_inspect.py | 78 +++++++++++++++++++-------- Misc/NEWS | 2 + 3 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2206,15 +2206,13 @@ id(self), self.name) def __eq__(self, other): - return (issubclass(other.__class__, Parameter) and - self._name == other._name and + if not isinstance(other, Parameter): + return NotImplemented + return (self._name == other._name and self._kind == other._kind and self._default == other._default and self._annotation == other._annotation) - def __ne__(self, other): - return not self.__eq__(other) - class BoundArguments: '''Result of `Signature.bind` call. Holds the mapping of arguments @@ -2295,13 +2293,11 @@ return kwargs def __eq__(self, other): - return (issubclass(other.__class__, BoundArguments) and - self.signature == other.signature and + if not isinstance(other, BoundArguments): + return NotImplemented + return (self.signature == other.signature and self.arguments == other.arguments) - def __ne__(self, other): - return not self.__eq__(other) - class Signature: '''A Signature object represents the overall signature of a function. @@ -2493,9 +2489,10 @@ return_annotation=return_annotation) def __eq__(self, other): - if (not issubclass(type(other), Signature) or - self.return_annotation != other.return_annotation or - len(self.parameters) != len(other.parameters)): + if not isinstance(other, Signature): + return NotImplemented + if (self.return_annotation != other.return_annotation or + len(self.parameters) != len(other.parameters)): return False other_positions = {param: idx @@ -2522,9 +2519,6 @@ return True - def __ne__(self, other): - return not self.__eq__(other) - def _bind(self, args, kwargs, *, partial=False): '''Private method. Don't use directly.''' 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 @@ -76,6 +76,10 @@ for i in range(2): yield i +class EqualsToAll: + def __eq__(self, other): + return True + class TestPredicates(IsTestBase): def test_sixteen(self): count = len([x for x in dir(inspect) if x.startswith('is')]) @@ -2459,47 +2463,62 @@ def test_signature_equality(self): def foo(a, *, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), 42) + self.assertFalse(inspect.signature(foo) == 42) + self.assertTrue(inspect.signature(foo) != 42) + self.assertTrue(inspect.signature(foo) == EqualsToAll()) + self.assertFalse(inspect.signature(foo) != EqualsToAll()) def bar(a, *, b:int) -> float: pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) def bar(a, *, b:int) -> int: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def bar(a, *, b:int): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def bar(a, *, b:int=42) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def bar(a, *, c) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def bar(a, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def spam(b:int, a) -> float: pass - self.assertNotEqual(inspect.signature(spam), inspect.signature(bar)) + self.assertFalse(inspect.signature(spam) == inspect.signature(bar)) + self.assertTrue(inspect.signature(spam) != inspect.signature(bar)) def foo(*, a, b, c): pass def bar(*, c, b, a): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) def foo(*, a=1, b, c): pass def bar(*, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) def foo(pos, *, a=1, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) def foo(pos, *, a, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) def foo(pos, *args, a=42, b, c, **kwargs:int): pass def bar(pos, *args, c, b, a=42, **kwargs:int): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) def test_signature_unhashable(self): def foo(a): pass @@ -2629,11 +2648,17 @@ P = inspect.Parameter p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) - self.assertEqual(p, p) - self.assertNotEqual(p, 42) - - self.assertEqual(p, P('foo', default=42, - kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertTrue(p == p) + self.assertFalse(p != p) + self.assertFalse(p == 42) + self.assertTrue(p != 42) + self.assertTrue(p == EqualsToAll()) + self.assertFalse(p != EqualsToAll()) + + self.assertTrue(p == P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertFalse(p != P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) def test_signature_parameter_unhashable(self): p = inspect.Parameter('foo', default=42, @@ -2936,19 +2961,26 @@ def test_signature_bound_arguments_equality(self): def foo(a): pass ba = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba) + self.assertTrue(ba == ba) + self.assertFalse(ba != ba) + self.assertTrue(ba == EqualsToAll()) + self.assertFalse(ba != EqualsToAll()) ba2 = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba2) + self.assertTrue(ba == ba2) + self.assertFalse(ba != ba2) ba3 = inspect.signature(foo).bind(2) - self.assertNotEqual(ba, ba3) + self.assertFalse(ba == ba3) + self.assertTrue(ba != ba3) ba3.arguments['a'] = 1 - self.assertEqual(ba, ba3) + self.assertTrue(ba == ba3) + self.assertFalse(ba != ba3) def bar(b): pass ba4 = inspect.signature(bar).bind(1) - self.assertNotEqual(ba, ba4) + self.assertFalse(ba == ba4) + self.assertTrue(ba != ba4) class TestSignaturePrivateHelpers(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. + - Issue #21750: mock_open.read_data can now be read from each instance, as it could in Python 3.3. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:22:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:22:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?b?IElzc3VlICMyNDIwNjogRml4ZWQgX19lcV9fIGFuZCBfX25lX18gbWV0aG9k?= =?utf-8?q?s_of_inspect_classes=2E?= Message-ID: <20150718202238.87956.89396@psf.io> https://hg.python.org/cpython/rev/66a5f66b4049 changeset: 96947:66a5f66b4049 branch: 3.5 parent: 96944:a7b226f94ed1 parent: 96946:5ec2bfbe8115 user: Serhiy Storchaka date: Sat Jul 18 23:20:50 2015 +0300 summary: Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. files: Lib/inspect.py | 41 ++++++------- Lib/test/test_inspect.py | 80 +++++++++++++++++++-------- Misc/NEWS | 2 + 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2488,15 +2488,14 @@ return hash((self.name, self.kind, self.annotation, self.default)) def __eq__(self, other): - return (self is other or - (issubclass(other.__class__, Parameter) and - self._name == other._name and - self._kind == other._kind and - self._default == other._default and - self._annotation == other._annotation)) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, Parameter): + return NotImplemented + return (self._name == other._name and + self._kind == other._kind and + self._default == other._default and + self._annotation == other._annotation) class BoundArguments: @@ -2610,13 +2609,12 @@ self.arguments = OrderedDict(new_arguments) def __eq__(self, other): - return (self is other or - (issubclass(other.__class__, BoundArguments) and - self.signature == other.signature and - self.arguments == other.arguments)) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, BoundArguments): + return NotImplemented + return (self.signature == other.signature and + self.arguments == other.arguments) def __setstate__(self, state): self._signature = state['_signature'] @@ -2775,12 +2773,11 @@ return hash((params, kwo_params, return_annotation)) def __eq__(self, other): - return (self is other or - (isinstance(other, Signature) and - self._hash_basis() == other._hash_basis())) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, Signature): + return NotImplemented + return self._hash_basis() == other._hash_basis() def _bind(self, args, kwargs, *, partial=False): """Private method. Don't use directly.""" 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 @@ -89,6 +89,9 @@ yield return 'spam' +class EqualsToAll: + def __eq__(self, other): + return True class TestPredicates(IsTestBase): @@ -2672,69 +2675,84 @@ def test_signature_equality(self): def foo(a, *, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), 42) + self.assertFalse(inspect.signature(foo) == 42) + self.assertTrue(inspect.signature(foo) != 42) + self.assertTrue(inspect.signature(foo) == EqualsToAll()) + self.assertFalse(inspect.signature(foo) != EqualsToAll()) def bar(a, *, b:int) -> float: pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int) -> int: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int=42) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, c) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def spam(b:int, a) -> float: pass - self.assertNotEqual(inspect.signature(spam), inspect.signature(bar)) + self.assertFalse(inspect.signature(spam) == inspect.signature(bar)) + self.assertTrue(inspect.signature(spam) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(spam)), hash(inspect.signature(bar))) def foo(*, a, b, c): pass def bar(*, c, b, a): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(*, a=1, b, c): pass def bar(*, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *, a=1, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *, a, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *args, a=42, b, c, **kwargs:int): pass def bar(pos, *args, c, b, a=42, **kwargs:int): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) @@ -2907,11 +2925,17 @@ P = inspect.Parameter p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) - self.assertEqual(p, p) - self.assertNotEqual(p, 42) - - self.assertEqual(p, P('foo', default=42, - kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertTrue(p == p) + self.assertFalse(p != p) + self.assertFalse(p == 42) + self.assertTrue(p != 42) + self.assertTrue(p == EqualsToAll()) + self.assertFalse(p != EqualsToAll()) + + self.assertTrue(p == P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertFalse(p != P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) def test_signature_parameter_replace(self): p = inspect.Parameter('foo', default=42, @@ -3215,25 +3239,33 @@ def test_signature_bound_arguments_equality(self): def foo(a): pass ba = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba) + self.assertTrue(ba == ba) + self.assertFalse(ba != ba) + self.assertTrue(ba == EqualsToAll()) + self.assertFalse(ba != EqualsToAll()) ba2 = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba2) + self.assertTrue(ba == ba2) + self.assertFalse(ba != ba2) ba3 = inspect.signature(foo).bind(2) - self.assertNotEqual(ba, ba3) + self.assertFalse(ba == ba3) + self.assertTrue(ba != ba3) ba3.arguments['a'] = 1 - self.assertEqual(ba, ba3) + self.assertTrue(ba == ba3) + self.assertFalse(ba != ba3) def bar(b): pass ba4 = inspect.signature(bar).bind(1) - self.assertNotEqual(ba, ba4) + self.assertFalse(ba == ba4) + self.assertTrue(ba != ba4) def foo(*, a, b): pass sig = inspect.signature(foo) ba1 = sig.bind(a=1, b=2) ba2 = sig.bind(b=2, a=1) - self.assertEqual(ba1, ba2) + self.assertTrue(ba1 == ba2) + self.assertFalse(ba1 != ba2) def test_signature_bound_arguments_pickle(self): def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. + - Issue #24631: Fixed regression in the timeit module with multiline setup. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:22:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:22:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogSXNzdWUgIzI0MjA2OiBGaXhlZCBfX2VxX18gYW5kIF9fbmVfXyBtZXRo?= =?utf-8?q?ods_of_inspect_classes=2E?= Message-ID: <20150718202239.9922.11871@psf.io> https://hg.python.org/cpython/rev/adc9869c6d0d changeset: 96948:adc9869c6d0d parent: 96945:2a9f4b9484b1 parent: 96947:66a5f66b4049 user: Serhiy Storchaka date: Sat Jul 18 23:21:16 2015 +0300 summary: Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. files: Lib/inspect.py | 41 ++++++------- Lib/test/test_inspect.py | 80 +++++++++++++++++++-------- Misc/NEWS | 2 + 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2488,15 +2488,14 @@ return hash((self.name, self.kind, self.annotation, self.default)) def __eq__(self, other): - return (self is other or - (issubclass(other.__class__, Parameter) and - self._name == other._name and - self._kind == other._kind and - self._default == other._default and - self._annotation == other._annotation)) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, Parameter): + return NotImplemented + return (self._name == other._name and + self._kind == other._kind and + self._default == other._default and + self._annotation == other._annotation) class BoundArguments: @@ -2610,13 +2609,12 @@ self.arguments = OrderedDict(new_arguments) def __eq__(self, other): - return (self is other or - (issubclass(other.__class__, BoundArguments) and - self.signature == other.signature and - self.arguments == other.arguments)) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, BoundArguments): + return NotImplemented + return (self.signature == other.signature and + self.arguments == other.arguments) def __setstate__(self, state): self._signature = state['_signature'] @@ -2775,12 +2773,11 @@ return hash((params, kwo_params, return_annotation)) def __eq__(self, other): - return (self is other or - (isinstance(other, Signature) and - self._hash_basis() == other._hash_basis())) - - def __ne__(self, other): - return not self.__eq__(other) + if self is other: + return True + if not isinstance(other, Signature): + return NotImplemented + return self._hash_basis() == other._hash_basis() def _bind(self, args, kwargs, *, partial=False): """Private method. Don't use directly.""" 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 @@ -89,6 +89,9 @@ yield return 'spam' +class EqualsToAll: + def __eq__(self, other): + return True class TestPredicates(IsTestBase): @@ -2672,69 +2675,84 @@ def test_signature_equality(self): def foo(a, *, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), 42) + self.assertFalse(inspect.signature(foo) == 42) + self.assertTrue(inspect.signature(foo) != 42) + self.assertTrue(inspect.signature(foo) == EqualsToAll()) + self.assertFalse(inspect.signature(foo) != EqualsToAll()) def bar(a, *, b:int) -> float: pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int) -> int: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, b:int=42) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, *, c) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def bar(a, b:int) -> float: pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def spam(b:int, a) -> float: pass - self.assertNotEqual(inspect.signature(spam), inspect.signature(bar)) + self.assertFalse(inspect.signature(spam) == inspect.signature(bar)) + self.assertTrue(inspect.signature(spam) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(spam)), hash(inspect.signature(bar))) def foo(*, a, b, c): pass def bar(*, c, b, a): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(*, a=1, b, c): pass def bar(*, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *, a=1, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *, a, b, c): pass def bar(pos, *, c, b, a=1): pass - self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) self.assertNotEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) def foo(pos, *args, a=42, b, c, **kwargs:int): pass def bar(pos, *args, c, b, a=42, **kwargs:int): pass - self.assertEqual(inspect.signature(foo), inspect.signature(bar)) + self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) + self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) self.assertEqual( hash(inspect.signature(foo)), hash(inspect.signature(bar))) @@ -2907,11 +2925,17 @@ P = inspect.Parameter p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) - self.assertEqual(p, p) - self.assertNotEqual(p, 42) - - self.assertEqual(p, P('foo', default=42, - kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertTrue(p == p) + self.assertFalse(p != p) + self.assertFalse(p == 42) + self.assertTrue(p != 42) + self.assertTrue(p == EqualsToAll()) + self.assertFalse(p != EqualsToAll()) + + self.assertTrue(p == P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) + self.assertFalse(p != P('foo', default=42, + kind=inspect.Parameter.KEYWORD_ONLY)) def test_signature_parameter_replace(self): p = inspect.Parameter('foo', default=42, @@ -3215,25 +3239,33 @@ def test_signature_bound_arguments_equality(self): def foo(a): pass ba = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba) + self.assertTrue(ba == ba) + self.assertFalse(ba != ba) + self.assertTrue(ba == EqualsToAll()) + self.assertFalse(ba != EqualsToAll()) ba2 = inspect.signature(foo).bind(1) - self.assertEqual(ba, ba2) + self.assertTrue(ba == ba2) + self.assertFalse(ba != ba2) ba3 = inspect.signature(foo).bind(2) - self.assertNotEqual(ba, ba3) + self.assertFalse(ba == ba3) + self.assertTrue(ba != ba3) ba3.arguments['a'] = 1 - self.assertEqual(ba, ba3) + self.assertTrue(ba == ba3) + self.assertFalse(ba != ba3) def bar(b): pass ba4 = inspect.signature(bar).bind(1) - self.assertNotEqual(ba, ba4) + self.assertFalse(ba == ba4) + self.assertTrue(ba != ba4) def foo(*, a, b): pass sig = inspect.signature(foo) ba1 = sig.bind(a=1, b=2) ba2 = sig.bind(b=2, a=1) - self.assertEqual(ba1, ba2) + self.assertTrue(ba1 == ba2) + self.assertFalse(ba1 != ba2) def test_signature_bound_arguments_pickle(self): def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,8 @@ Library ------- +- Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. + - Issue #24631: Fixed regression in the timeit module with multiline setup. - Issue #24608: chunk.Chunk.read() now always returns bytes, not str. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:38:11 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:38:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NTgw?= =?utf-8?q?=3A_Symbolic_group_references_to_open_group_in_re_patterns_now_?= =?utf-8?q?are?= Message-ID: <20150718203811.30183.6681@psf.io> https://hg.python.org/cpython/rev/361d7af9396e changeset: 96949:361d7af9396e branch: 3.5 parent: 96947:66a5f66b4049 user: Serhiy Storchaka date: Sat Jul 18 23:27:00 2015 +0300 summary: Issue #24580: Symbolic group references to open group in re patterns now are explicitly forbidden as well as numeric group references. files: Lib/sre_parse.py | 3 +++ Lib/test/test_re.py | 2 ++ Misc/NEWS | 3 +++ 3 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -675,6 +675,9 @@ if gid is None: msg = "unknown group name %r" % name raise source.error(msg, len(name) + 1) + if not state.checkgroup(gid): + raise source.error("cannot refer to an open group", + len(name) + 1) state.checklookbehindgroup(gid, source) subpatternappend((GROUPREF, gid)) continue 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 @@ -224,6 +224,8 @@ self.checkPatternError('(?P)(?P)', "redefinition of group name 'a' as group 2; " "was group 1") + self.checkPatternError('(?P(?P=a))', + "cannot refer to an open group", 10) self.checkPatternError('(?Pxy)', 'unknown extension ?Px') self.checkPatternError('(?P)(?P=a', 'missing ), unterminated name', 11) self.checkPatternError('(?P=', 'missing group name', 4) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #24580: Symbolic group references to open group in re patterns now are + explicitly forbidden as well as numeric group references. + - Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. - Issue #24631: Fixed regression in the timeit module with multiline setup. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 18 22:38:11 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 18 Jul 2015 20:38:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324580=3A_Symbolic_group_references_to_open_grou?= =?utf-8?q?p_in_re_patterns_now_are?= Message-ID: <20150718203811.130429.21519@psf.io> https://hg.python.org/cpython/rev/4d3557500019 changeset: 96950:4d3557500019 parent: 96948:adc9869c6d0d parent: 96949:361d7af9396e user: Serhiy Storchaka date: Sat Jul 18 23:37:31 2015 +0300 summary: Issue #24580: Symbolic group references to open group in re patterns now are explicitly forbidden as well as numeric group references. files: Lib/sre_parse.py | 3 +++ Lib/test/test_re.py | 2 ++ Misc/NEWS | 3 +++ 3 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -675,6 +675,9 @@ if gid is None: msg = "unknown group name %r" % name raise source.error(msg, len(name) + 1) + if not state.checkgroup(gid): + raise source.error("cannot refer to an open group", + len(name) + 1) state.checklookbehindgroup(gid, source) subpatternappend((GROUPREF, gid)) continue 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 @@ -224,6 +224,8 @@ self.checkPatternError('(?P)(?P)', "redefinition of group name 'a' as group 2; " "was group 1") + self.checkPatternError('(?P(?P=a))', + "cannot refer to an open group", 10) self.checkPatternError('(?Pxy)', 'unknown extension ?Px') self.checkPatternError('(?P)(?P=a', 'missing ), unterminated name', 11) self.checkPatternError('(?P=', 'missing group name', 4) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ Library ------- +- Issue #24580: Symbolic group references to open group in re patterns now are + explicitly forbidden as well as numeric group references. + - Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. - Issue #24631: Fixed regression in the timeit module with multiline setup. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 19 01:31:37 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 18 Jul 2015 23:31:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NTY4?= =?utf-8?q?=3A_fix_typo=2E?= Message-ID: <20150718233137.87946.64632@psf.io> https://hg.python.org/cpython/rev/669d6b5c1734 changeset: 96951:669d6b5c1734 branch: 2.7 parent: 96943:e4f9562d625d user: Raymond Hettinger date: Sat Jul 18 16:31:29 2015 -0700 summary: Issue #24568: fix typo. 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 @@ -171,7 +171,7 @@ - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. -- Issues #24099, #24100, and #24101: Fix use-after-use bug in heapq's siftup +- Issues #24099, #24100, and #24101: Fix use-after-free bug in heapq's siftup and siftdown functions. - Backport collections.deque fixes from Python 3.5. Prevents reentrant badness -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 19 06:48:34 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 19 Jul 2015 04:48:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixes_OpenSSL_?= =?utf-8?q?directory_reference?= Message-ID: <20150719044833.85831.28462@psf.io> https://hg.python.org/cpython/rev/3b35a5ce7590 changeset: 96952:3b35a5ce7590 branch: 2.7 user: Steve Dower date: Sat Jul 18 21:47:51 2015 -0700 summary: Fixes OpenSSL directory reference files: PCbuild/python.props | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -30,7 +30,7 @@ $(ExternalsDir)sqlite-3.6.21\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)db-4.7.25.0 - $(ExternalsDir)openssl-1.0.2a\ + $(ExternalsDir)openssl-1.0.2c\ $(ExternalsDir)\nasm-2.11.06\ -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Jul 19 10:50:49 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 19 Jul 2015 08:50:49 +0000 Subject: [Python-checkins] Daily reference leaks (4d3557500019): sum=4673118 Message-ID: <20150719085048.18734.32594@psf.io> results for 4d3557500019 on branch "default" -------------------------------------------- test_dict leaked [8, 8, 8] references, sum=24 test_dict leaked [2, 2, 2] memory blocks, sum=6 test_builtin leaked [6, 6, 6] references, sum=18 test_doctest leaked [49, 49, 49] references, sum=147 test_abc leaked [2, 2, 2] references, sum=6 test_argparse leaked [6891, 6891, 6891] references, sum=20673 test_argparse leaked [1499, 1501, 1501] memory blocks, sum=4501 test_ast leaked [465, 465, 465] references, sum=1395 test_ast leaked [7, 8, 8] memory blocks, sum=23 test_asyncio leaked [4189, 4139, 4189] references, sum=12517 test_asyncio leaked [18, 19, 19] memory blocks, sum=56 test_atexit leaked [242, 242, 242] references, sum=726 test_atexit leaked [6, 6, 6] memory blocks, sum=18 test_bigmem leaked [20586, 20586, 20586] references, sum=61758 test_bytes leaked [6504, 6504, 6504] references, sum=19512 test_bytes leaked [6504, 6506, 6506] memory blocks, sum=19516 test_capi leaked [123, 123, 123] references, sum=369 test_capi leaked [3, 3, 3] memory blocks, sum=9 test_cgi leaked [5, 5, 5] references, sum=15 test_cgi leaked [3, 3, 3] memory blocks, sum=9 test_cmd leaked [2, 2, 2] references, sum=6 test_cmd leaked [2, 2, 2] memory blocks, sum=6 test_codecs leaked [42, 42, 42] references, sum=126 test_codecs leaked [42, 42, 42] memory blocks, sum=126 test_collections leaked [352, 328, 351] references, sum=1031 test_collections leaked [98, 99, 99] memory blocks, sum=296 test_compile leaked [32, 32, 32] references, sum=96 test_concurrent_futures leaked [50, 50, 50] references, sum=150 test_concurrent_futures leaked [26, 26, 26] memory blocks, sum=78 test_configparser leaked [84, 84, 84] references, sum=252 test_configparser leaked [72, 72, 72] memory blocks, sum=216 test_decimal leaked [19, 19, 19] references, sum=57 test_decimal leaked [6, 6, 6] memory blocks, sum=18 test_dictviews leaked [24, 24, 24] references, sum=72 test_dictviews leaked [6, 6, 6] memory blocks, sum=18 test_distutils leaked [26, 26, 26] references, sum=78 test_distutils leaked [23, 23, 23] memory blocks, sum=69 test_email leaked [1183, 1183, 1183] references, sum=3549 test_enum leaked [1718, 1718, 1718] references, sum=5154 test_enumerate leaked [10004, 10004, 10004] references, sum=30012 test_enumerate leaked [10004, 10006, 10006] memory blocks, sum=30016 test_functools leaked [0, 2, 2] memory blocks, sum=4 test_generators leaked [1, 1, 1] references, sum=3 test_hash leaked [4645, 4645, 4645] references, sum=13935 test_hashlib leaked [444, 444, 444] references, sum=1332 test_hashlib leaked [222, 223, 223] memory blocks, sum=668 test_imp leaked [12, 12, 12] references, sum=36 test_importlib leaked [10, 10, 10] references, sum=30 test_importlib leaked [10, 10, 10] memory blocks, sum=30 test_inspect leaked [10, 10, 10] references, sum=30 test_ipaddress leaked [1962, 1962, 1962] references, sum=5886 test_ipaddress leaked [6, 7, 7] memory blocks, sum=20 test_itertools leaked [1274006, 1274006, 1274006] references, sum=3822018 test_itertools leaked [110, 111, 111] memory blocks, sum=332 test_lib2to3 leaked [81118, 81118, 81118] references, sum=243354 test_lib2to3 leaked [71752, 71754, 71754] memory blocks, sum=215260 test_listcomps leaked [3, 3, 3] references, sum=9 test_logging leaked [28, 28, 28] references, sum=84 test_macpath leaked [1, 1, 1] references, sum=3 test_mailbox leaked [2, 2, 2] references, sum=6 test_marshal leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] references, sum=30 test_module leaked [10, 10, 10] memory blocks, sum=30 test_multiprocessing_fork leaked [1, 1, 1] references, sum=3 test_multiprocessing_fork leaked [1, 2, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [1, 1, 1] references, sum=3 test_multiprocessing_forkserver leaked [1, 1, 2] memory blocks, sum=4 test_multiprocessing_spawn leaked [1, 1, 1] references, sum=3 test_ntpath leaked [153, 153, 153] references, sum=459 test_ntpath leaked [45, 45, 45] memory blocks, sum=135 test_numeric_tower leaked [1, 1, 1] references, sum=3 test_peepholer leaked [5, 5, 5] references, sum=15 test_pep277 leaked [206, 206, 206] references, sum=618 test_pep277 leaked [134, 134, 134] memory blocks, sum=402 test_pep352 leaked [2, 2, 2] references, sum=6 test_pep352 leaked [2, 2, 2] memory blocks, sum=6 test_pickle leaked [292, 292, 292] references, sum=876 test_posix leaked [1, 1, 1] references, sum=3 test_posixpath leaked [43, 43, 43] references, sum=129 test_pulldom leaked [4, 4, 4] references, sum=12 test_pydoc leaked [7, 7, 7] references, sum=21 test_pyexpat leaked [1, 1, 1] references, sum=3 test_random leaked [588, 588, 588] references, sum=1764 test_random leaked [392, 394, 394] memory blocks, sum=1180 test_regrtest leaked [1621, 1621, 1621] references, sum=4863 test_regrtest leaked [319, 321, 321] memory blocks, sum=961 test_scope leaked [2, 2, 2] references, sum=6 test_set leaked [26161, 23761, 25761] references, sum=75683 test_set leaked [785, 787, 787] memory blocks, sum=2359 test_setcomps leaked [36, 36, 36] references, sum=108 test_smtpd leaked [3167, 3167, 3167] references, sum=9501 test_smtplib leaked [20, 20, 20] references, sum=60 test_socket leaked [3, 3, 3] references, sum=9 test_socket leaked [3, 3, 3] memory blocks, sum=9 test_ssl leaked [26, 26, 26] references, sum=78 test_statistics leaked [781, 781, 781] references, sum=2343 test_string leaked [5, 5, 5] references, sum=15 test_strptime leaked [32, 32, 32] references, sum=96 test_sys leaked [5, 5, 5] references, sum=15 test_threading leaked [246, 246, 246] references, sum=738 test_threading leaked [6, 6, 6] memory blocks, sum=18 test_timeit leaked [3, 3, 3] references, sum=9 test_trace leaked [95, 95, 95] references, sum=285 test_trace leaked [2, 2, 2] memory blocks, sum=6 test_traceback leaked [252, 252, 252] references, sum=756 test_typechecks leaked [8, 8, 8] references, sum=24 test_unicode leaked [3264, 3264, 3264] references, sum=9792 test_unicode leaked [3252, 3254, 3254] memory blocks, sum=9760 test_unpack_ex leaked [1, 1, 1] references, sum=3 test_urllib2 leaked [1, 1, 1] references, sum=3 test_urllibnet leaked [1, 1, 1] references, sum=3 test_userstring leaked [3252, 3252, 3252] references, sum=9756 test_userstring leaked [3252, 3254, 3254] memory blocks, sum=9760 test_weakref leaked [1, 1, 1] references, sum=3 test_weakset leaked [53, 53, 53] references, sum=159 test_weakset leaked [53, 53, 53] memory blocks, sum=159 test_wsgiref leaked [6, 6, 6] references, sum=18 test_xml_etree leaked [3508, 3508, 3508] references, sum=10524 test_xml_etree leaked [1206, 1208, 1208] memory blocks, sum=3622 test_zipimport_support leaked [37, 37, 37] references, sum=111 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogKMO1tg', '--timeout', '7200'] From python-checkins at python.org Mon Jul 20 00:32:38 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 19 Jul 2015 22:32:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Njcx?= =?utf-8?q?=3A_Finish_print_conversion=2C_idlelib_GrepDialog_and_WidgetRed?= =?utf-8?q?irector=2E?= Message-ID: <20150719223238.23363.70283@psf.io> https://hg.python.org/cpython/rev/949ba97beece changeset: 96953:949ba97beece branch: 2.7 user: Terry Jan Reedy date: Sun Jul 19 18:32:06 2015 -0400 summary: Issue #24671: Finish print conversion, idlelib GrepDialog and WidgetRedirector. files: Lib/idlelib/GrepDialog.py | 1 + Lib/idlelib/WidgetRedirector.py | 3 ++- 2 files changed, 3 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 @@ -1,3 +1,4 @@ +from __future__ import print_function import os import fnmatch import re # for htest diff --git a/Lib/idlelib/WidgetRedirector.py b/Lib/idlelib/WidgetRedirector.py --- a/Lib/idlelib/WidgetRedirector.py +++ b/Lib/idlelib/WidgetRedirector.py @@ -1,3 +1,4 @@ +from __future__ import print_function from Tkinter import TclError class WidgetRedirector: @@ -161,7 +162,7 @@ text.focus_set() redir = WidgetRedirector(text) def my_insert(*args): - print "insert", args + print("insert", args) original_insert(*args) original_insert = redir.register("insert", my_insert) root.mainloop() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 06:25:57 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 04:25:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Divisions-by-two_for_a_pos?= =?utf-8?q?itive_Py=5Fssize=5Ft_compile_more_cleanly_with_=3E=3E1_than?= Message-ID: <20150720042557.130423.93369@psf.io> https://hg.python.org/cpython/rev/951552f602b2 changeset: 96954:951552f602b2 parent: 96950:4d3557500019 user: Raymond Hettinger date: Mon Jul 20 00:25:50 2015 -0400 summary: Divisions-by-two for a positive Py_ssize_t compile more cleanly with >>1 than /2. files: Modules/_collectionsmodule.c | 2 +- Modules/_heapqmodule.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -788,7 +788,7 @@ block *rightblock = deque->rightblock; Py_ssize_t leftindex = deque->leftindex; Py_ssize_t rightindex = deque->rightindex; - Py_ssize_t n = Py_SIZE(deque) / 2; + Py_ssize_t n = Py_SIZE(deque) >> 1; Py_ssize_t i; PyObject *tmp; diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -66,7 +66,7 @@ /* Bubble up the smaller child until hitting a leaf. */ arr = _PyList_ITEMS(heap); - limit = endpos / 2; /* smallest pos that has no child */ + limit = endpos >> 1; /* smallest pos that has no child */ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ @@ -347,7 +347,7 @@ n is odd = 2*j+1, this is (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. */ - for (i = n/2 - 1 ; i >= 0 ; i--) + for (i = (n >> 1) - 1 ; i >= 0 ; i--) if (siftup_func((PyListObject *)heap, i)) return NULL; Py_RETURN_NONE; @@ -420,7 +420,7 @@ /* Bubble up the smaller child until hitting a leaf. */ arr = _PyList_ITEMS(heap); - limit = endpos / 2; /* smallest pos that has no child */ + limit = endpos >> 1; /* smallest pos that has no child */ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 07:23:37 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 05:23:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324583=3A_Fix_refc?= =?utf-8?q?ount_leak=2E?= Message-ID: <20150720052337.30199.40131@psf.io> https://hg.python.org/cpython/rev/acb5b177dd4e changeset: 96955:acb5b177dd4e user: Raymond Hettinger date: Mon Jul 20 01:23:32 2015 -0400 summary: Issue #24583: Fix refcount leak. files: Objects/setobject.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -223,9 +223,13 @@ entry->hash = hash; if ((size_t)so->fill*3 < mask*2) return 0; - return set_table_resize(so, so->used); + if (!set_table_resize(so, so->used)) + return 0; + Py_INCREF(key); + return -1; found_active: + Py_DECREF(key); return 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 09:11:23 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 07:11:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE5NjYz?= =?utf-8?q?=3A_Improve_error_message_for_defaultdict=2E?= Message-ID: <20150720071123.18732.78174@psf.io> https://hg.python.org/cpython/rev/efda1eaf86a3 changeset: 96956:efda1eaf86a3 branch: 3.4 parent: 96946:5ec2bfbe8115 user: Raymond Hettinger date: Mon Jul 20 03:09:22 2015 -0400 summary: Issue #19663: Improve error message for defaultdict. files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1682,7 +1682,7 @@ newdefault = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(newdefault) && newdefault != Py_None) { PyErr_SetString(PyExc_TypeError, - "first argument must be callable"); + "first argument must be callable or None"); return -1; } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 09:11:45 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 07:11:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge?= Message-ID: <20150720071145.10084.7588@psf.io> https://hg.python.org/cpython/rev/1e0867706c99 changeset: 96957:1e0867706c99 branch: 3.5 parent: 96949:361d7af9396e parent: 96956:efda1eaf86a3 user: Raymond Hettinger date: Mon Jul 20 03:10:48 2015 -0400 summary: merge files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2023,7 +2023,7 @@ newdefault = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(newdefault) && newdefault != Py_None) { PyErr_SetString(PyExc_TypeError, - "first argument must be callable"); + "first argument must be callable or None"); return -1; } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 09:12:21 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 07:12:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150720071221.10084.26373@psf.io> https://hg.python.org/cpython/rev/eb689c088e18 changeset: 96958:eb689c088e18 parent: 96955:acb5b177dd4e parent: 96957:1e0867706c99 user: Raymond Hettinger date: Mon Jul 20 03:11:16 2015 -0400 summary: merge files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2023,7 +2023,7 @@ newdefault = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(newdefault) && newdefault != Py_None) { PyErr_SetString(PyExc_TypeError, - "first argument must be callable"); + "first argument must be callable or None"); return -1; } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 09:14:22 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 07:14:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5NjYz?= =?utf-8?q?=3A_Improve_error_message_for_defaultdict=2E?= Message-ID: <20150720071422.70547.30433@psf.io> https://hg.python.org/cpython/rev/d248702feab0 changeset: 96959:d248702feab0 branch: 2.7 parent: 96953:949ba97beece user: Raymond Hettinger date: Mon Jul 20 03:08:09 2015 -0400 summary: Issue #19663: Improve error message for defaultdict. files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1595,7 +1595,7 @@ newdefault = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(newdefault) && newdefault != Py_None) { PyErr_SetString(PyExc_TypeError, - "first argument must be callable"); + "first argument must be callable or None"); return -1; } } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Jul 20 10:43:16 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 20 Jul 2015 08:43:16 +0000 Subject: [Python-checkins] Daily reference leaks (acb5b177dd4e): sum=4 Message-ID: <20150720084315.85833.82069@psf.io> results for acb5b177dd4e on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogErEqbH', '--timeout', '7200'] From python-checkins at python.org Mon Jul 20 13:34:11 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 20 Jul 2015 11:34:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324583=3A__Consoli?= =?utf-8?q?date_previous_set_object_updates_into_a_single_function?= Message-ID: <20150720113411.10084.59468@psf.io> https://hg.python.org/cpython/rev/3f2c12c0abdb changeset: 96960:3f2c12c0abdb parent: 96958:eb689c088e18 user: Raymond Hettinger date: Mon Jul 20 07:34:05 2015 -0400 summary: Issue #24583: Consolidate previous set object updates into a single function with a single entry point, named exit points at the bottom, more self-evident refcount adjustments, and a comment describing why the pre-increment was necessary at all. files: Objects/setobject.c | 39 ++++++++++++++++---------------- 1 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -127,17 +127,27 @@ static int set_table_resize(PySetObject *, Py_ssize_t); static int -_set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) +set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) { - setentry *table = so->table; + setentry *table; setentry *freeslot; setentry *entry; size_t perturb; - size_t mask = so->mask; - size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */ + size_t mask; + size_t i; /* Unsigned for defined overflow behavior */ size_t j; int cmp; + /* Pre-increment is necessary to prevent arbitrary code in the rich + comparison from deallocating the key just before the insertion. */ + Py_INCREF(key); + + restart: + + table = so->table; + mask = so->mask; + i = (size_t)hash & mask; + entry = &table[i]; if (entry->key == NULL) goto found_unused; @@ -160,9 +170,9 @@ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); if (cmp < 0) /* unlikely */ - return -1; + goto comparison_error; if (table != so->table || entry->key != startkey) /* unlikely */ - return _set_add_entry(so, key, hash); + goto restart; if (cmp > 0) /* likely */ goto found_active; mask = so->mask; /* help avoid a register spill */ @@ -188,9 +198,9 @@ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); if (cmp < 0) - return -1; + goto comparison_error; if (table != so->table || entry->key != startkey) - return _set_add_entry(so, key, hash); + goto restart; if (cmp > 0) goto found_active; mask = so->mask; @@ -223,22 +233,13 @@ entry->hash = hash; if ((size_t)so->fill*3 < mask*2) return 0; - if (!set_table_resize(so, so->used)) - return 0; - Py_INCREF(key); - return -1; + return set_table_resize(so, so->used); found_active: Py_DECREF(key); return 0; -} -static int -set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) -{ - Py_INCREF(key); - if (!_set_add_entry(so, key, hash)) - return 0; + comparison_error: Py_DECREF(key); return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 17:13:44 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 20 Jul 2015 15:13:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150720151344.18736.67402@psf.io> https://hg.python.org/cpython/rev/350e18d4ce84 changeset: 96963:350e18d4ce84 parent: 96960:3f2c12c0abdb parent: 96962:0bb44313842a user: Victor Stinner date: Mon Jul 20 17:13:28 2015 +0200 summary: Merge 3.5 files: Lib/test/test_os.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -429,12 +429,18 @@ with open(self.fname, 'wb') as fp: fp.write(b"ABC") + def restore_float_times(state): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + + os.stat_float_times(state) + # ensure that st_atime and st_mtime are float with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - old_state = os.stat_float_times(-1) - self.addCleanup(os.stat_float_times, old_state) + old_float_times = os.stat_float_times(-1) + self.addCleanup(restore_float_times, old_float_times) os.stat_float_times(True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 17:13:44 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 20 Jul 2015 15:13:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150720151344.14728.35805@psf.io> https://hg.python.org/cpython/rev/0bb44313842a changeset: 96962:0bb44313842a branch: 3.5 parent: 96957:1e0867706c99 parent: 96961:bc67e0030d42 user: Victor Stinner date: Mon Jul 20 17:13:16 2015 +0200 summary: Merge 3.4 files: Lib/test/test_os.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -430,12 +430,18 @@ with open(self.fname, 'wb') as fp: fp.write(b"ABC") + def restore_float_times(state): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + + os.stat_float_times(state) + # ensure that st_atime and st_mtime are float with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - old_state = os.stat_float_times(-1) - self.addCleanup(os.stat_float_times, old_state) + old_float_times = os.stat_float_times(-1) + self.addCleanup(restore_float_times, old_float_times) os.stat_float_times(True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 17:13:47 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 20 Jul 2015 15:13:47 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Njc1?= =?utf-8?q?=3A_Avoid_DeprecationWarning_in_test=5Fos?= Message-ID: <20150720151344.85843.94159@psf.io> https://hg.python.org/cpython/rev/bc67e0030d42 changeset: 96961:bc67e0030d42 branch: 3.4 parent: 96956:efda1eaf86a3 user: Victor Stinner date: Mon Jul 20 17:12:57 2015 +0200 summary: Issue #24675: Avoid DeprecationWarning in test_os Patch written by Martin Panter. I replace tearDown() with addCleanup(). files: Lib/test/test_os.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -361,12 +361,18 @@ with open(self.fname, 'wb') as fp: fp.write(b"ABC") + def restore_float_times(state): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + + os.stat_float_times(state) + # ensure that st_atime and st_mtime are float with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - old_state = os.stat_float_times(-1) - self.addCleanup(os.stat_float_times, old_state) + old_float_times = os.stat_float_times(-1) + self.addCleanup(restore_float_times, old_float_times) os.stat_float_times(True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 21:59:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Jul 2015 19:59:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNTcz?= =?utf-8?q?=3A_Restored_optimization_of_bytes=2Erfind=28=29_and_bytearray?= =?utf-8?b?LnJmaW5kKCk=?= Message-ID: <20150720195909.33223.7512@psf.io> https://hg.python.org/cpython/rev/311a4d28631b changeset: 96964:311a4d28631b branch: 3.5 parent: 96962:0bb44313842a user: Serhiy Storchaka date: Mon Jul 20 22:58:02 2015 +0300 summary: Issue #23573: Restored optimization of bytes.rfind() and bytearray.rfind() for single-byte argument on Linux. files: Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 10 +++++++--- Objects/bytesobject.c | 10 +++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23573: Restored optimization of bytes.rfind() and bytearray.rfind() + for single-byte argument on Linux. + - Issue #24569: Make PEP 448 dictionary evaluation more consistent. - Issue #24583: Fix crash when set is mutated while being updated. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1171,12 +1171,16 @@ ADJUST_INDICES(start, end, len); if (end - start < sub_len) res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { + else if (sub_len == 1 +#ifndef HAVE_MEMRCHR + && dir > 0 +#endif + ) { unsigned char needle = *sub; + int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyByteArray_AS_STRING(self) + start, end - start, - needle, needle, FAST_SEARCH); + needle, needle, mode); if (res >= 0) res += start; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1815,12 +1815,16 @@ ADJUST_INDICES(start, end, len); if (end - start < sub_len) res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { + else if (sub_len == 1 +#ifndef HAVE_MEMRCHR + && dir > 0 +#endif + ) { unsigned char needle = *sub; + int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyBytes_AS_STRING(self) + start, end - start, - needle, needle, FAST_SEARCH); + needle, needle, mode); if (res >= 0) res += start; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 21:59:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Jul 2015 19:59:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323573=3A_Restored_optimization_of_bytes=2Erfind?= =?utf-8?b?KCkgYW5kIGJ5dGVhcnJheS5yZmluZCgp?= Message-ID: <20150720195909.33233.78813@psf.io> https://hg.python.org/cpython/rev/c06410c68217 changeset: 96965:c06410c68217 parent: 96963:350e18d4ce84 parent: 96964:311a4d28631b user: Serhiy Storchaka date: Mon Jul 20 22:58:29 2015 +0300 summary: Issue #23573: Restored optimization of bytes.rfind() and bytearray.rfind() for single-byte argument on Linux. files: Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 10 +++++++--- Objects/bytesobject.c | 10 +++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Core and Builtins ----------------- +- Issue #23573: Restored optimization of bytes.rfind() and bytearray.rfind() + for single-byte argument on Linux. + - Issue #24569: Make PEP 448 dictionary evaluation more consistent. - Issue #24583: Fix crash when set is mutated while being updated. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1171,12 +1171,16 @@ ADJUST_INDICES(start, end, len); if (end - start < sub_len) res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { + else if (sub_len == 1 +#ifndef HAVE_MEMRCHR + && dir > 0 +#endif + ) { unsigned char needle = *sub; + int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyByteArray_AS_STRING(self) + start, end - start, - needle, needle, FAST_SEARCH); + needle, needle, mode); if (res >= 0) res += start; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1815,12 +1815,16 @@ ADJUST_INDICES(start, end, len); if (end - start < sub_len) res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { + else if (sub_len == 1 +#ifndef HAVE_MEMRCHR + && dir > 0 +#endif + ) { unsigned char needle = *sub; + int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyBytes_AS_STRING(self) + start, end - start, - needle, needle, FAST_SEARCH); + needle, needle, mode); if (res >= 0) res += start; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 23:46:15 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 20 Jul 2015 21:46:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNzky?= =?utf-8?q?=3A_Expand_idle=5Ftest=2Etest=5Fpathbowser=2E_Tweak_file=2E?= Message-ID: <20150720214615.18742.40359@psf.io> https://hg.python.org/cpython/rev/61d7e6fe0003 changeset: 96966:61d7e6fe0003 branch: 2.7 parent: 96959:d248702feab0 user: Terry Jan Reedy date: Mon Jul 20 17:44:55 2015 -0400 summary: Issue #20792: Expand idle_test.test_pathbowser. Tweak file. Original patch by Saimadhav Heblikar. files: Lib/idlelib/PathBrowser.py | 5 +- Lib/idlelib/idle_test/test_pathbrowser.py | 18 ++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/PathBrowser.py b/Lib/idlelib/PathBrowser.py --- a/Lib/idlelib/PathBrowser.py +++ b/Lib/idlelib/PathBrowser.py @@ -17,6 +17,7 @@ self.init(flist) def settitle(self): + "Set window titles." self.top.wm_title("Path Browser") self.top.wm_iconname("Path Browser") @@ -70,7 +71,7 @@ def ispackagedir(self, file): if not os.path.isdir(file): - return 0 + return False init = os.path.join(file, "__init__.py") return os.path.exists(init) @@ -91,7 +92,7 @@ sorted.sort() return sorted -def _path_browser(parent): +def _path_browser(parent): # htest # flist = PyShellFileList(parent) PathBrowser(flist, _htest=True) parent.mainloop() diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py --- a/Lib/idlelib/idle_test/test_pathbrowser.py +++ b/Lib/idlelib/idle_test/test_pathbrowser.py @@ -1,5 +1,8 @@ import unittest -import idlelib.PathBrowser as PathBrowser +import os +import sys +import idlelib +from idlelib import PathBrowser class PathBrowserTest(unittest.TestCase): @@ -7,6 +10,19 @@ # Issue16226 - make sure that getting a sublist works d = PathBrowser.DirBrowserTreeItem('') d.GetSubList() + self.assertEqual('', d.GetText()) + + dir = os.path.split(os.path.abspath(idlelib.__file__))[0] + self.assertEqual(d.ispackagedir(dir), True) + self.assertEqual(d.ispackagedir(dir + '/Icons'), False) + + def test_PathBrowserTreeItem(self): + p = PathBrowser.PathBrowserTreeItem() + self.assertEqual(p.GetText(), 'sys.path') + sub = p.GetSubList() + self.assertEqual(len(sub), len(sys.path)) + # Following fails in 2.7 because old-style class + #self.assertEqual(type(sub[0]), PathBrowser.DirBrowserTreeItem) if __name__ == '__main__': unittest.main(verbosity=2, exit=False) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 23:46:15 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 20 Jul 2015 21:46:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150720214615.18720.33437@psf.io> https://hg.python.org/cpython/rev/28efabbc1d82 changeset: 96968:28efabbc1d82 branch: 3.5 parent: 96964:311a4d28631b parent: 96967:0220328f962c user: Terry Jan Reedy date: Mon Jul 20 17:45:22 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/PathBrowser.py | 10 +++-- Lib/idlelib/idle_test/test_pathbrowser.py | 17 ++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/PathBrowser.py b/Lib/idlelib/PathBrowser.py --- a/Lib/idlelib/PathBrowser.py +++ b/Lib/idlelib/PathBrowser.py @@ -17,6 +17,7 @@ self.init(flist) def settitle(self): + "Set window titles." self.top.wm_title("Path Browser") self.top.wm_iconname("Path Browser") @@ -69,16 +70,17 @@ return sublist def ispackagedir(self, file): + " Return true for directories that are packages." if not os.path.isdir(file): - return 0 + return False init = os.path.join(file, "__init__.py") return os.path.exists(init) def listmodules(self, allnames): modules = {} suffixes = importlib.machinery.EXTENSION_SUFFIXES[:] - suffixes += importlib.machinery.SOURCE_SUFFIXES[:] - suffixes += importlib.machinery.BYTECODE_SUFFIXES[:] + suffixes += importlib.machinery.SOURCE_SUFFIXES + suffixes += importlib.machinery.BYTECODE_SUFFIXES sorted = [] for suff in suffixes: i = -len(suff) @@ -93,7 +95,7 @@ sorted.sort() return sorted -def _path_browser(parent): +def _path_browser(parent): # htest # flist = PyShellFileList(parent) PathBrowser(flist, _htest=True) parent.mainloop() diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py --- a/Lib/idlelib/idle_test/test_pathbrowser.py +++ b/Lib/idlelib/idle_test/test_pathbrowser.py @@ -1,5 +1,8 @@ import unittest -import idlelib.PathBrowser as PathBrowser +import os +import sys +import idlelib +from idlelib import PathBrowser class PathBrowserTest(unittest.TestCase): @@ -7,6 +10,18 @@ # Issue16226 - make sure that getting a sublist works d = PathBrowser.DirBrowserTreeItem('') d.GetSubList() + self.assertEqual('', d.GetText()) + + dir = os.path.split(os.path.abspath(idlelib.__file__))[0] + self.assertEqual(d.ispackagedir(dir), True) + self.assertEqual(d.ispackagedir(dir + '/Icons'), False) + + def test_PathBrowserTreeItem(self): + p = PathBrowser.PathBrowserTreeItem() + self.assertEqual(p.GetText(), 'sys.path') + sub = p.GetSubList() + self.assertEqual(len(sub), len(sys.path)) + self.assertEqual(type(sub[0]), PathBrowser.DirBrowserTreeItem) if __name__ == '__main__': unittest.main(verbosity=2, exit=False) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 23:46:15 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 20 Jul 2015 21:46:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIwNzky?= =?utf-8?q?=3A_Expand_idle=5Ftest=2Etest=5Fpathbowser=2E_Tweak_file_to_not?= =?utf-8?q?_copy_twice=2E?= Message-ID: <20150720214615.30183.72479@psf.io> https://hg.python.org/cpython/rev/0220328f962c changeset: 96967:0220328f962c branch: 3.4 parent: 96961:bc67e0030d42 user: Terry Jan Reedy date: Mon Jul 20 17:44:59 2015 -0400 summary: Issue #20792: Expand idle_test.test_pathbowser. Tweak file to not copy twice. Original patch by Saimadhav Heblikar. files: Lib/idlelib/PathBrowser.py | 10 +++-- Lib/idlelib/idle_test/test_pathbrowser.py | 17 ++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/PathBrowser.py b/Lib/idlelib/PathBrowser.py --- a/Lib/idlelib/PathBrowser.py +++ b/Lib/idlelib/PathBrowser.py @@ -17,6 +17,7 @@ self.init(flist) def settitle(self): + "Set window titles." self.top.wm_title("Path Browser") self.top.wm_iconname("Path Browser") @@ -69,16 +70,17 @@ return sublist def ispackagedir(self, file): + " Return true for directories that are packages." if not os.path.isdir(file): - return 0 + return False init = os.path.join(file, "__init__.py") return os.path.exists(init) def listmodules(self, allnames): modules = {} suffixes = importlib.machinery.EXTENSION_SUFFIXES[:] - suffixes += importlib.machinery.SOURCE_SUFFIXES[:] - suffixes += importlib.machinery.BYTECODE_SUFFIXES[:] + suffixes += importlib.machinery.SOURCE_SUFFIXES + suffixes += importlib.machinery.BYTECODE_SUFFIXES sorted = [] for suff in suffixes: i = -len(suff) @@ -93,7 +95,7 @@ sorted.sort() return sorted -def _path_browser(parent): +def _path_browser(parent): # htest # flist = PyShellFileList(parent) PathBrowser(flist, _htest=True) parent.mainloop() diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py --- a/Lib/idlelib/idle_test/test_pathbrowser.py +++ b/Lib/idlelib/idle_test/test_pathbrowser.py @@ -1,5 +1,8 @@ import unittest -import idlelib.PathBrowser as PathBrowser +import os +import sys +import idlelib +from idlelib import PathBrowser class PathBrowserTest(unittest.TestCase): @@ -7,6 +10,18 @@ # Issue16226 - make sure that getting a sublist works d = PathBrowser.DirBrowserTreeItem('') d.GetSubList() + self.assertEqual('', d.GetText()) + + dir = os.path.split(os.path.abspath(idlelib.__file__))[0] + self.assertEqual(d.ispackagedir(dir), True) + self.assertEqual(d.ispackagedir(dir + '/Icons'), False) + + def test_PathBrowserTreeItem(self): + p = PathBrowser.PathBrowserTreeItem() + self.assertEqual(p.GetText(), 'sys.path') + sub = p.GetSubList() + self.assertEqual(len(sub), len(sys.path)) + self.assertEqual(type(sub[0]), PathBrowser.DirBrowserTreeItem) if __name__ == '__main__': unittest.main(verbosity=2, exit=False) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 20 23:46:15 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 20 Jul 2015 21:46:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150720214615.75698.91272@psf.io> https://hg.python.org/cpython/rev/f0496665e7b7 changeset: 96969:f0496665e7b7 parent: 96965:c06410c68217 parent: 96968:28efabbc1d82 user: Terry Jan Reedy date: Mon Jul 20 17:45:38 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/PathBrowser.py | 10 +++-- Lib/idlelib/idle_test/test_pathbrowser.py | 17 ++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/PathBrowser.py b/Lib/idlelib/PathBrowser.py --- a/Lib/idlelib/PathBrowser.py +++ b/Lib/idlelib/PathBrowser.py @@ -17,6 +17,7 @@ self.init(flist) def settitle(self): + "Set window titles." self.top.wm_title("Path Browser") self.top.wm_iconname("Path Browser") @@ -69,16 +70,17 @@ return sublist def ispackagedir(self, file): + " Return true for directories that are packages." if not os.path.isdir(file): - return 0 + return False init = os.path.join(file, "__init__.py") return os.path.exists(init) def listmodules(self, allnames): modules = {} suffixes = importlib.machinery.EXTENSION_SUFFIXES[:] - suffixes += importlib.machinery.SOURCE_SUFFIXES[:] - suffixes += importlib.machinery.BYTECODE_SUFFIXES[:] + suffixes += importlib.machinery.SOURCE_SUFFIXES + suffixes += importlib.machinery.BYTECODE_SUFFIXES sorted = [] for suff in suffixes: i = -len(suff) @@ -93,7 +95,7 @@ sorted.sort() return sorted -def _path_browser(parent): +def _path_browser(parent): # htest # flist = PyShellFileList(parent) PathBrowser(flist, _htest=True) parent.mainloop() diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py --- a/Lib/idlelib/idle_test/test_pathbrowser.py +++ b/Lib/idlelib/idle_test/test_pathbrowser.py @@ -1,5 +1,8 @@ import unittest -import idlelib.PathBrowser as PathBrowser +import os +import sys +import idlelib +from idlelib import PathBrowser class PathBrowserTest(unittest.TestCase): @@ -7,6 +10,18 @@ # Issue16226 - make sure that getting a sublist works d = PathBrowser.DirBrowserTreeItem('') d.GetSubList() + self.assertEqual('', d.GetText()) + + dir = os.path.split(os.path.abspath(idlelib.__file__))[0] + self.assertEqual(d.ispackagedir(dir), True) + self.assertEqual(d.ispackagedir(dir + '/Icons'), False) + + def test_PathBrowserTreeItem(self): + p = PathBrowser.PathBrowserTreeItem() + self.assertEqual(p.GetText(), 'sys.path') + sub = p.GetSubList() + self.assertEqual(len(sub), len(sys.path)) + self.assertEqual(type(sub[0]), PathBrowser.DirBrowserTreeItem) if __name__ == '__main__': unittest.main(verbosity=2, exit=False) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 04:53:45 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 21 Jul 2015 02:53:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Updates_get=5Fwix=2Epy_for_newer_version_of_WiX=2E?= Message-ID: <20150721025345.102490.15200@psf.io> https://hg.python.org/cpython/rev/2b56cc9dfd56 changeset: 96971:2b56cc9dfd56 parent: 96969:f0496665e7b7 parent: 96970:a4cbd997d261 user: Steve Dower date: Mon Jul 20 19:53:26 2015 -0700 summary: Updates get_wix.py for newer version of WiX. files: Tools/msi/get_wix.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/msi/get_wix.py b/Tools/msi/get_wix.py --- a/Tools/msi/get_wix.py +++ b/Tools/msi/get_wix.py @@ -13,7 +13,7 @@ from zipfile import ZipFile EXTERNALS_DIR = None -for p in Path(__file__).parents: +for p in (Path.cwd() / __file__).parents: if any(p.glob("PCBuild/*.vcxproj")): EXTERNALS_DIR = p / "externals" break @@ -22,7 +22,7 @@ print("Cannot find project root") sys.exit(1) -WIX_BINARIES_ZIP = 'http://wixtoolset.org/downloads/v3.10.0.1519/wix310-binaries.zip' +WIX_BINARIES_ZIP = 'http://wixtoolset.org/downloads/v3.10.0.1823/wix310-binaries.zip' TARGET_BIN_ZIP = EXTERNALS_DIR / "wix.zip" TARGET_BIN_DIR = EXTERNALS_DIR / "wix" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 04:53:45 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 21 Jul 2015 02:53:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogVXBkYXRlcyBnZXRf?= =?utf-8?q?wix=2Epy_for_newer_version_of_WiX=2E?= Message-ID: <20150721025345.29276.6698@psf.io> https://hg.python.org/cpython/rev/a4cbd997d261 changeset: 96970:a4cbd997d261 branch: 3.5 parent: 96968:28efabbc1d82 user: Steve Dower date: Mon Jul 20 19:52:15 2015 -0700 summary: Updates get_wix.py for newer version of WiX. files: Tools/msi/get_wix.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/msi/get_wix.py b/Tools/msi/get_wix.py --- a/Tools/msi/get_wix.py +++ b/Tools/msi/get_wix.py @@ -13,7 +13,7 @@ from zipfile import ZipFile EXTERNALS_DIR = None -for p in Path(__file__).parents: +for p in (Path.cwd() / __file__).parents: if any(p.glob("PCBuild/*.vcxproj")): EXTERNALS_DIR = p / "externals" break @@ -22,7 +22,7 @@ print("Cannot find project root") sys.exit(1) -WIX_BINARIES_ZIP = 'http://wixtoolset.org/downloads/v3.10.0.1519/wix310-binaries.zip' +WIX_BINARIES_ZIP = 'http://wixtoolset.org/downloads/v3.10.0.1823/wix310-binaries.zip' TARGET_BIN_ZIP = EXTERNALS_DIR / "wix.zip" TARGET_BIN_DIR = EXTERNALS_DIR / "wix" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 06:36:07 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 21 Jul 2015 04:36:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixes_argument_handling_in_build=2Ebat_and_HHC_search?= Message-ID: <20150721043607.102486.30759@psf.io> https://hg.python.org/cpython/rev/366ee0f84118 changeset: 96973:366ee0f84118 parent: 96971:2b56cc9dfd56 parent: 96972:75316f11b35c user: Steve Dower date: Mon Jul 20 21:35:38 2015 -0700 summary: Fixes argument handling in build.bat and HHC search files: Doc/make.bat | 17 +++++++---------- PCbuild/build.bat | 26 +++++++++++++------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -17,7 +17,13 @@ where /R ..\externals hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" if not exist "%HTMLHELP%" where /R "%ProgramFiles(x86)%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" if not exist "%HTMLHELP%" where /R "%ProgramFiles%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" -if not exist "%HTMLHELP%" echo Cannot find HHC on PATH or in externals & exit /B 1 +if not exist "%HTMLHELP%" ( + echo. + echo.The HTML Help Workshop was not found. Set the HTMLHELP variable + echo.to the path to hhc.exe or download and install it from + echo.http://msdn.microsoft.com/en-us/library/ms669985 + exit /B 1 +) :skiphhcsearch if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/extensions/patchlevel.py`) do set DISTVERSION=%%v @@ -85,15 +91,6 @@ cmd /C %SPHINXBUILD% %SPHINXOPTS% -b%1 -dbuild\doctrees . %BUILDDIR%\%* if "%1" EQU "htmlhelp" ( - if not exist "%HTMLHELP%" ( - echo. - echo.The HTML Help Workshop was not found. Set the HTMLHELP variable - echo.to the path to hhc.exe or download and install it from - echo.http://msdn.microsoft.com/en-us/library/ms669985 - rem Set errorlevel to 1 and exit - cmd /C exit /b 1 - goto end - ) cmd /C "%HTMLHELP%" build\htmlhelp\python%DISTVERSION:.=%.hhp rem hhc.exe seems to always exit with code 1, reset to 0 for less than 2 if not errorlevel 2 cmd /C exit /b 0 diff --git a/PCbuild/build.bat b/PCbuild/build.bat --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -25,24 +25,24 @@ set kill= :CheckOpts -if '%~1'=='-c' (set conf=%2) & shift & shift & goto CheckOpts -if '%~1'=='-p' (set platf=%2) & shift & shift & goto CheckOpts -if '%~1'=='-r' (set target=Rebuild) & shift & goto CheckOpts -if '%~1'=='-t' (set target=%2) & shift & shift & goto CheckOpts -if '%~1'=='-d' (set conf=Debug) & shift & goto CheckOpts -if '%~1'=='-e' call "%dir%get_externals.bat" & shift & goto CheckOpts -if '%~1'=='-m' (set parallel=/m) & shift & goto CheckOpts -if '%~1'=='-M' (set parallel=) & shift & goto CheckOpts -if '%~1'=='-v' (set verbose=/v:n) & shift & goto CheckOpts -if '%~1'=='-k' (set kill=true) & shift & goto CheckOpts -if '%~1'=='-V' shift & goto Version +if "%~1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts +if "%~1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts +if "%~1"=="-r" (set target=Rebuild) & shift & goto CheckOpts +if "%~1"=="-t" (set target=%2) & shift & shift & goto CheckOpts +if "%~1"=="-d" (set conf=Debug) & shift & goto CheckOpts +if "%~1"=="-e" call "%dir%get_externals.bat" & shift & goto CheckOpts +if "%~1"=="-m" (set parallel=/m) & shift & goto CheckOpts +if "%~1"=="-M" (set parallel=) & shift & goto CheckOpts +if "%~1"=="-v" (set verbose=/v:n) & shift & goto CheckOpts +if "%~1"=="-k" (set kill=true) & shift & goto CheckOpts +if "%~1"=="-V" shift & goto Version -if '%platf%'=='x64' (set vs_platf=x86_amd64) +if "%platf%"=="x64" (set vs_platf=x86_amd64) rem Setup the environment call "%dir%env.bat" %vs_platf% >nul -if '%kill%'=='true' ( +if "%kill%"=="true" ( msbuild /v:m /nologo /target:KillPython "%pcbuild%\pythoncore.vcxproj" /p:Configuration=%conf% /p:Platform=%platf% /p:KillPython=true ) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 06:36:07 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 21 Jul 2015 04:36:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixes_argument?= =?utf-8?q?_handling_in_build=2Ebat_and_HHC_search?= Message-ID: <20150721043606.29280.31571@psf.io> https://hg.python.org/cpython/rev/75316f11b35c changeset: 96972:75316f11b35c branch: 3.5 parent: 96970:a4cbd997d261 user: Steve Dower date: Mon Jul 20 21:34:45 2015 -0700 summary: Fixes argument handling in build.bat and HHC search files: Doc/make.bat | 17 +++++++---------- PCbuild/build.bat | 26 +++++++++++++------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -17,7 +17,13 @@ where /R ..\externals hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" if not exist "%HTMLHELP%" where /R "%ProgramFiles(x86)%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" if not exist "%HTMLHELP%" where /R "%ProgramFiles%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc" -if not exist "%HTMLHELP%" echo Cannot find HHC on PATH or in externals & exit /B 1 +if not exist "%HTMLHELP%" ( + echo. + echo.The HTML Help Workshop was not found. Set the HTMLHELP variable + echo.to the path to hhc.exe or download and install it from + echo.http://msdn.microsoft.com/en-us/library/ms669985 + exit /B 1 +) :skiphhcsearch if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/extensions/patchlevel.py`) do set DISTVERSION=%%v @@ -85,15 +91,6 @@ cmd /C %SPHINXBUILD% %SPHINXOPTS% -b%1 -dbuild\doctrees . %BUILDDIR%\%* if "%1" EQU "htmlhelp" ( - if not exist "%HTMLHELP%" ( - echo. - echo.The HTML Help Workshop was not found. Set the HTMLHELP variable - echo.to the path to hhc.exe or download and install it from - echo.http://msdn.microsoft.com/en-us/library/ms669985 - rem Set errorlevel to 1 and exit - cmd /C exit /b 1 - goto end - ) cmd /C "%HTMLHELP%" build\htmlhelp\python%DISTVERSION:.=%.hhp rem hhc.exe seems to always exit with code 1, reset to 0 for less than 2 if not errorlevel 2 cmd /C exit /b 0 diff --git a/PCbuild/build.bat b/PCbuild/build.bat --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -25,24 +25,24 @@ set kill= :CheckOpts -if '%~1'=='-c' (set conf=%2) & shift & shift & goto CheckOpts -if '%~1'=='-p' (set platf=%2) & shift & shift & goto CheckOpts -if '%~1'=='-r' (set target=Rebuild) & shift & goto CheckOpts -if '%~1'=='-t' (set target=%2) & shift & shift & goto CheckOpts -if '%~1'=='-d' (set conf=Debug) & shift & goto CheckOpts -if '%~1'=='-e' call "%dir%get_externals.bat" & shift & goto CheckOpts -if '%~1'=='-m' (set parallel=/m) & shift & goto CheckOpts -if '%~1'=='-M' (set parallel=) & shift & goto CheckOpts -if '%~1'=='-v' (set verbose=/v:n) & shift & goto CheckOpts -if '%~1'=='-k' (set kill=true) & shift & goto CheckOpts -if '%~1'=='-V' shift & goto Version +if "%~1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts +if "%~1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts +if "%~1"=="-r" (set target=Rebuild) & shift & goto CheckOpts +if "%~1"=="-t" (set target=%2) & shift & shift & goto CheckOpts +if "%~1"=="-d" (set conf=Debug) & shift & goto CheckOpts +if "%~1"=="-e" call "%dir%get_externals.bat" & shift & goto CheckOpts +if "%~1"=="-m" (set parallel=/m) & shift & goto CheckOpts +if "%~1"=="-M" (set parallel=) & shift & goto CheckOpts +if "%~1"=="-v" (set verbose=/v:n) & shift & goto CheckOpts +if "%~1"=="-k" (set kill=true) & shift & goto CheckOpts +if "%~1"=="-V" shift & goto Version -if '%platf%'=='x64' (set vs_platf=x86_amd64) +if "%platf%"=="x64" (set vs_platf=x86_amd64) rem Setup the environment call "%dir%env.bat" %vs_platf% >nul -if '%kill%'=='true' ( +if "%kill%"=="true" ( msbuild /v:m /nologo /target:KillPython "%pcbuild%\pythoncore.vcxproj" /p:Configuration=%conf% /p:Platform=%platf% /p:KillPython=true ) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 08:29:40 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 21 Jul 2015 06:29:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Use_setUpClass?= =?utf-8?q?_and_tearDownClass_correctly_in_test=5Fos=2E?= Message-ID: <20150721062940.102492.25420@psf.io> https://hg.python.org/cpython/rev/65959b843666 changeset: 96974:65959b843666 branch: 3.5 parent: 96972:75316f11b35c user: Berker Peksag date: Tue Jul 21 09:29:48 2015 +0300 summary: Use setUpClass and tearDownClass correctly in test_os. According to the documentation, they must be decorated as classmethods. files: Lib/test/test_os.py | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1080,7 +1080,8 @@ @unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown") class ChownFileTests(unittest.TestCase): - def setUpClass(): + @classmethod + def setUpClass(cls): os.mkdir(support.TESTFN) def test_chown_uid_gid_arguments_must_be_index(self): @@ -1125,7 +1126,8 @@ os.chown(support.TESTFN, uid_1, gid) os.chown(support.TESTFN, uid_2, gid) - def tearDownClass(): + @classmethod + def tearDownClass(cls): os.rmdir(support.TESTFN) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 08:29:40 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 21 Jul 2015 06:29:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Use_setUpClass_and_tearDownClass_correctly_in_test=5Fos?= =?utf-8?q?=2E?= Message-ID: <20150721062940.40581.90131@psf.io> https://hg.python.org/cpython/rev/0308327eb250 changeset: 96975:0308327eb250 parent: 96973:366ee0f84118 parent: 96974:65959b843666 user: Berker Peksag date: Tue Jul 21 09:30:09 2015 +0300 summary: Use setUpClass and tearDownClass correctly in test_os. According to the documentation, they must be decorated as classmethods. files: Lib/test/test_os.py | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1079,7 +1079,8 @@ @unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown") class ChownFileTests(unittest.TestCase): - def setUpClass(): + @classmethod + def setUpClass(cls): os.mkdir(support.TESTFN) def test_chown_uid_gid_arguments_must_be_index(self): @@ -1124,7 +1125,8 @@ os.chown(support.TESTFN, uid_1, gid) os.chown(support.TESTFN, uid_2, gid) - def tearDownClass(): + @classmethod + def tearDownClass(cls): os.rmdir(support.TESTFN) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 09:55:17 2015 From: python-checkins at python.org (ethan.furman) Date: Tue, 21 Jul 2015 07:55:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_issue6549=3A_minor_t?= =?utf-8?q?tk=2EStyle_fixes?= Message-ID: <20150721075517.23363.26340@psf.io> https://hg.python.org/cpython/rev/c3fa46d85857 changeset: 96976:c3fa46d85857 user: Ethan Furman date: Tue Jul 21 00:54:19 2015 -0700 summary: Close issue6549: minor ttk.Style fixes files: Lib/tkinter/ttk.py | 10 +++++++--- Misc/NEWS | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -381,7 +381,9 @@ a sequence identifying the value for that option.""" if query_opt is not None: kw[query_opt] = None - return _val_or_dict(self.tk, kw, self._name, "configure", style) + result = _val_or_dict(self.tk, kw, self._name, "configure", style) + if result or query_opt: + return result def map(self, style, query_opt=None, **kw): @@ -466,12 +468,14 @@ def element_names(self): """Returns the list of elements defined in the current theme.""" - return self.tk.splitlist(self.tk.call(self._name, "element", "names")) + return tuple(n.lstrip('-') for n in self.tk.splitlist( + self.tk.call(self._name, "element", "names"))) def element_options(self, elementname): """Return the list of elementname's options.""" - return self.tk.splitlist(self.tk.call(self._name, "element", "options", elementname)) + return tuple(o.lstrip('-') for o in self.tk.splitlist( + self.tk.call(self._name, "element", "options", elementname))) def theme_create(self, themename, parent=None, settings=None): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ - Issue #15014: SMTP.auth() and SMTP.login() now support RFC 4954's optional initial-response argument to the SMTP AUTH command. +- Issue #6549: Remove hyphen from ttk.Style().element options. Only return result + from ttk.Style().configure if a result was generated or a query submitted. + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue Jul 21 10:44:02 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 21 Jul 2015 08:44:02 +0000 Subject: [Python-checkins] Daily reference leaks (366ee0f84118): sum=7 Message-ID: <20150721084402.14726.39207@psf.io> results for 366ee0f84118 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogDLPXlT', '--timeout', '7200'] From python-checkins at python.org Tue Jul 21 18:04:55 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Jul 2015 16:04:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjY5?= =?utf-8?q?=3A_Fix_inspect=2Egetsource=28=29_for_=27async_def=27_functions?= =?utf-8?q?=2E?= Message-ID: <20150721160454.29278.90896@psf.io> https://hg.python.org/cpython/rev/f02c5bf59fbb changeset: 96977:f02c5bf59fbb branch: 3.5 parent: 96974:65959b843666 user: Yury Selivanov date: Tue Jul 21 19:01:52 2015 +0300 summary: Issue #24669: Fix inspect.getsource() for 'async def' functions. Patch by Kai Groner. files: Lib/inspect.py | 2 +- Lib/test/inspect_fodder.py | 3 +++ Lib/test/test_inspect.py | 2 ++ Misc/NEWS | 3 +++ 4 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -798,7 +798,7 @@ if not hasattr(object, 'co_firstlineno'): raise OSError('could not find function definition') lnum = object.co_firstlineno - 1 - pat = re.compile(r'^(\s*def\s)|(.*(? 0: if pat.match(lines[lnum]): break lnum = lnum - 1 diff --git a/Lib/test/inspect_fodder.py b/Lib/test/inspect_fodder.py --- a/Lib/test/inspect_fodder.py +++ b/Lib/test/inspect_fodder.py @@ -66,3 +66,6 @@ pass def contradiction(self): pass + +async def lobbest(grenade): + pass 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 @@ -336,6 +336,7 @@ def test_getfunctions(self): functions = inspect.getmembers(mod, inspect.isfunction) self.assertEqual(functions, [('eggs', mod.eggs), + ('lobbest', mod.lobbest), ('spam', mod.spam)]) @unittest.skipIf(sys.flags.optimize >= 2, @@ -393,6 +394,7 @@ def test_getsource(self): self.assertSourceEqual(git.abuse, 29, 39) self.assertSourceEqual(mod.StupidGit, 21, 50) + self.assertSourceEqual(mod.lobbest, 70, 71) def test_getsourcefile(self): self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ - Issue #15014: SMTP.auth() and SMTP.login() now support RFC 4954's optional initial-response argument to the SMTP AUTH command. +- Issue #24669: Fix inspect.getsource() for 'async def' functions. + Patch by Kai Groner. + What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 18:04:55 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Jul 2015 16:04:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2Njkp?= Message-ID: <20150721160454.14704.88863@psf.io> https://hg.python.org/cpython/rev/6629773fef63 changeset: 96978:6629773fef63 parent: 96976:c3fa46d85857 parent: 96977:f02c5bf59fbb user: Yury Selivanov date: Tue Jul 21 19:04:22 2015 +0300 summary: Merge 3.5 (Issue #24669) files: Lib/inspect.py | 2 +- Lib/test/inspect_fodder.py | 3 +++ Lib/test/test_inspect.py | 2 ++ Misc/NEWS | 2 ++ 4 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -798,7 +798,7 @@ if not hasattr(object, 'co_firstlineno'): raise OSError('could not find function definition') lnum = object.co_firstlineno - 1 - pat = re.compile(r'^(\s*def\s)|(.*(? 0: if pat.match(lines[lnum]): break lnum = lnum - 1 diff --git a/Lib/test/inspect_fodder.py b/Lib/test/inspect_fodder.py --- a/Lib/test/inspect_fodder.py +++ b/Lib/test/inspect_fodder.py @@ -66,3 +66,6 @@ pass def contradiction(self): pass + +async def lobbest(grenade): + pass 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 @@ -336,6 +336,7 @@ def test_getfunctions(self): functions = inspect.getmembers(mod, inspect.isfunction) self.assertEqual(functions, [('eggs', mod.eggs), + ('lobbest', mod.lobbest), ('spam', mod.spam)]) @unittest.skipIf(sys.flags.optimize >= 2, @@ -393,6 +394,7 @@ def test_getsource(self): self.assertSourceEqual(git.abuse, 29, 39) self.assertSourceEqual(mod.StupidGit, 21, 50) + self.assertSourceEqual(mod.lobbest, 70, 71) def test_getsourcefile(self): self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,8 @@ - Issue #6549: Remove hyphen from ttk.Style().element options. Only return result from ttk.Style().configure if a result was generated or a query submitted. +- Issue #24669: Fix inspect.getsource() for 'async def' functions. + Patch by Kai Groner. What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 21:41:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Jul 2015 19:41:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324678=3A_Fixed_raiseExceptions_typo_in_logging_?= =?utf-8?q?tests=2E?= Message-ID: <20150721194159.8488.99544@psf.io> https://hg.python.org/cpython/rev/83b45ea19d00 changeset: 96981:83b45ea19d00 parent: 96978:6629773fef63 parent: 96980:7a54e400155f user: Serhiy Storchaka date: Tue Jul 21 22:41:39 2015 +0300 summary: Issue #24678: Fixed raiseExceptions typo in logging tests. Patch by Jacek Ko?odziej. files: Lib/test/test_logging.py | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3779,18 +3779,12 @@ (exc.__class__, exc, exc.__traceback__)) def test_log_invalid_level_with_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = True - self.assertRaises(TypeError, self.logger.log, '10', 'test message') + with support.swap_attr(logging, 'raiseExceptions', True): + self.assertRaises(TypeError, self.logger.log, '10', 'test message') def test_log_invalid_level_no_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = False - self.logger.log('10', 'test message') # no exception happens + with support.swap_attr(logging, 'raiseExceptions', False): + self.logger.log('10', 'test message') # no exception happens def test_find_caller_with_stack_info(self): called = [] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 21:41:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Jul 2015 19:41:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Njc4?= =?utf-8?q?=3A_Fixed_raiseExceptions_typo_in_logging_tests=2E?= Message-ID: <20150721194159.3169.19364@psf.io> https://hg.python.org/cpython/rev/20e2b980bb87 changeset: 96979:20e2b980bb87 branch: 3.4 parent: 96967:0220328f962c user: Serhiy Storchaka date: Tue Jul 21 22:39:26 2015 +0300 summary: Issue #24678: Fixed raiseExceptions typo in logging tests. Patch by Jacek Ko?odziej. files: Lib/test/test_logging.py | 17 ++++++----------- 1 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -41,7 +41,8 @@ import tempfile from test.script_helper import assert_python_ok from test.support import (captured_stdout, run_with_locale, run_unittest, - patch, requires_zlib, TestHandler, Matcher, HOST) + patch, requires_zlib, TestHandler, Matcher, HOST, + swap_attr) import textwrap import time import unittest @@ -3748,18 +3749,12 @@ (exc.__class__, exc, exc.__traceback__)) def test_log_invalid_level_with_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = True - self.assertRaises(TypeError, self.logger.log, '10', 'test message') + with swap_attr(logging, 'raiseExceptions', True): + self.assertRaises(TypeError, self.logger.log, '10', 'test message') def test_log_invalid_level_no_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = False - self.logger.log('10', 'test message') # no exception happens + with swap_attr(logging, 'raiseExceptions', False): + self.logger.log('10', 'test message') # no exception happens def test_find_caller_with_stack_info(self): called = [] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 21 21:42:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Jul 2015 19:42:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324678=3A_Fixed_raiseExceptions_typo_in_logging_tests?= =?utf-8?q?=2E?= Message-ID: <20150721194159.47933.49459@psf.io> https://hg.python.org/cpython/rev/7a54e400155f changeset: 96980:7a54e400155f branch: 3.5 parent: 96977:f02c5bf59fbb parent: 96979:20e2b980bb87 user: Serhiy Storchaka date: Tue Jul 21 22:40:18 2015 +0300 summary: Issue #24678: Fixed raiseExceptions typo in logging tests. Patch by Jacek Ko?odziej. files: Lib/test/test_logging.py | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3779,18 +3779,12 @@ (exc.__class__, exc, exc.__traceback__)) def test_log_invalid_level_with_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = True - self.assertRaises(TypeError, self.logger.log, '10', 'test message') + with support.swap_attr(logging, 'raiseExceptions', True): + self.assertRaises(TypeError, self.logger.log, '10', 'test message') def test_log_invalid_level_no_raise(self): - old_raise = logging.raiseExceptions - self.addCleanup(setattr, logging, 'raiseExecptions', old_raise) - - logging.raiseExceptions = False - self.logger.log('10', 'test message') # no exception happens + with support.swap_attr(logging, 'raiseExceptions', False): + self.logger.log('10', 'test message') # no exception happens def test_find_caller_with_stack_info(self): called = [] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:35:04 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:35:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324680=3A_Merge_with_3=2E4?= Message-ID: <20150722033504.11652.44032@psf.io> https://hg.python.org/cpython/rev/d7229f26dbdb changeset: 96984:d7229f26dbdb branch: 3.5 parent: 96980:7a54e400155f parent: 96983:cf0011b6ebbd user: Zachary Ware date: Tue Jul 21 22:34:16 2015 -0500 summary: Issue #24680: Merge with 3.4 files: Doc/extending/building.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -87,7 +87,7 @@ distutils; this section explains building extension modules only. It is common to pre-compute arguments to :func:`setup`, to better structure the -driver script. In the example above, the\ ``ext_modules`` argument to +driver script. In the example above, the ``ext_modules`` argument to :func:`setup` is a list of extension modules, each of which is an instance of the :class:`~distutils.extension.Extension`. In the example, the instance defines an extension named ``demo`` which is build by compiling a single source -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:35:04 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:35:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324680=3A_Merge_with_3=2E5?= Message-ID: <20150722033504.62373.16977@psf.io> https://hg.python.org/cpython/rev/96910e822266 changeset: 96985:96910e822266 parent: 96981:83b45ea19d00 parent: 96984:d7229f26dbdb user: Zachary Ware date: Tue Jul 21 22:34:48 2015 -0500 summary: Closes #24680: Merge with 3.5 files: Doc/extending/building.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -87,7 +87,7 @@ distutils; this section explains building extension modules only. It is common to pre-compute arguments to :func:`setup`, to better structure the -driver script. In the example above, the\ ``ext_modules`` argument to +driver script. In the example above, the ``ext_modules`` argument to :func:`setup` is a list of extension modules, each of which is an instance of the :class:`~distutils.extension.Extension`. In the example, the instance defines an extension named ``demo`` which is build by compiling a single source -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:35:04 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:35:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Njgw?= =?utf-8?q?=3A_Remove_random_backslash=2E__Patch_by_cdz=2E?= Message-ID: <20150722033504.62371.20302@psf.io> https://hg.python.org/cpython/rev/cf0011b6ebbd changeset: 96983:cf0011b6ebbd branch: 3.4 parent: 96979:20e2b980bb87 user: Zachary Ware date: Tue Jul 21 22:33:16 2015 -0500 summary: Issue #24680: Remove random backslash. Patch by cdz. files: Doc/extending/building.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -56,7 +56,7 @@ distutils; this section explains building extension modules only. It is common to pre-compute arguments to :func:`setup`, to better structure the -driver script. In the example above, the\ ``ext_modules`` argument to +driver script. In the example above, the ``ext_modules`` argument to :func:`setup` is a list of extension modules, each of which is an instance of the :class:`~distutils.extension.Extension`. In the example, the instance defines an extension named ``demo`` which is build by compiling a single source -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:35:05 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:35:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Njgw?= =?utf-8?q?=3A_Remove_random_backslash=2E__Patch_by_cdz=2E?= Message-ID: <20150722033503.37556.157@psf.io> https://hg.python.org/cpython/rev/91b738cfdc2f changeset: 96982:91b738cfdc2f branch: 2.7 parent: 96966:61d7e6fe0003 user: Zachary Ware date: Tue Jul 21 22:33:16 2015 -0500 summary: Issue #24680: Remove random backslash. Patch by cdz. files: Doc/extending/building.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -56,7 +56,7 @@ distutils; this section explains building extension modules only. It is common to pre-compute arguments to :func:`setup`, to better structure the -driver script. In the example above, the\ ``ext_modules`` argument to +driver script. In the example above, the ``ext_modules`` argument to :func:`setup` is a list of extension modules, each of which is an instance of the :class:`~distutils.extension.Extension`. In the example, the instance defines an extension named ``demo`` which is build by compiling a single source -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:51:18 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:51:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogcnN0bGludDogZXhw?= =?utf-8?q?licitly_open_files_as_UTF8?= Message-ID: <20150722035118.24778.8297@psf.io> https://hg.python.org/cpython/rev/256e71b48fbd changeset: 96986:256e71b48fbd branch: 3.4 parent: 96983:cf0011b6ebbd user: Zachary Ware date: Tue Jul 21 22:50:29 2015 -0500 summary: rstlint: explicitly open files as UTF8 files: Doc/tools/rstlint.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/rstlint.py b/Doc/tools/rstlint.py --- a/Doc/tools/rstlint.py +++ b/Doc/tools/rstlint.py @@ -196,7 +196,7 @@ print('Checking %s...' % fn) try: - with open(fn, 'r') as f: + with open(fn, 'r', encoding='utf-8') as f: lines = list(f) except (IOError, OSError) as err: print('%s: cannot open: %s' % (fn, err)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:51:18 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:51:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150722035118.22223.19635@psf.io> https://hg.python.org/cpython/rev/c74a438c5698 changeset: 96987:c74a438c5698 branch: 3.5 parent: 96984:d7229f26dbdb parent: 96986:256e71b48fbd user: Zachary Ware date: Tue Jul 21 22:50:43 2015 -0500 summary: Merge with 3.4 files: Doc/tools/rstlint.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/rstlint.py b/Doc/tools/rstlint.py --- a/Doc/tools/rstlint.py +++ b/Doc/tools/rstlint.py @@ -196,7 +196,7 @@ print('Checking %s...' % fn) try: - with open(fn, 'r') as f: + with open(fn, 'r', encoding='utf-8') as f: lines = list(f) except (IOError, OSError) as err: print('%s: cannot open: %s' % (fn, err)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 05:51:18 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 03:51:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150722035118.13837.99896@psf.io> https://hg.python.org/cpython/rev/fc899dbe9da6 changeset: 96988:fc899dbe9da6 parent: 96985:96910e822266 parent: 96987:c74a438c5698 user: Zachary Ware date: Tue Jul 21 22:50:54 2015 -0500 summary: Merge with 3.5 files: Doc/tools/rstlint.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/rstlint.py b/Doc/tools/rstlint.py --- a/Doc/tools/rstlint.py +++ b/Doc/tools/rstlint.py @@ -196,7 +196,7 @@ print('Checking %s...' % fn) try: - with open(fn, 'r') as f: + with open(fn, 'r', encoding='utf-8') as f: lines = list(f) except (IOError, OSError) as err: print('%s: cannot open: %s' % (fn, err)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 06:29:01 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 04:29:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324603=3A_Update_the_Windows_build_to_use_OpenSSL_1=2E?= =?utf-8?q?0=2E2d?= Message-ID: <20150722042901.62389.82233@psf.io> https://hg.python.org/cpython/rev/2930e23d729f changeset: 96991:2930e23d729f branch: 3.5 parent: 96987:c74a438c5698 parent: 96990:f4cd9ac378d7 user: Zachary Ware date: Tue Jul 21 23:27:08 2015 -0500 summary: Issue #24603: Update the Windows build to use OpenSSL 1.0.2d files: Misc/NEWS | 5 +++++ PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,11 @@ - Issue #24669: Fix inspect.getsource() for 'async def' functions. Patch by Kai Groner. +Build +----- + +- Issue #24603: Update the Windows build to use OpenSSL 1.0.2d. + What's New in Python 3.5.0 beta 3? ================================== diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2c + openssl-1.0.2d tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2c\ + $(ExternalsDir)openssl-1.0.2d\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2c of the OpenSSL secure sockets + Python wrapper for version 1.0.2d of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 06:29:01 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 04:29:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NjAz?= =?utf-8?q?=3A_Update_the_Windows_build_to_use_OpenSSL_1=2E0=2E2d?= Message-ID: <20150722042901.11650.95912@psf.io> https://hg.python.org/cpython/rev/f4cd9ac378d7 changeset: 96990:f4cd9ac378d7 branch: 3.4 parent: 96986:256e71b48fbd user: Zachary Ware date: Tue Jul 21 23:20:47 2015 -0500 summary: Issue #24603: Update the Windows build to use OpenSSL 1.0.2d files: Misc/NEWS | 4 ++-- PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -359,8 +359,8 @@ - Issue #23445: pydebug builds now use "gcc -Og" where possible, to make the resulting executable faster. -- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL - 1.0.2c. +- Issue #24603: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2d. C API ----- diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2c + openssl-1.0.2d tcl-8.6.1.0 tk-8.6.1.0 tix-8.4.3.4 diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -20,7 +20,7 @@ $(externalsDir)\sqlite-3.8.3.1 $(externalsDir)\bzip2-1.0.6 $(externalsDir)\xz-5.0.5 - $(externalsDir)\openssl-1.0.2c + $(externalsDir)\openssl-1.0.2d $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,7 +171,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2c of the OpenSSL secure sockets + Python wrapper for version 1.0.2d of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 06:29:01 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 04:29:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NjAz?= =?utf-8?q?=3A_Update_Windows_build_to_use_OpenSSL_1=2E0=2E2d?= Message-ID: <20150722042901.24760.46977@psf.io> https://hg.python.org/cpython/rev/53c0c8914ad0 changeset: 96989:53c0c8914ad0 branch: 2.7 parent: 96982:91b738cfdc2f user: Zachary Ware date: Tue Jul 21 23:16:51 2015 -0500 summary: Issue #24603: Update Windows build to use OpenSSL 1.0.2d files: Misc/NEWS | 4 ++-- PC/VS9.0/pyproject.vsprops | 2 +- PC/VS9.0/readme.txt | 2 +- PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -107,8 +107,8 @@ backported files replace the old project files in PCbuild; the old files moved to PC/VS9.0 and remain supported. -- Issue #24432: Update Windows builds and OS X 10.5 installer to use OpenSSL - 1.0.2c. +- Issue #24603: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2d. IDLE ---- diff --git a/PC/VS9.0/pyproject.vsprops b/PC/VS9.0/pyproject.vsprops --- a/PC/VS9.0/pyproject.vsprops +++ b/PC/VS9.0/pyproject.vsprops @@ -82,7 +82,7 @@ /> $(ExternalsDir)sqlite-3.6.21\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)db-4.7.25.0 - $(ExternalsDir)openssl-1.0.2c\ + $(ExternalsDir)openssl-1.0.2d\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -146,7 +146,7 @@ Get the source code through - svn export http://svn.python.org/projects/external/openssl-1.0.2c + svn export http://svn.python.org/projects/external/openssl-1.0.2d ** NOTE: if you use the PCbuild\get_externals.bat approach for obtaining external sources then you don't need to manually get the source -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 06:29:01 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 22 Jul 2015 04:29:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324603=3A_Merge_with_3=2E5?= Message-ID: <20150722042901.3167.49818@psf.io> https://hg.python.org/cpython/rev/310613b993d4 changeset: 96992:310613b993d4 parent: 96988:fc899dbe9da6 parent: 96991:2930e23d729f user: Zachary Ware date: Tue Jul 21 23:28:28 2015 -0500 summary: Issue #24603: Merge with 3.5 files: Misc/NEWS | 5 +++++ PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -67,6 +67,11 @@ - Issue #24669: Fix inspect.getsource() for 'async def' functions. Patch by Kai Groner. +Build +----- + +- Issue #24603: Update the Windows build to use OpenSSL 1.0.2d. + What's New in Python 3.5.0 beta 3? ================================== diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2c + openssl-1.0.2d tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -34,7 +34,7 @@ $(ExternalsDir)sqlite-3.8.3.1\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2c\ + $(ExternalsDir)openssl-1.0.2d\ $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -197,7 +197,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2c of the OpenSSL secure sockets + Python wrapper for version 1.0.2d of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 08:17:23 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 22 Jul 2015 06:17:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogd2UgZG9uJ3QgY2Fy?= =?utf-8?q?e_about_python_1=2E5=2E2?= Message-ID: <20150722061722.13849.30406@psf.io> https://hg.python.org/cpython/rev/b2f4d8377bce changeset: 96993:b2f4d8377bce branch: 2.7 parent: 96989:53c0c8914ad0 user: Benjamin Peterson date: Tue Jul 21 23:17:16 2015 -0700 summary: we don't care about python 1.5.2 files: Doc/library/time.rst | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -47,8 +47,6 @@ years for all year input. When 2-digit years are accepted, they are converted according to the POSIX or X/Open standard: values 69-99 are mapped to 1969-1999, and values 0--68 are mapped to 2000--2068. Values 100--1899 are always illegal. - Note that this is new as of Python 1.5.2(a2); earlier versions, up to Python - 1.5.1 and 1.5.2a1, would add 1900 to year values below 1900. .. index:: single: UTC -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 09:14:26 2015 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 22 Jul 2015 07:14:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Source_layout_tweaks_and_mino?= =?utf-8?q?r_clarifications?= Message-ID: <20150722071425.62389.18024@psf.io> https://hg.python.org/peps/rev/f5f06f202b82 changeset: 5907:f5f06f202b82 user: Ronald Oussoren date: Wed Jul 22 09:14:17 2015 +0200 summary: Source layout tweaks and minor clarifications files: pep-0447.txt | 117 +++++++++++++++++++++++++++++---------- 1 files changed, 87 insertions(+), 30 deletions(-) diff --git a/pep-0447.txt b/pep-0447.txt --- a/pep-0447.txt +++ b/pep-0447.txt @@ -7,7 +7,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 12-Jun-2013 -Post-History: 2-Jul-2013, 15-Jul-2013, 29-Jul-2013 +Post-History: 2-Jul-2013, 15-Jul-2013, 29-Jul-2013, 22-Jul-2015 Abstract @@ -16,7 +16,8 @@ Currently ``object.__getattribute__`` and ``super.__getattribute__`` peek in the ``__dict__`` of classes on the MRO for a class when looking for an attribute. This PEP adds an optional ``__getdescriptor__`` method to -a metaclass that can be used to override this behavior. +a metaclass that replaces this behavior and gives more control over attribute +lookup, especially when using a `super`_ object. That is, the MRO walking loop in ``_PyType_Lookup`` and ``super.__getattribute__`` gets changed from:: @@ -39,6 +40,15 @@ return NotFound +The default implemention of ``__getdescriptor__`` looks in the class +dictionary:: + + class type: + def __getdescriptor__(cls, name): + try: + return cls.__dict__[name] + except KeyError: + raise AttributeError(name) from None Rationale ========= @@ -63,13 +73,23 @@ an example of which is `PyObjC`_. PyObjC creates a Python class for every class in the Objective-C runtime, and looks up methods in the Objective-C runtime when they are used. This works fine for normal access, but doesn't -work for access with ``super`` objects. Because of this PyObjC currently -includes a custom ``super`` that must be used with its classes. +work for access with `super`_ objects. Because of this PyObjC currently +includes a custom `super`_ that must be used with its classes, as well as +completely reimplementing `PyObject_GenericGetAttr`_ for normal attribute +access. -The API in this PEP makes it possible to remove the custom ``super`` and +The API in this PEP makes it possible to remove the custom `super`_ and simplifies the implementation because the custom lookup behavior can be added in a central location. +.. note:: + + `PyObjC`_ cannot precalculate the contents of the class ``__dict__`` + because Objective-C classes can grow new methods at runtime. Furthermore + Objective-C classes tend to contain a lot of methods while most Python + code will only use a small subset of them, this makes precalculating + unnecessarily expensive. + The superclass attribute lookup hook ==================================== @@ -88,12 +108,12 @@ Aside: Attribute resolution algorithm in Python ----------------------------------------------- -The attribute resolution proces as implemented by ``object.__getattribute__`` (or -PyObject_GenericGetAttr`` in CPython's implementation) is fairly straightforward, -but not entirely so without reading C code. +The attribute resolution proces as implemented by ``object.__getattribute__`` +(or PyObject_GenericGetAttr`` in CPython's implementation) is fairly +straightforward, but not entirely so without reading C code. -The current CPython implementation of object.__getattribute__ is basicly equivalent -to the following (pseudo-) Python code (excluding some house keeping and speed tricks):: +The current CPython implementation of object.__getattribute__ is basicly +equivalent to the following (pseudo-) Python code (excluding some house keeping and speed tricks):: def _PyType_Lookup(tp, name): @@ -179,8 +199,8 @@ This PEP should change the dict lookup at the lines starting at "# PEP 447" with -a method call to perform the actual lookup, making is possible to affect that lookup -both for normal attribute access and access through the `super proxy`_. +a method call to perform the actual lookup, making is possible to affect that +lookup both for normal attribute access and access through the `super proxy`_. Note that specific classes can already completely override the default behaviour by implementing their own ``__getattribute__`` slot (with or without @@ -232,18 +252,19 @@ obj = SillyObject() assert obj.m() == "fortytwo" -As mentioned earlier in this PEP a more realistic use case of this functionallity -is a ``__getdescriptor__`` method that dynamicly populates the class ``__dict__`` -based on attribute access, primarily when it is not possible to reliably keep the -class dict in sync with its source, for example because the source used to populate -``__dict__`` is dynamic as well and does not have triggers that can be used to detect -changes to that source. +As mentioned earlier in this PEP a more realistic use case of this +functionallity is a ``__getdescriptor__`` method that dynamicly populates the +class ``__dict__`` based on attribute access, primarily when it is not +possible to reliably keep the class dict in sync with its source, for example +because the source used to populate ``__dict__`` is dynamic as well and does +not have triggers that can be used to detect changes to that source. -An example of that are the class bridges in PyObjC: the class bridge is a Python -object (class) that represents an Objective-C class and conceptually has a Python -method for every Objective-C method in the Objective-C class. As with Python it is -possible to add new methods to an Objective-C class, or replace existing ones, and -there are no callbacks that can be used to detect this. +An example of that are the class bridges in PyObjC: the class bridge is a +Python object (class) that represents an Objective-C class and conceptually +has a Python method for every Objective-C method in the Objective-C class. +As with Python it is possible to add new methods to an Objective-C class, or +replace existing ones, and there are no callbacks that can be used to detect +this. In C code --------- @@ -290,16 +311,20 @@ with a metaclass that uses a custom ``__getdescriptor__`` method. This section lists those changes. +The items listed below are only affected by custom ``__getdescriptor__`` +methods, the default implementation for ``object`` won't cause problems +because that still only uses the class ``__dict__`` and won't cause visible +changes to the visible behaviour of the ``object.__getattribute__``. + * ``dir`` might not show all attributes - As with a custom ``__getattribute__`` method ``dir()`` might not see all + As with a custom ``__getattribute__`` method `dir()`_ might not see all (instance) attributes when using the ``__getdescriptor__()`` method to dynamicly resolve attributes. The solution for that is quite simple: classes using ``__getdescriptor__`` - should also implement ``__dir__`` if they want full support for the builtin - ``dir`` function. - + should also implement `__dir__()`_ if they want full support for the builtin + `dir()`_ function. * ``inspect.getattr_static`` might not show all attributes @@ -316,13 +341,26 @@ **TODO**: I haven't fully worked out what the impact of this is, and if there are mitigations for those using either updates to these functions, or - additional methods that users should implement to be fully compatible with these - functions. + additional methods that users should implement to be fully compatible with + these functions. + + One possible mitigation is to have a custom ``__getattribute__`` for these + classes that fills ``__dict__`` before returning and and defers to the + default implementation for other attributes. + +* Direct introspection of the class ``__dict__`` + + Any code that directly access the class ``__dict__`` for introspection + can be affected by a custom ``__getdescriptor__`` method. Performance impact ------------------ +**WARNING**: The benchmark results in this section are old, and will be updated +when I've ported the patch to the current trunk. I don't expect significant +changes to the results in this section. + The pybench output below compares an implementation of this PEP with the regular source tree, both based on changeset a5681f50bae2, run on an idle machine an Core i7 processor running Centos 6.4. @@ -567,11 +605,22 @@ This would mean that using ``tp_getattro`` instead of peeking the class dictionaries changes the semantics of the `super class`_. +Alternate placement of the new method +..................................... + +This PEP proposes to add ``__getdescriptor__`` as a method on the metaclass. +An alternative would be to add it as a class method on the class itself +(simular to how ``__new__`` is a `staticmethod`_ of the class and not a method +of the metaclass). + +The two are functionally equivalent, and there's something to be said about +not requiring the use of a meta class. + References ========== -* `Issue 18181`_ contains a prototype implementation +* `Issue 18181`_ contains an out of date prototype implementation Copyright ========= @@ -584,6 +633,14 @@ .. _`super proxy`: http://docs.python.org/3/library/functions.html#super +.. _`super`: http://docs.python.org/3/library/functions.html#super + +.. _`dir()`: http://docs.python.org/3/library/functions.html#dir + +.. _`staticmethod`: http://docs.python.org/3/library/functions.html#staticmethod + +.. _`__dir__()`: https://docs.python.org/3/reference/datamodel.html#object.__dir__ + .. _`NotImplemented`: http://docs.python.org/3/library/constants.html#NotImplemented .. _`PyObject_GenericGetAttr`: http://docs.python.org/3/c-api/object.html#PyObject_GenericGetAttr -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Wed Jul 22 10:44:59 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 22 Jul 2015 08:44:59 +0000 Subject: [Python-checkins] Daily reference leaks (310613b993d4): sum=4 Message-ID: <20150722084459.3159.59750@psf.io> results for 310613b993d4 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogzp5IZn', '--timeout', '7200'] From python-checkins at python.org Wed Jul 22 12:38:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Jul 2015 10:38:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjE5?= =?utf-8?q?=3A_New_approach_for_tokenizing_async/await=2E?= Message-ID: <20150722103843.22231.39910@psf.io> https://hg.python.org/cpython/rev/9da080ecadb2 changeset: 96994:9da080ecadb2 branch: 3.5 parent: 96991:2930e23d729f user: Yury Selivanov date: Wed Jul 22 13:33:45 2015 +0300 summary: Issue #24619: New approach for tokenizing async/await. This commit fixes how one-line async-defs and defs are tracked by tokenizer. It allows to correctly parse invalid code such as: >>> async def f(): ... def g(): pass ... async = 10 and valid code such as: >>> async def f(): ... async def g(): pass ... await z As a consequence, is is now possible to have one-line 'async def foo(): await ..' functions: >>> async def foo(): return await bar() files: Doc/reference/compound_stmts.rst | 4 +- Lib/lib2to3/pgen2/tokenize.py | 12 +- Lib/test/badsyntax_async1.py | 5 +- Lib/test/badsyntax_async2.py | 5 +- Lib/test/badsyntax_async4.py | 2 +- Lib/test/badsyntax_async9.py | 2 - Lib/test/test_coroutines.py | 226 ++++++++++++++++++- Lib/test/test_grammar.py | 5 +- Lib/test/test_tokenize.py | 15 +- Lib/tokenize.py | 7 +- Misc/NEWS | 3 + Parser/tokenizer.c | 105 +++++-- Parser/tokenizer.h | 21 +- 13 files changed, 343 insertions(+), 69 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -685,9 +685,7 @@ (see :term:`coroutine`). In the body of a coroutine, any ``await`` and ``async`` identifiers become reserved keywords; :keyword:`await` expressions, :keyword:`async for` and :keyword:`async with` can only be used in -coroutine bodies. However, to simplify the parser, these keywords cannot -be used on the same line as a function or coroutine (:keyword:`def` -statement) header. +coroutine bodies. Functions defined with ``async def`` syntax are always coroutine functions, even if they do not contain ``await`` or ``async`` keywords. diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -369,6 +369,7 @@ # 'stashed' and 'ctx' are used for async/await parsing stashed = None ctx = [('sync', 0)] + in_async = 0 while 1: # loop over lines in stream try: @@ -436,6 +437,14 @@ "unindent does not match any outer indentation level", ("", lnum, pos, line)) indents = indents[:-1] + + cur_indent = indents[-1] + while len(ctx) > 1 and ctx[-1][1] >= cur_indent: + if ctx[-1][0] == 'async': + in_async -= 1 + assert in_async >= 0 + ctx.pop() + yield (DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement @@ -499,7 +508,7 @@ yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name if token in ('async', 'await'): - if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + if in_async: yield (ASYNC if token == 'async' else AWAIT, token, spos, epos, line) continue @@ -515,6 +524,7 @@ and stashed[1] == 'async'): ctx.append(('async', indents[-1])) + in_async += 1 yield (ASYNC, stashed[1], stashed[2], stashed[3], diff --git a/Lib/test/badsyntax_async1.py b/Lib/test/badsyntax_async1.py --- a/Lib/test/badsyntax_async1.py +++ b/Lib/test/badsyntax_async1.py @@ -1,3 +1,2 @@ -async def foo(): - def foo(a=await something()): - pass +async def foo(a=await something()): + pass diff --git a/Lib/test/badsyntax_async2.py b/Lib/test/badsyntax_async2.py --- a/Lib/test/badsyntax_async2.py +++ b/Lib/test/badsyntax_async2.py @@ -1,3 +1,2 @@ -async def foo(): - def foo(a:await something()): - pass +async def foo(a:await something()): + pass diff --git a/Lib/test/badsyntax_async4.py b/Lib/test/badsyntax_async4.py --- a/Lib/test/badsyntax_async4.py +++ b/Lib/test/badsyntax_async4.py @@ -1,2 +1,2 @@ async def foo(): - async def foo(): await something() + await diff --git a/Lib/test/badsyntax_async9.py b/Lib/test/badsyntax_async9.py deleted file mode 100644 --- a/Lib/test/badsyntax_async9.py +++ /dev/null @@ -1,2 +0,0 @@ -async def foo(): - await diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -67,11 +67,11 @@ class AsyncBadSyntaxTest(unittest.TestCase): def test_badsyntax_1(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + with self.assertRaisesRegex(SyntaxError, "'await' outside"): import test.badsyntax_async1 def test_badsyntax_2(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + with self.assertRaisesRegex(SyntaxError, "'await' outside"): import test.badsyntax_async2 def test_badsyntax_3(self): @@ -103,10 +103,6 @@ import test.badsyntax_async8 def test_badsyntax_9(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): - import test.badsyntax_async9 - - def test_badsyntax_10(self): ns = {} for comp in {'(await a for a in b)', '[await a for a in b]', @@ -116,6 +112,221 @@ with self.assertRaisesRegex(SyntaxError, 'await.*in comprehen'): exec('async def f():\n\t{}'.format(comp), ns, ns) + def test_badsyntax_10(self): + # Tests for issue 24619 + + samples = [ + """async def foo(): + def bar(): pass + await = 1 + """, + + """async def foo(): + + def bar(): pass + await = 1 + """, + + """async def foo(): + def bar(): pass + if 1: + await = 1 + """, + + """def foo(): + async def bar(): pass + if 1: + await a + """, + + """def foo(): + async def bar(): pass + await a + """, + + """def foo(): + def baz(): pass + async def bar(): pass + await a + """, + + """def foo(): + def baz(): pass + # 456 + async def bar(): pass + # 123 + await a + """, + + """async def foo(): + def baz(): pass + # 456 + async def bar(): pass + # 123 + await = 2 + """, + + """def foo(): + + def baz(): pass + + async def bar(): pass + + await a + """, + + """async def foo(): + + def baz(): pass + + async def bar(): pass + + await = 2 + """, + + """async def foo(): + def async(): pass + """, + + """async def foo(): + def await(): pass + """, + + """async def foo(): + def bar(): + await + """, + + """async def foo(): + return lambda async: await + """, + + """async def foo(): + return lambda a: await + """, + + """async def foo(a: await b): + pass + """, + + """def baz(): + async def foo(a: await b): + pass + """, + + """async def foo(async): + pass + """, + + """async def foo(): + def bar(): + def baz(): + async = 1 + """, + + """async def foo(): + def bar(): + def baz(): + pass + async = 1 + """, + + """def foo(): + async def bar(): + + async def baz(): + pass + + def baz(): + 42 + + async = 1 + """, + + """async def foo(): + def bar(): + def baz(): + pass\nawait foo() + """, + + """def foo(): + def bar(): + async def baz(): + pass\nawait foo() + """, + + """async def foo(await): + pass + """, + + """def foo(): + + async def bar(): pass + + await a + """, + + """def foo(): + async def bar(): + pass\nawait a + """] + + ns = {} + for code in samples: + with self.subTest(code=code), self.assertRaises(SyntaxError): + exec(code, ns, ns) + + def test_goodsyntax_1(self): + # Tests for issue 24619 + + def foo(await): + async def foo(): pass + async def foo(): + pass + return await + 1 + self.assertEqual(foo(10), 11) + + def foo(await): + async def foo(): pass + async def foo(): pass + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + + async def foo(): pass + + async def foo(): pass + + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + """spam""" + async def foo(): \ + pass + # 123 + async def foo(): pass + # 456 + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + def foo(): pass + def foo(): pass + async def bar(): return await_ + await_ = await + try: + bar().send(None) + except StopIteration as ex: + return ex.args[0] + self.assertEqual(foo(42), 42) + + async def f(): + async def g(): pass + await z + self.assertTrue(inspect.iscoroutinefunction(f)) + class TokenizerRegrTest(unittest.TestCase): @@ -461,8 +672,7 @@ class Awaitable: pass - async def foo(): - return (await Awaitable()) + async def foo(): return await Awaitable() with self.assertRaisesRegex( TypeError, "object Awaitable can't be used in 'await' expression"): 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 @@ -1051,10 +1051,7 @@ async def test(): def sum(): - async = 1 - await = 41 - return async + await - + pass if 1: await someobj() 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 @@ -786,12 +786,12 @@ NAME 'def' (2, 2) (2, 5) NAME 'foo' (2, 6) (2, 9) OP '(' (2, 9) (2, 10) - NAME 'await' (2, 10) (2, 15) + AWAIT 'await' (2, 10) (2, 15) OP ')' (2, 15) (2, 16) OP ':' (2, 16) (2, 17) NEWLINE '\\n' (2, 17) (2, 18) INDENT ' ' (3, 0) (3, 4) - NAME 'await' (3, 4) (3, 9) + AWAIT 'await' (3, 4) (3, 9) OP '=' (3, 10) (3, 11) NUMBER '1' (3, 12) (3, 13) NEWLINE '\\n' (3, 13) (3, 14) @@ -829,6 +829,17 @@ OP ':' (2, 18) (2, 19) NAME 'pass' (2, 20) (2, 24) DEDENT '' (3, 0) (3, 0) + + >>> dump_tokens('''async def foo(async): await''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'foo' (1, 10) (1, 13) + OP '(' (1, 13) (1, 14) + ASYNC 'async' (1, 14) (1, 19) + OP ')' (1, 19) (1, 20) + OP ':' (1, 20) (1, 21) + AWAIT 'await' (1, 22) (1, 27) """ from test import support diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -501,6 +501,7 @@ # 'stashed' and 'ctx' are used for async/await parsing stashed = None ctx = [('sync', 0)] + in_async = 0 if encoding is not None: if encoding == "utf-8-sig": @@ -580,6 +581,9 @@ cur_indent = indents[-1] while len(ctx) > 1 and ctx[-1][1] >= cur_indent: + if ctx[-1][0] == 'async': + in_async -= 1 + assert in_async >= 0 ctx.pop() yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) @@ -640,7 +644,7 @@ yield TokenInfo(STRING, token, spos, epos, line) elif initial.isidentifier(): # ordinary name if token in ('async', 'await'): - if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + if in_async: yield TokenInfo( ASYNC if token == 'async' else AWAIT, token, spos, epos, line) @@ -657,6 +661,7 @@ and stashed.string == 'async'): ctx.append(('async', indents[-1])) + in_async += 1 yield TokenInfo(ASYNC, stashed.string, stashed.start, stashed.end, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ - Issue #24407: Fix crash when dict is mutated while being updated. +- Issue #24619: New approach for tokenizing async/await. As a consequence, + is is now possible to have one-line 'async def foo(): await ..' functions. + Library ------- diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -31,6 +31,12 @@ || c == '_'\ || (c >= 128)) +/* The following DEFTYPE* flags are used in 'tok_state->deftypestack', + and should be removed in 3.7, when async/await are regular + keywords. */ +#define DEFTYPE_ASYNC 1 +#define DEFTYPE_HAS_NL 2 + extern char *PyOS_Readline(FILE *, FILE *, const char *); /* Return malloc'ed string including trailing \n; empty malloc'ed string for EOF; @@ -130,6 +136,8 @@ tok->def = 0; tok->defstack[0] = 0; tok->deftypestack[0] = 0; + tok->def_async_behind = 0; + tok->def_in_async = 0; tok->atbol = 1; tok->pendin = 0; @@ -1436,7 +1444,12 @@ tok->pendin++; while (tok->def && tok->defstack[tok->def] >= tok->indent) { + if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { + tok->def_in_async--; + assert(tok->def_in_async >= 0); + } tok->def--; + assert(tok->def >= 0); } return DEDENT; @@ -1447,6 +1460,22 @@ } } + if (!blankline && tok->level == 0 + && tok->def && tok->deftypestack[tok->def] & DEFTYPE_HAS_NL + && tok->defstack[tok->def] >= tok->indent) + { + /* The top function on the stack did have a NEWLINE + token, but didn't have an INDENT. That means that + it's a one-line function and it should now be removed + from the stack. */ + if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { + tok->def_in_async--; + assert(tok->def_in_async >= 0); + } + tok->def--; + assert(tok->def >= 0); + } + again: tok->start = NULL; /* Skip spaces */ @@ -1501,59 +1530,58 @@ tok_len = tok->cur - tok->start; if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { - if (tok->def && tok->deftypestack[tok->def] == 3) { - tok->deftypestack[tok->def] = 2; + /* The current token is 'def'. */ + if (tok->def + 1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return ERRORTOKEN; } - else if (tok->defstack[tok->def] < tok->indent) { - /* We advance defs stack only when we see "def" *and* - the indentation level was increased relative to the - previous "def". */ - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; - } + /* Advance defs stack. */ + tok->def++; + tok->defstack[tok->def] = tok->indent; - tok->def++; - tok->defstack[tok->def] = tok->indent; - tok->deftypestack[tok->def] = 1; + if (tok->def_async_behind) { + /* The previous token was 'async'. */ + tok->def_async_behind = 0; + tok->deftypestack[tok->def] = DEFTYPE_ASYNC; + tok->def_in_async++; + } + else { + /* This is a regular function (not async def). */ + tok->deftypestack[tok->def] = 0; } } else if (tok_len == 5) { if (memcmp(tok->start, "async", 5) == 0) { + /* The current token is 'async'. */ memcpy(&ahead_tok, tok, sizeof(ahead_tok)); + /* Try to look ahead one token. */ ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start, &ahead_top_end); - if (ahead_tok_kind == NAME && - ahead_tok.cur - ahead_tok.start == 3 && - memcmp(ahead_tok.start, "def", 3) == 0) { - - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; - } - - tok->def++; - tok->defstack[tok->def] = tok->indent; - tok->deftypestack[tok->def] = 3; - + if (ahead_tok_kind == NAME + && ahead_tok.cur - ahead_tok.start == 3 + && memcmp(ahead_tok.start, "def", 3) == 0) + { + /* The next token is going to be 'def', so instead of + returning 'async' NAME token, we return ASYNC. */ + tok->def_async_behind = 1; return ASYNC; } - else if (tok->def && tok->deftypestack[tok->def] == 2 - && tok->defstack[tok->def] < tok->indent) { - + else if (tok->def_in_async) + { + /* We're inside an 'async def' function, so we treat + 'async' token as ASYNC, instead of NAME. */ return ASYNC; } } - else if (memcmp(tok->start, "await", 5) == 0 - && tok->def && tok->deftypestack[tok->def] == 2 - && tok->defstack[tok->def] < tok->indent) { - + else if (memcmp(tok->start, "await", 5) == 0 && tok->def_in_async) + { + /* We're inside an 'async def' function, so we treat + 'await' token as AWAIT, instead of NAME. */ return AWAIT; } } @@ -1569,6 +1597,13 @@ *p_start = tok->start; *p_end = tok->cur - 1; /* Leave '\n' out of the string */ tok->cont_line = 0; + if (tok->def) { + /* Mark the top function on the stack that it had + at least one NEWLINE. That will help us to + distinguish one-line functions from functions + with multiple statements. */ + tok->deftypestack[tok->def] |= DEFTYPE_HAS_NL; + } return NEWLINE; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -66,12 +66,21 @@ const char* str; const char* input; /* Tokenizer's newline translated copy of the string. */ - int defstack[MAXINDENT]; /* stack if funcs & indents where they - were defined */ - int deftypestack[MAXINDENT]; /* stack of func types - (0 not func; 1: "def name"; - 2: "async def name") */ - int def; /* Length of stack of func types */ + /* `def*` fields are for parsing async/await in a backwards compatible + way. They should be removed in 3.7, when they will become + regular constants. See PEP 492 for more details. */ + int defstack[MAXINDENT]; /* Stack of funcs & indents where they + were defined. */ + int deftypestack[MAXINDENT]; /* Stack of func flags, see DEFTYPE_* + constants. */ + int def; /* Length of stack of func types/flags. */ + int def_async_behind; /* 1 if there was an 'async' token before + a 'def' token. */ + int def_in_async; /* Counter of how deep 'async def's + are nested. If greater than 0, + we are somewhere in an 'async def' + body, so 'async' and 'await' should + be parsed as keywords.*/ }; extern struct tok_state *PyTokenizer_FromString(const char *, int); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 12:38:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Jul 2015 10:38:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2MTkp?= Message-ID: <20150722103843.13839.34277@psf.io> https://hg.python.org/cpython/rev/987b72921a0c changeset: 96995:987b72921a0c parent: 96992:310613b993d4 parent: 96994:9da080ecadb2 user: Yury Selivanov date: Wed Jul 22 13:38:18 2015 +0300 summary: Merge 3.5 (Issue #24619) files: Doc/reference/compound_stmts.rst | 4 +- Lib/lib2to3/pgen2/tokenize.py | 12 +- Lib/test/badsyntax_async1.py | 5 +- Lib/test/badsyntax_async2.py | 5 +- Lib/test/badsyntax_async4.py | 2 +- Lib/test/badsyntax_async9.py | 2 - Lib/test/test_coroutines.py | 226 ++++++++++++++++++- Lib/test/test_grammar.py | 5 +- Lib/test/test_tokenize.py | 15 +- Lib/tokenize.py | 7 +- Misc/NEWS | 3 + Parser/tokenizer.c | 105 +++++-- Parser/tokenizer.h | 21 +- 13 files changed, 343 insertions(+), 69 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -685,9 +685,7 @@ (see :term:`coroutine`). In the body of a coroutine, any ``await`` and ``async`` identifiers become reserved keywords; :keyword:`await` expressions, :keyword:`async for` and :keyword:`async with` can only be used in -coroutine bodies. However, to simplify the parser, these keywords cannot -be used on the same line as a function or coroutine (:keyword:`def` -statement) header. +coroutine bodies. Functions defined with ``async def`` syntax are always coroutine functions, even if they do not contain ``await`` or ``async`` keywords. diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -369,6 +369,7 @@ # 'stashed' and 'ctx' are used for async/await parsing stashed = None ctx = [('sync', 0)] + in_async = 0 while 1: # loop over lines in stream try: @@ -436,6 +437,14 @@ "unindent does not match any outer indentation level", ("", lnum, pos, line)) indents = indents[:-1] + + cur_indent = indents[-1] + while len(ctx) > 1 and ctx[-1][1] >= cur_indent: + if ctx[-1][0] == 'async': + in_async -= 1 + assert in_async >= 0 + ctx.pop() + yield (DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement @@ -499,7 +508,7 @@ yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name if token in ('async', 'await'): - if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + if in_async: yield (ASYNC if token == 'async' else AWAIT, token, spos, epos, line) continue @@ -515,6 +524,7 @@ and stashed[1] == 'async'): ctx.append(('async', indents[-1])) + in_async += 1 yield (ASYNC, stashed[1], stashed[2], stashed[3], diff --git a/Lib/test/badsyntax_async1.py b/Lib/test/badsyntax_async1.py --- a/Lib/test/badsyntax_async1.py +++ b/Lib/test/badsyntax_async1.py @@ -1,3 +1,2 @@ -async def foo(): - def foo(a=await something()): - pass +async def foo(a=await something()): + pass diff --git a/Lib/test/badsyntax_async2.py b/Lib/test/badsyntax_async2.py --- a/Lib/test/badsyntax_async2.py +++ b/Lib/test/badsyntax_async2.py @@ -1,3 +1,2 @@ -async def foo(): - def foo(a:await something()): - pass +async def foo(a:await something()): + pass diff --git a/Lib/test/badsyntax_async4.py b/Lib/test/badsyntax_async4.py --- a/Lib/test/badsyntax_async4.py +++ b/Lib/test/badsyntax_async4.py @@ -1,2 +1,2 @@ async def foo(): - async def foo(): await something() + await diff --git a/Lib/test/badsyntax_async9.py b/Lib/test/badsyntax_async9.py deleted file mode 100644 --- a/Lib/test/badsyntax_async9.py +++ /dev/null @@ -1,2 +0,0 @@ -async def foo(): - await diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -67,11 +67,11 @@ class AsyncBadSyntaxTest(unittest.TestCase): def test_badsyntax_1(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + with self.assertRaisesRegex(SyntaxError, "'await' outside"): import test.badsyntax_async1 def test_badsyntax_2(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + with self.assertRaisesRegex(SyntaxError, "'await' outside"): import test.badsyntax_async2 def test_badsyntax_3(self): @@ -103,10 +103,6 @@ import test.badsyntax_async8 def test_badsyntax_9(self): - with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): - import test.badsyntax_async9 - - def test_badsyntax_10(self): ns = {} for comp in {'(await a for a in b)', '[await a for a in b]', @@ -116,6 +112,221 @@ with self.assertRaisesRegex(SyntaxError, 'await.*in comprehen'): exec('async def f():\n\t{}'.format(comp), ns, ns) + def test_badsyntax_10(self): + # Tests for issue 24619 + + samples = [ + """async def foo(): + def bar(): pass + await = 1 + """, + + """async def foo(): + + def bar(): pass + await = 1 + """, + + """async def foo(): + def bar(): pass + if 1: + await = 1 + """, + + """def foo(): + async def bar(): pass + if 1: + await a + """, + + """def foo(): + async def bar(): pass + await a + """, + + """def foo(): + def baz(): pass + async def bar(): pass + await a + """, + + """def foo(): + def baz(): pass + # 456 + async def bar(): pass + # 123 + await a + """, + + """async def foo(): + def baz(): pass + # 456 + async def bar(): pass + # 123 + await = 2 + """, + + """def foo(): + + def baz(): pass + + async def bar(): pass + + await a + """, + + """async def foo(): + + def baz(): pass + + async def bar(): pass + + await = 2 + """, + + """async def foo(): + def async(): pass + """, + + """async def foo(): + def await(): pass + """, + + """async def foo(): + def bar(): + await + """, + + """async def foo(): + return lambda async: await + """, + + """async def foo(): + return lambda a: await + """, + + """async def foo(a: await b): + pass + """, + + """def baz(): + async def foo(a: await b): + pass + """, + + """async def foo(async): + pass + """, + + """async def foo(): + def bar(): + def baz(): + async = 1 + """, + + """async def foo(): + def bar(): + def baz(): + pass + async = 1 + """, + + """def foo(): + async def bar(): + + async def baz(): + pass + + def baz(): + 42 + + async = 1 + """, + + """async def foo(): + def bar(): + def baz(): + pass\nawait foo() + """, + + """def foo(): + def bar(): + async def baz(): + pass\nawait foo() + """, + + """async def foo(await): + pass + """, + + """def foo(): + + async def bar(): pass + + await a + """, + + """def foo(): + async def bar(): + pass\nawait a + """] + + ns = {} + for code in samples: + with self.subTest(code=code), self.assertRaises(SyntaxError): + exec(code, ns, ns) + + def test_goodsyntax_1(self): + # Tests for issue 24619 + + def foo(await): + async def foo(): pass + async def foo(): + pass + return await + 1 + self.assertEqual(foo(10), 11) + + def foo(await): + async def foo(): pass + async def foo(): pass + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + + async def foo(): pass + + async def foo(): pass + + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + """spam""" + async def foo(): \ + pass + # 123 + async def foo(): pass + # 456 + return await + 2 + self.assertEqual(foo(20), 22) + + def foo(await): + def foo(): pass + def foo(): pass + async def bar(): return await_ + await_ = await + try: + bar().send(None) + except StopIteration as ex: + return ex.args[0] + self.assertEqual(foo(42), 42) + + async def f(): + async def g(): pass + await z + self.assertTrue(inspect.iscoroutinefunction(f)) + class TokenizerRegrTest(unittest.TestCase): @@ -461,8 +672,7 @@ class Awaitable: pass - async def foo(): - return (await Awaitable()) + async def foo(): return await Awaitable() with self.assertRaisesRegex( TypeError, "object Awaitable can't be used in 'await' expression"): 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 @@ -1051,10 +1051,7 @@ async def test(): def sum(): - async = 1 - await = 41 - return async + await - + pass if 1: await someobj() 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 @@ -786,12 +786,12 @@ NAME 'def' (2, 2) (2, 5) NAME 'foo' (2, 6) (2, 9) OP '(' (2, 9) (2, 10) - NAME 'await' (2, 10) (2, 15) + AWAIT 'await' (2, 10) (2, 15) OP ')' (2, 15) (2, 16) OP ':' (2, 16) (2, 17) NEWLINE '\\n' (2, 17) (2, 18) INDENT ' ' (3, 0) (3, 4) - NAME 'await' (3, 4) (3, 9) + AWAIT 'await' (3, 4) (3, 9) OP '=' (3, 10) (3, 11) NUMBER '1' (3, 12) (3, 13) NEWLINE '\\n' (3, 13) (3, 14) @@ -829,6 +829,17 @@ OP ':' (2, 18) (2, 19) NAME 'pass' (2, 20) (2, 24) DEDENT '' (3, 0) (3, 0) + + >>> dump_tokens('''async def foo(async): await''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'foo' (1, 10) (1, 13) + OP '(' (1, 13) (1, 14) + ASYNC 'async' (1, 14) (1, 19) + OP ')' (1, 19) (1, 20) + OP ':' (1, 20) (1, 21) + AWAIT 'await' (1, 22) (1, 27) """ from test import support diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -501,6 +501,7 @@ # 'stashed' and 'ctx' are used for async/await parsing stashed = None ctx = [('sync', 0)] + in_async = 0 if encoding is not None: if encoding == "utf-8-sig": @@ -580,6 +581,9 @@ cur_indent = indents[-1] while len(ctx) > 1 and ctx[-1][1] >= cur_indent: + if ctx[-1][0] == 'async': + in_async -= 1 + assert in_async >= 0 ctx.pop() yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) @@ -640,7 +644,7 @@ yield TokenInfo(STRING, token, spos, epos, line) elif initial.isidentifier(): # ordinary name if token in ('async', 'await'): - if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + if in_async: yield TokenInfo( ASYNC if token == 'async' else AWAIT, token, spos, epos, line) @@ -657,6 +661,7 @@ and stashed.string == 'async'): ctx.append(('async', indents[-1])) + in_async += 1 yield TokenInfo(ASYNC, stashed.string, stashed.start, stashed.end, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ - Issue #24407: Fix crash when dict is mutated while being updated. +- Issue #24619: New approach for tokenizing async/await. As a consequence, + is is now possible to have one-line 'async def foo(): await ..' functions. + Library ------- diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -31,6 +31,12 @@ || c == '_'\ || (c >= 128)) +/* The following DEFTYPE* flags are used in 'tok_state->deftypestack', + and should be removed in 3.7, when async/await are regular + keywords. */ +#define DEFTYPE_ASYNC 1 +#define DEFTYPE_HAS_NL 2 + extern char *PyOS_Readline(FILE *, FILE *, const char *); /* Return malloc'ed string including trailing \n; empty malloc'ed string for EOF; @@ -130,6 +136,8 @@ tok->def = 0; tok->defstack[0] = 0; tok->deftypestack[0] = 0; + tok->def_async_behind = 0; + tok->def_in_async = 0; tok->atbol = 1; tok->pendin = 0; @@ -1436,7 +1444,12 @@ tok->pendin++; while (tok->def && tok->defstack[tok->def] >= tok->indent) { + if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { + tok->def_in_async--; + assert(tok->def_in_async >= 0); + } tok->def--; + assert(tok->def >= 0); } return DEDENT; @@ -1447,6 +1460,22 @@ } } + if (!blankline && tok->level == 0 + && tok->def && tok->deftypestack[tok->def] & DEFTYPE_HAS_NL + && tok->defstack[tok->def] >= tok->indent) + { + /* The top function on the stack did have a NEWLINE + token, but didn't have an INDENT. That means that + it's a one-line function and it should now be removed + from the stack. */ + if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { + tok->def_in_async--; + assert(tok->def_in_async >= 0); + } + tok->def--; + assert(tok->def >= 0); + } + again: tok->start = NULL; /* Skip spaces */ @@ -1501,59 +1530,58 @@ tok_len = tok->cur - tok->start; if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { - if (tok->def && tok->deftypestack[tok->def] == 3) { - tok->deftypestack[tok->def] = 2; + /* The current token is 'def'. */ + if (tok->def + 1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return ERRORTOKEN; } - else if (tok->defstack[tok->def] < tok->indent) { - /* We advance defs stack only when we see "def" *and* - the indentation level was increased relative to the - previous "def". */ - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; - } + /* Advance defs stack. */ + tok->def++; + tok->defstack[tok->def] = tok->indent; - tok->def++; - tok->defstack[tok->def] = tok->indent; - tok->deftypestack[tok->def] = 1; + if (tok->def_async_behind) { + /* The previous token was 'async'. */ + tok->def_async_behind = 0; + tok->deftypestack[tok->def] = DEFTYPE_ASYNC; + tok->def_in_async++; + } + else { + /* This is a regular function (not async def). */ + tok->deftypestack[tok->def] = 0; } } else if (tok_len == 5) { if (memcmp(tok->start, "async", 5) == 0) { + /* The current token is 'async'. */ memcpy(&ahead_tok, tok, sizeof(ahead_tok)); + /* Try to look ahead one token. */ ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start, &ahead_top_end); - if (ahead_tok_kind == NAME && - ahead_tok.cur - ahead_tok.start == 3 && - memcmp(ahead_tok.start, "def", 3) == 0) { - - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; - } - - tok->def++; - tok->defstack[tok->def] = tok->indent; - tok->deftypestack[tok->def] = 3; - + if (ahead_tok_kind == NAME + && ahead_tok.cur - ahead_tok.start == 3 + && memcmp(ahead_tok.start, "def", 3) == 0) + { + /* The next token is going to be 'def', so instead of + returning 'async' NAME token, we return ASYNC. */ + tok->def_async_behind = 1; return ASYNC; } - else if (tok->def && tok->deftypestack[tok->def] == 2 - && tok->defstack[tok->def] < tok->indent) { - + else if (tok->def_in_async) + { + /* We're inside an 'async def' function, so we treat + 'async' token as ASYNC, instead of NAME. */ return ASYNC; } } - else if (memcmp(tok->start, "await", 5) == 0 - && tok->def && tok->deftypestack[tok->def] == 2 - && tok->defstack[tok->def] < tok->indent) { - + else if (memcmp(tok->start, "await", 5) == 0 && tok->def_in_async) + { + /* We're inside an 'async def' function, so we treat + 'await' token as AWAIT, instead of NAME. */ return AWAIT; } } @@ -1569,6 +1597,13 @@ *p_start = tok->start; *p_end = tok->cur - 1; /* Leave '\n' out of the string */ tok->cont_line = 0; + if (tok->def) { + /* Mark the top function on the stack that it had + at least one NEWLINE. That will help us to + distinguish one-line functions from functions + with multiple statements. */ + tok->deftypestack[tok->def] |= DEFTYPE_HAS_NL; + } return NEWLINE; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -66,12 +66,21 @@ const char* str; const char* input; /* Tokenizer's newline translated copy of the string. */ - int defstack[MAXINDENT]; /* stack if funcs & indents where they - were defined */ - int deftypestack[MAXINDENT]; /* stack of func types - (0 not func; 1: "def name"; - 2: "async def name") */ - int def; /* Length of stack of func types */ + /* `def*` fields are for parsing async/await in a backwards compatible + way. They should be removed in 3.7, when they will become + regular constants. See PEP 492 for more details. */ + int defstack[MAXINDENT]; /* Stack of funcs & indents where they + were defined. */ + int deftypestack[MAXINDENT]; /* Stack of func flags, see DEFTYPE_* + constants. */ + int def; /* Length of stack of func types/flags. */ + int def_async_behind; /* 1 if there was an 'async' token before + a 'def' token. */ + int def_in_async; /* Counter of how deep 'async def's + are nested. If greater than 0, + we are somewhere in an 'async def' + body, so 'async' and 'await' should + be parsed as keywords.*/ }; extern struct tok_state *PyTokenizer_FromString(const char *, int); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 13:49:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Jul 2015 11:49:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2MTkp?= Message-ID: <20150722114921.24774.56803@psf.io> https://hg.python.org/cpython/rev/6f4e0c462daf changeset: 96997:6f4e0c462daf parent: 96995:987b72921a0c parent: 96996:e4e01488afff user: Yury Selivanov date: Wed Jul 22 14:49:13 2015 +0300 summary: Merge 3.5 (Issue #24619) files: Lib/test/badsyntax_async2.py | 2 +- Lib/test/test_coroutines.py | 9 +++++---- Python/compile.c | 5 ++--- Python/symtable.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/test/badsyntax_async2.py b/Lib/test/badsyntax_async2.py --- a/Lib/test/badsyntax_async2.py +++ b/Lib/test/badsyntax_async2.py @@ -1,2 +1,2 @@ -async def foo(a:await something()): +async def foo(a=await something()): pass diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -205,12 +205,14 @@ return lambda a: await """, - """async def foo(a: await b): + """await a()""", + + """async def foo(a=await b): pass """, """def baz(): - async def foo(a: await b): + async def foo(a=await b): pass """, @@ -271,10 +273,9 @@ pass\nawait a """] - ns = {} for code in samples: with self.subTest(code=code), self.assertRaises(SyntaxError): - exec(code, ns, ns) + compile(code, "", "exec") def test_goodsyntax_1(self): # Tests for issue 24619 diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1749,13 +1749,12 @@ arglength = asdl_seq_LEN(args->defaults); arglength |= kw_default_count << 8; arglength |= num_annotations << 16; + if (is_async) + co->co_flags |= CO_COROUTINE; compiler_make_closure(c, co, arglength, qualname); Py_DECREF(qualname); Py_DECREF(co); - if (is_async) - co->co_flags |= CO_COROUTINE; - /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1542,7 +1542,7 @@ if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) return 0; if (returns) - VISIT(st, expr, s->v.FunctionDef.returns); + VISIT(st, expr, returns); return 1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 13:49:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Jul 2015 11:49:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjE5?= =?utf-8?q?=3A_More_tests=3B_fix_nits_in_compiler=2Ec?= Message-ID: <20150722114921.24770.84713@psf.io> https://hg.python.org/cpython/rev/e4e01488afff changeset: 96996:e4e01488afff branch: 3.5 parent: 96994:9da080ecadb2 user: Yury Selivanov date: Wed Jul 22 14:48:57 2015 +0300 summary: Issue #24619: More tests; fix nits in compiler.c files: Lib/test/badsyntax_async2.py | 2 +- Lib/test/test_coroutines.py | 9 +++++---- Python/compile.c | 5 ++--- Python/symtable.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/test/badsyntax_async2.py b/Lib/test/badsyntax_async2.py --- a/Lib/test/badsyntax_async2.py +++ b/Lib/test/badsyntax_async2.py @@ -1,2 +1,2 @@ -async def foo(a:await something()): +async def foo(a=await something()): pass diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -205,12 +205,14 @@ return lambda a: await """, - """async def foo(a: await b): + """await a()""", + + """async def foo(a=await b): pass """, """def baz(): - async def foo(a: await b): + async def foo(a=await b): pass """, @@ -271,10 +273,9 @@ pass\nawait a """] - ns = {} for code in samples: with self.subTest(code=code), self.assertRaises(SyntaxError): - exec(code, ns, ns) + compile(code, "", "exec") def test_goodsyntax_1(self): # Tests for issue 24619 diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1749,13 +1749,12 @@ arglength = asdl_seq_LEN(args->defaults); arglength |= kw_default_count << 8; arglength |= num_annotations << 16; + if (is_async) + co->co_flags |= CO_COROUTINE; compiler_make_closure(c, co, arglength, qualname); Py_DECREF(qualname); Py_DECREF(co); - if (is_async) - co->co_flags |= CO_COROUTINE; - /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1542,7 +1542,7 @@ if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) return 0; if (returns) - VISIT(st, expr, s->v.FunctionDef.returns); + VISIT(st, expr, returns); return 1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 16:58:08 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 14:58:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=238585=3A_improved_?= =?utf-8?q?tests_for_zipimporter2=2E_Patch_from_Mark_Lawrence=2E?= Message-ID: <20150722145805.37582.46175@psf.io> https://hg.python.org/cpython/rev/ef5c5a2bbd48 changeset: 96998:ef5c5a2bbd48 user: Robert Collins date: Thu Jul 23 02:57:56 2015 +1200 summary: Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. files: Lib/test/test_zipimport.py | 21 ++++++++++++++++++++- Misc/NEWS | 2 ++ 2 files changed, 22 insertions(+), 1 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 @@ -214,7 +214,8 @@ packdir2 = packdir + TESTPACK2 + os.sep files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), packdir2 + "__init__" + pyc_ext: (NOW, test_pyc), - packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)} + packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc), + "spam" + pyc_ext: (NOW, test_pyc)} z = ZipFile(TEMP_ZIP, "w") try: @@ -228,6 +229,14 @@ zi = zipimport.zipimporter(TEMP_ZIP) self.assertEqual(zi.archive, TEMP_ZIP) self.assertEqual(zi.is_package(TESTPACK), True) + + find_mod = zi.find_module('spam') + self.assertIsNotNone(find_mod) + self.assertIsInstance(find_mod, zipimport.zipimporter) + self.assertFalse(find_mod.is_package('spam')) + load_mod = find_mod.load_module('spam') + self.assertEqual(find_mod.get_filename('spam'), load_mod.__file__) + mod = zi.load_module(TESTPACK) self.assertEqual(zi.get_filename(TESTPACK), mod.__file__) @@ -287,6 +296,16 @@ self.assertEqual( zi.is_package(TESTPACK2 + os.sep + TESTMOD), False) + pkg_path = TEMP_ZIP + os.sep + packdir + TESTPACK2 + zi2 = zipimport.zipimporter(pkg_path) + find_mod_dotted = zi2.find_module(TESTMOD) + self.assertIsNotNone(find_mod_dotted) + self.assertIsInstance(find_mod_dotted, zipimport.zipimporter) + self.assertFalse(zi2.is_package(TESTMOD)) + load_mod = find_mod_dotted.load_module(TESTMOD) + self.assertEqual( + find_mod_dotted.get_filename(TESTMOD), load_mod.__file__) + mod_path = TESTPACK2 + os.sep + TESTMOD mod_name = module_path_to_dotted_name(mod_path) __import__(mod_name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. + - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. Patch from Nicola Palumbo and Laurent De Buyst. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 18:25:35 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 22 Jul 2015 16:25:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNDQw?= =?utf-8?q?=3A_Improve_http=2Eserver=2ESimpleHTTPRequestHandler_tests?= Message-ID: <20150722162534.11664.37247@psf.io> https://hg.python.org/cpython/rev/267ea1731a91 changeset: 96999:267ea1731a91 branch: 3.5 parent: 96996:e4e01488afff user: Berker Peksag date: Wed Jul 22 19:25:37 2015 +0300 summary: Issue #23440: Improve http.server.SimpleHTTPRequestHandler tests * Tests that index.html is served, rather than an automatic directory listing * Tests that there is no extra data sent after the response Patch by Martin Panter. files: Lib/test/test_httpservers.py | 36 +++++++++++++++++++---- 1 files changed, 29 insertions(+), 7 deletions(-) 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 @@ -298,12 +298,28 @@ BaseTestCase.tearDown(self) def check_status_and_reason(self, response, status, data=None): + def close_conn(): + """Don't close reader yet so we can check if there was leftover + buffered input""" + nonlocal reader + reader = response.fp + response.fp = None + reader = None + response._close_conn = close_conn + body = response.read() self.assertTrue(response) self.assertEqual(response.status, status) self.assertIsNotNone(response.reason) if data: self.assertEqual(data, body) + # Ensure the server has not set up a persistent connection, and has + # not sent any extra data + self.assertEqual(response.version, 10) + self.assertEqual(response.msg.get("Connection", "close"), "close") + self.assertEqual(reader.read(30), b'', 'Connection should be closed') + + reader.close() return body @support.requires_mac_ver(10, 5) @@ -353,15 +369,21 @@ self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) response = self.request('/' + 'ThisDoesNotExist' + '/') self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) - with open(os.path.join(self.tempdir_name, 'index.html'), 'w') as f: - response = self.request('/' + self.tempdir_name + '/') - self.check_status_and_reason(response, HTTPStatus.OK) - # chmod() doesn't work as expected on Windows, and filesystem - # permissions are ignored by root on Unix. - if os.name == 'posix' and os.geteuid() != 0: - os.chmod(self.tempdir, 0) + + data = b"Dummy index file\r\n" + with open(os.path.join(self.tempdir_name, 'index.html'), 'wb') as f: + f.write(data) + response = self.request('/' + self.tempdir_name + '/') + self.check_status_and_reason(response, HTTPStatus.OK, data) + + # chmod() doesn't work as expected on Windows, and filesystem + # permissions are ignored by root on Unix. + if os.name == 'posix' and os.geteuid() != 0: + os.chmod(self.tempdir, 0) + try: response = self.request(self.tempdir_name + '/') self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) + finally: os.chmod(self.tempdir, 0o755) def test_head(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 18:25:41 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 22 Jul 2015 16:25:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323440=3A_Improve_http=2Eserver=2ESimpleHTTPRequ?= =?utf-8?q?estHandler_tests?= Message-ID: <20150722162534.13851.68301@psf.io> https://hg.python.org/cpython/rev/7999671dc991 changeset: 97000:7999671dc991 parent: 96998:ef5c5a2bbd48 parent: 96999:267ea1731a91 user: Berker Peksag date: Wed Jul 22 19:26:09 2015 +0300 summary: Issue #23440: Improve http.server.SimpleHTTPRequestHandler tests * Tests that index.html is served, rather than an automatic directory listing * Tests that there is no extra data sent after the response Patch by Martin Panter. files: Lib/test/test_httpservers.py | 36 +++++++++++++++++++---- 1 files changed, 29 insertions(+), 7 deletions(-) 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 @@ -298,12 +298,28 @@ BaseTestCase.tearDown(self) def check_status_and_reason(self, response, status, data=None): + def close_conn(): + """Don't close reader yet so we can check if there was leftover + buffered input""" + nonlocal reader + reader = response.fp + response.fp = None + reader = None + response._close_conn = close_conn + body = response.read() self.assertTrue(response) self.assertEqual(response.status, status) self.assertIsNotNone(response.reason) if data: self.assertEqual(data, body) + # Ensure the server has not set up a persistent connection, and has + # not sent any extra data + self.assertEqual(response.version, 10) + self.assertEqual(response.msg.get("Connection", "close"), "close") + self.assertEqual(reader.read(30), b'', 'Connection should be closed') + + reader.close() return body @support.requires_mac_ver(10, 5) @@ -353,15 +369,21 @@ self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) response = self.request('/' + 'ThisDoesNotExist' + '/') self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) - with open(os.path.join(self.tempdir_name, 'index.html'), 'w') as f: - response = self.request('/' + self.tempdir_name + '/') - self.check_status_and_reason(response, HTTPStatus.OK) - # chmod() doesn't work as expected on Windows, and filesystem - # permissions are ignored by root on Unix. - if os.name == 'posix' and os.geteuid() != 0: - os.chmod(self.tempdir, 0) + + data = b"Dummy index file\r\n" + with open(os.path.join(self.tempdir_name, 'index.html'), 'wb') as f: + f.write(data) + response = self.request('/' + self.tempdir_name + '/') + self.check_status_and_reason(response, HTTPStatus.OK, data) + + # chmod() doesn't work as expected on Windows, and filesystem + # permissions are ignored by root on Unix. + if os.name == 'posix' and os.geteuid() != 0: + os.chmod(self.tempdir, 0) + try: response = self.request(self.tempdir_name + '/') self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) + finally: os.chmod(self.tempdir, 0o755) def test_head(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 20:19:27 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 18:19:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313938=3A_2to3_con?= =?utf-8?q?verts_StringTypes_to_a_tuple=2E_Patch_from_Mark_Hammond=2E?= Message-ID: <20150722181925.37473.88628@psf.io> https://hg.python.org/cpython/rev/b97b6cc381d7 changeset: 97001:b97b6cc381d7 user: Robert Collins date: Thu Jul 23 06:19:18 2015 +1200 summary: Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. files: Lib/lib2to3/fixes/fix_types.py | 2 +- Lib/lib2to3/tests/test_fixers.py | 4 ++++ Misc/NEWS | 2 ++ 3 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/lib2to3/fixes/fix_types.py b/Lib/lib2to3/fixes/fix_types.py --- a/Lib/lib2to3/fixes/fix_types.py +++ b/Lib/lib2to3/fixes/fix_types.py @@ -42,7 +42,7 @@ 'NotImplementedType' : 'type(NotImplemented)', 'SliceType' : 'slice', 'StringType': 'bytes', # XXX ? - 'StringTypes' : 'str', # XXX ? + 'StringTypes' : '(str,)', # XXX ? 'TupleType': 'tuple', 'TypeType' : 'type', 'UnicodeType': 'str', diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -3322,6 +3322,10 @@ a = """type(None)""" self.check(b, a) + b = "types.StringTypes" + a = "(str,)" + self.check(b, a) + class Test_idioms(FixerTestCase): fixer = "idioms" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. + - Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 20:40:37 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 18:40:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTUz?= =?utf-8?q?=3A_Improve_unittest_docs=2E_Patch_from_Martin_Panter_and_evilz?= =?utf-8?q?ero=2E?= Message-ID: <20150722184037.62367.58908@psf.io> https://hg.python.org/cpython/rev/eefc157b3096 changeset: 97002:eefc157b3096 branch: 3.4 parent: 96990:f4cd9ac378d7 user: Robert Collins date: Thu Jul 23 06:37:26 2015 +1200 summary: Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. files: Doc/library/unittest.rst | 12 ++++++++---- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -644,10 +644,8 @@ kinds of failure. Each instance of :class:`TestCase` will run a single base method: the method - named *methodName*. However, the standard implementation of the default - *methodName*, ``runTest()``, will run every method starting with ``test`` - as an individual test, and count successes and failures accordingly. - Therefore, in most uses of :class:`TestCase`, you will neither change + named *methodName*. + In most uses of :class:`TestCase`, you will neither change the *methodName* nor reimplement the default ``runTest()`` method. .. versionchanged:: 3.2 @@ -1551,6 +1549,12 @@ Return a suite of all tests cases contained in the :class:`TestCase`\ -derived :class:`testCaseClass`. + A test case instance is created for each method named by + :meth:`getTestCaseNames`. By default these are the method names + beginning with ``test``. If :meth:`getTestCaseNames` returns no + methods, but the :meth:`runTest` method is implemented, a single test + case is created for that method instead. + .. method:: loadTestsFromModule(module) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1535,3 +1535,4 @@ Peter ?strand Laurent De Buyst Nicola Palumbo +evilzero diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. + - Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. - Issue #21750: mock_open.read_data can now be read from each instance, as it -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 20:40:38 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 18:40:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2322153=3A_Improve_unittest_docs=2E_Patch_from_Martin_P?= =?utf-8?q?anter_and_evilzero=2E?= Message-ID: <20150722184037.8508.46705@psf.io> https://hg.python.org/cpython/rev/10f5a7fa26d5 changeset: 97003:10f5a7fa26d5 branch: 3.5 parent: 96999:267ea1731a91 parent: 97002:eefc157b3096 user: Robert Collins date: Thu Jul 23 06:39:06 2015 +1200 summary: Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. files: Doc/library/unittest.rst | 12 ++++++++---- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -651,10 +651,8 @@ kinds of failure. Each instance of :class:`TestCase` will run a single base method: the method - named *methodName*. However, the standard implementation of the default - *methodName*, ``runTest()``, will run every method starting with ``test`` - as an individual test, and count successes and failures accordingly. - Therefore, in most uses of :class:`TestCase`, you will neither change + named *methodName*. + In most uses of :class:`TestCase`, you will neither change the *methodName* nor reimplement the default ``runTest()`` method. .. versionchanged:: 3.2 @@ -1572,6 +1570,12 @@ Return a suite of all tests cases contained in the :class:`TestCase`\ -derived :class:`testCaseClass`. + A test case instance is created for each method named by + :meth:`getTestCaseNames`. By default these are the method names + beginning with ``test``. If :meth:`getTestCaseNames` returns no + methods, but the :meth:`runTest` method is implemented, a single test + case is created for that method instead. + .. method:: loadTestsFromModule(module, pattern=None) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1584,3 +1584,4 @@ Ignacio Rossi Laurent De Buyst Nicola Palumbo +evilzero diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,8 @@ Library ------- +- Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. + - Issue #24580: Symbolic group references to open group in re patterns now are explicitly forbidden as well as numeric group references. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 20:40:38 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 18:40:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322153=3A_Improve_unittest_docs=2E_Patch_from_Ma?= =?utf-8?q?rtin_Panter_and_evilzero=2E?= Message-ID: <20150722184037.3167.3674@psf.io> https://hg.python.org/cpython/rev/45bd2dadbd0d changeset: 97004:45bd2dadbd0d parent: 97001:b97b6cc381d7 parent: 97003:10f5a7fa26d5 user: Robert Collins date: Thu Jul 23 06:40:13 2015 +1200 summary: Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. files: Doc/library/unittest.rst | 12 ++++++++---- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -651,10 +651,8 @@ kinds of failure. Each instance of :class:`TestCase` will run a single base method: the method - named *methodName*. However, the standard implementation of the default - *methodName*, ``runTest()``, will run every method starting with ``test`` - as an individual test, and count successes and failures accordingly. - Therefore, in most uses of :class:`TestCase`, you will neither change + named *methodName*. + In most uses of :class:`TestCase`, you will neither change the *methodName* nor reimplement the default ``runTest()`` method. .. versionchanged:: 3.2 @@ -1572,6 +1570,12 @@ Return a suite of all tests cases contained in the :class:`TestCase`\ -derived :class:`testCaseClass`. + A test case instance is created for each method named by + :meth:`getTestCaseNames`. By default these are the method names + beginning with ``test``. If :meth:`getTestCaseNames` returns no + methods, but the :meth:`runTest` method is implemented, a single test + case is created for that method instead. + .. method:: loadTestsFromModule(module, pattern=None) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1585,3 +1585,4 @@ Ignacio Rossi Laurent De Buyst Nicola Palumbo +evilzero diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -51,6 +51,8 @@ Library ------- +- Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. + - Issue #24580: Symbolic group references to open group in re patterns now are explicitly forbidden as well as numeric group references. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 21:09:31 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 19:09:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_suspicious?= =?utf-8?q?_after_the_unittest_docs_change=2E?= Message-ID: <20150722190928.62369.96040@psf.io> https://hg.python.org/cpython/rev/f20b2d260171 changeset: 97005:f20b2d260171 branch: 3.4 parent: 97002:eefc157b3096 user: Robert Collins date: Thu Jul 23 07:07:07 2015 +1200 summary: Fix suspicious after the unittest docs change. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -196,10 +196,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1412,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:foo,'ERROR:foo.bar:second message']) -library/unittest,1412,:second,'ERROR:foo.bar:second message']) +library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:foo,'ERROR:foo.bar:second message']) +library/unittest,1406,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 21:33:13 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 19:33:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_unittest_docs_suspicious_fix=2E?= Message-ID: <20150722193312.8498.18794@psf.io> https://hg.python.org/cpython/rev/d697d410e157 changeset: 97006:d697d410e157 branch: 3.5 parent: 97003:10f5a7fa26d5 parent: 97005:f20b2d260171 user: Robert Collins date: Thu Jul 23 07:32:27 2015 +1200 summary: Merge unittest docs suspicious fix. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -194,10 +194,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1412,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:foo,'ERROR:foo.bar:second message']) -library/unittest,1412,:second,'ERROR:foo.bar:second message']) +library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:foo,'ERROR:foo.bar:second message']) +library/unittest,1406,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 21:33:13 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 19:33:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_unittest_docs_suspicious_fix=2E?= Message-ID: <20150722193312.8500.82987@psf.io> https://hg.python.org/cpython/rev/b11bd6e50b0c changeset: 97007:b11bd6e50b0c parent: 97004:45bd2dadbd0d parent: 97006:d697d410e157 user: Robert Collins date: Thu Jul 23 07:32:39 2015 +1200 summary: Merge unittest docs suspicious fix. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -194,10 +194,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1412,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1412,:foo,'ERROR:foo.bar:second message']) -library/unittest,1412,:second,'ERROR:foo.bar:second message']) +library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,1406,:foo,'ERROR:foo.bar:second message']) +library/unittest,1406,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 21:41:59 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 19:41:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzOTM4?= =?utf-8?q?=3A_2to3_converts_StringTypes_to_a_tuple=2E_Patch_from_Mark_Ham?= =?utf-8?q?mond=2E?= Message-ID: <20150722194158.13847.82357@psf.io> https://hg.python.org/cpython/rev/ce34c78ebf65 changeset: 97008:ce34c78ebf65 branch: 2.7 parent: 96993:b2f4d8377bce user: Robert Collins date: Thu Jul 23 06:19:18 2015 +1200 summary: Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. files: Lib/lib2to3/fixes/fix_types.py | 2 +- Lib/lib2to3/tests/test_fixers.py | 4 ++++ Misc/NEWS | 2 ++ 3 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/lib2to3/fixes/fix_types.py b/Lib/lib2to3/fixes/fix_types.py --- a/Lib/lib2to3/fixes/fix_types.py +++ b/Lib/lib2to3/fixes/fix_types.py @@ -42,7 +42,7 @@ 'NotImplementedType' : 'type(NotImplemented)', 'SliceType' : 'slice', 'StringType': 'bytes', # XXX ? - 'StringTypes' : 'str', # XXX ? + 'StringTypes' : '(str,)', # XXX ? 'TupleType': 'tuple', 'TypeType' : 'type', 'UnicodeType': 'str', diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -3263,6 +3263,10 @@ a = """type(None)""" self.check(b, a) + b = "types.StringTypes" + a = "(str,)" + self.check(b, a) + class Test_idioms(FixerTestCase): fixer = "idioms" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. + - Issue #24611: Fixed compiling the posix module on non-Windows platforms without mknod() or makedev() (e.g. on Unixware). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 22:09:46 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 20:09:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Remove_line_numbers_from_unittest_in_susp-ignored=2E?= Message-ID: <20150722200946.24786.6967@psf.io> https://hg.python.org/cpython/rev/9474ae243afa changeset: 97010:9474ae243afa branch: 3.5 parent: 97006:d697d410e157 parent: 97009:f574da88c3be user: Robert Collins date: Thu Jul 23 08:08:59 2015 +1200 summary: Remove line numbers from unittest in susp-ignored. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -194,10 +194,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:foo,'ERROR:foo.bar:second message']) -library/unittest,1406,:second,'ERROR:foo.bar:second message']) +library/unittest,,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:foo,'ERROR:foo.bar:second message']) +library/unittest,,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 22:09:46 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 20:09:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Remove_line_nu?= =?utf-8?q?mbers_from_unittest_in_susp-ignored=2E?= Message-ID: <20150722200946.24768.32748@psf.io> https://hg.python.org/cpython/rev/f574da88c3be changeset: 97009:f574da88c3be branch: 3.4 parent: 97005:f20b2d260171 user: Robert Collins date: Thu Jul 23 08:08:38 2015 +1200 summary: Remove line numbers from unittest in susp-ignored. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -196,10 +196,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:foo,'ERROR:foo.bar:second message']) -library/unittest,1406,:second,'ERROR:foo.bar:second message']) +library/unittest,,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:foo,'ERROR:foo.bar:second message']) +library/unittest,,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 22 22:09:47 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 22 Jul 2015 20:09:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Remove_line_numbers_from_unittest_in_susp-ignored=2E?= Message-ID: <20150722200946.52004.86902@psf.io> https://hg.python.org/cpython/rev/6c6f1e107cfe changeset: 97011:6c6f1e107cfe parent: 97007:b11bd6e50b0c parent: 97010:9474ae243afa user: Robert Collins date: Thu Jul 23 08:09:05 2015 +1200 summary: Remove line numbers from unittest in susp-ignored. files: Doc/tools/susp-ignored.csv | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -194,10 +194,10 @@ library/time,,:ss, library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: -library/unittest,1406,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," -library/unittest,1406,:foo,'ERROR:foo.bar:second message']) -library/unittest,1406,:second,'ERROR:foo.bar:second message']) +library/unittest,,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:first,"self.assertEqual(cm.output, ['INFO:foo:first message'," +library/unittest,,:foo,'ERROR:foo.bar:second message']) +library/unittest,,:second,'ERROR:foo.bar:second message']) library/urllib.request,,:close,Connection:close library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/urllib.request,,:password,"""joe:password at python.org""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 00:19:32 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Jul 2015 22:19:32 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Sync_the_PEP_with?= =?utf-8?q?_the_latest_state_of_things_in_CPython?= Message-ID: <20150722221931.37347.7360@psf.io> https://hg.python.org/peps/rev/d7d11f7d91a5 changeset: 5908:d7d11f7d91a5 user: Yury Selivanov date: Thu Jul 23 01:19:31 2015 +0300 summary: pep-0492: Sync the PEP with the latest state of things in CPython files: pep-0492.txt | 58 +++++++++++++-------------------------- 1 files changed, 19 insertions(+), 39 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -701,6 +701,9 @@ * ``inspect.iscoroutinefunction(obj)`` returns ``True`` if ``obj`` is a *native coroutine function*. +* ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` is an + *awaitable*. + * ``inspect.getcoroutinestate(coro)`` returns the current state of a *native coroutine object* (mirrors ``inspect.getfgeneratorstate(gen)``). @@ -735,6 +738,20 @@ implement ``send(value)``, ``throw(type, exc, tb)``, ``close()`` and ``__await__()`` methods. + Note that generator-based coroutines with ``CO_ITERABLE_COROUTINE`` + flag do not implement ``__await__`` method, and therefore are not + instances of ``collections.abc.Coroutine`` and + ``collections.abc.Awaitable`` ABCs:: + + @types.coroutine + def gencoro(): + yield + + assert not isinstance(gencoro(), collections.abc.Coroutine) + + # however: + assert inspect.isawaitable(gencoro()) + To allow easy testing if objects support asynchronous iteration, two more ABCs are added: @@ -837,8 +854,6 @@ * recognizes ``async def`` ``NAME`` tokens combination; -* keeps track of regular ``def`` and ``async def`` indented blocks; - * while tokenizing ``async def`` block, it replaces ``'async'`` ``NAME`` token with ``ASYNC``, and ``'await'`` ``NAME`` token with ``AWAIT``; @@ -931,41 +946,6 @@ atom_expr: [AWAIT] atom trailer* -Transition Period Shortcomings ------------------------------- - -There is just one. - -Until ``async`` and ``await`` are not proper keywords, it is not -possible (or at least very hard) to fix ``tokenizer.c`` to recognize -them on the **same line** with ``def`` keyword:: - - # async and await will always be parsed as variables - - async def outer(): # 1 - def nested(a=(await fut)): - pass - - async def foo(): return (await fut) # 2 - -Since ``await`` and ``async`` in such cases are parsed as ``NAME`` -tokens, a ``SyntaxError`` will be raised. - -To workaround these issues, the above examples can be easily rewritten -to a more readable form:: - - async def outer(): # 1 - a_default = await fut - def nested(a=a_default): - pass - - async def foo(): # 2 - return (await fut) - -This limitation will go away as soon as ``async`` and ``await`` are -proper keywords. - - Deprecation Plans ----------------- @@ -1365,8 +1345,8 @@ 6. New functions: ``sys.set_coroutine_wrapper(callback)``, ``sys.get_coroutine_wrapper()``, ``types.coroutine(gen)``, ``inspect.iscoroutinefunction(func)``, ``inspect.iscoroutine(obj)``, - ``inspect.getcoroutinestate(coro)``, and - ``inspect.getcoroutinelocals(coro)``. + ``inspect.isawaitable(obj)``, ``inspect.getcoroutinestate(coro)``, + and ``inspect.getcoroutinelocals(coro)``. 7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Jul 23 07:55:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 05:55:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Njg4?= =?utf-8?q?=3A_ast=2Eget=5Fdocstring=28=29_for_=27async_def=27_functions?= =?utf-8?q?=2E?= Message-ID: <20150723055530.3171.89361@psf.io> https://hg.python.org/cpython/rev/ecb13b9c4cd0 changeset: 97012:ecb13b9c4cd0 branch: 3.5 parent: 97010:9474ae243afa user: Yury Selivanov date: Thu Jul 23 08:54:35 2015 +0300 summary: Issue #24688: ast.get_docstring() for 'async def' functions. files: Lib/ast.py | 2 +- Lib/test/test_ast.py | 3 +++ Misc/NEWS | 2 ++ 3 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py --- a/Lib/ast.py +++ b/Lib/ast.py @@ -194,7 +194,7 @@ be found. If the node provided does not have docstrings a TypeError will be raised. """ - if not isinstance(node, (FunctionDef, ClassDef, Module)): + if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) if node.body and isinstance(node.body[0], Expr) and \ isinstance(node.body[0].value, Str): 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 @@ -511,6 +511,9 @@ self.assertEqual(ast.get_docstring(node.body[0]), 'line one\nline two') + node = ast.parse('async def foo():\n """spam\n ham"""') + self.assertEqual(ast.get_docstring(node.body[0]), 'spam\nham') + def test_literal_eval(self): self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3]) self.assertEqual(ast.literal_eval('{"foo": 42}'), {"foo": 42}) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -53,6 +53,8 @@ - Issue #24669: Fix inspect.getsource() for 'async def' functions. Patch by Kai Groner. +- Issue #24688: ast.get_docstring() for 'async def' functions. + Build ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 07:55:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 05:55:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2ODgp?= Message-ID: <20150723055530.22233.69269@psf.io> https://hg.python.org/cpython/rev/5c8c88973709 changeset: 97013:5c8c88973709 parent: 97011:6c6f1e107cfe parent: 97012:ecb13b9c4cd0 user: Yury Selivanov date: Thu Jul 23 08:55:07 2015 +0300 summary: Merge 3.5 (Issue #24688) files: Lib/ast.py | 2 +- Lib/test/test_ast.py | 3 +++ Misc/NEWS | 2 ++ 3 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py --- a/Lib/ast.py +++ b/Lib/ast.py @@ -194,7 +194,7 @@ be found. If the node provided does not have docstrings a TypeError will be raised. """ - if not isinstance(node, (FunctionDef, ClassDef, Module)): + if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) if node.body and isinstance(node.body[0], Expr) and \ isinstance(node.body[0].value, Str): 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 @@ -511,6 +511,9 @@ self.assertEqual(ast.get_docstring(node.body[0]), 'line one\nline two') + node = ast.parse('async def foo():\n """spam\n ham"""') + self.assertEqual(ast.get_docstring(node.body[0]), 'spam\nham') + def test_literal_eval(self): self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3]) self.assertEqual(ast.literal_eval('{"foo": 42}'), {"foo": 42}) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -76,6 +76,8 @@ - Issue #24669: Fix inspect.getsource() for 'async def' functions. Patch by Kai Groner. +- Issue #24688: ast.get_docstring() for 'async def' functions. + Build ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 08:14:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 06:14:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Njg3?= =?utf-8?q?=3A_Plug_refleak_on_SyntaxError_in_function_parameters_annotati?= =?utf-8?q?ons=2E?= Message-ID: <20150723061436.22235.35756@psf.io> https://hg.python.org/cpython/rev/b5a7f529b4ac changeset: 97014:b5a7f529b4ac branch: 3.5 parent: 97012:ecb13b9c4cd0 user: Yury Selivanov date: Thu Jul 23 09:10:44 2015 +0300 summary: Issue #24687: Plug refleak on SyntaxError in function parameters annotations. files: Lib/test/test_coroutines.py | 4 +++ Lib/test/test_grammar.py | 3 +- Misc/NEWS | 3 ++ Python/compile.c | 27 ++++++++++++------------ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -211,6 +211,10 @@ pass """, + """async def foo(a:await b): + pass + """, + """def baz(): async def foo(a=await b): pass 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 @@ -534,7 +534,8 @@ # Not allowed at class scope check_syntax_error(self, "class foo:yield 1") check_syntax_error(self, "class foo:yield from ()") - + # Check annotation refleak on SyntaxError + check_syntax_error(self, "def g(a:(yield)): pass") def test_raise(self): # 'raise' test [',' test] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ - Issue #24619: New approach for tokenizing async/await. As a consequence, is is now possible to have one-line 'async def foo(): await ..' functions. +- Issue #24687: Plug refleak on SyntaxError in function parameters + annotations. + Library ------- diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1559,32 +1559,31 @@ VISIT(c, expr, annotation); mangled = _Py_Mangle(c->u->u_private, id); if (!mangled) - return -1; + return 0; if (PyList_Append(names, mangled) < 0) { Py_DECREF(mangled); - return -1; + return 0; } Py_DECREF(mangled); } - return 0; + return 1; } static int compiler_visit_argannotations(struct compiler *c, asdl_seq* args, PyObject *names) { - int i, error; + int i; for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - error = compiler_visit_argannotation( + if (!compiler_visit_argannotation( c, arg->arg, arg->annotation, - names); - if (error) - return error; + names)) + return 0; } - return 0; + return 1; } static int @@ -1604,16 +1603,16 @@ if (!names) return -1; - if (compiler_visit_argannotations(c, args->args, names)) + if (!compiler_visit_argannotations(c, args->args, names)) goto error; if (args->vararg && args->vararg->annotation && - compiler_visit_argannotation(c, args->vararg->arg, + !compiler_visit_argannotation(c, args->vararg->arg, args->vararg->annotation, names)) goto error; - if (compiler_visit_argannotations(c, args->kwonlyargs, names)) + if (!compiler_visit_argannotations(c, args->kwonlyargs, names)) goto error; if (args->kwarg && args->kwarg->annotation && - compiler_visit_argannotation(c, args->kwarg->arg, + !compiler_visit_argannotation(c, args->kwarg->arg, args->kwarg->annotation, names)) goto error; @@ -1622,7 +1621,7 @@ if (!return_str) goto error; } - if (compiler_visit_argannotation(c, return_str, returns, names)) { + if (!compiler_visit_argannotation(c, return_str, returns, names)) { goto error; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 08:14:37 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 06:14:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2ODcp?= Message-ID: <20150723061436.37676.70083@psf.io> https://hg.python.org/cpython/rev/cf91ae981afd changeset: 97015:cf91ae981afd parent: 97013:5c8c88973709 parent: 97014:b5a7f529b4ac user: Yury Selivanov date: Thu Jul 23 09:11:13 2015 +0300 summary: Merge 3.5 (Issue #24687) files: Lib/test/test_coroutines.py | 4 +++ Lib/test/test_grammar.py | 3 +- Misc/NEWS | 3 ++ Python/compile.c | 27 ++++++++++++------------ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -211,6 +211,10 @@ pass """, + """async def foo(a:await b): + pass + """, + """def baz(): async def foo(a=await b): pass 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 @@ -534,7 +534,8 @@ # Not allowed at class scope check_syntax_error(self, "class foo:yield 1") check_syntax_error(self, "class foo:yield from ()") - + # Check annotation refleak on SyntaxError + check_syntax_error(self, "def g(a:(yield)): pass") def test_raise(self): # 'raise' test [',' test] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,9 @@ - Issue #24619: New approach for tokenizing async/await. As a consequence, is is now possible to have one-line 'async def foo(): await ..' functions. +- Issue #24687: Plug refleak on SyntaxError in function parameters + annotations. + Library ------- diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1559,32 +1559,31 @@ VISIT(c, expr, annotation); mangled = _Py_Mangle(c->u->u_private, id); if (!mangled) - return -1; + return 0; if (PyList_Append(names, mangled) < 0) { Py_DECREF(mangled); - return -1; + return 0; } Py_DECREF(mangled); } - return 0; + return 1; } static int compiler_visit_argannotations(struct compiler *c, asdl_seq* args, PyObject *names) { - int i, error; + int i; for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - error = compiler_visit_argannotation( + if (!compiler_visit_argannotation( c, arg->arg, arg->annotation, - names); - if (error) - return error; + names)) + return 0; } - return 0; + return 1; } static int @@ -1604,16 +1603,16 @@ if (!names) return -1; - if (compiler_visit_argannotations(c, args->args, names)) + if (!compiler_visit_argannotations(c, args->args, names)) goto error; if (args->vararg && args->vararg->annotation && - compiler_visit_argannotation(c, args->vararg->arg, + !compiler_visit_argannotation(c, args->vararg->arg, args->vararg->annotation, names)) goto error; - if (compiler_visit_argannotations(c, args->kwonlyargs, names)) + if (!compiler_visit_argannotations(c, args->kwonlyargs, names)) goto error; if (args->kwarg && args->kwarg->annotation && - compiler_visit_argannotation(c, args->kwarg->arg, + !compiler_visit_argannotation(c, args->kwarg->arg, args->kwarg->annotation, names)) goto error; @@ -1622,7 +1621,7 @@ if (!return_str) goto error; } - if (compiler_visit_argannotation(c, return_str, returns, names)) { + if (!compiler_visit_argannotation(c, return_str, returns, names)) { goto error; } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Jul 23 10:43:40 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 23 Jul 2015 08:43:40 +0000 Subject: [Python-checkins] Daily reference leaks (6c6f1e107cfe): sum=7 Message-ID: <20150723084339.51994.60339@psf.io> results for 6c6f1e107cfe on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogmUt9DF', '--timeout', '7200'] From python-checkins at python.org Thu Jul 23 13:42:41 2015 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 23 Jul 2015 11:42:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324681=3A__Move_th?= =?utf-8?q?e_store_of_so-=3Etable_to_the_code_block_where_it_is_used=2E?= Message-ID: <20150723114240.3163.86258@psf.io> https://hg.python.org/cpython/rev/bc80c783c4ab changeset: 97016:bc80c783c4ab user: Raymond Hettinger date: Thu Jul 23 07:42:23 2015 -0400 summary: Issue #24681: Move the store of so->table to the code block where it is used. files: Objects/setobject.c | 17 ++++++++++------- 1 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -50,7 +50,7 @@ static setentry * set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { - setentry *table = so->table; + setentry *table; setentry *entry; size_t perturb; size_t mask = so->mask; @@ -58,7 +58,7 @@ size_t j; int cmp; - entry = &table[i]; + entry = &so->table[i]; if (entry->key == NULL) return entry; @@ -75,6 +75,7 @@ && PyUnicode_CheckExact(key) && _PyUnicode_EQ(startkey, key)) return entry; + table = so->table; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); @@ -101,6 +102,7 @@ && PyUnicode_CheckExact(key) && _PyUnicode_EQ(startkey, key)) return entry; + table = so->table; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); @@ -118,7 +120,7 @@ perturb >>= PERTURB_SHIFT; i = (i * 5 + 1 + perturb) & mask; - entry = &table[i]; + entry = &so->table[i]; if (entry->key == NULL) return entry; } @@ -144,11 +146,10 @@ restart: - table = so->table; mask = so->mask; i = (size_t)hash & mask; - entry = &table[i]; + entry = &so->table[i]; if (entry->key == NULL) goto found_unused; @@ -166,6 +167,7 @@ && PyUnicode_CheckExact(key) && _PyUnicode_EQ(startkey, key)) goto found_active; + table = so->table; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); @@ -177,7 +179,7 @@ goto found_active; mask = so->mask; /* help avoid a register spill */ } - if (entry->hash == -1 && freeslot == NULL) + else if (entry->hash == -1 && freeslot == NULL) freeslot = entry; if (i + LINEAR_PROBES <= mask) { @@ -194,6 +196,7 @@ && PyUnicode_CheckExact(key) && _PyUnicode_EQ(startkey, key)) goto found_active; + table = so->table; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); @@ -213,7 +216,7 @@ perturb >>= PERTURB_SHIFT; i = (i * 5 + 1 + perturb) & mask; - entry = &table[i]; + entry = &so->table[i]; if (entry->key == NULL) goto found_unused_or_dummy; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 14:02:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 12:02:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2MTkp?= Message-ID: <20150723120245.24786.10175@psf.io> https://hg.python.org/cpython/rev/3f8048926690 changeset: 97018:3f8048926690 parent: 97016:bc80c783c4ab parent: 97017:d03f86e41066 user: Yury Selivanov date: Thu Jul 23 15:02:25 2015 +0300 summary: Merge 3.5 (Issue #24619) files: Lib/lib2to3/pgen2/tokenize.py | 33 ++-- Lib/lib2to3/tests/test_parser.py | 22 +++ Lib/test/test_coroutines.py | 1 + Lib/test/test_tokenize.py | 73 +++++++++++ Lib/tokenize.py | 39 +++-- Parser/tokenizer.c | 126 +++++------------- Parser/tokenizer.h | 21 +-- 7 files changed, 183 insertions(+), 132 deletions(-) diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -366,10 +366,11 @@ contline = None indents = [0] - # 'stashed' and 'ctx' are used for async/await parsing + # 'stashed' and 'async_*' are used for async/await parsing stashed = None - ctx = [('sync', 0)] - in_async = 0 + async_def = False + async_def_indent = 0 + async_def_nl = False while 1: # loop over lines in stream try: @@ -438,15 +439,18 @@ ("", lnum, pos, line)) indents = indents[:-1] - cur_indent = indents[-1] - while len(ctx) > 1 and ctx[-1][1] >= cur_indent: - if ctx[-1][0] == 'async': - in_async -= 1 - assert in_async >= 0 - ctx.pop() + if async_def and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 yield (DEDENT, '', (lnum, pos), (lnum, pos), line) + if async_def and async_def_nl and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 + else: # continued statement if not line: raise TokenError("EOF in multi-line statement", (lnum, 0)) @@ -466,10 +470,13 @@ newline = NEWLINE if parenlev > 0: newline = NL + elif async_def: + async_def_nl = True if stashed: yield stashed stashed = None yield (newline, token, spos, epos, line) + elif initial == '#': assert not token.endswith("\n") if stashed: @@ -508,7 +515,7 @@ yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name if token in ('async', 'await'): - if in_async: + if async_def: yield (ASYNC if token == 'async' else AWAIT, token, spos, epos, line) continue @@ -523,15 +530,13 @@ and stashed[0] == NAME and stashed[1] == 'async'): - ctx.append(('async', indents[-1])) - in_async += 1 + async_def = True + async_def_indent = indents[-1] yield (ASYNC, stashed[1], stashed[2], stashed[3], stashed[4]) stashed = None - else: - ctx.append(('sync', indents[-1])) if stashed: yield stashed diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -67,10 +67,32 @@ await x """) + self.validate("""async def foo(): + + def foo(): pass + + def foo(): pass + + await x + """) + + self.validate("""async def foo(): return await a""") + + self.validate("""def foo(): + def foo(): pass + async def foo(): await x + """) + self.invalid_syntax("await x") self.invalid_syntax("""def foo(): await x""") + self.invalid_syntax("""def foo(): + def foo(): pass + async def foo(): pass + await x + """) + def test_async_var(self): self.validate("""async = 1""") self.validate("""await = 1""") diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -330,6 +330,7 @@ async def f(): async def g(): pass await z + await = 1 self.assertTrue(inspect.iscoroutinefunction(f)) 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 @@ -840,6 +840,79 @@ OP ')' (1, 19) (1, 20) OP ':' (1, 20) (1, 21) AWAIT 'await' (1, 22) (1, 27) + + >>> dump_tokens('''def f(): + ... + ... def baz(): pass + ... async def bar(): pass + ... + ... await = 2''') + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'def' (1, 0) (1, 3) + NAME 'f' (1, 4) (1, 5) + OP '(' (1, 5) (1, 6) + OP ')' (1, 6) (1, 7) + OP ':' (1, 7) (1, 8) + NEWLINE '\\n' (1, 8) (1, 9) + NL '\\n' (2, 0) (2, 1) + INDENT ' ' (3, 0) (3, 2) + NAME 'def' (3, 2) (3, 5) + NAME 'baz' (3, 6) (3, 9) + OP '(' (3, 9) (3, 10) + OP ')' (3, 10) (3, 11) + OP ':' (3, 11) (3, 12) + NAME 'pass' (3, 13) (3, 17) + NEWLINE '\\n' (3, 17) (3, 18) + ASYNC 'async' (4, 2) (4, 7) + NAME 'def' (4, 8) (4, 11) + NAME 'bar' (4, 12) (4, 15) + OP '(' (4, 15) (4, 16) + OP ')' (4, 16) (4, 17) + OP ':' (4, 17) (4, 18) + NAME 'pass' (4, 19) (4, 23) + NEWLINE '\\n' (4, 23) (4, 24) + NL '\\n' (5, 0) (5, 1) + NAME 'await' (6, 2) (6, 7) + OP '=' (6, 8) (6, 9) + NUMBER '2' (6, 10) (6, 11) + DEDENT '' (7, 0) (7, 0) + + >>> dump_tokens('''async def f(): + ... + ... def baz(): pass + ... async def bar(): pass + ... + ... await = 2''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'f' (1, 10) (1, 11) + OP '(' (1, 11) (1, 12) + OP ')' (1, 12) (1, 13) + OP ':' (1, 13) (1, 14) + NEWLINE '\\n' (1, 14) (1, 15) + NL '\\n' (2, 0) (2, 1) + INDENT ' ' (3, 0) (3, 2) + NAME 'def' (3, 2) (3, 5) + NAME 'baz' (3, 6) (3, 9) + OP '(' (3, 9) (3, 10) + OP ')' (3, 10) (3, 11) + OP ':' (3, 11) (3, 12) + NAME 'pass' (3, 13) (3, 17) + NEWLINE '\\n' (3, 17) (3, 18) + ASYNC 'async' (4, 2) (4, 7) + NAME 'def' (4, 8) (4, 11) + NAME 'bar' (4, 12) (4, 15) + OP '(' (4, 15) (4, 16) + OP ')' (4, 16) (4, 17) + OP ':' (4, 17) (4, 18) + NAME 'pass' (4, 19) (4, 23) + NEWLINE '\\n' (4, 23) (4, 24) + NL '\\n' (5, 0) (5, 1) + AWAIT 'await' (6, 2) (6, 7) + OP '=' (6, 8) (6, 9) + NUMBER '2' (6, 10) (6, 11) + DEDENT '' (7, 0) (7, 0) """ from test import support diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -498,10 +498,11 @@ contline = None indents = [0] - # 'stashed' and 'ctx' are used for async/await parsing + # 'stashed' and 'async_*' are used for async/await parsing stashed = None - ctx = [('sync', 0)] - in_async = 0 + async_def = False + async_def_indent = 0 + async_def_nl = False if encoding is not None: if encoding == "utf-8-sig": @@ -579,15 +580,18 @@ ("", lnum, pos, line)) indents = indents[:-1] - cur_indent = indents[-1] - while len(ctx) > 1 and ctx[-1][1] >= cur_indent: - if ctx[-1][0] == 'async': - in_async -= 1 - assert in_async >= 0 - ctx.pop() + if async_def and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) + if async_def and async_def_nl and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 + else: # continued statement if not line: raise TokenError("EOF in multi-line statement", (lnum, 0)) @@ -609,8 +613,13 @@ if stashed: yield stashed stashed = None - yield TokenInfo(NL if parenlev > 0 else NEWLINE, - token, spos, epos, line) + if parenlev > 0: + yield TokenInfo(NL, token, spos, epos, line) + else: + yield TokenInfo(NEWLINE, token, spos, epos, line) + if async_def: + async_def_nl = True + elif initial == '#': assert not token.endswith("\n") if stashed: @@ -644,7 +653,7 @@ yield TokenInfo(STRING, token, spos, epos, line) elif initial.isidentifier(): # ordinary name if token in ('async', 'await'): - if in_async: + if async_def: yield TokenInfo( ASYNC if token == 'async' else AWAIT, token, spos, epos, line) @@ -660,15 +669,13 @@ and stashed.type == NAME and stashed.string == 'async'): - ctx.append(('async', indents[-1])) - in_async += 1 + async_def = True + async_def_indent = indents[-1] yield TokenInfo(ASYNC, stashed.string, stashed.start, stashed.end, stashed.line) stashed = None - else: - ctx.append(('sync', indents[-1])) if stashed: yield stashed diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -31,12 +31,6 @@ || c == '_'\ || (c >= 128)) -/* The following DEFTYPE* flags are used in 'tok_state->deftypestack', - and should be removed in 3.7, when async/await are regular - keywords. */ -#define DEFTYPE_ASYNC 1 -#define DEFTYPE_HAS_NL 2 - extern char *PyOS_Readline(FILE *, FILE *, const char *); /* Return malloc'ed string including trailing \n; empty malloc'ed string for EOF; @@ -133,12 +127,6 @@ tok->indent = 0; tok->indstack[0] = 0; - tok->def = 0; - tok->defstack[0] = 0; - tok->deftypestack[0] = 0; - tok->def_async_behind = 0; - tok->def_in_async = 0; - tok->atbol = 1; tok->pendin = 0; tok->prompt = tok->nextprompt = NULL; @@ -159,6 +147,11 @@ tok->decoding_readline = NULL; tok->decoding_buffer = NULL; #endif + + tok->async_def = 0; + tok->async_def_indent = 0; + tok->async_def_nl = 0; + return tok; } @@ -1350,11 +1343,6 @@ int c; int blankline, nonascii; - int tok_len; - struct tok_state ahead_tok; - char *ahead_tok_start = NULL, *ahead_top_end = NULL; - int ahead_tok_kind; - *p_start = *p_end = NULL; nextline: tok->start = NULL; @@ -1442,16 +1430,6 @@ if (tok->pendin != 0) { if (tok->pendin < 0) { tok->pendin++; - - while (tok->def && tok->defstack[tok->def] >= tok->indent) { - if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { - tok->def_in_async--; - assert(tok->def_in_async >= 0); - } - tok->def--; - assert(tok->def >= 0); - } - return DEDENT; } else { @@ -1460,20 +1438,19 @@ } } - if (!blankline && tok->level == 0 - && tok->def && tok->deftypestack[tok->def] & DEFTYPE_HAS_NL - && tok->defstack[tok->def] >= tok->indent) + if (tok->async_def + && !blankline + && tok->level == 0 + /* There was a NEWLINE after ASYNC DEF, + so we're past the signature. */ + && tok->async_def_nl + /* Current indentation level is less than where + the async function was defined */ + && tok->async_def_indent >= tok->indent) { - /* The top function on the stack did have a NEWLINE - token, but didn't have an INDENT. That means that - it's a one-line function and it should now be removed - from the stack. */ - if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { - tok->def_in_async--; - assert(tok->def_in_async >= 0); - } - tok->def--; - assert(tok->def >= 0); + tok->async_def = 0; + tok->async_def_indent = 0; + tok->async_def_nl = 0; } again: @@ -1528,38 +1505,27 @@ *p_start = tok->start; *p_end = tok->cur; - tok_len = tok->cur - tok->start; - if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { - /* The current token is 'def'. */ - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; + /* async/await parsing block. */ + if (tok->cur - tok->start == 5) { + /* Current token length is 5. */ + if (tok->async_def) { + /* We're inside an 'async def' function. */ + if (memcmp(tok->start, "async", 5) == 0) + return ASYNC; + if (memcmp(tok->start, "await", 5) == 0) + return AWAIT; } + else if (memcmp(tok->start, "async", 5) == 0) { + /* The current token is 'async'. + Look ahead one token.*/ - /* Advance defs stack. */ - tok->def++; - tok->defstack[tok->def] = tok->indent; + struct tok_state ahead_tok; + char *ahead_tok_start = NULL, *ahead_tok_end = NULL; + int ahead_tok_kind; - if (tok->def_async_behind) { - /* The previous token was 'async'. */ - tok->def_async_behind = 0; - tok->deftypestack[tok->def] = DEFTYPE_ASYNC; - tok->def_in_async++; - } - else { - /* This is a regular function (not async def). */ - tok->deftypestack[tok->def] = 0; - } - } - else if (tok_len == 5) { - if (memcmp(tok->start, "async", 5) == 0) { - /* The current token is 'async'. */ memcpy(&ahead_tok, tok, sizeof(ahead_tok)); - - /* Try to look ahead one token. */ ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start, - &ahead_top_end); + &ahead_tok_end); if (ahead_tok_kind == NAME && ahead_tok.cur - ahead_tok.start == 3 @@ -1567,22 +1533,10 @@ { /* The next token is going to be 'def', so instead of returning 'async' NAME token, we return ASYNC. */ - tok->def_async_behind = 1; + tok->async_def_indent = tok->indent; + tok->async_def = 1; return ASYNC; } - else if (tok->def_in_async) - { - /* We're inside an 'async def' function, so we treat - 'async' token as ASYNC, instead of NAME. */ - return ASYNC; - } - - } - else if (memcmp(tok->start, "await", 5) == 0 && tok->def_in_async) - { - /* We're inside an 'async def' function, so we treat - 'await' token as AWAIT, instead of NAME. */ - return AWAIT; } } @@ -1597,12 +1551,10 @@ *p_start = tok->start; *p_end = tok->cur - 1; /* Leave '\n' out of the string */ tok->cont_line = 0; - if (tok->def) { - /* Mark the top function on the stack that it had - at least one NEWLINE. That will help us to - distinguish one-line functions from functions - with multiple statements. */ - tok->deftypestack[tok->def] |= DEFTYPE_HAS_NL; + if (tok->async_def) { + /* We're somewhere inside an 'async def' function, and + we've encountered a NEWLINE after its signature. */ + tok->async_def_nl = 1; } return NEWLINE; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -66,21 +66,12 @@ const char* str; const char* input; /* Tokenizer's newline translated copy of the string. */ - /* `def*` fields are for parsing async/await in a backwards compatible - way. They should be removed in 3.7, when they will become - regular constants. See PEP 492 for more details. */ - int defstack[MAXINDENT]; /* Stack of funcs & indents where they - were defined. */ - int deftypestack[MAXINDENT]; /* Stack of func flags, see DEFTYPE_* - constants. */ - int def; /* Length of stack of func types/flags. */ - int def_async_behind; /* 1 if there was an 'async' token before - a 'def' token. */ - int def_in_async; /* Counter of how deep 'async def's - are nested. If greater than 0, - we are somewhere in an 'async def' - body, so 'async' and 'await' should - be parsed as keywords.*/ + /* async/await related fields; can be removed in 3.7 when async and await + become normal keywords. */ + int async_def; /* =1 if tokens are inside an 'async def' body. */ + int async_def_indent; /* Indentation level of the outermost 'async def'. */ + int async_def_nl; /* =1 if the outermost 'async def' had at least one + NEWLINE token after it. */ }; extern struct tok_state *PyTokenizer_FromString(const char *, int); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 14:02:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 12:02:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjE5?= =?utf-8?q?=3A_Simplify_async/await_tokenization=2E?= Message-ID: <20150723120245.11652.14156@psf.io> https://hg.python.org/cpython/rev/d03f86e41066 changeset: 97017:d03f86e41066 branch: 3.5 parent: 97014:b5a7f529b4ac user: Yury Selivanov date: Thu Jul 23 15:01:58 2015 +0300 summary: Issue #24619: Simplify async/await tokenization. This commit simplifies async/await tokenization in tokenizer.c, tokenize.py & lib2to3/tokenize.py. Previous solution was to keep a stack of async-def & def blocks, whereas the new approach is just to remember position of the outermost async-def block. This change won't bring any parsing performance improvements, but it makes the code much easier to read and validate. files: Lib/lib2to3/pgen2/tokenize.py | 33 ++-- Lib/lib2to3/tests/test_parser.py | 22 +++ Lib/test/test_coroutines.py | 1 + Lib/test/test_tokenize.py | 73 +++++++++++ Lib/tokenize.py | 39 +++-- Parser/tokenizer.c | 126 +++++------------- Parser/tokenizer.h | 21 +-- 7 files changed, 183 insertions(+), 132 deletions(-) diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -366,10 +366,11 @@ contline = None indents = [0] - # 'stashed' and 'ctx' are used for async/await parsing + # 'stashed' and 'async_*' are used for async/await parsing stashed = None - ctx = [('sync', 0)] - in_async = 0 + async_def = False + async_def_indent = 0 + async_def_nl = False while 1: # loop over lines in stream try: @@ -438,15 +439,18 @@ ("", lnum, pos, line)) indents = indents[:-1] - cur_indent = indents[-1] - while len(ctx) > 1 and ctx[-1][1] >= cur_indent: - if ctx[-1][0] == 'async': - in_async -= 1 - assert in_async >= 0 - ctx.pop() + if async_def and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 yield (DEDENT, '', (lnum, pos), (lnum, pos), line) + if async_def and async_def_nl and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 + else: # continued statement if not line: raise TokenError("EOF in multi-line statement", (lnum, 0)) @@ -466,10 +470,13 @@ newline = NEWLINE if parenlev > 0: newline = NL + elif async_def: + async_def_nl = True if stashed: yield stashed stashed = None yield (newline, token, spos, epos, line) + elif initial == '#': assert not token.endswith("\n") if stashed: @@ -508,7 +515,7 @@ yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name if token in ('async', 'await'): - if in_async: + if async_def: yield (ASYNC if token == 'async' else AWAIT, token, spos, epos, line) continue @@ -523,15 +530,13 @@ and stashed[0] == NAME and stashed[1] == 'async'): - ctx.append(('async', indents[-1])) - in_async += 1 + async_def = True + async_def_indent = indents[-1] yield (ASYNC, stashed[1], stashed[2], stashed[3], stashed[4]) stashed = None - else: - ctx.append(('sync', indents[-1])) if stashed: yield stashed diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -67,10 +67,32 @@ await x """) + self.validate("""async def foo(): + + def foo(): pass + + def foo(): pass + + await x + """) + + self.validate("""async def foo(): return await a""") + + self.validate("""def foo(): + def foo(): pass + async def foo(): await x + """) + self.invalid_syntax("await x") self.invalid_syntax("""def foo(): await x""") + self.invalid_syntax("""def foo(): + def foo(): pass + async def foo(): pass + await x + """) + def test_async_var(self): self.validate("""async = 1""") self.validate("""await = 1""") diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -330,6 +330,7 @@ async def f(): async def g(): pass await z + await = 1 self.assertTrue(inspect.iscoroutinefunction(f)) 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 @@ -840,6 +840,79 @@ OP ')' (1, 19) (1, 20) OP ':' (1, 20) (1, 21) AWAIT 'await' (1, 22) (1, 27) + + >>> dump_tokens('''def f(): + ... + ... def baz(): pass + ... async def bar(): pass + ... + ... await = 2''') + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'def' (1, 0) (1, 3) + NAME 'f' (1, 4) (1, 5) + OP '(' (1, 5) (1, 6) + OP ')' (1, 6) (1, 7) + OP ':' (1, 7) (1, 8) + NEWLINE '\\n' (1, 8) (1, 9) + NL '\\n' (2, 0) (2, 1) + INDENT ' ' (3, 0) (3, 2) + NAME 'def' (3, 2) (3, 5) + NAME 'baz' (3, 6) (3, 9) + OP '(' (3, 9) (3, 10) + OP ')' (3, 10) (3, 11) + OP ':' (3, 11) (3, 12) + NAME 'pass' (3, 13) (3, 17) + NEWLINE '\\n' (3, 17) (3, 18) + ASYNC 'async' (4, 2) (4, 7) + NAME 'def' (4, 8) (4, 11) + NAME 'bar' (4, 12) (4, 15) + OP '(' (4, 15) (4, 16) + OP ')' (4, 16) (4, 17) + OP ':' (4, 17) (4, 18) + NAME 'pass' (4, 19) (4, 23) + NEWLINE '\\n' (4, 23) (4, 24) + NL '\\n' (5, 0) (5, 1) + NAME 'await' (6, 2) (6, 7) + OP '=' (6, 8) (6, 9) + NUMBER '2' (6, 10) (6, 11) + DEDENT '' (7, 0) (7, 0) + + >>> dump_tokens('''async def f(): + ... + ... def baz(): pass + ... async def bar(): pass + ... + ... await = 2''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'f' (1, 10) (1, 11) + OP '(' (1, 11) (1, 12) + OP ')' (1, 12) (1, 13) + OP ':' (1, 13) (1, 14) + NEWLINE '\\n' (1, 14) (1, 15) + NL '\\n' (2, 0) (2, 1) + INDENT ' ' (3, 0) (3, 2) + NAME 'def' (3, 2) (3, 5) + NAME 'baz' (3, 6) (3, 9) + OP '(' (3, 9) (3, 10) + OP ')' (3, 10) (3, 11) + OP ':' (3, 11) (3, 12) + NAME 'pass' (3, 13) (3, 17) + NEWLINE '\\n' (3, 17) (3, 18) + ASYNC 'async' (4, 2) (4, 7) + NAME 'def' (4, 8) (4, 11) + NAME 'bar' (4, 12) (4, 15) + OP '(' (4, 15) (4, 16) + OP ')' (4, 16) (4, 17) + OP ':' (4, 17) (4, 18) + NAME 'pass' (4, 19) (4, 23) + NEWLINE '\\n' (4, 23) (4, 24) + NL '\\n' (5, 0) (5, 1) + AWAIT 'await' (6, 2) (6, 7) + OP '=' (6, 8) (6, 9) + NUMBER '2' (6, 10) (6, 11) + DEDENT '' (7, 0) (7, 0) """ from test import support diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -498,10 +498,11 @@ contline = None indents = [0] - # 'stashed' and 'ctx' are used for async/await parsing + # 'stashed' and 'async_*' are used for async/await parsing stashed = None - ctx = [('sync', 0)] - in_async = 0 + async_def = False + async_def_indent = 0 + async_def_nl = False if encoding is not None: if encoding == "utf-8-sig": @@ -579,15 +580,18 @@ ("", lnum, pos, line)) indents = indents[:-1] - cur_indent = indents[-1] - while len(ctx) > 1 and ctx[-1][1] >= cur_indent: - if ctx[-1][0] == 'async': - in_async -= 1 - assert in_async >= 0 - ctx.pop() + if async_def and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) + if async_def and async_def_nl and async_def_indent >= indents[-1]: + async_def = False + async_def_nl = False + async_def_indent = 0 + else: # continued statement if not line: raise TokenError("EOF in multi-line statement", (lnum, 0)) @@ -609,8 +613,13 @@ if stashed: yield stashed stashed = None - yield TokenInfo(NL if parenlev > 0 else NEWLINE, - token, spos, epos, line) + if parenlev > 0: + yield TokenInfo(NL, token, spos, epos, line) + else: + yield TokenInfo(NEWLINE, token, spos, epos, line) + if async_def: + async_def_nl = True + elif initial == '#': assert not token.endswith("\n") if stashed: @@ -644,7 +653,7 @@ yield TokenInfo(STRING, token, spos, epos, line) elif initial.isidentifier(): # ordinary name if token in ('async', 'await'): - if in_async: + if async_def: yield TokenInfo( ASYNC if token == 'async' else AWAIT, token, spos, epos, line) @@ -660,15 +669,13 @@ and stashed.type == NAME and stashed.string == 'async'): - ctx.append(('async', indents[-1])) - in_async += 1 + async_def = True + async_def_indent = indents[-1] yield TokenInfo(ASYNC, stashed.string, stashed.start, stashed.end, stashed.line) stashed = None - else: - ctx.append(('sync', indents[-1])) if stashed: yield stashed diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -31,12 +31,6 @@ || c == '_'\ || (c >= 128)) -/* The following DEFTYPE* flags are used in 'tok_state->deftypestack', - and should be removed in 3.7, when async/await are regular - keywords. */ -#define DEFTYPE_ASYNC 1 -#define DEFTYPE_HAS_NL 2 - extern char *PyOS_Readline(FILE *, FILE *, const char *); /* Return malloc'ed string including trailing \n; empty malloc'ed string for EOF; @@ -133,12 +127,6 @@ tok->indent = 0; tok->indstack[0] = 0; - tok->def = 0; - tok->defstack[0] = 0; - tok->deftypestack[0] = 0; - tok->def_async_behind = 0; - tok->def_in_async = 0; - tok->atbol = 1; tok->pendin = 0; tok->prompt = tok->nextprompt = NULL; @@ -159,6 +147,11 @@ tok->decoding_readline = NULL; tok->decoding_buffer = NULL; #endif + + tok->async_def = 0; + tok->async_def_indent = 0; + tok->async_def_nl = 0; + return tok; } @@ -1350,11 +1343,6 @@ int c; int blankline, nonascii; - int tok_len; - struct tok_state ahead_tok; - char *ahead_tok_start = NULL, *ahead_top_end = NULL; - int ahead_tok_kind; - *p_start = *p_end = NULL; nextline: tok->start = NULL; @@ -1442,16 +1430,6 @@ if (tok->pendin != 0) { if (tok->pendin < 0) { tok->pendin++; - - while (tok->def && tok->defstack[tok->def] >= tok->indent) { - if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { - tok->def_in_async--; - assert(tok->def_in_async >= 0); - } - tok->def--; - assert(tok->def >= 0); - } - return DEDENT; } else { @@ -1460,20 +1438,19 @@ } } - if (!blankline && tok->level == 0 - && tok->def && tok->deftypestack[tok->def] & DEFTYPE_HAS_NL - && tok->defstack[tok->def] >= tok->indent) + if (tok->async_def + && !blankline + && tok->level == 0 + /* There was a NEWLINE after ASYNC DEF, + so we're past the signature. */ + && tok->async_def_nl + /* Current indentation level is less than where + the async function was defined */ + && tok->async_def_indent >= tok->indent) { - /* The top function on the stack did have a NEWLINE - token, but didn't have an INDENT. That means that - it's a one-line function and it should now be removed - from the stack. */ - if (tok->deftypestack[tok->def] & DEFTYPE_ASYNC) { - tok->def_in_async--; - assert(tok->def_in_async >= 0); - } - tok->def--; - assert(tok->def >= 0); + tok->async_def = 0; + tok->async_def_indent = 0; + tok->async_def_nl = 0; } again: @@ -1528,38 +1505,27 @@ *p_start = tok->start; *p_end = tok->cur; - tok_len = tok->cur - tok->start; - if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { - /* The current token is 'def'. */ - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; + /* async/await parsing block. */ + if (tok->cur - tok->start == 5) { + /* Current token length is 5. */ + if (tok->async_def) { + /* We're inside an 'async def' function. */ + if (memcmp(tok->start, "async", 5) == 0) + return ASYNC; + if (memcmp(tok->start, "await", 5) == 0) + return AWAIT; } + else if (memcmp(tok->start, "async", 5) == 0) { + /* The current token is 'async'. + Look ahead one token.*/ - /* Advance defs stack. */ - tok->def++; - tok->defstack[tok->def] = tok->indent; + struct tok_state ahead_tok; + char *ahead_tok_start = NULL, *ahead_tok_end = NULL; + int ahead_tok_kind; - if (tok->def_async_behind) { - /* The previous token was 'async'. */ - tok->def_async_behind = 0; - tok->deftypestack[tok->def] = DEFTYPE_ASYNC; - tok->def_in_async++; - } - else { - /* This is a regular function (not async def). */ - tok->deftypestack[tok->def] = 0; - } - } - else if (tok_len == 5) { - if (memcmp(tok->start, "async", 5) == 0) { - /* The current token is 'async'. */ memcpy(&ahead_tok, tok, sizeof(ahead_tok)); - - /* Try to look ahead one token. */ ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start, - &ahead_top_end); + &ahead_tok_end); if (ahead_tok_kind == NAME && ahead_tok.cur - ahead_tok.start == 3 @@ -1567,22 +1533,10 @@ { /* The next token is going to be 'def', so instead of returning 'async' NAME token, we return ASYNC. */ - tok->def_async_behind = 1; + tok->async_def_indent = tok->indent; + tok->async_def = 1; return ASYNC; } - else if (tok->def_in_async) - { - /* We're inside an 'async def' function, so we treat - 'async' token as ASYNC, instead of NAME. */ - return ASYNC; - } - - } - else if (memcmp(tok->start, "await", 5) == 0 && tok->def_in_async) - { - /* We're inside an 'async def' function, so we treat - 'await' token as AWAIT, instead of NAME. */ - return AWAIT; } } @@ -1597,12 +1551,10 @@ *p_start = tok->start; *p_end = tok->cur - 1; /* Leave '\n' out of the string */ tok->cont_line = 0; - if (tok->def) { - /* Mark the top function on the stack that it had - at least one NEWLINE. That will help us to - distinguish one-line functions from functions - with multiple statements. */ - tok->deftypestack[tok->def] |= DEFTYPE_HAS_NL; + if (tok->async_def) { + /* We're somewhere inside an 'async def' function, and + we've encountered a NEWLINE after its signature. */ + tok->async_def_nl = 1; } return NEWLINE; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -66,21 +66,12 @@ const char* str; const char* input; /* Tokenizer's newline translated copy of the string. */ - /* `def*` fields are for parsing async/await in a backwards compatible - way. They should be removed in 3.7, when they will become - regular constants. See PEP 492 for more details. */ - int defstack[MAXINDENT]; /* Stack of funcs & indents where they - were defined. */ - int deftypestack[MAXINDENT]; /* Stack of func flags, see DEFTYPE_* - constants. */ - int def; /* Length of stack of func types/flags. */ - int def_async_behind; /* 1 if there was an 'async' token before - a 'def' token. */ - int def_in_async; /* Counter of how deep 'async def's - are nested. If greater than 0, - we are somewhere in an 'async def' - body, so 'async' and 'await' should - be parsed as keywords.*/ + /* async/await related fields; can be removed in 3.7 when async and await + become normal keywords. */ + int async_def; /* =1 if tokens are inside an 'async def' body. */ + int async_def_indent; /* Indentation level of the outermost 'async def'. */ + int async_def_nl; /* =1 if the outermost 'async def' had at least one + NEWLINE token after it. */ }; extern struct tok_state *PyTokenizer_FromString(const char *, int); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 14:59:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 12:59:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Njky?= =?utf-8?q?=3A_Add_more_tests_for_types=2Ecoroutine?= Message-ID: <20150723125929.37654.72556@psf.io> https://hg.python.org/cpython/rev/636ce05ea8f6 changeset: 97019:636ce05ea8f6 branch: 3.5 parent: 97017:d03f86e41066 user: Yury Selivanov date: Thu Jul 23 15:58:37 2015 +0300 summary: Issue #24692: Add more tests for types.coroutine files: Lib/test/test_types.py | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 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 @@ -1213,6 +1213,10 @@ return aw self.assertIs(aw, foo()) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(aw, foo()) + def test_async_def(self): # Test that types.coroutine passes 'async def' coroutines # without modification @@ -1226,12 +1230,13 @@ self.assertIs(decorated_foo.__code__, foo_code) foo_coro = foo() - @types.coroutine def bar(): return foo_coro - coro = bar() - self.assertIs(foo_coro, coro) - self.assertEqual(coro.cr_code.co_flags, foo_flags) - coro.close() + for _ in range(2): + bar = types.coroutine(bar) + coro = bar() + self.assertIs(foo_coro, coro) + self.assertEqual(coro.cr_code.co_flags, foo_flags) + coro.close() def test_duck_coro(self): class CoroLike: @@ -1447,6 +1452,10 @@ with self.assertRaisesRegex(Exception, 'ham'): wrapper.throw(Exception, Exception('ham')) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(foo().__await__(), gen) + def test_returning_itercoro(self): @types.coroutine def gen(): @@ -1460,9 +1469,14 @@ self.assertIs(foo(), gencoro) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(foo(), gencoro) + def test_genfunc(self): def gen(): yield self.assertIs(types.coroutine(gen), gen) + self.assertIs(types.coroutine(types.coroutine(gen)), gen) self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE) self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 14:59:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 12:59:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChJc3N1ZSAjMjQ2OTIp?= Message-ID: <20150723125929.37530.47852@psf.io> https://hg.python.org/cpython/rev/3f3e398bcd3e changeset: 97020:3f3e398bcd3e parent: 97018:3f8048926690 parent: 97019:636ce05ea8f6 user: Yury Selivanov date: Thu Jul 23 15:58:57 2015 +0300 summary: Merge 3.5 (Issue #24692) files: Lib/test/test_types.py | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 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 @@ -1213,6 +1213,10 @@ return aw self.assertIs(aw, foo()) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(aw, foo()) + def test_async_def(self): # Test that types.coroutine passes 'async def' coroutines # without modification @@ -1226,12 +1230,13 @@ self.assertIs(decorated_foo.__code__, foo_code) foo_coro = foo() - @types.coroutine def bar(): return foo_coro - coro = bar() - self.assertIs(foo_coro, coro) - self.assertEqual(coro.cr_code.co_flags, foo_flags) - coro.close() + for _ in range(2): + bar = types.coroutine(bar) + coro = bar() + self.assertIs(foo_coro, coro) + self.assertEqual(coro.cr_code.co_flags, foo_flags) + coro.close() def test_duck_coro(self): class CoroLike: @@ -1447,6 +1452,10 @@ with self.assertRaisesRegex(Exception, 'ham'): wrapper.throw(Exception, Exception('ham')) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(foo().__await__(), gen) + def test_returning_itercoro(self): @types.coroutine def gen(): @@ -1460,9 +1469,14 @@ self.assertIs(foo(), gencoro) + # decorate foo second time + foo = types.coroutine(foo) + self.assertIs(foo(), gencoro) + def test_genfunc(self): def gen(): yield self.assertIs(types.coroutine(gen), gen) + self.assertIs(types.coroutine(types.coroutine(gen)), gen) self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE) self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 16:10:49 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 14:10:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDg1?= =?utf-8?q?=3A_Revert_backwards_compatibility_breaking_changes_of_=2321217?= =?utf-8?q?=2E?= Message-ID: <20150723141048.37654.68815@psf.io> https://hg.python.org/cpython/rev/4e42a62d5648 changeset: 97021:4e42a62d5648 branch: 3.5 parent: 97019:636ce05ea8f6 user: Yury Selivanov date: Thu Jul 23 17:10:00 2015 +0300 summary: Issue #24485: Revert backwards compatibility breaking changes of #21217. files: Lib/inspect.py | 20 ++------------------ Lib/test/inspect_fodder2.py | 7 +++++++ Lib/test/test_inspect.py | 5 +++++ Misc/NEWS | 4 ---- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -902,14 +902,6 @@ pass return lines[:blockfinder.last] -def _line_number_helper(code_obj, lines, lnum): - """Return a list of source lines and starting line number for a code object. - - The arguments must be a code object with lines and lnum from findsource. - """ - _, end_line = list(dis.findlinestarts(code_obj))[-1] - return lines[lnum:end_line], lnum + 1 - def getsourcelines(object): """Return a list of source lines and starting line number for an object. @@ -921,16 +913,8 @@ object = unwrap(object) lines, lnum = findsource(object) - if ismodule(object): - return lines, 0 - elif iscode(object): - return _line_number_helper(object, lines, lnum) - elif isfunction(object): - return _line_number_helper(object.__code__, lines, lnum) - elif ismethod(object): - return _line_number_helper(object.__func__.__code__, lines, lnum) - else: - return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): return lines, 0 + else: return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py --- a/Lib/test/inspect_fodder2.py +++ b/Lib/test/inspect_fodder2.py @@ -130,3 +130,10 @@ @decorator def real(): return 20 + +#line 134 +class cls135: + def func136(): + def func137(): + never_reached1 + never_reached2 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 @@ -464,6 +464,7 @@ def test_getsource_unwrap(self): self.assertSourceEqual(mod2.real, 130, 132) + @unittest.expectedFailure def test_decorator_with_lambda(self): self.assertSourceEqual(mod2.func114, 113, 115) @@ -563,6 +564,10 @@ def test_getsource_on_method(self): self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) + def test_nested_func(self): + self.assertSourceEqual(mod2.cls135.func136, 136, 139) + + class TestNoEOL(GetSourceBase): def setUp(self): self.tempdir = TESTFN + '_dir' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -551,10 +551,6 @@ - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. -- Issue #21217: inspect.getsourcelines() now tries to compute the start and end - lines from the code object, fixing an issue when a lambda function is used as - decorator argument. Patch by Thomas Ballinger and Allison Kaptur. - - Issue #24521: Fix possible integer overflows in the pickle module. - Issue #22931: Allow '[' and ']' in cookie values. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 16:10:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 14:10:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZXMgIzIxMjE3LCAjMjQ0ODUpLg==?= Message-ID: <20150723141049.47945.18563@psf.io> https://hg.python.org/cpython/rev/98a2bbf2cce2 changeset: 97022:98a2bbf2cce2 parent: 97020:3f3e398bcd3e parent: 97021:4e42a62d5648 user: Yury Selivanov date: Thu Jul 23 17:10:24 2015 +0300 summary: Merge 3.5 (issues #21217, #24485). files: Lib/inspect.py | 20 ++------------------ Lib/test/inspect_fodder2.py | 7 +++++++ Lib/test/test_inspect.py | 5 +++++ Misc/NEWS | 4 ---- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -902,14 +902,6 @@ pass return lines[:blockfinder.last] -def _line_number_helper(code_obj, lines, lnum): - """Return a list of source lines and starting line number for a code object. - - The arguments must be a code object with lines and lnum from findsource. - """ - _, end_line = list(dis.findlinestarts(code_obj))[-1] - return lines[lnum:end_line], lnum + 1 - def getsourcelines(object): """Return a list of source lines and starting line number for an object. @@ -921,16 +913,8 @@ object = unwrap(object) lines, lnum = findsource(object) - if ismodule(object): - return lines, 0 - elif iscode(object): - return _line_number_helper(object, lines, lnum) - elif isfunction(object): - return _line_number_helper(object.__code__, lines, lnum) - elif ismethod(object): - return _line_number_helper(object.__func__.__code__, lines, lnum) - else: - return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): return lines, 0 + else: return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py --- a/Lib/test/inspect_fodder2.py +++ b/Lib/test/inspect_fodder2.py @@ -130,3 +130,10 @@ @decorator def real(): return 20 + +#line 134 +class cls135: + def func136(): + def func137(): + never_reached1 + never_reached2 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 @@ -464,6 +464,7 @@ def test_getsource_unwrap(self): self.assertSourceEqual(mod2.real, 130, 132) + @unittest.expectedFailure def test_decorator_with_lambda(self): self.assertSourceEqual(mod2.func114, 113, 115) @@ -563,6 +564,10 @@ def test_getsource_on_method(self): self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) + def test_nested_func(self): + self.assertSourceEqual(mod2.cls135.func136, 136, 139) + + class TestNoEOL(GetSourceBase): def setUp(self): self.tempdir = TESTFN + '_dir' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -576,10 +576,6 @@ - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. -- Issue #21217: inspect.getsourcelines() now tries to compute the start and end - lines from the code object, fixing an issue when a lambda function is used as - decorator argument. Patch by Thomas Ballinger and Allison Kaptur. - - Issue #24521: Fix possible integer overflows in the pickle module. - Issue #22931: Allow '[' and ']' in cookie values. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 16:36:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 14:36:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313248=3A_Remove_i?= =?utf-8?q?nspect=2Egetargspec_from_3=2E6_=28deprecated_from_3=2E0=29?= Message-ID: <20150723143634.51996.95929@psf.io> https://hg.python.org/cpython/rev/a565aad5d6e1 changeset: 97023:a565aad5d6e1 user: Yury Selivanov date: Thu Jul 23 17:36:02 2015 +0300 summary: Issue #13248: Remove inspect.getargspec from 3.6 (deprecated from 3.0) files: Doc/library/inspect.rst | 18 ------------ Doc/whatsnew/3.6.rst | 3 +- Lib/inspect.py | 25 ----------------- Lib/test/test_inspect.py | 40 +++------------------------ 4 files changed, 7 insertions(+), 79 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -805,24 +805,6 @@ classes using multiple inheritance and their descendants will appear multiple times. - -.. function:: getargspec(func) - - Get the names and default values of a Python function's arguments. A - :term:`named tuple` ``ArgSpec(args, varargs, keywords, defaults)`` is - returned. *args* is a list of the argument names. *varargs* and *keywords* - are the names of the ``*`` and ``**`` arguments or ``None``. *defaults* is a - tuple of default argument values or ``None`` if there are no default - arguments; if this tuple has *n* elements, they correspond to the last - *n* elements listed in *args*. - - .. deprecated:: 3.0 - Use :func:`signature` and - :ref:`Signature Object `, which provide a - better introspecting API for callables. This function will be removed - in Python 3.6. - - .. function:: getfullargspec(func) Get the names and default values of a Python function's arguments. A diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -145,7 +145,8 @@ API and Feature Removals ------------------------ -* None yet. +* ``inspect.getargspec()`` was removed (was deprecated since CPython 3.0). + :func:`inspect.getfullargspec` is an almost drop in replacement. Porting to Python 3.6 diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1002,31 +1002,6 @@ varkw = co.co_varnames[nargs] return args, varargs, kwonlyargs, varkw - -ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') - -def getargspec(func): - """Get the names and default values of a function's arguments. - - A tuple of four things is returned: (args, varargs, keywords, defaults). - 'args' is a list of the argument names, including keyword-only argument names. - 'varargs' and 'keywords' are the names of the * and ** arguments or None. - 'defaults' is an n-tuple of the default values of the last n arguments. - - Use the getfullargspec() API for Python 3 code, as annotations - and keyword arguments are supported. getargspec() will raise ValueError - if the func has either annotations or keyword arguments. - """ - warnings.warn("inspect.getargspec() is deprecated, " - "use inspect.signature() instead", DeprecationWarning, - stacklevel=2) - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ - getfullargspec(func) - if kwonlyargs or ann: - raise ValueError("Function has keyword-only arguments or annotations" - ", use getfullargspec() API which can support them") - return ArgSpec(args, varargs, varkw, defaults) - FullArgSpec = namedtuple('FullArgSpec', 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') 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 @@ -629,18 +629,6 @@ got = inspect.getmro(D) self.assertEqual(expected, got) - def assertArgSpecEquals(self, routine, args_e, varargs_e=None, - varkw_e=None, defaults_e=None, formatted=None): - with self.assertWarns(DeprecationWarning): - args, varargs, varkw, defaults = inspect.getargspec(routine) - self.assertEqual(args, args_e) - self.assertEqual(varargs, varargs_e) - self.assertEqual(varkw, varkw_e) - self.assertEqual(defaults, defaults_e) - if formatted is not None: - self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults), - formatted) - def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None, varkw_e=None, defaults_e=None, kwonlyargs_e=[], kwonlydefaults_e=None, @@ -659,23 +647,6 @@ kwonlyargs, kwonlydefaults, ann), formatted) - def test_getargspec(self): - self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)') - - self.assertArgSpecEquals(mod.spam, - ['a', 'b', 'c', 'd', 'e', 'f'], - 'g', 'h', (3, 4, 5), - '(a, b, c, d=3, e=4, f=5, *g, **h)') - - self.assertRaises(ValueError, self.assertArgSpecEquals, - mod2.keyworded, []) - - self.assertRaises(ValueError, self.assertArgSpecEquals, - mod2.annotated, []) - self.assertRaises(ValueError, self.assertArgSpecEquals, - mod2.keyword_only_arg, []) - - def test_getfullargspec(self): self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1', kwonlyargs_e=['arg2'], @@ -689,20 +660,19 @@ kwonlyargs_e=['arg'], formatted='(*, arg)') - def test_argspec_api_ignores_wrapped(self): + def test_fullargspec_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)') + self.assertFullArgSpecEquals(f, ['self', 'x', 'y'], + formatted='(self, x, y)') class C: @functools.wraps(mod.spam) def ham(self, x, y): @@ -780,11 +750,11 @@ with self.assertRaises(TypeError): inspect.getfullargspec(builtin) - def test_getargspec_method(self): + def test_getfullargspec_method(self): class A(object): def m(self): pass - self.assertArgSpecEquals(A.m, ['self']) + self.assertFullArgSpecEquals(A.m, ['self']) def test_classify_newstyle(self): class A(object): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 16:49:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 14:49:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313248=3A_Remove_i?= =?utf-8?q?nspect=2Egetmoduleinfo=28=29_from_3=2E6_=28deprecated_in_3=2E3?= =?utf-8?q?=29?= Message-ID: <20150723144935.8502.24885@psf.io> https://hg.python.org/cpython/rev/558199e060fd changeset: 97024:558199e060fd user: Yury Selivanov date: Thu Jul 23 17:49:00 2015 +0300 summary: Issue #13248: Remove inspect.getmoduleinfo() from 3.6 (deprecated in 3.3) files: Doc/library/inspect.rst | 21 +-------------------- Doc/whatsnew/3.6.rst | 4 ++++ Lib/inspect.py | 17 ----------------- 3 files changed, 5 insertions(+), 37 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -227,24 +227,6 @@ listed in the metaclass' custom :meth:`__dir__`. -.. function:: getmoduleinfo(path) - - Returns a :term:`named tuple` ``ModuleInfo(name, suffix, mode, module_type)`` - of values that describe how Python will interpret the file identified by - *path* if it is a module, or ``None`` if it would not be identified as a - module. In that tuple, *name* is the name of the module without the name of - any enclosing package, *suffix* is the trailing part of the file name (which - may not be a dot-delimited extension), *mode* is the :func:`open` mode that - would be used (``'r'`` or ``'rb'``), and *module_type* is an integer giving - the type of the module. *module_type* will have a value which can be - compared to the constants defined in the :mod:`imp` module; see the - documentation for that module for more information on module types. - - .. deprecated:: 3.3 - You may check the file path's suffix against the supported suffixes - listed in :mod:`importlib.machinery` to infer the same information. - - .. function:: getmodulename(path) Return the name of the module named by the file *path*, without including the @@ -258,8 +240,7 @@ still return ``None``. .. versionchanged:: 3.3 - This function is now based directly on :mod:`importlib` rather than the - deprecated :func:`getmoduleinfo`. + The function is based directly on :mod:`importlib`. .. function:: ismodule(object) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -148,6 +148,10 @@ * ``inspect.getargspec()`` was removed (was deprecated since CPython 3.0). :func:`inspect.getfullargspec` is an almost drop in replacement. +* ``inspect.getmoduleinfo`` was removed (was deprecated since CPython 3.3). + :func:`inspect.getmodulename` should be used for obtaining the module + name for a given path. + Porting to Python 3.6 ===================== diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -623,23 +623,6 @@ raise TypeError('{!r} is not a module, class, method, ' 'function, traceback, frame, or code object'.format(object)) -ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type') - -def getmoduleinfo(path): - """Get the module name, suffix, mode, and module type for a given file.""" - warnings.warn('inspect.getmoduleinfo() is deprecated', DeprecationWarning, - 2) - with warnings.catch_warnings(): - warnings.simplefilter('ignore', PendingDeprecationWarning) - import imp - filename = os.path.basename(path) - suffixes = [(-len(suffix), suffix, mode, mtype) - for suffix, mode, mtype in imp.get_suffixes()] - suffixes.sort() # try longest suffixes first, in case they overlap - for neglen, suffix, mode, mtype in suffixes: - if filename[neglen:] == suffix: - return ModuleInfo(filename[:neglen], suffix, mode, mtype) - def getmodulename(path): """Return the module name for a given file, or None.""" fname = os.path.basename(path) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 16:52:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Jul 2015 14:52:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Sync_NEWS_=28re_removed_in?= =?utf-8?q?spect=2Egetargspec_and_inspect=2Egetmoduleinfo=29?= Message-ID: <20150723145226.37411.22810@psf.io> https://hg.python.org/cpython/rev/bdb23b2dbd04 changeset: 97025:bdb23b2dbd04 user: Yury Selivanov date: Thu Jul 23 17:51:34 2015 +0300 summary: Sync NEWS (re removed inspect.getargspec and inspect.getmoduleinfo) files: Doc/whatsnew/3.6.rst | 2 +- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -148,7 +148,7 @@ * ``inspect.getargspec()`` was removed (was deprecated since CPython 3.0). :func:`inspect.getfullargspec` is an almost drop in replacement. -* ``inspect.getmoduleinfo`` was removed (was deprecated since CPython 3.3). +* ``inspect.getmoduleinfo()`` was removed (was deprecated since CPython 3.3). :func:`inspect.getmodulename` should be used for obtaining the module name for a given path. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ - Issue #23661: unittest.mock side_effects can now be exceptions again. This was a regression vs Python 3.4. Patch from Ignacio Rossi +- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo + functions. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 17:49:26 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 15:49:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321750=3A_Further_fixup_to_be_styled_like_other_?= =?utf-8?q?mock_APIs=2E?= Message-ID: <20150723154926.24758.29884@psf.io> https://hg.python.org/cpython/rev/c896ab62ac75 changeset: 97028:c896ab62ac75 parent: 97025:bdb23b2dbd04 parent: 97027:b30fc1de006c user: Robert Collins date: Fri Jul 24 03:49:01 2015 +1200 summary: Issue #21750: Further fixup to be styled like other mock APIs. files: Doc/library/unittest.mock.rst | 8 +- Lib/unittest/mock.py | 79 +++++++------ Lib/unittest/test/testmock/testmock.py | 24 ++++- Lib/unittest/test/testmock/testwith.py | 4 +- 4 files changed, 73 insertions(+), 42 deletions(-) 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 @@ -2037,9 +2037,11 @@ :meth:`~io.IOBase.readline`, and :meth:`~io.IOBase.readlines` methods of the file handle to return. Calls to those methods will take data from *read_data* until it is depleted. The mock of these methods is pretty - simplistic. If you need more control over the data that you are feeding to - the tested code you will need to customize this mock for yourself. - *read_data* is an empty string by default. + simplistic: every time the *mock* is called, the *read_data* is rewound to + the start. If you need more control over the data that you are feeding to + the tested code you will need to customize this mock for yourself. When that + is insufficient, one of the in-memory filesystem packages on `PyPI + `_ can offer a realistic filesystem for testing. Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2299,6 +2299,24 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_state[0]) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_state[0]) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _state[0]: + yield line + + global file_spec if file_spec is None: import _io @@ -2307,42 +2325,31 @@ if mock is None: mock = MagicMock(name='open', spec=open) - def make_handle(*args, **kwargs): - # Arg checking is handled by __call__ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - _check_and_set_parent(mock, handle, None, '()') - return handle - - mock.side_effect = make_handle + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _state = [_iterate_read_data(read_data), None] + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + handle.readlines.side_effect = _readlines_side_effect + + def reset_data(*args, **kwargs): + _state[0] = _iterate_read_data(read_data) + if handle.readline.side_effect == _state[1]: + # Only reset the side effect if the user hasn't overridden it. + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + return DEFAULT + + mock.side_effect = reset_data + mock.return_value = handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1,5 +1,6 @@ import copy import sys +import tempfile import unittest from unittest.test.testmock.support import is_instance @@ -1374,8 +1375,29 @@ def test_mock_open_reuse_issue_21750(self): mocked_open = mock.mock_open(read_data='data') f1 = mocked_open('a-name') + f1_data = f1.read() f2 = mocked_open('another-name') - self.assertEqual(f1.read(), f2.read()) + f2_data = f2.read() + self.assertEqual(f1_data, f2_data) + + def test_mock_open_write(self): + # Test exception in file writing write() + mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV')) + with mock.patch('tempfile.NamedTemporaryFile', mock_namedtemp): + mock_filehandle = mock_namedtemp.return_value + mock_write = mock_filehandle.write + mock_write.side_effect = OSError('Test 2 Error') + def attempt(): + tempfile.NamedTemporaryFile().write('asd') + self.assertRaises(OSError, attempt) + + def test_mock_open_alter_readline(self): + mopen = mock.mock_open(read_data='foo\nbarn') + mopen.return_value.readline.side_effect = lambda *args:'abc' + first = mopen().readline() + second = mopen().readline() + self.assertEqual('abc', first) + self.assertEqual('abc', second) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,6 +141,7 @@ def test_mock_open_context_manager(self): mock = mock_open() + handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -148,8 +149,7 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - # mock_open.return_value is no longer static, because - # readline support requires that it mutate state + self.assertIs(f, handle) def test_mock_open_context_manager_multiple_times(self): mock = mock_open() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 17:49:26 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 15:49:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNzUw?= =?utf-8?q?=3A_Further_fixup_to_be_styled_like_other_mock_APIs=2E?= Message-ID: <20150723154926.13865.29969@psf.io> https://hg.python.org/cpython/rev/83e28ee348bf changeset: 97026:83e28ee348bf branch: 3.4 parent: 97009:f574da88c3be user: Robert Collins date: Fri Jul 24 03:48:20 2015 +1200 summary: Issue #21750: Further fixup to be styled like other mock APIs. files: Doc/library/unittest.mock.rst | 8 +- Lib/unittest/mock.py | 79 +++++++------ Lib/unittest/test/testmock/testmock.py | 24 ++++- Lib/unittest/test/testmock/testwith.py | 4 +- 4 files changed, 73 insertions(+), 42 deletions(-) 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 @@ -1995,9 +1995,11 @@ :meth:`~io.IOBase.readline`, and :meth:`~io.IOBase.readlines` methods of the file handle to return. Calls to those methods will take data from *read_data* until it is depleted. The mock of these methods is pretty - simplistic. If you need more control over the data that you are feeding to - the tested code you will need to customize this mock for yourself. - *read_data* is an empty string by default. + simplistic: every time the *mock* is called, the *read_data* is rewound to + the start. If you need more control over the data that you are feeding to + the tested code you will need to customize this mock for yourself. When that + is insufficient, one of the in-memory filesystem packages on `PyPI + `_ can offer a realistic filesystem for testing. Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2278,6 +2278,24 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_state[0]) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_state[0]) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _state[0]: + yield line + + global file_spec if file_spec is None: import _io @@ -2286,42 +2304,31 @@ if mock is None: mock = MagicMock(name='open', spec=open) - def make_handle(*args, **kwargs): - # Arg checking is handled by __call__ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - _check_and_set_parent(mock, handle, None, '()') - return handle - - mock.side_effect = make_handle + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _state = [_iterate_read_data(read_data), None] + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + handle.readlines.side_effect = _readlines_side_effect + + def reset_data(*args, **kwargs): + _state[0] = _iterate_read_data(read_data) + if handle.readline.side_effect == _state[1]: + # Only reset the side effect if the user hasn't overridden it. + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + return DEFAULT + + mock.side_effect = reset_data + mock.return_value = handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1,5 +1,6 @@ import copy import sys +import tempfile import unittest from unittest.test.testmock.support import is_instance @@ -1329,8 +1330,29 @@ def test_mock_open_reuse_issue_21750(self): mocked_open = mock.mock_open(read_data='data') f1 = mocked_open('a-name') + f1_data = f1.read() f2 = mocked_open('another-name') - self.assertEqual(f1.read(), f2.read()) + f2_data = f2.read() + self.assertEqual(f1_data, f2_data) + + def test_mock_open_write(self): + # Test exception in file writing write() + mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV')) + with mock.patch('tempfile.NamedTemporaryFile', mock_namedtemp): + mock_filehandle = mock_namedtemp.return_value + mock_write = mock_filehandle.write + mock_write.side_effect = OSError('Test 2 Error') + def attempt(): + tempfile.NamedTemporaryFile().write('asd') + self.assertRaises(OSError, attempt) + + def test_mock_open_alter_readline(self): + mopen = mock.mock_open(read_data='foo\nbarn') + mopen.return_value.readline.side_effect = lambda *args:'abc' + first = mopen().readline() + second = mopen().readline() + self.assertEqual('abc', first) + self.assertEqual('abc', second) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,6 +141,7 @@ def test_mock_open_context_manager(self): mock = mock_open() + handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -148,8 +149,7 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - # mock_open.return_value is no longer static, because - # readline support requires that it mutate state + self.assertIs(f, handle) def test_mock_open_context_manager_multiple_times(self): mock = mock_open() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 17:49:26 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 15:49:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321750=3A_Further_fixup_to_be_styled_like_other_mock_A?= =?utf-8?q?PIs=2E?= Message-ID: <20150723154926.47921.73876@psf.io> https://hg.python.org/cpython/rev/b30fc1de006c changeset: 97027:b30fc1de006c branch: 3.5 parent: 97021:4e42a62d5648 parent: 97026:83e28ee348bf user: Robert Collins date: Fri Jul 24 03:48:45 2015 +1200 summary: Issue #21750: Further fixup to be styled like other mock APIs. files: Doc/library/unittest.mock.rst | 8 +- Lib/unittest/mock.py | 79 +++++++------ Lib/unittest/test/testmock/testmock.py | 24 ++++- Lib/unittest/test/testmock/testwith.py | 4 +- 4 files changed, 73 insertions(+), 42 deletions(-) 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 @@ -2037,9 +2037,11 @@ :meth:`~io.IOBase.readline`, and :meth:`~io.IOBase.readlines` methods of the file handle to return. Calls to those methods will take data from *read_data* until it is depleted. The mock of these methods is pretty - simplistic. If you need more control over the data that you are feeding to - the tested code you will need to customize this mock for yourself. - *read_data* is an empty string by default. + simplistic: every time the *mock* is called, the *read_data* is rewound to + the start. If you need more control over the data that you are feeding to + the tested code you will need to customize this mock for yourself. When that + is insufficient, one of the in-memory filesystem packages on `PyPI + `_ can offer a realistic filesystem for testing. Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2299,6 +2299,24 @@ `read_data` is a string for the `read` methoddline`, and `readlines` of the file handle to return. This is an empty string by default. """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_state[0]) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return ''.join(_state[0]) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _state[0]: + yield line + + global file_spec if file_spec is None: import _io @@ -2307,42 +2325,31 @@ if mock is None: mock = MagicMock(name='open', spec=open) - def make_handle(*args, **kwargs): - # Arg checking is handled by __call__ - def _readlines_side_effect(*args, **kwargs): - if handle.readlines.return_value is not None: - return handle.readlines.return_value - return list(_data) - - def _read_side_effect(*args, **kwargs): - if handle.read.return_value is not None: - return handle.read.return_value - return ''.join(_data) - - def _readline_side_effect(): - if handle.readline.return_value is not None: - while True: - yield handle.readline.return_value - for line in _data: - yield line - - handle = MagicMock(spec=file_spec) - handle.__enter__.return_value = handle - - _data = _iterate_read_data(read_data) - - handle.write.return_value = None - handle.read.return_value = None - handle.readline.return_value = None - handle.readlines.return_value = None - - handle.read.side_effect = _read_side_effect - handle.readline.side_effect = _readline_side_effect() - handle.readlines.side_effect = _readlines_side_effect - _check_and_set_parent(mock, handle, None, '()') - return handle - - mock.side_effect = make_handle + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _state = [_iterate_read_data(read_data), None] + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + handle.readlines.side_effect = _readlines_side_effect + + def reset_data(*args, **kwargs): + _state[0] = _iterate_read_data(read_data) + if handle.readline.side_effect == _state[1]: + # Only reset the side effect if the user hasn't overridden it. + _state[1] = _readline_side_effect() + handle.readline.side_effect = _state[1] + return DEFAULT + + mock.side_effect = reset_data + mock.return_value = handle return mock diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1,5 +1,6 @@ import copy import sys +import tempfile import unittest from unittest.test.testmock.support import is_instance @@ -1374,8 +1375,29 @@ def test_mock_open_reuse_issue_21750(self): mocked_open = mock.mock_open(read_data='data') f1 = mocked_open('a-name') + f1_data = f1.read() f2 = mocked_open('another-name') - self.assertEqual(f1.read(), f2.read()) + f2_data = f2.read() + self.assertEqual(f1_data, f2_data) + + def test_mock_open_write(self): + # Test exception in file writing write() + mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV')) + with mock.patch('tempfile.NamedTemporaryFile', mock_namedtemp): + mock_filehandle = mock_namedtemp.return_value + mock_write = mock_filehandle.write + mock_write.side_effect = OSError('Test 2 Error') + def attempt(): + tempfile.NamedTemporaryFile().write('asd') + self.assertRaises(OSError, attempt) + + def test_mock_open_alter_readline(self): + mopen = mock.mock_open(read_data='foo\nbarn') + mopen.return_value.readline.side_effect = lambda *args:'abc' + first = mopen().readline() + second = mopen().readline() + self.assertEqual('abc', first) + self.assertEqual('abc', second) def test_mock_parents(self): for Klass in Mock, MagicMock: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -141,6 +141,7 @@ def test_mock_open_context_manager(self): mock = mock_open() + handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() @@ -148,8 +149,7 @@ expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) - # mock_open.return_value is no longer static, because - # readline support requires that it mutate state + self.assertIs(f, handle) def test_mock_open_context_manager_multiple_times(self): mock = mock_open() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 18:11:50 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 16:11:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Add_versionchanged_information_for_mock=5Fopen=2E?= Message-ID: <20150723161149.24780.44522@psf.io> https://hg.python.org/cpython/rev/732de5ba1f2b changeset: 97030:732de5ba1f2b branch: 3.5 parent: 97027:b30fc1de006c parent: 97029:13af5c3414b5 user: Robert Collins date: Fri Jul 24 04:10:27 2015 +1200 summary: Add versionchanged information for mock_open. files: Doc/library/unittest.mock.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) 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 @@ -2043,6 +2043,14 @@ is insufficient, one of the in-memory filesystem packages on `PyPI `_ can offer a realistic filesystem for testing. + .. versionchanged:: 3.4 + Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. + The mock of :meth:`~io.IOBase.read` changed to consume *read_data* rather + than returning it on each call. + + .. versionchanged:: 3.5 + *read_data* is now reset on each call to the *mock*. + Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 18:11:50 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 16:11:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Add_versionchanged_information_for_mock=5Fopen=2E?= Message-ID: <20150723161149.11644.5439@psf.io> https://hg.python.org/cpython/rev/262c43c71927 changeset: 97031:262c43c71927 parent: 97028:c896ab62ac75 parent: 97030:732de5ba1f2b user: Robert Collins date: Fri Jul 24 04:10:49 2015 +1200 summary: Add versionchanged information for mock_open. files: Doc/library/unittest.mock.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) 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 @@ -2043,6 +2043,14 @@ is insufficient, one of the in-memory filesystem packages on `PyPI `_ can offer a realistic filesystem for testing. + .. versionchanged:: 3.4 + Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. + The mock of :meth:`~io.IOBase.read` changed to consume *read_data* rather + than returning it on each call. + + .. versionchanged:: 3.5 + *read_data* is now reset on each call to the *mock*. + Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 23 18:11:52 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 23 Jul 2015 16:11:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Add_versioncha?= =?utf-8?q?nged_information_for_mock=5Fopen=2E?= Message-ID: <20150723161149.47947.26074@psf.io> https://hg.python.org/cpython/rev/13af5c3414b5 changeset: 97029:13af5c3414b5 branch: 3.4 parent: 97026:83e28ee348bf user: Robert Collins date: Fri Jul 24 04:09:59 2015 +1200 summary: Add versionchanged information for mock_open. files: Doc/library/unittest.mock.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) 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 @@ -2001,6 +2001,14 @@ is insufficient, one of the in-memory filesystem packages on `PyPI `_ can offer a realistic filesystem for testing. + .. versionchanged:: 3.4 + Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. + The mock of :meth:`~io.IOBase.read` changed to consume *read_data* rather + than returning it on each call. + + .. versionchanged:: 3.4.4 + *read_data* is now reset on each call to the *mock*. + Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 06:00:12 2015 From: python-checkins at python.org (meador.inge) Date: Fri, 24 Jul 2015 04:00:12 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDg1?= =?utf-8?q?=3A_Function_source_inspection_fails_on_closures=2E?= Message-ID: <20150724040011.13851.71452@psf.io> https://hg.python.org/cpython/rev/5400e21e92a7 changeset: 97032:5400e21e92a7 branch: 3.5 parent: 97030:732de5ba1f2b user: Meador Inge date: Thu Jul 23 22:49:37 2015 -0500 summary: Issue #24485: Function source inspection fails on closures. The fix for Issue #21217 introduced a regression that caused `inspect.getsource` to return incorrect results on nested functions. The root cause of the regression was due to switching the implementation to analyze the underlying bytecode instead of the source code. This commit switches things back to analyzing the source code in a more complete way. The original bug and the regression are both fixed by the new source code analysis. files: Lib/inspect.py | 26 ++++++++++++++++++++++---- Lib/test/test_inspect.py | 1 - Misc/NEWS | 7 +++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -859,21 +859,37 @@ self.islambda = False self.started = False self.passline = False + self.indecorator = False + self.decoratorhasargs = False self.last = 1 def tokeneater(self, type, token, srowcol, erowcol, line): - if not self.started: + if not self.started and not self.indecorator: + # skip any decorators + if token == "@": + self.indecorator = True # look for the first "def", "class" or "lambda" - if token in ("def", "class", "lambda"): + elif token in ("def", "class", "lambda"): if token == "lambda": self.islambda = True self.started = True self.passline = True # skip to the end of the line + elif token == "(": + if self.indecorator: + self.decoratorhasargs = True + elif token == ")": + if self.indecorator: + self.indecorator = False + self.decoratorhasargs = False elif type == tokenize.NEWLINE: self.passline = False # stop skipping when a NEWLINE is seen self.last = srowcol[0] if self.islambda: # lambdas always end at the first NEWLINE raise EndOfBlock + # hitting a NEWLINE when in a decorator without args + # ends the decorator + if self.indecorator and not self.decoratorhasargs: + self.indecorator = False elif self.passline: pass elif type == tokenize.INDENT: @@ -913,8 +929,10 @@ object = unwrap(object) lines, lnum = findsource(object) - if ismodule(object): return lines, 0 - else: return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): + return lines, 0 + else: + return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. 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 @@ -464,7 +464,6 @@ def test_getsource_unwrap(self): self.assertSourceEqual(mod2.real, 130, 132) - @unittest.expectedFailure def test_decorator_with_lambda(self): self.assertSourceEqual(mod2.func114, 113, 115) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect + results on nested functions. + - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. - Issue #24580: Symbolic group references to open group in re patterns now are @@ -551,6 +554,10 @@ - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. +- Issue #21217: inspect.getsourcelines() now tries to compute the start and end + lines from the code object, fixing an issue when a lambda function is used as + decorator argument. Patch by Thomas Ballinger and Allison Kaptur. + - Issue #24521: Fix possible integer overflows in the pickle module. - Issue #22931: Allow '[' and ']' in cookie values. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 06:00:13 2015 From: python-checkins at python.org (meador.inge) Date: Fri, 24 Jul 2015 04:00:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324485=3A_Function_source_inspection_fails_on_cl?= =?utf-8?q?osures=2E?= Message-ID: <20150724040011.24762.5944@psf.io> https://hg.python.org/cpython/rev/0e7d64595223 changeset: 97033:0e7d64595223 parent: 97031:262c43c71927 parent: 97032:5400e21e92a7 user: Meador Inge date: Thu Jul 23 22:52:49 2015 -0500 summary: Issue #24485: Function source inspection fails on closures. The fix for Issue #21217 introduced a regression that caused `inspect.getsource` to return incorrect results on nested functions. The root cause of the regression was due to switching the implementation to analyze the underlying bytecode instead of the source code. This commit switches things back to analyzing the source code in a more complete way. The original bug and the regression are both fixed by the new source code analysis. files: Lib/inspect.py | 26 ++++++++++++++++++++++---- Lib/test/test_inspect.py | 1 - Misc/NEWS | 7 +++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -842,21 +842,37 @@ self.islambda = False self.started = False self.passline = False + self.indecorator = False + self.decoratorhasargs = False self.last = 1 def tokeneater(self, type, token, srowcol, erowcol, line): - if not self.started: + if not self.started and not self.indecorator: + # skip any decorators + if token == "@": + self.indecorator = True # look for the first "def", "class" or "lambda" - if token in ("def", "class", "lambda"): + elif token in ("def", "class", "lambda"): if token == "lambda": self.islambda = True self.started = True self.passline = True # skip to the end of the line + elif token == "(": + if self.indecorator: + self.decoratorhasargs = True + elif token == ")": + if self.indecorator: + self.indecorator = False + self.decoratorhasargs = False elif type == tokenize.NEWLINE: self.passline = False # stop skipping when a NEWLINE is seen self.last = srowcol[0] if self.islambda: # lambdas always end at the first NEWLINE raise EndOfBlock + # hitting a NEWLINE when in a decorator without args + # ends the decorator + if self.indecorator and not self.decoratorhasargs: + self.indecorator = False elif self.passline: pass elif type == tokenize.INDENT: @@ -896,8 +912,10 @@ object = unwrap(object) lines, lnum = findsource(object) - if ismodule(object): return lines, 0 - else: return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): + return lines, 0 + else: + return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. 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 @@ -464,7 +464,6 @@ def test_getsource_unwrap(self): self.assertSourceEqual(mod2.real, 130, 132) - @unittest.expectedFailure def test_decorator_with_lambda(self): self.assertSourceEqual(mod2.func114, 113, 115) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,9 @@ Library ------- +- Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect + results on nested functions. + - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. - Issue #24580: Symbolic group references to open group in re patterns now are @@ -579,6 +582,10 @@ - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. +- Issue #21217: inspect.getsourcelines() now tries to compute the start and end + lines from the code object, fixing an issue when a lambda function is used as + decorator argument. Patch by Thomas Ballinger and Allison Kaptur. + - Issue #24521: Fix possible integer overflows in the pickle module. - Issue #22931: Allow '[' and ']' in cookie values. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 06:49:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 04:49:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Initialize_buf?= =?utf-8?q?=2Eoutobj_in_multibyte_encoder_=28closes_issue_=2324702=29=2E?= Message-ID: <20150724044525.47943.15143@psf.io> https://hg.python.org/cpython/rev/ba8ab143f4e6 changeset: 97035:ba8ab143f4e6 branch: 2.7 parent: 97008:ce34c78ebf65 user: Serhiy Storchaka date: Fri Jul 24 07:44:42 2015 +0300 summary: Initialize buf.outobj in multibyte encoder (closes issue #24702). Patch by pankaj.s01. files: Modules/cjkcodecs/multibytecodec.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -478,6 +478,7 @@ return PyString_FromString(""); buf.excobj = NULL; + buf.outobj = NULL; buf.inbuf = buf.inbuf_top = *data; buf.inbuf_end = buf.inbuf_top + datalen; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 06:43:53 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 24 Jul 2015 04:43:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324300=3A__Minor_r?= =?utf-8?q?efactoring=2E?= Message-ID: <20150724044353.13849.31733@psf.io> https://hg.python.org/cpython/rev/3bbd0cbfe836 changeset: 97034:3bbd0cbfe836 user: Raymond Hettinger date: Fri Jul 24 00:43:44 2015 -0400 summary: Issue #24300: Minor refactoring. files: Modules/nismodule.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Modules/nismodule.c b/Modules/nismodule.c --- a/Modules/nismodule.c +++ b/Modules/nismodule.c @@ -76,11 +76,7 @@ *pfix = 0; for (i=0; aliases[i].alias != 0L; i++) { - if (!strcmp (aliases[i].alias, map)) { - *pfix = aliases[i].fix; - return aliases[i].map; - } - if (!strcmp (aliases[i].map, map)) { + if (!strcmp (aliases[i].alias, map) || !strcmp (aliases[i].map, map)) { *pfix = aliases[i].fix; return aliases[i].map; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 07:06:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 05:06:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NzAz?= =?utf-8?q?=3A_Fixed_resource_leak_on_error_in_bsddb=2Everify=28=29=2E?= Message-ID: <20150724050616.22215.60228@psf.io> https://hg.python.org/cpython/rev/4fc7b803ac00 changeset: 97036:4fc7b803ac00 branch: 2.7 user: Serhiy Storchaka date: Fri Jul 24 08:05:45 2015 +0300 summary: Issue #24703: Fixed resource leak on error in bsddb.verify(). Original patch by Pankaj Sharma. files: Modules/_bsddb.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -3454,9 +3454,11 @@ error=DB_close_internal(self, 0, 1); if (error) { - return error; + if (outFile) + fclose(outFile); + return error; } - } + } MYDB_BEGIN_ALLOW_THREADS; err = self->db->verify(self->db, fileName, dbName, outFile, flags); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 07:08:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 24 Jul 2015 05:08:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324300=3A__Minor_r?= =?utf-8?q?efactoring=2E?= Message-ID: <20150724044353.13849.31733@psf.io> https://hg.python.org/cpython/rev/3bbd0cbfe836 changeset: 97034:3bbd0cbfe836 user: Raymond Hettinger date: Fri Jul 24 00:43:44 2015 -0400 summary: Issue #24300: Minor refactoring. files: Modules/nismodule.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Modules/nismodule.c b/Modules/nismodule.c --- a/Modules/nismodule.c +++ b/Modules/nismodule.c @@ -76,11 +76,7 @@ *pfix = 0; for (i=0; aliases[i].alias != 0L; i++) { - if (!strcmp (aliases[i].alias, map)) { - *pfix = aliases[i].fix; - return aliases[i].map; - } - if (!strcmp (aliases[i].map, map)) { + if (!strcmp (aliases[i].alias, map) || !strcmp (aliases[i].map, map)) { *pfix = aliases[i].fix; return aliases[i].map; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 08:08:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 06:08:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NjIw?= =?utf-8?q?=3A_Random=2Esetstate=28=29_now_validates_the_value_of_state_la?= =?utf-8?q?st_element=2E?= Message-ID: <20150724060820.51994.51161@psf.io> https://hg.python.org/cpython/rev/0933c00c2765 changeset: 97037:0933c00c2765 branch: 3.4 parent: 97029:13af5c3414b5 user: Serhiy Storchaka date: Fri Jul 24 09:02:53 2015 +0300 summary: Issue #24620: Random.setstate() now validates the value of state last element. files: Lib/test/test_random.py | 5 +++++ Misc/NEWS | 2 ++ Modules/_randommodule.c | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -338,6 +338,11 @@ self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None)) # Last element s/b an int also self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None)) + # Last element s/b between 0 and 624 + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(625,), None)) + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(-1,), None)) # Little trick to make "tuple(x % (2**32) for x in internalstate)" # raise ValueError. I cannot think of a simple way to achieve this, so diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #24620: Random.setstate() now validates the value of state last element. + - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. - Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -340,6 +340,10 @@ index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); if (index == -1 && PyErr_Occurred()) return NULL; + if (index < 0 || index > N) { + PyErr_SetString(PyExc_ValueError, "invalid state"); + return NULL; + } self->index = (int)index; Py_INCREF(Py_None); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 08:33:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 06:33:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324620=3A_Random=2Esetstate=28=29_now_validates_the_va?= =?utf-8?q?lue_of_state_last_element=2E?= Message-ID: <20150724060820.3157.98481@psf.io> https://hg.python.org/cpython/rev/d8229c26dd92 changeset: 97039:d8229c26dd92 branch: 3.5 parent: 97032:5400e21e92a7 parent: 97037:0933c00c2765 user: Serhiy Storchaka date: Fri Jul 24 09:05:59 2015 +0300 summary: Issue #24620: Random.setstate() now validates the value of state last element. files: Lib/test/test_random.py | 5 +++++ Misc/NEWS | 2 ++ Modules/_randommodule.c | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -338,6 +338,11 @@ self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None)) # Last element s/b an int also self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None)) + # Last element s/b between 0 and 624 + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(625,), None)) + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(-1,), None)) # Little trick to make "tuple(x % (2**32) for x in internalstate)" # raise ValueError. I cannot think of a simple way to achieve this, so diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,8 @@ Library ------- +- Issue #24620: Random.setstate() now validates the value of state last element. + - Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect results on nested functions. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -335,6 +335,10 @@ index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); if (index == -1 && PyErr_Occurred()) return NULL; + if (index < 0 || index > N) { + PyErr_SetString(PyExc_ValueError, "invalid state"); + return NULL; + } self->index = (int)index; Py_INCREF(Py_None); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 08:48:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 06:48:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324620=3A_Random=2Esetstate=28=29_now_validates_?= =?utf-8?q?the_value_of_state_last_element=2E?= Message-ID: <20150724060820.24764.64759@psf.io> https://hg.python.org/cpython/rev/f6e399ae670f changeset: 97040:f6e399ae670f parent: 97034:3bbd0cbfe836 parent: 97039:d8229c26dd92 user: Serhiy Storchaka date: Fri Jul 24 09:07:12 2015 +0300 summary: Issue #24620: Random.setstate() now validates the value of state last element. files: Lib/test/test_random.py | 5 +++++ Misc/NEWS | 2 ++ Modules/_randommodule.c | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -338,6 +338,11 @@ self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None)) # Last element s/b an int also self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None)) + # Last element s/b between 0 and 624 + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(625,), None)) + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(-1,), None)) # Little trick to make "tuple(x % (2**32) for x in internalstate)" # raise ValueError. I cannot think of a simple way to achieve this, so diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,8 @@ Library ------- +- Issue #24620: Random.setstate() now validates the value of state last element. + - Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect results on nested functions. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -335,6 +335,10 @@ index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); if (index == -1 && PyErr_Occurred()) return NULL; + if (index < 0 || index > N) { + PyErr_SetString(PyExc_ValueError, "invalid state"); + return NULL; + } self->index = (int)index; Py_INCREF(Py_None); -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri Jul 24 10:43:44 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 24 Jul 2015 08:43:44 +0000 Subject: [Python-checkins] Daily reference leaks (3bbd0cbfe836): sum=4 Message-ID: <20150724084344.22213.23490@psf.io> results for 3bbd0cbfe836 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogxOCfnX', '--timeout', '7200'] From python-checkins at python.org Fri Jul 24 11:58:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 09:58:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NzA0?= =?utf-8?q?=3A_Fixed_possible_NULL_pointer_dereferencing_in_the_=5Fjson_mo?= =?utf-8?q?dule?= Message-ID: <20150724095856.22217.65395@psf.io> https://hg.python.org/cpython/rev/a1a1e3fe837a changeset: 97041:a1a1e3fe837a branch: 2.7 parent: 97038:84070c1225c5 user: Serhiy Storchaka date: Fri Jul 24 12:58:25 2015 +0300 summary: Issue #24704: Fixed possible NULL pointer dereferencing in the _json module initialization. Patch by Pankaj Sharma. files: Modules/_json.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -2419,6 +2419,8 @@ if (PyType_Ready(&PyEncoderType) < 0) return; m = Py_InitModule3("_json", speedups_methods, module_doc); + if (m == NULL) + return; Py_INCREF((PyObject*)&PyScannerType); PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType); Py_INCREF((PyObject*)&PyEncoderType); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 14:33:30 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 24 Jul 2015 12:33:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NjIw?= =?utf-8?q?=3A_Random=2Esetstate=28=29_now_validates_the_value_of_state_la?= =?utf-8?q?st_element=2E?= Message-ID: <20150724060820.51980.74221@psf.io> https://hg.python.org/cpython/rev/84070c1225c5 changeset: 97038:84070c1225c5 branch: 2.7 parent: 97036:4fc7b803ac00 user: Serhiy Storchaka date: Fri Jul 24 09:02:53 2015 +0300 summary: Issue #24620: Random.setstate() now validates the value of state last element. files: Lib/test/test_random.py | 5 +++++ Misc/NEWS | 2 ++ Modules/_randommodule.c | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -319,6 +319,11 @@ self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None)) # Last element s/b an int also self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None)) + # Last element s/b between 0 and 624 + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(625,), None)) + with self.assertRaises((ValueError, OverflowError)): + self.gen.setstate((2, (1,)*624+(-1,), None)) def test_referenceImplementation(self): # Compare the python implementation with results from the original diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #24620: Random.setstate() now validates the value of state last element. + - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. - Issue #24611: Fixed compiling the posix module on non-Windows platforms diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -363,6 +363,10 @@ index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); if (index == -1 && PyErr_Occurred()) return NULL; + if (index < 0 || index > N) { + PyErr_SetString(PyExc_ValueError, "invalid state"); + return NULL; + } self->index = (int)index; Py_INCREF(Py_None); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 16:36:53 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 24 Jul 2015 14:36:53 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Njk1?= =?utf-8?q?=3A_Fix_a_regression_in_traceback=2Eprint=5Fexception=28=29?= Message-ID: <20150724143652.24788.4132@psf.io> https://hg.python.org/cpython/rev/b45077269aaa changeset: 97042:b45077269aaa branch: 3.5 parent: 97039:d8229c26dd92 user: Berker Peksag date: Fri Jul 24 17:36:21 2015 +0300 summary: Issue #24695: Fix a regression in traceback.print_exception() If exc_traceback is None we shouldn't print a traceback header like described in the documentation. files: Lib/test/test_traceback.py | 13 +++++++++++++ Lib/traceback.py | 4 +++- Misc/NEWS | 4 ++++ 3 files changed, 20 insertions(+), 1 deletions(-) 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 @@ -209,6 +209,13 @@ b'ZeroDivisionError: division by zero'] self.assertEqual(stderr.splitlines(), expected) + def test_print_exception(self): + output = StringIO() + traceback.print_exception( + Exception, Exception("projector"), None, file=output + ) + self.assertEqual(output.getvalue(), "Exception: projector\n") + class TracebackFormatTests(unittest.TestCase): @@ -848,6 +855,12 @@ exc = traceback.TracebackException(Exception, e, tb) self.assertEqual(exc.stack[0].locals, None) + def test_traceback_header(self): + # do not print a traceback header if exc_traceback is None + # see issue #24695 + exc = traceback.TracebackException(Exception, Exception("haven"), None) + self.assertEqual(list(exc.format()), ["Exception: haven\n"]) + class MiscTest(unittest.TestCase): diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -453,6 +453,7 @@ _seen=_seen) else: context = None + self.exc_traceback = exc_traceback self.__cause__ = cause self.__context__ = context self.__suppress_context__ = \ @@ -561,6 +562,7 @@ not self.__suppress_context__): yield from self.__context__.format(chain=chain) yield _context_message - yield 'Traceback (most recent call last):\n' + if self.exc_traceback is not None: + yield 'Traceback (most recent call last):\n' yield from self.stack.format() yield from self.format_exception_only() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,10 @@ Library ------- +- Issue #24695: Fix a regression in traceback.print_exception(). If + exc_traceback is None we shouldn't print a traceback header like described + in the documentation. + - Issue #24620: Random.setstate() now validates the value of state last element. - Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 16:36:53 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 24 Jul 2015 14:36:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324695=3A_Fix_a_regression_in_traceback=2Eprint?= =?utf-8?b?X2V4Y2VwdGlvbigp?= Message-ID: <20150724143652.62373.91611@psf.io> https://hg.python.org/cpython/rev/2825c87d3f72 changeset: 97043:2825c87d3f72 parent: 97040:f6e399ae670f parent: 97042:b45077269aaa user: Berker Peksag date: Fri Jul 24 17:37:27 2015 +0300 summary: Issue #24695: Fix a regression in traceback.print_exception() If exc_traceback is None we shouldn't print a traceback header like described in the documentation. files: Lib/test/test_traceback.py | 13 +++++++++++++ Lib/traceback.py | 4 +++- Misc/NEWS | 4 ++++ 3 files changed, 20 insertions(+), 1 deletions(-) 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 @@ -209,6 +209,13 @@ b'ZeroDivisionError: division by zero'] self.assertEqual(stderr.splitlines(), expected) + def test_print_exception(self): + output = StringIO() + traceback.print_exception( + Exception, Exception("projector"), None, file=output + ) + self.assertEqual(output.getvalue(), "Exception: projector\n") + class TracebackFormatTests(unittest.TestCase): @@ -848,6 +855,12 @@ exc = traceback.TracebackException(Exception, e, tb) self.assertEqual(exc.stack[0].locals, None) + def test_traceback_header(self): + # do not print a traceback header if exc_traceback is None + # see issue #24695 + exc = traceback.TracebackException(Exception, Exception("haven"), None) + self.assertEqual(list(exc.format()), ["Exception: haven\n"]) + class MiscTest(unittest.TestCase): diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -453,6 +453,7 @@ _seen=_seen) else: context = None + self.exc_traceback = exc_traceback self.__cause__ = cause self.__context__ = context self.__suppress_context__ = \ @@ -561,6 +562,7 @@ not self.__suppress_context__): yield from self.__context__.format(chain=chain) yield _context_message - yield 'Traceback (most recent call last):\n' + if self.exc_traceback is not None: + yield 'Traceback (most recent call last):\n' yield from self.stack.format() yield from self.format_exception_only() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,10 @@ Library ------- +- Issue #24695: Fix a regression in traceback.print_exception(). If + exc_traceback is None we shouldn't print a traceback header like described + in the documentation. + - Issue #24620: Random.setstate() now validates the value of state last element. - Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 24 17:22:56 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 24 Jul 2015 15:22:56 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Issue_=2310708=3A_Add_a_F?= =?utf-8?q?AQ_entry_about_porting_Python_to_a_new_platform=2E?= Message-ID: <20150724151249.8502.76023@psf.io> https://hg.python.org/devguide/rev/d6e10dfbeab1 changeset: 751:d6e10dfbeab1 user: Berker Peksag date: Fri Jul 24 18:13:34 2015 +0300 summary: Issue #10708: Add a FAQ entry about porting Python to a new platform. Patch by Paul Anton Letnes. files: faq.rst | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 42 insertions(+), 0 deletions(-) diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -994,3 +994,45 @@ to ``~/.gdbinit`` (edit the specific list of paths as appropriate):: add-auto-load-safe-path ~/devel/py3k:~/devel/py32:~/devel/py27 + + +How do I port Python to a new platform? +--------------------------------------- + +The first step is to familiarize yourself with the development toolchain on +the platform in question, notably the C compiler. Make sure you can compile and +run a hello-world program using the target compiler. + +Next, learn how to compile and run the Python interpreter on a platform to +which it has already been ported; preferably Unix, but Windows will +do, too. The build process for Python, in particular the ``Makefile`` in the +source distribution, will give you a hint on which files to compile +for Python. Not all source files are relevant: some are platform +specific, others are only used in emergencies (e.g. ``getopt.c``). + +It is not recommended to start porting Python without at least medium-level +understanding of your target platform; i.e. how it is generally used, how to +write platform specific apps, etc. Also, some Python knowledge is required, or +you will be unable to verify that your port is working correctly. + +You will need a ``pyconfig.h`` file tailored for your platform. You can +start with ``pyconfig.h.in``, read the comments, and turn on definitions that +apply to your platform. Also, you will need a ``config.c`` file, which lists +the built-in modules you support. Again, starting with +``Modules/config.c.in`` is recommended. + +Finally, you will run into some things that are not supported on your +target platform. Forget about the ``posix`` module in the beginning. You can +simply comment it out of the ``config.c`` file. + +Keep working on it until you get a ``>>>`` prompt. You may have to disable the +importing of ``site.py`` by passing the ``-S`` option. When you have a prompt, +bang on it until it executes very simple Python statements. + +At some point you will want to use the ``os`` module; this is the time to start +thinking about what to do with the ``posix`` module. It is okay to simply +comment out functions in the ``posix`` module that cause problems; the +remaining ones will be quite useful. + +Before you are done, it is highly recommended to run the Python regression test +suite, as described in :ref:`runtests`. -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Fri Jul 24 17:23:39 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 24 Jul 2015 15:23:39 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_431=3A_Update_from_Lennar?= =?utf-8?q?t_Regebro=2E?= Message-ID: <20150724152339.8514.62701@psf.io> https://hg.python.org/peps/rev/52a33f783dcb changeset: 5909:52a33f783dcb user: Berker Peksag date: Fri Jul 24 18:24:24 2015 +0300 summary: PEP 431: Update from Lennart Regebro. files: pep-0431.txt | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/pep-0431.txt b/pep-0431.txt --- a/pep-0431.txt +++ b/pep-0431.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Lennart Regebro BDFL-Delegate: Barry Warsaw -Status: Draft +Status: Postponed Type: Standards Track Content-Type: text/x-rst Created: 11-Dec-2012 @@ -19,6 +19,19 @@ with ambiguous time specifications during DST changes. +Postponement +============ + +The implementation has turned out to be exceedingly complex, due to having to +convert back and forth between the local time and UTC during arithmetic +and adjusting the DST for each arithmetic step, with ambiguous times being +particularly hard to get right. + +This is likely to become much easier if the UTC timestamp is stored internally +and used for all arithmetic, and an investigation into changing the +``datetime()`` object to use UTC internally should be done. + + Proposal ======== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Jul 24 18:30:27 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 24 Jul 2015 16:30:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_=22Postponed=22_is_not_a_vali?= =?utf-8?q?d_identifier=2E?= Message-ID: <20150724163026.13853.2075@psf.io> https://hg.python.org/peps/rev/1aead2cb0bc0 changeset: 5910:1aead2cb0bc0 user: Berker Peksag date: Fri Jul 24 19:31:13 2015 +0300 summary: "Postponed" is not a valid identifier. files: pep-0431.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0431.txt b/pep-0431.txt --- a/pep-0431.txt +++ b/pep-0431.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Lennart Regebro BDFL-Delegate: Barry Warsaw -Status: Postponed +Status: Deferred Type: Standards Track Content-Type: text/x-rst Created: 11-Dec-2012 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Jul 25 01:26:21 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 24 Jul 2015 23:26:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NjAz?= =?utf-8?q?=3A_Update_the_OS_X_32-bit_installer_build_to_use_OpenSSL_1=2E0?= =?utf-8?q?=2E2d=2E?= Message-ID: <20150724232621.22213.2750@psf.io> https://hg.python.org/cpython/rev/436b8902b305 changeset: 97045:436b8902b305 branch: 3.4 parent: 97037:0933c00c2765 user: Ned Deily date: Fri Jul 24 16:21:18 2015 -0700 summary: Issue #24603: Update the OS X 32-bit installer build to use OpenSSL 1.0.2d. files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- 2 files changed, 4 insertions(+), 4 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2c", - url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", - checksum='8c8d81a9ae7005276e486702edbcd4b6', + name="OpenSSL 1.0.2d", + url="https://www.openssl.org/source/openssl-1.0.2d.tar.gz", + checksum='38dd619b2e77cbac69b99f52a053d25a', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2c +# using openssl 1.0.2d # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 01:26:21 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 24 Jul 2015 23:26:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NjAz?= =?utf-8?q?=3A_Update_the_OS_X_32-bit_installer_build_to_use_OpenSSL_1=2E0?= =?utf-8?q?=2E2d=2E?= Message-ID: <20150724232621.8492.19461@psf.io> https://hg.python.org/cpython/rev/7ba239d4efbb changeset: 97044:7ba239d4efbb branch: 2.7 parent: 97041:a1a1e3fe837a user: Ned Deily date: Fri Jul 24 16:19:00 2015 -0700 summary: Issue #24603: Update the OS X 32-bit installer build to use OpenSSL 1.0.2d. files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- 2 files changed, 4 insertions(+), 4 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2c", - url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", - checksum='8c8d81a9ae7005276e486702edbcd4b6', + name="OpenSSL 1.0.2d", + url="https://www.openssl.org/source/openssl-1.0.2d.tar.gz", + checksum='38dd619b2e77cbac69b99f52a053d25a', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2c +# using openssl 1.0.2d # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 01:26:27 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 24 Jul 2015 23:26:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324603=3A_merge_from_3=2E4?= Message-ID: <20150724232627.20792.63463@psf.io> https://hg.python.org/cpython/rev/78254d483573 changeset: 97046:78254d483573 branch: 3.5 parent: 97042:b45077269aaa parent: 97045:436b8902b305 user: Ned Deily date: Fri Jul 24 16:24:47 2015 -0700 summary: Issue #24603: merge from 3.4 files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 3 ++- 3 files changed, 6 insertions(+), 5 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2c", - url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", - checksum='8c8d81a9ae7005276e486702edbcd4b6', + name="OpenSSL 1.0.2d", + url="https://www.openssl.org/source/openssl-1.0.2d.tar.gz", + checksum='38dd619b2e77cbac69b99f52a053d25a', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2c +# using openssl 1.0.2d # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -70,7 +70,8 @@ Build ----- -- Issue #24603: Update the Windows build to use OpenSSL 1.0.2d. +- Issue #24603: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2d. What's New in Python 3.5.0 beta 3? -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 01:26:27 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 24 Jul 2015 23:26:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324603=3A_merge_from_3=2E5?= Message-ID: <20150724232627.97491.36327@psf.io> https://hg.python.org/cpython/rev/d205e7e5f9aa changeset: 97047:d205e7e5f9aa parent: 97043:2825c87d3f72 parent: 97046:78254d483573 user: Ned Deily date: Fri Jul 24 16:25:30 2015 -0700 summary: Issue #24603: merge from 3.5 files: Mac/BuildScript/build-installer.py | 6 +++--- Mac/BuildScript/openssl_sdk_makedepend.patch | 2 +- Misc/NEWS | 3 ++- 3 files changed, 6 insertions(+), 5 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 @@ -237,9 +237,9 @@ result.extend([ dict( - name="OpenSSL 1.0.2c", - url="https://www.openssl.org/source/openssl-1.0.2c.tar.gz", - checksum='8c8d81a9ae7005276e486702edbcd4b6', + name="OpenSSL 1.0.2d", + url="https://www.openssl.org/source/openssl-1.0.2d.tar.gz", + checksum='38dd619b2e77cbac69b99f52a053d25a', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Mac/BuildScript/openssl_sdk_makedepend.patch b/Mac/BuildScript/openssl_sdk_makedepend.patch --- a/Mac/BuildScript/openssl_sdk_makedepend.patch +++ b/Mac/BuildScript/openssl_sdk_makedepend.patch @@ -2,7 +2,7 @@ # Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43 # openssl_sdk_makedepend.patch # -# using openssl 1.0.2c +# using openssl 1.0.2d # # - support building with an OS X SDK # - allow "make depend" to use compilers with names other than "gcc" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -96,7 +96,8 @@ Build ----- -- Issue #24603: Update the Windows build to use OpenSSL 1.0.2d. +- Issue #24603: Update Windows builds and OS X 10.5 installer to use OpenSSL + 1.0.2d. What's New in Python 3.5.0 beta 3? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 02:47:19 2015 From: python-checkins at python.org (victor.stinner) Date: Sat, 25 Jul 2015 00:47:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogc3lu?= =?utf-8?q?c_with_github?= Message-ID: <20150725004719.24776.23561@psf.io> https://hg.python.org/cpython/rev/fc1d40a706e7 changeset: 97049:fc1d40a706e7 branch: 3.4 user: Victor Stinner date: Sat Jul 25 02:40:40 2015 +0200 summary: asyncio: sync with github * Fix ResourceWarning warnings in test_streams * Return True from StreamReader.eof_received() to fix http://bugs.python.org/issue24539 (but still needs a unittest). Add StreamReader.__repr__() for easy debugging. * remove unused imports * Issue #234: Drop JoinableQueue on Python 3.5+ files: Lib/asyncio/locks.py | 1 - Lib/asyncio/queues.py | 10 +++-- Lib/asyncio/streams.py | 20 ++++++++++- Lib/asyncio/subprocess.py | 2 - Lib/asyncio/tasks.py | 2 - Lib/asyncio/transports.py | 2 - Lib/test/test_asyncio/test_streams.py | 28 ++++++-------- 7 files changed, 37 insertions(+), 28 deletions(-) diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,7 +3,6 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections -import sys from . import compat from . import events diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -1,11 +1,11 @@ """Queues""" -__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty', - 'JoinableQueue'] +__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty'] import collections import heapq +from . import compat from . import events from . import futures from . import locks @@ -289,5 +289,7 @@ return self._queue.pop() -JoinableQueue = Queue -"""Deprecated alias for Queue.""" +if not compat.PY35: + JoinableQueue = Queue + """Deprecated alias for Queue.""" + __all__.append('JoinableQueue') diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,7 +6,6 @@ ] import socket -import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) @@ -240,6 +239,7 @@ def eof_received(self): self._stream_reader.feed_eof() + return True class StreamWriter: @@ -321,6 +321,24 @@ self._transport = None self._paused = False + def __repr__(self): + info = ['StreamReader'] + if self._buffer: + info.append('%d bytes' % len(info)) + if self._eof: + info.append('eof') + if self._limit != _DEFAULT_LIMIT: + info.append('l=%d' % self._limit) + if self._waiter: + info.append('w=%r' % self._waiter) + if self._exception: + info.append('e=%r' % self._exception) + if self._transport: + info.append('t=%r' % self._transport) + if self._paused: + info.append('paused') + return '<%s>' % ' '.join(info) + def exception(self): return self._exception diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -1,10 +1,8 @@ __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 diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -10,8 +10,6 @@ import functools import inspect import linecache -import sys -import types import traceback import warnings import weakref diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -1,7 +1,5 @@ """Abstract Transport class.""" -import sys - from asyncio import compat __all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport', 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 @@ -446,6 +446,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): sock = socket.socket() @@ -457,12 +459,8 @@ 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): sock = socket.socket() @@ -522,6 +520,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): self.server = self.loop.run_until_complete( @@ -530,18 +530,14 @@ loop=self.loop)) 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client_callback, - path=self.path, - loop=self.loop)) + start = asyncio.start_unix_server(self.handle_client_callback, + path=self.path, + loop=self.loop) + self.server = self.loop.run_until_complete(start) def stop(self): if self.server is not None: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 02:47:19 2015 From: python-checkins at python.org (victor.stinner) Date: Sat, 25 Jul 2015 00:47:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150725004719.113884.40858@psf.io> https://hg.python.org/cpython/rev/6888979cd407 changeset: 97050:6888979cd407 branch: 3.5 parent: 97046:78254d483573 parent: 97049:fc1d40a706e7 user: Victor Stinner date: Sat Jul 25 02:43:31 2015 +0200 summary: Merge 3.4 files: Lib/asyncio/compat.py | 17 +++++++++ Lib/asyncio/coroutines.py | 6 +-- Lib/asyncio/events.py | 7 +-- Lib/asyncio/futures.py | 10 ++--- Lib/asyncio/locks.py | 7 +-- Lib/asyncio/queues.py | 7 +++ Lib/asyncio/streams.py | 24 +++++++++++- Lib/asyncio/subprocess.py | 2 - Lib/asyncio/tasks.py | 7 +-- Lib/asyncio/transports.py | 12 +---- Lib/test/test_asyncio/test_streams.py | 28 ++++++-------- 11 files changed, 73 insertions(+), 54 deletions(-) diff --git a/Lib/asyncio/compat.py b/Lib/asyncio/compat.py new file mode 100644 --- /dev/null +++ b/Lib/asyncio/compat.py @@ -0,0 +1,17 @@ +"""Compatibility helpers for the different Python versions.""" + +import sys + +PY34 = sys.version_info >= (3, 4) +PY35 = sys.version_info >= (3, 5) + + +def flatten_list_bytes(list_of_data): + """Concatenate a sequence of bytes-like objects.""" + if not PY34: + # On Python 3.3 and older, bytes.join() doesn't handle + # memoryview. + list_of_data = ( + bytes(data) if isinstance(data, memoryview) else data + for data in list_of_data) + return b''.join(list_of_data) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -9,14 +9,12 @@ import traceback import types +from . import compat from . import events from . import futures from .log import logger -_PY35 = sys.version_info >= (3, 5) - - # Opcode of "yield from" instruction _YIELD_FROM = opcode.opmap['YIELD_FROM'] @@ -140,7 +138,7 @@ def gi_code(self): return self.gen.gi_code - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -17,12 +17,11 @@ import threading import traceback - -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat def _get_function_source(func): - if _PY34: + if compat.PY34: func = inspect.unwrap(func) elif hasattr(func, '__wrapped__'): func = func.__wrapped__ @@ -31,7 +30,7 @@ return (code.co_filename, code.co_firstlineno) if isinstance(func, functools.partial): return _get_function_source(func.func) - if _PY34 and isinstance(func, functools.partialmethod): + if compat.PY34 and isinstance(func, functools.partialmethod): return _get_function_source(func.func) return None diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -11,6 +11,7 @@ import sys import traceback +from . import compat from . import events # States for Future. @@ -18,9 +19,6 @@ _CANCELLED = 'CANCELLED' _FINISHED = 'FINISHED' -_PY34 = sys.version_info >= (3, 4) -_PY35 = sys.version_info >= (3, 5) - Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError TimeoutError = concurrent.futures.TimeoutError @@ -199,7 +197,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if not self._log_traceback: # set_exception() was not called, or result() or exception() @@ -352,7 +350,7 @@ self._exception = exception self._state = _FINISHED self._schedule_callbacks() - if _PY34: + if compat.PY34: self._log_traceback = True else: self._tb_logger = _TracebackLogger(self, exception) @@ -388,7 +386,7 @@ assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,16 +3,13 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections -import sys +from . import compat from . import events from . import futures from .coroutines import coroutine -_PY35 = sys.version_info >= (3, 5) - - class _ContextManager: """Context manager. @@ -70,7 +67,7 @@ yield from self.acquire() return _ContextManager(self) - if _PY35: + if compat.PY35: def __await__(self): # To make "with await lock" work. diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -5,6 +5,7 @@ import collections import heapq +from . import compat from . import events from . import futures from . import locks @@ -286,3 +287,9 @@ def _get(self): return self._queue.pop() + + +if not compat.PY35: + JoinableQueue = Queue + """Deprecated alias for Queue.""" + __all__.append('JoinableQueue') diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,12 +6,12 @@ ] import socket -import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) from . import coroutines +from . import compat from . import events from . import futures from . import protocols @@ -20,7 +20,6 @@ _DEFAULT_LIMIT = 2**16 -_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -240,6 +239,7 @@ def eof_received(self): self._stream_reader.feed_eof() + return True class StreamWriter: @@ -321,6 +321,24 @@ self._transport = None self._paused = False + def __repr__(self): + info = ['StreamReader'] + if self._buffer: + info.append('%d bytes' % len(info)) + if self._eof: + info.append('eof') + if self._limit != _DEFAULT_LIMIT: + info.append('l=%d' % self._limit) + if self._waiter: + info.append('w=%r' % self._waiter) + if self._exception: + info.append('e=%r' % self._exception) + if self._transport: + info.append('t=%r' % self._transport) + if self._paused: + info.append('paused') + return '<%s>' % ' '.join(info) + def exception(self): return self._exception @@ -488,7 +506,7 @@ return b''.join(blocks) - if _PY35: + if compat.PY35: @coroutine def __aiter__(self): return self diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -1,10 +1,8 @@ __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 diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -10,19 +10,16 @@ import functools import inspect import linecache -import sys -import types import traceback import warnings import weakref +from . import compat from . import coroutines from . import events from . import futures from .coroutines import coroutine -_PY34 = (sys.version_info >= (3, 4)) - class Task(futures.Future): """A coroutine wrapped in a Future.""" @@ -83,7 +80,7 @@ # On Python 3.3 or older, objects with a destructor that are part of a # reference cycle are never destroyed. That's not the case any more on # Python 3.4 thanks to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: context = { diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -1,8 +1,6 @@ """Abstract Transport class.""" -import sys - -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat __all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport', 'Transport', 'DatagramTransport', 'SubprocessTransport', @@ -94,12 +92,8 @@ The default implementation concatenates the arguments and calls write() on the result. """ - if not _PY34: - # In Python 3.3, bytes.join() doesn't handle memoryview. - list_of_data = ( - bytes(data) if isinstance(data, memoryview) else data - for data in list_of_data) - self.write(b''.join(list_of_data)) + data = compat.flatten_list_bytes(list_of_data) + self.write(data) def write_eof(self): """Close the write end after flushing buffered data. 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 @@ -446,6 +446,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): sock = socket.socket() @@ -457,12 +459,8 @@ 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): sock = socket.socket() @@ -522,6 +520,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): self.server = self.loop.run_until_complete( @@ -530,18 +530,14 @@ loop=self.loop)) 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client_callback, - path=self.path, - loop=self.loop)) + start = asyncio.start_unix_server(self.handle_client_callback, + path=self.path, + loop=self.loop) + self.server = self.loop.run_until_complete(start) def stop(self): if self.server is not None: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 02:47:19 2015 From: python-checkins at python.org (victor.stinner) Date: Sat, 25 Jul 2015 00:47:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogQWRk?= =?utf-8?q?_asyncio=2Ecompat_module?= Message-ID: <20150725004719.110430.7487@psf.io> https://hg.python.org/cpython/rev/f2a15e60621b changeset: 97048:f2a15e60621b branch: 3.4 parent: 97045:436b8902b305 user: Victor Stinner date: Sat Jul 25 02:23:21 2015 +0200 summary: asyncio: Add asyncio.compat module Move compatibility helpers for the different Python versions to a new asyncio.compat module. files: Lib/asyncio/compat.py | 17 +++++++++++++++++ Lib/asyncio/coroutines.py | 6 ++---- Lib/asyncio/events.py | 7 +++---- Lib/asyncio/futures.py | 10 ++++------ Lib/asyncio/locks.py | 6 ++---- Lib/asyncio/streams.py | 4 ++-- Lib/asyncio/tasks.py | 5 ++--- Lib/asyncio/transports.py | 10 +++------- 8 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Lib/asyncio/compat.py b/Lib/asyncio/compat.py new file mode 100644 --- /dev/null +++ b/Lib/asyncio/compat.py @@ -0,0 +1,17 @@ +"""Compatibility helpers for the different Python versions.""" + +import sys + +PY34 = sys.version_info >= (3, 4) +PY35 = sys.version_info >= (3, 5) + + +def flatten_list_bytes(list_of_data): + """Concatenate a sequence of bytes-like objects.""" + if not PY34: + # On Python 3.3 and older, bytes.join() doesn't handle + # memoryview. + list_of_data = ( + bytes(data) if isinstance(data, memoryview) else data + for data in list_of_data) + return b''.join(list_of_data) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -9,14 +9,12 @@ import traceback import types +from . import compat from . import events from . import futures from .log import logger -_PY35 = sys.version_info >= (3, 5) - - # Opcode of "yield from" instruction _YIELD_FROM = opcode.opmap['YIELD_FROM'] @@ -140,7 +138,7 @@ def gi_code(self): return self.gen.gi_code - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -17,12 +17,11 @@ import threading import traceback - -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat def _get_function_source(func): - if _PY34: + if compat.PY34: func = inspect.unwrap(func) elif hasattr(func, '__wrapped__'): func = func.__wrapped__ @@ -31,7 +30,7 @@ return (code.co_filename, code.co_firstlineno) if isinstance(func, functools.partial): return _get_function_source(func.func) - if _PY34 and isinstance(func, functools.partialmethod): + if compat.PY34 and isinstance(func, functools.partialmethod): return _get_function_source(func.func) return None diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -11,6 +11,7 @@ import sys import traceback +from . import compat from . import events # States for Future. @@ -18,9 +19,6 @@ _CANCELLED = 'CANCELLED' _FINISHED = 'FINISHED' -_PY34 = sys.version_info >= (3, 4) -_PY35 = sys.version_info >= (3, 5) - Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError TimeoutError = concurrent.futures.TimeoutError @@ -199,7 +197,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if not self._log_traceback: # set_exception() was not called, or result() or exception() @@ -352,7 +350,7 @@ self._exception = exception self._state = _FINISHED self._schedule_callbacks() - if _PY34: + if compat.PY34: self._log_traceback = True else: self._tb_logger = _TracebackLogger(self, exception) @@ -388,7 +386,7 @@ assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -5,14 +5,12 @@ import collections import sys +from . import compat from . import events from . import futures from .coroutines import coroutine -_PY35 = sys.version_info >= (3, 5) - - class _ContextManager: """Context manager. @@ -70,7 +68,7 @@ yield from self.acquire() return _ContextManager(self) - if _PY35: + if compat.PY35: def __await__(self): # To make "with await lock" work. diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -12,6 +12,7 @@ __all__.extend(['open_unix_connection', 'start_unix_server']) from . import coroutines +from . import compat from . import events from . import futures from . import protocols @@ -20,7 +21,6 @@ _DEFAULT_LIMIT = 2**16 -_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -488,7 +488,7 @@ return b''.join(blocks) - if _PY35: + if compat.PY35: @coroutine def __aiter__(self): return self diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -16,13 +16,12 @@ import warnings import weakref +from . import compat from . import coroutines from . import events from . import futures from .coroutines import coroutine -_PY34 = (sys.version_info >= (3, 4)) - class Task(futures.Future): """A coroutine wrapped in a Future.""" @@ -83,7 +82,7 @@ # On Python 3.3 or older, objects with a destructor that are part of a # reference cycle are never destroyed. That's not the case any more on # Python 3.4 thanks to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: context = { diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -2,7 +2,7 @@ import sys -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat __all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport', 'Transport', 'DatagramTransport', 'SubprocessTransport', @@ -94,12 +94,8 @@ The default implementation concatenates the arguments and calls write() on the result. """ - if not _PY34: - # In Python 3.3, bytes.join() doesn't handle memoryview. - list_of_data = ( - bytes(data) if isinstance(data, memoryview) else data - for data in list_of_data) - self.write(b''.join(list_of_data)) + data = compat.flatten_list_bytes(list_of_data) + self.write(data) def write_eof(self): """Close the write end after flushing buffered data. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 02:47:19 2015 From: python-checkins at python.org (victor.stinner) Date: Sat, 25 Jul 2015 00:47:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28asyncio=29?= Message-ID: <20150725004719.22235.32432@psf.io> https://hg.python.org/cpython/rev/c53d24ee3963 changeset: 97051:c53d24ee3963 parent: 97047:d205e7e5f9aa parent: 97050:6888979cd407 user: Victor Stinner date: Sat Jul 25 02:45:18 2015 +0200 summary: Merge 3.5 (asyncio) files: Lib/asyncio/compat.py | 17 +++++++++ Lib/asyncio/coroutines.py | 6 +-- Lib/asyncio/events.py | 7 +-- Lib/asyncio/futures.py | 10 ++--- Lib/asyncio/locks.py | 7 +-- Lib/asyncio/queues.py | 7 +++ Lib/asyncio/streams.py | 24 +++++++++++- Lib/asyncio/subprocess.py | 2 - Lib/asyncio/tasks.py | 7 +-- Lib/asyncio/transports.py | 12 +---- Lib/test/test_asyncio/test_streams.py | 28 ++++++-------- 11 files changed, 73 insertions(+), 54 deletions(-) diff --git a/Lib/asyncio/compat.py b/Lib/asyncio/compat.py new file mode 100644 --- /dev/null +++ b/Lib/asyncio/compat.py @@ -0,0 +1,17 @@ +"""Compatibility helpers for the different Python versions.""" + +import sys + +PY34 = sys.version_info >= (3, 4) +PY35 = sys.version_info >= (3, 5) + + +def flatten_list_bytes(list_of_data): + """Concatenate a sequence of bytes-like objects.""" + if not PY34: + # On Python 3.3 and older, bytes.join() doesn't handle + # memoryview. + list_of_data = ( + bytes(data) if isinstance(data, memoryview) else data + for data in list_of_data) + return b''.join(list_of_data) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -9,14 +9,12 @@ import traceback import types +from . import compat from . import events from . import futures from .log import logger -_PY35 = sys.version_info >= (3, 5) - - # Opcode of "yield from" instruction _YIELD_FROM = opcode.opmap['YIELD_FROM'] @@ -140,7 +138,7 @@ def gi_code(self): return self.gen.gi_code - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -17,12 +17,11 @@ import threading import traceback - -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat def _get_function_source(func): - if _PY34: + if compat.PY34: func = inspect.unwrap(func) elif hasattr(func, '__wrapped__'): func = func.__wrapped__ @@ -31,7 +30,7 @@ return (code.co_filename, code.co_firstlineno) if isinstance(func, functools.partial): return _get_function_source(func.func) - if _PY34 and isinstance(func, functools.partialmethod): + if compat.PY34 and isinstance(func, functools.partialmethod): return _get_function_source(func.func) return None diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -11,6 +11,7 @@ import sys import traceback +from . import compat from . import events # States for Future. @@ -18,9 +19,6 @@ _CANCELLED = 'CANCELLED' _FINISHED = 'FINISHED' -_PY34 = sys.version_info >= (3, 4) -_PY35 = sys.version_info >= (3, 5) - Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError TimeoutError = concurrent.futures.TimeoutError @@ -199,7 +197,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if not self._log_traceback: # set_exception() was not called, or result() or exception() @@ -352,7 +350,7 @@ self._exception = exception self._state = _FINISHED self._schedule_callbacks() - if _PY34: + if compat.PY34: self._log_traceback = True else: self._tb_logger = _TracebackLogger(self, exception) @@ -388,7 +386,7 @@ assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. - if _PY35: + if compat.PY35: __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,16 +3,13 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections -import sys +from . import compat from . import events from . import futures from .coroutines import coroutine -_PY35 = sys.version_info >= (3, 5) - - class _ContextManager: """Context manager. @@ -70,7 +67,7 @@ yield from self.acquire() return _ContextManager(self) - if _PY35: + if compat.PY35: def __await__(self): # To make "with await lock" work. diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -5,6 +5,7 @@ import collections import heapq +from . import compat from . import events from . import futures from . import locks @@ -286,3 +287,9 @@ def _get(self): return self._queue.pop() + + +if not compat.PY35: + JoinableQueue = Queue + """Deprecated alias for Queue.""" + __all__.append('JoinableQueue') diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,12 +6,12 @@ ] import socket -import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) from . import coroutines +from . import compat from . import events from . import futures from . import protocols @@ -20,7 +20,6 @@ _DEFAULT_LIMIT = 2**16 -_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -240,6 +239,7 @@ def eof_received(self): self._stream_reader.feed_eof() + return True class StreamWriter: @@ -321,6 +321,24 @@ self._transport = None self._paused = False + def __repr__(self): + info = ['StreamReader'] + if self._buffer: + info.append('%d bytes' % len(info)) + if self._eof: + info.append('eof') + if self._limit != _DEFAULT_LIMIT: + info.append('l=%d' % self._limit) + if self._waiter: + info.append('w=%r' % self._waiter) + if self._exception: + info.append('e=%r' % self._exception) + if self._transport: + info.append('t=%r' % self._transport) + if self._paused: + info.append('paused') + return '<%s>' % ' '.join(info) + def exception(self): return self._exception @@ -488,7 +506,7 @@ return b''.join(blocks) - if _PY35: + if compat.PY35: @coroutine def __aiter__(self): return self diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -1,10 +1,8 @@ __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 diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -10,19 +10,16 @@ import functools import inspect import linecache -import sys -import types import traceback import warnings import weakref +from . import compat from . import coroutines from . import events from . import futures from .coroutines import coroutine -_PY34 = (sys.version_info >= (3, 4)) - class Task(futures.Future): """A coroutine wrapped in a Future.""" @@ -83,7 +80,7 @@ # On Python 3.3 or older, objects with a destructor that are part of a # reference cycle are never destroyed. That's not the case any more on # Python 3.4 thanks to the PEP 442. - if _PY34: + if compat.PY34: def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: context = { diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -1,8 +1,6 @@ """Abstract Transport class.""" -import sys - -_PY34 = sys.version_info >= (3, 4) +from asyncio import compat __all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport', 'Transport', 'DatagramTransport', 'SubprocessTransport', @@ -94,12 +92,8 @@ The default implementation concatenates the arguments and calls write() on the result. """ - if not _PY34: - # In Python 3.3, bytes.join() doesn't handle memoryview. - list_of_data = ( - bytes(data) if isinstance(data, memoryview) else data - for data in list_of_data) - self.write(b''.join(list_of_data)) + data = compat.flatten_list_bytes(list_of_data) + self.write(data) def write_eof(self): """Close the write end after flushing buffered data. 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 @@ -446,6 +446,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): sock = socket.socket() @@ -457,12 +459,8 @@ 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): sock = socket.socket() @@ -522,6 +520,8 @@ def handle_client(self, client_reader, client_writer): data = yield from client_reader.readline() client_writer.write(data) + yield from client_writer.drain() + client_writer.close() def start(self): self.server = self.loop.run_until_complete( @@ -530,18 +530,14 @@ loop=self.loop)) 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) + self.loop.create_task(self.handle_client(client_reader, + client_writer)) def start_callback(self): - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client_callback, - path=self.path, - loop=self.loop)) + start = asyncio.start_unix_server(self.handle_client_callback, + path=self.path, + loop=self.loop) + self.server = self.loop.run_until_complete(start) def stop(self): if self.server is not None: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 08:25:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 25 Jul 2015 06:25:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_proper_overflo?= =?utf-8?q?w_checks_for_mymemreplace_=28closes_=2324708=29?= Message-ID: <20150725062554.11654.42601@psf.io> https://hg.python.org/cpython/rev/7b5513e5afd2 changeset: 97052:7b5513e5afd2 branch: 2.7 parent: 97044:7ba239d4efbb user: Benjamin Peterson date: Fri Jul 24 23:25:35 2015 -0700 summary: proper overflow checks for mymemreplace (closes #24708) files: Lib/test/test_strop.py | 5 +++++ Misc/NEWS | 2 ++ Modules/stropmodule.c | 11 +++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_strop.py b/Lib/test/test_strop.py --- a/Lib/test/test_strop.py +++ b/Lib/test/test_strop.py @@ -141,6 +141,11 @@ else: self.assertEqual(len(r), len(a) * 3) + @unittest.skipUnless(sys.maxsize == 2147483647, "only for 32-bit") + def test_stropreplace_overflow(self): + a = "A" * 0x10000 + self.assertRaises(MemoryError, strop.replace, a, "A", a) + transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #24708: Fix possible integer overflow in strop.replace(). + - Issue #24620: Random.setstate() now validates the value of state last element. - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c --- a/Modules/stropmodule.c +++ b/Modules/stropmodule.c @@ -1094,7 +1094,7 @@ { char *out_s; char *new_s; - Py_ssize_t nfound, offset, new_len; + Py_ssize_t nfound, offset, new_len, delta_len, abs_delta; if (len == 0 || pat_len > len) goto return_same; @@ -1108,7 +1108,14 @@ if (nfound == 0) goto return_same; - new_len = len + nfound*(sub_len - pat_len); + delta_len = sub_len - pat_len; + abs_delta = (delta_len < 0) ? -delta_len : delta_len; + if (PY_SSIZE_T_MAX/nfound < abs_delta) + return NULL; + delta_len *= nfound; + if (PY_SSIZE_T_MAX - len < delta_len) + return NULL; + new_len = len + delta_len; if (new_len == 0) { /* Have to allocate something for the caller to free(). */ out_s = (char *)PyMem_MALLOC(1); -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Jul 25 10:46:10 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 25 Jul 2015 08:46:10 +0000 Subject: [Python-checkins] Daily reference leaks (c53d24ee3963): sum=7 Message-ID: <20150725084609.97485.44695@psf.io> results for c53d24ee3963 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogJeXveN', '--timeout', '7200'] From python-checkins at python.org Sat Jul 25 11:11:37 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 25 Jul 2015 09:11:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE0Mzcz?= =?utf-8?q?=3A_Fixed_segmentation_fault_when_gc=2Ecollect=28=29_is_called_?= =?utf-8?q?during?= Message-ID: <20150725091137.20782.74368@psf.io> https://hg.python.org/cpython/rev/5345e5ce2eed changeset: 97053:5345e5ce2eed branch: 3.5 parent: 97050:6888979cd407 user: Serhiy Storchaka date: Sat Jul 25 12:10:21 2015 +0300 summary: Issue #14373: Fixed segmentation fault when gc.collect() is called during constructing lru_cache (C implementation). files: Misc/NEWS | 3 +++ Modules/_functoolsmodule.c | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #14373: Fixed segmentation fault when gc.collect() is called during + constructing lru_cache (C implementation). + - Issue #24695: Fix a regression in traceback.print_exception(). If exc_traceback is None we shouldn't print a traceback header like described in the documentation. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -899,7 +899,7 @@ static PyObject * lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - PyObject *func, *maxsize_O, *cache_info_type; + PyObject *func, *maxsize_O, *cache_info_type, *cachedict; int typed; lru_cache_object *obj; Py_ssize_t maxsize; @@ -937,15 +937,16 @@ return NULL; } - obj = (lru_cache_object *)type->tp_alloc(type, 0); - if (obj == NULL) + if (!(cachedict = PyDict_New())) return NULL; - if (!(obj->cache = PyDict_New())) { - Py_DECREF(obj); + obj = (lru_cache_object *)type->tp_alloc(type, 0); + if (obj == NULL) { + Py_DECREF(cachedict); return NULL; } + obj->cache = cachedict; obj->root.prev = &obj->root; obj->root.next = &obj->root; obj->maxsize = maxsize; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 11:11:37 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 25 Jul 2015 09:11:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2314373=3A_Fixed_segmentation_fault_when_gc=2Ecol?= =?utf-8?q?lect=28=29_is_called_during?= Message-ID: <20150725091137.97487.6284@psf.io> https://hg.python.org/cpython/rev/9c6d11d22801 changeset: 97054:9c6d11d22801 parent: 97051:c53d24ee3963 parent: 97053:5345e5ce2eed user: Serhiy Storchaka date: Sat Jul 25 12:11:00 2015 +0300 summary: Issue #14373: Fixed segmentation fault when gc.collect() is called during constructing lru_cache (C implementation). files: Misc/NEWS | 3 +++ Modules/_functoolsmodule.c | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,9 @@ Library ------- +- Issue #14373: Fixed segmentation fault when gc.collect() is called during + constructing lru_cache (C implementation). + - Issue #24695: Fix a regression in traceback.print_exception(). If exc_traceback is None we shouldn't print a traceback header like described in the documentation. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -899,7 +899,7 @@ static PyObject * lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - PyObject *func, *maxsize_O, *cache_info_type; + PyObject *func, *maxsize_O, *cache_info_type, *cachedict; int typed; lru_cache_object *obj; Py_ssize_t maxsize; @@ -937,15 +937,16 @@ return NULL; } - obj = (lru_cache_object *)type->tp_alloc(type, 0); - if (obj == NULL) + if (!(cachedict = PyDict_New())) return NULL; - if (!(obj->cache = PyDict_New())) { - Py_DECREF(obj); + obj = (lru_cache_object *)type->tp_alloc(type, 0); + if (obj == NULL) { + Py_DECREF(cachedict); return NULL; } + obj->cache = cachedict; obj->root.prev = &obj->root; obj->root.next = &obj->root; obj->maxsize = maxsize; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 12:03:55 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 10:03:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzEz?= =?utf-8?q?=3A_Use_importlib=2Ereload=28=29_in_import_reference_document?= =?utf-8?q?=2E?= Message-ID: <20150725100355.22221.93732@psf.io> https://hg.python.org/cpython/rev/6c713dcce26a changeset: 97055:6c713dcce26a branch: 3.4 parent: 97049:fc1d40a706e7 user: Berker Peksag date: Sat Jul 25 13:02:37 2015 +0300 summary: Issue #24713: Use importlib.reload() in import reference document. imp.reload() was deprecated in Python 3.4 and changed to call importlib.reload(). Patch by Petr Viktorin. files: Doc/reference/import.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -200,7 +200,7 @@ Beware though, as if you keep a reference to the module object, invalidate its cache entry in :data:`sys.modules`, and then re-import the named module, the two module objects will *not* be the same. By contrast, -:func:`imp.reload` will reuse the *same* module object, and simply +:func:`importlib.reload` will reuse the *same* module object, and simply reinitialise the module contents by rerunning the module's code. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 12:03:55 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 10:03:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324713=3A_Use_importlib=2Ereload=28=29_in_import_refer?= =?utf-8?q?ence_document=2E?= Message-ID: <20150725100355.3155.68917@psf.io> https://hg.python.org/cpython/rev/afb12ebd96df changeset: 97056:afb12ebd96df branch: 3.5 parent: 97053:5345e5ce2eed parent: 97055:6c713dcce26a user: Berker Peksag date: Sat Jul 25 13:03:08 2015 +0300 summary: Issue #24713: Use importlib.reload() in import reference document. imp.reload() was deprecated in Python 3.4 and changed to call importlib.reload(). Patch by Petr Viktorin. files: Doc/reference/import.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -200,7 +200,7 @@ Beware though, as if you keep a reference to the module object, invalidate its cache entry in :data:`sys.modules`, and then re-import the named module, the two module objects will *not* be the same. By contrast, -:func:`imp.reload` will reuse the *same* module object, and simply +:func:`importlib.reload` will reuse the *same* module object, and simply reinitialise the module contents by rerunning the module's code. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 12:03:55 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 10:03:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324713=3A_Use_importlib=2Ereload=28=29_in_import?= =?utf-8?q?_reference_document=2E?= Message-ID: <20150725100355.3149.45194@psf.io> https://hg.python.org/cpython/rev/5fb7d3238248 changeset: 97057:5fb7d3238248 parent: 97054:9c6d11d22801 parent: 97056:afb12ebd96df user: Berker Peksag date: Sat Jul 25 13:03:30 2015 +0300 summary: Issue #24713: Use importlib.reload() in import reference document. imp.reload() was deprecated in Python 3.4 and changed to call importlib.reload(). Patch by Petr Viktorin. files: Doc/reference/import.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -200,7 +200,7 @@ Beware though, as if you keep a reference to the module object, invalidate its cache entry in :data:`sys.modules`, and then re-import the named module, the two module objects will *not* be the same. By contrast, -:func:`imp.reload` will reuse the *same* module object, and simply +:func:`importlib.reload` will reuse the *same* module object, and simply reinitialise the module contents by rerunning the module's code. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:15:18 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:15:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjc5?= =?utf-8?q?=3A_Update_test=5Fbase64_to_use_test=2Esupport=2Escript=5Fhelpe?= =?utf-8?q?r=2E?= Message-ID: <20150725111518.24768.81684@psf.io> https://hg.python.org/cpython/rev/8e1291cc8b69 changeset: 97058:8e1291cc8b69 branch: 3.5 parent: 97056:afb12ebd96df user: Berker Peksag date: Sat Jul 25 14:14:24 2015 +0300 summary: Issue #24279: Update test_base64 to use test.support.script_helper. Initial patch by Christie. files: Lib/test/test_base64.py | 26 +++++++++----------------- 1 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -3,10 +3,8 @@ import base64 import binascii import os -import sys -import subprocess -import struct from array import array +from test.support import script_helper class LegacyBase64TestCase(unittest.TestCase): @@ -622,15 +620,13 @@ self.assertTrue(issubclass(binascii.Error, ValueError)) - class TestMain(unittest.TestCase): def tearDown(self): if os.path.exists(support.TESTFN): os.unlink(support.TESTFN) - def get_output(self, *args, **options): - args = (sys.executable, '-m', 'base64') + args - return subprocess.check_output(args, **options) + def get_output(self, *args): + return script_helper.assert_python_ok('-m', 'base64', *args).out def test_encode_decode(self): output = self.get_output('-t') @@ -643,13 +639,14 @@ def test_encode_file(self): with open(support.TESTFN, 'wb') as fp: fp.write(b'a\xffb\n') - output = self.get_output('-e', support.TESTFN) self.assertEqual(output.rstrip(), b'Yf9iCg==') - with open(support.TESTFN, 'rb') as fp: - output = self.get_output('-e', stdin=fp) - self.assertEqual(output.rstrip(), b'Yf9iCg==') + def test_encode_from_stdin(self): + with script_helper.spawn_python('-m', 'base64', '-e') as proc: + out, err = proc.communicate(b'a\xffb\n') + self.assertEqual(out.rstrip(), b'Yf9iCg==') + self.assertIsNone(err) def test_decode(self): with open(support.TESTFN, 'wb') as fp: @@ -657,10 +654,5 @@ output = self.get_output('-d', support.TESTFN) self.assertEqual(output.rstrip(), b'a\xffb') - - -def test_main(): - support.run_unittest(__name__) - if __name__ == '__main__': - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:15:18 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:15:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324279=3A_Update_test=5Fbase64_to_use_test=2Esup?= =?utf-8?q?port=2Escript=5Fhelper=2E?= Message-ID: <20150725111518.8492.73770@psf.io> https://hg.python.org/cpython/rev/472f354c70b8 changeset: 97059:472f354c70b8 parent: 97057:5fb7d3238248 parent: 97058:8e1291cc8b69 user: Berker Peksag date: Sat Jul 25 14:14:50 2015 +0300 summary: Issue #24279: Update test_base64 to use test.support.script_helper. Initial patch by Christie. files: Lib/test/test_base64.py | 26 +++++++++----------------- 1 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -3,10 +3,8 @@ import base64 import binascii import os -import sys -import subprocess -import struct from array import array +from test.support import script_helper class LegacyBase64TestCase(unittest.TestCase): @@ -622,15 +620,13 @@ self.assertTrue(issubclass(binascii.Error, ValueError)) - class TestMain(unittest.TestCase): def tearDown(self): if os.path.exists(support.TESTFN): os.unlink(support.TESTFN) - def get_output(self, *args, **options): - args = (sys.executable, '-m', 'base64') + args - return subprocess.check_output(args, **options) + def get_output(self, *args): + return script_helper.assert_python_ok('-m', 'base64', *args).out def test_encode_decode(self): output = self.get_output('-t') @@ -643,13 +639,14 @@ def test_encode_file(self): with open(support.TESTFN, 'wb') as fp: fp.write(b'a\xffb\n') - output = self.get_output('-e', support.TESTFN) self.assertEqual(output.rstrip(), b'Yf9iCg==') - with open(support.TESTFN, 'rb') as fp: - output = self.get_output('-e', stdin=fp) - self.assertEqual(output.rstrip(), b'Yf9iCg==') + def test_encode_from_stdin(self): + with script_helper.spawn_python('-m', 'base64', '-e') as proc: + out, err = proc.communicate(b'a\xffb\n') + self.assertEqual(out.rstrip(), b'Yf9iCg==') + self.assertIsNone(err) def test_decode(self): with open(support.TESTFN, 'wb') as fp: @@ -657,10 +654,5 @@ output = self.get_output('-d', support.TESTFN) self.assertEqual(output.rstrip(), b'a\xffb') - - -def test_main(): - support.run_unittest(__name__) - if __name__ == '__main__': - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:17:38 2015 From: python-checkins at python.org (ronald.oussoren) Date: Sat, 25 Jul 2015 11:17:38 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Furhter_updates?= Message-ID: <20150725111738.24786.80943@psf.io> https://hg.python.org/peps/rev/22d30cd3c701 changeset: 5911:22d30cd3c701 user: Ronald Oussoren date: Sat Jul 25 13:17:34 2015 +0200 summary: Furhter updates files: pep-0447.txt | 101 +++++++++++++++++++++++++++++++------- 1 files changed, 81 insertions(+), 20 deletions(-) diff --git a/pep-0447.txt b/pep-0447.txt --- a/pep-0447.txt +++ b/pep-0447.txt @@ -56,7 +56,8 @@ It is currently not possible to influence how the `super class`_ looks up attributes (that is, ``super.__getattribute__`` unconditionally peeks in the class ``__dict__``), and that can be problematic for -dynamic classes that can grow new methods on demand. +dynamic classes that can grow new methods on demand, for example dynamic +proxy classes. The ``__getdescriptor__`` method makes it possible to dynamically add attributes even when looking them up using the `super class`_. @@ -113,7 +114,8 @@ straightforward, but not entirely so without reading C code. The current CPython implementation of object.__getattribute__ is basicly -equivalent to the following (pseudo-) Python code (excluding some house keeping and speed tricks):: +equivalent to the following (pseudo-) Python code (excluding some house +keeping and speed tricks):: def _PyType_Lookup(tp, name): @@ -269,6 +271,9 @@ In C code --------- +A new type flag ``Py_TPFLAGS_GETDESCRIPTOR`` with value ``(1UL << 11)`` that +indicates that the new slot is present and to be used. + A new slot ``tp_getdescriptor`` is added to the ``PyTypeObject`` struct, this slot corresponds to the ``__getdescriptor__`` method on `type`_. @@ -281,6 +286,9 @@ without setting an exception when the *name* cannot be found, and returns a new reference otherwise (not a borrowed reference). +Classes with a ``tp_getdescriptor`` slot must add ``Py_TPFLAGS_GETDESCRIPTOR`` +to ``tp_flags`` to indicate that new slot must be used. + Use of this hook by the interpreter ----------------------------------- @@ -300,12 +308,16 @@ this will cause compile-time errors for all out-of-tree users of this private API. +For the same reason ``_PyType_LookupId`` is renamed to ``_PyType_LookupId2``. +A number of other functions in typeobject.c with the same issue do not get +an updated name because they are private to that file. + The attribute lookup cache in ``Objects/typeobject.c`` is disabled for classes that have a metaclass that overrides ``__getdescriptor__``, because using the cache might not be valid for such classes. Impact of this PEP on introspection ------------------------------------ +=================================== Use of the method introduced in this PEP can affect introspection of classes with a metaclass that uses a custom ``__getdescriptor__`` method. This section @@ -334,33 +346,46 @@ be ignored and is another way in which the result of ``inspect.getattr_static`` can be different from that of ``builtin.getattr``. -* ``inspect.getmembers`` and ``inspect.get_class_attrs`` +* ``inspect.getmembers`` and ``inspect.classify_class_attrs`` Both of these functions directly access the class __dict__ of classes along the MRO, and hence can be affected by a custom ``__getdescriptor__`` method. - **TODO**: I haven't fully worked out what the impact of this is, and if there - are mitigations for those using either updates to these functions, or - additional methods that users should implement to be fully compatible with - these functions. + Code with a custom ``__getdescriptor__`` method that want to play nice with + these methods also needs to ensure that the ``__dict__`` is set up correctly + when that is accessed directly by Python code. - One possible mitigation is to have a custom ``__getattribute__`` for these - classes that fills ``__dict__`` before returning and and defers to the - default implementation for other attributes. + Note that ``inspect.getmembers`` is used by ``pydoc`` and hence this can + affect runtime documentation introspection. * Direct introspection of the class ``__dict__`` Any code that directly access the class ``__dict__`` for introspection - can be affected by a custom ``__getdescriptor__`` method. + can be affected by a custom ``__getdescriptor__`` method, see the previous + item. Performance impact ------------------- +================== **WARNING**: The benchmark results in this section are old, and will be updated when I've ported the patch to the current trunk. I don't expect significant changes to the results in this section. +Micro benchmarks +---------------- + +`Issue 18181`_ has a micro benchmark as one of its attachments +(`pep447-micro-bench.py`_) that specifically tests the speed of attribute +lookup, both directly and through super. + +Note that attribute lookup with deep class hierarchies is significantly slower +when using a custom ``__getdescriptor__`` method. This is because the +attribute lookup cache for CPython cannot be used when having this method. + +Pybench +------- + The pybench output below compares an implementation of this PEP with the regular source tree, both based on changeset a5681f50bae2, run on an idle machine an Core i7 processor running Centos 6.4. @@ -579,10 +604,10 @@ Alternative proposals ---------------------- +===================== ``__getattribute_super__`` -.......................... +-------------------------- An earlier version of this PEP used the following static method on classes:: @@ -593,7 +618,7 @@ Reuse ``tp_getattro`` -..................... +--------------------- It would be nice to avoid adding a new slot, thus keeping the API simpler and easier to understand. A comment on `Issue 18181`_ asked about reusing the @@ -605,16 +630,44 @@ This would mean that using ``tp_getattro`` instead of peeking the class dictionaries changes the semantics of the `super class`_. -Alternate placement of the new method -..................................... +Alternative placement of the new method +--------------------------------------- This PEP proposes to add ``__getdescriptor__`` as a method on the metaclass. An alternative would be to add it as a class method on the class itself (simular to how ``__new__`` is a `staticmethod`_ of the class and not a method of the metaclass). -The two are functionally equivalent, and there's something to be said about -not requiring the use of a meta class. +The advantage of using a method on the metaclass is that will give an error +when two classes on the MRO have different metaclasses that may have different +behaviors for ``__getdescriptor__``. With a normal classmethod that problem +would pass undetected while it might cause subtle errors when running the code. + +History +======= + +* 23-Jul-2015: Added type flag ``Py_TPFLAGS_GETDESCRIPTOR`` after talking + with Guido. + + The new flag is primarily useful to avoid crashing when loading an extension + for an older version of CPython and could have positive speed implications + as well. + +* Jul-2014: renamed slot to ``__getdescriptor__``, the old name didn't + match the naming style of other slots and was less descriptive. + +Discussion threads +================== + +* The initial version of the PEP was send with + Message-ID `<75030FAC-6918-4E94-95DA-67A88D53E6F5 at mac.com>`_ + +* Further discusion starting at a message with + Message-ID `<5BB87CC4-F31B-4213-AAAC-0C0CE738460C at mac.com>`_ + +* And more discussion starting at message with + Message-ID `<00AA7433-C853-4101-9718-060468EBAC54 at mac.com>`_ + References @@ -627,6 +680,12 @@ This document has been placed in the public domain. +.. _`<75030FAC-6918-4E94-95DA-67A88D53E6F5 at mac.com>`: http://marc.info/?l=python-dev&m=137510220928964&w=2 + +.. _`<5BB87CC4-F31B-4213-AAAC-0C0CE738460C at mac.com>`: https://mail.python.org/pipermail/python-ideas/2014-July/028420.html + +.. _`<00AA7433-C853-4101-9718-060468EBAC54 at mac.com>`: https://mail.python.org/pipermail/python-dev/2013-July/127321.html + .. _`Issue 18181`: http://bugs.python.org/issue18181 .. _`super class`: http://docs.python.org/3/library/functions.html#super @@ -652,3 +711,5 @@ .. _`PyObjC`: http://pyobjc.sourceforge.net/ .. _`classmethod`: http://docs.python.org/3/library/functions.html#classmethod + +.. _`pep447-micro-bench.py`: http://bugs.python.org/file40013/pep447-micro-bench.py -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Jul 25 13:28:16 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:28:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDIw?= =?utf-8?q?=3A_Fix_documentation_regression_introduced_by_f0a00ee094ff=2E?= Message-ID: <20150725112816.97469.72368@psf.io> https://hg.python.org/cpython/rev/bedff93d778d changeset: 97060:bedff93d778d branch: 3.5 parent: 97058:8e1291cc8b69 user: Berker Peksag date: Sat Jul 25 14:27:07 2015 +0300 summary: Issue #24420: Fix documentation regression introduced by f0a00ee094ff. These functions accept same arguments as subprocess.Popen(). Patch by Martin Panter. files: Doc/library/subprocess.rst | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -825,7 +825,7 @@ .. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) Run the command described by *args*. Wait for command to complete, then - return the :attr:`returncode` attribute. + return the :attr:`~Popen.returncode` attribute. This is equivalent to:: @@ -833,6 +833,11 @@ (except that the *input* and *check* parameters are not supported) + The arguments shown above are merely the most + common ones. The full function signature is largely the + same as that of the :class:`Popen` constructor - this function passes all + supplied arguments other than *timeout* directly through to that interface. + .. note:: Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this @@ -856,6 +861,11 @@ (except that the *input* parameter is not supported) + The arguments shown above are merely the most + common ones. The full function signature is largely the + same as that of the :class:`Popen` constructor - this function passes all + supplied arguments other than *timeout* directly through to that interface. + .. note:: Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this @@ -867,7 +877,7 @@ *timeout* was added. -.. function:: check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) +.. function:: check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) Run command with arguments and return its output. @@ -880,6 +890,12 @@ run(..., check=True, stdout=PIPE).stdout + The arguments shown above are merely the most common ones. + The full function signature is largely the same as that of :func:`run` - + most arguments are passed directly through to that interface. + However, explicitly passing ``input=None`` to inherit the parent's + standard input file handle is not supported. + By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level. @@ -902,7 +918,7 @@ *timeout* was added. .. versionchanged:: 3.4 - *input* was added. + Support for the *input* keyword argument was added. .. _subprocess-replacements: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:28:16 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:28:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324420=3A_Fix_documentation_regression_introduce?= =?utf-8?q?d_by_f0a00ee094ff=2E?= Message-ID: <20150725112816.20774.79654@psf.io> https://hg.python.org/cpython/rev/9b17df697a3c changeset: 97061:9b17df697a3c parent: 97059:472f354c70b8 parent: 97060:bedff93d778d user: Berker Peksag date: Sat Jul 25 14:27:32 2015 +0300 summary: Issue #24420: Fix documentation regression introduced by f0a00ee094ff. These functions accept same arguments as subprocess.Popen(). Patch by Martin Panter. files: Doc/library/subprocess.rst | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -825,7 +825,7 @@ .. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) Run the command described by *args*. Wait for command to complete, then - return the :attr:`returncode` attribute. + return the :attr:`~Popen.returncode` attribute. This is equivalent to:: @@ -833,6 +833,11 @@ (except that the *input* and *check* parameters are not supported) + The arguments shown above are merely the most + common ones. The full function signature is largely the + same as that of the :class:`Popen` constructor - this function passes all + supplied arguments other than *timeout* directly through to that interface. + .. note:: Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this @@ -856,6 +861,11 @@ (except that the *input* parameter is not supported) + The arguments shown above are merely the most + common ones. The full function signature is largely the + same as that of the :class:`Popen` constructor - this function passes all + supplied arguments other than *timeout* directly through to that interface. + .. note:: Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this @@ -867,7 +877,7 @@ *timeout* was added. -.. function:: check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) +.. function:: check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) Run command with arguments and return its output. @@ -880,6 +890,12 @@ run(..., check=True, stdout=PIPE).stdout + The arguments shown above are merely the most common ones. + The full function signature is largely the same as that of :func:`run` - + most arguments are passed directly through to that interface. + However, explicitly passing ``input=None`` to inherit the parent's + standard input file handle is not supported. + By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level. @@ -902,7 +918,7 @@ *timeout* was added. .. versionchanged:: 3.4 - *input* was added. + Support for the *input* keyword argument was added. .. _subprocess-replacements: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:56:16 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:56:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNjk3?= =?utf-8?q?=3A_shutil=2Ecopytree=28=29_now_correctly_handles_symbolic_link?= =?utf-8?q?s_that_point?= Message-ID: <20150725115616.20792.8212@psf.io> https://hg.python.org/cpython/rev/e807f1d81cb6 changeset: 97062:e807f1d81cb6 branch: 3.4 parent: 97055:6c713dcce26a user: Berker Peksag date: Sat Jul 25 14:53:48 2015 +0300 summary: Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. files: Lib/shutil.py | 6 +++++- Lib/test/test_shutil.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -321,7 +321,11 @@ if not os.path.exists(linkto) and ignore_dangling_symlinks: continue # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) + if os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, + copy_function) + else: + copy_function(srcname, dstname) elif os.path.isdir(srcname): copytree(srcname, dstname, symlinks, ignore, copy_function) else: 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 @@ -895,6 +895,26 @@ shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) + @support.skip_unless_symlink + def test_copytree_symlink_dir(self): + src_dir = self.mkdtemp() + dst_dir = os.path.join(self.mkdtemp(), 'destination') + os.mkdir(os.path.join(src_dir, 'real_dir')) + with open(os.path.join(src_dir, 'real_dir', 'test.txt'), 'w'): + pass + os.symlink(os.path.join(src_dir, 'real_dir'), + os.path.join(src_dir, 'link_to_dir'), + target_is_directory=True) + + shutil.copytree(src_dir, dst_dir, symlinks=False) + self.assertFalse(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + + dst_dir = os.path.join(self.mkdtemp(), 'destination2') + shutil.copytree(src_dir, dst_dir, symlinks=True) + self.assertTrue(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + def _copy_file(self, method): fname = 'test.txt' tmpdir = self.mkdtemp() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #21697: shutil.copytree() now correctly handles symbolic links that + point to directories. Patch by Eduardo Seabra and Thomas Kluyver. + - Issue #24620: Random.setstate() now validates the value of state last element. - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:56:16 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:56:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321697=3A_shutil=2Ecopytree=28=29_now_correctly_?= =?utf-8?q?handles_symbolic_links_that_point?= Message-ID: <20150725115616.8494.76498@psf.io> https://hg.python.org/cpython/rev/8f65be73eb3a changeset: 97064:8f65be73eb3a parent: 97061:9b17df697a3c parent: 97063:31f4041b9286 user: Berker Peksag date: Sat Jul 25 14:55:32 2015 +0300 summary: Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. files: Lib/shutil.py | 6 +++++- Lib/test/test_shutil.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -327,7 +327,11 @@ if not os.path.exists(linkto) and ignore_dangling_symlinks: continue # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) + if os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, + copy_function) + else: + copy_function(srcname, dstname) elif os.path.isdir(srcname): copytree(srcname, dstname, symlinks, ignore, copy_function) else: 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 @@ -901,6 +901,26 @@ shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) + @support.skip_unless_symlink + def test_copytree_symlink_dir(self): + src_dir = self.mkdtemp() + dst_dir = os.path.join(self.mkdtemp(), 'destination') + os.mkdir(os.path.join(src_dir, 'real_dir')) + with open(os.path.join(src_dir, 'real_dir', 'test.txt'), 'w'): + pass + os.symlink(os.path.join(src_dir, 'real_dir'), + os.path.join(src_dir, 'link_to_dir'), + target_is_directory=True) + + shutil.copytree(src_dir, dst_dir, symlinks=False) + self.assertFalse(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + + dst_dir = os.path.join(self.mkdtemp(), 'destination2') + shutil.copytree(src_dir, dst_dir, symlinks=True) + self.assertTrue(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + def _copy_file(self, method): fname = 'test.txt' tmpdir = self.mkdtemp() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,9 @@ Library ------- +- Issue #21697: shutil.copytree() now correctly handles symbolic links that + point to directories. Patch by Eduardo Seabra and Thomas Kluyver. + - Issue #14373: Fixed segmentation fault when gc.collect() is called during constructing lru_cache (C implementation). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 13:56:16 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 25 Jul 2015 11:56:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321697=3A_shutil=2Ecopytree=28=29_now_correctly_handle?= =?utf-8?q?s_symbolic_links_that_point?= Message-ID: <20150725115616.9208.52984@psf.io> https://hg.python.org/cpython/rev/31f4041b9286 changeset: 97063:31f4041b9286 branch: 3.5 parent: 97060:bedff93d778d parent: 97062:e807f1d81cb6 user: Berker Peksag date: Sat Jul 25 14:55:06 2015 +0300 summary: Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. files: Lib/shutil.py | 6 +++++- Lib/test/test_shutil.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -327,7 +327,11 @@ if not os.path.exists(linkto) and ignore_dangling_symlinks: continue # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) + if os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, + copy_function) + else: + copy_function(srcname, dstname) elif os.path.isdir(srcname): copytree(srcname, dstname, symlinks, ignore, copy_function) else: 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 @@ -901,6 +901,26 @@ shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) + @support.skip_unless_symlink + def test_copytree_symlink_dir(self): + src_dir = self.mkdtemp() + dst_dir = os.path.join(self.mkdtemp(), 'destination') + os.mkdir(os.path.join(src_dir, 'real_dir')) + with open(os.path.join(src_dir, 'real_dir', 'test.txt'), 'w'): + pass + os.symlink(os.path.join(src_dir, 'real_dir'), + os.path.join(src_dir, 'link_to_dir'), + target_is_directory=True) + + shutil.copytree(src_dir, dst_dir, symlinks=False) + self.assertFalse(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + + dst_dir = os.path.join(self.mkdtemp(), 'destination2') + shutil.copytree(src_dir, dst_dir, symlinks=True) + self.assertTrue(os.path.islink(os.path.join(dst_dir, 'link_to_dir'))) + self.assertIn('test.txt', os.listdir(os.path.join(dst_dir, 'link_to_dir'))) + def _copy_file(self, method): fname = 'test.txt' tmpdir = self.mkdtemp() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #21697: shutil.copytree() now correctly handles symbolic links that + point to directories. Patch by Eduardo Seabra and Thomas Kluyver. + - Issue #14373: Fixed segmentation fault when gc.collect() is called during constructing lru_cache (C implementation). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 19:20:31 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 25 Jul 2015 17:20:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_possible_memor?= =?utf-8?q?y_leak_in_error_case_=28closes_=2324719=29?= Message-ID: <20150725172031.22223.67591@psf.io> https://hg.python.org/cpython/rev/a789ee93f152 changeset: 97065:a789ee93f152 branch: 2.7 parent: 97052:7b5513e5afd2 user: Benjamin Peterson date: Sat Jul 25 10:20:13 2015 -0700 summary: possible memory leak in error case (closes #24719) Patch by Pankaj Sharma. files: Modules/cPickle.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/cPickle.c b/Modules/cPickle.c --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -2910,7 +2910,7 @@ if (ik >= lm || ik == 0) { PyErr_SetString(PicklingError, "Invalid get data"); - return NULL; + goto err; } have_get[ik] = 1; rsize += ik < 256 ? 2 : 5; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 20:43:31 2015 From: python-checkins at python.org (robert.collins) Date: Sat, 25 Jul 2015 18:43:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_-_Issue_=232091=3A_error_c?= =?utf-8?q?orrectly_on_open=28=29_with_mode_=27U=27_and_=27+=27?= Message-ID: <20150725184330.97461.36251@psf.io> https://hg.python.org/cpython/rev/1a5bbb31f740 changeset: 97066:1a5bbb31f740 parent: 97064:8f65be73eb3a user: Robert Collins date: Sun Jul 26 06:43:13 2015 +1200 summary: - Issue #2091: error correctly on open() with mode 'U' and '+' open() accepted a 'U' mode string containing '+', but 'U' can only be used with 'r'. Patch from Jeff Balogh and John O'Connor. files: Lib/_pyio.py | 4 ++-- Lib/test/test_file.py | 2 +- Misc/NEWS | 3 +++ Modules/_io/_iomodule.c | 16 ++++++++-------- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -181,8 +181,8 @@ text = "t" in modes binary = "b" in modes if "U" in modes: - if creating or writing or appending: - raise ValueError("can't use U and writing mode at once") + if creating or writing or appending or updating: + raise ValueError("mode U cannot be combined with 'x', 'w', 'a', or '+'") import warnings warnings.warn("'U' mode is deprecated", DeprecationWarning, 2) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -139,7 +139,7 @@ def testModeStrings(self): # check invalid mode strings - for mode in ("", "aU", "wU+"): + for mode in ("", "aU", "wU+", "U+", "+U", "rU+"): try: f = self.open(TESTFN, mode) except ValueError: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. +- Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can + only be used with 'r'. Patch from Jeff Balogh and John O'Connor. + - Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -248,8 +248,8 @@ _Py_IDENTIFIER(close); if (!PyUnicode_Check(file) && - !PyBytes_Check(file) && - !PyNumber_Check(file)) { + !PyBytes_Check(file) && + !PyNumber_Check(file)) { PyErr_Format(PyExc_TypeError, "invalid file: %R", file); return NULL; } @@ -307,9 +307,9 @@ /* Parameters validation */ if (universal) { - if (writing || appending) { + if (creating || writing || appending || updating) { PyErr_SetString(PyExc_ValueError, - "can't use U and writing mode at once"); + "mode U cannot be combined with x', 'w', 'a', or '+'"); return NULL; } if (PyErr_WarnEx(PyExc_DeprecationWarning, @@ -437,10 +437,10 @@ /* wraps into a TextIOWrapper */ wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type, - "Osssi", - buffer, - encoding, errors, newline, - line_buffering); + "Osssi", + buffer, + encoding, errors, newline, + line_buffering); if (wrapper == NULL) goto error; result = wrapper; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Jul 25 20:51:10 2015 From: python-checkins at python.org (robert.collins) Date: Sat, 25 Jul 2015 18:51:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324710=3A_Use_cls_?= =?utf-8?q?in_TracebackException=2Efrom=5Fexception=2E?= Message-ID: <20150725185110.109932.11094@psf.io> https://hg.python.org/cpython/rev/1be4d7388279 changeset: 97067:1be4d7388279 user: Robert Collins date: Sun Jul 26 06:50:51 2015 +1200 summary: Issue #24710: Use cls in TracebackException.from_exception. Minor cleanup patch from Berker Peksag. files: Lib/traceback.py | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -477,10 +477,9 @@ self._load_lines() @classmethod - def from_exception(self, exc, *args, **kwargs): + def from_exception(cls, exc, *args, **kwargs): """Create a TracebackException from an exception.""" - return TracebackException( - type(exc), exc, exc.__traceback__, *args, **kwargs) + return cls(type(exc), exc, exc.__traceback__, *args, **kwargs) def _load_lines(self): """Private API. force all lines in the stack to be loaded.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 07:50:55 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 26 Jul 2015 05:50:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NjEz?= =?utf-8?q?=3A_Calling_array=2Efromstring=28=29_with_self_is_no_longer_all?= =?utf-8?q?owed?= Message-ID: <20150726055055.9220.97964@psf.io> https://hg.python.org/cpython/rev/2d39777f3477 changeset: 97068:2d39777f3477 branch: 2.7 parent: 97065:a789ee93f152 user: Serhiy Storchaka date: Sun Jul 26 08:49:37 2015 +0300 summary: Issue #24613: Calling array.fromstring() with self is no longer allowed to prevent the use-after-free error. Patch by John Leitch. files: Lib/test/test_array.py | 1 + Misc/NEWS | 3 +++ Modules/arraymodule.c | 5 +++++ 3 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -247,6 +247,7 @@ self.assertRaises(TypeError, a.tostring, 42) self.assertRaises(TypeError, b.fromstring) self.assertRaises(TypeError, b.fromstring, 42) + self.assertRaises(ValueError, a.fromstring, a) b.fromstring(a.tostring()) self.assertEqual(a, b) if a.itemsize>1: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #24613: Calling array.fromstring() with self is no longer allowed + to prevent the use-after-free error. Patch by John Leitch. + - Issue #24708: Fix possible integer overflow in strop.replace(). - Issue #24620: Random.setstate() now validates the value of state last element. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1380,6 +1380,11 @@ int itemsize = self->ob_descr->itemsize; if (!PyArg_ParseTuple(args, "s#:fromstring", &str, &n)) return NULL; + if (str == self->ob_item) { + PyErr_SetString(PyExc_ValueError, + "array.fromstring(x): x cannot be self"); + return NULL; + } if (n % itemsize != 0) { PyErr_SetString(PyExc_ValueError, "string length not a multiple of item size"); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 08:04:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 26 Jul 2015 06:04:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Njgz?= =?utf-8?q?=3A_Fixed_crashes_in_=5Fjson_functions_called_with_arguments_of?= Message-ID: <20150726060439.113862.55772@psf.io> https://hg.python.org/cpython/rev/b3d0bf112f70 changeset: 97069:b3d0bf112f70 branch: 3.4 parent: 97062:e807f1d81cb6 user: Serhiy Storchaka date: Sun Jul 26 09:01:22 2015 +0300 summary: Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. files: Lib/test/test_json/test_separators.py | 6 ++++++ Misc/NEWS | 3 +++ Modules/_json.c | 12 ++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_json/test_separators.py b/Lib/test/test_json/test_separators.py --- a/Lib/test/test_json/test_separators.py +++ b/Lib/test/test_json/test_separators.py @@ -39,6 +39,12 @@ self.assertEqual(h2, h) self.assertEqual(d2, expect) + def test_illegal_separators(self): + h = {1: 2, 3: 4} + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', ': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(', ', b': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', b': ')) + class TestPySeparators(TestSeparators, PyTest): pass class TestCSeparators(TestSeparators, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #24683: Fixed crashes in _json functions called with arguments of + inappropriate type. + - Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1223,11 +1223,19 @@ assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, - &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist, + &markers, &defaultfn, &encoder, &indent, + &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; + if (markers != Py_None && !PyDict_Check(markers)) { + PyErr_Format(PyExc_TypeError, + "make_encoder() argument 1 must be dict or None, " + "not %.200s", Py_TYPE(markers)->tp_name); + return -1; + } + s->markers = markers; s->defaultfn = defaultfn; s->encoder = encoder; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 08:04:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 26 Jul 2015 06:04:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324683=3A_Fixed_crashes_in_=5Fjson_functions_called_wi?= =?utf-8?q?th_arguments_of?= Message-ID: <20150726060439.110130.45821@psf.io> https://hg.python.org/cpython/rev/ef4d09399b99 changeset: 97070:ef4d09399b99 branch: 3.5 parent: 97063:31f4041b9286 parent: 97069:b3d0bf112f70 user: Serhiy Storchaka date: Sun Jul 26 09:02:23 2015 +0300 summary: Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. files: Lib/test/test_json/test_separators.py | 6 ++++++ Misc/NEWS | 3 +++ Modules/_json.c | 12 ++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_json/test_separators.py b/Lib/test/test_json/test_separators.py --- a/Lib/test/test_json/test_separators.py +++ b/Lib/test/test_json/test_separators.py @@ -39,6 +39,12 @@ self.assertEqual(h2, h) self.assertEqual(d2, expect) + def test_illegal_separators(self): + h = {1: 2, 3: 4} + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', ': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(', ', b': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', b': ')) + class TestPySeparators(TestSeparators, PyTest): pass class TestCSeparators(TestSeparators, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #24683: Fixed crashes in _json functions called with arguments of + inappropriate type. + - Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1344,11 +1344,19 @@ assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, - &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist, + &markers, &defaultfn, &encoder, &indent, + &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; + if (markers != Py_None && !PyDict_Check(markers)) { + PyErr_Format(PyExc_TypeError, + "make_encoder() argument 1 must be dict or None, " + "not %.200s", Py_TYPE(markers)->tp_name); + return -1; + } + s->markers = markers; s->defaultfn = defaultfn; s->encoder = encoder; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 08:04:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 26 Jul 2015 06:04:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324683=3A_Fixed_crashes_in_=5Fjson_functions_cal?= =?utf-8?q?led_with_arguments_of?= Message-ID: <20150726060439.110430.48074@psf.io> https://hg.python.org/cpython/rev/7de4abf4eed2 changeset: 97071:7de4abf4eed2 parent: 97067:1be4d7388279 parent: 97070:ef4d09399b99 user: Serhiy Storchaka date: Sun Jul 26 09:03:16 2015 +0300 summary: Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. files: Lib/test/test_json/test_separators.py | 6 ++++++ Misc/NEWS | 3 +++ Modules/_json.c | 12 ++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_json/test_separators.py b/Lib/test/test_json/test_separators.py --- a/Lib/test/test_json/test_separators.py +++ b/Lib/test/test_json/test_separators.py @@ -39,6 +39,12 @@ self.assertEqual(h2, h) self.assertEqual(d2, expect) + def test_illegal_separators(self): + h = {1: 2, 3: 4} + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', ': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(', ', b': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', b': ')) + class TestPySeparators(TestSeparators, PyTest): pass class TestCSeparators(TestSeparators, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,9 @@ Library ------- +- Issue #24683: Fixed crashes in _json functions called with arguments of + inappropriate type. + - Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1344,11 +1344,19 @@ assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, - &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist, + &markers, &defaultfn, &encoder, &indent, + &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; + if (markers != Py_None && !PyDict_Check(markers)) { + PyErr_Format(PyExc_TypeError, + "make_encoder() argument 1 must be dict or None, " + "not %.200s", Py_TYPE(markers)->tp_name); + return -1; + } + s->markers = markers; s->defaultfn = defaultfn; s->encoder = encoder; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 08:08:52 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 26 Jul 2015 06:08:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Njgz?= =?utf-8?q?=3A_Fixed_a_crash_in_=5Fjson=2Emake=5Fencoder=28=29_called_with?= =?utf-8?q?_non-dict_1st?= Message-ID: <20150726060852.3173.96756@psf.io> https://hg.python.org/cpython/rev/0a1266ef1b5d changeset: 97072:0a1266ef1b5d branch: 2.7 parent: 97068:2d39777f3477 user: Serhiy Storchaka date: Sun Jul 26 09:07:53 2015 +0300 summary: Issue #24683: Fixed a crash in _json.make_encoder() called with non-dict 1st argument. files: Modules/_json.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1850,6 +1850,13 @@ if (allow_nan < 0) return -1; + if (markers != Py_None && !PyDict_Check(markers)) { + PyErr_Format(PyExc_TypeError, + "make_encoder() argument 1 must be dict or None, " + "not %.200s", Py_TYPE(markers)->tp_name); + return -1; + } + s->markers = markers; s->defaultfn = defaultfn; s->encoder = encoder; -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Jul 26 10:42:25 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 26 Jul 2015 08:42:25 +0000 Subject: [Python-checkins] Daily reference leaks (1be4d7388279): sum=4 Message-ID: <20150726084225.22211.24129@psf.io> results for 1be4d7388279 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog_bie9q', '--timeout', '7200'] From python-checkins at python.org Sun Jul 26 13:12:04 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 26 Jul 2015 11:12:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2320544=3A_use_spe?= =?utf-8?q?cific_asserts_in_operator_tests=2E?= Message-ID: <20150726111203.113886.81377@psf.io> https://hg.python.org/cpython/rev/7bf3d91f8d6c changeset: 97073:7bf3d91f8d6c parent: 97071:7de4abf4eed2 user: Antoine Pitrou date: Sun Jul 26 13:11:49 2015 +0200 summary: Closes #20544: use specific asserts in operator tests. Patch by Serhiy. files: Lib/test/test_operator.py | 50 +++++++++++++------------- 1 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -120,63 +120,63 @@ operator = self.module self.assertRaises(TypeError, operator.add) self.assertRaises(TypeError, operator.add, None, None) - self.assertTrue(operator.add(3, 4) == 7) + self.assertEqual(operator.add(3, 4), 7) def test_bitwise_and(self): operator = self.module self.assertRaises(TypeError, operator.and_) self.assertRaises(TypeError, operator.and_, None, None) - self.assertTrue(operator.and_(0xf, 0xa) == 0xa) + self.assertEqual(operator.and_(0xf, 0xa), 0xa) def test_concat(self): operator = self.module self.assertRaises(TypeError, operator.concat) self.assertRaises(TypeError, operator.concat, None, None) - self.assertTrue(operator.concat('py', 'thon') == 'python') - self.assertTrue(operator.concat([1, 2], [3, 4]) == [1, 2, 3, 4]) - self.assertTrue(operator.concat(Seq1([5, 6]), Seq1([7])) == [5, 6, 7]) - self.assertTrue(operator.concat(Seq2([5, 6]), Seq2([7])) == [5, 6, 7]) + self.assertEqual(operator.concat('py', 'thon'), 'python') + self.assertEqual(operator.concat([1, 2], [3, 4]), [1, 2, 3, 4]) + self.assertEqual(operator.concat(Seq1([5, 6]), Seq1([7])), [5, 6, 7]) + self.assertEqual(operator.concat(Seq2([5, 6]), Seq2([7])), [5, 6, 7]) self.assertRaises(TypeError, operator.concat, 13, 29) def test_countOf(self): operator = self.module self.assertRaises(TypeError, operator.countOf) self.assertRaises(TypeError, operator.countOf, None, None) - self.assertTrue(operator.countOf([1, 2, 1, 3, 1, 4], 3) == 1) - self.assertTrue(operator.countOf([1, 2, 1, 3, 1, 4], 5) == 0) + self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 3), 1) + self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 5), 0) def test_delitem(self): operator = self.module a = [4, 3, 2, 1] self.assertRaises(TypeError, operator.delitem, a) self.assertRaises(TypeError, operator.delitem, a, None) - self.assertTrue(operator.delitem(a, 1) is None) - self.assertTrue(a == [4, 2, 1]) + self.assertIsNone(operator.delitem(a, 1)) + self.assertEqual(a, [4, 2, 1]) def test_floordiv(self): operator = self.module self.assertRaises(TypeError, operator.floordiv, 5) self.assertRaises(TypeError, operator.floordiv, None, None) - self.assertTrue(operator.floordiv(5, 2) == 2) + self.assertEqual(operator.floordiv(5, 2), 2) def test_truediv(self): operator = self.module self.assertRaises(TypeError, operator.truediv, 5) self.assertRaises(TypeError, operator.truediv, None, None) - self.assertTrue(operator.truediv(5, 2) == 2.5) + self.assertEqual(operator.truediv(5, 2), 2.5) def test_getitem(self): operator = self.module a = range(10) self.assertRaises(TypeError, operator.getitem) self.assertRaises(TypeError, operator.getitem, a, None) - self.assertTrue(operator.getitem(a, 2) == 2) + self.assertEqual(operator.getitem(a, 2), 2) def test_indexOf(self): operator = self.module self.assertRaises(TypeError, operator.indexOf) self.assertRaises(TypeError, operator.indexOf, None, None) - self.assertTrue(operator.indexOf([4, 3, 2, 1], 3) == 1) + self.assertEqual(operator.indexOf([4, 3, 2, 1], 3), 1) self.assertRaises(ValueError, operator.indexOf, [4, 3, 2, 1], 0) def test_invert(self): @@ -189,21 +189,21 @@ operator = self.module self.assertRaises(TypeError, operator.lshift) self.assertRaises(TypeError, operator.lshift, None, 42) - self.assertTrue(operator.lshift(5, 1) == 10) - self.assertTrue(operator.lshift(5, 0) == 5) + self.assertEqual(operator.lshift(5, 1), 10) + self.assertEqual(operator.lshift(5, 0), 5) self.assertRaises(ValueError, operator.lshift, 2, -1) def test_mod(self): operator = self.module self.assertRaises(TypeError, operator.mod) self.assertRaises(TypeError, operator.mod, None, 42) - self.assertTrue(operator.mod(5, 2) == 1) + self.assertEqual(operator.mod(5, 2), 1) def test_mul(self): operator = self.module self.assertRaises(TypeError, operator.mul) self.assertRaises(TypeError, operator.mul, None, None) - self.assertTrue(operator.mul(5, 2) == 10) + self.assertEqual(operator.mul(5, 2), 10) def test_matmul(self): operator = self.module @@ -227,7 +227,7 @@ operator = self.module self.assertRaises(TypeError, operator.or_) self.assertRaises(TypeError, operator.or_, None, None) - self.assertTrue(operator.or_(0xa, 0x5) == 0xf) + self.assertEqual(operator.or_(0xa, 0x5), 0xf) def test_pos(self): operator = self.module @@ -250,8 +250,8 @@ operator = self.module self.assertRaises(TypeError, operator.rshift) self.assertRaises(TypeError, operator.rshift, None, 42) - self.assertTrue(operator.rshift(5, 1) == 2) - self.assertTrue(operator.rshift(5, 0) == 5) + self.assertEqual(operator.rshift(5, 1), 2) + self.assertEqual(operator.rshift(5, 0), 5) self.assertRaises(ValueError, operator.rshift, 2, -1) def test_contains(self): @@ -266,15 +266,15 @@ a = list(range(3)) self.assertRaises(TypeError, operator.setitem, a) self.assertRaises(TypeError, operator.setitem, a, None, None) - self.assertTrue(operator.setitem(a, 0, 2) is None) - self.assertTrue(a == [2, 1, 2]) + self.assertIsNone(operator.setitem(a, 0, 2)) + self.assertEqual(a, [2, 1, 2]) self.assertRaises(IndexError, operator.setitem, a, 4, 2) def test_sub(self): operator = self.module self.assertRaises(TypeError, operator.sub) self.assertRaises(TypeError, operator.sub, None, None) - self.assertTrue(operator.sub(5, 2) == 3) + self.assertEqual(operator.sub(5, 2), 3) def test_truth(self): operator = self.module @@ -292,7 +292,7 @@ operator = self.module self.assertRaises(TypeError, operator.xor) self.assertRaises(TypeError, operator.xor, None, None) - self.assertTrue(operator.xor(0xb, 0xc) == 0x7) + self.assertEqual(operator.xor(0xb, 0xc), 0x7) def test_is(self): operator = self.module -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 17:01:18 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 26 Jul 2015 15:01:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Version_bump_f?= =?utf-8?q?or_Python_3=2E5=2E0b4=2E?= Message-ID: <20150726150118.8498.46884@psf.io> https://hg.python.org/cpython/rev/c0d641054635 changeset: 97075:c0d641054635 branch: 3.5 tag: v3.5.0b4 user: Larry Hastings date: Sat Jul 25 14:22:13 2015 -0700 summary: Version bump for Python 3.5.0b4. files: Include/patchlevel.h | 4 ++-- Misc/NEWS | 4 ++-- README | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.5.0b3+" +#define PY_VERSION "3.5.0b4" /*--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 @@ -40,8 +40,8 @@ - Issue #24620: Random.setstate() now validates the value of state last element. -- Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect - results on nested functions. +- Issue #22485: Fixed an issue that caused `inspect.getsource` to return + incorrect results on nested functions. - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.5.0 beta 3 +This is Python version 3.5.0 beta 4 =================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 17:01:19 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 26 Jul 2015 15:01:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Post-release_u?= =?utf-8?q?pdates_for_Python_3=2E5=2E0b4=2E?= Message-ID: <20150726150119.11646.19716@psf.io> https://hg.python.org/cpython/rev/7e0b3b84c45e changeset: 97077:7e0b3b84c45e branch: 3.5 user: Larry Hastings date: Sun Jul 26 07:55:08 2015 -0700 summary: Post-release updates for Python 3.5.0b4. 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 4 /* Version as a string */ -#define PY_VERSION "3.5.0b4" +#define PY_VERSION "3.5.0b4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 release candidate 1? +=============================================== + +Release date: 2015-08-09 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 17:01:19 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 26 Jul 2015 15:01:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Updated_pydoc_?= =?utf-8?q?topics_for_3=2E5=2E0b4=2E?= Message-ID: <20150726150118.20792.14343@psf.io> https://hg.python.org/cpython/rev/a0019f7c8c7d changeset: 97074:a0019f7c8c7d branch: 3.5 parent: 97063:31f4041b9286 user: Larry Hastings date: Sat Jul 25 14:17:35 2015 -0700 summary: Updated pydoc topics for 3.5.0b4. files: Lib/pydoc_data/topics.py | 6 +++--- 1 files changed, 3 insertions(+), 3 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 Jul 4 19:11:05 2015 +# Autogenerated by Sphinx on Sat Jul 25 14:16:44 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -19,7 +19,7 @@ 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n', 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and "{2,3}" are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', - 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\nHowever, to simplify the parser, these keywords cannot be used on the\nsame line as a function or coroutine ("def" statement) header.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', 'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works as follows:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string as a\nleft argument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', @@ -51,7 +51,7 @@ 'numbers': u'\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', 'numeric-types': u'\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n', 'objects': u'\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, "id(x)" is the memory\naddress where "x" is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The "type()" function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (so\nyou should always close files explicitly).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement and the \'"with"\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n', - 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedence in Python, from\nlowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for exponentiation, which\ngroups from right to left).\n\nNote that comparisons, membership tests, and identity tests, all have\nthe same precedence and have a left-to-right chaining feature as\ndescribed in the *Comparisons* section.\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "@", "/", "//", "%" | Multiplication, matrix multiplication |\n| | division, remainder [5] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "await" "x" | Await expression |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0327\\u0043"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', + 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedence in Python, from\nlowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for exponentiation, which\ngroups from right to left).\n\nNote that comparisons, membership tests, and identity tests, all have\nthe same precedence and have a left-to-right chaining feature as\ndescribed in the *Comparisons* section.\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "@", "/", "//", "%" | Multiplication, matrix multiplication |\n| | division, remainder [5] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "await" "x" | Await expression |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0043\\u0327"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', 'pass': u'\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= await ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n', 'raise': u'\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "RuntimeError" exception is raised indicating\nthat this is an error.\n\nOtherwise, "raise" evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n"BaseException". If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the "__traceback__" attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the "with_traceback()" exception method (which returns\nthe same exception instance, with its traceback set to its argument),\nlike so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe "from" clause is used for exception chaining: if given, the second\n*expression* must be another exception class or instance, which will\nthen be attached to the raised exception as the "__cause__" attribute\n(which is writable). If the raised exception is not handled, both\nexceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler or a "finally" clause: the previous exception is\nthen attached as the new exception\'s "__context__" attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 17:01:20 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 26 Jul 2015 15:01:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_tag_v3?= =?utf-8?q?=2E5=2E0b4_for_changeset_c0d641054635?= Message-ID: <20150726150119.9208.6304@psf.io> https://hg.python.org/cpython/rev/f65605b99cb4 changeset: 97076:f65605b99cb4 branch: 3.5 user: Larry Hastings date: Sat Jul 25 14:23:29 2015 -0700 summary: Added tag v3.5.0b4 for changeset c0d641054635 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -151,3 +151,4 @@ 071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 +c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Jul 26 17:01:20 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 26 Jul 2015 15:01:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge_Python_3=2E5=2E0b4_changes_back_with_3=2E5_branch_head?= =?utf-8?q?=2E?= Message-ID: <20150726150119.97483.27206@psf.io> https://hg.python.org/cpython/rev/b339a35e2e77 changeset: 97078:b339a35e2e77 branch: 3.5 parent: 97077:7e0b3b84c45e parent: 97070:ef4d09399b99 user: Larry Hastings date: Sun Jul 26 07:59:45 2015 -0700 summary: Merge Python 3.5.0b4 changes back with 3.5 branch head. files: Lib/test/test_json/test_separators.py | 6 ++++++ Misc/NEWS | 3 +++ Modules/_json.c | 12 ++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_json/test_separators.py b/Lib/test/test_json/test_separators.py --- a/Lib/test/test_json/test_separators.py +++ b/Lib/test/test_json/test_separators.py @@ -39,6 +39,12 @@ self.assertEqual(h2, h) self.assertEqual(d2, expect) + def test_illegal_separators(self): + h = {1: 2, 3: 4} + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', ': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(', ', b': ')) + self.assertRaises(TypeError, self.dumps, h, separators=(b', ', b': ')) + class TestPySeparators(TestSeparators, PyTest): pass class TestCSeparators(TestSeparators, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Library ------- +- Issue #24683: Fixed crashes in _json functions called with arguments of + inappropriate type. + - Issue #21697: shutil.copytree() now correctly handles symbolic links that point to directories. Patch by Eduardo Seabra and Thomas Kluyver. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1344,11 +1344,19 @@ assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, - &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist, + &markers, &defaultfn, &encoder, &indent, + &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; + if (markers != Py_None && !PyDict_Check(markers)) { + PyErr_Format(PyExc_TypeError, + "make_encoder() argument 1 must be dict or None, " + "not %.200s", Py_TYPE(markers)->tp_name); + return -1; + } + s->markers = markers; s->defaultfn = defaultfn; s->encoder = encoder; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 00:47:34 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 26 Jul 2015 22:47:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2317527=3A_Add_PATCH_to_wsgiref=2Evalidator=2E_Patch_fr?= =?utf-8?q?om_Luca_Sbardella=2E?= Message-ID: <20150726224734.113884.66347@psf.io> https://hg.python.org/cpython/rev/cb0c56f87a47 changeset: 97081:cb0c56f87a47 branch: 3.5 parent: 97078:b339a35e2e77 parent: 97080:1a5b3dbafcca user: Robert Collins date: Mon Jul 27 10:42:54 2015 +1200 summary: Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. files: Lib/wsgiref/validate.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/wsgiref/validate.py b/Lib/wsgiref/validate.py --- a/Lib/wsgiref/validate.py +++ b/Lib/wsgiref/validate.py @@ -337,7 +337,7 @@ # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( - 'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'): + 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1242,6 +1242,7 @@ Dave Sawyer Ben Sayer sbt +Luca Sbardella Marco Scataglini Andrew Schaaf Michael Scharf diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 00:47:34 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 26 Jul 2015 22:47:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE3NTI3?= =?utf-8?q?=3A_Add_PATCH_to_wsgiref=2Evalidator=2E_Patch_from_Luca_Sbardel?= =?utf-8?b?bGEu?= Message-ID: <20150726224734.11656.99720@psf.io> https://hg.python.org/cpython/rev/1a5b3dbafcca changeset: 97080:1a5b3dbafcca branch: 3.4 parent: 97069:b3d0bf112f70 user: Robert Collins date: Mon Jul 27 10:42:01 2015 +1200 summary: Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. files: Lib/wsgiref/validate.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/wsgiref/validate.py b/Lib/wsgiref/validate.py --- a/Lib/wsgiref/validate.py +++ b/Lib/wsgiref/validate.py @@ -337,7 +337,7 @@ # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( - 'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'): + 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1207,6 +1207,7 @@ Dave Sawyer Ben Sayer sbt +Luca Sbardella Marco Scataglini Andrew Schaaf Michael Scharf diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. + - Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 00:47:34 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 26 Jul 2015 22:47:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3NTI3?= =?utf-8?q?=3A_Add_PATCH_to_wsgiref=2Evalidator=2E_Patch_from_Luca_Sbardel?= =?utf-8?b?bGEu?= Message-ID: <20150726224733.24778.87734@psf.io> https://hg.python.org/cpython/rev/5919531c0b03 changeset: 97079:5919531c0b03 branch: 2.7 parent: 97072:0a1266ef1b5d user: Robert Collins date: Mon Jul 27 10:40:15 2015 +1200 summary: Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. files: Lib/wsgiref/validate.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/wsgiref/validate.py b/Lib/wsgiref/validate.py --- a/Lib/wsgiref/validate.py +++ b/Lib/wsgiref/validate.py @@ -329,7 +329,7 @@ # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( - 'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'): + 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1197,6 +1197,7 @@ Bob Savage Ben Sayer sbt +Luca Sbardella Marco Scataglini Andrew Schaaf Michael Scharf diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. + - Issue #24613: Calling array.fromstring() with self is no longer allowed to prevent the use-after-free error. Patch by John Leitch. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 00:47:34 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 26 Jul 2015 22:47:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2317527=3A_Add_PATCH_to_wsgiref=2Evalidator=2E_Pa?= =?utf-8?q?tch_from_Luca_Sbardella=2E?= Message-ID: <20150726224734.3175.21205@psf.io> https://hg.python.org/cpython/rev/d8d148624004 changeset: 97082:d8d148624004 parent: 97073:7bf3d91f8d6c parent: 97081:cb0c56f87a47 user: Robert Collins date: Mon Jul 27 10:46:42 2015 +1200 summary: Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. files: .hgtags | 1 + Lib/wsgiref/validate.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 6 ++++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -151,3 +151,4 @@ 071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 +c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 diff --git a/Lib/wsgiref/validate.py b/Lib/wsgiref/validate.py --- a/Lib/wsgiref/validate.py +++ b/Lib/wsgiref/validate.py @@ -337,7 +337,7 @@ # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( - 'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'): + 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1242,6 +1242,7 @@ Dave Sawyer Ben Sayer sbt +Luca Sbardella Marco Scataglini Andrew Schaaf Michael Scharf diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. + - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. - Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can @@ -75,8 +77,8 @@ - Issue #24620: Random.setstate() now validates the value of state last element. -- Issue #22485: Fixed an issue that caused `inspect.getsource` to return incorrect - results on nested functions. +- Issue #22485: Fixed an issue that caused `inspect.getsource` to return + incorrect results on nested functions. - Issue #22153: Improve unittest docs. Patch from Martin Panter and evilzero. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Jul 27 10:41:02 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 27 Jul 2015 08:41:02 +0000 Subject: [Python-checkins] Daily reference leaks (d8d148624004): sum=7 Message-ID: <20150727084102.9212.41018@psf.io> results for d8d148624004 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog0dyv64', '--timeout', '7200'] From lp_benchmark_robot at intel.com Mon Jul 27 10:45:04 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 27 Jul 2015 08:45:04 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-07-27 Message-ID: Results for project python_default-nightly, build date 2015-07-27 09:02:04 commit: d8d148624004ce93da92663a855b1a52739a7e34 revision date: 2015-07-27 01:46:42 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-| pybench sec -0.13087% -1.94533% :-( regex_v8 sec 0.62185% -2.38540% :-| nbody sec 0.68036% -0.80983% :-| json_dump_v2 sec -0.88401% -1.17185% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From python-checkins at python.org Mon Jul 27 13:08:50 2015 From: python-checkins at python.org (stefan.krah) Date: Mon, 27 Jul 2015 11:08:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogRml4IHJlZmxlYWsu?= Message-ID: <20150727110850.24762.38973@psf.io> https://hg.python.org/cpython/rev/07d37b87d1c0 changeset: 97083:07d37b87d1c0 branch: 3.5 parent: 97081:cb0c56f87a47 user: Stefan Krah date: Mon Jul 27 12:56:49 2015 +0200 summary: Fix refleak. files: Python/compile.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1146,8 +1146,10 @@ v = PyDict_GetItem(dict, t); if (!v) { - if (PyErr_Occurred()) + if (PyErr_Occurred()) { + Py_DECREF(t); return -1; + } arg = PyDict_Size(dict); v = PyLong_FromSsize_t(arg); if (!v) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 13:08:50 2015 From: python-checkins at python.org (stefan.krah) Date: Mon, 27 Jul 2015 11:08:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogRml4IHJlZmxlYWsu?= Message-ID: <20150727110850.22233.81642@psf.io> https://hg.python.org/cpython/rev/cbff4ed7def0 changeset: 97084:cbff4ed7def0 parent: 97082:d8d148624004 parent: 97083:07d37b87d1c0 user: Stefan Krah date: Mon Jul 27 12:57:21 2015 +0200 summary: Fix refleak. files: Python/compile.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1146,8 +1146,10 @@ v = PyDict_GetItem(dict, t); if (!v) { - if (PyErr_Occurred()) + if (PyErr_Occurred()) { + Py_DECREF(t); return -1; + } arg = PyDict_Size(dict); v = PyLong_FromSsize_t(arg); if (!v) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 15:49:17 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 13:49:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324728=3A_Null_merge?= Message-ID: <20150727134917.8498.7760@psf.io> https://hg.python.org/cpython/rev/401bb7ceb7e8 changeset: 97086:401bb7ceb7e8 branch: 3.5 parent: 97083:07d37b87d1c0 parent: 97085:d10f7e0cd059 user: Berker Peksag date: Mon Jul 27 16:48:06 2015 +0300 summary: Issue #24728: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 15:49:17 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 13:49:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzI4?= =?utf-8?q?=3A_Fix_building_without_threads=2E?= Message-ID: <20150727134917.24762.71912@psf.io> https://hg.python.org/cpython/rev/d10f7e0cd059 changeset: 97085:d10f7e0cd059 branch: 3.4 parent: 97080:1a5b3dbafcca user: Berker Peksag date: Mon Jul 27 16:46:11 2015 +0300 summary: Issue #24728: Fix building without threads. Patch by Louis Dassy. files: Python/pythonrun.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2642,8 +2642,12 @@ return; display_stack: +#ifdef WITH_THREAD /* PyGILState_GetThisThreadState() works even if the GIL was released */ tstate = PyGILState_GetThisThreadState(); +#else + tstate = PyThreadState_GET(); +#endif if (tstate == NULL) { /* _Py_DumpTracebackThreads() requires the thread state to display * frames */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 15:49:17 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 13:49:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324728=3A_Null_merge?= Message-ID: <20150727134917.11668.98557@psf.io> https://hg.python.org/cpython/rev/752b59a9b9cd changeset: 97087:752b59a9b9cd parent: 97084:cbff4ed7def0 parent: 97086:401bb7ceb7e8 user: Berker Peksag date: Mon Jul 27 16:48:42 2015 +0300 summary: Issue #24728: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 16:47:36 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 27 Jul 2015 14:47:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_check_return_v?= =?utf-8?q?alue_of_PyString=5FFromStringAndSize_for_NULL_=28closes_=232473?= =?utf-8?q?4=29?= Message-ID: <20150727144730.113870.5128@psf.io> https://hg.python.org/cpython/rev/68cd7a64fbb0 changeset: 97088:68cd7a64fbb0 branch: 2.7 parent: 97079:5919531c0b03 user: Benjamin Peterson date: Mon Jul 27 07:47:21 2015 -0700 summary: check return value of PyString_FromStringAndSize for NULL (closes #24734) Patch by Pankaj Sharma. files: Python/compile.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1979,9 +1979,12 @@ identifier tmp = alias->name; const char *base = PyString_AS_STRING(alias->name); char *dot = strchr(base, '.'); - if (dot) + if (dot) { tmp = PyString_FromStringAndSize(base, dot - base); + if (tmp == NULL) + return 0; + } r = compiler_nameop(c, tmp, Store); if (dot) { Py_DECREF(tmp); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:08:56 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 21:08:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNDQx?= =?utf-8?q?=3A_rcompleter_now_prints_a_tab_character_instead_of_displaying?= Message-ID: <20150727210856.29410.54258@psf.io> https://hg.python.org/cpython/rev/82ccdf2df5ac changeset: 97089:82ccdf2df5ac branch: 3.4 parent: 97085:d10f7e0cd059 user: Berker Peksag date: Tue Jul 28 00:06:31 2015 +0300 summary: Issue #23441: rcompleter now prints a tab character instead of displaying possible completions for an empty word. Initial patch by Martin Sekera. files: Lib/rlcompleter.py | 6 ++++++ Lib/test/test_rlcompleter.py | 12 ++++++++---- Misc/NEWS | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -73,6 +73,12 @@ if self.use_main_ns: self.namespace = __main__.__dict__ + if not text.strip(): + if state == 0: + return '\t' + else: + return None + if state == 0: if "." in text: self.matches = self.attr_matches(text) diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -1,4 +1,3 @@ -from test import support import unittest import builtins import rlcompleter @@ -65,9 +64,14 @@ ['egg.{}('.format(x) for x in dir(str) if x.startswith('s')]) -def test_main(): - support.run_unittest(TestRlcompleter) + def test_complete(self): + completer = rlcompleter.Completer() + self.assertEqual(completer.complete('', 0), '\t') + self.assertEqual(completer.complete('a', 0), 'and') + self.assertEqual(completer.complete('a', 1), 'as') + self.assertEqual(completer.complete('as', 2), 'assert') + self.assertEqual(completer.complete('an', 0), 'and') if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #23441: rcompleter now prints a tab character instead of displaying + possible completions for an empty word. Initial patch by Martin Sekera. + - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. - Issue #24683: Fixed crashes in _json functions called with arguments of -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:09:01 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 21:09:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323441=3A_rcompleter_now_prints_a_tab_character_?= =?utf-8?q?instead_of_displaying?= Message-ID: <20150727210856.111283.10805@psf.io> https://hg.python.org/cpython/rev/2715734b3378 changeset: 97091:2715734b3378 parent: 97087:752b59a9b9cd parent: 97090:d55bdd2dc45e user: Berker Peksag date: Tue Jul 28 00:08:49 2015 +0300 summary: Issue #23441: rcompleter now prints a tab character instead of displaying possible completions for an empty word. Initial patch by Martin Sekera. files: Lib/rlcompleter.py | 6 ++++++ Lib/test/test_rlcompleter.py | 8 ++++++++ Misc/NEWS | 3 +++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -73,6 +73,12 @@ if self.use_main_ns: self.namespace = __main__.__dict__ + if not text.strip(): + if state == 0: + return '\t' + else: + return None + if state == 0: if "." in text: self.matches = self.attr_matches(text) diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -64,5 +64,13 @@ ['egg.{}('.format(x) for x in dir(str) if x.startswith('s')]) + def test_complete(self): + completer = rlcompleter.Completer() + self.assertEqual(completer.complete('', 0), '\t') + self.assertEqual(completer.complete('a', 0), 'and') + self.assertEqual(completer.complete('a', 1), 'as') + self.assertEqual(completer.complete('as', 2), 'assert') + self.assertEqual(completer.complete('an', 0), 'and') + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -62,6 +62,9 @@ Library ------- +- Issue #23441: rcompleter now prints a tab character instead of displaying + possible completions for an empty word. Initial patch by Martin Sekera. + - Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:09:01 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Jul 2015 21:09:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323441=3A_rcompleter_now_prints_a_tab_character_instea?= =?utf-8?q?d_of_displaying?= Message-ID: <20150727210856.124086.50825@psf.io> https://hg.python.org/cpython/rev/d55bdd2dc45e changeset: 97090:d55bdd2dc45e branch: 3.5 parent: 97086:401bb7ceb7e8 parent: 97089:82ccdf2df5ac user: Berker Peksag date: Tue Jul 28 00:08:24 2015 +0300 summary: Issue #23441: rcompleter now prints a tab character instead of displaying possible completions for an empty word. Initial patch by Martin Sekera. files: Lib/rlcompleter.py | 6 ++++++ Lib/test/test_rlcompleter.py | 8 ++++++++ Misc/NEWS | 3 +++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -73,6 +73,12 @@ if self.use_main_ns: self.namespace = __main__.__dict__ + if not text.strip(): + if state == 0: + return '\t' + else: + return None + if state == 0: if "." in text: self.matches = self.attr_matches(text) diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -64,5 +64,13 @@ ['egg.{}('.format(x) for x in dir(str) if x.startswith('s')]) + def test_complete(self): + completer = rlcompleter.Completer() + self.assertEqual(completer.complete('', 0), '\t') + self.assertEqual(completer.complete('a', 0), 'and') + self.assertEqual(completer.complete('a', 1), 'as') + self.assertEqual(completer.complete('as', 2), 'assert') + self.assertEqual(completer.complete('an', 0), 'and') + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ Library ------- +- Issue #23441: rcompleter now prints a tab character instead of displaying + possible completions for an empty word. Initial patch by Martin Sekera. + - Issue #24683: Fixed crashes in _json functions called with arguments of inappropriate type. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:39:30 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 27 Jul 2015 21:39:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NzMy?= =?utf-8?q?=2C_=2323834=3A_Fix_sock=5Faccept=5Fimpl=28=29_on_Windows?= Message-ID: <20150727213930.17729.32556@psf.io> https://hg.python.org/cpython/rev/cd60eccaa331 changeset: 97092:cd60eccaa331 branch: 3.5 parent: 97090:d55bdd2dc45e user: Victor Stinner date: Mon Jul 27 23:37:11 2015 +0200 summary: Issue #24732, #23834: Fix sock_accept_impl() on Windows accept() returns INVALID_SOCKET on error, it's not necessary a negative number. files: Modules/socketmodule.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2211,7 +2211,12 @@ #else ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); #endif + +#ifdef MS_WINDOWS + return (ctx->result != INVALID_SOCKET); +#else return (ctx->result >= 0); +#endif } /* s._accept() -> (fd, address) */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:39:30 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 27 Jul 2015 21:39:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChzb2NrZXQp?= Message-ID: <20150727213930.29402.9963@psf.io> https://hg.python.org/cpython/rev/6f98ef46fede changeset: 97093:6f98ef46fede parent: 97091:2715734b3378 parent: 97092:cd60eccaa331 user: Victor Stinner date: Mon Jul 27 23:39:22 2015 +0200 summary: Merge 3.5 (socket) files: Modules/socketmodule.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2211,7 +2211,12 @@ #else ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); #endif + +#ifdef MS_WINDOWS + return (ctx->result != INVALID_SOCKET); +#else return (ctx->result >= 0); +#endif } /* s._accept() -> (fd, address) */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:59:43 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 27 Jul 2015 21:59:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150727215943.730.69473@psf.io> https://hg.python.org/cpython/rev/64c39d30014e changeset: 97095:64c39d30014e parent: 97093:6f98ef46fede parent: 97094:0e8fc11cbfca user: Steve Dower date: Mon Jul 27 14:59:00 2015 -0700 summary: Merge with 3.5 files: PCbuild/openssl.props | 6 ++++-- PCbuild/pyproject.props | 10 +++++++--- PCbuild/python.props | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props --- a/PCbuild/openssl.props +++ b/PCbuild/openssl.props @@ -1,11 +1,13 @@ ? + + $(opensslDir)tmp\ + + StaticLibrary - $(opensslDir)tmp\$(ArchName)_$(Configuration)\$(ProjectName)\ - $(opensslDir)tmp\$(ArchName)\$(ProjectName)\ diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -1,11 +1,15 @@ ? - + <_ProjectFileVersion>10.0.30319.1 10.0 $(BuildPath) - $(SolutionDir)obj\$(ArchName)_$(Configuration)\$(ProjectName)\ - $(SolutionDir)obj\$(ArchName)\$(ProjectName)\ + $(Py_OutDir) + $(OutDir)\ + $(SolutionDir)obj\ + $(IntDir)\ + $(Py_IntDir)\$(ArchName)_$(Configuration)\$(ProjectName)\ + $(Py_IntDir)\$(ArchName)_PGO\$(ProjectName)\ $(ProjectName) $(TargetName)$(PyDebugExt) false diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -26,7 +26,8 @@ $(PySourcePath)\ - $(PySourcePath)PCBuild\$(ArchName)\ + $(PySourcePath)PCBuild\$(ArchName)\ + $(PyBuildPath) $(BuildPath)\ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Jul 27 23:59:43 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 27 Jul 2015 21:59:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Allow_intermed?= =?utf-8?q?iate_build_directory_to_be_overridden=2E?= Message-ID: <20150727215943.18466.52644@psf.io> https://hg.python.org/cpython/rev/0e8fc11cbfca changeset: 97094:0e8fc11cbfca branch: 3.5 parent: 97092:cd60eccaa331 user: Steve Dower date: Mon Jul 27 14:56:58 2015 -0700 summary: Allow intermediate build directory to be overridden. files: PCbuild/openssl.props | 6 ++++-- PCbuild/pyproject.props | 10 +++++++--- PCbuild/python.props | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props --- a/PCbuild/openssl.props +++ b/PCbuild/openssl.props @@ -1,11 +1,13 @@ ? + + $(opensslDir)tmp\ + + StaticLibrary - $(opensslDir)tmp\$(ArchName)_$(Configuration)\$(ProjectName)\ - $(opensslDir)tmp\$(ArchName)\$(ProjectName)\ diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -1,11 +1,15 @@ ? - + <_ProjectFileVersion>10.0.30319.1 10.0 $(BuildPath) - $(SolutionDir)obj\$(ArchName)_$(Configuration)\$(ProjectName)\ - $(SolutionDir)obj\$(ArchName)\$(ProjectName)\ + $(Py_OutDir) + $(OutDir)\ + $(SolutionDir)obj\ + $(IntDir)\ + $(Py_IntDir)\$(ArchName)_$(Configuration)\$(ProjectName)\ + $(Py_IntDir)\$(ArchName)_PGO\$(ProjectName)\ $(ProjectName) $(TargetName)$(PyDebugExt) false diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -26,7 +26,8 @@ $(PySourcePath)\ - $(PySourcePath)PCBuild\$(ArchName)\ + $(PySourcePath)PCBuild\$(ArchName)\ + $(PyBuildPath) $(BuildPath)\ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 28 00:40:55 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 27 Jul 2015 22:40:55 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Updates_notes_about_VS_su?= =?utf-8?q?pport_and_download_locations=2E?= Message-ID: <20150727224054.18454.31165@psf.io> https://hg.python.org/devguide/rev/845d6f9fed07 changeset: 752:845d6f9fed07 user: Steve Dower date: Mon Jul 27 15:39:43 2015 -0700 summary: Updates notes about VS support and download locations. files: setup.rst | 12 ++++-------- 1 files changed, 4 insertions(+), 8 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -229,16 +229,12 @@ software is required to build which parts of Python. **Python 3.5** and later use Microsoft Visual Studio 2015. You can download -`Microsoft Visual Studio 2015 CTP 6 or newer -`_, -or you can continue to use Visual Studio 2010 SP1 until Microsoft releases -the final version of Visual Studio 2015. +and use any of the free or paid versions of `Visual Studio 2015 +`_. Python 3.3 and 3.4 use Microsoft Visual Studio 2010. You can download -Microsoft Visual C++ 2010 Express `from Microsoft's site -`_. -To use it for more than 28 days, one must register through a -Microsoft account (formerly known as a Windows Live or Hotmail account). +Microsoft Visual Studio 2010 Express with an `MSDN subscription +`_. You'll also need to install the Visual Studio `Service Pack 1 (SP1) `_. If you don't install this service pack, you may receive errors like the following -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Tue Jul 28 05:55:16 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 28 Jul 2015 03:55:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323426=3A_run=5Fse?= =?utf-8?q?tup_was_broken_in_distutils=2E?= Message-ID: <20150728035516.111143.46113@psf.io> https://hg.python.org/cpython/rev/d8950778e3c2 changeset: 97096:d8950778e3c2 user: Robert Collins date: Tue Jul 28 15:55:07 2015 +1200 summary: Issue #23426: run_setup was broken in distutils. Patch from Alexander Belopolsky. files: Lib/distutils/core.py | 5 +-- Lib/distutils/tests/test_core.py | 30 ++++++++++++++++++++ Misc/NEWS | 3 ++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py --- a/Lib/distutils/core.py +++ b/Lib/distutils/core.py @@ -204,16 +204,15 @@ global _setup_stop_after, _setup_distribution _setup_stop_after = stop_after - save_argv = sys.argv + save_argv = sys.argv.copy() g = {'__file__': script_name} - l = {} try: try: sys.argv[0] = script_name if script_args is not None: sys.argv[1:] = script_args with open(script_name, 'rb') as f: - exec(f.read(), g, l) + exec(f.read(), g) finally: sys.argv = save_argv _setup_stop_after = None diff --git a/Lib/distutils/tests/test_core.py b/Lib/distutils/tests/test_core.py --- a/Lib/distutils/tests/test_core.py +++ b/Lib/distutils/tests/test_core.py @@ -28,6 +28,21 @@ setup() """ +setup_does_nothing = """\ +from distutils.core import setup +setup() +""" + + +setup_defines_subclass = """\ +from distutils.core import setup +from distutils.command.install import install as _install + +class install(_install): + sub_commands = _install.sub_commands + ['cmd'] + +setup(cmdclass={'install': install}) +""" class CoreTestCase(support.EnvironGuard, unittest.TestCase): @@ -65,6 +80,21 @@ distutils.core.run_setup( self.write_setup(setup_using___file__)) + def test_run_setup_preserves_sys_argv(self): + # Make sure run_setup does not clobber sys.argv + argv_copy = sys.argv.copy() + distutils.core.run_setup( + self.write_setup(setup_does_nothing)) + self.assertEqual(sys.argv, argv_copy) + + def test_run_setup_defines_subclass(self): + # Make sure the script can use __file__; if that's missing, the test + # setup.py script will raise NameError. + dist = distutils.core.run_setup( + self.write_setup(setup_defines_subclass)) + install = dist.get_command_obj('install') + self.assertIn('cmd', install.sub_commands) + def test_run_setup_uses_current_dir(self): # This tests that the setup script is run with the current directory # as its own current directory; this was temporarily broken by a diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23426: run_setup was broken in distutils. + Patch from Alexander Belopolsky. + - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 28 07:01:12 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 28 Jul 2015 05:01:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Set_a_default_?= =?utf-8?q?BasePlatformToolset_to_allow_the_ICC_buildbot_to_build=2E?= Message-ID: <20150728050112.758.94625@psf.io> https://hg.python.org/cpython/rev/d4f64d27ded7 changeset: 97097:d4f64d27ded7 branch: 2.7 parent: 97088:68cd7a64fbb0 user: Zachary Ware date: Tue Jul 28 00:00:47 2015 -0500 summary: Set a default BasePlatformToolset to allow the ICC buildbot to build. files: PCbuild/pyproject.props | 5 +++-- PCbuild/python.props | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -11,8 +11,9 @@ false false - true - true + + true + true true true false diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -7,7 +7,10 @@ Use only MSVC 9.0, unless explicitly overridden --> v90 - + + v90 $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) - $(ExternalsDir)sqlite-3.8.3.1\ + $(ExternalsDir)sqlite-3.8.11.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ $(ExternalsDir)openssl-1.0.2d\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -232,7 +232,7 @@ functionality to _ssl or _hashlib. They will not clean up their output with the normal Clean target; CleanAll should be used instead. _sqlite3 - Wraps SQLite 3.8.3.1, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.8.11.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Jul 28 20:39:08 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 28 Jul 2015 18:39:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319450=3A_Update_Windows_builds_to_use_SQLite_3?= =?utf-8?b?LjguMTEuMA==?= Message-ID: <20150728183905.111215.36208@psf.io> https://hg.python.org/cpython/rev/efb8132a7a22 changeset: 97103:efb8132a7a22 parent: 97100:e01289b08ca8 parent: 97102:4b37e81fcc54 user: Steve Dower date: Tue Jul 28 11:11:58 2015 -0700 summary: Issue #19450: Update Windows builds to use SQLite 3.8.11.0 files: PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -58,7 +58,7 @@ tcl-core-8.6.4.1 tk-8.6.4.1 tix-8.4.3.4 - sqlite-3.8.3.1 + sqlite-3.8.11.0 xz-5.0.5 ) do ( if exist %%e ( diff --git a/PCbuild/python.props b/PCbuild/python.props --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -32,7 +32,7 @@ $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) - $(ExternalsDir)sqlite-3.8.3.1\ + $(ExternalsDir)sqlite-3.8.11.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ $(ExternalsDir)openssl-1.0.2d\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -232,7 +232,7 @@ functionality to _ssl or _hashlib. They will not clean up their output with the normal Clean target; CleanAll should be used instead. _sqlite3 - Wraps SQLite 3.8.3.1, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.8.11.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 00:52:50 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 22:52:50 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_471=3A_add_the_DirEntry?= =?utf-8?b?Lmlub2RlKCkgbWV0aG9k?= Message-ID: <20150728225250.124064.83933@psf.io> https://hg.python.org/peps/rev/8ed4c8320c26 changeset: 5912:8ed4c8320c26 user: Victor Stinner date: Wed Jul 29 00:52:34 2015 +0200 summary: PEP 471: add the DirEntry.inode() method Update the PEP according to the implementation. files: pep-0471.txt | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/pep-0471.txt b/pep-0471.txt --- a/pep-0471.txt +++ b/pep-0471.txt @@ -118,6 +118,11 @@ path) -- the equivalent of ``os.path.join(scandir_path, entry.name)`` +* ``inode()``: return the inode number of the entry. The result is cached on + the ``DirEntry`` object, use ``os.stat(entry.path, + follow_symlinks=False).st_ino`` to fetch up-to-date information. + On Unix, no system call is required. + * ``is_dir(*, follow_symlinks=True)``: similar to ``pathlib.Path.is_dir()``, but the return value is cached on the ``DirEntry`` object; doesn't require a system call in most cases; -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Jul 29 01:21:27 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:21:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogV2hhdCdzIE5ldyBp?= =?utf-8?q?n_Python_3=2E5=3A_move_PEP_475_doc?= Message-ID: <20150728232126.111105.17470@psf.io> https://hg.python.org/cpython/rev/ee9a4f385801 changeset: 97104:ee9a4f385801 branch: 3.5 parent: 97102:4b37e81fcc54 user: Victor Stinner date: Wed Jul 29 01:11:10 2015 +0200 summary: What's New in Python 3.5: move PEP 475 doc files: Doc/whatsnew/3.5.rst | 117 +++++++++++++++++------------- 1 files changed, 65 insertions(+), 52 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -227,6 +227,68 @@ EINTR or :exc:`InterruptedError` manually, and should make it more robust against asynchronous signal reception. +Examples of functions which are now retried when interrupted by a signal +instead of raising :exc:`InterruptedError` if the Python signal handler does +not raise an exception: + +* :func:`open`, :func:`os.open`, :func:`io.open` +* functions of the :mod:`faulthandler` module +* :mod:`os` functions: + + - :func:`os.fchdir` + - :func:`os.fchmod` + - :func:`os.fchown` + - :func:`os.fdatasync` + - :func:`os.fstat` + - :func:`os.fstatvfs` + - :func:`os.fsync` + - :func:`os.ftruncate` + - :func:`os.mkfifo` + - :func:`os.mknod` + - :func:`os.posix_fadvise` + - :func:`os.posix_fallocate` + - :func:`os.pread` + - :func:`os.pwrite` + - :func:`os.read` + - :func:`os.readv` + - :func:`os.sendfile` + - :func:`os.wait3` + - :func:`os.wait4` + - :func:`os.wait` + - :func:`os.waitid` + - :func:`os.waitpid` + - :func:`os.write` + - :func:`os.writev` + - special cases: :func:`os.close` and :func:`os.dup2` now ignore + :py:data:`~errno.EINTR` error, the syscall is not retried (see the PEP + for the rationale) + +* :mod:`select` functions: + + - :func:`select.devpoll.poll` + - :func:`select.epoll.poll` + - :func:`select.kqueue.control` + - :func:`select.poll.poll` + - :func:`select.select` + +* :func:`socket.socket` methods: + + - :meth:`~socket.socket.accept` + - :meth:`~socket.socket.connect` (except for non-blocking sockets) + - :meth:`~socket.socket.recv` + - :meth:`~socket.socket.recvfrom` + - :meth:`~socket.socket.recvmsg` + - :meth:`~socket.socket.send` + - :meth:`~socket.socket.sendall` + - :meth:`~socket.socket.sendmsg` + - :meth:`~socket.socket.sendto` + +* :func:`signal.sigtimedwait`, :func:`signal.sigwaitinfo` +* :func:`time.sleep` + +PEP and implementation written by Charles-Fran?ois Natali and Victor Stinner, +with the help of Antoine Pitrou (the french connection). + .. seealso:: :pep:`475` -- Retry system calls failing with EINTR @@ -966,58 +1028,9 @@ Changes in the Python API ------------------------- -* :pep:`475`: Examples of functions which are now retried when interrupted - instead of raising :exc:`InterruptedError` if the signal handler does not - raise an exception: - - - :func:`open`, :func:`os.open`, :func:`io.open` - - functions of the :mod:`faulthandler` module - - :mod:`os` functions: - - * :func:`os.fchdir` - * :func:`os.fchmod` - * :func:`os.fchown` - * :func:`os.fdatasync` - * :func:`os.fstat` - * :func:`os.fstatvfs` - * :func:`os.fsync` - * :func:`os.ftruncate` - * :func:`os.mkfifo` - * :func:`os.mknod` - * :func:`os.posix_fadvise` - * :func:`os.posix_fallocate` - * :func:`os.pread` - * :func:`os.pwrite` - * :func:`os.read` - * :func:`os.readv` - * :func:`os.sendfile` - * :func:`os.wait3` - * :func:`os.wait4` - * :func:`os.wait` - * :func:`os.waitid` - * :func:`os.waitpid` - * :func:`os.write` - * :func:`os.writev` - * special cases: :func:`os.close` and :func:`os.dup2` now ignore - :py:data:`~errno.EINTR` error, the syscall is not retried (see the PEP - for the rationale) - - - :func:`select.select`, :func:`select.poll.poll`, :func:`select.epoll.poll`, - :func:`select.kqueue.control`, :func:`select.devpoll.poll` - - :func:`socket.socket` methods: - - * :meth:`~socket.socket.accept` - * :meth:`~socket.socket.connect` (except for non-blocking sockets) - * :meth:`~socket.socket.recv` - * :meth:`~socket.socket.recvfrom` - * :meth:`~socket.socket.recvmsg` - * :meth:`~socket.socket.send` - * :meth:`~socket.socket.sendall` - * :meth:`~socket.socket.sendmsg` - * :meth:`~socket.socket.sendto` - - - :func:`signal.sigtimedwait`, :func:`signal.sigwaitinfo` - - :func:`time.sleep` +* :pep:`475`: System calls are now retried when interrupted by a signal instead + of raising :exc:`InterruptedError` if the Python signal handler does not + raise an exception. * Before Python 3.5, a :class:`datetime.time` object was considered to be false if it represented midnight in UTC. This behavior was considered obscure and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 01:21:26 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:21:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChkb2Mp?= Message-ID: <20150728232126.17729.82751@psf.io> https://hg.python.org/cpython/rev/3de1c5d6a7b8 changeset: 97105:3de1c5d6a7b8 parent: 97103:efb8132a7a22 parent: 97104:ee9a4f385801 user: Victor Stinner date: Wed Jul 29 01:21:19 2015 +0200 summary: Merge 3.5 (doc) files: Doc/whatsnew/3.5.rst | 117 +++++++++++++++++------------- 1 files changed, 65 insertions(+), 52 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -227,6 +227,68 @@ EINTR or :exc:`InterruptedError` manually, and should make it more robust against asynchronous signal reception. +Examples of functions which are now retried when interrupted by a signal +instead of raising :exc:`InterruptedError` if the Python signal handler does +not raise an exception: + +* :func:`open`, :func:`os.open`, :func:`io.open` +* functions of the :mod:`faulthandler` module +* :mod:`os` functions: + + - :func:`os.fchdir` + - :func:`os.fchmod` + - :func:`os.fchown` + - :func:`os.fdatasync` + - :func:`os.fstat` + - :func:`os.fstatvfs` + - :func:`os.fsync` + - :func:`os.ftruncate` + - :func:`os.mkfifo` + - :func:`os.mknod` + - :func:`os.posix_fadvise` + - :func:`os.posix_fallocate` + - :func:`os.pread` + - :func:`os.pwrite` + - :func:`os.read` + - :func:`os.readv` + - :func:`os.sendfile` + - :func:`os.wait3` + - :func:`os.wait4` + - :func:`os.wait` + - :func:`os.waitid` + - :func:`os.waitpid` + - :func:`os.write` + - :func:`os.writev` + - special cases: :func:`os.close` and :func:`os.dup2` now ignore + :py:data:`~errno.EINTR` error, the syscall is not retried (see the PEP + for the rationale) + +* :mod:`select` functions: + + - :func:`select.devpoll.poll` + - :func:`select.epoll.poll` + - :func:`select.kqueue.control` + - :func:`select.poll.poll` + - :func:`select.select` + +* :func:`socket.socket` methods: + + - :meth:`~socket.socket.accept` + - :meth:`~socket.socket.connect` (except for non-blocking sockets) + - :meth:`~socket.socket.recv` + - :meth:`~socket.socket.recvfrom` + - :meth:`~socket.socket.recvmsg` + - :meth:`~socket.socket.send` + - :meth:`~socket.socket.sendall` + - :meth:`~socket.socket.sendmsg` + - :meth:`~socket.socket.sendto` + +* :func:`signal.sigtimedwait`, :func:`signal.sigwaitinfo` +* :func:`time.sleep` + +PEP and implementation written by Charles-Fran?ois Natali and Victor Stinner, +with the help of Antoine Pitrou (the french connection). + .. seealso:: :pep:`475` -- Retry system calls failing with EINTR @@ -966,58 +1028,9 @@ Changes in the Python API ------------------------- -* :pep:`475`: Examples of functions which are now retried when interrupted - instead of raising :exc:`InterruptedError` if the signal handler does not - raise an exception: - - - :func:`open`, :func:`os.open`, :func:`io.open` - - functions of the :mod:`faulthandler` module - - :mod:`os` functions: - - * :func:`os.fchdir` - * :func:`os.fchmod` - * :func:`os.fchown` - * :func:`os.fdatasync` - * :func:`os.fstat` - * :func:`os.fstatvfs` - * :func:`os.fsync` - * :func:`os.ftruncate` - * :func:`os.mkfifo` - * :func:`os.mknod` - * :func:`os.posix_fadvise` - * :func:`os.posix_fallocate` - * :func:`os.pread` - * :func:`os.pwrite` - * :func:`os.read` - * :func:`os.readv` - * :func:`os.sendfile` - * :func:`os.wait3` - * :func:`os.wait4` - * :func:`os.wait` - * :func:`os.waitid` - * :func:`os.waitpid` - * :func:`os.write` - * :func:`os.writev` - * special cases: :func:`os.close` and :func:`os.dup2` now ignore - :py:data:`~errno.EINTR` error, the syscall is not retried (see the PEP - for the rationale) - - - :func:`select.select`, :func:`select.poll.poll`, :func:`select.epoll.poll`, - :func:`select.kqueue.control`, :func:`select.devpoll.poll` - - :func:`socket.socket` methods: - - * :meth:`~socket.socket.accept` - * :meth:`~socket.socket.connect` (except for non-blocking sockets) - * :meth:`~socket.socket.recv` - * :meth:`~socket.socket.recvfrom` - * :meth:`~socket.socket.recvmsg` - * :meth:`~socket.socket.send` - * :meth:`~socket.socket.sendall` - * :meth:`~socket.socket.sendmsg` - * :meth:`~socket.socket.sendto` - - - :func:`signal.sigtimedwait`, :func:`signal.sigwaitinfo` - - :func:`time.sleep` +* :pep:`475`: System calls are now retried when interrupted by a signal instead + of raising :exc:`InterruptedError` if the Python signal handler does not + raise an exception. * Before Python 3.5, a :class:`datetime.time` object was considered to be false if it represented midnight in UTC. This behavior was considered obscure and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 01:39:37 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:39:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChkb2Mp?= Message-ID: <20150728233936.63166.82870@psf.io> https://hg.python.org/cpython/rev/f81bdca9113d changeset: 97107:f81bdca9113d parent: 97105:3de1c5d6a7b8 parent: 97106:b7442c597842 user: Victor Stinner date: Wed Jul 29 01:39:30 2015 +0200 summary: Merge 3.5 (doc) files: Doc/whatsnew/3.5.rst | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -750,6 +750,15 @@ :func:`~collections.namedtuple`. (Contributed by Claudiu Popa in :issue:`18615`.) +ssl +--- + +The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, +:meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of +:class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes +are received or sent. The socket timeout is now the maximum total duration of +the method. + socket ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 01:39:38 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:39:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogV2hhdCdzIE5ldyBp?= =?utf-8?q?n_Python_3=2E5=3A_Document_ssl_methods_change_on_timeout?= Message-ID: <20150728233936.63174.11218@psf.io> https://hg.python.org/cpython/rev/b7442c597842 changeset: 97106:b7442c597842 branch: 3.5 parent: 97104:ee9a4f385801 user: Victor Stinner date: Wed Jul 29 01:39:13 2015 +0200 summary: What's New in Python 3.5: Document ssl methods change on timeout files: Doc/whatsnew/3.5.rst | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -750,6 +750,15 @@ :func:`~collections.namedtuple`. (Contributed by Claudiu Popa in :issue:`18615`.) +ssl +--- + +The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, +:meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of +:class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes +are received or sent. The socket timeout is now the maximum total duration of +the method. + socket ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 01:41:40 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:41:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogV2hhdCdzIE5ldyBp?= =?utf-8?q?n_Python_3=2E5=3A_document_socket=2Esendall=28=29_change_on_tim?= =?utf-8?q?eout?= Message-ID: <20150728234140.1387.1029@psf.io> https://hg.python.org/cpython/rev/62b45cf17fa1 changeset: 97108:62b45cf17fa1 branch: 3.5 parent: 97106:b7442c597842 user: Victor Stinner date: Wed Jul 29 01:41:25 2015 +0200 summary: What's New in Python 3.5: document socket.sendall() change on timeout files: Doc/whatsnew/3.5.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -768,6 +768,10 @@ :meth:`socket.socket.send`. (Contributed by Giampaolo Rodola' in :issue:`17552`.) +* The :meth:`socket.socket.sendall` method don't reset the socket timeout + anymore each time bytes are received or sent. The socket timeout is now the + maximum total duration to send all data. + subprocess ---------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 01:41:40 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 28 Jul 2015 23:41:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChkb2Mp?= Message-ID: <20150728234140.17713.60006@psf.io> https://hg.python.org/cpython/rev/df8660b2d8fb changeset: 97109:df8660b2d8fb parent: 97107:f81bdca9113d parent: 97108:62b45cf17fa1 user: Victor Stinner date: Wed Jul 29 01:41:34 2015 +0200 summary: Merge 3.5 (doc) files: Doc/whatsnew/3.5.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -768,6 +768,10 @@ :meth:`socket.socket.send`. (Contributed by Giampaolo Rodola' in :issue:`17552`.) +* The :meth:`socket.socket.sendall` method don't reset the socket timeout + anymore each time bytes are received or sent. The socket timeout is now the + maximum total duration to send all data. + subprocess ---------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:30:01 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 00:30:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogV2hhdCdzIE5ldyBp?= =?utf-8?q?n_Python_3=2E5=3A_document_os=2Eurandom=28=29_changes?= Message-ID: <20150729003000.63164.92571@psf.io> https://hg.python.org/cpython/rev/dab79e4dfa51 changeset: 97110:dab79e4dfa51 branch: 3.5 parent: 97108:62b45cf17fa1 user: Victor Stinner date: Wed Jul 29 02:28:32 2015 +0200 summary: What's New in Python 3.5: document os.urandom() changes files: Doc/library/os.rst | 6 ++++++ Doc/whatsnew/3.5.rst | 5 +++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3730,3 +3730,9 @@ For an easy-to-use interface to the random number generator provided by your platform, please see :class:`random.SystemRandom`. + + .. versionchanged:: 3.5 + On Linux 3.17 and newer, the ``getrandom()`` syscall is now used + when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` + function is now used. These functions avoid the usage of an internal file + descriptor. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -648,6 +648,11 @@ * :class:`os.stat_result` now has a :attr:`~os.stat_result.st_file_attributes` attribute on Windows. (Contributed by Ben Hoyt in :issue:`21719`.) +* :func:`os.urandom`: On Linux 3.17 and newer, the ``getrandom()`` syscall is + now used when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` + function is now used. These functions avoid the usage of an internal file + descriptor. + os.path ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:30:01 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 00:30:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChkb2Mp?= Message-ID: <20150729003001.753.64282@psf.io> https://hg.python.org/cpython/rev/3cf560285315 changeset: 97111:3cf560285315 parent: 97109:df8660b2d8fb parent: 97110:dab79e4dfa51 user: Victor Stinner date: Wed Jul 29 02:29:54 2015 +0200 summary: Merge 3.5 (doc) files: Doc/library/os.rst | 6 ++++++ Doc/whatsnew/3.5.rst | 5 +++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3735,3 +3735,9 @@ For an easy-to-use interface to the random number generator provided by your platform, please see :class:`random.SystemRandom`. + + .. versionchanged:: 3.5 + On Linux 3.17 and newer, the ``getrandom()`` syscall is now used + when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` + function is now used. These functions avoid the usage of an internal file + descriptor. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -648,6 +648,11 @@ * :class:`os.stat_result` now has a :attr:`~os.stat_result.st_file_attributes` attribute on Windows. (Contributed by Ben Hoyt in :issue:`21719`.) +* :func:`os.urandom`: On Linux 3.17 and newer, the ``getrandom()`` syscall is + now used when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` + function is now used. These functions avoid the usage of an internal file + descriptor. + os.path ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:55:50 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 00:55:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMjU0?= =?utf-8?q?=3A_Document_how_to_close_the_TCPServer_listening_socket=2E?= Message-ID: <20150729005550.5539.33636@psf.io> https://hg.python.org/cpython/rev/8afd995802a6 changeset: 97112:8afd995802a6 branch: 2.7 parent: 97097:d4f64d27ded7 user: Robert Collins date: Wed Jul 29 12:48:42 2015 +1200 summary: Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. files: Doc/library/socketserver.rst | 13 +++++++++++-- Lib/test/test_socketserver.py | 2 ++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -39,9 +39,10 @@ handler class by subclassing the :class:`BaseRequestHandler` class and overriding its :meth:`handle` method; this method will process incoming requests. Second, you must instantiate one of the server classes, passing it -the server's address and the request handler class. Finally, call the +the server's address and the request handler class. Then call the :meth:`handle_request` or :meth:`serve_forever` method of the server object to -process one or many requests. +process one or many requests. Finally, call :meth:`~BaseServer.server_close` +to close the socket. When inheriting from :class:`ThreadingMixIn` for threaded connection behavior, you should explicitly declare how you want your threads to behave on an abrupt @@ -170,6 +171,13 @@ .. versionadded:: 2.6 +.. method:: BaseServer.server_close() + + Clean up the server. May be overridden. + + .. versionadded:: 2.6 + + .. attribute:: BaseServer.address_family The family of protocols to which the server's socket belongs. @@ -540,6 +548,7 @@ client(ip, port, "Hello World 3") server.shutdown() + server.server_close() The output of the example should look something like this:: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -158,6 +158,8 @@ if verbose: print "waiting for server" server.shutdown() t.join() + server.server_close() + self.assertRaises(socket.error, server.socket.fileno) if verbose: print "done" def stream_examine(self, proto, addr): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #23254: Document how to close the TCPServer listening socket. + Patch from Martin Panter. + - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. - Issue #24613: Calling array.fromstring() with self is no longer allowed -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:55:50 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 00:55:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323254=3A_Document_how_to_close_the_TCPServer_listenin?= =?utf-8?q?g_socket=2E?= Message-ID: <20150729005550.29404.15181@psf.io> https://hg.python.org/cpython/rev/5ee8a4efc06f changeset: 97114:5ee8a4efc06f branch: 3.5 parent: 97110:dab79e4dfa51 parent: 97113:1123de53195e user: Robert Collins date: Wed Jul 29 12:53:30 2015 +1200 summary: Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. files: Doc/library/socketserver.rst | 13 +++++++++++-- Lib/test/test_socketserver.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -33,9 +33,10 @@ handler class by subclassing the :class:`BaseRequestHandler` class and overriding its :meth:`handle` method; this method will process incoming requests. Second, you must instantiate one of the server classes, passing it -the server's address and the request handler class. Finally, call the +the server's address and the request handler class. Then call the :meth:`handle_request` or :meth:`serve_forever` method of the server object to -process one or many requests. +process one or many requests. Finally, call :meth:`~BaseServer.server_close` +to close the socket. When inheriting from :class:`ThreadingMixIn` for threaded connection behavior, you should explicitly declare how you want your threads to behave on an abrupt @@ -177,6 +178,13 @@ Tell the :meth:`serve_forever` loop to stop and wait until it does. +.. method:: BaseServer.server_close() + + Clean up the server. May be overridden. + + .. versionadded:: 2.6 + + .. attribute:: BaseServer.address_family The family of protocols to which the server's socket belongs. @@ -547,6 +555,7 @@ client(ip, port, "Hello World 3") server.shutdown() + server.server_close() The output of the example should look something like this:: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -144,6 +144,7 @@ server.shutdown() t.join() server.server_close() + self.assertEqual(-1, server.socket.fileno()) if verbose: print("done") def stream_examine(self, proto, addr): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23254: Document how to close the TCPServer listening socket. + Patch from Martin Panter. + - Issue #19450: Update Windows builds to use SQLite 3.8.11.0 - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:55:50 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 00:55:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323254=3A_Document_how_to_close_the_TCPServer_li?= =?utf-8?q?stening_socket=2E?= Message-ID: <20150729005550.29408.65151@psf.io> https://hg.python.org/cpython/rev/256d5c7146cb changeset: 97115:256d5c7146cb parent: 97111:3cf560285315 parent: 97114:5ee8a4efc06f user: Robert Collins date: Wed Jul 29 12:55:33 2015 +1200 summary: Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. files: Doc/library/socketserver.rst | 13 +++++++++++-- Lib/test/test_socketserver.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -33,9 +33,10 @@ handler class by subclassing the :class:`BaseRequestHandler` class and overriding its :meth:`handle` method; this method will process incoming requests. Second, you must instantiate one of the server classes, passing it -the server's address and the request handler class. Finally, call the +the server's address and the request handler class. Then call the :meth:`handle_request` or :meth:`serve_forever` method of the server object to -process one or many requests. +process one or many requests. Finally, call :meth:`~BaseServer.server_close` +to close the socket. When inheriting from :class:`ThreadingMixIn` for threaded connection behavior, you should explicitly declare how you want your threads to behave on an abrupt @@ -177,6 +178,13 @@ Tell the :meth:`serve_forever` loop to stop and wait until it does. +.. method:: BaseServer.server_close() + + Clean up the server. May be overridden. + + .. versionadded:: 2.6 + + .. attribute:: BaseServer.address_family The family of protocols to which the server's socket belongs. @@ -547,6 +555,7 @@ client(ip, port, "Hello World 3") server.shutdown() + server.server_close() The output of the example should look something like this:: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -144,6 +144,7 @@ server.shutdown() t.join() server.server_close() + self.assertEqual(-1, server.socket.fileno()) if verbose: print("done") def stream_examine(self, proto, addr): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23254: Document how to close the TCPServer listening socket. + Patch from Martin Panter. + - Issue #23426: run_setup was broken in distutils. Patch from Alexander Belopolsky. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 02:55:51 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 00:55:51 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMjU0?= =?utf-8?q?=3A_Document_how_to_close_the_TCPServer_listening_socket=2E?= Message-ID: <20150729005550.111105.42691@psf.io> https://hg.python.org/cpython/rev/1123de53195e changeset: 97113:1123de53195e branch: 3.4 parent: 97101:1003746ee7a0 user: Robert Collins date: Wed Jul 29 12:52:40 2015 +1200 summary: Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. files: Doc/library/socketserver.rst | 13 +++++++++++-- Lib/test/test_socketserver.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -33,9 +33,10 @@ handler class by subclassing the :class:`BaseRequestHandler` class and overriding its :meth:`handle` method; this method will process incoming requests. Second, you must instantiate one of the server classes, passing it -the server's address and the request handler class. Finally, call the +the server's address and the request handler class. Then call the :meth:`handle_request` or :meth:`serve_forever` method of the server object to -process one or many requests. +process one or many requests. Finally, call :meth:`~BaseServer.server_close` +to close the socket. When inheriting from :class:`ThreadingMixIn` for threaded connection behavior, you should explicitly declare how you want your threads to behave on an abrupt @@ -177,6 +178,13 @@ Tell the :meth:`serve_forever` loop to stop and wait until it does. +.. method:: BaseServer.server_close() + + Clean up the server. May be overridden. + + .. versionadded:: 2.6 + + .. attribute:: BaseServer.address_family The family of protocols to which the server's socket belongs. @@ -547,6 +555,7 @@ client(ip, port, "Hello World 3") server.shutdown() + server.server_close() The output of the example should look something like this:: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -144,6 +144,7 @@ server.shutdown() t.join() server.server_close() + self.assertEqual(-1, server.socket.fileno()) if verbose: print("done") def stream_examine(self, proto, addr): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #23254: Document how to close the TCPServer listening socket. + Patch from Martin Panter. + - Issue #19450: Update Windows builds to use SQLite 3.8.11.0 - Issue #23441: rcompleter now prints a tab character instead of displaying -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 08:30:22 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 29 Jul 2015 06:30:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2319450=3A_merge_from_3=2E4?= Message-ID: <20150729063022.726.44289@psf.io> https://hg.python.org/cpython/rev/ebe72984c1b9 changeset: 97117:ebe72984c1b9 branch: 3.5 parent: 97114:5ee8a4efc06f parent: 97116:33dbcde76b3f user: Ned Deily date: Tue Jul 28 23:25:41 2015 -0700 summary: Issue #19450: merge from 3.4 files: Mac/BuildScript/README.txt | 4 ++-- Mac/BuildScript/build-installer.py | 6 +++--- Misc/NEWS | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt --- a/Mac/BuildScript/README.txt +++ b/Mac/BuildScript/README.txt @@ -22,7 +22,7 @@ - builds the following third-party libraries * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries @@ -57,7 +57,7 @@ - builds the following third-party libraries * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries 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 @@ -339,9 +339,9 @@ ), ), dict( - name="SQLite 3.8.3.1", - url="http://www.sqlite.org/2014/sqlite-autoconf-3080301.tar.gz", - checksum='509ff98d8dc9729b618b7e96612079c6', + name="SQLite 3.8.11", + url="https://www.sqlite.org/2015/sqlite-autoconf-3081100.tar.gz", + checksum='77b451925121028befbddbf45ea2bc49', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS4 ' '-DSQLITE_ENABLE_FTS3_PARENTHESIS ' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,7 +16,7 @@ - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. -- Issue #19450: Update Windows builds to use SQLite 3.8.11.0 +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 08:30:22 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 29 Jul 2015 06:30:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE5NDUw?= =?utf-8?q?=3A_Update_OS_X_installer_builds_to_use_SQLite_3=2E8=2E11=2E?= Message-ID: <20150729063022.29402.56166@psf.io> https://hg.python.org/cpython/rev/33dbcde76b3f changeset: 97116:33dbcde76b3f branch: 3.4 parent: 97113:1123de53195e user: Ned Deily date: Tue Jul 28 23:22:23 2015 -0700 summary: Issue #19450: Update OS X installer builds to use SQLite 3.8.11. files: Mac/BuildScript/README.txt | 4 ++-- Mac/BuildScript/build-installer.py | 6 +++--- Misc/NEWS | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt --- a/Mac/BuildScript/README.txt +++ b/Mac/BuildScript/README.txt @@ -33,7 +33,7 @@ * libcrypto and libssl from OpenSSL 1.0.1 (new, as of 3.4.3) * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries @@ -68,7 +68,7 @@ - builds the following third-party libraries * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries 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 @@ -339,9 +339,9 @@ ), ), dict( - name="SQLite 3.8.3.1", - url="http://www.sqlite.org/2014/sqlite-autoconf-3080301.tar.gz", - checksum='509ff98d8dc9729b618b7e96612079c6', + name="SQLite 3.8.11", + url="https://www.sqlite.org/2015/sqlite-autoconf-3081100.tar.gz", + checksum='77b451925121028befbddbf45ea2bc49', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS4 ' '-DSQLITE_ENABLE_FTS3_PARENTHESIS ' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -69,7 +69,7 @@ - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. -- Issue #19450: Update Windows builds to use SQLite 3.8.11.0 +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - Issue #23441: rcompleter now prints a tab character instead of displaying possible completions for an empty word. Initial patch by Martin Sekera. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 08:30:22 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 29 Jul 2015 06:30:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319450=3A_merge_from_3=2E5?= Message-ID: <20150729063022.736.37369@psf.io> https://hg.python.org/cpython/rev/1f4ef305b658 changeset: 97118:1f4ef305b658 parent: 97115:256d5c7146cb parent: 97117:ebe72984c1b9 user: Ned Deily date: Tue Jul 28 23:29:51 2015 -0700 summary: Issue #19450: merge from 3.5 files: Mac/BuildScript/README.txt | 4 ++-- Mac/BuildScript/build-installer.py | 6 +++--- Misc/NEWS | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt --- a/Mac/BuildScript/README.txt +++ b/Mac/BuildScript/README.txt @@ -22,7 +22,7 @@ - builds the following third-party libraries * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries @@ -57,7 +57,7 @@ - builds the following third-party libraries * NCurses 5.9 (http://bugs.python.org/issue15037) - * SQLite 3.8.3.1 + * SQLite 3.8.11 * XZ 5.0.5 - uses system-supplied versions of third-party libraries 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 @@ -339,9 +339,9 @@ ), ), dict( - name="SQLite 3.8.3.1", - url="http://www.sqlite.org/2014/sqlite-autoconf-3080301.tar.gz", - checksum='509ff98d8dc9729b618b7e96612079c6', + name="SQLite 3.8.11", + url="https://www.sqlite.org/2015/sqlite-autoconf-3081100.tar.gz", + checksum='77b451925121028befbddbf45ea2bc49', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS4 ' '-DSQLITE_ENABLE_FTS3_PARENTHESIS ' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. + - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Wed Jul 29 10:13:13 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Wed, 29 Jul 2015 08:13:13 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-07-29 Message-ID: Results for project python_default-nightly, build date 2015-07-29 10:42:12 commit: 1f4ef305b65822bfbabdf0143b8d9221bd6dadeb revision date: 2015-07-29 09:29:51 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 0.17868% -2.08238% :-( regex_v8 sec -0.75082% -4.31781% :-( nbody sec -2.19989% -2.84359% :-| json_dump_v2 sec 0.99048% -0.28707% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From solipsis at pitrou.net Wed Jul 29 10:41:07 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 29 Jul 2015 08:41:07 +0000 Subject: [Python-checkins] Daily reference leaks (256d5c7146cb): sum=4 Message-ID: <20150729084107.124078.73615@psf.io> results for 256d5c7146cb on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogHC2WQA', '--timeout', '7200'] From python-checkins at python.org Wed Jul 29 14:36:17 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:36:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMzE5?= =?utf-8?q?=3A_Fix_ctypes=2EBigEndianStructure=2C_swap_correctly_bytes=2E_?= =?utf-8?q?Patch?= Message-ID: <20150729123616.29408.18325@psf.io> https://hg.python.org/cpython/rev/935ae7f001e3 changeset: 97119:935ae7f001e3 branch: 3.4 parent: 97116:33dbcde76b3f user: Victor Stinner date: Wed Jul 29 14:33:52 2015 +0200 summary: Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. files: Lib/ctypes/test/test_bitfields.py | 28 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_ctypes/cfield.c | 1 + 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -259,5 +259,33 @@ x.a = 0xFEDCBA9876543211 self.assertEqual(x.a, 0xFEDCBA9876543211) + @need_symbol('c_uint32') + def test_uint32_swap_little_endian(self): + # Issue #23319 + class Little(LittleEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Little.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xef\xcd\xab\x21') + + @need_symbol('c_uint32') + def test_uint32_swap_big_endian(self): + # Issue #23319 + class Big(BigEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Big.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xab\xcd\xef\x12') + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch + written by Matthieu Gautier. + - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -765,6 +765,7 @@ if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field)); + field = SWAP_INT(field); field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:36:17 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:36:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChjdHlwZXMp?= Message-ID: <20150729123617.29418.77654@psf.io> https://hg.python.org/cpython/rev/803a83dd3c9c changeset: 97121:803a83dd3c9c parent: 97118:1f4ef305b658 parent: 97120:883d2443941e user: Victor Stinner date: Wed Jul 29 14:36:03 2015 +0200 summary: Merge 3.5 (ctypes) files: Lib/ctypes/test/test_bitfields.py | 28 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_ctypes/cfield.c | 1 + 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -259,5 +259,33 @@ x.a = 0xFEDCBA9876543211 self.assertEqual(x.a, 0xFEDCBA9876543211) + @need_symbol('c_uint32') + def test_uint32_swap_little_endian(self): + # Issue #23319 + class Little(LittleEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Little.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xef\xcd\xab\x21') + + @need_symbol('c_uint32') + def test_uint32_swap_big_endian(self): + # Issue #23319 + class Big(BigEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Big.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xab\xcd\xef\x12') + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch + written by Matthieu Gautier. + - Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - Issue #23254: Document how to close the TCPServer listening socket. diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -765,6 +765,7 @@ if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field)); + field = SWAP_INT(field); field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:36:18 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:36:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28ctypes=29?= Message-ID: <20150729123617.23410.47721@psf.io> https://hg.python.org/cpython/rev/883d2443941e changeset: 97120:883d2443941e branch: 3.5 parent: 97117:ebe72984c1b9 parent: 97119:935ae7f001e3 user: Victor Stinner date: Wed Jul 29 14:35:12 2015 +0200 summary: Merge 3.4 (ctypes) files: Lib/ctypes/test/test_bitfields.py | 28 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_ctypes/cfield.c | 1 + 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -259,5 +259,33 @@ x.a = 0xFEDCBA9876543211 self.assertEqual(x.a, 0xFEDCBA9876543211) + @need_symbol('c_uint32') + def test_uint32_swap_little_endian(self): + # Issue #23319 + class Little(LittleEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Little.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xef\xcd\xab\x21') + + @need_symbol('c_uint32') + def test_uint32_swap_big_endian(self): + # Issue #23319 + class Big(BigEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Big.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xab\xcd\xef\x12') + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch + written by Matthieu Gautier. + - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -765,6 +765,7 @@ if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field)); + field = SWAP_INT(field); field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:37:33 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:37:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMzE5?= =?utf-8?q?=3A_Fix_ctypes=2EBigEndianStructure=2C_swap_correctly_bytes=2E_?= =?utf-8?q?Patch?= Message-ID: <20150729123733.5517.38322@psf.io> https://hg.python.org/cpython/rev/88f2c4f12b56 changeset: 97122:88f2c4f12b56 branch: 2.7 parent: 97112:8afd995802a6 user: Victor Stinner date: Wed Jul 29 14:37:17 2015 +0200 summary: Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. files: Lib/ctypes/test/test_bitfields.py | 28 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_ctypes/cfield.c | 1 + 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -259,5 +259,33 @@ x.a = 0xFEDCBA9876543211 self.assertEqual(x.a, 0xFEDCBA9876543211) + @need_symbol('c_uint32') + def test_uint32_swap_little_endian(self): + # Issue #23319 + class Little(LittleEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Little.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xef\xcd\xab\x21') + + @need_symbol('c_uint32') + def test_uint32_swap_big_endian(self): + # Issue #23319 + class Big(BigEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Big.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xab\xcd\xef\x12') + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch + written by Matthieu Gautier. + - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -769,6 +769,7 @@ if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field)); + field = SWAP_INT(field); field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:41:30 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:41:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMzE5?= =?utf-8?q?=3A_Add_Matthieu_Gautier_to_Misc/ACKS?= Message-ID: <20150729124130.17725.75045@psf.io> https://hg.python.org/cpython/rev/12b353f76447 changeset: 97123:12b353f76447 branch: 2.7 user: Victor Stinner date: Wed Jul 29 14:40:27 2015 +0200 summary: Issue #23319: Add Matthieu Gautier to Misc/ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -460,6 +460,7 @@ Lars Marius Garshol Dan Gass Andrew Gaul +Matthieu Gautier Stephen M. Gava Xavier de Gaye Harry Henry Gebel -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:41:30 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:41:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMzE5?= =?utf-8?q?=3A_Add_Matthieu_Gautier_to_Misc/ACKS?= Message-ID: <20150729124130.29388.73464@psf.io> https://hg.python.org/cpython/rev/3caa68f55e3e changeset: 97124:3caa68f55e3e branch: 3.4 parent: 97119:935ae7f001e3 user: Victor Stinner date: Wed Jul 29 14:40:38 2015 +0200 summary: Issue #23319: Add Matthieu Gautier to Misc/ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -469,6 +469,7 @@ Lars Marius Garshol Dan Gass Andrew Gaul +Matthieu Gautier Stephen M. Gava Xavier de Gaye Harry Henry Gebel -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:41:32 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:41:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28Misc/ACKS=29?= Message-ID: <20150729124130.53975.27813@psf.io> https://hg.python.org/cpython/rev/f83864dd6e40 changeset: 97125:f83864dd6e40 branch: 3.5 parent: 97120:883d2443941e parent: 97124:3caa68f55e3e user: Victor Stinner date: Wed Jul 29 14:40:53 2015 +0200 summary: Merge 3.4 (Misc/ACKS) files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -476,6 +476,7 @@ Lars Marius Garshol Dan Gass Andrew Gaul +Matthieu Gautier Stephen M. Gava Xavier de Gaye Harry Henry Gebel -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 14:41:32 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 29 Jul 2015 12:41:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChNaXNjL0FDS1Mp?= Message-ID: <20150729124130.23398.17528@psf.io> https://hg.python.org/cpython/rev/4a0985c7674f changeset: 97126:4a0985c7674f parent: 97121:803a83dd3c9c parent: 97125:f83864dd6e40 user: Victor Stinner date: Wed Jul 29 14:41:02 2015 +0200 summary: Merge 3.5 (Misc/ACKS) files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -476,6 +476,7 @@ Lars Marius Garshol Dan Gass Andrew Gaul +Matthieu Gautier Stephen M. Gava Xavier de Gaye Harry Henry Gebel -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 15:58:16 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 29 Jul 2015 13:58:16 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Issue_=2323404=3A_Add_a_n?= =?utf-8?q?ote_to_clarify_that_=22make_touch=22_only_works_with_a_hg?= Message-ID: <20150729135816.29396.76944@psf.io> https://hg.python.org/devguide/rev/ffbb19026599 changeset: 754:ffbb19026599 user: Berker Peksag date: Wed Jul 29 16:58:08 2015 +0300 summary: Issue #23404: Add a note to clarify that "make touch" only works with a hg clone. Patch by Carol Willing. files: setup.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -308,7 +308,8 @@ To overcome this problem, auto-generated files are also checked into the Mercurial repository. So if you don't touch the auto-generation scripts, there's no real need to auto-generate anything. However, as Mercurial doesn't preserve -timestamps well, a special build target ``touch`` was added. Run:: +timestamps well, a special build target ``touch`` was added (the ``touch`` +build target is not designed for git clones and does not support them). Run:: make touch -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Wed Jul 29 18:45:12 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 29 Jul 2015 16:45:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_typeshed_link=2E?= Message-ID: <20150729164512.29398.9506@psf.io> https://hg.python.org/peps/rev/daf8448cd8d7 changeset: 5913:daf8448cd8d7 user: Guido van Rossum date: Wed Jul 29 18:44:48 2015 +0200 summary: Update typeshed link. files: pep-0484.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -1646,7 +1646,7 @@ http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29 .. [typeshed] - https://github.com/JukkaL/typeshed/ + https://github.com/python/typeshed/ .. [pyflakes] https://github.com/pyflakes/pyflakes/ -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Jul 29 19:00:27 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 29 Jul 2015 17:00:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_0431_withdrawal=2E?= Message-ID: <20150729170025.53973.24846@psf.io> https://hg.python.org/peps/rev/7eb9d7413960 changeset: 5914:7eb9d7413960 user: Guido van Rossum date: Wed Jul 29 19:00:15 2015 +0200 summary: PEP 0431 withdrawal. files: pep-0431.txt | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pep-0431.txt b/pep-0431.txt --- a/pep-0431.txt +++ b/pep-0431.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Lennart Regebro BDFL-Delegate: Barry Warsaw -Status: Deferred +Status: Withdrawn Type: Standards Track Content-Type: text/x-rst Created: 11-Dec-2012 @@ -19,17 +19,17 @@ with ambiguous time specifications during DST changes. -Postponement -============ +Withdrawal +========== -The implementation has turned out to be exceedingly complex, due to having to -convert back and forth between the local time and UTC during arithmetic -and adjusting the DST for each arithmetic step, with ambiguous times being -particularly hard to get right. +After lengthy discussion it has turned out that the things I thought was +problem in datetime's implementation are intentional. Those include +completely ignoring DST transistions when making date time arithmetic. +That makes the is_dst flags part of this PEP pointless, as they would +have no useful function. ``datetime`` by design does not separate between +ambiguous datetimes and will never do so. -This is likely to become much easier if the UTC timestamp is stored internally -and used for all arithmetic, and an investigation into changing the -``datetime()`` object to use UTC internally should be done. +I therefore withdraw this PEP. Proposal -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Jul 29 20:20:36 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 18:20:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNTg5?= =?utf-8?q?=3A_Remove_duplicate_sentence_from_the_FAQ=2E__Patch_by_Yongzhi?= =?utf-8?q?_Pan=2E?= Message-ID: <20150729182036.17739.46342@psf.io> https://hg.python.org/cpython/rev/941b9c27b8c8 changeset: 97128:941b9c27b8c8 branch: 3.4 parent: 97124:3caa68f55e3e user: Robert Collins date: Thu Jul 30 06:14:32 2015 +1200 summary: Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. files: Doc/faq/programming.rst | 6 ++---- Misc/NEWS | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -187,10 +187,8 @@ ------------------------------------------------------------ In Python, variables that are only referenced inside a function are implicitly -global. If a variable is assigned a new value anywhere within the function's -body, it's assumed to be a local. If a variable is ever assigned a new value -inside the function, the variable is implicitly local, and you need to -explicitly declare it as 'global'. +global. If a variable is assigned a value anywhere within the function's body, +it's assumed to be a local unless explicitly declared as global. Though a bit surprising at first, a moment's consideration explains this. On one hand, requiring :keyword:`global` for assigned variables provides a bar diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -396,6 +396,8 @@ Documentation ------------- +- Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. + - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:20:36 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 18:20:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNTg5?= =?utf-8?q?=3A_Remove_duplicate_sentence_from_the_FAQ=2E__Patch_by_Yongzhi?= =?utf-8?q?_Pan=2E?= Message-ID: <20150729182036.1374.62467@psf.io> https://hg.python.org/cpython/rev/02f3bf3f74aa changeset: 97127:02f3bf3f74aa branch: 2.7 parent: 97123:12b353f76447 user: Robert Collins date: Thu Jul 30 06:14:32 2015 +1200 summary: Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. files: Doc/faq/programming.rst | 6 ++---- Misc/NEWS | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -333,10 +333,8 @@ ------------------------------------------------------------ In Python, variables that are only referenced inside a function are implicitly -global. If a variable is assigned a new value anywhere within the function's -body, it's assumed to be a local. If a variable is ever assigned a new value -inside the function, the variable is implicitly local, and you need to -explicitly declare it as 'global'. +global. If a variable is assigned a value anywhere within the function's body, +it's assumed to be a local unless explicitly declared as global. Though a bit surprising at first, a moment's consideration explains this. On one hand, requiring :keyword:`global` for assigned variables provides a bar diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -136,6 +136,8 @@ Documentation ------------- +- Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. + - Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter doc. Remove obsolete example from FAQ. Patch by Martin Panter. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:20:36 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 18:20:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323589=3A_Remove_duplicate_sentence_from_the_FAQ?= =?utf-8?q?=2E__Patch_by_Yongzhi_Pan=2E?= Message-ID: <20150729182036.1372.16441@psf.io> https://hg.python.org/cpython/rev/7163dd7e9511 changeset: 97130:7163dd7e9511 parent: 97126:4a0985c7674f parent: 97129:93f3ca8fdc39 user: Robert Collins date: Thu Jul 30 06:20:21 2015 +1200 summary: Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. files: Doc/faq/programming.rst | 6 ++---- Misc/NEWS | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -187,10 +187,8 @@ ------------------------------------------------------------ In Python, variables that are only referenced inside a function are implicitly -global. If a variable is assigned a new value anywhere within the function's -body, it's assumed to be a local. If a variable is ever assigned a new value -inside the function, the variable is implicitly local, and you need to -explicitly declare it as 'global'. +global. If a variable is assigned a value anywhere within the function's body, +it's assumed to be a local unless explicitly declared as global. Though a bit surprising at first, a moment's consideration explains this. On one hand, requiring :keyword:`global` for assigned variables provides a bar diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -46,6 +46,11 @@ - Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo functions. +Documentation +------------- + +- Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:20:37 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 29 Jul 2015 18:20:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323589=3A_Remove_duplicate_sentence_from_the_FAQ=2E__P?= =?utf-8?q?atch_by_Yongzhi_Pan=2E?= Message-ID: <20150729182036.94782.55269@psf.io> https://hg.python.org/cpython/rev/93f3ca8fdc39 changeset: 97129:93f3ca8fdc39 branch: 3.5 parent: 97125:f83864dd6e40 parent: 97128:941b9c27b8c8 user: Robert Collins date: Thu Jul 30 06:16:46 2015 +1200 summary: Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. files: Doc/faq/programming.rst | 6 ++---- Misc/NEWS | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -187,10 +187,8 @@ ------------------------------------------------------------ In Python, variables that are only referenced inside a function are implicitly -global. If a variable is assigned a new value anywhere within the function's -body, it's assumed to be a local. If a variable is ever assigned a new value -inside the function, the variable is implicitly local, and you need to -explicitly declare it as 'global'. +global. If a variable is assigned a value anywhere within the function's body, +it's assumed to be a local unless explicitly declared as global. Though a bit surprising at first, a moment's consideration explains this. On one hand, requiring :keyword:`global` for assigned variables provides a bar diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,11 @@ - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. +Documentation +------------- + +- Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:30:05 2015 From: python-checkins at python.org (jason.coombs) Date: Wed, 29 Jul 2015 18:30:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_Merge?= Message-ID: <20150729183005.1379.31716@psf.io> https://hg.python.org/cpython/rev/3e3fe8a811c3 changeset: 97133:3e3fe8a811c3 branch: 3.4 parent: 97128:941b9c27b8c8 parent: 97132:20084be60761 user: Jason R. Coombs date: Wed Jul 29 14:25:58 2015 -0400 summary: Merge files: Doc/tutorial/inputoutput.rst | 6 +++--- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -247,8 +247,9 @@ omitted. Normally, files are opened in :dfn:`text mode`, that means, you read and write -strings from and to the file, which are encoded in a specific encoding (the -default being UTF-8). ``'b'`` appended to the mode opens the file in +strings from and to the file, which are encoded in a specific encoding. If +encoding is not specified, the default is platform dependent (see +:func:`open`). ``'b'`` appended to the mode opens the file in :dfn:`binary mode`: now the data is read and written in the form of bytes objects. This mode should be used for all files that don't contain text. @@ -437,4 +438,3 @@ written in other languages. It is also insecure by default: deserializing pickle data coming from an untrusted source can execute arbitrary code, if the data was crafted by a skilled attacker. - diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -398,6 +398,9 @@ - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. +- Issue #24729: Correct IO tutorial to match implementation regarding + encoding parameter to open function. + - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:30:05 2015 From: python-checkins at python.org (jason.coombs) Date: Wed, 29 Jul 2015 18:30:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzI5?= =?utf-8?q?=3A_Update_tutorial_to_match_implementation=2E?= Message-ID: <20150729183004.94788.93747@psf.io> https://hg.python.org/cpython/rev/c9e78d91d588 changeset: 97131:c9e78d91d588 branch: 3.4 parent: 97124:3caa68f55e3e user: Alessandro Cucci date: Tue Jul 28 21:00:10 2015 +0200 summary: Issue #24729: Update tutorial to match implementation. files: Doc/tutorial/inputoutput.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -247,8 +247,9 @@ omitted. Normally, files are opened in :dfn:`text mode`, that means, you read and write -strings from and to the file, which are encoded in a specific encoding (the -default being UTF-8). ``'b'`` appended to the mode opens the file in +strings from and to the file, which are encoded in a specific encoding. If +encoding is not specified the default is platform dependent (see :func:`~functions.open`). +``'b'`` appended to the mode opens the file in :dfn:`binary mode`: now the data is read and written in the form of bytes objects. This mode should be used for all files that don't contain text. @@ -437,4 +438,3 @@ written in other languages. It is also insecure by default: deserializing pickle data coming from an untrusted source can execute arbitrary code, if the data was crafted by a skilled attacker. - -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:30:05 2015 From: python-checkins at python.org (jason.coombs) Date: Wed, 29 Jul 2015 18:30:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzI5?= =?utf-8?q?=3A_Correct_reference_to_open_function=2E?= Message-ID: <20150729183005.53965.451@psf.io> https://hg.python.org/cpython/rev/20084be60761 changeset: 97132:20084be60761 branch: 3.4 user: Jason R. Coombs date: Wed Jul 29 14:04:36 2015 -0400 summary: Issue #24729: Correct reference to open function. files: Doc/tutorial/inputoutput.rst | 4 ++-- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -248,8 +248,8 @@ Normally, files are opened in :dfn:`text mode`, that means, you read and write strings from and to the file, which are encoded in a specific encoding. If -encoding is not specified the default is platform dependent (see :func:`~functions.open`). -``'b'`` appended to the mode opens the file in +encoding is not specified, the default is platform dependent (see +:func:`open`). ``'b'`` appended to the mode opens the file in :dfn:`binary mode`: now the data is read and written in the form of bytes objects. This mode should be used for all files that don't contain text. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -396,6 +396,9 @@ Documentation ------------- +- Issue #24729: Correct IO tutorial to match implementation regarding + encoding parameter to open function. + - Issue #24351: Clarify what is meant by "identifier" in the context of string.Template instances. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:30:05 2015 From: python-checkins at python.org (jason.coombs) Date: Wed, 29 Jul 2015 18:30:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4_for_Issue_=2324729?= Message-ID: <20150729183005.5539.79927@psf.io> https://hg.python.org/cpython/rev/575e60ed7cb8 changeset: 97134:575e60ed7cb8 branch: 3.5 parent: 97129:93f3ca8fdc39 parent: 97133:3e3fe8a811c3 user: Jason R. Coombs date: Wed Jul 29 14:29:26 2015 -0400 summary: Merge with 3.4 for Issue #24729 files: Doc/tutorial/inputoutput.rst | 6 +++--- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -247,8 +247,9 @@ omitted. Normally, files are opened in :dfn:`text mode`, that means, you read and write -strings from and to the file, which are encoded in a specific encoding (the -default being UTF-8). ``'b'`` appended to the mode opens the file in +strings from and to the file, which are encoded in a specific encoding. If +encoding is not specified, the default is platform dependent (see +:func:`open`). ``'b'`` appended to the mode opens the file in :dfn:`binary mode`: now the data is read and written in the form of bytes objects. This mode should be used for all files that don't contain text. @@ -437,4 +438,3 @@ written in other languages. It is also insecure by default: deserializing pickle data coming from an untrusted source can execute arbitrary code, if the data was crafted by a skilled attacker. - diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. +- Issue #24729: Correct IO tutorial to match implementation regarding + encoding parameter to open function. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 20:30:06 2015 From: python-checkins at python.org (jason.coombs) Date: Wed, 29 Jul 2015 18:30:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5_for_Issue_=2324729?= Message-ID: <20150729183005.110834.46202@psf.io> https://hg.python.org/cpython/rev/47330144debd changeset: 97135:47330144debd parent: 97130:7163dd7e9511 parent: 97134:575e60ed7cb8 user: Jason R. Coombs date: Wed Jul 29 14:29:47 2015 -0400 summary: Merge with 3.5 for Issue #24729 files: Doc/tutorial/inputoutput.rst | 6 +++--- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -247,8 +247,9 @@ omitted. Normally, files are opened in :dfn:`text mode`, that means, you read and write -strings from and to the file, which are encoded in a specific encoding (the -default being UTF-8). ``'b'`` appended to the mode opens the file in +strings from and to the file, which are encoded in a specific encoding. If +encoding is not specified, the default is platform dependent (see +:func:`open`). ``'b'`` appended to the mode opens the file in :dfn:`binary mode`: now the data is read and written in the form of bytes objects. This mode should be used for all files that don't contain text. @@ -437,4 +438,3 @@ written in other languages. It is also insecure by default: deserializing pickle data coming from an untrusted source can execute arbitrary code, if the data was crafted by a skilled attacker. - diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -51,6 +51,9 @@ - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. +- Issue #24729: Correct IO tutorial to match implementation regarding + encoding parameter to open function. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 22:51:53 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 29 Jul 2015 20:51:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324360=3A_Improve_?= =?utf-8?q?=5F=5Frepr=5F=5F_of_argparse=2ENamespace=28=29_for_invalid_iden?= =?utf-8?q?tifiers=2E?= Message-ID: <20150729205152.29386.86622@psf.io> https://hg.python.org/cpython/rev/dcc00d9ba8db changeset: 97136:dcc00d9ba8db user: Berker Peksag date: Wed Jul 29 23:51:47 2015 +0300 summary: Issue #24360: Improve __repr__ of argparse.Namespace() for invalid identifiers. Patch by Matthias Bussonnier. files: Lib/argparse.py | 8 +++++++- Lib/test/test_argparse.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -118,10 +118,16 @@ def __repr__(self): type_name = type(self).__name__ arg_strings = [] + star_args = {} for arg in self._get_args(): arg_strings.append(repr(arg)) for name, value in self._get_kwargs(): - arg_strings.append('%s=%r' % (name, value)) + if name.isidentifier(): + arg_strings.append('%s=%r' % (name, value)) + else: + star_args[name] = value + if star_args: + arg_strings.append('**%s' % repr(star_args)) return '%s(%s)' % (type_name, ', '.join(arg_strings)) def _get_kwargs(self): diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4512,6 +4512,21 @@ string = "Namespace(bar='spam', foo=42)" self.assertStringEqual(ns, string) + def test_namespace_starkwargs_notidentifier(self): + ns = argparse.Namespace(**{'"': 'quote'}) + string = """Namespace(**{'"': 'quote'})""" + self.assertStringEqual(ns, string) + + def test_namespace_kwargs_and_starkwargs_notidentifier(self): + ns = argparse.Namespace(a=1, **{'"': 'quote'}) + string = """Namespace(a=1, **{'"': 'quote'})""" + self.assertStringEqual(ns, string) + + def test_namespace_starkwargs_identifier(self): + ns = argparse.Namespace(**{'valid': True}) + string = "Namespace(valid=True)" + self.assertStringEqual(ns, string) + def test_parser(self): parser = argparse.ArgumentParser(prog='PROG') string = ( diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #24360: Improve __repr__ of argparse.Namespace() for invalid + identifiers. Patch by Matthias Bussonnier. + - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 23:04:36 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 29 Jul 2015 21:04:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324109=3A_Include_Tools/scripts/diff=2Epy_instea?= =?utf-8?q?d_of_duplicating_it_in?= Message-ID: <20150729210436.41833.20529@psf.io> https://hg.python.org/cpython/rev/aa2517e9f9ce changeset: 97138:aa2517e9f9ce parent: 97136:dcc00d9ba8db parent: 97137:8777e59a99bd user: Berker Peksag date: Thu Jul 30 00:04:11 2015 +0300 summary: Issue #24109: Include Tools/scripts/diff.py instead of duplicating it in difflib documentation. Patch by Keith Gray. files: Doc/library/difflib.rst | 63 +---------------------------- 1 files changed, 1 insertions(+), 62 deletions(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -743,65 +743,4 @@ It is also contained in the Python source distribution, as :file:`Tools/scripts/diff.py`. -.. testcode:: - - """ Command line interface to difflib.py providing diffs in four formats: - - * ndiff: lists every line and highlights interline changes. - * context: highlights clusters of changes in a before/after format. - * unified: highlights clusters of changes in an inline format. - * html: generates side by side comparison with change highlights. - - """ - - import sys, os, time, difflib, optparse - - def main(): - # Configure the option parser - usage = "usage: %prog [options] fromfile tofile" - parser = optparse.OptionParser(usage) - parser.add_option("-c", action="store_true", default=False, - help='Produce a context format diff (default)') - parser.add_option("-u", action="store_true", default=False, - help='Produce a unified format diff') - hlp = 'Produce HTML side by side diff (can use -c and -l in conjunction)' - parser.add_option("-m", action="store_true", default=False, help=hlp) - parser.add_option("-n", action="store_true", default=False, - help='Produce a ndiff format diff') - parser.add_option("-l", "--lines", type="int", default=3, - help='Set number of context lines (default 3)') - (options, args) = parser.parse_args() - - if len(args) == 0: - parser.print_help() - sys.exit(1) - if len(args) != 2: - parser.error("need to specify both a fromfile and tofile") - - n = options.lines - fromfile, tofile = args # as specified in the usage string - - # we're passing these as arguments to the diff function - fromdate = time.ctime(os.stat(fromfile).st_mtime) - todate = time.ctime(os.stat(tofile).st_mtime) - with open(fromfile) as fromf, open(tofile) as tof: - fromlines, tolines = list(fromf), list(tof) - - if options.u: - diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile, - fromdate, todate, n=n) - elif options.n: - diff = difflib.ndiff(fromlines, tolines) - elif options.m: - diff = difflib.HtmlDiff().make_file(fromlines, tolines, fromfile, - tofile, context=options.c, - numlines=n) - else: - diff = difflib.context_diff(fromlines, tolines, fromfile, tofile, - fromdate, todate, n=n) - - # we're using writelines because diff is a generator - sys.stdout.writelines(diff) - - if __name__ == '__main__': - main() +.. literalinclude:: ../../Tools/scripts/diff.py -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Jul 29 23:04:37 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 29 Jul 2015 21:04:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0MTA5?= =?utf-8?q?=3A_Include_Tools/scripts/diff=2Epy_instead_of_duplicating_it_i?= =?utf-8?q?n?= Message-ID: <20150729210436.41837.24325@psf.io> https://hg.python.org/cpython/rev/8777e59a99bd changeset: 97137:8777e59a99bd branch: 3.5 parent: 97134:575e60ed7cb8 user: Berker Peksag date: Thu Jul 30 00:03:48 2015 +0300 summary: Issue #24109: Include Tools/scripts/diff.py instead of duplicating it in difflib documentation. Patch by Keith Gray. files: Doc/library/difflib.rst | 63 +---------------------------- 1 files changed, 1 insertions(+), 62 deletions(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -743,65 +743,4 @@ It is also contained in the Python source distribution, as :file:`Tools/scripts/diff.py`. -.. testcode:: - - """ Command line interface to difflib.py providing diffs in four formats: - - * ndiff: lists every line and highlights interline changes. - * context: highlights clusters of changes in a before/after format. - * unified: highlights clusters of changes in an inline format. - * html: generates side by side comparison with change highlights. - - """ - - import sys, os, time, difflib, optparse - - def main(): - # Configure the option parser - usage = "usage: %prog [options] fromfile tofile" - parser = optparse.OptionParser(usage) - parser.add_option("-c", action="store_true", default=False, - help='Produce a context format diff (default)') - parser.add_option("-u", action="store_true", default=False, - help='Produce a unified format diff') - hlp = 'Produce HTML side by side diff (can use -c and -l in conjunction)' - parser.add_option("-m", action="store_true", default=False, help=hlp) - parser.add_option("-n", action="store_true", default=False, - help='Produce a ndiff format diff') - parser.add_option("-l", "--lines", type="int", default=3, - help='Set number of context lines (default 3)') - (options, args) = parser.parse_args() - - if len(args) == 0: - parser.print_help() - sys.exit(1) - if len(args) != 2: - parser.error("need to specify both a fromfile and tofile") - - n = options.lines - fromfile, tofile = args # as specified in the usage string - - # we're passing these as arguments to the diff function - fromdate = time.ctime(os.stat(fromfile).st_mtime) - todate = time.ctime(os.stat(tofile).st_mtime) - with open(fromfile) as fromf, open(tofile) as tof: - fromlines, tolines = list(fromf), list(tof) - - if options.u: - diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile, - fromdate, todate, n=n) - elif options.n: - diff = difflib.ndiff(fromlines, tolines) - elif options.m: - diff = difflib.HtmlDiff().make_file(fromlines, tolines, fromfile, - tofile, context=options.c, - numlines=n) - else: - diff = difflib.context_diff(fromlines, tolines, fromfile, tofile, - fromdate, todate, n=n) - - # we're using writelines because diff is a generator - sys.stdout.writelines(diff) - - if __name__ == '__main__': - main() +.. literalinclude:: ../../Tools/scripts/diff.py -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 07:18:31 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 30 Jul 2015 05:18:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_make_comment_n?= =?utf-8?q?ot_lie_about_the_size_of_SMALL=5FREQUEST=5FTHRESHOLD?= Message-ID: <20150730051831.29414.59718@psf.io> https://hg.python.org/cpython/rev/148638b777b7 changeset: 97139:148638b777b7 branch: 2.7 parent: 97127:02f3bf3f74aa user: Benjamin Peterson date: Wed Jul 29 22:18:16 2015 -0700 summary: make comment not lie about the size of SMALL_REQUEST_THRESHOLD files: Objects/obmalloc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -167,7 +167,7 @@ * this value according to your application behaviour and memory needs. * * The following invariants must hold: - * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 256 + * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 512 * 2) SMALL_REQUEST_THRESHOLD is evenly divisible by ALIGNMENT * * Note: a size threshold of 512 guarantees that newly created dictionaries -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 07:51:59 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 30 Jul 2015 05:51:59 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_describe_how_to_add/remov?= =?utf-8?q?e_hg_users?= Message-ID: <20150730055159.17709.44831@psf.io> https://hg.python.org/devguide/rev/eaa3d077a4c6 changeset: 755:eaa3d077a4c6 user: Benjamin Peterson date: Wed Jul 29 22:51:55 2015 -0700 summary: describe how to add/remove hg users files: developers.rst | 26 ++++++++++++++++++++++---- 1 files changed, 22 insertions(+), 4 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -8,10 +8,10 @@ The purpose is to provide some institutional memory of who was given access and why. -The first entry starts in April 2005. In keeping with the style of -Misc/NEWS, newer entries should be added to the top. -Entries should include the initials of the -project admin who made the change or granted access. +The first entry starts in April 2005. In keeping with the style of Misc/NEWS, +newer entries should be added to the top. Entries should include the initials +of the project admin who made the change or granted access. The procedure for +adding or removing users is described in :ref:`altering-access`. Note, when giving new commit permissions, be sure to get a contributor agreement from the committer. See http://www.python.org/psf/contrib/ for details. When @@ -457,3 +457,21 @@ * MvL: Martin v. Loewis * GvR: Guido van Rossum * RDH: Raymond Hettinger + + +.. _altering-access: + +Procedure for Granting or Dropping Access +----------------------------------------- + +Obtain a checkout of the keys repo:: + + hg clone ssh://hgaccounts at hg.python.org/repo + +The key files are stored in the form ``first.last``. Simply create or remove the +appropriate file, commit the change, and push. A hook on the server should +automatically regenerate the ``authorized_keys`` file for the ``hg`` user. Make +sure to update the developer log above. + +To add or remove hg account admins, submit pull requests to the `psf-salt repo +`_. -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Thu Jul 30 10:16:16 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 30 Jul 2015 08:16:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChvcy51cmFuZG9tKQ==?= Message-ID: <20150730081616.1379.14267@psf.io> https://hg.python.org/cpython/rev/89d34aea8d7e changeset: 97141:89d34aea8d7e parent: 97138:aa2517e9f9ce parent: 97140:25403a40feb2 user: Victor Stinner date: Thu Jul 30 10:14:52 2015 +0200 summary: Merge 3.5 (os.urandom) files: Python/random.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -142,7 +142,6 @@ } if (errno == EINTR) { - /* Note: EINTR should not occur with flags=0 */ if (PyErr_CheckSignals()) { if (!raise) Py_FatalError("getrandom() interrupted by a signal"); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 10:16:16 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 30 Jul 2015 08:16:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogcHlfZ2V0cmFuZG9t?= =?utf-8?q?=28=29=3A_getrandom=28=29_*can*_return_EINTR?= Message-ID: <20150730081616.41825.31990@psf.io> https://hg.python.org/cpython/rev/25403a40feb2 changeset: 97140:25403a40feb2 branch: 3.5 parent: 97137:8777e59a99bd user: Victor Stinner date: Thu Jul 30 10:13:52 2015 +0200 summary: py_getrandom(): getrandom() *can* return EINTR See the latest version of getrandom() manual page: http://man7.org/linux/man-pages/man2/getrandom.2.html#NOTES The behavior when a call to getrandom() that is blocked while reading from /dev/urandom is interrupted by a signal handler depends on the initialization state of the entropy buffer and on the request size, buflen. If the entropy is not yet initialized, then the call will fail with the EINTR error. If the entropy pool has been initialized and the request size is large (buflen > 256), the call either succeeds, returning a partially filled buffer, or fails with the error EINTR. If the entropy pool has been initialized and the request size is small (buflen <= 256), then getrandom() will not fail with EINTR. Instead, it will return all of the bytes that have been requested. Note: py_getrandom() calls getrandom() with flags=0. files: Python/random.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -142,7 +142,6 @@ } if (errno == EINTR) { - /* Note: EINTR should not occur with flags=0 */ if (PyErr_CheckSignals()) { if (!raise) Py_FatalError("getrandom() interrupted by a signal"); -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Thu Jul 30 10:29:07 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Thu, 30 Jul 2015 08:29:07 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-07-30 Message-ID: Results for project python_default-nightly, build date 2015-07-30 09:02:00 commit: aa2517e9f9ce57bf0fb58f42089dedfe644a6e5a revision date: 2015-07-30 00:04:11 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-| pybench sec 0.32445% -1.75118% :-( regex_v8 sec 0.55912% -3.73455% :-| nbody sec 1.84600% -0.94510% :-( json_dump_v2 sec -2.47270% -2.76687% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From solipsis at pitrou.net Thu Jul 30 10:44:20 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 30 Jul 2015 08:44:20 +0000 Subject: [Python-checkins] Daily reference leaks (aa2517e9f9ce): sum=4 Message-ID: <20150730084419.53963.60198@psf.io> results for aa2517e9f9ce on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogCNXz_W', '--timeout', '7200'] From python-checkins at python.org Thu Jul 30 16:50:43 2015 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 30 Jul 2015 14:50:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1MTM4?= =?utf-8?q?=3A_Speed_up_base64=2Eurlsafe=5Fb64*_considerably_=282=2E7_back?= =?utf-8?b?cG9ydCku?= Message-ID: <20150730145042.23406.57179@psf.io> https://hg.python.org/cpython/rev/309cbbc32491 changeset: 97142:309cbbc32491 branch: 2.7 parent: 97139:148638b777b7 user: Guido van Rossum date: Thu Jul 30 16:50:25 2015 +0200 summary: Issue #15138: Speed up base64.urlsafe_b64* considerably (2.7 backport). files: Lib/base64.py | 14 +++++++++----- Misc/NEWS | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/base64.py b/Lib/base64.py --- a/Lib/base64.py +++ b/Lib/base64.py @@ -7,6 +7,7 @@ import re import struct +import string import binascii @@ -52,7 +53,7 @@ # Strip off the trailing newline encoded = binascii.b2a_base64(s)[:-1] if altchars is not None: - return _translate(encoded, {'+': altchars[0], '/': altchars[1]}) + return encoded.translate(string.maketrans(b'+/', altchars[:2])) return encoded @@ -68,7 +69,7 @@ string. """ if altchars is not None: - s = _translate(s, {altchars[0]: '+', altchars[1]: '/'}) + s = s.translate(string.maketrans(altchars[:2], '+/')) try: return binascii.a2b_base64(s) except binascii.Error, msg: @@ -92,13 +93,16 @@ """ return b64decode(s) +_urlsafe_encode_translation = string.maketrans(b'+/', b'-_') +_urlsafe_decode_translation = string.maketrans(b'-_', b'+/') + def urlsafe_b64encode(s): """Encode a string using a url-safe Base64 alphabet. s is the string to encode. The encoded string is returned. The alphabet uses '-' instead of '+' and '_' instead of '/'. """ - return b64encode(s, '-_') + return b64encode(s).translate(_urlsafe_encode_translation) def urlsafe_b64decode(s): """Decode a string encoded with the standard Base64 alphabet. @@ -109,7 +113,7 @@ The alphabet uses '-' instead of '+' and '_' instead of '/'. """ - return b64decode(s, '-_') + return b64decode(s.translate(_urlsafe_decode_translation)) @@ -200,7 +204,7 @@ # False, or the character to map the digit 1 (one) to. It should be # either L (el) or I (eye). if map01: - s = _translate(s, {'0': 'O', '1': map01}) + s = s.translate(string.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() # Strip off pad characters from the right. We need to count the pad diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #15138: Speed up base64.urlsafe_b64{en,de}code considerably. + - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 17:06:56 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 15:06:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE1NTgy?= =?utf-8?q?=3A_Add_a_whatsnew_entry_for_inspect=2Egetdoc=28=29_changes_in_?= =?utf-8?q?3=2E5=2E?= Message-ID: <20150730150653.110979.58655@psf.io> https://hg.python.org/cpython/rev/4476b578b8fd changeset: 97143:4476b578b8fd branch: 3.5 parent: 97140:25403a40feb2 user: Berker Peksag date: Thu Jul 30 18:06:09 2015 +0300 summary: Issue #15582: Add a whatsnew entry for inspect.getdoc() changes in 3.5. Patch by Martin Panter. files: Doc/library/inspect.rst | 3 +++ Doc/whatsnew/3.5.rst | 7 +++++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -423,6 +423,9 @@ a class, a method, a property or a descriptor, retrieve the documentation string from the inheritance hierarchy. + .. versionchanged:: 3.5 + Documentation strings are now inherited if not overridden. + .. function:: getcomments(object) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1139,6 +1139,13 @@ ``True`` when finding the empty string and the indexes are completely out of range. See :issue:`24284`. +* The :func:`inspect.getdoc` function now returns documentation strings + inherited from base classes. Documentation strings no longer need to be + duplicated if the inherited documentation is appropriate. To suppress an + inherited string, an empty string must be specified (or the documentation + may be filled in). This change affects the output of the :mod:`pydoc` + module and the :func:`help` function. See :issue:`15582`. + Changes in the C API -------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 17:06:56 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 15:06:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315582=3A_Add_a_whatsnew_entry_for_inspect=2Eget?= =?utf-8?b?ZG9jKCkgY2hhbmdlcyBpbiAzLjUu?= Message-ID: <20150730150654.110979.89254@psf.io> https://hg.python.org/cpython/rev/e0f4a5f09bfa changeset: 97144:e0f4a5f09bfa parent: 97141:89d34aea8d7e parent: 97143:4476b578b8fd user: Berker Peksag date: Thu Jul 30 18:06:30 2015 +0300 summary: Issue #15582: Add a whatsnew entry for inspect.getdoc() changes in 3.5. Patch by Martin Panter. files: Doc/library/inspect.rst | 3 +++ Doc/whatsnew/3.5.rst | 7 +++++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -404,6 +404,9 @@ a class, a method, a property or a descriptor, retrieve the documentation string from the inheritance hierarchy. + .. versionchanged:: 3.5 + Documentation strings are now inherited if not overridden. + .. function:: getcomments(object) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1139,6 +1139,13 @@ ``True`` when finding the empty string and the indexes are completely out of range. See :issue:`24284`. +* The :func:`inspect.getdoc` function now returns documentation strings + inherited from base classes. Documentation strings no longer need to be + duplicated if the inherited documentation is appropriate. To suppress an + inherited string, an empty string must be specified (or the documentation + may be filled in). This change affects the output of the :mod:`pydoc` + module and the :func:`help` function. See :issue:`15582`. + Changes in the C API -------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 17:27:34 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 15:27:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2312160=3A_Fix_incorrect_StreamCodec_references_i?= =?utf-8?q?n_Codec=2Eencode=28=29_and?= Message-ID: <20150730152734.17711.23128@psf.io> https://hg.python.org/cpython/rev/d3b20bff9c5d changeset: 97147:d3b20bff9c5d parent: 97144:e0f4a5f09bfa parent: 97146:98631f35426f user: Berker Peksag date: Thu Jul 30 18:27:04 2015 +0300 summary: Issue #12160: Fix incorrect StreamCodec references in Codec.encode() and Codec.decode() docs. It should StreamWriter for Codecs.encode() and StreamReader for Codec.decode(). Patch by Nick Weinhold. files: Doc/library/codecs.rst | 8 ++++---- Lib/codecs.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -454,8 +454,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamWriter` for codecs which have to keep state in order to make + encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this situation. @@ -476,8 +476,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamReader` for codecs which have to keep state in order to make + decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this situation. diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -143,8 +143,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamWriter for codecs which have to keep state in order to + make encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this @@ -166,8 +166,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamReader for codecs which have to keep state in order to + make decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 17:27:34 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 15:27:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzEyMTYw?= =?utf-8?q?=3A_Fix_incorrect_StreamCodec_references_in_Codec=2Eencode=28?= =?utf-8?q?=29_and?= Message-ID: <20150730152734.1399.21256@psf.io> https://hg.python.org/cpython/rev/f9694502f07c changeset: 97145:f9694502f07c branch: 3.4 parent: 97133:3e3fe8a811c3 user: Berker Peksag date: Thu Jul 30 18:26:10 2015 +0300 summary: Issue #12160: Fix incorrect StreamCodec references in Codec.encode() and Codec.decode() docs. It should StreamWriter for Codecs.encode() and StreamReader for Codec.decode(). Patch by Nick Weinhold. files: Doc/library/codecs.rst | 8 ++++---- Lib/codecs.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -436,8 +436,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamWriter` for codecs which have to keep state in order to make + encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this situation. @@ -458,8 +458,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamReader` for codecs which have to keep state in order to make + decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this situation. diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -141,8 +141,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamWriter for codecs which have to keep state in order to + make encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this @@ -164,8 +164,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamReader for codecs which have to keep state in order to + make decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 17:27:36 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 15:27:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2312160=3A_Fix_incorrect_StreamCodec_references_in_Code?= =?utf-8?q?c=2Eencode=28=29_and?= Message-ID: <20150730152734.111049.92845@psf.io> https://hg.python.org/cpython/rev/98631f35426f changeset: 97146:98631f35426f branch: 3.5 parent: 97143:4476b578b8fd parent: 97145:f9694502f07c user: Berker Peksag date: Thu Jul 30 18:26:35 2015 +0300 summary: Issue #12160: Fix incorrect StreamCodec references in Codec.encode() and Codec.decode() docs. It should StreamWriter for Codecs.encode() and StreamReader for Codec.decode(). Patch by Nick Weinhold. files: Doc/library/codecs.rst | 8 ++++---- Lib/codecs.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -454,8 +454,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamWriter` for codecs which have to keep state in order to make + encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this situation. @@ -476,8 +476,8 @@ It defaults to ``'strict'`` handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamReader` for codecs which have to keep state in order to make + decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this situation. diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -143,8 +143,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamWriter for codecs which have to keep state in order to + make encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this @@ -166,8 +166,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamReader for codecs which have to keep state in order to + make decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 19:56:04 2015 From: python-checkins at python.org (jesus.cea) Date: Thu, 30 Jul 2015 17:56:04 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Write_my_name_correctly?= Message-ID: <20150730175604.17735.48777@psf.io> https://hg.python.org/devguide/rev/da60478118e7 changeset: 756:da60478118e7 user: Jesus Cea date: Thu Jul 30 19:55:58 2015 +0200 summary: Write my name correctly files: developers.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -241,7 +241,7 @@ - Heiko Weinen was given SVN access on 29 April 2008 by MvL, for GSoC contributions. -- Jesus Cea was given SVN access on 24 April 2008 by MvL, +- Jes?s Cea was given SVN access on 24 April 2008 by MvL, for maintenance of bsddb. - Guilherme Polo was given SVN access on 24 April 2008 by MvL, -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Thu Jul 30 20:51:51 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 30 Jul 2015 18:51:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Update_default_msvccompiler_link_options_to_match_the_op?= =?utf-8?q?tions_used_for_core?= Message-ID: <20150730185151.29402.74717@psf.io> https://hg.python.org/cpython/rev/7ada3cc41e2a changeset: 97149:7ada3cc41e2a parent: 97147:d3b20bff9c5d parent: 97148:401c65b0ae3f user: Steve Dower date: Thu Jul 30 11:51:30 2015 -0700 summary: Update default msvccompiler link options to match the options used for core builds. files: Lib/distutils/_msvccompiler.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -207,10 +207,10 @@ ] self.ldflags_shared = [ - '/nologo', '/DLL', '/INCREMENTAL:NO' + '/nologo', '/DLL', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib' ] self.ldflags_shared_debug = [ - '/nologo', '/DLL', '/INCREMENTAL:no', '/DEBUG:FULL' + '/nologo', '/DLL', '/INCREMENTAL:no', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib' ] self.ldflags_static = [ '/nologo' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 20:51:51 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 30 Jul 2015 18:51:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Update_default?= =?utf-8?q?_msvccompiler_link_options_to_match_the_options_used_for_core?= Message-ID: <20150730185151.53979.79759@psf.io> https://hg.python.org/cpython/rev/401c65b0ae3f changeset: 97148:401c65b0ae3f branch: 3.5 parent: 97146:98631f35426f user: Steve Dower date: Thu Jul 30 11:51:06 2015 -0700 summary: Update default msvccompiler link options to match the options used for core builds. This ensures that wheels will work when moved to machines that have the same subset of the MSVC libraries as a regular CPython install. Specifically, vcruntime##0.dll may not be installed, and should not be a dependency. files: Lib/distutils/_msvccompiler.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -207,10 +207,10 @@ ] self.ldflags_shared = [ - '/nologo', '/DLL', '/INCREMENTAL:NO' + '/nologo', '/DLL', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib' ] self.ldflags_shared_debug = [ - '/nologo', '/DLL', '/INCREMENTAL:no', '/DEBUG:FULL' + '/nologo', '/DLL', '/INCREMENTAL:no', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib' ] self.ldflags_static = [ '/nologo' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 22:27:22 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 30 Jul 2015 20:27:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEyMTYw?= =?utf-8?q?=3A_Fix_incorrect_StreamCodec_references_in_Codec=2Eencode=28?= =?utf-8?q?=29_and?= Message-ID: <20150730202719.23404.12200@psf.io> https://hg.python.org/cpython/rev/296a09614f31 changeset: 97150:296a09614f31 branch: 2.7 parent: 97142:309cbbc32491 user: Berker Peksag date: Thu Jul 30 23:27:13 2015 +0300 summary: Issue #12160: Fix incorrect StreamCodec references in Codec.encode() and Codec.decode() docs. It should StreamWriter for Codecs.encode() and StreamReader for Codec.decode(). Patch by Nick Weinhold. files: Doc/library/codecs.rst | 8 ++++---- Lib/codecs.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -392,8 +392,8 @@ handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamWriter` for codecs which have to keep state in order to make + encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this situation. @@ -413,8 +413,8 @@ handling. The method may not store state in the :class:`Codec` instance. Use - :class:`StreamCodec` for codecs which have to keep state in order to make - encoding/decoding efficient. + :class:`StreamReader` for codecs which have to keep state in order to make + decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this situation. diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -138,8 +138,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamWriter for codecs which have to keep state in order to + make encoding efficient. The encoder must be able to handle zero length input and return an empty object of the output object type in this @@ -161,8 +161,8 @@ 'strict' handling. The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. + StreamReader for codecs which have to keep state in order to + make decoding efficient. The decoder must be able to handle zero length input and return an empty object of the output object type in this -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 22:45:14 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 30 Jul 2015 20:45:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzEzODg0?= =?utf-8?q?=3A_Idle=3A_Remove_tearoff_lines_from_menus=2E_Patch_by_Roger_S?= =?utf-8?q?erwy=2E?= Message-ID: <20150730204514.29416.82403@psf.io> https://hg.python.org/cpython/rev/6eb4441ed14b changeset: 97152:6eb4441ed14b branch: 3.4 parent: 97145:f9694502f07c user: Terry Jan Reedy date: Thu Jul 30 16:44:22 2015 -0400 summary: Issue #13884: Idle: Remove tearoff lines from menus. Patch by Roger Serwy. files: Doc/library/idle.rst | 2 -- Lib/idlelib/EditorWindow.py | 7 ++++--- Lib/idlelib/help.txt | 4 +--- Lib/idlelib/macosxSupport.py | 5 +++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -37,8 +37,6 @@ IDLE's menus dynamically change based on which window is currently selected. Each menu documented below indicates which window type it is associated with. -Click on the dotted line at the top of a menu to "tear it off": a separate -window containing the menu is created (for Unix and Windows only). File menu (Shell and Editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -447,14 +447,15 @@ self.menudict = menudict = {} for name, label in self.menu_specs: underline, label = prepstr(label) - menudict[name] = menu = Menu(mbar, name=name) + menudict[name] = menu = Menu(mbar, name=name, tearoff=0) mbar.add_cascade(label=label, menu=menu, underline=underline) if macosxSupport.isCarbonTk(): # Insert the application menu - menudict['application'] = menu = Menu(mbar, name='apple') + menudict['application'] = menu = Menu(mbar, name='apple', + tearoff=0) mbar.add_cascade(label='IDLE', menu=menu) self.fill_menus() - self.recent_files_menu = Menu(self.menubar) + self.recent_files_menu = Menu(self.menubar, tearoff=0) self.menudict['file'].insert_cascade(3, label='Recent Files', underline=0, menu=self.recent_files_menu) diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -15,9 +15,7 @@ IDLE has two window types the Shell window and the Editor window. It is possible to have multiple editor windows simultaneously. IDLE's menus dynamically change based on which window is currently selected. Each menu -documented below indicates which window type it is associated with. Click on -the dotted line at the top of a menu to "tear it off": a separate window -containing the menu is created (for Unix and Windows only). +documented below indicates which window type it is associated with. File Menu (Shell and Editor): diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -145,7 +145,7 @@ root.configure(menu=menubar) menudict = {} - menudict['windows'] = menu = Menu(menubar, name='windows') + menudict['windows'] = menu = Menu(menubar, name='windows', tearoff=0) menubar.add_cascade(label='Window', menu=menu, underline=0) def postwindowsmenu(menu=menu): @@ -191,7 +191,8 @@ if isCarbonTk(): # for Carbon AquaTk, replace the default Tk apple menu - menudict['application'] = menu = Menu(menubar, name='apple') + menudict['application'] = menu = Menu(menubar, name='apple', + tearoff=0) menubar.add_cascade(label='IDLE', menu=menu) Bindings.menudefs.insert(0, ('application', [ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 22:45:15 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 30 Jul 2015 20:45:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150730204514.94782.73800@psf.io> https://hg.python.org/cpython/rev/3dd296430cc7 changeset: 97153:3dd296430cc7 branch: 3.5 parent: 97148:401c65b0ae3f parent: 97152:6eb4441ed14b user: Terry Jan Reedy date: Thu Jul 30 16:44:41 2015 -0400 summary: Merge with 3.4 files: Doc/library/idle.rst | 2 -- Lib/idlelib/EditorWindow.py | 7 ++++--- Lib/idlelib/help.txt | 4 +--- Lib/idlelib/macosxSupport.py | 5 +++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -37,8 +37,6 @@ IDLE's menus dynamically change based on which window is currently selected. Each menu documented below indicates which window type it is associated with. -Click on the dotted line at the top of a menu to "tear it off": a separate -window containing the menu is created (for Unix and Windows only). File menu (Shell and Editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -447,14 +447,15 @@ self.menudict = menudict = {} for name, label in self.menu_specs: underline, label = prepstr(label) - menudict[name] = menu = Menu(mbar, name=name) + menudict[name] = menu = Menu(mbar, name=name, tearoff=0) mbar.add_cascade(label=label, menu=menu, underline=underline) if macosxSupport.isCarbonTk(): # Insert the application menu - menudict['application'] = menu = Menu(mbar, name='apple') + menudict['application'] = menu = Menu(mbar, name='apple', + tearoff=0) mbar.add_cascade(label='IDLE', menu=menu) self.fill_menus() - self.recent_files_menu = Menu(self.menubar) + self.recent_files_menu = Menu(self.menubar, tearoff=0) self.menudict['file'].insert_cascade(3, label='Recent Files', underline=0, menu=self.recent_files_menu) diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -15,9 +15,7 @@ IDLE has two window types the Shell window and the Editor window. It is possible to have multiple editor windows simultaneously. IDLE's menus dynamically change based on which window is currently selected. Each menu -documented below indicates which window type it is associated with. Click on -the dotted line at the top of a menu to "tear it off": a separate window -containing the menu is created (for Unix and Windows only). +documented below indicates which window type it is associated with. File Menu (Shell and Editor): diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -145,7 +145,7 @@ root.configure(menu=menubar) menudict = {} - menudict['windows'] = menu = Menu(menubar, name='windows') + menudict['windows'] = menu = Menu(menubar, name='windows', tearoff=0) menubar.add_cascade(label='Window', menu=menu, underline=0) def postwindowsmenu(menu=menu): @@ -191,7 +191,8 @@ if isCarbonTk(): # for Carbon AquaTk, replace the default Tk apple menu - menudict['application'] = menu = Menu(menubar, name='apple') + menudict['application'] = menu = Menu(menubar, name='apple', + tearoff=0) menubar.add_cascade(label='IDLE', menu=menu) Bindings.menudefs.insert(0, ('application', [ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 22:45:15 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 30 Jul 2015 20:45:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150730204515.53967.91354@psf.io> https://hg.python.org/cpython/rev/f05fc1a16e53 changeset: 97154:f05fc1a16e53 parent: 97149:7ada3cc41e2a parent: 97153:3dd296430cc7 user: Terry Jan Reedy date: Thu Jul 30 16:44:55 2015 -0400 summary: Merge with 3.5 files: Doc/library/idle.rst | 2 -- Lib/idlelib/EditorWindow.py | 7 ++++--- Lib/idlelib/help.txt | 4 +--- Lib/idlelib/macosxSupport.py | 5 +++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -37,8 +37,6 @@ IDLE's menus dynamically change based on which window is currently selected. Each menu documented below indicates which window type it is associated with. -Click on the dotted line at the top of a menu to "tear it off": a separate -window containing the menu is created (for Unix and Windows only). File menu (Shell and Editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -447,14 +447,15 @@ self.menudict = menudict = {} for name, label in self.menu_specs: underline, label = prepstr(label) - menudict[name] = menu = Menu(mbar, name=name) + menudict[name] = menu = Menu(mbar, name=name, tearoff=0) mbar.add_cascade(label=label, menu=menu, underline=underline) if macosxSupport.isCarbonTk(): # Insert the application menu - menudict['application'] = menu = Menu(mbar, name='apple') + menudict['application'] = menu = Menu(mbar, name='apple', + tearoff=0) mbar.add_cascade(label='IDLE', menu=menu) self.fill_menus() - self.recent_files_menu = Menu(self.menubar) + self.recent_files_menu = Menu(self.menubar, tearoff=0) self.menudict['file'].insert_cascade(3, label='Recent Files', underline=0, menu=self.recent_files_menu) diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -15,9 +15,7 @@ IDLE has two window types the Shell window and the Editor window. It is possible to have multiple editor windows simultaneously. IDLE's menus dynamically change based on which window is currently selected. Each menu -documented below indicates which window type it is associated with. Click on -the dotted line at the top of a menu to "tear it off": a separate window -containing the menu is created (for Unix and Windows only). +documented below indicates which window type it is associated with. File Menu (Shell and Editor): diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -145,7 +145,7 @@ root.configure(menu=menubar) menudict = {} - menudict['windows'] = menu = Menu(menubar, name='windows') + menudict['windows'] = menu = Menu(menubar, name='windows', tearoff=0) menubar.add_cascade(label='Window', menu=menu, underline=0) def postwindowsmenu(menu=menu): @@ -191,7 +191,8 @@ if isCarbonTk(): # for Carbon AquaTk, replace the default Tk apple menu - menudict['application'] = menu = Menu(menubar, name='apple') + menudict['application'] = menu = Menu(menubar, name='apple', + tearoff=0) menubar.add_cascade(label='IDLE', menu=menu) Bindings.menudefs.insert(0, ('application', [ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 22:45:15 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 30 Jul 2015 20:45:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzODg0?= =?utf-8?q?=3A_Idle=3A_Remove_tearoff_lines_from_menus=2E_Patch_by_Roger_S?= =?utf-8?q?erwy=2E?= Message-ID: <20150730204514.41851.31145@psf.io> https://hg.python.org/cpython/rev/bead9330438c changeset: 97151:bead9330438c branch: 2.7 user: Terry Jan Reedy date: Thu Jul 30 16:44:09 2015 -0400 summary: Issue #13884: Idle: Remove tearoff lines from menus. Patch by Roger Serwy. files: Doc/library/idle.rst | 2 -- Lib/idlelib/EditorWindow.py | 7 ++++--- Lib/idlelib/help.txt | 3 --- Lib/idlelib/macosxSupport.py | 5 +++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -37,8 +37,6 @@ IDLE's menus dynamically change based on which window is currently selected. Each menu documented below indicates which window type it is associated with. -Click on the dotted line at the top of a menu to "tear it off": a separate -window containing the menu is created (for Unix and Windows only). File menu (Shell and Editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -316,7 +316,7 @@ io.set_filename_change_hook(self.filename_change_hook) # Create the recent files submenu - self.recent_files_menu = Menu(self.menubar) + self.recent_files_menu = Menu(self.menubar, tearoff=0) self.menudict['file'].insert_cascade(3, label='Recent Files', underline=0, menu=self.recent_files_menu) @@ -477,12 +477,13 @@ self.menudict = menudict = {} for name, label in self.menu_specs: underline, label = prepstr(label) - menudict[name] = menu = Menu(mbar, name=name) + menudict[name] = menu = Menu(mbar, name=name, tearoff=0) mbar.add_cascade(label=label, menu=menu, underline=underline) if macosxSupport.isCarbonTk(): # Insert the application menu - menudict['application'] = menu = Menu(mbar, name='apple') + menudict['application'] = menu = Menu(mbar, name='apple', + tearoff=0) mbar.add_cascade(label='IDLE', menu=menu) self.fill_menus() diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -1,8 +1,5 @@ [See the end of this file for ** TIPS ** on using IDLE !!] -Click on the dotted line at the top of a menu to "tear it off": a -separate window containing the menu is created. - File Menu: New File -- Create a new editing window diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -147,7 +147,7 @@ root.configure(menu=menubar) menudict = {} - menudict['windows'] = menu = Menu(menubar, name='windows') + menudict['windows'] = menu = Menu(menubar, name='windows', tearoff=0) menubar.add_cascade(label='Window', menu=menu, underline=0) def postwindowsmenu(menu=menu): @@ -187,7 +187,8 @@ if isCarbonTk(): # for Carbon AquaTk, replace the default Tk apple menu - menudict['application'] = menu = Menu(menubar, name='apple') + menudict['application'] = menu = Menu(menubar, name='apple', + tearoff=0) menubar.add_cascade(label='IDLE', menu=menu) Bindings.menudefs.insert(0, ('application', [ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 23:03:40 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 30 Jul 2015 21:03:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323779=3A_imaplib_raises_TypeError_if_authentica?= =?utf-8?q?tor_tries_to_abort=2E?= Message-ID: <20150730210339.1381.68909@psf.io> https://hg.python.org/cpython/rev/0879f2c53289 changeset: 97157:0879f2c53289 parent: 97154:f05fc1a16e53 parent: 97156:b6f04b9d8c12 user: Robert Collins date: Fri Jul 31 09:02:09 2015 +1200 summary: Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. files: Lib/imaplib.py | 2 +- Lib/test/test_imaplib.py | 20 ++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 25 insertions(+), 1 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1353,7 +1353,7 @@ def process(self, data): ret = self.mech(self.decode(data)) if ret is None: - return '*' # Abort conversation + return b'*' # Abort conversation return self.encode(ret) def encode(self, inp): diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -419,6 +419,26 @@ ret, data = client.login_cram_md5("tim", b"tanstaaftanstaaf") self.assertEqual(ret, "OK") + + @reap_threads + def test_aborted_authentication(self): + + class MyServer(SimpleIMAPHandler): + + def cmd_AUTHENTICATE(self, tag, args): + self._send_textline('+') + self.response = yield + + if self.response == b'*\r\n': + self._send_tagged(tag, 'NO', '[AUTHENTICATIONFAILED] aborted') + else: + self._send_tagged(tag, 'OK', 'MYAUTH successful') + + with self.reaped_pair(MyServer) as (server, client): + with self.assertRaises(imaplib.IMAP4.error): + code, data = client.authenticate('MYAUTH', lambda x: None) + + def test_linetoolong(self): class TooLongHandler(SimpleIMAPHandler): def handle(self): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -603,6 +603,7 @@ Shane Holloway Rune Holm Thomas Holmes +Craig Holmquist Philip Homburg Naofumi Honda Jeffrey Honig diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23779: imaplib raises TypeError if authenticator tries to abort. + Patch from Craig Holmquist. + - Issue #24360: Improve __repr__ of argparse.Namespace() for invalid identifiers. Patch by Matthias Bussonnier. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 23:03:45 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 30 Jul 2015 21:03:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323779=3A_imaplib_raises_TypeError_if_authenticator_tr?= =?utf-8?q?ies_to_abort=2E?= Message-ID: <20150730210339.94790.2758@psf.io> https://hg.python.org/cpython/rev/b6f04b9d8c12 changeset: 97156:b6f04b9d8c12 branch: 3.5 parent: 97153:3dd296430cc7 parent: 97155:fe55a36a335b user: Robert Collins date: Fri Jul 31 09:01:38 2015 +1200 summary: Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. files: Lib/imaplib.py | 2 +- Lib/test/test_imaplib.py | 20 ++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 25 insertions(+), 1 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1353,7 +1353,7 @@ def process(self, data): ret = self.mech(self.decode(data)) if ret is None: - return '*' # Abort conversation + return b'*' # Abort conversation return self.encode(ret) def encode(self, inp): diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -419,6 +419,26 @@ ret, data = client.login_cram_md5("tim", b"tanstaaftanstaaf") self.assertEqual(ret, "OK") + + @reap_threads + def test_aborted_authentication(self): + + class MyServer(SimpleIMAPHandler): + + def cmd_AUTHENTICATE(self, tag, args): + self._send_textline('+') + self.response = yield + + if self.response == b'*\r\n': + self._send_tagged(tag, 'NO', '[AUTHENTICATIONFAILED] aborted') + else: + self._send_tagged(tag, 'OK', 'MYAUTH successful') + + with self.reaped_pair(MyServer) as (server, client): + with self.assertRaises(imaplib.IMAP4.error): + code, data = client.authenticate('MYAUTH', lambda x: None) + + def test_linetoolong(self): class TooLongHandler(SimpleIMAPHandler): def handle(self): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -603,6 +603,7 @@ Shane Holloway Rune Holm Thomas Holmes +Craig Holmquist Philip Homburg Naofumi Honda Jeffrey Honig diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23779: imaplib raises TypeError if authenticator tries to abort. + Patch from Craig Holmquist. + - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Jul 30 23:03:46 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 30 Jul 2015 21:03:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzc5?= =?utf-8?q?=3A_imaplib_raises_TypeError_if_authenticator_tries_to_abort=2E?= Message-ID: <20150730210339.94778.41265@psf.io> https://hg.python.org/cpython/rev/fe55a36a335b changeset: 97155:fe55a36a335b branch: 3.4 parent: 97152:6eb4441ed14b user: Robert Collins date: Fri Jul 31 08:59:02 2015 +1200 summary: Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. files: Lib/imaplib.py | 2 +- Lib/test/test_imaplib.py | 19 +++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 24 insertions(+), 1 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1306,7 +1306,7 @@ def process(self, data): ret = self.mech(self.decode(data)) if ret is None: - return '*' # Abort conversation + return b'*' # Abort conversation return self.encode(ret) def encode(self, inp): diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -325,6 +325,25 @@ self.assertEqual(ret, "OK") + + @reap_threads + def test_aborted_authentication(self): + + class MyServer(SimpleIMAPHandler): + + def cmd_AUTHENTICATE(self, tag, args): + self._send_textline('+') + self.response = yield + + if self.response == b'*\r\n': + self._send_tagged(tag, 'NO', '[AUTHENTICATIONFAILED] aborted') + else: + self._send_tagged(tag, 'OK', 'MYAUTH successful') + + with self.reaped_pair(MyServer) as (server, client): + with self.assertRaises(imaplib.IMAP4.error): + code, data = client.authenticate('MYAUTH', lambda x: None) + def test_linetoolong(self): class TooLongHandler(SimpleIMAPHandler): def handle(self): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -592,6 +592,7 @@ Shane Holloway Rune Holm Thomas Holmes +Craig Holmquist Philip Homburg Naofumi Honda Jeffrey Honig diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #23779: imaplib raises TypeError if authenticator tries to abort. + Patch from Craig Holmquist. + - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 03:11:36 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 31 Jul 2015 01:11:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313248=3A_Delete_r?= =?utf-8?q?emaining_references_of_inspect=2Egetargspec=28=29=2E?= Message-ID: <20150731011136.110979.11362@psf.io> https://hg.python.org/cpython/rev/ad4c1bfe257f changeset: 97158:ad4c1bfe257f user: Berker Peksag date: Fri Jul 31 04:11:29 2015 +0300 summary: Issue #13248: Delete remaining references of inspect.getargspec(). Noticed by Yaroslav Halchenko. files: Doc/library/inspect.rst | 4 +--- Lib/inspect.py | 7 ++----- Lib/test/test_inspect.py | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -805,8 +805,6 @@ from kwonlyargs to defaults. *annotations* is a dictionary mapping argument names to annotations. - The first four items in the tuple correspond to :func:`getargspec`. - .. versionchanged:: 3.4 This function is now based on :func:`signature`, but still ignores ``__wrapped__`` attributes and includes the already bound first @@ -835,7 +833,7 @@ .. function:: formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations[, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]]) Format a pretty argument spec from the values returned by - :func:`getargspec` or :func:`getfullargspec`. + :func:`getfullargspec`. The first seven arguments are (``args``, ``varargs``, ``varkw``, ``defaults``, ``kwonlyargs``, ``kwonlydefaults``, ``annotations``). diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -16,7 +16,7 @@ getmodule() - determine the module that an object came from getclasstree() - arrange classes so as to represent their hierarchy - getargspec(), getargvalues(), getcallargs() - get info about function arguments + getargvalues(), getcallargs() - get info about function arguments getfullargspec() - same, with support for Python 3 features formatargspec(), formatargvalues() - format an argument spec getouterframes(), getinnerframes() - get info about frames @@ -1018,8 +1018,6 @@ 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. 'annotations' is a dictionary mapping argument names to annotations. - The first four items in the tuple correspond to getargspec(). - This function is deprecated, use inspect.signature() instead. """ @@ -1130,8 +1128,7 @@ formatvalue=lambda value: '=' + repr(value), formatreturns=lambda text: ' -> ' + text, formatannotation=formatannotation): - """Format an argument spec from the values returned by getargspec - or getfullargspec. + """Format an argument spec from the values returned by getfullargspec. The first seven arguments are (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations). The other five arguments diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -38,7 +38,7 @@ # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers, # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource, -# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues, +# getclasstree, getargvalues, formatargspec, formatargvalues, # currentframe, stack, trace, isdatadescriptor # NOTE: There are some additional tests relating to interaction with -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 03:17:50 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 31 Jul 2015 01:17:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQ3NTk6?= =?utf-8?q?_Gracefull_exit_Idle_if_ttk_import_fails=2E?= Message-ID: <20150731011750.17735.76548@psf.io> https://hg.python.org/cpython/rev/13a8782a775e changeset: 97160:13a8782a775e branch: 3.4 parent: 97155:fe55a36a335b user: Terry Jan Reedy date: Thu Jul 30 21:16:16 2015 -0400 summary: Issue 24759: Gracefull exit Idle if ttk import fails. files: Lib/idlelib/PyShell.py | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,6 +23,16 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox +try: + from tkinter import ttk +except: + root = Tk() + root.withdraw() + tkMessageBox.showerror("Idle Cannot Start", + "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" + + "It found tk %s and no ttk." % TkVersion, + parent=root) + sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 03:17:50 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 31 Jul 2015 01:17:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgMjQ3NTk6?= =?utf-8?q?_Gracefull_exit_Idle_if_ttk_import_fails=2E?= Message-ID: <20150731011750.17719.83418@psf.io> https://hg.python.org/cpython/rev/8203fc75b3d2 changeset: 97159:8203fc75b3d2 branch: 2.7 parent: 97151:bead9330438c user: Terry Jan Reedy date: Thu Jul 30 21:16:09 2015 -0400 summary: Issue 24759: Gracefull exit Idle if ttk import fails. files: Lib/idlelib/PyShell.py | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,6 +23,16 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkMessageBox +try: + import ttk +except: + root = Tk() + root.withdraw() + tkMessageBox.showerror("Idle Cannot Start", + "Idle now requires the Tkinter ttk module from tcl/tk 8.5+.\n" + + "It found tk %s and no ttk." % TkVersion, + parent=root) + sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 03:17:55 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 31 Jul 2015 01:17:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150731011755.94782.9746@psf.io> https://hg.python.org/cpython/rev/3006f1e6a276 changeset: 97161:3006f1e6a276 branch: 3.5 parent: 97156:b6f04b9d8c12 parent: 97160:13a8782a775e user: Terry Jan Reedy date: Thu Jul 30 21:16:29 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/PyShell.py | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,6 +23,16 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox +try: + from tkinter import ttk +except: + root = Tk() + root.withdraw() + tkMessageBox.showerror("Idle Cannot Start", + "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" + + "It found tk %s and no ttk." % TkVersion, + parent=root) + sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 03:17:56 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 31 Jul 2015 01:17:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150731011756.5527.85743@psf.io> https://hg.python.org/cpython/rev/3358b5d32910 changeset: 97162:3358b5d32910 parent: 97158:ad4c1bfe257f parent: 97161:3006f1e6a276 user: Terry Jan Reedy date: Thu Jul 30 21:16:44 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/PyShell.py | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,6 +23,16 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox +try: + from tkinter import ttk +except: + root = Tk() + root.withdraw() + tkMessageBox.showerror("Idle Cannot Start", + "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" + + "It found tk %s and no ttk." % TkVersion, + parent=root) + sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Fri Jul 31 10:09:02 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Fri, 31 Jul 2015 08:09:02 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-07-31 Message-ID: Results for project python_default-nightly, build date 2015-07-31 09:01:55 commit: 3358b5d32910d4b005f207f52b764d1cfad61799 revision date: 2015-07-31 04:16:44 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-| pybench sec -0.08231% -1.83493% :-( regex_v8 sec -0.13875% -3.87849% :-| nbody sec -0.87546% -1.82883% :-| json_dump_v2 sec 0.90857% -1.83316% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From solipsis at pitrou.net Fri Jul 31 10:46:38 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 31 Jul 2015 08:46:38 +0000 Subject: [Python-checkins] Daily reference leaks (3358b5d32910): sum=4 Message-ID: <20150731084638.1369.18120@psf.io> results for 3358b5d32910 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogr1f6vs', '--timeout', '7200'] From python-checkins at python.org Fri Jul 31 16:59:06 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 31 Jul 2015 14:59:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324681=3A__Move_th?= =?utf-8?q?e_most_likely_test_first_in_set=5Fadd=5Fentry=28=29=2E?= Message-ID: <20150731145905.29398.62707@psf.io> https://hg.python.org/cpython/rev/9e3be159d023 changeset: 97163:9e3be159d023 user: Raymond Hettinger date: Fri Jul 31 07:58:56 2015 -0700 summary: Issue #24681: Move the most likely test first in set_add_entry(). files: Objects/setobject.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -171,12 +171,15 @@ Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); - if (cmp < 0) /* unlikely */ - goto comparison_error; - if (table != so->table || entry->key != startkey) /* unlikely */ - goto restart; if (cmp > 0) /* likely */ goto found_active; + if (cmp < 0) + goto comparison_error; + /* Continuing the search from the current entry only makes + sense if the table and entry are unchanged; otherwise, + we have to restart from the beginning */ + if (table != so->table || entry->key != startkey) + goto restart; mask = so->mask; /* help avoid a register spill */ } else if (entry->hash == -1 && freeslot == NULL) @@ -200,12 +203,12 @@ Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); + if (cmp > 0) + goto found_active; if (cmp < 0) goto comparison_error; if (table != so->table || entry->key != startkey) goto restart; - if (cmp > 0) - goto found_active; mask = so->mask; } else if (entry->hash == -1 && freeslot == NULL) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 17:51:26 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 15:51:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_ResourceWa?= =?utf-8?q?rning_in_asyncio=2EBaseSubprocessTransport?= Message-ID: <20150731155126.29410.61467@psf.io> https://hg.python.org/cpython/rev/f6b8a0c6b8c9 changeset: 97164:f6b8a0c6b8c9 branch: 3.4 parent: 97160:13a8782a775e user: Victor Stinner date: Fri Jul 31 17:49:43 2015 +0200 summary: Fix ResourceWarning in asyncio.BaseSubprocessTransport Issue #24763: Fix resource warnings when asyncio.BaseSubprocessTransport constructor fails, if subprocess.Popen raises an exception for example. Patch written by Martin Richard, test written by me. files: Lib/asyncio/base_subprocess.py | 9 +++++- Lib/test/test_asyncio/test_subprocess.py | 15 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) 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 @@ -35,8 +35,13 @@ self._pipes[2] = None # Create the child process: set the _proc attribute - self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, - stderr=stderr, bufsize=bufsize, **kwargs) + try: + self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, + stderr=stderr, bufsize=bufsize, **kwargs) + except: + self.close() + raise + self._pid = self._proc.pid self._extra['subprocess'] = self._proc 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 @@ -1,6 +1,7 @@ import signal import sys import unittest +import warnings from unittest import mock import asyncio @@ -413,6 +414,20 @@ # the transport was not notified yet self.assertFalse(killed) + def test_popen_error(self): + # Issue #24763: check that the subprocess transport is closed + # when BaseSubprocessTransport fails + with mock.patch('subprocess.Popen') as popen: + exc = ZeroDivisionError + popen.side_effect = exc + + create = asyncio.create_subprocess_exec(sys.executable, '-c', + 'pass', loop=self.loop) + with warnings.catch_warnings(record=True) as warns: + with self.assertRaises(exc): + self.loop.run_until_complete(create) + self.assertEqual(warns, []) + if sys.platform != 'win32': # Unix -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 17:51:26 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 15:51:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28asyncio=29?= Message-ID: <20150731155126.29398.91831@psf.io> https://hg.python.org/cpython/rev/88c537e6d788 changeset: 97165:88c537e6d788 branch: 3.5 parent: 97161:3006f1e6a276 parent: 97164:f6b8a0c6b8c9 user: Victor Stinner date: Fri Jul 31 17:50:13 2015 +0200 summary: Merge 3.4 (asyncio) files: Lib/asyncio/base_subprocess.py | 9 +++++- Lib/test/test_asyncio/test_subprocess.py | 15 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) 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 @@ -35,8 +35,13 @@ self._pipes[2] = None # Create the child process: set the _proc attribute - self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, - stderr=stderr, bufsize=bufsize, **kwargs) + try: + self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, + stderr=stderr, bufsize=bufsize, **kwargs) + except: + self.close() + raise + self._pid = self._proc.pid self._extra['subprocess'] = self._proc 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 @@ -1,6 +1,7 @@ import signal import sys import unittest +import warnings from unittest import mock import asyncio @@ -413,6 +414,20 @@ # the transport was not notified yet self.assertFalse(killed) + def test_popen_error(self): + # Issue #24763: check that the subprocess transport is closed + # when BaseSubprocessTransport fails + with mock.patch('subprocess.Popen') as popen: + exc = ZeroDivisionError + popen.side_effect = exc + + create = asyncio.create_subprocess_exec(sys.executable, '-c', + 'pass', loop=self.loop) + with warnings.catch_warnings(record=True) as warns: + with self.assertRaises(exc): + self.loop.run_until_complete(create) + self.assertEqual(warns, []) + if sys.platform != 'win32': # Unix -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 17:51:26 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 15:51:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28asyncio=29?= Message-ID: <20150731155126.17729.70280@psf.io> https://hg.python.org/cpython/rev/eb3d61f5d3ae changeset: 97166:eb3d61f5d3ae parent: 97163:9e3be159d023 parent: 97165:88c537e6d788 user: Victor Stinner date: Fri Jul 31 17:50:29 2015 +0200 summary: Merge 3.5 (asyncio) files: Lib/asyncio/base_subprocess.py | 9 +++++- Lib/test/test_asyncio/test_subprocess.py | 15 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) 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 @@ -35,8 +35,13 @@ self._pipes[2] = None # Create the child process: set the _proc attribute - self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, - stderr=stderr, bufsize=bufsize, **kwargs) + try: + self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, + stderr=stderr, bufsize=bufsize, **kwargs) + except: + self.close() + raise + self._pid = self._proc.pid self._extra['subprocess'] = self._proc 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 @@ -1,6 +1,7 @@ import signal import sys import unittest +import warnings from unittest import mock import asyncio @@ -413,6 +414,20 @@ # the transport was not notified yet self.assertFalse(killed) + def test_popen_error(self): + # Issue #24763: check that the subprocess transport is closed + # when BaseSubprocessTransport fails + with mock.patch('subprocess.Popen') as popen: + exc = ZeroDivisionError + popen.side_effect = exc + + create = asyncio.create_subprocess_exec(sys.executable, '-c', + 'pass', loop=self.loop) + with warnings.catch_warnings(record=True) as warns: + with self.assertRaises(exc): + self.loop.run_until_complete(create) + self.assertEqual(warns, []) + if sys.platform != 'win32': # Unix -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 21:03:25 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 31 Jul 2015 19:03:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_minor_typo_in_a_commen?= =?utf-8?q?t?= Message-ID: <20150731190324.29388.76079@psf.io> https://hg.python.org/cpython/rev/c13839a3d4fc changeset: 97167:c13839a3d4fc user: Raymond Hettinger date: Fri Jul 31 12:03:20 2015 -0700 summary: Fix minor typo in a comment files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1047,7 +1047,7 @@ static int valid_index(Py_ssize_t i, Py_ssize_t limit) { - /* The cast to size_t let us use just a single comparison + /* The cast to size_t lets us use just a single comparison to check whether i is in the range: 0 <= i < limit */ return (size_t) i < (size_t) limit; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 22:20:17 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 31 Jul 2015 20:20:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2322932=3A_Fix_timezones_in_email=2Eutils=2Eformatdate?= =?utf-8?q?=2E?= Message-ID: <20150731202017.29390.15248@psf.io> https://hg.python.org/cpython/rev/94b43b36e464 changeset: 97169:94b43b36e464 branch: 3.5 parent: 97165:88c537e6d788 parent: 97168:fa8b76dfd138 user: Robert Collins date: Sat Aug 01 08:19:06 2015 +1200 summary: Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. files: Lib/email/utils.py | 30 ++++-------------- Lib/test/test_email/test_utils.py | 20 ++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 + 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -155,30 +155,14 @@ # 2822 requires that day and month names be the English abbreviations. if timeval is None: timeval = time.time() + if localtime or usegmt: + dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc) + else: + dt = datetime.datetime.utcfromtimestamp(timeval) if localtime: - now = time.localtime(timeval) - # Calculate timezone offset, based on whether the local zone has - # daylight savings time, and whether DST is in effect. - if time.daylight and now[-1]: - offset = time.altzone - else: - offset = time.timezone - hours, minutes = divmod(abs(offset), 3600) - # Remember offset is in seconds west of UTC, but the timezone is in - # minutes east of UTC, so the signs differ. - if offset > 0: - sign = '-' - else: - sign = '+' - zone = '%s%02d%02d' % (sign, hours, minutes // 60) - else: - now = time.gmtime(timeval) - # Timezone offset is always -0000 - if usegmt: - zone = 'GMT' - else: - zone = '-0000' - return _format_timetuple_and_zone(now, zone) + dt = dt.astimezone() + usegmt = False + return format_datetime(dt, usegmt) def format_datetime(dt, usegmt=False): """Turn a datetime into a date string as specified in RFC 2822. diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -136,5 +136,25 @@ t1 = utils.localtime(t0) self.assertEqual(t1.tzname(), 'EET') +class FormatDateTests(unittest.TestCase): + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate(self): + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=False, usegmt=False) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 -0000') + string = utils.formatdate(timeval, localtime=False, usegmt=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 GMT') + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate_with_localtime(self): + timeval = time.mktime((2011, 1, 1, 18, 0, 0, 6, 1, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Sat, 01 Jan 2011 18:00:00 +0200') + # Minsk moved from +0200 (with DST) to +0300 (without DST) in 2011 + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 18:00:00 +0300') + if __name__ == '__main__': unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1282,6 +1282,7 @@ Pete Sevander Denis Severson Ian Seyer +Dmitry Shachnev Daniel Shahaf Ha Shao Mark Shannon diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #22932: Fix timezones in email.utils.formatdate. + Patch from Dmitry Shachnev. + - Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 22:20:18 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 31 Jul 2015 20:20:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyOTMy?= =?utf-8?q?=3A_Fix_timezones_in_email=2Eutils=2Eformatdate=2E?= Message-ID: <20150731202017.29398.35667@psf.io> https://hg.python.org/cpython/rev/fa8b76dfd138 changeset: 97168:fa8b76dfd138 branch: 3.4 parent: 97164:f6b8a0c6b8c9 user: Robert Collins date: Sat Aug 01 08:18:22 2015 +1200 summary: Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. files: Lib/email/utils.py | 30 ++++-------------- Lib/test/test_email/test_utils.py | 20 ++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 + 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -155,30 +155,14 @@ # 2822 requires that day and month names be the English abbreviations. if timeval is None: timeval = time.time() + if localtime or usegmt: + dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc) + else: + dt = datetime.datetime.utcfromtimestamp(timeval) if localtime: - now = time.localtime(timeval) - # Calculate timezone offset, based on whether the local zone has - # daylight savings time, and whether DST is in effect. - if time.daylight and now[-1]: - offset = time.altzone - else: - offset = time.timezone - hours, minutes = divmod(abs(offset), 3600) - # Remember offset is in seconds west of UTC, but the timezone is in - # minutes east of UTC, so the signs differ. - if offset > 0: - sign = '-' - else: - sign = '+' - zone = '%s%02d%02d' % (sign, hours, minutes // 60) - else: - now = time.gmtime(timeval) - # Timezone offset is always -0000 - if usegmt: - zone = 'GMT' - else: - zone = '-0000' - return _format_timetuple_and_zone(now, zone) + dt = dt.astimezone() + usegmt = False + return format_datetime(dt, usegmt) def format_datetime(dt, usegmt=False): """Turn a datetime into a date string as specified in RFC 2822. diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -136,5 +136,25 @@ t1 = utils.localtime(t0) self.assertEqual(t1.tzname(), 'EET') +class FormatDateTests(unittest.TestCase): + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate(self): + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=False, usegmt=False) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 -0000') + string = utils.formatdate(timeval, localtime=False, usegmt=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 GMT') + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate_with_localtime(self): + timeval = time.mktime((2011, 1, 1, 18, 0, 0, 6, 1, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Sat, 01 Jan 2011 18:00:00 +0200') + # Minsk moved from +0200 (with DST) to +0300 (without DST) in 2011 + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 18:00:00 +0300') + if __name__ == '__main__': unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1247,6 +1247,7 @@ Pete Sevander Denis Severson Ian Seyer +Dmitry Shachnev Daniel Shahaf Ha Shao Mark Shannon diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,9 @@ Library ------- +- Issue #22932: Fix timezones in email.utils.formatdate. + Patch from Dmitry Shachnev. + - Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 22:20:19 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 31 Jul 2015 20:20:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322932=3A_Fix_timezones_in_email=2Eutils=2Eforma?= =?utf-8?q?tdate=2E?= Message-ID: <20150731202017.94786.20081@psf.io> https://hg.python.org/cpython/rev/479787100b91 changeset: 97170:479787100b91 parent: 97167:c13839a3d4fc parent: 97169:94b43b36e464 user: Robert Collins date: Sat Aug 01 08:20:04 2015 +1200 summary: Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. files: Lib/email/utils.py | 30 ++++-------------- Lib/test/test_email/test_utils.py | 20 ++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 + 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -155,30 +155,14 @@ # 2822 requires that day and month names be the English abbreviations. if timeval is None: timeval = time.time() + if localtime or usegmt: + dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc) + else: + dt = datetime.datetime.utcfromtimestamp(timeval) if localtime: - now = time.localtime(timeval) - # Calculate timezone offset, based on whether the local zone has - # daylight savings time, and whether DST is in effect. - if time.daylight and now[-1]: - offset = time.altzone - else: - offset = time.timezone - hours, minutes = divmod(abs(offset), 3600) - # Remember offset is in seconds west of UTC, but the timezone is in - # minutes east of UTC, so the signs differ. - if offset > 0: - sign = '-' - else: - sign = '+' - zone = '%s%02d%02d' % (sign, hours, minutes // 60) - else: - now = time.gmtime(timeval) - # Timezone offset is always -0000 - if usegmt: - zone = 'GMT' - else: - zone = '-0000' - return _format_timetuple_and_zone(now, zone) + dt = dt.astimezone() + usegmt = False + return format_datetime(dt, usegmt) def format_datetime(dt, usegmt=False): """Turn a datetime into a date string as specified in RFC 2822. diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -136,5 +136,25 @@ t1 = utils.localtime(t0) self.assertEqual(t1.tzname(), 'EET') +class FormatDateTests(unittest.TestCase): + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate(self): + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=False, usegmt=False) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 -0000') + string = utils.formatdate(timeval, localtime=False, usegmt=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 GMT') + + @test.support.run_with_tz('Europe/Minsk') + def test_formatdate_with_localtime(self): + timeval = time.mktime((2011, 1, 1, 18, 0, 0, 6, 1, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Sat, 01 Jan 2011 18:00:00 +0200') + # Minsk moved from +0200 (with DST) to +0300 (without DST) in 2011 + timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0)) + string = utils.formatdate(timeval, localtime=True) + self.assertEqual(string, 'Thu, 01 Dec 2011 18:00:00 +0300') + if __name__ == '__main__': unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1282,6 +1282,7 @@ Pete Sevander Denis Severson Ian Seyer +Dmitry Shachnev Daniel Shahaf Ha Shao Mark Shannon diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #22932: Fix timezones in email.utils.formatdate. + Patch from Dmitry Shachnev. + - Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 23:37:38 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 21:37:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzYz?= =?utf-8?q?=3A_Fix_asyncio_test_on_Windows?= Message-ID: <20150731213738.29394.31838@psf.io> https://hg.python.org/cpython/rev/6703ac68bf49 changeset: 97171:6703ac68bf49 branch: 3.4 parent: 97168:fa8b76dfd138 user: Victor Stinner date: Fri Jul 31 23:36:00 2015 +0200 summary: Issue #24763: Fix asyncio test on Windows files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) 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 @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 23:37:39 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 21:37:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28asyncio_test=29?= Message-ID: <20150731213738.23384.54939@psf.io> https://hg.python.org/cpython/rev/743b3058295d changeset: 97172:743b3058295d branch: 3.5 parent: 97169:94b43b36e464 parent: 97171:6703ac68bf49 user: Victor Stinner date: Fri Jul 31 23:36:15 2015 +0200 summary: Merge 3.4 (asyncio test) files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) 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 @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Jul 31 23:37:39 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 31 Jul 2015 21:37:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28asyncio_tests=29?= Message-ID: <20150731213738.53985.49142@psf.io> https://hg.python.org/cpython/rev/74fc1af57c72 changeset: 97173:74fc1af57c72 parent: 97170:479787100b91 parent: 97172:743b3058295d user: Victor Stinner date: Fri Jul 31 23:36:28 2015 +0200 summary: Merge 3.5 (asyncio tests) files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) 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 @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython