From solipsis at pitrou.net Fri Mar 1 06:00:48 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 01 Mar 2013 06:00:48 +0100 Subject: [Python-checkins] Daily reference leaks (637c2cd716d1): sum=6 Message-ID: results for 637c2cd716d1 on branch "default" -------------------------------------------- test_site leaked [0, 2, 0] references, sum=2 test_site leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogQ1wQc3', '-x'] From python-checkins at python.org Fri Mar 1 09:56:54 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 09:56:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MDc5OiB0ZXN0?= =?utf-8?q?=5Fctypes_now_works_with_unittest_test_discovery=2E__Patch_by_Z?= =?utf-8?q?achary?= Message-ID: <3ZHPdL66gWzRhN@mail.python.org> http://hg.python.org/cpython/rev/42d4a29509c4 changeset: 82431:42d4a29509c4 branch: 3.3 parent: 82428:66d0f6ef2a7f user: Ezio Melotti date: Fri Mar 01 10:55:17 2013 +0200 summary: #17079: test_ctypes now works with unittest test discovery. Patch by Zachary Ware. files: Lib/test/test_ctypes.py | 8 ++++---- Misc/NEWS | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py --- a/Lib/test/test_ctypes.py +++ b/Lib/test/test_ctypes.py @@ -1,16 +1,16 @@ import unittest -from test.support import run_unittest, import_module +from test.support import import_module # Skip tests if _ctypes module was not built. import_module('_ctypes') import ctypes.test -def test_main(): +def load_tests(*args): skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) suites = [unittest.makeSuite(t) for t in testcases] - run_unittest(unittest.TestSuite(suites)) + return unittest.TestSuite(suites) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -644,6 +644,9 @@ - Issue #15539: Added regression tests for Tools/scripts/pindent.py. +- Issue #17079: test_ctypes now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17304: test_hash now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 09:56:56 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 09:56:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MDc5OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZHPdN21l7zSLy@mail.python.org> http://hg.python.org/cpython/rev/e222f24837dd changeset: 82432:e222f24837dd parent: 82429:637c2cd716d1 parent: 82431:42d4a29509c4 user: Ezio Melotti date: Fri Mar 01 10:56:35 2013 +0200 summary: #17079: merge with 3.3. files: Lib/test/test_ctypes.py | 8 ++++---- Misc/NEWS | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py --- a/Lib/test/test_ctypes.py +++ b/Lib/test/test_ctypes.py @@ -1,16 +1,16 @@ import unittest -from test.support import run_unittest, import_module +from test.support import import_module # Skip tests if _ctypes module was not built. import_module('_ctypes') import ctypes.test -def test_main(): +def load_tests(*args): skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) suites = [unittest.makeSuite(t) for t in testcases] - run_unittest(unittest.TestSuite(suites)) + return unittest.TestSuite(suites) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -896,6 +896,9 @@ - Issue #16836: Enable IPv6 support even if IPv6 is disabled on the build host. +- Issue #17079: test_ctypes now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17304: test_hash now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 10:25:00 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 10:25:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MDgyOiB0ZXN0?= =?utf-8?q?=5Fdbm*_now_work_with_unittest_test_discovery=2E__Patch_by_Zach?= =?utf-8?q?ary_Ware=2E?= Message-ID: <3ZHQFm5FpbzSbQ@mail.python.org> http://hg.python.org/cpython/rev/b62317fe1a22 changeset: 82433:b62317fe1a22 branch: 3.3 parent: 82431:42d4a29509c4 user: Ezio Melotti date: Fri Mar 01 11:23:28 2013 +0200 summary: #17082: test_dbm* now work with unittest test discovery. Patch by Zachary Ware. files: Lib/test/test_dbm.py | 20 ++++++++++---------- Lib/test/test_dbm_dumb.py | 10 +--------- Lib/test/test_dbm_gnu.py | 7 ++----- Lib/test/test_dbm_ndbm.py | 5 +---- Misc/NEWS | 3 +++ 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py --- a/Lib/test/test_dbm.py +++ b/Lib/test/test_dbm.py @@ -34,7 +34,7 @@ test.support.unlink(f) -class AnyDBMTestCase(unittest.TestCase): +class AnyDBMTestCase: _dict = {'0': b'', 'a': b'Python:', 'b': b'Programming', @@ -119,10 +119,6 @@ class WhichDBTestCase(unittest.TestCase): - # Actual test methods are added to namespace after class definition. - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_whichdb(self): for module in dbm_iterator(): # Check whether whichdb correctly guesses module name @@ -169,12 +165,16 @@ self.d.close() -def test_main(): - classes = [WhichDBTestCase] +def load_tests(loader, tests, pattern): + classes = [] for mod in dbm_iterator(): - classes.append(type("TestCase-" + mod.__name__, (AnyDBMTestCase,), + classes.append(type("TestCase-" + mod.__name__, + (AnyDBMTestCase, unittest.TestCase), {'module': mod})) - test.support.run_unittest(*classes) + suites = [unittest.makeSuite(c) for c in classes] + + tests.addTests(suites) + return tests if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -29,9 +29,6 @@ '\u00fc'.encode('utf-8') : b'!', } - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_dumbdbm_creation(self): f = dumbdbm.open(_fname, 'c') self.assertEqual(list(f.keys()), []) @@ -195,11 +192,6 @@ def setUp(self): _delete_files() -def test_main(): - try: - support.run_unittest(DumbDBMTestCase) - finally: - _delete_files() if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -2,7 +2,7 @@ gdbm = support.import_module("dbm.gnu") #skip if not supported import unittest import os -from test.support import verbose, TESTFN, run_unittest, unlink +from test.support import verbose, TESTFN, unlink filename = TESTFN @@ -81,8 +81,5 @@ self.assertTrue(size1 > size2 >= size0) -def test_main(): - run_unittest(TestGdbm) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py --- a/Lib/test/test_dbm_ndbm.py +++ b/Lib/test/test_dbm_ndbm.py @@ -36,8 +36,5 @@ except error: self.fail() -def test_main(): - support.run_unittest(DbmTestCase) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -644,6 +644,9 @@ - Issue #15539: Added regression tests for Tools/scripts/pindent.py. +- Issue #17082: test_dbm* now work with unittest test discovery. + Patch by Zachary Ware. + - Issue #17079: test_ctypes now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 10:25:02 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 10:25:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MDgyOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZHQFp0pwKzSkB@mail.python.org> http://hg.python.org/cpython/rev/e35c053cc4ec changeset: 82434:e35c053cc4ec parent: 82432:e222f24837dd parent: 82433:b62317fe1a22 user: Ezio Melotti date: Fri Mar 01 11:24:42 2013 +0200 summary: #17082: merge with 3.3. files: Lib/test/test_dbm.py | 20 ++++++++++---------- Lib/test/test_dbm_dumb.py | 10 +--------- Lib/test/test_dbm_gnu.py | 7 ++----- Lib/test/test_dbm_ndbm.py | 5 +---- Misc/NEWS | 3 +++ 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py --- a/Lib/test/test_dbm.py +++ b/Lib/test/test_dbm.py @@ -34,7 +34,7 @@ test.support.unlink(f) -class AnyDBMTestCase(unittest.TestCase): +class AnyDBMTestCase: _dict = {'0': b'', 'a': b'Python:', 'b': b'Programming', @@ -119,10 +119,6 @@ class WhichDBTestCase(unittest.TestCase): - # Actual test methods are added to namespace after class definition. - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_whichdb(self): for module in dbm_iterator(): # Check whether whichdb correctly guesses module name @@ -169,12 +165,16 @@ self.d.close() -def test_main(): - classes = [WhichDBTestCase] +def load_tests(loader, tests, pattern): + classes = [] for mod in dbm_iterator(): - classes.append(type("TestCase-" + mod.__name__, (AnyDBMTestCase,), + classes.append(type("TestCase-" + mod.__name__, + (AnyDBMTestCase, unittest.TestCase), {'module': mod})) - test.support.run_unittest(*classes) + suites = [unittest.makeSuite(c) for c in classes] + + tests.addTests(suites) + return tests if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -29,9 +29,6 @@ '\u00fc'.encode('utf-8') : b'!', } - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_dumbdbm_creation(self): f = dumbdbm.open(_fname, 'c') self.assertEqual(list(f.keys()), []) @@ -195,11 +192,6 @@ def setUp(self): _delete_files() -def test_main(): - try: - support.run_unittest(DumbDBMTestCase) - finally: - _delete_files() if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -2,7 +2,7 @@ gdbm = support.import_module("dbm.gnu") #skip if not supported import unittest import os -from test.support import verbose, TESTFN, run_unittest, unlink +from test.support import verbose, TESTFN, unlink filename = TESTFN @@ -81,8 +81,5 @@ self.assertTrue(size1 > size2 >= size0) -def test_main(): - run_unittest(TestGdbm) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py --- a/Lib/test/test_dbm_ndbm.py +++ b/Lib/test/test_dbm_ndbm.py @@ -36,8 +36,5 @@ except error: self.fail() -def test_main(): - support.run_unittest(DbmTestCase) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -896,6 +896,9 @@ - Issue #16836: Enable IPv6 support even if IPv6 is disabled on the build host. +- Issue #17082: test_dbm* now work with unittest test discovery. + Patch by Zachary Ware. + - Issue #17079: test_ctypes now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 12:31:20 2013 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 1 Mar 2013 12:31:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Regex_should_b?= =?utf-8?q?e_a_raw_string?= Message-ID: <3ZHT3X1xLRzRXb@mail.python.org> http://hg.python.org/cpython/rev/43ac02b7e322 changeset: 82435:43ac02b7e322 branch: 3.3 parent: 82433:b62317fe1a22 user: Raymond Hettinger date: Fri Mar 01 03:30:20 2013 -0800 summary: Regex should be a raw string files: Doc/library/collections.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -210,7 +210,7 @@ >>> # Find the ten most common words in Hamlet >>> import re - >>> words = re.findall('\w+', open('hamlet.txt').read().lower()) + >>> words = re.findall(r'\w+', open('hamlet.txt').read().lower()) >>> Counter(words).most_common(10) [('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631), ('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 12:31:21 2013 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 1 Mar 2013 12:31:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZHT3Y4ZvHzRXb@mail.python.org> http://hg.python.org/cpython/rev/a066466fddd3 changeset: 82436:a066466fddd3 parent: 82434:e35c053cc4ec parent: 82435:43ac02b7e322 user: Raymond Hettinger date: Fri Mar 01 03:31:05 2013 -0800 summary: Merge files: Doc/library/collections.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -215,7 +215,7 @@ >>> # Find the ten most common words in Hamlet >>> import re - >>> words = re.findall('\w+', open('hamlet.txt').read().lower()) + >>> words = re.findall(r'\w+', open('hamlet.txt').read().lower()) >>> Counter(words).most_common(10) [('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631), ('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 13:02:02 2013 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 1 Mar 2013 13:02:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogRG9uJ3QgZGVhZGxv?= =?utf-8?q?ck_on_a_reentrant_call=2E?= Message-ID: <3ZHTky0hvLzSyt@mail.python.org> http://hg.python.org/cpython/rev/1920422626a5 changeset: 82437:1920422626a5 branch: 3.3 parent: 82435:43ac02b7e322 user: Raymond Hettinger date: Fri Mar 01 03:47:57 2013 -0800 summary: Don't deadlock on a reentrant call. files: Lib/functools.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -14,9 +14,9 @@ from _functools import partial, reduce from collections import namedtuple try: - from _thread import allocate_lock as Lock + from _thread import RLock except: - from _dummy_thread import allocate_lock as Lock + from dummy_threading import RLock ################################################################################ @@ -207,7 +207,7 @@ hits = misses = currsize = 0 full = False cache_get = cache.get # bound method to lookup a key or return None - lock = Lock() # because linkedlist updates aren't threadsafe + lock = RLock() # because linkedlist updates aren't threadsafe root = [] # root of the circular doubly linked list root[:] = [root, root, None, None] # initialize by pointing to self -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 13:02:03 2013 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 1 Mar 2013 13:02:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZHTkz3HSgzSq3@mail.python.org> http://hg.python.org/cpython/rev/dd341e1e30a7 changeset: 82438:dd341e1e30a7 parent: 82436:a066466fddd3 parent: 82437:1920422626a5 user: Raymond Hettinger date: Fri Mar 01 03:48:30 2013 -0800 summary: Merge files: Lib/functools.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -17,9 +17,9 @@ pass from collections import namedtuple try: - from _thread import allocate_lock as Lock + from _thread import RLock except: - from _dummy_thread import allocate_lock as Lock + from dummy_threading import RLock ################################################################################ @@ -232,7 +232,7 @@ hits = misses = 0 full = False cache_get = cache.get # bound method to lookup a key or return None - lock = Lock() # because linkedlist updates aren't threadsafe + lock = RLock() # because linkedlist updates aren't threadsafe root = [] # root of the circular doubly linked list root[:] = [root, root, None, None] # initialize by pointing to self -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 13:48:09 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 13:48:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2316935=3A_unittest_now_c?= =?utf-8?q?ounts_the_module_as_skipped_if_it_raises_SkipTest=2C?= Message-ID: <3ZHVm92kBfzSwP@mail.python.org> http://hg.python.org/cpython/rev/61ce6deb4577 changeset: 82439:61ce6deb4577 user: Ezio Melotti date: Fri Mar 01 14:47:50 2013 +0200 summary: #16935: unittest now counts the module as skipped if it raises SkipTest, instead of counting it as an error. Patch by Zachary Ware. files: Doc/library/unittest.rst | 8 ++++- Lib/unittest/loader.py | 10 ++++++ Lib/unittest/test/test_discovery.py | 27 ++++++++++++++-- Misc/NEWS | 3 + 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1493,7 +1493,9 @@ directory must be specified separately. If importing a module fails, for example due to a syntax error, then this - will be recorded as a single error and discovery will continue. + will be recorded as a single error and discovery will continue. If the + import failure is due to ``SkipTest`` being raised, it will be recorded + as a skip instead of an error. If a test package name (directory with :file:`__init__.py`) matches the pattern then the package will be checked for a ``load_tests`` @@ -1512,6 +1514,10 @@ .. versionadded:: 3.2 + .. versionchanged:: 3.4 + Modules that raise ``SkipTest`` on import are recorded as skips, not + errors. + The following attributes of a :class:`TestLoader` can be configured either by subclassing or assignment on an instance: diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -34,6 +34,14 @@ TestClass = type(classname, (case.TestCase,), attrs) return suiteClass((TestClass(methodname),)) +def _make_skipped_test(methodname, exception, suiteClass): + @case.skip(str(exception)) + def testSkipped(self): + pass + attrs = {methodname: testSkipped} + TestClass = type("ModuleSkipped", (case.TestCase,), attrs) + return suiteClass((TestClass(methodname),)) + def _jython_aware_splitext(path): if path.lower().endswith('$py.class'): return path[:-9] @@ -259,6 +267,8 @@ name = self._get_name_from_path(full_path) try: module = self._get_module_from_name(name) + except case.SkipTest as e: + yield _make_skipped_test(name, e, self.suiteClass) except: yield _make_failed_import_test(name, self.suiteClass) else: diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -184,11 +184,9 @@ self.assertEqual(_find_tests_args, [(start_dir, 'pattern')]) self.assertIn(top_level_dir, sys.path) - def test_discover_with_modules_that_fail_to_import(self): - loader = unittest.TestLoader() - + def setup_import_issue_tests(self, fakefile): listdir = os.listdir - os.listdir = lambda _: ['test_this_does_not_exist.py'] + os.listdir = lambda _: [fakefile] isfile = os.path.isfile os.path.isfile = lambda _: True orig_sys_path = sys.path[:] @@ -198,6 +196,11 @@ sys.path[:] = orig_sys_path self.addCleanup(restore) + def test_discover_with_modules_that_fail_to_import(self): + loader = unittest.TestLoader() + + self.setup_import_issue_tests('test_this_does_not_exist.py') + suite = loader.discover('.') self.assertIn(os.getcwd(), sys.path) self.assertEqual(suite.countTestCases(), 1) @@ -206,6 +209,22 @@ with self.assertRaises(ImportError): test.test_this_does_not_exist() + def test_discover_with_module_that_raises_SkipTest_on_import(self): + loader = unittest.TestLoader() + + def _get_module_from_name(name): + raise unittest.SkipTest('skipperoo') + loader._get_module_from_name = _get_module_from_name + + self.setup_import_issue_tests('test_skip_dummy.py') + + suite = loader.discover('.') + self.assertEqual(suite.countTestCases(), 1) + + result = unittest.TestResult() + suite.run(result) + self.assertEqual(len(result.skipped), 1) + def test_command_line_handling_parseArgs(self): program = TestableTestProgram() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -270,6 +270,9 @@ Library ------- +- Issue #16935: unittest now counts the module as skipped if it raises SkipTest, + instead of counting it as an error. Patch by Zachary Ware. + - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. - Issue #17197: profile/cProfile modules refactored so that code of run() and -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 13:54:45 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 13:54:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2316935=3A_update_test=5F?= =?utf-8?q?crypt_now_that_unittest_discover_understands_SkipTest=2E?= Message-ID: <3ZHVvn5VmQzRZL@mail.python.org> http://hg.python.org/cpython/rev/22b6b59c70e6 changeset: 82440:22b6b59c70e6 user: Ezio Melotti date: Fri Mar 01 14:53:45 2013 +0200 summary: #16935: update test_crypt now that unittest discover understands SkipTest. files: Lib/test/test_crypt.py | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py --- a/Lib/test/test_crypt.py +++ b/Lib/test/test_crypt.py @@ -1,11 +1,7 @@ from test import support import unittest -def setUpModule(): - # this import will raise unittest.SkipTest if _crypt doesn't exist, - # so it has to be done in setUpModule for test discovery to work - global crypt - crypt = support.import_module('crypt') +crypt = support.import_module('crypt') class CryptTestCase(unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From ezio.melotti at gmail.com Fri Mar 1 14:22:57 2013 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Fri, 1 Mar 2013 15:22:57 +0200 Subject: [Python-checkins] cpython (3.3): Don't deadlock on a reentrant call. In-Reply-To: <3ZHTky0hvLzSyt@mail.python.org> References: <3ZHTky0hvLzSyt@mail.python.org> Message-ID: Hi, On Fri, Mar 1, 2013 at 2:02 PM, raymond.hettinger wrote: > http://hg.python.org/cpython/rev/1920422626a5 > changeset: 82437:1920422626a5 > branch: 3.3 > parent: 82435:43ac02b7e322 > user: Raymond Hettinger > date: Fri Mar 01 03:47:57 2013 -0800 > summary: > Don't deadlock on a reentrant call. this seems to have broken builds without threads. After this commit I get a compile error: $ ./configure --without-threads --with-pydebug && make -j2 [...] ./python -E -S -m sysconfig --generate-posix-vars Could not find platform dependent libraries Consider setting $PYTHONHOME to [:] Could not import runpy module Exception ignored in: 'garbage collection' Traceback (most recent call last): File "/home/wolf/dev/py/py3k/Lib/runpy.py", line 16, in import imp File "/home/wolf/dev/py/py3k/Lib/imp.py", line 23, in import tokenize File "/home/wolf/dev/py/py3k/Lib/tokenize.py", line 28, in import re File "/home/wolf/dev/py/py3k/Lib/re.py", line 124, in import functools File "/home/wolf/dev/py/py3k/Lib/functools.py", line 22, in from dummy_threading import RLock File "/home/wolf/dev/py/py3k/Lib/dummy_threading.py", line 45, in import threading File "/home/wolf/dev/py/py3k/Lib/threading.py", line 6, in from time import sleep as _sleep ImportError: No module named 'time' Fatal Python error: unexpected exception during garbage collection Current thread 0x00000000: make: *** [pybuilddir.txt] Aborted (core dumped) See also: http://buildbot.python.org/all/builders/AMD64%20Fedora%20without%20threads%203.x/builds/4006 http://buildbot.python.org/all/builders/AMD64%20Fedora%20without%20threads%203.3/builds/516 (Also having tests for this change would be nice.) Best Regards, Ezio Melotti From solipsis at pitrou.net Fri Mar 1 16:21:37 2013 From: solipsis at pitrou.net (Antoine Pitrou) Date: Fri, 1 Mar 2013 16:21:37 +0100 Subject: [Python-checkins] cpython (3.3): Don't deadlock on a reentrant call. References: <3ZHTky0hvLzSyt@mail.python.org> Message-ID: <20130301162137.22f80a3e@pitrou.net> Le Fri, 1 Mar 2013 15:22:57 +0200, Ezio Melotti a ?crit : > Hi, > > On Fri, Mar 1, 2013 at 2:02 PM, raymond.hettinger > wrote: > > http://hg.python.org/cpython/rev/1920422626a5 > > changeset: 82437:1920422626a5 > > branch: 3.3 > > parent: 82435:43ac02b7e322 > > user: Raymond Hettinger > > date: Fri Mar 01 03:47:57 2013 -0800 > > summary: > > Don't deadlock on a reentrant call. > > [...] > > (Also having tests for this change would be nice.) +1, we definitely need a test for this one. Regards Antoine. From python-checkins at python.org Fri Mar 1 20:01:11 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:01:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3MzE1OiB1bmxp?= =?utf-8?q?nk_a_file_that_test=5Fposixpath_was_leaving_around=2E?= Message-ID: <3ZHg2b3BvkzRv4@mail.python.org> http://hg.python.org/cpython/rev/ed3ca7298055 changeset: 82441:ed3ca7298055 branch: 2.7 parent: 82430:6ae4938256c6 user: Ezio Melotti date: Fri Mar 01 20:56:13 2013 +0200 summary: #17315: unlink a file that test_posixpath was leaving around. files: Lib/test/test_posixpath.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -284,6 +284,7 @@ test_support.unlink(ABSTFN+"2") test_support.unlink(ABSTFN+"y") test_support.unlink(ABSTFN+"c") + test_support.unlink(ABSTFN+"a") def test_realpath_repeated_indirect_symlinks(self): # Issue #6975. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:01:12 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:01:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzE1OiB1bmxp?= =?utf-8?q?nk_a_file_that_test=5Fposixpath_was_leaving_around=2E?= Message-ID: <3ZHg2c6CwVz7Lkc@mail.python.org> http://hg.python.org/cpython/rev/c65e98ce1a05 changeset: 82442:c65e98ce1a05 branch: 3.2 parent: 82427:52b9d5e3f026 user: Ezio Melotti date: Fri Mar 01 20:59:17 2013 +0200 summary: #17315: unlink a file that test_posixpath was leaving around. files: Lib/test/test_posixpath.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -421,6 +421,7 @@ support.unlink(ABSTFN+"2") support.unlink(ABSTFN+"y") support.unlink(ABSTFN+"c") + support.unlink(ABSTFN+"a") @unittest.skipUnless(hasattr(os, "symlink"), "Missing symlink implementation") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:01:14 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:01:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317315=3A_merge_with_3=2E2=2E?= Message-ID: <3ZHg2f231Wz7Lkc@mail.python.org> http://hg.python.org/cpython/rev/7a2169a80f48 changeset: 82443:7a2169a80f48 branch: 3.3 parent: 82437:1920422626a5 parent: 82442:c65e98ce1a05 user: Ezio Melotti date: Fri Mar 01 21:00:05 2013 +0200 summary: #17315: merge with 3.2. files: Lib/test/test_posixpath.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -423,6 +423,7 @@ support.unlink(ABSTFN+"2") support.unlink(ABSTFN+"y") support.unlink(ABSTFN+"c") + support.unlink(ABSTFN+"a") @unittest.skipUnless(hasattr(os, "symlink"), "Missing symlink implementation") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:01:15 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:01:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzE1OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZHg2g4bSWz7LmM@mail.python.org> http://hg.python.org/cpython/rev/7234370fc556 changeset: 82444:7234370fc556 parent: 82440:22b6b59c70e6 parent: 82443:7a2169a80f48 user: Ezio Melotti date: Fri Mar 01 21:00:48 2013 +0200 summary: #17315: merge with 3.3. files: Lib/test/test_posixpath.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -366,6 +366,7 @@ support.unlink(ABSTFN+"2") support.unlink(ABSTFN+"y") support.unlink(ABSTFN+"c") + support.unlink(ABSTFN+"a") @unittest.skipUnless(hasattr(os, "symlink"), "Missing symlink implementation") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:10:46 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:10:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2317312=3A_unlink_a_file_?= =?utf-8?q?that_test=5Faifc_was_leaving_around=2E?= Message-ID: <3ZHgFf4ZCcz7Lmk@mail.python.org> http://hg.python.org/cpython/rev/10909360a11d changeset: 82445:10909360a11d user: Ezio Melotti date: Fri Mar 01 21:10:26 2013 +0200 summary: #17312: unlink a file that test_aifc was leaving around. files: Lib/test/test_aifc.py | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -331,12 +331,14 @@ def test_write_aiff_by_extension(self): sampwidth = 2 - fout = self.fout = aifc.open(TESTFN + '.aiff', 'wb') + filename = TESTFN + '.aiff' + fout = self.fout = aifc.open(filename, 'wb') + self.addCleanup(unlink, filename) fout.setparams((1, sampwidth, 1, 1, b'ULAW', b'')) frames = b'\x00' * fout.getnchannels() * sampwidth fout.writeframes(frames) fout.close() - f = self.f = aifc.open(TESTFN + '.aiff', 'rb') + f = self.f = aifc.open(filename, 'rb') self.assertEqual(f.getcomptype(), b'NONE') f.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:28:42 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:28:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_markup_in_?= =?utf-8?q?unittest_doc=2E?= Message-ID: <3ZHgfL5sCKzNt4@mail.python.org> http://hg.python.org/cpython/rev/2f500533e9b9 changeset: 82446:2f500533e9b9 branch: 2.7 parent: 82441:ed3ca7298055 user: Ezio Melotti date: Fri Mar 01 21:26:04 2013 +0200 summary: Fix markup in unittest doc. files: Doc/library/unittest.rst | 8 ++++---- 1 files changed, 4 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 @@ -584,7 +584,7 @@ Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` or one of its conditional variants. -Basic skipping looks like this: :: +Basic skipping looks like this:: class MyTestCase(unittest.TestCase): @@ -603,7 +603,7 @@ # windows specific testing code pass -This is the output of running the example above in verbose mode: :: +This is the output of running the example above in verbose mode:: test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' @@ -614,7 +614,7 @@ OK (skipped=3) -Classes can be skipped just like methods: :: +Classes can be skipped just like methods:: @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): @@ -633,7 +633,7 @@ It's easy to roll your own skipping decorators by making a decorator that calls :func:`skip` on the test when it wants it to be skipped. This decorator skips -the test unless the passed object has a certain attribute: :: +the test unless the passed object has a certain attribute:: def skipUnlessHasattr(obj, attr): if hasattr(obj, attr): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:28:44 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:28:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_markup_in_?= =?utf-8?q?unittest_doc=2E?= Message-ID: <3ZHgfN1qrCzQ4R@mail.python.org> http://hg.python.org/cpython/rev/23669bea387e changeset: 82447:23669bea387e branch: 3.2 parent: 82442:c65e98ce1a05 user: Ezio Melotti date: Fri Mar 01 21:26:04 2013 +0200 summary: Fix markup in unittest doc. files: Doc/library/unittest.rst | 8 ++++---- 1 files changed, 4 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 @@ -609,7 +609,7 @@ Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` or one of its conditional variants. -Basic skipping looks like this: :: +Basic skipping looks like this:: class MyTestCase(unittest.TestCase): @@ -628,7 +628,7 @@ # windows specific testing code pass -This is the output of running the example above in verbose mode: :: +This is the output of running the example above in verbose mode:: test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' @@ -639,7 +639,7 @@ OK (skipped=3) -Classes can be skipped just like methods: :: +Classes can be skipped just like methods:: @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): @@ -658,7 +658,7 @@ It's easy to roll your own skipping decorators by making a decorator that calls :func:`skip` on the test when it wants it to be skipped. This decorator skips -the test unless the passed object has a certain attribute: :: +the test unless the passed object has a certain attribute:: def skipUnlessHasattr(obj, attr): if hasattr(obj, attr): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:28:45 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:28:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_markup_fixes_in_unittest_doc_from_3=2E2=2E?= Message-ID: <3ZHgfP4QV3zRhf@mail.python.org> http://hg.python.org/cpython/rev/01bfd48efef5 changeset: 82448:01bfd48efef5 branch: 3.3 parent: 82443:7a2169a80f48 parent: 82447:23669bea387e user: Ezio Melotti date: Fri Mar 01 21:28:06 2013 +0200 summary: Merge markup fixes in unittest doc from 3.2. files: Doc/library/unittest.rst | 8 ++++---- 1 files changed, 4 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 @@ -476,7 +476,7 @@ Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` or one of its conditional variants. -Basic skipping looks like this: :: +Basic skipping looks like this:: class MyTestCase(unittest.TestCase): @@ -495,7 +495,7 @@ # windows specific testing code pass -This is the output of running the example above in verbose mode: :: +This is the output of running the example above in verbose mode:: test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' @@ -506,7 +506,7 @@ OK (skipped=3) -Classes can be skipped just like methods: :: +Classes can be skipped just like methods:: @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): @@ -525,7 +525,7 @@ It's easy to roll your own skipping decorators by making a decorator that calls :func:`skip` on the test when it wants it to be skipped. This decorator skips -the test unless the passed object has a certain attribute: :: +the test unless the passed object has a certain attribute:: def skipUnlessHasattr(obj, attr): if hasattr(obj, attr): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 20:28:46 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 1 Mar 2013 20:28:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_markup_fixes_in_unittest_doc_from_3=2E3=2E?= Message-ID: <3ZHgfQ72JtzRh6@mail.python.org> http://hg.python.org/cpython/rev/1bf721567067 changeset: 82449:1bf721567067 parent: 82445:10909360a11d parent: 82448:01bfd48efef5 user: Ezio Melotti date: Fri Mar 01 21:28:23 2013 +0200 summary: Merge markup fixes in unittest doc from 3.3. files: Doc/library/unittest.rst | 8 ++++---- 1 files changed, 4 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 @@ -476,7 +476,7 @@ Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` or one of its conditional variants. -Basic skipping looks like this: :: +Basic skipping looks like this:: class MyTestCase(unittest.TestCase): @@ -495,7 +495,7 @@ # windows specific testing code pass -This is the output of running the example above in verbose mode: :: +This is the output of running the example above in verbose mode:: test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' @@ -506,7 +506,7 @@ OK (skipped=3) -Classes can be skipped just like methods: :: +Classes can be skipped just like methods:: @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): @@ -525,7 +525,7 @@ It's easy to roll your own skipping decorators by making a decorator that calls :func:`skip` on the test when it wants it to be skipped. This decorator skips -the test unless the passed object has a certain attribute: :: +the test unless the passed object has a certain attribute:: def skipUnlessHasattr(obj, attr): if hasattr(obj, attr): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 1 23:14:33 2013 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 1 Mar 2013 23:14:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_as=5Furi=28=29_method_a?= =?utf-8?q?s_suggested_by_Charles-Fran=C3=A7ois=2C_to_return_a_file_URI=2E?= Message-ID: <3ZHlKj6Vf8z7Ljh@mail.python.org> http://hg.python.org/peps/rev/96389266e4af changeset: 4778:96389266e4af user: Antoine Pitrou date: Fri Mar 01 23:10:53 2013 +0100 summary: Add a as_uri() method as suggested by Charles-Fran?ois, to return a file URI. files: pep-0428.txt | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/pep-0428.txt b/pep-0428.txt --- a/pep-0428.txt +++ b/pep-0428.txt @@ -341,6 +341,15 @@ >>> bytes(p) b'/home/antoine/pathlib/setup.py' +To represent the path as a ``file`` URI, call the ``as_uri()`` method:: + + >>> p = PurePosixPath('/etc/passwd') + >>> p.as_uri() + 'file:///etc/passwd' + >>> p = PureNTPath('c:/Windows') + >>> p.as_uri() + 'file:///c:/Windows' + Properties ---------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Mar 1 23:28:11 2013 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 1 Mar 2013 23:28:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Mention_the_dedicated_branch_?= =?utf-8?q?in_the_Mercurial_repo=2E?= Message-ID: <3ZHldR3rk0zQtG@mail.python.org> http://hg.python.org/peps/rev/53a41d76241c changeset: 4779:53a41d76241c user: Antoine Pitrou date: Fri Mar 01 23:24:24 2013 +0100 summary: Mention the dedicated branch in the Mercurial repo. files: pep-0428.txt | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/pep-0428.txt b/pep-0428.txt --- a/pep-0428.txt +++ b/pep-0428.txt @@ -55,6 +55,15 @@ .. _`Unipath`: https://bitbucket.org/sluggo/unipath/overview +Implementation +============== + +The implementation of this proposal is tracked in the ``pep428`` branch +of pathlib's `Mercurial repository`_. + +.. _`Mercurial repository`: https://bitbucket.org/pitrou/pathlib/ + + Why an object-oriented API ========================== -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Sat Mar 2 05:59:52 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 02 Mar 2013 05:59:52 +0100 Subject: [Python-checkins] Daily reference leaks (1bf721567067): sum=1 Message-ID: results for 1bf721567067 on branch "default" -------------------------------------------- test_unittest leaked [0, -1, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogyJDDCz', '-x'] From python-checkins at python.org Sat Mar 2 08:28:00 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 2 Mar 2013 08:28:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Remove_depende?= =?utf-8?q?ncy_on_dummy=5Fthreading_=28to_solve_a_bootstrap_problem=29=2E?= Message-ID: <3ZHzcJ3fqvz7Lmc@mail.python.org> http://hg.python.org/cpython/rev/e9732c25a018 changeset: 82450:e9732c25a018 branch: 3.3 parent: 82448:01bfd48efef5 user: Raymond Hettinger date: Fri Mar 01 23:20:13 2013 -0800 summary: Remove dependency on dummy_threading (to solve a bootstrap problem). files: Lib/functools.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -16,7 +16,10 @@ try: from _thread import RLock except: - from dummy_threading import RLock + class RLock: + 'Dummy reentrant lock' + def __enter__(self): pass + def __exit__(self, exctype, excinst, exctb): pass ################################################################################ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 08:28:01 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 2 Mar 2013 08:28:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZHzcK6Vkyz7LnH@mail.python.org> http://hg.python.org/cpython/rev/fd9e4646bec9 changeset: 82451:fd9e4646bec9 parent: 82449:1bf721567067 parent: 82450:e9732c25a018 user: Raymond Hettinger date: Fri Mar 01 23:21:00 2013 -0800 summary: Merge files: Lib/functools.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -19,7 +19,10 @@ try: from _thread import RLock except: - from dummy_threading import RLock + class RLock: + 'Dummy reentrant lock' + def __enter__(self): pass + def __exit__(self, exctype, excinst, exctb): pass ################################################################################ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 08:51:55 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 2 Mar 2013 08:51:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MzMx?= =?utf-8?q?=3A__Use_isidentifier=28=29_instead_of_isalnum=28=29_to_check_f?= =?utf-8?q?or_valid?= Message-ID: <3ZJ07v6LQKz7Lmf@mail.python.org> http://hg.python.org/cpython/rev/80bcc98bf939 changeset: 82452:80bcc98bf939 branch: 3.3 parent: 82450:e9732c25a018 user: Raymond Hettinger date: Fri Mar 01 23:43:48 2013 -0800 summary: Issue #17331: Use isidentifier() instead of isalnum() to check for valid identifiers. files: Lib/collections/__init__.py | 13 ++++--------- 1 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -323,24 +323,19 @@ if rename: seen = set() for index, name in enumerate(field_names): - if (not all(c.isalnum() or c=='_' for c in name) + if (not name.isidentifier() or _iskeyword(name) - or not name - or name[0].isdigit() or name.startswith('_') or name in seen): field_names[index] = '_%d' % index seen.add(name) for name in [typename] + field_names: - if not all(c.isalnum() or c=='_' for c in name): - raise ValueError('Type names and field names can only contain ' - 'alphanumeric characters and underscores: %r' % name) + if not name.isidentifier(): + raise ValueError('Type names and field names must be valid ' + 'identifiers: %r' % name) if _iskeyword(name): raise ValueError('Type names and field names cannot be a ' 'keyword: %r' % name) - if name[0].isdigit(): - raise ValueError('Type names and field names cannot start with ' - 'a number: %r' % name) seen = set() for name in field_names: if name.startswith('_') and not rename: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 08:51:57 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 2 Mar 2013 08:51:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZJ07x20jgz7Lng@mail.python.org> http://hg.python.org/cpython/rev/96b16fe4a961 changeset: 82453:96b16fe4a961 parent: 82451:fd9e4646bec9 parent: 82452:80bcc98bf939 user: Raymond Hettinger date: Fri Mar 01 23:51:26 2013 -0800 summary: Merge files: Lib/collections/__init__.py | 13 ++++--------- 1 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -322,24 +322,19 @@ if rename: seen = set() for index, name in enumerate(field_names): - if (not all(c.isalnum() or c=='_' for c in name) + if (not name.isidentifier() or _iskeyword(name) - or not name - or name[0].isdigit() or name.startswith('_') or name in seen): field_names[index] = '_%d' % index seen.add(name) for name in [typename] + field_names: - if not all(c.isalnum() or c=='_' for c in name): - raise ValueError('Type names and field names can only contain ' - 'alphanumeric characters and underscores: %r' % name) + if not name.isidentifier(): + raise ValueError('Type names and field names must be valid ' + 'identifiers: %r' % name) if _iskeyword(name): raise ValueError('Type names and field names cannot be a ' 'keyword: %r' % name) - if name[0].isdigit(): - raise ValueError('Type names and field names cannot start with ' - 'a number: %r' % name) seen = set() for name in field_names: if name.startswith('_') and not rename: -- Repository URL: http://hg.python.org/cpython From root at python.org Sat Mar 2 12:05:23 2013 From: root at python.org (Cron Daemon) Date: Sat, 02 Mar 2013 12:05:23 +0100 Subject: [Python-checkins] Cron /home/docs/build-devguide Message-ID: abort: error: Connection timed out From python-checkins at python.org Sat Mar 2 13:33:25 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Mar 2013 13:33:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MzMzOiB0ZXN0?= =?utf-8?q?=5Fimaplib_now_works_with_unittest_test_discovery=2E__Patch_by_?= =?utf-8?q?Zachary?= Message-ID: <3ZJ6Nj60W9zRsn@mail.python.org> http://hg.python.org/cpython/rev/02bbc5375a56 changeset: 82454:02bbc5375a56 branch: 3.3 parent: 82452:80bcc98bf939 user: Ezio Melotti date: Sat Mar 02 14:25:56 2013 +0200 summary: #17333: test_imaplib now works with unittest test discovery. Patch by Zachary Ware. files: Lib/test/test_imaplib.py | 6 +++--- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) 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 @@ -444,7 +444,7 @@ keyfile=CERTFILE, ssl_context=self.create_ssl_context()) -def test_main(): +def load_tests(*args): tests = [TestImaplib] if support.is_resource_enabled('network'): @@ -459,9 +459,9 @@ RemoteIMAPTest, RemoteIMAP_SSLTest, RemoteIMAP_STARTTLSTest, ]) - support.run_unittest(*tests) + return unittest.TestSuite([unittest.makeSuite(test) for test in tests]) if __name__ == "__main__": support.use_resources = ['network'] - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -644,6 +644,9 @@ - Issue #15539: Added regression tests for Tools/scripts/pindent.py. +- Issue #17333: test_imaplib now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17082: test_dbm* now work with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 13:33:27 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Mar 2013 13:33:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzMzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZJ6Nl1gscz7Lnp@mail.python.org> http://hg.python.org/cpython/rev/b8bafae4a15a changeset: 82455:b8bafae4a15a parent: 82453:96b16fe4a961 parent: 82454:02bbc5375a56 user: Ezio Melotti date: Sat Mar 02 14:33:05 2013 +0200 summary: #17333: merge with 3.3. files: Lib/test/test_imaplib.py | 6 +++--- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) 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 @@ -444,7 +444,7 @@ keyfile=CERTFILE, ssl_context=self.create_ssl_context()) -def test_main(): +def load_tests(*args): tests = [TestImaplib] if support.is_resource_enabled('network'): @@ -459,9 +459,9 @@ RemoteIMAPTest, RemoteIMAP_SSLTest, RemoteIMAP_STARTTLSTest, ]) - support.run_unittest(*tests) + return unittest.TestSuite([unittest.makeSuite(test) for test in tests]) if __name__ == "__main__": support.use_resources = ['network'] - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -899,6 +899,9 @@ - Issue #16836: Enable IPv6 support even if IPv6 is disabled on the build host. +- Issue #17333: test_imaplib now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17082: test_dbm* now work with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 13:48:21 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Mar 2013 13:48:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MzM0OiB0ZXN0?= =?utf-8?q?=5Findex_now_works_with_unittest_test_discovery=2E__Patch_by_Za?= =?utf-8?q?chary?= Message-ID: <3ZJ6jx13VfzRlt@mail.python.org> http://hg.python.org/cpython/rev/886df716cd09 changeset: 82456:886df716cd09 branch: 3.3 parent: 82454:02bbc5375a56 user: Ezio Melotti date: Sat Mar 02 14:47:07 2013 +0200 summary: #17334: test_index now works with unittest test discovery. Patch by Zachary Ware. files: Lib/test/test_index.py | 29 ++++++++--------------------- Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_index.py b/Lib/test/test_index.py --- a/Lib/test/test_index.py +++ b/Lib/test/test_index.py @@ -56,7 +56,7 @@ self.assertRaises(TypeError, slice(self.n).indices, 0) -class SeqTestCase(unittest.TestCase): +class SeqTestCase: # This test case isn't run directly. It just defines common tests # to the different sequence types below def setUp(self): @@ -126,7 +126,7 @@ self.assertRaises(TypeError, sliceobj, self.n, self) -class ListTestCase(SeqTestCase): +class ListTestCase(SeqTestCase, unittest.TestCase): seq = [0,10,20,30,40,50] def test_setdelitem(self): @@ -182,19 +182,19 @@ return self._list[index] -class TupleTestCase(SeqTestCase): +class TupleTestCase(SeqTestCase, unittest.TestCase): seq = (0,10,20,30,40,50) -class ByteArrayTestCase(SeqTestCase): +class ByteArrayTestCase(SeqTestCase, unittest.TestCase): seq = bytearray(b"this is a test") -class BytesTestCase(SeqTestCase): +class BytesTestCase(SeqTestCase, unittest.TestCase): seq = b"this is a test" -class StringTestCase(SeqTestCase): +class StringTestCase(SeqTestCase, unittest.TestCase): seq = "this is a test" -class NewSeqTestCase(SeqTestCase): +class NewSeqTestCase(SeqTestCase, unittest.TestCase): seq = NewSeq((0,10,20,30,40,50)) @@ -237,18 +237,5 @@ self.assertRaises(OverflowError, lambda: "a" * self.neg) -def test_main(): - support.run_unittest( - BaseTestCase, - ListTestCase, - TupleTestCase, - BytesTestCase, - ByteArrayTestCase, - StringTestCase, - NewSeqTestCase, - RangeTestCase, - OverflowTestCase, - ) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -644,6 +644,9 @@ - Issue #15539: Added regression tests for Tools/scripts/pindent.py. +- Issue #17334: test_index now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17333: test_imaplib now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 2 13:48:22 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Mar 2013 13:48:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzM0OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZJ6jy3pvxz7LpD@mail.python.org> http://hg.python.org/cpython/rev/1c71882938eb changeset: 82457:1c71882938eb parent: 82455:b8bafae4a15a parent: 82456:886df716cd09 user: Ezio Melotti date: Sat Mar 02 14:48:01 2013 +0200 summary: #17334: merge with 3.3. files: Lib/test/test_index.py | 29 ++++++++--------------------- Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_index.py b/Lib/test/test_index.py --- a/Lib/test/test_index.py +++ b/Lib/test/test_index.py @@ -56,7 +56,7 @@ self.assertRaises(TypeError, slice(self.n).indices, 0) -class SeqTestCase(unittest.TestCase): +class SeqTestCase: # This test case isn't run directly. It just defines common tests # to the different sequence types below def setUp(self): @@ -126,7 +126,7 @@ self.assertRaises(TypeError, sliceobj, self.n, self) -class ListTestCase(SeqTestCase): +class ListTestCase(SeqTestCase, unittest.TestCase): seq = [0,10,20,30,40,50] def test_setdelitem(self): @@ -182,19 +182,19 @@ return self._list[index] -class TupleTestCase(SeqTestCase): +class TupleTestCase(SeqTestCase, unittest.TestCase): seq = (0,10,20,30,40,50) -class ByteArrayTestCase(SeqTestCase): +class ByteArrayTestCase(SeqTestCase, unittest.TestCase): seq = bytearray(b"this is a test") -class BytesTestCase(SeqTestCase): +class BytesTestCase(SeqTestCase, unittest.TestCase): seq = b"this is a test" -class StringTestCase(SeqTestCase): +class StringTestCase(SeqTestCase, unittest.TestCase): seq = "this is a test" -class NewSeqTestCase(SeqTestCase): +class NewSeqTestCase(SeqTestCase, unittest.TestCase): seq = NewSeq((0,10,20,30,40,50)) @@ -237,18 +237,5 @@ self.assertRaises(OverflowError, lambda: "a" * self.neg) -def test_main(): - support.run_unittest( - BaseTestCase, - ListTestCase, - TupleTestCase, - BytesTestCase, - ByteArrayTestCase, - StringTestCase, - NewSeqTestCase, - RangeTestCase, - OverflowTestCase, - ) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -899,6 +899,9 @@ - Issue #16836: Enable IPv6 support even if IPv6 is disabled on the build host. +- Issue #17334: test_index now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17333: test_imaplib now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From root at python.org Sat Mar 2 23:25:22 2013 From: root at python.org (Cron Daemon) Date: Sat, 02 Mar 2013 23:25:22 +0100 Subject: [Python-checkins] Cron /home/docs/build-devguide Message-ID: abort: error: Connection timed out From solipsis at pitrou.net Sun Mar 3 06:02:01 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 03 Mar 2013 06:02:01 +0100 Subject: [Python-checkins] Daily reference leaks (1c71882938eb): sum=-2 Message-ID: results for 1c71882938eb on branch "default" -------------------------------------------- test_concurrent_futures leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflognu59ci', '-x'] From python-checkins at python.org Sun Mar 3 12:13:48 2013 From: python-checkins at python.org (mark.dickinson) Date: Sun, 3 Mar 2013 12:13:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2NDQ1?= =?utf-8?q?=3A_Fix_potential_segmentation_fault_when_deleting_an_exception?= Message-ID: <3ZJhZN66hMzRwv@mail.python.org> http://hg.python.org/cpython/rev/0e41c4466d58 changeset: 82458:0e41c4466d58 branch: 2.7 parent: 82446:2f500533e9b9 user: Mark Dickinson date: Sun Mar 03 11:13:34 2013 +0000 summary: Issue #16445: Fix potential segmentation fault when deleting an exception message. files: Lib/test/test_exceptions.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Objects/exceptions.c | 3 +-- 3 files changed, 16 insertions(+), 2 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 @@ -479,6 +479,18 @@ except AssertionError as e: self.assertEqual(str(e), "(3,)") + def test_bad_exception_clearing(self): + # See issue 16445: use of Py_XDECREF instead of Py_CLEAR in + # BaseException_set_message gave a possible way to segfault the + # interpreter. + class Nasty(str): + def __del__(message): + del e.message + + e = ValueError(Nasty("msg")) + e.args = () + del e.message + # Helper class used by TestSameStrAndUnicodeMsg class ExcWithOverriddenStr(Exception): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #16445: Fixed potential segmentation fault when deleting an exception + message. + - Issue #17275: Corrected class name in init error messages of the C version of BufferedWriter and BufferedRandom. diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -349,8 +349,7 @@ if (PyDict_DelItemString(self->dict, "message") < 0) return -1; } - Py_XDECREF(self->message); - self->message = NULL; + Py_CLEAR(self->message); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 14:13:17 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 3 Mar 2013 14:13:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2317032=3A_The_=22global?= =?utf-8?q?=22_in_the_=22NameError=3A_global_name_=27x=27_is_not_defined?= =?utf-8?q?=22_error?= Message-ID: <3ZJlDF26jczQrk@mail.python.org> http://hg.python.org/cpython/rev/f1d3fbcd837d changeset: 82459:f1d3fbcd837d parent: 82457:1c71882938eb user: Ezio Melotti date: Sun Mar 03 15:12:44 2013 +0200 summary: #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. files: Lib/test/test_keywordonlyarg.py | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ Python/ceval.c | 8 +++----- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -182,10 +182,10 @@ with self.assertRaises(NameError) as err: def f(v=a, x=b, *, y=c, z=d): pass - self.assertEqual(str(err.exception), "global name 'b' is not defined") + self.assertEqual(str(err.exception), "name 'b' is not defined") with self.assertRaises(NameError) as err: f = lambda v=a, x=b, *, y=c, z=d: None - self.assertEqual(str(err.exception), "global name 'b' is not defined") + self.assertEqual(str(err.exception), "name 'b' is not defined") def test_main(): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -969,6 +969,7 @@ Pierre Quentel Brian Quinlan Anders Qvist +Ram Rachum J?r?me Radix Burton Radons Jeff Ramnani diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #17032: The "global" in the "NameError: global name 'x' is not defined" + error message has been removed. Patch by Ram Rachum. + - Issue #17223: array module: Fix a crasher when converting an array containing invalid characters (outside range [U+0000; U+10ffff]) to Unicode: repr(array), str(array) and array.tounicode(). Patch written by Manuel Jacob. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -142,8 +142,6 @@ #define NAME_ERROR_MSG \ "name '%.200s' is not defined" -#define GLOBAL_NAME_ERROR_MSG \ - "global name '%.200s' is not defined" #define UNBOUNDLOCAL_ERROR_MSG \ "local variable '%.200s' referenced before assignment" #define UNBOUNDFREE_ERROR_MSG \ @@ -2140,7 +2138,7 @@ err = PyDict_DelItem(f->f_globals, name); if (err != 0) { format_exc_check_arg( - PyExc_NameError, GLOBAL_NAME_ERROR_MSG, name); + PyExc_NameError, NAME_ERROR_MSG, name); goto error; } DISPATCH(); @@ -2208,7 +2206,7 @@ if (v == NULL) { if (!PyErr_Occurred()) format_exc_check_arg(PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, name); + NAME_ERROR_MSG, name); goto error; } Py_INCREF(v); @@ -2222,7 +2220,7 @@ if (PyErr_ExceptionMatches(PyExc_KeyError)) format_exc_check_arg( PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, name); + NAME_ERROR_MSG, name); goto error; } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 19:53:34 2013 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 3 Mar 2013 19:53:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2OTYy?= =?utf-8?q?=3A_Use_getdents64_instead_of_the_obsolete_getdents_syscall_in?= Message-ID: <3ZJtmt0djQzQmx@mail.python.org> http://hg.python.org/cpython/rev/30e643e36bae changeset: 82460:30e643e36bae branch: 3.3 parent: 82456:886df716cd09 user: Gregory P. Smith date: Sun Mar 03 10:45:05 2013 -0800 summary: Issue #16962: Use getdents64 instead of the obsolete getdents syscall in the subprocess module on Linux. files: Misc/NEWS | 6 +++--- Modules/_posixsubprocess.c | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -191,6 +191,9 @@ Library ------- +- Issue #16962: Use getdents64 instead of the obsolete getdents syscall + in the subprocess module on Linux. + - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. - Issue #14720: sqlite3: Convert datetime microseconds correctly. @@ -626,9 +629,6 @@ - Issue #15906: Fix a regression in `argparse` caused by the preceding change, when ``action='append'``, ``type='str'`` and ``default=[]``. -Extension Modules ------------------ - - Issue #12268: The io module file object write methods no longer abort early when one of its write system calls is interrupted (EINTR). diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -176,17 +176,11 @@ * This structure is very old and stable: It will not change unless the kernel * chooses to break compatibility with all existing binaries. Highly Unlikely. */ -struct linux_dirent { -#if defined(__x86_64__) && defined(__ILP32__) - /* Support the wacky x32 ABI (fake 32-bit userspace speaking to x86_64 - * kernel interfaces) - https://sites.google.com/site/x32abi/ */ +struct linux_dirent64 { unsigned long long d_ino; - unsigned long long d_off; -#else - unsigned long d_ino; /* Inode number */ - unsigned long d_off; /* Offset to next linux_dirent */ -#endif + long long d_off; unsigned short d_reclen; /* Length of this linux_dirent */ + unsigned char d_type; char d_name[256]; /* Filename (null-terminated) */ }; @@ -228,16 +222,16 @@ _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep); return; } else { - char buffer[sizeof(struct linux_dirent)]; + char buffer[sizeof(struct linux_dirent64)]; int bytes; - while ((bytes = syscall(SYS_getdents, fd_dir_fd, - (struct linux_dirent *)buffer, + while ((bytes = syscall(SYS_getdents64, fd_dir_fd, + (struct linux_dirent64 *)buffer, sizeof(buffer))) > 0) { - struct linux_dirent *entry; + struct linux_dirent64 *entry; int offset; for (offset = 0; offset < bytes; offset += entry->d_reclen) { int fd; - entry = (struct linux_dirent *)(buffer + offset); + entry = (struct linux_dirent64 *)(buffer + offset); if ((fd = _pos_int_from_ascii(entry->d_name)) < 0) continue; /* Not a number. */ if (fd != fd_dir_fd && fd >= start_fd && fd < end_fd && -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 19:53:35 2013 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 3 Mar 2013 19:53:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fixes_Issue_=2316962=3A_Use_getdents64_instead_of_the_ob?= =?utf-8?q?solete_getdents_syscall?= Message-ID: <3ZJtmv3N8RzQqb@mail.python.org> http://hg.python.org/cpython/rev/7ab1c55fcf82 changeset: 82461:7ab1c55fcf82 parent: 82459:f1d3fbcd837d parent: 82460:30e643e36bae user: Gregory P. Smith date: Sun Mar 03 10:53:27 2013 -0800 summary: Fixes Issue #16962: Use getdents64 instead of the obsolete getdents syscall in the subprocess module on Linux. files: Misc/NEWS | 3 +++ Modules/_posixsubprocess.c | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -273,6 +273,9 @@ Library ------- +- Issue #16962: Use getdents64 instead of the obsolete getdents syscall + in the subprocess module on Linux. + - Issue #16935: unittest now counts the module as skipped if it raises SkipTest, instead of counting it as an error. Patch by Zachary Ware. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -176,17 +176,11 @@ * This structure is very old and stable: It will not change unless the kernel * chooses to break compatibility with all existing binaries. Highly Unlikely. */ -struct linux_dirent { -#if defined(__x86_64__) && defined(__ILP32__) - /* Support the wacky x32 ABI (fake 32-bit userspace speaking to x86_64 - * kernel interfaces) - https://sites.google.com/site/x32abi/ */ +struct linux_dirent64 { unsigned long long d_ino; - unsigned long long d_off; -#else - unsigned long d_ino; /* Inode number */ - unsigned long d_off; /* Offset to next linux_dirent */ -#endif + long long d_off; unsigned short d_reclen; /* Length of this linux_dirent */ + unsigned char d_type; char d_name[256]; /* Filename (null-terminated) */ }; @@ -228,16 +222,16 @@ _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep); return; } else { - char buffer[sizeof(struct linux_dirent)]; + char buffer[sizeof(struct linux_dirent64)]; int bytes; - while ((bytes = syscall(SYS_getdents, fd_dir_fd, - (struct linux_dirent *)buffer, + while ((bytes = syscall(SYS_getdents64, fd_dir_fd, + (struct linux_dirent64 *)buffer, sizeof(buffer))) > 0) { - struct linux_dirent *entry; + struct linux_dirent64 *entry; int offset; for (offset = 0; offset < bytes; offset += entry->d_reclen) { int fd; - entry = (struct linux_dirent *)(buffer + offset); + entry = (struct linux_dirent64 *)(buffer + offset); if ((fd = _pos_int_from_ascii(entry->d_name)) < 0) continue; /* Not a number. */ if (fd != fd_dir_fd && fd >= start_fd && fd < end_fd && -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 22:34:50 2013 From: python-checkins at python.org (nadeem.vawda) Date: Sun, 3 Mar 2013 22:34:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzODk4?= =?utf-8?q?=3A_test=5Fssl_no_longer_prints_a_spurious_stack_trace_on_Ubunt?= =?utf-8?q?u=2E?= Message-ID: <3ZJyLy61Kxz7LkY@mail.python.org> http://hg.python.org/cpython/rev/fa24c1382bd3 changeset: 82462:fa24c1382bd3 branch: 3.2 parent: 82447:23669bea387e user: Nadeem Vawda date: Sun Mar 03 22:31:21 2013 +0100 summary: Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. files: Lib/test/test_ssl.py | 8 +++++++- Misc/NEWS | 2 ++ 2 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -774,7 +774,13 @@ try: self.sslconn = self.server.context.wrap_socket( self.sock, server_side=True) - except ssl.SSLError as e: + except (ssl.SSLError, socket.error) as e: + # Treat ECONNRESET as though it were an SSLError - OpenSSL + # on Ubuntu abruptly closes the connection when asked to use + # an unsupported protocol. + if (not isinstance(e, ssl.SSLError) and + e.errno != errno.ECONNRESET): + raise # XXX Various errors can have happened here, for example # a mismatching protocol version, an invalid certificate, # or a low-level bug. This should be made more discriminating. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -947,6 +947,8 @@ Tests ----- +- Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. + - Issue #17249: convert a test in test_capi to use unittest and reap threads. - Issue #17041: Fix testing when Python is configured with the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 22:44:40 2013 From: python-checkins at python.org (nadeem.vawda) Date: Sun, 3 Mar 2013 22:44:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2313898=3A_test=5Fssl_no_longer_prints_a_spurious_stack?= =?utf-8?q?_trace_on_Ubuntu=2E?= Message-ID: <3ZJyZJ5gCXzRqX@mail.python.org> http://hg.python.org/cpython/rev/77cbb3ba5d40 changeset: 82463:77cbb3ba5d40 branch: 3.3 parent: 82460:30e643e36bae parent: 82462:fa24c1382bd3 user: Nadeem Vawda date: Sun Mar 03 22:44:22 2013 +0100 summary: Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. files: Lib/test/test_ssl.py | 6 +++++- Misc/NEWS | 2 ++ 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -942,7 +942,11 @@ self.sslconn = self.server.context.wrap_socket( self.sock, server_side=True) self.server.selected_protocols.append(self.sslconn.selected_npn_protocol()) - except ssl.SSLError as e: + except (ssl.SSLError, ConnectionResetError) as e: + # We treat ConnectionResetError as though it were an + # SSLError - OpenSSL on Ubuntu abruptly closes the + # connection when asked to use an unsupported protocol. + # # XXX Various errors can have happened here, for example # a mismatching protocol version, an invalid certificate, # or a low-level bug. This should be made more discriminating. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -635,6 +635,8 @@ Tests ----- +- Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. + - Issue #17249: convert a test in test_capi to use unittest and reap threads. - Issue #17041: Fix testing when Python is configured with the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 3 22:48:37 2013 From: python-checkins at python.org (nadeem.vawda) Date: Sun, 3 Mar 2013 22:48:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2313898=3A_test=5Fssl_no_longer_prints_a_spurious?= =?utf-8?q?_stack_trace_on_Ubuntu=2E?= Message-ID: <3ZJyfs1DCHzQfC@mail.python.org> http://hg.python.org/cpython/rev/69f737f410f0 changeset: 82464:69f737f410f0 parent: 82461:7ab1c55fcf82 parent: 82463:77cbb3ba5d40 user: Nadeem Vawda date: Sun Mar 03 22:48:15 2013 +0100 summary: Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. files: Lib/test/test_ssl.py | 6 +++++- Misc/NEWS | 2 ++ 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -979,7 +979,11 @@ self.sslconn = self.server.context.wrap_socket( self.sock, server_side=True) self.server.selected_protocols.append(self.sslconn.selected_npn_protocol()) - except ssl.SSLError as e: + except (ssl.SSLError, ConnectionResetError) as e: + # We treat ConnectionResetError as though it were an + # SSLError - OpenSSL on Ubuntu abruptly closes the + # connection when asked to use an unsupported protocol. + # # XXX Various errors can have happened here, for example # a mismatching protocol version, an invalid certificate, # or a low-level bug. This should be made more discriminating. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -887,6 +887,8 @@ Tests ----- +- Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. + - Issue #17283: Share code between `__main__.py` and `regrtest.py` in `Lib/test`. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Mar 4 05:57:44 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 04 Mar 2013 05:57:44 +0100 Subject: [Python-checkins] Daily reference leaks (69f737f410f0): sum=3 Message-ID: results for 69f737f410f0 on branch "default" -------------------------------------------- test_support leaked [0, -1, 1] references, sum=0 test_support leaked [0, -1, 3] memory blocks, sum=2 test_concurrent_futures leaked [0, -2, 3] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog66f0Kd', '-x'] From python-checkins at python.org Mon Mar 4 08:21:21 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 08:21:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316098=3A__Update_?= =?utf-8?q?heapq=2Ensmallest_to_use_the_same_algorithm_as_nlargest=2E?= Message-ID: <3ZKCMj0fCzzSwn@mail.python.org> http://hg.python.org/cpython/rev/362826298fdb changeset: 82465:362826298fdb user: Raymond Hettinger date: Mon Mar 04 02:20:31 2013 -0500 summary: Issue #16098: Update heapq.nsmallest to use the same algorithm as nlargest. This removes the dependency on bisect and it bring the pure Python code in-sync with the C code. files: Lib/heapq.py | 84 ++++++++++++++++++++++++++++----------- 1 files changed, 59 insertions(+), 25 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -127,8 +127,7 @@ __all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop'] -from itertools import islice, repeat, count, tee, chain -import bisect +from itertools import islice, count, tee, chain def heappush(heap, item): """Push item onto heap, maintaining the heap invariant.""" @@ -180,6 +179,19 @@ for i in reversed(range(n//2)): _siftup(x, i) +def _heappushpop_max(heap, item): + """Maxheap version of a heappush followed by a heappop.""" + if heap and heap[0] > item: + item, heap[0] = heap[0], item + _siftup_max(heap, 0) + return item + +def _heapify_max(x): + """Transform list into a maxheap, in-place, in O(len(x)) time.""" + n = len(x) + for i in reversed(range(n//2)): + _siftup_max(x, i) + def nlargest(n, iterable): """Find the n largest elements in a dataset. @@ -205,30 +217,16 @@ """ if n < 0: return [] - if hasattr(iterable, '__len__') and n * 10 <= len(iterable): - # For smaller values of n, the bisect method is faster than a minheap. - # It is also memory efficient, consuming only n elements of space. - it = iter(iterable) - result = sorted(islice(it, 0, n)) - if not result: - return result - insort = bisect.insort - pop = result.pop - los = result[-1] # los --> Largest of the nsmallest - for elem in it: - if elem < los: - insort(result, elem) - pop() - los = result[-1] + it = iter(iterable) + result = list(islice(it, n)) + if not result: return result - # An alternative approach manifests the whole iterable in memory but - # saves comparisons by heapifying all at once. Also, saves time - # over bisect.insort() which has O(n) data movement time for every - # insertion. Finding the n smallest of an m length iterable requires - # O(m) + O(n log m) comparisons. - h = list(iterable) - heapify(h) - return list(map(heappop, repeat(h, min(n, len(h))))) + _heapify_max(result) + _heappushpop = _heappushpop_max + for elem in it: + _heappushpop(result, elem) + result.sort() + return result # 'heap' is a heap at all indices >= startpos, except possibly for pos. pos # is the index of a leaf with a possibly out-of-order value. Restore the @@ -306,6 +304,42 @@ heap[pos] = newitem _siftdown(heap, startpos, pos) +def _siftdown_max(heap, startpos, pos): + 'Maxheap variant of _siftdown' + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if newitem > parent: + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +def _siftup_max(heap, pos): + 'Minheap variant of _siftup' + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the larger child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of larger child. + rightpos = childpos + 1 + if rightpos < endpos and not heap[childpos] > heap[rightpos]: + childpos = rightpos + # Move the larger child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown_max(heap, startpos, pos) + # If available, use C implementation try: from _heapq import * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 08:59:00 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 08:59:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Add_test_for_R?= =?utf-8?q?Lock_in_the_lru=5Fcache=28=29=2E?= Message-ID: <3ZKDC83PfZzRkL@mail.python.org> http://hg.python.org/cpython/rev/f27eaeffc4c0 changeset: 82466:f27eaeffc4c0 branch: 3.3 parent: 82463:77cbb3ba5d40 user: Raymond Hettinger date: Mon Mar 04 02:52:50 2013 -0500 summary: Add test for RLock in the lru_cache(). files: Lib/test/test_functools.py | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -777,6 +777,31 @@ self.assertEqual(square.cache_info().hits, 4) self.assertEqual(square.cache_info().misses, 4) + def test_need_for_rlock(self): + # This will deadlock on an LRU cache that uses a regular lock + + @functools.lru_cache(maxsize=10) + def test_func(x): + 'Used to demonstrate a reentrant lru_cache call within a single thread' + return x + + class DoubleEq: + 'Demonstrate a reentrant lru_cache call within a single thread' + def __init__(self, x): + self.x = x + def __hash__(self): + return self.x + def __eq__(self, other): + if self.x == 2: + test_func(DoubleEq(1)) + return self.x == other.x + + test_func(DoubleEq(1)) # Load the cache + test_func(DoubleEq(2)) # Load the cache + self.assertEqual(test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call + DoubleEq(2)) # Verify the correct return value + + def test_main(verbose=None): test_classes = ( TestPartial, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 08:59:01 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 08:59:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZKDC965wZzSl6@mail.python.org> http://hg.python.org/cpython/rev/af1961e38ccb changeset: 82467:af1961e38ccb parent: 82465:362826298fdb parent: 82466:f27eaeffc4c0 user: Raymond Hettinger date: Mon Mar 04 02:58:40 2013 -0500 summary: merge files: Lib/test/test_functools.py | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -809,6 +809,31 @@ self.assertEqual(fib.cache_info(), functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + def test_need_for_rlock(self): + # This will deadlock on an LRU cache that uses a regular lock + + @functools.lru_cache(maxsize=10) + def test_func(x): + 'Used to demonstrate a reentrant lru_cache call within a single thread' + return x + + class DoubleEq: + 'Demonstrate a reentrant lru_cache call within a single thread' + def __init__(self, x): + self.x = x + def __hash__(self): + return self.x + def __eq__(self, other): + if self.x == 2: + test_func(DoubleEq(1)) + return self.x == other.x + + test_func(DoubleEq(1)) # Load the cache + test_func(DoubleEq(2)) # Load the cache + self.assertEqual(test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call + DoubleEq(2)) # Verify the correct return value + + def test_main(verbose=None): test_classes = ( TestPartialC, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 09:54:56 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 09:54:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_other_re-e?= =?utf-8?q?ntrancy_nits_for_the_lru=5Fcache=2E?= Message-ID: <3ZKFRh0VFZzQrN@mail.python.org> http://hg.python.org/cpython/rev/4b06fd08b78c changeset: 82468:4b06fd08b78c branch: 3.3 parent: 82466:f27eaeffc4c0 user: Raymond Hettinger date: Mon Mar 04 03:34:09 2013 -0500 summary: Fix other re-entrancy nits for the lru_cache. Keep references for oldkey and oldvalue so they can't trigger a __del__ method to reenter our thread. Move the cache[key]=link step to the end, after the link data is in a consistent state. Under exotic circumstances, the cache[key]=link step could trigger reentrancy (i.e. the key would have to have a hash exactly equal to that for another key in the cache and the key would need a __eq__ method that makes a reentrant call our cached function). files: Lib/functools.py | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -267,19 +267,23 @@ # computed result and update the count of misses. pass elif full: - # use root to store the new key and result - root[KEY] = key - root[RESULT] = result - cache[key] = root + # use the old root to store the new key and result + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result # empty the oldest link and make it the new root - root = root[NEXT] - del cache[root[KEY]] + root = oldroot[NEXT] + oldkey = root[KEY] + oldvalue = root[RESULT] root[KEY] = root[RESULT] = None + # now update the cache dictionary for the new links + del cache[oldkey] + cache[key] = oldroot else: # put result in a new link at the front of the queue last = root[PREV] link = [last, root, key, result] - cache[key] = last[NEXT] = root[PREV] = link + last[NEXT] = root[PREV] = cache[key] = link currsize += 1 full = (currsize == maxsize) misses += 1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 09:54:57 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 09:54:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZKFRj33TmzRvh@mail.python.org> http://hg.python.org/cpython/rev/c761011eb02c changeset: 82469:c761011eb02c parent: 82467:af1961e38ccb parent: 82468:4b06fd08b78c user: Raymond Hettinger date: Mon Mar 04 03:54:45 2013 -0500 summary: merge files: Lib/functools.py | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -291,19 +291,23 @@ # computed result and update the count of misses. pass elif full: - # use root to store the new key and result - root[KEY] = key - root[RESULT] = result - cache[key] = root + # use the old root to store the new key and result + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result # empty the oldest link and make it the new root - root = root[NEXT] - del cache[root[KEY]] + root = oldroot[NEXT] + oldkey = root[KEY] + oldvalue = root[RESULT] root[KEY] = root[RESULT] = None + # now update the cache dictionary for the new links + del cache[oldkey] + cache[key] = oldroot else: # put result in a new link at the front of the queue last = root[PREV] link = [last, root, key, result] - cache[key] = last[NEXT] = root[PREV] = link + last[NEXT] = root[PREV] = cache[key] = link full = (len(cache) == maxsize) misses += 1 return result -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 10:20:57 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 10:20:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQW5vdGhlciBuaXQu?= Message-ID: <3ZKG1j2YBxz7LkK@mail.python.org> http://hg.python.org/cpython/rev/052b90daf8b9 changeset: 82470:052b90daf8b9 branch: 3.3 parent: 82468:4b06fd08b78c user: Raymond Hettinger date: Mon Mar 04 04:19:09 2013 -0500 summary: Another nit. files: Lib/functools.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -285,7 +285,7 @@ link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link currsize += 1 - full = (currsize == maxsize) + full = (currsize >= maxsize) misses += 1 return result -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 10:20:58 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Mar 2013 10:20:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZKG1k55Qgz7Lkj@mail.python.org> http://hg.python.org/cpython/rev/244a721edf3a changeset: 82471:244a721edf3a parent: 82469:c761011eb02c parent: 82470:052b90daf8b9 user: Raymond Hettinger date: Mon Mar 04 04:20:46 2013 -0500 summary: Merge files: Lib/functools.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -308,7 +308,7 @@ last = root[PREV] link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) == maxsize) + full = (len(cache) >= maxsize) misses += 1 return result -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 14:23:26 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Mar 2013 14:23:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzQ2OiBtYWtl?= =?utf-8?q?_sure_pickle_tests_are_run_against_all_protocols=2E__Initial_pa?= =?utf-8?q?tch_by?= Message-ID: <3ZKMPV6Fc5zRw4@mail.python.org> http://hg.python.org/cpython/rev/a982feb29584 changeset: 82472:a982feb29584 branch: 3.2 parent: 82462:fa24c1382bd3 user: Ezio Melotti date: Mon Mar 04 15:17:56 2013 +0200 summary: #17346: make sure pickle tests are run against all protocols. Initial patch by Marius Gedminas. files: Lib/test/pickletester.py | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -577,10 +577,10 @@ i = C() i.attr = i for proto in protocols: - s = self.dumps(i, 2) + s = self.dumps(i, proto) x = self.loads(s) self.assertEqual(dir(x), dir(i)) - self.assertTrue(x.attr is x) + self.assertIs(x.attr, x) def test_recursive_multi(self): l = [] @@ -637,13 +637,13 @@ def test_bytes(self): for proto in protocols: for s in b'', b'xyz', b'xyz'*100: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i, i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) def test_ints(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 14:23:28 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Mar 2013 14:23:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317346=3A_merge_with_3=2E2=2E?= Message-ID: <3ZKMPX1jYJz7LkD@mail.python.org> http://hg.python.org/cpython/rev/796de4f7df07 changeset: 82473:796de4f7df07 branch: 3.3 parent: 82470:052b90daf8b9 parent: 82472:a982feb29584 user: Ezio Melotti date: Mon Mar 04 15:19:02 2013 +0200 summary: #17346: merge with 3.2. files: Lib/test/pickletester.py | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -578,10 +578,10 @@ i = C() i.attr = i for proto in protocols: - s = self.dumps(i, 2) + s = self.dumps(i, proto) x = self.loads(s) self.assertEqual(dir(x), dir(i)) - self.assertTrue(x.attr is x) + self.assertIs(x.attr, x) def test_recursive_multi(self): l = [] @@ -638,13 +638,13 @@ def test_bytes(self): for proto in protocols: for s in b'', b'xyz', b'xyz'*100: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i, i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) def test_ints(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 14:23:29 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Mar 2013 14:23:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzQ2OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZKMPY4gkCzSsc@mail.python.org> http://hg.python.org/cpython/rev/5c8a5cfe25b0 changeset: 82474:5c8a5cfe25b0 parent: 82471:244a721edf3a parent: 82473:796de4f7df07 user: Ezio Melotti date: Mon Mar 04 15:21:14 2013 +0200 summary: #17346: merge with 3.3. files: Lib/test/pickletester.py | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -578,10 +578,10 @@ i = C() i.attr = i for proto in protocols: - s = self.dumps(i, 2) + s = self.dumps(i, proto) x = self.loads(s) self.assertEqual(dir(x), dir(i)) - self.assertTrue(x.attr is x) + self.assertIs(x.attr, x) def test_recursive_multi(self): l = [] @@ -638,13 +638,13 @@ def test_bytes(self): for proto in protocols: for s in b'', b'xyz', b'xyz'*100: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) for s in [bytes([i, i]) for i in range(256)]: - p = self.dumps(s) + p = self.dumps(s, proto) self.assertEqual(self.loads(p), s) def test_ints(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 14:23:31 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Mar 2013 14:23:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3MzQ2OiBtYWtl?= =?utf-8?q?_sure_pickle_tests_are_run_against_all_protocols=2E?= Message-ID: <3ZKMPb0DbdzRw4@mail.python.org> http://hg.python.org/cpython/rev/654136546895 changeset: 82475:654136546895 branch: 2.7 parent: 82458:0e41c4466d58 user: Ezio Melotti date: Mon Mar 04 15:23:12 2013 +0200 summary: #17346: make sure pickle tests are run against all protocols. files: Lib/test/pickletester.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -503,10 +503,10 @@ i = C() i.attr = i for proto in protocols: - s = self.dumps(i, 2) + s = self.dumps(i, proto) x = self.loads(s) self.assertEqual(dir(x), dir(i)) - self.assertTrue(x.attr is x) + self.assertIs(x.attr, x) def test_recursive_multi(self): l = [] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 15:48:39 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 4 Mar 2013 15:48:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_fix_possible_s?= =?utf-8?q?etdefault_refleak_=28closes_=2317328=29?= Message-ID: <3ZKPHq2NJDzQmx@mail.python.org> http://hg.python.org/cpython/rev/1a589001d752 changeset: 82476:1a589001d752 branch: 3.3 parent: 82473:796de4f7df07 user: Benjamin Peterson date: Mon Mar 04 09:47:50 2013 -0500 summary: fix possible setdefault refleak (closes #17328) files: Misc/NEWS | 2 ++ Objects/dictobject.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Issue #17328: Fix possible refleak in dict.setdefault. + - Issue #17223: array module: Fix a crasher when converting an array containing invalid characters (outside range [U+0000; U+10ffff]) to Unicode: repr(array), str(array) and array.tounicode(). Patch written by Manuel Jacob. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2230,14 +2230,14 @@ return NULL; val = *value_addr; if (val == NULL) { - Py_INCREF(failobj); - Py_INCREF(key); if (mp->ma_keys->dk_usable <= 0) { /* Need to resize. */ if (insertion_resize(mp) < 0) return NULL; ep = find_empty_slot(mp, key, hash, &value_addr); } + Py_INCREF(failobj); + Py_INCREF(key); MAINTAIN_TRACKING(mp, key, failobj); ep->me_key = key; ep->me_hash = hash; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 15:48:40 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 4 Mar 2013 15:48:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMTczMjgp?= Message-ID: <3ZKPHr571wzRVF@mail.python.org> http://hg.python.org/cpython/rev/fac46cf6af3f changeset: 82477:fac46cf6af3f parent: 82474:5c8a5cfe25b0 parent: 82476:1a589001d752 user: Benjamin Peterson date: Mon Mar 04 09:48:30 2013 -0500 summary: merge 3.3 (#17328) files: Misc/NEWS | 2 ++ Objects/dictobject.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. +- Issue #17328: Fix possible refleak in dict.setdefault. + - Issue #17223: array module: Fix a crasher when converting an array containing invalid characters (outside range [U+0000; U+10ffff]) to Unicode: repr(array), str(array) and array.tounicode(). Patch written by Manuel Jacob. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2235,14 +2235,14 @@ return NULL; val = *value_addr; if (val == NULL) { - Py_INCREF(failobj); - Py_INCREF(key); if (mp->ma_keys->dk_usable <= 0) { /* Need to resize. */ if (insertion_resize(mp) < 0) return NULL; ep = find_empty_slot(mp, key, hash, &value_addr); } + Py_INCREF(failobj); + Py_INCREF(key); MAINTAIN_TRACKING(mp, key, failobj); ep->me_key = key; ep->me_hash = hash; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 16:55:11 2013 From: python-checkins at python.org (nick.coghlan) Date: Mon, 4 Mar 2013 16:55:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Revised_PEP_422=2C_now_with_t?= =?utf-8?q?he_namespace_setting?= Message-ID: <3ZKQmb1dcGzQK1@mail.python.org> http://hg.python.org/peps/rev/37881876ca6f changeset: 4780:37881876ca6f user: Nick Coghlan date: Tue Mar 05 01:54:19 2013 +1000 summary: Revised PEP 422, now with the namespace setting This revealed an interesting conflict between the use of __prepare__ to share a namespace between two different class instances, and the assumption in the cache invalidation for type attribute lookup thatthe class fully controls the contents of the underlying namespace. files: pep-0422.txt | 305 +++++++++++++++++++------------------- 1 files changed, 151 insertions(+), 154 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -1,5 +1,5 @@ PEP: 422 -Title: Simple class initialisation hook +Title: Simpler customisation of class creation Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan , @@ -9,30 +9,34 @@ Content-Type: text/x-rst Created: 5-Jun-2012 Python-Version: 3.4 -Post-History: 5-Jun-2012, 10-Feb-2012 +Post-History: 5-Jun-2012, 10-Feb-2013 Abstract ======== -In Python 2, the body of a class definition could modify the way a class -was created (or simply arrange to run other code after the class was created) -by setting the ``__metaclass__`` attribute in the class body. While doing -this implicitly from called code required the use of an implementation detail -(specifically, ``sys._getframes()``), it could also be done explicitly in a -fully supported fashion (for example, by passing ``locals()`` to a -function that calculated a suitable ``__metaclass__`` value) +Currently, customising class creation requires the use of a custom metaclass. +This custom metaclass then persists for the entire lifecycle of the class, +creating the potential for spurious metaclass conflicts. -There is currently no corresponding mechanism in Python 3 that allows the -code executed in the class body to directly influence how the class object -is created. Instead, the class creation process is fully defined by the -class header, before the class body even begins executing. +This PEP proposes to instead support a wide range of customisation +scenarios through a new ``namespace`` parameter in the class header, and +a new ``__init_class__`` hook in the class body. -This PEP proposes a mechanism that will once again allow the body of a -class definition to more directly influence the way a class is created -(albeit in a more constrained fashion), as well as replacing some current -uses of metaclasses with a simpler, easier to understand alternative. +The new mechanism is also much easier to understand and use than +implementing a custom metaclass, and thus should provide a gentler +introduction to the full power Python's metaclass machinery. +.. note:: + + This PEP, in particular the use of __prepare__ to share a single + namespace amongst multiple class objects, highlights a possible issue + with the attribute lookup caching: when the underlying mapping is updated + by other means, the attribute lookup cache is not invalidated correctly. + Since the optimisation provided by that cache is highly desirable, + some of the ideas in this PEP may need to be declared as officially + unsupported (since the observed behaviour is rather odd when the + caches get out of sync). Background ========== @@ -81,25 +85,32 @@ name had not yet been bound in the containing scope), similarly, Python 3 metaclasses cannot call methods that rely on the implicit ``__class__`` reference (as it is not populated until after the metaclass has returned -control to the class creation machiner). +control to the class creation machinery). + +Finally, when a class uses a custom metaclass, it can pose additional +challenges to the use of multiple inheritance, as a new class cannot +inherit from parent classes with unrelated metaclasses. This means that +it is impossible to add a metaclass to an already published class: such +an addition is a backwards incompatible change due to the risk of metaclass +conflicts. Proposal ======== -This PEP proposes that a mechanism be added to Python 3 that meets the -following criteria: +This PEP proposes that a new mechanism to customise class creation be +added to Python 3.4 that meets the following criteria: -1. Restores the ability for class namespaces to have some influence on the +1. Integrates nicely with class inheritance structures (including mixins and + multiple inheritance) +2. Integrates nicely with the implicit ``__class__`` reference and + zero-argument ``super()`` syntax introduced by PEP 3135 +3. Can be added to an existing base class without a significant risk of + introducing backwards compatibility problems +4. Restores the ability for class namespaces to have some influence on the class creation process (above and beyond populating the namespace itself), but potentially without the full flexibility of the Python 2 style ``__metaclass__`` hook -2. Integrates nicely with class inheritance structures (including mixins and - multiple inheritance) -3. Integrates nicely with the implicit ``__class__`` reference and - zero-argument ``super()`` syntax introduced by PEP 3135 -4. Can be added to an existing base class without a significant risk of - introducing backwards compatibility problems One mechanism that can achieve this goal is to add a new class initialisation hook, modelled directly on the existing instance @@ -110,7 +121,6 @@ class initialisation hook as follows:: class Example: - @classmethod def __init_class__(cls): # This is invoked after the class is created, but before any # explicit decorators are called @@ -121,13 +131,15 @@ If present on the created object, this new hook will be called by the class creation machinery *after* the ``__class__`` reference has been initialised. For ``types.new_class()``, it will be called as the last step before -returning the created class object. +returning the created class object. ``__init_class__`` is implicitly +converted to a class method when the class is created (prior to the hook +being invoked). If a metaclass wishes to block class initialisation for some reason, it must arrange for ``cls.__init_class__`` to trigger ``AttributeError``. Note, that when ``__init_class__`` is called, the name of the class is not -bound to the new class object yet. As a consequence, the two argument form +yet bound to the new class object. As a consequence, the two argument form of ``super()`` cannot be used to call methods (e.g., ``super(Example, cls)`` wouldn't work in the example above). However, the zero argument form of ``super()`` works as expected, since the ``__class__`` reference is already @@ -139,19 +151,31 @@ but the situation has changed sufficiently in recent years that the idea is worth reconsidering. +However, the introduction of the metaclass ``__prepare__`` method in PEP +3115 allows a further enhancement that was not possible in Python 2: this +PEP also proposes that ``type.__prepare__`` be updated to accept a +``namespace`` keyword-only argument. If present, the value provided as the +``namespace`` argument will be returned from ``type.__prepare__`` instead of +a freshly created dictionary instance. For example, the following will use +the ordered dictionary created in the header as the class namespace:: + + class OrderedExample(namespace=collections.OrderedDict()): + def __init_class__(cls): + # cls.__dict__ is still a read-only proxy to the class namespace, + # but the underlying storage is the OrderedDict instance + Key Benefits ============ -Replaces many use cases for dynamic setting of ``__metaclass__`` ------------------------------------------------------------------ +Easier use of custom namespaces for a class +------------------------------------------- -For use cases that don't involve completely replacing the defined class, -Python 2 code that dynamically set ``__metaclass__`` can now dynamically -set ``__init_class__`` instead. For more advanced use cases, introduction of -an explicit metaclass (possibly made available as a required base class) will -still be necessary in order to support Python 3. +Currently, to use a different type (such as ``collections.OrderedDict``) for +a class namespace, or to use a pre-populated namespace, it is necessary to +write and use a custom metaclass. With this PEP, using a custom namespace +becomes as simple as specifying it in the class header. Easier inheritance of definition time behaviour @@ -201,137 +225,89 @@ that use the zero argument form of ``super()``. -Alternatives -============ +Replaces many use cases for dynamic setting of ``__metaclass__`` +----------------------------------------------------------------- +For use cases that don't involve completely replacing the defined class, +Python 2 code that dynamically set ``__metaclass__`` can now dynamically +set ``__init_class__`` instead. For more advanced use cases, introduction of +an explicit metaclass (possibly made available as a required base class) will +still be necessary in order to support Python 3. -The Python 3 Status Quo + +New Ways of Using Classes +========================= + +The new ``namespace`` keyword in the class header enables a number of +interesting options for controlling the way a class is initialised, +including some aspects of the object models of both Javascript and Ruby. + +All of the examples below are actually possible today through the use of a +custom metaclass:: + + class CustomNamespace(type): + @classmethod + def __prepare__(meta, name, bases, *, namespace=None, **kwds): + parent_namespace = super().__prepare__(name, bases, **kwds) + return namespace if namespace is not None else parent_namespace + + def __new__(meta, name, bases, ns, *, namespace=None, **kwds): + return super().__new__(meta, name, bases, ns, **kwds) + + def __init__(cls, name, bases, ns, *, namespace=None, **kwds): + return super().__init__(name, bases, ns, **kwds) + +The advantage of implementing the new keyword directly in +``type.__prepare__`` is that the *only* persistent effect is +the change in the underlying storage of the class attributes. The metaclass +of the class remains unchanged, eliminating many of the drawbacks +typically associated with these kinds of customisations. + + +Order preserving classes +------------------------ + +:: + class OrderedClass(namespace=collections.OrderedDict()): + a = 1 + b = 2 + c = 3 + + +Prepopulated namespaces ----------------------- -The Python 3 status quo already offers a great deal of flexibility. For -changes which only affect a single class definition and which can be -specified at the time the code is written, then class decorators can be -used to modify a class explicitly. Class decorators largely ignore class -inheritance and can make full use of methods that rely on the ``__class__`` -reference being populated. +:: + seed_data = dict(a=1, b=2, c=3) + class PrepopulatedClass(namespace=seed_data.copy()): + pass -Using a custom metaclass provides the same level of power as it did in -Python 2. However, it's notable that, unlike class decorators, a metaclass -cannot call any methods that rely on the ``__class__`` reference, as that -reference is not populated until after the metaclass constructor returns -control to the class creation code. -One major use case for metaclasses actually closely resembles the use of -class decorators. It occurs whenever a metaclass has an implementation that -uses the following pattern:: +Cloning a prototype class +------------------------- - class Metaclass(type): - def __new__(meta, *args, **kwds): - cls = super(Metaclass, meta).__new__(meta, *args, **kwds) - # Do something with cls - return cls +:: + class NewClass(namespace=Prototype.__dict__.copy()): + pass -The key difference between this pattern and a class decorator is that it -is automatically inherited by subclasses. However, it also comes with a -major disadvantage: Python does not allow you to inherit from classes with -unrelated metaclasses. -Thus, the status quo requires that developers choose between the following -two alternatives: +Defining an extensible class +---------------------------- -* Use a class decorator, meaning that behaviour is not inherited and must be - requested explicitly on every subclass -* Use a metaclass, meaning that behaviour is inherited, but metaclass - conflicts may make integration with other libraries and frameworks more - difficult than it otherwise would be +:: + class Extensible: + namespace = locals() -If this PEP is ultimately rejected, then this is the existing design that -will remain in place by default. + class ExtendingClass(namespace=Extensible.namespace): + pass -Restoring the Python 2 metaclass hook -------------------------------------- +Rejected Design Options +======================= -One simple alternative would be to restore support for a Python 2 style -``metaclass`` hook in the class body. This would be checked after the class -body was executed, potentially overwriting the metaclass hint provided in the -class header. -The main attraction of such an approach is that it would simplify porting -Python 2 applications that make use of this hook (especially those that do -so dynamically). - -However, this approach does nothing to simplify the process of adding -*inherited* class definition time behaviour, nor does it interoperate -cleanly with the PEP 3135 ``__class__`` and ``super()`` semantics (as with -any metaclass based solution, the ``__metaclass__`` hook would have to run -before the ``__class__`` reference has been populated. - - -Dynamic class decorators ------------------------- - -The original version of this PEP was called "Dynamic class decorators" and -focused solely on a significantly more complicated proposal than that -presented in the current version. - -As with the current version, it proposed that a new step be added to the -class creation process, after the metaclass invocation to construct the -class instance and before the application of lexical decorators. However, -instead of a simple process of calling a single class method that relies -on normal inheritance mechanisms, it proposed a far more complicated -procedure that walked the class MRO looking for decorators stored in -iterable ``__decorators__`` attributes. - -Using the current version of the PEP, the scheme originally proposed could -be implemented as:: - - class DynamicDecorators(Base): - @classmethod - def __init_class__(cls): - # Process any classes later in the MRO - try: - mro_chain = super().__init_class__ - except AttributeError: - pass - else: - mro_chain() - # Process any __decorators__ attributes in the MRO - for entry in reversed(cls.mro()): - decorators = entry.__dict__.get("__decorators__", ()) - for deco in reversed(decorators): - cls = deco(cls) - -Any subclasses of ``DynamicDecorators`` would then automatically have the -contents of any ``__decorators__`` attributes processed and invoked. - -The mechanism in the current PEP is considered superior, as many issues -to do with ordering and the same decorator being invoked multiple times -just go away, as that kind of thing is taken care of through the use of an -ordinary class method invocation. - - -Automatic metaclass derivation ------------------------------- - -When no appropriate metaclass is found, it's theoretically possible to -automatically derive a metaclass for a new type based on the metaclass hint -and the metaclasses of the bases. - -While adding such a mechanism would reduce the risk of spurious metaclass -conflicts, it would do nothing to improve integration with PEP 3135, would -not help with porting Python 2 code that set ``__metaclass__`` dynamically -and would not provide a more straightforward inherited mechanism for invoking -additional operations after the class invocation is complete. - -In addition, there would still be a risk of metaclass conflicts in cases -where the base metaclasses were not written with multiple inheritance in -mind. In such situations, there's a chance of introducing latent defects -if one or more metaclasses are not invoked correctly. - - -Calling the new hook from ``type.__init__`` -------------------------------------------- +Calling ``__init_class__`` from ``type.__init__`` +------------------------------------------------- Calling the new hook automatically from ``type.__init__``, would achieve most of the goals of this PEP. However, using that approach would mean that @@ -340,11 +316,32 @@ ``super()``), and could not make use of those features themselves. +Requiring an explict decorator on ``__init_class__`` +---------------------------------------------------- + +Originally, this PEP required the explicit use of ``@classmethod`` on the +``__init_class__`` decorator. It was made implicit since there's no +sensible interpretation for leaving it out, and that case would need to be +detected anyway in order to give a useful error message. + +This decision was reinforced after noticing that the user experience of +defining ``__prepare__`` and forgetting the ``@classmethod`` method +decorator is singularly incomprehensible (particularly since PEP 3115 +documents it as an ordinary method, and the current documentation doesn't +explicitly say anything one way or the other). + + Reference Implementation ======================== -The reference implementation has been posted to the `issue tracker`_. +A reference implementation for __init_class__ has been posted to the +`issue tracker`_. It does not yet include the new ``namespace`` parameter +for ``type.__prepare__``. +TODO +==== + +* address the 5 points in http://mail.python.org/pipermail/python-dev/2013-February/123970.html References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Mar 4 16:58:02 2013 From: python-checkins at python.org (nick.coghlan) Date: Mon, 4 Mar 2013 16:58:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_markup?= Message-ID: <3ZKQqt35ZFzQK1@mail.python.org> http://hg.python.org/peps/rev/63b87a7d9832 changeset: 4781:63b87a7d9832 user: Nick Coghlan date: Tue Mar 05 01:57:51 2013 +1000 summary: Fix markup files: pep-0422.txt | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -268,6 +268,7 @@ ------------------------ :: + class OrderedClass(namespace=collections.OrderedDict()): a = 1 b = 2 @@ -278,6 +279,7 @@ ----------------------- :: + seed_data = dict(a=1, b=2, c=3) class PrepopulatedClass(namespace=seed_data.copy()): pass @@ -287,6 +289,7 @@ ------------------------- :: + class NewClass(namespace=Prototype.__dict__.copy()): pass @@ -295,6 +298,7 @@ ---------------------------- :: + class Extensible: namespace = locals() -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Mar 4 20:33:55 2013 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 4 Mar 2013 20:33:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Mjc4?= =?utf-8?q?=3A_Fix_a_crash_in_heapq=2Eheappush=28=29_and_heapq=2Eheappop?= =?utf-8?q?=28=29_when_the_list?= Message-ID: <3ZKWcz6PrCzQvf@mail.python.org> http://hg.python.org/cpython/rev/21ded74b51fa changeset: 82478:21ded74b51fa branch: 2.7 parent: 82475:654136546895 user: Antoine Pitrou date: Mon Mar 04 20:30:01 2013 +0100 summary: Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. files: Lib/test/test_heapq.py | 26 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_heapqmodule.c | 40 +++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -315,6 +315,16 @@ 'Test multiple tiers of iterators' return chain(imap(lambda x:x, R(Ig(G(seqn))))) +class SideEffectLT: + def __init__(self, value, heap): + self.value = value + self.heap = heap + + def __lt__(self, other): + self.heap[:] = [] + return self.value < other.value + + class TestErrorHandling(TestCase): module = None @@ -361,6 +371,22 @@ self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + # Issue #17278: the heap may change size while it's being walked. + + def test_heappush_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappush(heap, SideEffectLT(5, heap)) + + def test_heappop_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappop(heap) + class TestErrorHandlingPython(TestErrorHandling): module = py_heapq diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,6 +214,9 @@ Library ------- +- Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when + the list is being resized concurrently. + - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. - Issue #14720: sqlite3: Convert datetime microseconds correctly. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -35,12 +35,14 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, *olditem; int cmp; Py_ssize_t parentpos; + Py_ssize_t size; assert(PyList_Check(heap)); - if (pos >= PyList_GET_SIZE(heap)) { + size = PyList_GET_SIZE(heap); + if (pos >= size) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } @@ -57,12 +59,24 @@ Py_DECREF(newitem); return -1; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } if (cmp == 0) break; Py_INCREF(parent); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, parent); + Py_DECREF(olditem); pos = parentpos; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -74,10 +88,12 @@ { Py_ssize_t startpos, endpos, childpos, rightpos; int cmp; - PyObject *newitem, *tmp; + PyObject *newitem, *tmp, *olditem; + Py_ssize_t size; assert(PyList_Check(heap)); - endpos = PyList_GET_SIZE(heap); + size = PyList_GET_SIZE(heap); + endpos = size; startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); @@ -102,13 +118,25 @@ if (cmp == 0) childpos = rightpos; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } /* Move the smaller child up. */ tmp = PyList_GET_ITEM(heap, childpos); Py_INCREF(tmp); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, tmp); + Py_DECREF(olditem); pos = childpos; childpos = 2*pos + 1; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } /* The leaf at pos is empty now. Put newitem there, and and bubble -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 20:39:47 2013 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 4 Mar 2013 20:39:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3Mjc4?= =?utf-8?q?=3A_Fix_a_crash_in_heapq=2Eheappush=28=29_and_heapq=2Eheappop?= =?utf-8?q?=28=29_when_the_list?= Message-ID: <3ZKWll0ngYzRJy@mail.python.org> http://hg.python.org/cpython/rev/905b02749c26 changeset: 82479:905b02749c26 branch: 3.2 parent: 82472:a982feb29584 user: Antoine Pitrou date: Mon Mar 04 20:30:01 2013 +0100 summary: Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. files: Lib/test/test_heapq.py | 26 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_heapqmodule.c | 40 +++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -319,6 +319,16 @@ return chain(map(lambda x:x, R(Ig(G(seqn))))) +class SideEffectLT: + def __init__(self, value, heap): + self.value = value + self.heap = heap + + def __lt__(self, other): + self.heap[:] = [] + return self.value < other.value + + class TestErrorHandling(TestCase): module = None @@ -370,6 +380,22 @@ self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + # Issue #17278: the heap may change size while it's being walked. + + def test_heappush_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappush(heap, SideEffectLT(5, heap)) + + def test_heappop_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappop(heap) + class TestErrorHandlingPython(TestErrorHandling): module = py_heapq diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,9 @@ Library ------- +- Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when + the list is being resized concurrently. + - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. - Issue #14720: sqlite3: Convert datetime microseconds correctly. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -11,12 +11,14 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, *olditem; int cmp; Py_ssize_t parentpos; + Py_ssize_t size; assert(PyList_Check(heap)); - if (pos >= PyList_GET_SIZE(heap)) { + size = PyList_GET_SIZE(heap); + if (pos >= size) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } @@ -33,12 +35,24 @@ Py_DECREF(newitem); return -1; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } if (cmp == 0) break; Py_INCREF(parent); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, parent); + Py_DECREF(olditem); pos = parentpos; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -50,10 +64,12 @@ { Py_ssize_t startpos, endpos, childpos, rightpos; int cmp; - PyObject *newitem, *tmp; + PyObject *newitem, *tmp, *olditem; + Py_ssize_t size; assert(PyList_Check(heap)); - endpos = PyList_GET_SIZE(heap); + size = PyList_GET_SIZE(heap); + endpos = size; startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); @@ -79,13 +95,25 @@ if (cmp == 0) childpos = rightpos; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } /* Move the smaller child up. */ tmp = PyList_GET_ITEM(heap, childpos); Py_INCREF(tmp); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, tmp); + Py_DECREF(olditem); pos = childpos; childpos = 2*pos + 1; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } /* The leaf at pos is empty now. Put newitem there, and and bubble -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 20:39:48 2013 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 4 Mar 2013 20:39:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2317278=3A_Fix_a_crash_in_heapq=2Eheappush=28=29_and_he?= =?utf-8?q?apq=2Eheappop=28=29_when_the_list?= Message-ID: <3ZKWlm4lqwzSc2@mail.python.org> http://hg.python.org/cpython/rev/451299b97b4f changeset: 82480:451299b97b4f branch: 3.3 parent: 82476:1a589001d752 parent: 82479:905b02749c26 user: Antoine Pitrou date: Mon Mar 04 20:33:36 2013 +0100 summary: Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. files: Lib/test/test_heapq.py | 26 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_heapqmodule.c | 40 +++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -319,6 +319,16 @@ return chain(map(lambda x:x, R(Ig(G(seqn))))) +class SideEffectLT: + def __init__(self, value, heap): + self.value = value + self.heap = heap + + def __lt__(self, other): + self.heap[:] = [] + return self.value < other.value + + class TestErrorHandling: def test_non_sequence(self): @@ -369,6 +379,22 @@ self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + # Issue #17278: the heap may change size while it's being walked. + + def test_heappush_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappush(heap, SideEffectLT(5, heap)) + + def test_heappop_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappop(heap) + class TestErrorHandlingPython(TestErrorHandling, TestCase): module = py_heapq diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,9 @@ Library ------- +- Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when + the list is being resized concurrently. + - Issue #16962: Use getdents64 instead of the obsolete getdents syscall in the subprocess module on Linux. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -11,12 +11,14 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, *olditem; int cmp; Py_ssize_t parentpos; + Py_ssize_t size; assert(PyList_Check(heap)); - if (pos >= PyList_GET_SIZE(heap)) { + size = PyList_GET_SIZE(heap); + if (pos >= size) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } @@ -33,12 +35,24 @@ Py_DECREF(newitem); return -1; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } if (cmp == 0) break; Py_INCREF(parent); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, parent); + Py_DECREF(olditem); pos = parentpos; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -50,10 +64,12 @@ { Py_ssize_t startpos, endpos, childpos, rightpos; int cmp; - PyObject *newitem, *tmp; + PyObject *newitem, *tmp, *olditem; + Py_ssize_t size; assert(PyList_Check(heap)); - endpos = PyList_GET_SIZE(heap); + size = PyList_GET_SIZE(heap); + endpos = size; startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); @@ -79,13 +95,25 @@ if (cmp == 0) childpos = rightpos; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } /* Move the smaller child up. */ tmp = PyList_GET_ITEM(heap, childpos); Py_INCREF(tmp); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, tmp); + Py_DECREF(olditem); pos = childpos; childpos = 2*pos + 1; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } /* The leaf at pos is empty now. Put newitem there, and and bubble -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 20:39:50 2013 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 4 Mar 2013 20:39:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2317278=3A_Fix_a_crash_in_heapq=2Eheappush=28=29_?= =?utf-8?q?and_heapq=2Eheappop=28=29_when_the_list?= Message-ID: <3ZKWlp25fQzSgw@mail.python.org> http://hg.python.org/cpython/rev/d57c60db94e7 changeset: 82481:d57c60db94e7 parent: 82477:fac46cf6af3f parent: 82480:451299b97b4f user: Antoine Pitrou date: Mon Mar 04 20:35:55 2013 +0100 summary: Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. files: Lib/test/test_heapq.py | 26 +++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_heapqmodule.c | 40 +++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -319,6 +319,16 @@ return chain(map(lambda x:x, R(Ig(G(seqn))))) +class SideEffectLT: + def __init__(self, value, heap): + self.value = value + self.heap = heap + + def __lt__(self, other): + self.heap[:] = [] + return self.value < other.value + + class TestErrorHandling: def test_non_sequence(self): @@ -369,6 +379,22 @@ self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + # Issue #17278: the heap may change size while it's being walked. + + def test_heappush_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappush(heap, SideEffectLT(5, heap)) + + def test_heappop_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappop(heap) + class TestErrorHandlingPython(TestErrorHandling, TestCase): module = py_heapq diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -275,6 +275,9 @@ Library ------- +- Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when + the list is being resized concurrently. + - Issue #16962: Use getdents64 instead of the obsolete getdents syscall in the subprocess module on Linux. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -11,12 +11,14 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, *olditem; int cmp; Py_ssize_t parentpos; + Py_ssize_t size; assert(PyList_Check(heap)); - if (pos >= PyList_GET_SIZE(heap)) { + size = PyList_GET_SIZE(heap); + if (pos >= size) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } @@ -33,12 +35,24 @@ Py_DECREF(newitem); return -1; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } if (cmp == 0) break; Py_INCREF(parent); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, parent); + Py_DECREF(olditem); pos = parentpos; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -50,10 +64,12 @@ { Py_ssize_t startpos, endpos, childpos, rightpos; int cmp; - PyObject *newitem, *tmp; + PyObject *newitem, *tmp, *olditem; + Py_ssize_t size; assert(PyList_Check(heap)); - endpos = PyList_GET_SIZE(heap); + size = PyList_GET_SIZE(heap); + endpos = size; startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); @@ -79,13 +95,25 @@ if (cmp == 0) childpos = rightpos; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } /* Move the smaller child up. */ tmp = PyList_GET_ITEM(heap, childpos); Py_INCREF(tmp); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, tmp); + Py_DECREF(olditem); pos = childpos; childpos = 2*pos + 1; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } /* The leaf at pos is empty now. Put newitem there, and and bubble -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 4 23:32:04 2013 From: python-checkins at python.org (ned.deily) Date: Mon, 4 Mar 2013 23:32:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQ4?= =?utf-8?q?=3A_python-config_now_returns_proper_--ldflags_values_for_OS_X?= Message-ID: <3ZKbZX4bgzz7Lmr@mail.python.org> http://hg.python.org/cpython/rev/bab708624dc4 changeset: 82482:bab708624dc4 branch: 2.7 parent: 82478:21ded74b51fa user: Ned Deily date: Mon Mar 04 14:31:04 2013 -0800 summary: Issue #16848: python-config now returns proper --ldflags values for OS X framework builds. files: Misc/NEWS | 3 +++ Misc/python-config.in | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -923,6 +923,9 @@ - Issue #17161: make install now also installs a python2 and python man page. +- Issue #16848: python-config now returns proper --ldflags values for OS X + framework builds. + Tools/Demos ----------- diff --git a/Misc/python-config.in b/Misc/python-config.in --- a/Misc/python-config.in +++ b/Misc/python-config.in @@ -51,6 +51,7 @@ if opt == '--ldflags': if not getvar('Py_ENABLE_SHARED'): libs.insert(0, '-L' + getvar('LIBPL')) - libs.extend(getvar('LINKFORSHARED').split()) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) print ' '.join(libs) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Mar 5 06:00:20 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 05 Mar 2013 06:00:20 +0100 Subject: [Python-checkins] Daily reference leaks (d57c60db94e7): sum=2 Message-ID: results for d57c60db94e7 on branch "default" -------------------------------------------- test_unittest leaked [-1, 1, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog07mUMV', '-x'] From python-checkins at python.org Tue Mar 5 07:25:30 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 07:25:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_LT_in_all_comparisons?= Message-ID: <3ZKp4p2DZNz7Lmt@mail.python.org> http://hg.python.org/cpython/rev/bc059a6d6939 changeset: 82483:bc059a6d6939 parent: 82481:d57c60db94e7 user: Raymond Hettinger date: Tue Mar 05 01:17:57 2013 -0500 summary: Use LT in all comparisons files: Lib/heapq.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -181,7 +181,7 @@ def _heappushpop_max(heap, item): """Maxheap version of a heappush followed by a heappop.""" - if heap and heap[0] > item: + if heap and item < heap[0]: item, heap[0] = heap[0], item _siftup_max(heap, 0) return item @@ -312,7 +312,7 @@ while pos > startpos: parentpos = (pos - 1) >> 1 parent = heap[parentpos] - if newitem > parent: + if parent < newitem: heap[pos] = parent pos = parentpos continue @@ -329,7 +329,7 @@ while childpos < endpos: # Set childpos to index of larger child. rightpos = childpos + 1 - if rightpos < endpos and not heap[childpos] > heap[rightpos]: + if rightpos < endpos and not heap[rightpos] < heap[childpos]: childpos = rightpos # Move the larger child up. heap[pos] = heap[childpos] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 07:49:57 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 07:49:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2MDk4?= =?utf-8?q?=3A__Update_heapq=2Ensmallest_to_use_the_same_algorithm_as_nlar?= =?utf-8?q?gest=2E?= Message-ID: <3ZKpd14tBcz7Ll4@mail.python.org> http://hg.python.org/cpython/rev/de6627cf81f4 changeset: 82484:de6627cf81f4 branch: 3.3 parent: 82480:451299b97b4f user: Raymond Hettinger date: Tue Mar 05 01:36:30 2013 -0500 summary: Issue #16098: Update heapq.nsmallest to use the same algorithm as nlargest. This removes the dependency on bisect and it bring the pure Python code in-sync with the C code. files: Lib/heapq.py | 84 ++++++++++++++++++++++++++++----------- 1 files changed, 59 insertions(+), 25 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -127,8 +127,7 @@ __all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop'] -from itertools import islice, repeat, count, tee, chain -import bisect +from itertools import islice, count, tee, chain def heappush(heap, item): """Push item onto heap, maintaining the heap invariant.""" @@ -180,6 +179,19 @@ for i in reversed(range(n//2)): _siftup(x, i) +def _heappushpop_max(heap, item): + """Maxheap version of a heappush followed by a heappop.""" + if heap and item < heap[0]: + item, heap[0] = heap[0], item + _siftup_max(heap, 0) + return item + +def _heapify_max(x): + """Transform list into a maxheap, in-place, in O(len(x)) time.""" + n = len(x) + for i in reversed(range(n//2)): + _siftup_max(x, i) + def nlargest(n, iterable): """Find the n largest elements in a dataset. @@ -205,30 +217,16 @@ """ if n < 0: return [] - if hasattr(iterable, '__len__') and n * 10 <= len(iterable): - # For smaller values of n, the bisect method is faster than a minheap. - # It is also memory efficient, consuming only n elements of space. - it = iter(iterable) - result = sorted(islice(it, 0, n)) - if not result: - return result - insort = bisect.insort - pop = result.pop - los = result[-1] # los --> Largest of the nsmallest - for elem in it: - if elem < los: - insort(result, elem) - pop() - los = result[-1] + it = iter(iterable) + result = list(islice(it, n)) + if not result: return result - # An alternative approach manifests the whole iterable in memory but - # saves comparisons by heapifying all at once. Also, saves time - # over bisect.insort() which has O(n) data movement time for every - # insertion. Finding the n smallest of an m length iterable requires - # O(m) + O(n log m) comparisons. - h = list(iterable) - heapify(h) - return list(map(heappop, repeat(h, min(n, len(h))))) + _heapify_max(result) + _heappushpop = _heappushpop_max + for elem in it: + _heappushpop(result, elem) + result.sort() + return result # 'heap' is a heap at all indices >= startpos, except possibly for pos. pos # is the index of a leaf with a possibly out-of-order value. Restore the @@ -306,6 +304,42 @@ heap[pos] = newitem _siftdown(heap, startpos, pos) +def _siftdown_max(heap, startpos, pos): + 'Maxheap variant of _siftdown' + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if parent < newitem: + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +def _siftup_max(heap, pos): + 'Minheap variant of _siftup' + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the larger child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of larger child. + rightpos = childpos + 1 + if rightpos < endpos and not heap[rightpos] < heap[childpos]: + childpos = rightpos + # Move the larger child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown_max(heap, startpos, pos) + # If available, use C implementation try: from _heapq import * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 07:49:59 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 07:49:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZKpd30fNHz7Lmg@mail.python.org> http://hg.python.org/cpython/rev/f349e03bb41f changeset: 82485:f349e03bb41f parent: 82483:bc059a6d6939 parent: 82484:de6627cf81f4 user: Raymond Hettinger date: Tue Mar 05 01:37:02 2013 -0500 summary: merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 08:12:00 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 08:12:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_typo?= Message-ID: <3ZKq6S0BH7zR11@mail.python.org> http://hg.python.org/cpython/rev/b691f25c3553 changeset: 82486:b691f25c3553 branch: 3.3 parent: 82484:de6627cf81f4 user: Raymond Hettinger date: Tue Mar 05 02:11:10 2013 -0500 summary: Fix typo files: Lib/heapq.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -320,7 +320,7 @@ heap[pos] = newitem def _siftup_max(heap, pos): - 'Minheap variant of _siftup' + 'Maxheap variant of _siftup' endpos = len(heap) startpos = pos newitem = heap[pos] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 08:12:01 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 08:12:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZKq6T34JPz7Lmy@mail.python.org> http://hg.python.org/cpython/rev/f23814bab066 changeset: 82487:f23814bab066 parent: 82485:f349e03bb41f parent: 82486:b691f25c3553 user: Raymond Hettinger date: Tue Mar 05 02:11:37 2013 -0500 summary: merge files: Lib/heapq.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -320,7 +320,7 @@ heap[pos] = newitem def _siftup_max(heap, pos): - 'Minheap variant of _siftup' + 'Maxheap variant of _siftup' endpos = len(heap) startpos = pos newitem = heap[pos] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 08:21:08 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 08:21:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2MDk4?= =?utf-8?q?=3A__Update_heapq=2Ensmallest_to_use_the_same_algorithm_as_nlar?= =?utf-8?q?gest=2E?= Message-ID: <3ZKqK02LKkzT1h@mail.python.org> http://hg.python.org/cpython/rev/aa9ed98a49cb changeset: 82488:aa9ed98a49cb branch: 2.7 parent: 82430:6ae4938256c6 user: Raymond Hettinger date: Tue Mar 05 02:15:01 2013 -0500 summary: Issue #16098: Update heapq.nsmallest to use the same algorithm as nlargest. This removes the dependency on bisect and it bring the pure Python code in-sync with the C code. files: Lib/heapq.py | 84 ++++++++++++++++++++++++++++----------- 1 files changed, 59 insertions(+), 25 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -129,9 +129,8 @@ __all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop'] -from itertools import islice, repeat, count, imap, izip, tee, chain +from itertools import islice, count, imap, izip, tee, chain from operator import itemgetter -import bisect def cmp_lt(x, y): # Use __lt__ if available; otherwise, try __le__. @@ -188,6 +187,19 @@ for i in reversed(xrange(n//2)): _siftup(x, i) +def _heappushpop_max(heap, item): + """Maxheap version of a heappush followed by a heappop.""" + if heap and cmp_lt(item, heap[0]): + item, heap[0] = heap[0], item + _siftup_max(heap, 0) + return item + +def _heapify_max(x): + """Transform list into a maxheap, in-place, in O(len(x)) time.""" + n = len(x) + for i in reversed(range(n//2)): + _siftup_max(x, i) + def nlargest(n, iterable): """Find the n largest elements in a dataset. @@ -213,30 +225,16 @@ """ if n < 0: return [] - if hasattr(iterable, '__len__') and n * 10 <= len(iterable): - # For smaller values of n, the bisect method is faster than a minheap. - # It is also memory efficient, consuming only n elements of space. - it = iter(iterable) - result = sorted(islice(it, 0, n)) - if not result: - return result - insort = bisect.insort - pop = result.pop - los = result[-1] # los --> Largest of the nsmallest - for elem in it: - if cmp_lt(elem, los): - insort(result, elem) - pop() - los = result[-1] + it = iter(iterable) + result = list(islice(it, n)) + if not result: return result - # An alternative approach manifests the whole iterable in memory but - # saves comparisons by heapifying all at once. Also, saves time - # over bisect.insort() which has O(n) data movement time for every - # insertion. Finding the n smallest of an m length iterable requires - # O(m) + O(n log m) comparisons. - h = list(iterable) - heapify(h) - return map(heappop, repeat(h, min(n, len(h)))) + _heapify_max(result) + _heappushpop = _heappushpop_max + for elem in it: + _heappushpop(result, elem) + result.sort() + return result # 'heap' is a heap at all indices >= startpos, except possibly for pos. pos # is the index of a leaf with a possibly out-of-order value. Restore the @@ -314,6 +312,42 @@ heap[pos] = newitem _siftdown(heap, startpos, pos) +def _siftdown_max(heap, startpos, pos): + 'Maxheap variant of _siftdown' + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if cmp_lt(parent, newitem): + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +def _siftup_max(heap, pos): + 'Maxheap variant of _siftup' + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the larger child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of larger child. + rightpos = childpos + 1 + if rightpos < endpos and not cmp_lt(heap[rightpos], heap[childpos]): + childpos = rightpos + # Move the larger child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown_max(heap, startpos, pos) + # If available, use C implementation try: from _heapq import * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 08:21:09 2013 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 5 Mar 2013 08:21:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge?= Message-ID: <3ZKqK16qkKzT2C@mail.python.org> http://hg.python.org/cpython/rev/d4269f0b866a changeset: 82489:d4269f0b866a branch: 2.7 parent: 82488:aa9ed98a49cb parent: 82482:bab708624dc4 user: Raymond Hettinger date: Tue Mar 05 02:16:45 2013 -0500 summary: merge files: Doc/library/unittest.rst | 8 ++-- Lib/test/pickletester.py | 4 +- Lib/test/test_exceptions.py | 12 +++++++ Lib/test/test_heapq.py | 26 ++++++++++++++++ Lib/test/test_posixpath.py | 1 + Misc/NEWS | 9 +++++ Misc/python-config.in | 3 +- Modules/_heapqmodule.c | 40 +++++++++++++++++++++--- Objects/exceptions.c | 3 +- 9 files changed, 91 insertions(+), 15 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -584,7 +584,7 @@ Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` or one of its conditional variants. -Basic skipping looks like this: :: +Basic skipping looks like this:: class MyTestCase(unittest.TestCase): @@ -603,7 +603,7 @@ # windows specific testing code pass -This is the output of running the example above in verbose mode: :: +This is the output of running the example above in verbose mode:: test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' @@ -614,7 +614,7 @@ OK (skipped=3) -Classes can be skipped just like methods: :: +Classes can be skipped just like methods:: @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): @@ -633,7 +633,7 @@ It's easy to roll your own skipping decorators by making a decorator that calls :func:`skip` on the test when it wants it to be skipped. This decorator skips -the test unless the passed object has a certain attribute: :: +the test unless the passed object has a certain attribute:: def skipUnlessHasattr(obj, attr): if hasattr(obj, attr): diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -503,10 +503,10 @@ i = C() i.attr = i for proto in protocols: - s = self.dumps(i, 2) + s = self.dumps(i, proto) x = self.loads(s) self.assertEqual(dir(x), dir(i)) - self.assertTrue(x.attr is x) + self.assertIs(x.attr, x) def test_recursive_multi(self): l = [] 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 @@ -479,6 +479,18 @@ except AssertionError as e: self.assertEqual(str(e), "(3,)") + def test_bad_exception_clearing(self): + # See issue 16445: use of Py_XDECREF instead of Py_CLEAR in + # BaseException_set_message gave a possible way to segfault the + # interpreter. + class Nasty(str): + def __del__(message): + del e.message + + e = ValueError(Nasty("msg")) + e.args = () + del e.message + # Helper class used by TestSameStrAndUnicodeMsg class ExcWithOverriddenStr(Exception): diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -315,6 +315,16 @@ 'Test multiple tiers of iterators' return chain(imap(lambda x:x, R(Ig(G(seqn))))) +class SideEffectLT: + def __init__(self, value, heap): + self.value = value + self.heap = heap + + def __lt__(self, other): + self.heap[:] = [] + return self.value < other.value + + class TestErrorHandling(TestCase): module = None @@ -361,6 +371,22 @@ self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + # Issue #17278: the heap may change size while it's being walked. + + def test_heappush_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappush(heap, SideEffectLT(5, heap)) + + def test_heappop_mutating_heap(self): + heap = [] + heap.extend(SideEffectLT(i, heap) for i in range(200)) + # Python version raises IndexError, C version RuntimeError + with self.assertRaises((IndexError, RuntimeError)): + self.module.heappop(heap) + class TestErrorHandlingPython(TestErrorHandling): module = py_heapq diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -284,6 +284,7 @@ test_support.unlink(ABSTFN+"2") test_support.unlink(ABSTFN+"y") test_support.unlink(ABSTFN+"c") + test_support.unlink(ABSTFN+"a") def test_realpath_repeated_indirect_symlinks(self): # Issue #6975. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #16445: Fixed potential segmentation fault when deleting an exception + message. + - Issue #17275: Corrected class name in init error messages of the C version of BufferedWriter and BufferedRandom. @@ -211,6 +214,9 @@ Library ------- +- Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when + the list is being resized concurrently. + - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. - Issue #14720: sqlite3: Convert datetime microseconds correctly. @@ -917,6 +923,9 @@ - Issue #17161: make install now also installs a python2 and python man page. +- Issue #16848: python-config now returns proper --ldflags values for OS X + framework builds. + Tools/Demos ----------- diff --git a/Misc/python-config.in b/Misc/python-config.in --- a/Misc/python-config.in +++ b/Misc/python-config.in @@ -51,6 +51,7 @@ if opt == '--ldflags': if not getvar('Py_ENABLE_SHARED'): libs.insert(0, '-L' + getvar('LIBPL')) - libs.extend(getvar('LINKFORSHARED').split()) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) print ' '.join(libs) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -35,12 +35,14 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, *olditem; int cmp; Py_ssize_t parentpos; + Py_ssize_t size; assert(PyList_Check(heap)); - if (pos >= PyList_GET_SIZE(heap)) { + size = PyList_GET_SIZE(heap); + if (pos >= size) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } @@ -57,12 +59,24 @@ Py_DECREF(newitem); return -1; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } if (cmp == 0) break; Py_INCREF(parent); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, parent); + Py_DECREF(olditem); pos = parentpos; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -74,10 +88,12 @@ { Py_ssize_t startpos, endpos, childpos, rightpos; int cmp; - PyObject *newitem, *tmp; + PyObject *newitem, *tmp, *olditem; + Py_ssize_t size; assert(PyList_Check(heap)); - endpos = PyList_GET_SIZE(heap); + size = PyList_GET_SIZE(heap); + endpos = size; startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); @@ -102,13 +118,25 @@ if (cmp == 0) childpos = rightpos; } + if (size != PyList_GET_SIZE(heap)) { + Py_DECREF(newitem); + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } /* Move the smaller child up. */ tmp = PyList_GET_ITEM(heap, childpos); Py_INCREF(tmp); - Py_DECREF(PyList_GET_ITEM(heap, pos)); + olditem = PyList_GET_ITEM(heap, pos); PyList_SET_ITEM(heap, pos, tmp); + Py_DECREF(olditem); pos = childpos; childpos = 2*pos + 1; + if (size != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); + return -1; + } } /* The leaf at pos is empty now. Put newitem there, and and bubble diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -349,8 +349,7 @@ if (PyDict_DelItemString(self->dict, "message") < 0) return -1; } - Py_XDECREF(self->message); - self->message = NULL; + Py_CLEAR(self->message); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 10:24:00 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 10:24:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRml4IElzc3VlICMx?= =?utf-8?q?2921=3A_BaseHTTPServer=27s_send=5Ferror_should_send_the_correct?= =?utf-8?q?_error?= Message-ID: <3ZKt2m6wKzzNn1@mail.python.org> http://hg.python.org/cpython/rev/c31d700dea8b changeset: 82490:c31d700dea8b branch: 2.7 user: Senthil Kumaran date: Tue Mar 05 01:21:13 2013 -0800 summary: Fix Issue #12921: BaseHTTPServer's send_error should send the correct error response message when send_error includes a message in addition to error status. Patch contributed by Karl. files: Lib/BaseHTTPServer.py | 2 +- Misc/NEWS | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py --- a/Lib/BaseHTTPServer.py +++ b/Lib/BaseHTTPServer.py @@ -365,7 +365,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, message) + self.send_response(code, short) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,6 +214,10 @@ Library ------- +- Issue #12921: BaseHTTPServer's send_error should send the correct error + response message when send_error includes a message in addition to error + status. Patch submitted by Karl. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 10:24:02 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 10:24:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogRml4IElzc3VlICMx?= =?utf-8?q?2921=3A_BaseHTTPServer=27s_send=5Ferror_should_send_the_correct?= =?utf-8?q?_error?= Message-ID: <3ZKt2p2xx9z7LnZ@mail.python.org> http://hg.python.org/cpython/rev/5126e62c60af changeset: 82491:5126e62c60af branch: 3.2 parent: 82479:905b02749c26 user: Senthil Kumaran date: Tue Mar 05 01:22:57 2013 -0800 summary: Fix Issue #12921: BaseHTTPServer's send_error should send the correct error response message when send_error includes a message in addition to error status. Patch contributed by Karl. files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -421,7 +421,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, message) + self.send_response(code, shortmsg) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,10 @@ Library ------- +- Issue #12921: BaseHTTPServer's send_error should send the correct error + response message when send_error includes a message in addition to error + status. Patch submitted by Karl. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 10:24:03 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 10:24:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Fix_Issue_=2312921=3A_BaseHTTPServer=27s_send=5Ferror_should_s?= =?utf-8?q?end_the_correct_error?= Message-ID: <3ZKt2q606Dz7Lt4@mail.python.org> http://hg.python.org/cpython/rev/5d76a4746d9d changeset: 82492:5d76a4746d9d branch: 3.3 parent: 82486:b691f25c3553 parent: 82491:5126e62c60af user: Senthil Kumaran date: Tue Mar 05 01:23:44 2013 -0800 summary: Fix Issue #12921: BaseHTTPServer's send_error should send the correct error response message when send_error includes a message in addition to error status. Patch contributed by Karl. files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -425,7 +425,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, message) + self.send_response(code, shortmsg) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,10 @@ Library ------- +- Issue #12921: BaseHTTPServer's send_error should send the correct error + response message when send_error includes a message in addition to error + status. Patch submitted by Karl. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 10:24:05 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 10:24:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fix_Issue_=2312921=3A_BaseHTTPServer=27s_send=5Ferror_sh?= =?utf-8?q?ould_send_the_correct_error?= Message-ID: <3ZKt2s1nCJz7Lt0@mail.python.org> http://hg.python.org/cpython/rev/b87792757ee8 changeset: 82493:b87792757ee8 parent: 82487:f23814bab066 parent: 82492:5d76a4746d9d user: Senthil Kumaran date: Tue Mar 05 01:26:33 2013 -0800 summary: Fix Issue #12921: BaseHTTPServer's send_error should send the correct error response message when send_error includes a message in addition to error status. Patch contributed by Karl. files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -426,7 +426,7 @@ content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) body = content.encode('UTF-8', 'replace') - self.send_response(code, message) + self.send_response(code, shortmsg) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.send_header('Content-Length', int(len(body))) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -275,6 +275,10 @@ Library ------- +- Issue #12921: BaseHTTPServer's send_error should send the correct error + response message when send_error includes a message in addition to error + status. Patch submitted by Karl. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 11:25:48 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 11:25:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Reverting_the_?= =?utf-8?q?changeset_c31d700dea8b_made_for_Issue_=2312921?= Message-ID: <3ZKvQ44dPzzSJJ@mail.python.org> http://hg.python.org/cpython/rev/4e6c46d5f77d changeset: 82494:4e6c46d5f77d branch: 2.7 parent: 82490:c31d700dea8b user: Senthil Kumaran date: Tue Mar 05 02:24:03 2013 -0800 summary: Reverting the changeset c31d700dea8b made for Issue #12921 files: Lib/BaseHTTPServer.py | 2 +- Misc/NEWS | 4 ---- 2 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py --- a/Lib/BaseHTTPServer.py +++ b/Lib/BaseHTTPServer.py @@ -365,7 +365,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, short) + self.send_response(code, message) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,10 +214,6 @@ Library ------- -- Issue #12921: BaseHTTPServer's send_error should send the correct error - response message when send_error includes a message in addition to error - status. Patch submitted by Karl. - - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 11:25:50 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 11:25:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Reverting_the_?= =?utf-8?q?changeset_5126e62c60af_made_for_Issue_=2312921?= Message-ID: <3ZKvQ619rzz7Ljk@mail.python.org> http://hg.python.org/cpython/rev/637d7c953b10 changeset: 82495:637d7c953b10 branch: 3.2 parent: 82491:5126e62c60af user: Senthil Kumaran date: Tue Mar 05 02:25:58 2013 -0800 summary: Reverting the changeset 5126e62c60af made for Issue #12921 files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ---- 2 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -421,7 +421,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, shortmsg) + self.send_response(code, message) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,10 +233,6 @@ Library ------- -- Issue #12921: BaseHTTPServer's send_error should send the correct error - response message when send_error includes a message in addition to error - status. Patch submitted by Karl. - - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 11:25:51 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 11:25:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Reverting_the_changeset_5d76a4746d9d_made_for_Issue_=2312921?= Message-ID: <3ZKvQ741VgzSJJ@mail.python.org> http://hg.python.org/cpython/rev/84e7a7f6ddb8 changeset: 82496:84e7a7f6ddb8 branch: 3.3 parent: 82492:5d76a4746d9d parent: 82495:637d7c953b10 user: Senthil Kumaran date: Tue Mar 05 02:26:50 2013 -0800 summary: Reverting the changeset 5d76a4746d9d made for Issue #12921 files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ---- 2 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -425,7 +425,7 @@ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, shortmsg) + self.send_response(code, message) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.end_headers() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,10 +193,6 @@ Library ------- -- Issue #12921: BaseHTTPServer's send_error should send the correct error - response message when send_error includes a message in addition to error - status. Patch submitted by Karl. - - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 11:25:52 2013 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 5 Mar 2013 11:25:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Reverting_the_changeset_b87792757ee8__made_for_Issue_=23?= =?utf-8?q?12921?= Message-ID: <3ZKvQ86jVbzRvY@mail.python.org> http://hg.python.org/cpython/rev/b0890674bc21 changeset: 82497:b0890674bc21 parent: 82493:b87792757ee8 parent: 82496:84e7a7f6ddb8 user: Senthil Kumaran date: Tue Mar 05 02:28:18 2013 -0800 summary: Reverting the changeset b87792757ee8 made for Issue #12921 files: Lib/http/server.py | 2 +- Misc/NEWS | 4 ---- 2 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -426,7 +426,7 @@ content = (self.error_message_format % {'code': code, 'message': _quote_html(message), 'explain': explain}) body = content.encode('UTF-8', 'replace') - self.send_response(code, shortmsg) + self.send_response(code, message) self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') self.send_header('Content-Length', int(len(body))) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -275,10 +275,6 @@ Library ------- -- Issue #12921: BaseHTTPServer's send_error should send the correct error - response message when send_error includes a message in addition to error - status. Patch submitted by Karl. - - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 13:22:58 2013 From: python-checkins at python.org (nick.coghlan) Date: Tue, 5 Mar 2013 13:22:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Adjust_the_redrafted_PEP_422_?= =?utf-8?q?to_match_reality?= Message-ID: <3ZKy1G1gHxz7LkD@mail.python.org> http://hg.python.org/peps/rev/bf60a9ca80a9 changeset: 4782:bf60a9ca80a9 user: Nick Coghlan date: Tue Mar 05 22:22:20 2013 +1000 summary: Adjust the redrafted PEP 422 to match reality files: pep-0422.txt | 107 ++++++++++++++++++++++++++++---------- 1 files changed, 78 insertions(+), 29 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -27,16 +27,6 @@ implementing a custom metaclass, and thus should provide a gentler introduction to the full power Python's metaclass machinery. -.. note:: - - This PEP, in particular the use of __prepare__ to share a single - namespace amongst multiple class objects, highlights a possible issue - with the attribute lookup caching: when the underlying mapping is updated - by other means, the attribute lookup cache is not invalidated correctly. - Since the optimisation provided by that cache is highly desirable, - some of the ideas in this PEP may need to be declared as officially - unsupported (since the observed behaviour is rather odd when the - caches get out of sync). Background ========== @@ -153,16 +143,31 @@ However, the introduction of the metaclass ``__prepare__`` method in PEP 3115 allows a further enhancement that was not possible in Python 2: this -PEP also proposes that ``type.__prepare__`` be updated to accept a -``namespace`` keyword-only argument. If present, the value provided as the -``namespace`` argument will be returned from ``type.__prepare__`` instead of -a freshly created dictionary instance. For example, the following will use +PEP also proposes that ``type.__prepare__`` be updated to accept a factory +function as a ``namespace`` keyword-only argument. If present, the value +provided as the ``namespace`` argument will be called without arguments +to create the result of ``type.__prepare__`` instead of using a freshly +created dictionary instance. For example, the following will use the ordered dictionary created in the header as the class namespace:: - class OrderedExample(namespace=collections.OrderedDict()): + class OrderedExample(namespace=collections.OrderedDict): def __init_class__(cls): # cls.__dict__ is still a read-only proxy to the class namespace, - # but the underlying storage is the OrderedDict instance + # but the underlying storage is an OrderedDict instance + +.. note:: + + This PEP, along with the existing ability to use __prepare__ to share a + single namespace amongst multiple class objects, highlights a possible + issue with the attribute lookup caching: when the underlying mapping is + updated by other means, the attribute lookup cache is not invalidated + correctly (this is a key part of the reason class ``__dict__`` attributes + produce a read-only view of the underlying storage). + + Since the optimisation provided by that cache is highly desirable, + the use of a preexisting namespace as the class namespace may need to + be declared as officially unsupported (since the observed behaviour is + rather strange when the caches get out of sync). Key Benefits @@ -175,7 +180,8 @@ Currently, to use a different type (such as ``collections.OrderedDict``) for a class namespace, or to use a pre-populated namespace, it is necessary to write and use a custom metaclass. With this PEP, using a custom namespace -becomes as simple as specifying it in the class header. +becomes as simple as specifying an appropriate factory function in the +class header. Easier inheritance of definition time behaviour @@ -245,20 +251,19 @@ All of the examples below are actually possible today through the use of a custom metaclass:: +if 1: class CustomNamespace(type): @classmethod def __prepare__(meta, name, bases, *, namespace=None, **kwds): parent_namespace = super().__prepare__(name, bases, **kwds) - return namespace if namespace is not None else parent_namespace - + return namespace() if namespace is not None else parent_namespace def __new__(meta, name, bases, ns, *, namespace=None, **kwds): return super().__new__(meta, name, bases, ns, **kwds) - def __init__(cls, name, bases, ns, *, namespace=None, **kwds): return super().__init__(name, bases, ns, **kwds) The advantage of implementing the new keyword directly in -``type.__prepare__`` is that the *only* persistent effect is +``type.__prepare__`` is that the *only* persistent effect is then the change in the underlying storage of the class attributes. The metaclass of the class remains unchanged, eliminating many of the drawbacks typically associated with these kinds of customisations. @@ -269,7 +274,7 @@ :: - class OrderedClass(namespace=collections.OrderedDict()): + class OrderedClass(namespace=collections.OrderedDict): a = 1 b = 2 c = 3 @@ -281,7 +286,7 @@ :: seed_data = dict(a=1, b=2, c=3) - class PrepopulatedClass(namespace=seed_data.copy()): + class PrepopulatedClass(namespace=seed_data.copy): pass @@ -290,21 +295,54 @@ :: - class NewClass(namespace=Prototype.__dict__.copy()): + class NewClass(namespace=Prototype.__dict__.copy): pass -Defining an extensible class ----------------------------- +Extending a class +----------------- + +.. note:: Just because the PEP makes it *possible* to do this relatively, + cleanly doesn't mean anyone *should* do this! :: - class Extensible: - namespace = locals() + from collections import MutableMapping - class ExtendingClass(namespace=Extensible.namespace): + # The MutableMapping + dict combination should give something that + # generally behaves correctly as a mapping, while still being accepted + # as a class namespace + class ClassNamespace(MutableMapping, dict): + def __init__(self, cls): + self._cls = cls + def __len__(self): + return len(dir(self._cls)) + def __iter__(self): + for attr in dir(self._cls): + yield attr + def __contains__(self, attr): + return hasattr(self._cls, attr) + def __getitem__(self, attr): + return getattr(self._cls, attr) + def __setitem__(self, attr, value): + setattr(self._cls, attr, value) + def __delitem__(self, attr): + delattr(self._cls, attr) + + def extend(cls): + return lambda: ClassNamespace(cls) + + class Example: pass + class ExtendedExample(namespace=extend(Example)): + a = 1 + b = 2 + c = 3 + + >>> Example.a, Example.b, Example.c + (1, 2, 3) + Rejected Design Options ======================= @@ -335,6 +373,17 @@ explicitly say anything one way or the other). +Passing in the namespace directly rather than a factory function +---------------------------------------------------------------- + +At one point, this PEP proposed that the class namespace be passed +directly as a keyword argument, rather than passing a factory function. +However, this encourages an unsupported behaviour (that is, passing the +same namespace to multiple classes, or retaining direct write access +to a mapping used as a class namespace), so the API was switched to +the factory function version. + + Reference Implementation ======================== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Mar 5 13:26:01 2013 From: python-checkins at python.org (nick.coghlan) Date: Tue, 5 Mar 2013 13:26:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_markup?= Message-ID: <3ZKy4n2wyzzS7w@mail.python.org> http://hg.python.org/peps/rev/e61f80e9d5fe changeset: 4783:e61f80e9d5fe user: Nick Coghlan date: Tue Mar 05 22:25:52 2013 +1000 summary: Fix markup files: pep-0422.txt | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -251,7 +251,6 @@ All of the examples below are actually possible today through the use of a custom metaclass:: -if 1: class CustomNamespace(type): @classmethod def __prepare__(meta, name, bases, *, namespace=None, **kwds): -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Mar 5 13:32:36 2013 From: python-checkins at python.org (nick.coghlan) Date: Tue, 5 Mar 2013 13:32:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Missed_a_ref_to_the_old_API_i?= =?utf-8?q?n_PEP_422?= Message-ID: <3ZKyDN03dYzT1q@mail.python.org> http://hg.python.org/peps/rev/cbeb9952c038 changeset: 4784:cbeb9952c038 user: Nick Coghlan date: Tue Mar 05 22:32:26 2013 +1000 summary: Missed a ref to the old API in PEP 422 files: pep-0422.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -148,7 +148,7 @@ provided as the ``namespace`` argument will be called without arguments to create the result of ``type.__prepare__`` instead of using a freshly created dictionary instance. For example, the following will use -the ordered dictionary created in the header as the class namespace:: +an ordered dictionary as the class namespace:: class OrderedExample(namespace=collections.OrderedDict): def __init_class__(cls): -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Mar 5 13:34:52 2013 From: python-checkins at python.org (nick.coghlan) Date: Tue, 5 Mar 2013 13:34:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Minor_wording_nit?= Message-ID: <3ZKyH03MF2z7Lm1@mail.python.org> http://hg.python.org/peps/rev/64c17479a841 changeset: 4785:64c17479a841 user: Nick Coghlan date: Tue Mar 05 22:34:43 2013 +1000 summary: Minor wording nit files: pep-0422.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -141,7 +141,7 @@ but the situation has changed sufficiently in recent years that the idea is worth reconsidering. -However, the introduction of the metaclass ``__prepare__`` method in PEP +In addition, the introduction of the metaclass ``__prepare__`` method in PEP 3115 allows a further enhancement that was not possible in Python 2: this PEP also proposes that ``type.__prepare__`` be updated to accept a factory function as a ``namespace`` keyword-only argument. If present, the value -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Mar 5 19:33:55 2013 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Mar 2013 19:33:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzExNzMyOiBhZGQg?= =?utf-8?q?a_new_suppress=5Fcrash=5Fpopup=28=29_context_manager_to_test=2E?= =?utf-8?q?support=2E?= Message-ID: <3ZL6FH3p8Bz7LkT@mail.python.org> http://hg.python.org/cpython/rev/834a451f1cdb changeset: 82498:834a451f1cdb branch: 3.3 parent: 82496:84e7a7f6ddb8 user: Ezio Melotti date: Tue Mar 05 20:26:17 2013 +0200 summary: #11732: add a new suppress_crash_popup() context manager to test.support. files: Doc/library/test.rst | 7 ++++++ Lib/test/support.py | 24 ++++++++++++++++++++++- Lib/test/test_capi.py | 3 +- Lib/test/test_faulthandler.py | 6 +++- Misc/NEWS | 4 +++ 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -405,6 +405,13 @@ A decorator for running tests that require support for symbolic links. +.. function:: suppress_crash_popup() + + A context manager that disables Windows Error Reporting dialogs using + `SetErrorMode `_. + On other platforms it's a no-op. + + .. decorator:: anticipate_failure(condition) A decorator to conditionally mark tests with diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -71,7 +71,7 @@ "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "skip_unless_xattr", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", "anticipate_failure", "run_with_tz", - "requires_bz2", "requires_lzma" + "requires_bz2", "requires_lzma", "suppress_crash_popup", ] class Error(Exception): @@ -1905,6 +1905,28 @@ msg = "no non-broken extended attribute support" return test if ok else unittest.skip(msg)(test) + +if sys.platform.startswith('win'): + @contextlib.contextmanager + def suppress_crash_popup(): + """Disable Windows Error Reporting dialogs using SetErrorMode.""" + # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + import ctypes + k32 = ctypes.windll.kernel32 + old_error_mode = k32.GetErrorMode() + SEM_NOGPFAULTERRORBOX = 0x02 + k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) + try: + yield + finally: + k32.SetErrorMode(old_error_mode) +else: + # this is a no-op for other platforms + @contextlib.contextmanager + def suppress_crash_popup(): + yield + + def patch(test_instance, object_to_patch, attr_name, new_value): """Override 'object_to_patch'.'attr_name' with 'new_value'. diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -44,7 +44,8 @@ @unittest.skipUnless(threading, 'Threading required for this test.') def test_no_FatalError_infinite_loop(self): - p = subprocess.Popen([sys.executable, "-c", + with support.suppress_crash_popup(): + p = subprocess.Popen([sys.executable, "-c", 'import _testcapi;' '_testcapi.crash_no_current_thread()'], stdout=subprocess.PIPE, diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -101,7 +101,8 @@ header=re.escape(header)) if other_regex: regex += '|' + other_regex - output, exitcode = self.get_output(code, filename) + with support.suppress_crash_popup(): + output, exitcode = self.get_output(code, filename) output = '\n'.join(output) self.assertRegex(output, regex) self.assertNotEqual(exitcode, 0) @@ -229,7 +230,8 @@ faulthandler._read_null() """.strip() not_expected = 'Fatal Python error' - stderr, exitcode = self.get_output(code) + with support.suppress_crash_popup(): + stderr, exitcode = self.get_output(code) stder = '\n'.join(stderr) self.assertTrue(not_expected not in stderr, "%r is present in %r" % (not_expected, stderr)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -640,6 +640,10 @@ Tests ----- +- Issue #11732: add a new suppress_crash_popup() context manager to test.support + that disables crash popups on Windows and use it in test_faulthandler and + test_ctypes. + - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. - Issue #17249: convert a test in test_capi to use unittest and reap threads. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 19:33:56 2013 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Mar 2013 19:33:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_indentatio?= =?utf-8?q?n=2E?= Message-ID: <3ZL6FJ6zbJz7Lnl@mail.python.org> http://hg.python.org/cpython/rev/ef7565180b48 changeset: 82499:ef7565180b48 branch: 3.3 user: Ezio Melotti date: Tue Mar 05 20:31:34 2013 +0200 summary: Fix indentation. files: Lib/test/test_capi.py | 8 ++++---- Lib/test/test_faulthandler.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -46,10 +46,10 @@ def test_no_FatalError_infinite_loop(self): with support.suppress_crash_popup(): p = subprocess.Popen([sys.executable, "-c", - 'import _testcapi;' - '_testcapi.crash_no_current_thread()'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + 'import _testcapi;' + '_testcapi.crash_no_current_thread()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) (out, err) = p.communicate() self.assertEqual(out, b'') # This used to cause an infinite loop. diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -102,7 +102,7 @@ if other_regex: regex += '|' + other_regex with support.suppress_crash_popup(): - output, exitcode = self.get_output(code, filename) + output, exitcode = self.get_output(code, filename) output = '\n'.join(output) self.assertRegex(output, regex) self.assertNotEqual(exitcode, 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 5 19:33:58 2013 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Mar 2013 19:33:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExNzMyOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZL6FL4c0tz7LpK@mail.python.org> http://hg.python.org/cpython/rev/b87123015fb0 changeset: 82500:b87123015fb0 parent: 82497:b0890674bc21 parent: 82499:ef7565180b48 user: Ezio Melotti date: Tue Mar 05 20:33:38 2013 +0200 summary: #11732: merge with 3.3. files: Doc/library/test.rst | 7 ++++++ Lib/test/support.py | 24 ++++++++++++++++++++++- Lib/test/test_capi.py | 11 +++++---- Lib/test/test_faulthandler.py | 6 +++- Misc/NEWS | 4 +++ 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -405,6 +405,13 @@ A decorator for running tests that require support for symbolic links. +.. function:: suppress_crash_popup() + + A context manager that disables Windows Error Reporting dialogs using + `SetErrorMode `_. + On other platforms it's a no-op. + + .. decorator:: anticipate_failure(condition) A decorator to conditionally mark tests with diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -71,7 +71,7 @@ "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "skip_unless_xattr", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", "anticipate_failure", "run_with_tz", - "requires_bz2", "requires_lzma" + "requires_bz2", "requires_lzma", "suppress_crash_popup", ] class Error(Exception): @@ -1907,6 +1907,28 @@ msg = "no non-broken extended attribute support" return test if ok else unittest.skip(msg)(test) + +if sys.platform.startswith('win'): + @contextlib.contextmanager + def suppress_crash_popup(): + """Disable Windows Error Reporting dialogs using SetErrorMode.""" + # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + import ctypes + k32 = ctypes.windll.kernel32 + old_error_mode = k32.GetErrorMode() + SEM_NOGPFAULTERRORBOX = 0x02 + k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) + try: + yield + finally: + k32.SetErrorMode(old_error_mode) +else: + # this is a no-op for other platforms + @contextlib.contextmanager + def suppress_crash_popup(): + yield + + def patch(test_instance, object_to_patch, attr_name, new_value): """Override 'object_to_patch'.'attr_name' with 'new_value'. diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -44,11 +44,12 @@ @unittest.skipUnless(threading, 'Threading required for this test.') def test_no_FatalError_infinite_loop(self): - p = subprocess.Popen([sys.executable, "-c", - 'import _testcapi;' - '_testcapi.crash_no_current_thread()'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + with support.suppress_crash_popup(): + p = subprocess.Popen([sys.executable, "-c", + 'import _testcapi;' + '_testcapi.crash_no_current_thread()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) (out, err) = p.communicate() self.assertEqual(out, b'') # This used to cause an infinite loop. diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -101,7 +101,8 @@ header=re.escape(header)) if other_regex: regex += '|' + other_regex - output, exitcode = self.get_output(code, filename) + with support.suppress_crash_popup(): + output, exitcode = self.get_output(code, filename) output = '\n'.join(output) self.assertRegex(output, regex) self.assertNotEqual(exitcode, 0) @@ -229,7 +230,8 @@ faulthandler._read_null() """.strip() not_expected = 'Fatal Python error' - stderr, exitcode = self.get_output(code) + with support.suppress_crash_popup(): + stderr, exitcode = self.get_output(code) stder = '\n'.join(stderr) self.assertTrue(not_expected not in stderr, "%r is present in %r" % (not_expected, stderr)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -892,6 +892,10 @@ Tests ----- +- Issue #11732: add a new suppress_crash_popup() context manager to test.support + that disables crash popups on Windows and use it in test_faulthandler and + test_ctypes. + - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. - Issue #17283: Share code between `__main__.py` and `regrtest.py` in -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 00:42:21 2013 From: python-checkins at python.org (victor.stinner) Date: Wed, 6 Mar 2013 00:42:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317223=3A_Add_anot?= =?utf-8?q?her_test_to_check_that_=5FPyUnicode=5FReady=28=29_rejects?= Message-ID: <3ZLF591ycqz7Lnt@mail.python.org> http://hg.python.org/cpython/rev/15190138d3f3 changeset: 82501:15190138d3f3 user: Victor Stinner date: Wed Mar 06 00:39:03 2013 +0100 summary: Issue #17223: Add another test to check that _PyUnicode_Ready() rejects code points bigger than U+10ffff files: Modules/_testcapimodule.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1418,6 +1418,16 @@ else return raiseTestError("test_widechar", "PyUnicode_FromUnicode(L\"\\U00110000\", 1) didn't fail"); + + wide = PyUnicode_FromUnicode(NULL, 1); + if (wide == NULL) + return NULL; + PyUnicode_AS_UNICODE(wide)[0] = invalid[0]; + if (_PyUnicode_Ready(wide) < 0) + PyErr_Clear(); + else + return raiseTestError("test_widechar", + "PyUnicode_Ready() didn't fail"); #endif Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 00:42:22 2013 From: python-checkins at python.org (victor.stinner) Date: Wed, 6 Mar 2013 00:42:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317223=3A_Fix_PyUn?= =?utf-8?q?icode=5FFromUnicode=28=29_on_Windows_=2816-bit_wchar=5Ft_type?= =?utf-8?q?=29?= Message-ID: <3ZLF5B4mmbz7Lpf@mail.python.org> http://hg.python.org/cpython/rev/b9f7b1bf36aa changeset: 82502:b9f7b1bf36aa user: Victor Stinner date: Wed Mar 06 00:41:50 2013 +0100 summary: Issue #17223: Fix PyUnicode_FromUnicode() on Windows (16-bit wchar_t type) to reject invalid UTF-16 surrogate. files: Misc/NEWS | 3 +++ Objects/unicodeobject.c | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #17223: Fix PyUnicode_FromUnicode() on Windows (16-bit wchar_t type) + to reject invalid UTF-16 surrogate. + - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1384,13 +1384,18 @@ for (iter = begin; iter < end; ) { #if SIZEOF_WCHAR_T == 2 - if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0]) - && (iter+1) < end - && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) - { - ch = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); - ++(*num_surrogates); - iter += 2; + if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0])) { + if ((iter+1) < end + && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) + { + ch = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); + ++(*num_surrogates); + iter += 2; + } + else { + PyErr_SetString(PyExc_ValueError, "illegal UTF-16 surrogate"); + return -1; + } } else #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 01:09:44 2013 From: python-checkins at python.org (victor.stinner) Date: Wed, 6 Mar 2013 01:09:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset_b9f7b?= =?utf-8?q?1bf36aa?= Message-ID: <3ZLFhm07Ycz7LkL@mail.python.org> http://hg.python.org/cpython/rev/583a0321c7b9 changeset: 82503:583a0321c7b9 user: Victor Stinner date: Wed Mar 06 01:09:24 2013 +0100 summary: Backed out changeset b9f7b1bf36aa files: Misc/NEWS | 3 --- Objects/unicodeobject.c | 19 +++++++------------ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,9 +10,6 @@ Core and Builtins ----------------- -- Issue #17223: Fix PyUnicode_FromUnicode() on Windows (16-bit wchar_t type) - to reject invalid UTF-16 surrogate. - - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1384,18 +1384,13 @@ for (iter = begin; iter < end; ) { #if SIZEOF_WCHAR_T == 2 - if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0])) { - if ((iter+1) < end - && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) - { - ch = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); - ++(*num_surrogates); - iter += 2; - } - else { - PyErr_SetString(PyExc_ValueError, "illegal UTF-16 surrogate"); - return -1; - } + if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0]) + && (iter+1) < end + && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) + { + ch = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); + ++(*num_surrogates); + iter += 2; } else #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 01:59:38 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 01:59:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MzYzOiBmaXgg?= =?utf-8?q?arguments_in_PyState=5FAddModule_and_PyState=5FRemoveModule_doc?= =?utf-8?q?s=2E?= Message-ID: <3ZLGpL2wyPz7Lpr@mail.python.org> http://hg.python.org/cpython/rev/29d5bc1226f9 changeset: 82504:29d5bc1226f9 branch: 3.3 parent: 82499:ef7565180b48 user: Ezio Melotti date: Wed Mar 06 02:57:25 2013 +0200 summary: #17363: fix arguments in PyState_AddModule and PyState_RemoveModule docs. files: Doc/c-api/module.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -122,7 +122,7 @@ :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(PyModuleDef *def, PyObject *module) +.. 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 @@ -130,7 +130,7 @@ .. versionadded:: 3.3 -.. c:function:: int PyState_RemoveModule(PyModuleDef *def, PyObject *module) +.. c:function:: int PyState_RemoveModule(PyModuleDef *def) Removes the module object created from *def* from the interpreter state. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 01:59:39 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 01:59:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzYzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZLGpM5dP1z7LmC@mail.python.org> http://hg.python.org/cpython/rev/75c0cb169be5 changeset: 82505:75c0cb169be5 parent: 82503:583a0321c7b9 parent: 82504:29d5bc1226f9 user: Ezio Melotti date: Wed Mar 06 02:59:25 2013 +0200 summary: #17363: merge with 3.3. files: Doc/c-api/module.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -122,7 +122,7 @@ :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(PyModuleDef *def, PyObject *module) +.. 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 @@ -130,7 +130,7 @@ .. versionadded:: 3.3 -.. c:function:: int PyState_RemoveModule(PyModuleDef *def, PyObject *module) +.. c:function:: int PyState_RemoveModule(PyModuleDef *def) Removes the module object created from *def* from the interpreter state. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 02:24:07 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 02:24:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3MzY0OiByZW1v?= =?utf-8?q?ve_documentation_for_a_function_that_does_not_exist=2E?= Message-ID: <3ZLHLb3FxJzSlH@mail.python.org> http://hg.python.org/cpython/rev/01a8fcc91d5a changeset: 82506:01a8fcc91d5a branch: 2.7 parent: 82494:4e6c46d5f77d user: Ezio Melotti date: Wed Mar 06 03:20:27 2013 +0200 summary: #17364: remove documentation for a function that does not exist. files: Doc/library/multiprocessing.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -579,7 +579,6 @@ :exc:`Queue.Empty` exception (*timeout* is ignored in that case). .. method:: get_nowait() - get_no_wait() Equivalent to ``get(False)``. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 02:24:08 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 02:24:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzY0OiByZW1v?= =?utf-8?q?ve_documentation_for_a_function_that_does_not_exist=2E?= Message-ID: <3ZLHLc6ByWzSsL@mail.python.org> http://hg.python.org/cpython/rev/4f9de1b18cab changeset: 82507:4f9de1b18cab branch: 3.2 parent: 82495:637d7c953b10 user: Ezio Melotti date: Wed Mar 06 03:20:27 2013 +0200 summary: #17364: remove documentation for a function that does not exist. files: Doc/library/multiprocessing.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -579,7 +579,6 @@ :exc:`queue.Empty` exception (*timeout* is ignored in that case). .. method:: get_nowait() - get_no_wait() Equivalent to ``get(False)``. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 02:24:10 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 02:24:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317364=3A_merge_with_3=2E2=2E?= Message-ID: <3ZLHLf1sTVzSns@mail.python.org> http://hg.python.org/cpython/rev/5e294202f93e changeset: 82508:5e294202f93e branch: 3.3 parent: 82504:29d5bc1226f9 parent: 82507:4f9de1b18cab user: Ezio Melotti date: Wed Mar 06 03:23:28 2013 +0200 summary: #17364: merge with 3.2. files: Doc/library/multiprocessing.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -608,7 +608,6 @@ :exc:`queue.Empty` exception (*timeout* is ignored in that case). .. method:: get_nowait() - get_no_wait() Equivalent to ``get(False)``. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 02:24:11 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 6 Mar 2013 02:24:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzY0OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZLHLg4QJkz7Lpr@mail.python.org> http://hg.python.org/cpython/rev/b87e9b8dc9ad changeset: 82509:b87e9b8dc9ad parent: 82505:75c0cb169be5 parent: 82508:5e294202f93e user: Ezio Melotti date: Wed Mar 06 03:23:52 2013 +0200 summary: #17364: merge with 3.3. files: Doc/library/multiprocessing.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -608,7 +608,6 @@ :exc:`queue.Empty` exception (*timeout* is ignored in that case). .. method:: get_nowait() - get_no_wait() Equivalent to ``get(False)``. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 05:17:13 2013 From: python-checkins at python.org (terry.reedy) Date: Wed, 6 Mar 2013 05:17:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP-434=3A_Touch-up_format_to?= =?utf-8?q?_comform_to_PEP-1_guidelines_and_PEP-12_template=2E?= Message-ID: <3ZLMBK6vflzRx7@mail.python.org> http://hg.python.org/peps/rev/fe24e53bc195 changeset: 4786:fe24e53bc195 parent: 4761:4de791923041 user: Terry Jan Reedy date: Tue Mar 05 19:07:25 2013 -0500 summary: PEP-434: Touch-up format to comform to PEP-1 guidelines and PEP-12 template. Re-write to focus more on the specific pep proposal and the difficulty of classifying IDLE issues. Added discussion of backwards compatibility with extensions. files: pep-0434.txt | 174 ++++++++++++++++++++++++++++++-------- 1 files changed, 138 insertions(+), 36 deletions(-) diff --git a/pep-0434.txt b/pep-0434.txt --- a/pep-0434.txt +++ b/pep-0434.txt @@ -1,52 +1,153 @@ PEP: 434 Title: IDLE Enhancement Exception for All Branches -Version: -Last-Modified: -Author: Todd Rovito , Terry Reedy +Version: $Revision$ +Last-Modified: $Date$ +Author: Todd Rovito , + Terry Reedy BDFL-Delegate: Nick Coghlan Status: Draft Type: Informational Content-Type: text/x-rst Created: 16-Feb-2013 -Python-Version: 2.7 Post-History: 16-Feb-2013 Abstract ======== -Generally only new features are applied to Python 3.4 but this PEP requests an -exception for IDLE [1]_. IDLE is part of the standard library and has numerous -outstanding issues [2]_. Since IDLE is often the first thing a new Python user -sees it desperately needs to be brought up to date with modern GUI standards -across the three major platforms Linux, Mac OS X, and Windows. +Most CPython tracker issues are classified as behavior or +enhancement. Most behavior patches are backported to branches for +existing versions. Enhancement patches are restricted to the default +branch that becomes the next Python version. + +This PEP proposes that the restriction on applying enhancements be +relaxed for IDLE code, residing in .../Lib/idlelib/. In practice, +this would mean that IDLE developers would not have to classify or +agree on the classification of a patch but could instead focus on +what is best for IDLE users and future IDLE developement. It would +also mean that IDLE patches would not necessarily have to be split +into 'bugfix' changes and enhancement changes. + +The PEP would apply to changes in existing features and addition of +small features, such as would require a new menu entry, but not +necessarily to possible major re-writes such as switching to themed +widgets or tabbed windows. + + +Motivation +========== + +This PEP was prompted by controversy on both the tracker and pydev +list over adding Cut, Copy, and Paste to right-click context menus +(Issue 1207589, opened in 2005 [1]_; pydev thread [2]_). The +features were available as keyboard shortcuts but not on the context +menu. It is standard, at least on Windows, that they should be when +applicable (a read-only window would only have Copy), so users do not +have to shift to the keyboard after selecting text for cutting or +copying or a slice point for pasting. The context menu was not +documented until 10 days before the new options were added (Issue +10405 [3]_). + +Normally, behavior is called a bug if it conflicts with documentation +judged to be correct. But if there is no doc, what is the standard? +If the code is its own documentation, most IDLE issues on the tracker +are enhancement issues. If we substitute reasonable user expectation, +(which can, of course, be its own subject of disagreement), many more +issues are behavior issues. + +For context menus, people disagreed on the status of the additions -- +bugfix or enhancement. Even people who called it an enhancement +disagreed as to whether the patch should be backported. This PEP +proposes to make the status disagreement irrelevant by explicitly +allowing more liberal backporting than for other stdlib modules. Rationale ========= -Python does have many advanced features yet Python is well known for being a -easy computer language for beginners [3]_. A major Python philosophy is -"batteries included" which is best demonstrated in Python's standard library -with many modules that are not typically included with other programming -languages [4]_. IDLE is a important "battery" in the Python toolbox because it -allows a beginner to get started quickly without downloading and configuring a -third party IDE. IDLE is primarily used as an application that ships with -Python, rather than as a library module used to build Python applications, -hence a different standard should apply to IDLE enhancements. Additional -patches to IDLE cannot break any existing program/library because IDLE is used -by humans. +People primarily use IDLE by running the gui application, rather than +by directly importing the effectively private (undocumented) +implementation modules in idlelib. Whether they use the shell, the +editor, or both, we believe they will benefit more from consistency +across the latest releases of current Python versions than from +consistency within the bugfix releases for one Python version. This +is especially true when existing behavior is clearly unsatisfactory. +When people use the standard interpreter, the OS-provided frame works +pretty much the same for all Python versions. If, for instance, +Microsoft were to upgrade the Command Prompt gui, the improvements +would be present regardless of which Python were running within it. +Similarly, if one edits Python code with editor X, behaviors such as +the right-click context menu and the search-replace box do not depend +on the version of Python being edited or even the language being +edited. -Details -======= +The benefit for IDLE developers is mixed. On the one hand, testing +more versions and possibly having to adjust a patch, especially for +2.7, is more work. (There is, of course, the option on not +backporting everything. For issue 12510, some changes to calltips for +classes were not included in the 2.7 patch because of issues with +old-style classes [4]_.) On the other hand, bike-shedding can be an +energy drain. If the obvious fix for a bug looks like an enhancement, +writing a separate bugfix-only patch is more work. And making the +code diverge between versions makes future multi-version patches more +difficult. -Python 2.7 does not accept bug fixes, this rule can be ignored for IDLE if the -Python development team accepts this PEP [5]_. IDLE issues will be carefully -tested on the three major platforms Linux, Mac OS X, and Windows before any -commits are made. Since IDLE is segregated to a particular part of the source -tree this enhancement exception only applies to Lib/idlelib directory in -Python branches >= 2.7. +These issue are illustrated by the search-and-replace dialog box. +It used to raise an exception for certain user entries [5]_. The +uncaught exception caused IDLE to exit. At least on Windows, the +exit was silent (no visible traceback) and looked like a crash if +IDLE was started normally, from an icon. + +Was this a bug? IDLE Help (on the current Help submenu) just says +"Replace... Open a search-and-replace dialog box", and a box *was* +opened. It is not, in general, a bug for a library method to raise an +exception. And it is not, in general, a bug for a library method to +ignore an exception raised by functions it calls. So if we were to +adopt the 'code = doc' philosopy in the absence of detailed docs, one +might say 'No'. + +However, IDLE exiting when it does not need to is definitely +obnoxious. So four of us agreed that it should be prevented. But +there was still the question of what to do instead? Catch the +exception? Just not raise the exception? Beep? Display an error +message box? Or try to do something useful with the user's entry? +Would replacing a 'crash' with useful behavior be an enhancement, +limited to future Python releases? Should IDLE developers have to +ask that? + + +Backwards Compatibility +======================= + +For IDLE, there are three types of users who might be concerned about +back compatibility. First are people who run IDLE as an application. +We have already discussed them above. + +Second are people who import one of the idlelib modules. As far as +we know, this is only done to start the IDLE application, and we do +not propose breaking such use. Otherwise, the modules are +undocumented and effectively private implementations. If an IDLE +module were defined as public, documented, and perhaps moved to the +tkinter package, it would then follow the normal rules. (Documenting +the private interfaces for the benefit of people working on the IDLE +code is a separate issue.) + +Third are people who write IDLE extensions. The guaranteed extension +interface is given in idlelib/extension.txt. This should be respected +at least in existing versions, and not frivolously changed in future +versions. But there is a warning that "The extension cannot assume +much about this [EditorWindow] argument." This guarantee should +rarely be an issue with patches, and the issue is not specific to +'enhancement' versus 'bugfix' patches. + +As is happens, after the context menu patch was applied, it came up +that extensions that added items to the context menu (rare) would be +broken because the patch a) added a new item to standard rmenu_specs +and b) expected every rmenu_spec to be lengthened. It is not clear +whether this violates the guarantee, but there is a second patch that +fixes assumption b). It should be applied when it is clear that the +first patch will not have to be reverted. References @@ -55,17 +156,18 @@ .. [1] IDLE: Right Click Context Menu, Foord, Michael (http://bugs.python.org/issue1207589) -.. [2] Meta-issue for "Invent with Python" IDLE feedback - (http://bugs.python.org/issue13504) +.. [2] Cut/Copy/Paste items in IDLE right click context menu + (http://mail.python.org/pipermail/python-dev/2012-November/122514.html) -.. [3] Getting Started with Python - (http://www.python.org/about/gettingstarted/) +.. [3] IDLE breakpoint facility undocumented, Daily, Ned + (http://bugs.python.org/issue10405) -.. [4] Batteries Included - (http://docs.python.org/2/tutorial/stdlib.html#batteries-included) +.. [4] IDLE: calltips mishandle raw strings and other examples, + Reedy, Terry + (http://bugs.python.org/issue12510) -.. [5] Python 2.7 Release Schedule - (http://www.python.org/dev/peps/pep-0373/) +.. [5] IDLE: replace ending with '\' causes crash, Reedy, Terry + (http://bugs.python.org/issue13052) Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Mar 6 05:17:16 2013 From: python-checkins at python.org (terry.reedy) Date: Wed, 6 Mar 2013 05:17:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_Merge?= Message-ID: <3ZLMBN0xNbzS96@mail.python.org> http://hg.python.org/peps/rev/feacb6c0633d changeset: 4787:feacb6c0633d parent: 4786:fe24e53bc195 parent: 4785:64c17479a841 user: Terry Jan Reedy date: Tue Mar 05 23:16:18 2013 -0500 summary: Merge files: pep-0422.txt | 341 ++++++++++++++---------- pep-0426.txt | 190 ++++++++----- pep-0427.txt | 20 +- pep-0428.txt | 18 + pep-0435.txt | 542 +++++++++++++++++++++++++++++++++++++++ pep-0436.txt | 480 ++++++++++++++++++++++++++++++++++ 6 files changed, 1371 insertions(+), 220 deletions(-) diff --git a/pep-0422.txt b/pep-0422.txt --- a/pep-0422.txt +++ b/pep-0422.txt @@ -1,5 +1,5 @@ PEP: 422 -Title: Simple class initialisation hook +Title: Simpler customisation of class creation Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan , @@ -9,29 +9,23 @@ Content-Type: text/x-rst Created: 5-Jun-2012 Python-Version: 3.4 -Post-History: 5-Jun-2012, 10-Feb-2012 +Post-History: 5-Jun-2012, 10-Feb-2013 Abstract ======== -In Python 2, the body of a class definition could modify the way a class -was created (or simply arrange to run other code after the class was created) -by setting the ``__metaclass__`` attribute in the class body. While doing -this implicitly from called code required the use of an implementation detail -(specifically, ``sys._getframes()``), it could also be done explicitly in a -fully supported fashion (for example, by passing ``locals()`` to a -function that calculated a suitable ``__metaclass__`` value) +Currently, customising class creation requires the use of a custom metaclass. +This custom metaclass then persists for the entire lifecycle of the class, +creating the potential for spurious metaclass conflicts. -There is currently no corresponding mechanism in Python 3 that allows the -code executed in the class body to directly influence how the class object -is created. Instead, the class creation process is fully defined by the -class header, before the class body even begins executing. +This PEP proposes to instead support a wide range of customisation +scenarios through a new ``namespace`` parameter in the class header, and +a new ``__init_class__`` hook in the class body. -This PEP proposes a mechanism that will once again allow the body of a -class definition to more directly influence the way a class is created -(albeit in a more constrained fashion), as well as replacing some current -uses of metaclasses with a simpler, easier to understand alternative. +The new mechanism is also much easier to understand and use than +implementing a custom metaclass, and thus should provide a gentler +introduction to the full power Python's metaclass machinery. Background @@ -81,25 +75,32 @@ name had not yet been bound in the containing scope), similarly, Python 3 metaclasses cannot call methods that rely on the implicit ``__class__`` reference (as it is not populated until after the metaclass has returned -control to the class creation machiner). +control to the class creation machinery). + +Finally, when a class uses a custom metaclass, it can pose additional +challenges to the use of multiple inheritance, as a new class cannot +inherit from parent classes with unrelated metaclasses. This means that +it is impossible to add a metaclass to an already published class: such +an addition is a backwards incompatible change due to the risk of metaclass +conflicts. Proposal ======== -This PEP proposes that a mechanism be added to Python 3 that meets the -following criteria: +This PEP proposes that a new mechanism to customise class creation be +added to Python 3.4 that meets the following criteria: -1. Restores the ability for class namespaces to have some influence on the +1. Integrates nicely with class inheritance structures (including mixins and + multiple inheritance) +2. Integrates nicely with the implicit ``__class__`` reference and + zero-argument ``super()`` syntax introduced by PEP 3135 +3. Can be added to an existing base class without a significant risk of + introducing backwards compatibility problems +4. Restores the ability for class namespaces to have some influence on the class creation process (above and beyond populating the namespace itself), but potentially without the full flexibility of the Python 2 style ``__metaclass__`` hook -2. Integrates nicely with class inheritance structures (including mixins and - multiple inheritance) -3. Integrates nicely with the implicit ``__class__`` reference and - zero-argument ``super()`` syntax introduced by PEP 3135 -4. Can be added to an existing base class without a significant risk of - introducing backwards compatibility problems One mechanism that can achieve this goal is to add a new class initialisation hook, modelled directly on the existing instance @@ -110,7 +111,6 @@ class initialisation hook as follows:: class Example: - @classmethod def __init_class__(cls): # This is invoked after the class is created, but before any # explicit decorators are called @@ -121,13 +121,15 @@ If present on the created object, this new hook will be called by the class creation machinery *after* the ``__class__`` reference has been initialised. For ``types.new_class()``, it will be called as the last step before -returning the created class object. +returning the created class object. ``__init_class__`` is implicitly +converted to a class method when the class is created (prior to the hook +being invoked). If a metaclass wishes to block class initialisation for some reason, it must arrange for ``cls.__init_class__`` to trigger ``AttributeError``. Note, that when ``__init_class__`` is called, the name of the class is not -bound to the new class object yet. As a consequence, the two argument form +yet bound to the new class object. As a consequence, the two argument form of ``super()`` cannot be used to call methods (e.g., ``super(Example, cls)`` wouldn't work in the example above). However, the zero argument form of ``super()`` works as expected, since the ``__class__`` reference is already @@ -139,19 +141,47 @@ but the situation has changed sufficiently in recent years that the idea is worth reconsidering. +In addition, the introduction of the metaclass ``__prepare__`` method in PEP +3115 allows a further enhancement that was not possible in Python 2: this +PEP also proposes that ``type.__prepare__`` be updated to accept a factory +function as a ``namespace`` keyword-only argument. If present, the value +provided as the ``namespace`` argument will be called without arguments +to create the result of ``type.__prepare__`` instead of using a freshly +created dictionary instance. For example, the following will use +an ordered dictionary as the class namespace:: + + class OrderedExample(namespace=collections.OrderedDict): + def __init_class__(cls): + # cls.__dict__ is still a read-only proxy to the class namespace, + # but the underlying storage is an OrderedDict instance + +.. note:: + + This PEP, along with the existing ability to use __prepare__ to share a + single namespace amongst multiple class objects, highlights a possible + issue with the attribute lookup caching: when the underlying mapping is + updated by other means, the attribute lookup cache is not invalidated + correctly (this is a key part of the reason class ``__dict__`` attributes + produce a read-only view of the underlying storage). + + Since the optimisation provided by that cache is highly desirable, + the use of a preexisting namespace as the class namespace may need to + be declared as officially unsupported (since the observed behaviour is + rather strange when the caches get out of sync). + Key Benefits ============ -Replaces many use cases for dynamic setting of ``__metaclass__`` ------------------------------------------------------------------ +Easier use of custom namespaces for a class +------------------------------------------- -For use cases that don't involve completely replacing the defined class, -Python 2 code that dynamically set ``__metaclass__`` can now dynamically -set ``__init_class__`` instead. For more advanced use cases, introduction of -an explicit metaclass (possibly made available as a required base class) will -still be necessary in order to support Python 3. +Currently, to use a different type (such as ``collections.OrderedDict``) for +a class namespace, or to use a pre-populated namespace, it is necessary to +write and use a custom metaclass. With this PEP, using a custom namespace +becomes as simple as specifying an appropriate factory function in the +class header. Easier inheritance of definition time behaviour @@ -201,137 +231,124 @@ that use the zero argument form of ``super()``. -Alternatives -============ +Replaces many use cases for dynamic setting of ``__metaclass__`` +----------------------------------------------------------------- +For use cases that don't involve completely replacing the defined class, +Python 2 code that dynamically set ``__metaclass__`` can now dynamically +set ``__init_class__`` instead. For more advanced use cases, introduction of +an explicit metaclass (possibly made available as a required base class) will +still be necessary in order to support Python 3. -The Python 3 Status Quo + +New Ways of Using Classes +========================= + +The new ``namespace`` keyword in the class header enables a number of +interesting options for controlling the way a class is initialised, +including some aspects of the object models of both Javascript and Ruby. + +All of the examples below are actually possible today through the use of a +custom metaclass:: + + class CustomNamespace(type): + @classmethod + def __prepare__(meta, name, bases, *, namespace=None, **kwds): + parent_namespace = super().__prepare__(name, bases, **kwds) + return namespace() if namespace is not None else parent_namespace + def __new__(meta, name, bases, ns, *, namespace=None, **kwds): + return super().__new__(meta, name, bases, ns, **kwds) + def __init__(cls, name, bases, ns, *, namespace=None, **kwds): + return super().__init__(name, bases, ns, **kwds) + +The advantage of implementing the new keyword directly in +``type.__prepare__`` is that the *only* persistent effect is then +the change in the underlying storage of the class attributes. The metaclass +of the class remains unchanged, eliminating many of the drawbacks +typically associated with these kinds of customisations. + + +Order preserving classes +------------------------ + +:: + + class OrderedClass(namespace=collections.OrderedDict): + a = 1 + b = 2 + c = 3 + + +Prepopulated namespaces ----------------------- -The Python 3 status quo already offers a great deal of flexibility. For -changes which only affect a single class definition and which can be -specified at the time the code is written, then class decorators can be -used to modify a class explicitly. Class decorators largely ignore class -inheritance and can make full use of methods that rely on the ``__class__`` -reference being populated. +:: -Using a custom metaclass provides the same level of power as it did in -Python 2. However, it's notable that, unlike class decorators, a metaclass -cannot call any methods that rely on the ``__class__`` reference, as that -reference is not populated until after the metaclass constructor returns -control to the class creation code. + seed_data = dict(a=1, b=2, c=3) + class PrepopulatedClass(namespace=seed_data.copy): + pass -One major use case for metaclasses actually closely resembles the use of -class decorators. It occurs whenever a metaclass has an implementation that -uses the following pattern:: - class Metaclass(type): - def __new__(meta, *args, **kwds): - cls = super(Metaclass, meta).__new__(meta, *args, **kwds) - # Do something with cls - return cls +Cloning a prototype class +------------------------- -The key difference between this pattern and a class decorator is that it -is automatically inherited by subclasses. However, it also comes with a -major disadvantage: Python does not allow you to inherit from classes with -unrelated metaclasses. +:: -Thus, the status quo requires that developers choose between the following -two alternatives: + class NewClass(namespace=Prototype.__dict__.copy): + pass -* Use a class decorator, meaning that behaviour is not inherited and must be - requested explicitly on every subclass -* Use a metaclass, meaning that behaviour is inherited, but metaclass - conflicts may make integration with other libraries and frameworks more - difficult than it otherwise would be -If this PEP is ultimately rejected, then this is the existing design that -will remain in place by default. +Extending a class +----------------- +.. note:: Just because the PEP makes it *possible* to do this relatively, + cleanly doesn't mean anyone *should* do this! -Restoring the Python 2 metaclass hook -------------------------------------- +:: -One simple alternative would be to restore support for a Python 2 style -``metaclass`` hook in the class body. This would be checked after the class -body was executed, potentially overwriting the metaclass hint provided in the -class header. + from collections import MutableMapping -The main attraction of such an approach is that it would simplify porting -Python 2 applications that make use of this hook (especially those that do -so dynamically). + # The MutableMapping + dict combination should give something that + # generally behaves correctly as a mapping, while still being accepted + # as a class namespace + class ClassNamespace(MutableMapping, dict): + def __init__(self, cls): + self._cls = cls + def __len__(self): + return len(dir(self._cls)) + def __iter__(self): + for attr in dir(self._cls): + yield attr + def __contains__(self, attr): + return hasattr(self._cls, attr) + def __getitem__(self, attr): + return getattr(self._cls, attr) + def __setitem__(self, attr, value): + setattr(self._cls, attr, value) + def __delitem__(self, attr): + delattr(self._cls, attr) -However, this approach does nothing to simplify the process of adding -*inherited* class definition time behaviour, nor does it interoperate -cleanly with the PEP 3135 ``__class__`` and ``super()`` semantics (as with -any metaclass based solution, the ``__metaclass__`` hook would have to run -before the ``__class__`` reference has been populated. + def extend(cls): + return lambda: ClassNamespace(cls) + class Example: + pass -Dynamic class decorators ------------------------- + class ExtendedExample(namespace=extend(Example)): + a = 1 + b = 2 + c = 3 -The original version of this PEP was called "Dynamic class decorators" and -focused solely on a significantly more complicated proposal than that -presented in the current version. + >>> Example.a, Example.b, Example.c + (1, 2, 3) -As with the current version, it proposed that a new step be added to the -class creation process, after the metaclass invocation to construct the -class instance and before the application of lexical decorators. However, -instead of a simple process of calling a single class method that relies -on normal inheritance mechanisms, it proposed a far more complicated -procedure that walked the class MRO looking for decorators stored in -iterable ``__decorators__`` attributes. -Using the current version of the PEP, the scheme originally proposed could -be implemented as:: +Rejected Design Options +======================= - class DynamicDecorators(Base): - @classmethod - def __init_class__(cls): - # Process any classes later in the MRO - try: - mro_chain = super().__init_class__ - except AttributeError: - pass - else: - mro_chain() - # Process any __decorators__ attributes in the MRO - for entry in reversed(cls.mro()): - decorators = entry.__dict__.get("__decorators__", ()) - for deco in reversed(decorators): - cls = deco(cls) -Any subclasses of ``DynamicDecorators`` would then automatically have the -contents of any ``__decorators__`` attributes processed and invoked. - -The mechanism in the current PEP is considered superior, as many issues -to do with ordering and the same decorator being invoked multiple times -just go away, as that kind of thing is taken care of through the use of an -ordinary class method invocation. - - -Automatic metaclass derivation ------------------------------- - -When no appropriate metaclass is found, it's theoretically possible to -automatically derive a metaclass for a new type based on the metaclass hint -and the metaclasses of the bases. - -While adding such a mechanism would reduce the risk of spurious metaclass -conflicts, it would do nothing to improve integration with PEP 3135, would -not help with porting Python 2 code that set ``__metaclass__`` dynamically -and would not provide a more straightforward inherited mechanism for invoking -additional operations after the class invocation is complete. - -In addition, there would still be a risk of metaclass conflicts in cases -where the base metaclasses were not written with multiple inheritance in -mind. In such situations, there's a chance of introducing latent defects -if one or more metaclasses are not invoked correctly. - - -Calling the new hook from ``type.__init__`` -------------------------------------------- +Calling ``__init_class__`` from ``type.__init__`` +------------------------------------------------- Calling the new hook automatically from ``type.__init__``, would achieve most of the goals of this PEP. However, using that approach would mean that @@ -340,11 +357,43 @@ ``super()``), and could not make use of those features themselves. +Requiring an explict decorator on ``__init_class__`` +---------------------------------------------------- + +Originally, this PEP required the explicit use of ``@classmethod`` on the +``__init_class__`` decorator. It was made implicit since there's no +sensible interpretation for leaving it out, and that case would need to be +detected anyway in order to give a useful error message. + +This decision was reinforced after noticing that the user experience of +defining ``__prepare__`` and forgetting the ``@classmethod`` method +decorator is singularly incomprehensible (particularly since PEP 3115 +documents it as an ordinary method, and the current documentation doesn't +explicitly say anything one way or the other). + + +Passing in the namespace directly rather than a factory function +---------------------------------------------------------------- + +At one point, this PEP proposed that the class namespace be passed +directly as a keyword argument, rather than passing a factory function. +However, this encourages an unsupported behaviour (that is, passing the +same namespace to multiple classes, or retaining direct write access +to a mapping used as a class namespace), so the API was switched to +the factory function version. + + Reference Implementation ======================== -The reference implementation has been posted to the `issue tracker`_. +A reference implementation for __init_class__ has been posted to the +`issue tracker`_. It does not yet include the new ``namespace`` parameter +for ``type.__prepare__``. +TODO +==== + +* address the 5 points in http://mail.python.org/pipermail/python-dev/2013-February/123970.html References ========== diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -343,10 +343,10 @@ Provides-Extra (multiple use) ----------------------------- -A string containing the name of an optional feature. Must be printable -ASCII, not containing whitespace, comma (,), or square brackets []. -May be used to make a dependency conditional on whether the optional -feature has been requested. +A string containing the name of an optional feature or "extra" that may +only be available when additional dependencies have been installed. Must +be printable ASCII, not containing whitespace, comma (,), or square +brackets []. See `Optional Features`_ for details on the use of this field. @@ -861,7 +861,7 @@ Within a post-release (``1.0.post1``), the following suffixes are permitted and are ordered as shown:: - devN, + .devN, Note that ``devN`` and ``postN`` must always be preceded by a dot, even when used immediately following a numeric version (e.g. ``1.0.dev456``, @@ -976,8 +976,9 @@ As with other incompatible version schemes, date based versions can be stored in the ``Private-Version`` field. Translating them to a compliant -version is straightforward: the simplest approach is to subtract the year -of the first release from the major component in the release number. +public version is straightforward: the simplest approach is to subtract +the year before the first release from the major component in the release +number. Version specifiers @@ -994,48 +995,93 @@ The comma (",") is equivalent to a logical **and** operator. -Comparison operators must be one of ``<``, ``>``, ``<=``, ``>=``, ``==`` -or ``!=``. - -The ``==`` and ``!=`` operators are strict - in order to match, the -version supplied must exactly match the specified version, with no -additional trailing suffix. - -However, when no comparison operator is provided along with a version -identifier ``V``, it is equivalent to using the following pair of version -clauses:: - - >= V, < V+1 - -where ``V+1`` is the next version after ``V``, as determined by -incrementing the last numeric component in ``V`` (for example, if -``V == 1.0a3``, then ``V+1 == 1.0a4``, while if ``V == 1.0``, then -``V+1 == 1.1``). - -This approach makes it easy to depend on a particular release series -simply by naming it in a version specifier, without requiring any -additional annotation. For example, the following pairs of version -specifiers are equivalent:: - - 2 - >= 2, < 3 - - 3.3 - >= 3.3, < 3.4 - Whitespace between a conditional operator and the following version identifier is optional, as is the whitespace around the commas. + +Compatible release +------------------ + +A compatible release clause omits the comparison operator and matches any +version that is expected to be compatible with the specified version. + +For a given release identifier ``V.N``, the compatible release clause is +approximately equivalent to the pair of comparison clauses:: + + >= V.N, < V+1.dev0 + +where ``V+1`` is the next version after ``V``, as determined by +incrementing the last numeric component in ``V``. For example, +the following version clauses are approximately equivalent:: + + 2.2 + >= 2.2, < 3.dev0 + + 1.4.5 + >= 1.4.5, < 1.5.dev0 + +The difference between the two is that using a compatible release clause +does *not* count as `explicitly mentioning a pre-release`__. + +__ `Handling of pre-releases`_ + +If a pre-release, post-release or developmental release is named in a +compatible release clause as ``V.N.suffix``, then the suffix is ignored +when determining the upper limit of compatibility:: + + 2.2.post3 + >= 2.2.post3, < 3.dev0 + + 1.4.5a4 + >= 1.4.5a4, < 1.5.dev0 + + +Version comparisons +------------------- + +A version comparison clause includes a comparison operator and a version +identifier, and will match any version where the comparison is true. + +Comparison clauses are only needed to cover cases which cannot be handled +with an appropriate compatible release clause, including coping with +dependencies which do not have a robust backwards compatibility policy +and thus break the assumptions of a compatible release clause. + +The defined comparison operators are ``<``, ``>``, ``<=``, ``>=``, ``==``, +and ``!=``. + +The ordered comparison operators ``<``, ``>``, ``<=``, ``>=`` are based +on the consistent ordering defined by the standard `Version scheme`_. + +The ``==`` and ``!=`` operators are based on string comparisons - in order +to match, the version being checked must start with exactly that sequence of +characters. + +.. note:: + + The use of ``==`` when defining dependencies for published distributions + is strongly discouraged, as it greatly complicates the deployment of + security fixes (the strict version comparison operator is intended + primarily for use when defining dependencies for particular + applications while using a shared distribution index). + + +Handling of pre-releases +------------------------ + Pre-releases of any kind, including developmental releases, are implicitly excluded from all version specifiers, *unless* a pre-release or developmental -developmental release is explicitly mentioned in one of the clauses. For -example, this specifier implicitly excludes all pre-releases and development +release is explicitly mentioned in one of the clauses. For example, these +specifiers implicitly exclude all pre-releases and development releases of later versions:: + 2.2 >= 1.0 -While these specifiers would include them:: +While these specifiers would include at least some of them:: + 2.2.dev0 + 2.2, != 2.3b2 >= 1.0a1 >= 1.0c1 >= 1.0, != 1.0b2 @@ -1053,37 +1099,26 @@ Post-releases and purely numeric releases receive no special treatment - they are always included unless explicitly excluded. -Given the above rules, projects which include the ``.0`` suffix for the -first release in a series, such as ``2.5.0``, can easily refer specifically -to that version with the clause ``2.5.0``, while the clause ``2.5`` refers -to that entire series. Projects which omit the ".0" suffix for the first -release of a series, by using a version string like ``2.5`` rather than -``2.5.0``, will need to use an explicit clause like ``>= 2.5, < 2.5.1`` to -refer specifically to that initial release. -Some examples: +Examples +-------- -* ``Requires-Dist: zope.interface (3.1)``: any version that starts with 3.1, +* ``Requires-Dist: zope.interface (3.1)``: version 3.1 or later, but not + version 4.0 or later. Excludes pre-releases and developmental releases. +* ``Requires-Dist: zope.interface (3.1.0)``: version 3.1.0 or later, but not + version 3.2.0 or later. Excludes pre-releases and developmental releases. +* ``Requires-Dist: zope.interface (==3.1)``: any version that starts + with 3.1, excluding pre-releases and developmental releases. +* ``Requires-Dist: zope.interface (3.1.0,!=3.1.3)``: version 3.1.0 or later, + but not version 3.1.3 and not version 3.2.0 or later. Excludes pre-releases + and developmental releases. For this particular project, this means: "any + version of the 3.1 series but not 3.1.3". This is equivalent to: + ``>=3.1, !=3.1.3, <3.2``. +* ``Requires-Python: 2.6``: Any version of Python 2.6 or 2.7. It + automatically excludes Python 3 or later. +* ``Requires-Python: 3.2, < 3.3``: Specifically requires Python 3.2, excluding pre-releases. -* ``Requires-Dist: zope.interface (==3.1)``: equivalent to ``Requires-Dist: - zope.interface (3.1)``. -* ``Requires-Dist: zope.interface (3.1.0)``: any version that starts with - 3.1.0, excluding pre-releases. Since that particular project doesn't - use more than 3 digits, it also means "only the 3.1.0 release". -* ``Requires-Python: 3``: Any Python 3 version, excluding pre-releases. -* ``Requires-Python: >=2.6,<3``: Any version of Python 2.6 or 2.7, including - post-releases (if they were used for Python). It excludes pre releases of - Python 3. -* ``Requires-Python: 2.6.2``: Equivalent to ">=2.6.2,<2.6.3". So this includes - only Python 2.6.2. Of course, if Python was numbered with 4 digits, it would - include all versions of the 2.6.2 series, excluding pre-releases. -* ``Requires-Python: 2.5``: Equivalent to ">=2.5,<2.6". -* ``Requires-Dist: zope.interface (3.1,!=3.1.3)``: any version that starts - with 3.1, excluding pre-releases of 3.1 *and* excluding any version that - starts with "3.1.3". For this particular project, this means: "any version - of the 3.1 series but not 3.1.3". This is equivalent to: - ">=3.1,!=3.1.3,<3.2". -* ``Requires-Python: >=3.3a1``: Any version of Python 3.3+, including +* ``Requires-Python: 3.3a1``: Any version of Python 3.3+, including pre-releases like 3.4a1. @@ -1439,10 +1474,10 @@ The previous interpretation of version specifiers made it very easy to accidentally download a pre-release version of a dependency. This in turn made it difficult for developers to publish pre-release versions -of software to the Python Package Index, as leaving the package set as -public would lead to users inadvertently downloading pre-release software, -while hiding it would defeat the purpose of publishing it for user -testing. +of software to the Python Package Index, as even marking the package as +hidden wasn't enough to keep automated tools from downloading it, and also +made it harder for users to obtain the test release manually through the +main PyPI web interface. The previous interpretation also excluded post-releases from some version specifiers for no adequately justified reason. @@ -1451,6 +1486,16 @@ accept a pre-release version as satisfying a dependency, while allowing pre-release versions to be explicitly requested when needed. +The "some forward compatibility assumed" default version constraint is +taken directly from the Ruby community's "pessimistic version constraint" +operator [4]_ to allow projects to take a cautious approach to forward +compatibility promises, while still easily setting a minimum required +version for their dependencies. It is made the default behaviour rather +than needing a separate operator in order to explicitly discourage +overspecification of dependencies by library developers. The explicit +comparison operators remain available to cope with dependencies with +unreliable or non-existent backwards compatibility policies. + Packaging, build and installation dependencies ---------------------------------------------- @@ -1548,6 +1593,9 @@ .. [3] Version compatibility analysis script: http://hg.python.org/peps/file/default/pep-0426/pepsort.py +.. [4] Pessimistic version constraint + http://docs.rubygems.org/read/chapter/16 + Appendix A ========== diff --git a/pep-0427.txt b/pep-0427.txt --- a/pep-0427.txt +++ b/pep-0427.txt @@ -101,6 +101,15 @@ accompanying .exe wrappers. Windows installers may want to add them during install. +Recommended archiver features +''''''''''''''''''''''''''''' + +Place ``.dist-info`` at the end of the archive. + Archivers are encouraged to place the ``.dist-info`` files physically + at the end of the archive. This enables some potentially interesting + ZIP tricks including the ability to amend the metadata without + rewriting the entire archive. + File Format ----------- @@ -149,9 +158,14 @@ re.sub("[^\w\d.]+", "_", distribution, re.UNICODE) -The filename is Unicode. It will be some time before the tools are -updated to support non-ASCII filenames, but they are supported in this -specification. +The archive filename is Unicode. It will be some time before the tools +are updated to support non-ASCII filenames, but they are supported in +this specification. + +The filenames *inside* the archive are encoded as UTF-8. Although some +ZIP clients in common use do not properly display UTF-8 filenames, +the encoding is supported by both the ZIP specification and Python's +``zipfile``. File contents ''''''''''''' diff --git a/pep-0428.txt b/pep-0428.txt --- a/pep-0428.txt +++ b/pep-0428.txt @@ -55,6 +55,15 @@ .. _`Unipath`: https://bitbucket.org/sluggo/unipath/overview +Implementation +============== + +The implementation of this proposal is tracked in the ``pep428`` branch +of pathlib's `Mercurial repository`_. + +.. _`Mercurial repository`: https://bitbucket.org/pitrou/pathlib/ + + Why an object-oriented API ========================== @@ -341,6 +350,15 @@ >>> bytes(p) b'/home/antoine/pathlib/setup.py' +To represent the path as a ``file`` URI, call the ``as_uri()`` method:: + + >>> p = PurePosixPath('/etc/passwd') + >>> p.as_uri() + 'file:///etc/passwd' + >>> p = PureNTPath('c:/Windows') + >>> p.as_uri() + 'file:///c:/Windows' + Properties ---------- diff --git a/pep-0435.txt b/pep-0435.txt new file mode 100644 --- /dev/null +++ b/pep-0435.txt @@ -0,0 +1,542 @@ +PEP: 435 +Title: Adding an Enum type to the Python standard library +Version: $Revision$ +Last-Modified: $Date$ +Author: Barry Warsaw , + Eli Bendersky +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 2013-02-23 +Python-Version: 3.4 +Post-History: 2013-02-23 + + +Abstract +======== + +This PEP proposes adding an enumeration type to the Python standard library. +Specifically, it proposes moving the existing ``flufl.enum`` package by Barry +Warsaw into the standard library. Much of this PEP is based on the "using" +[1]_ document from the documentation of ``flufl.enum``. + +An enumeration is a set of symbolic names bound to unique, constant integer +values. Within an enumeration, the values can be compared by identity, and the +enumeration itself can be iterated over. Enumeration items can be converted to +and from their integer equivalents, supporting use cases such as storing +enumeration values in a database. + + +Status of discussions +===================== + +The idea of adding an enum type to Python is not new - PEP 354 [2]_ is a +previous attempt that was rejected in 2005. Recently a new set of discussions +was initiated [3]_ on the ``python-ideas`` mailing list. Many new ideas were +proposed in several threads; after a lengthy discussion Guido proposed adding +``flufl.enum`` to the standard library [4]_. This PEP is an attempt to +formalize this decision as well as discuss a number of variations that can be +considered for inclusion. + + +Motivation +========== + +*[Based partly on the Motivation stated in PEP 354]* + +The properties of an enumeration are useful for defining an immutable, related +set of constant values that have a defined sequence but no inherent semantic +meaning. Classic examples are days of the week (Sunday through Saturday) and +school assessment grades ('A' through 'D', and 'F'). Other examples include +error status values and states within a defined process. + +It is possible to simply define a sequence of values of some other basic type, +such as ``int`` or ``str``, to represent discrete arbitrary values. However, +an enumeration ensures that such values are distinct from any others including, +importantly, values within other enumerations, and that operations without +meaning ("Wednesday times two") are not defined for these values. It also +provides a convenient printable representation of enum values without requiring +tedious repetition while defining them (i.e. no ``GREEN = 'green'``). + + +Module and type name +==================== + +We propose to add a module named ``enum`` to the standard library. The main +type exposed by this module is ``Enum``. Hence, to import the ``Enum`` type +user code will run:: + + >>> from enum import Enum + + +Proposed semantics for the new enumeration type +=============================================== + +Creating an Enum +---------------- + +Enumerations are created using the class syntax, which makes them easy to read +and write. Every enumeration value must have a unique integer value and the +only restriction on their names is that they must be valid Python identifiers. +To define an enumeration, derive from the ``Enum`` class and add attributes +with assignment to their integer values:: + + >>> from enum import Enum + >>> class Colors(Enum): + ... red = 1 + ... green = 2 + ... blue = 3 + +Enumeration values are compared by identity:: + + >>> Colors.red is Colors.red + True + >>> Colors.blue is Colors.blue + True + >>> Colors.red is not Colors.blue + True + >>> Colors.blue is Colors.red + False + +Enumeration values have nice, human readable string representations:: + + >>> print(Colors.red) + Colors.red + +...while their repr has more information:: + + >>> print(repr(Colors.red)) + + +The enumeration value names are available through the class members:: + + >>> for member in Colors.__members__: + ... print(member) + red + green + blue + +Let's say you wanted to encode an enumeration value in a database. You might +want to get the enumeration class object from an enumeration value:: + + >>> cls = Colors.red.enum + >>> print(cls.__name__) + Colors + +Enums also have a property that contains just their item name:: + + >>> print(Colors.red.name) + red + >>> print(Colors.green.name) + green + >>> print(Colors.blue.name) + blue + +The str and repr of the enumeration class also provides useful information:: + + >>> print(Colors) + + >>> print(repr(Colors)) + + +You can extend previously defined Enums by subclassing:: + + >>> class MoreColors(Colors): + ... pink = 4 + ... cyan = 5 + +When extended in this way, the base enumeration's values are identical to the +same named values in the derived class:: + + >>> Colors.red is MoreColors.red + True + >>> Colors.blue is MoreColors.blue + True + +However, these are not doing comparisons against the integer equivalent +values, because if you define an enumeration with similar item names and +integer values, they will not be identical:: + + >>> class OtherColors(Enum): + ... red = 1 + ... blue = 2 + ... yellow = 3 + >>> Colors.red is OtherColors.red + False + >>> Colors.blue is not OtherColors.blue + True + +These enumeration values are not equal, nor do they hash equally:: + + >>> Colors.red == OtherColors.red + False + >>> len(set((Colors.red, OtherColors.red))) + 2 + +Ordered comparisons between enumeration values are *not* supported. Enums are +not integers:: + + >>> Colors.red < Colors.blue + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.red <= Colors.blue + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.blue > Colors.green + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.blue >= Colors.green + Traceback (most recent call last): + ... + NotImplementedError + +Equality comparisons are defined though:: + + >>> Colors.blue == Colors.blue + True + >>> Colors.green != Colors.blue + True + +Enumeration values do not support ordered comparisons:: + + >>> Colors.red < Colors.blue + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.red < 3 + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.red <= 3 + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.blue > 2 + Traceback (most recent call last): + ... + NotImplementedError + >>> Colors.blue >= 2 + Traceback (most recent call last): + ... + NotImplementedError + +While equality comparisons are allowed, comparisons against non-enumeration +values will always compare not equal:: + + >>> Colors.green == 2 + False + >>> Colors.blue == 3 + False + >>> Colors.green != 3 + True + >>> Colors.green == 'green' + False + +If you really want the integer equivalent values, you can convert enumeration +values explicitly using the ``int()`` built-in. This is quite convenient for +storing enums in a database, as well as for interoperability with C extensions +that expect integers:: + + >>> int(Colors.red) + 1 + >>> int(Colors.green) + 2 + >>> int(Colors.blue) + 3 + +You can also convert back to the enumeration value by calling the Enum +subclass, passing in the integer value for the item you want:: + + >>> Colors(1) + + >>> Colors(2) + + >>> Colors(3) + + >>> Colors(1) is Colors.red + True + +The Enum subclass also accepts the string name of the enumeration value:: + + >>> Colors('red') + + >>> Colors('blue') is Colors.blue + True + +You get exceptions though, if you try to use invalid arguments:: + + >>> Colors('magenta') + Traceback (most recent call last): + ... + ValueError: magenta + >>> Colors(99) + Traceback (most recent call last): + ... + ValueError: 99 + +The Enum base class also supports getitem syntax, exactly equivalent to the +class's call semantics:: + + >>> Colors[1] + + >>> Colors[2] + + >>> Colors[3] + + >>> Colors[1] is Colors.red + True + >>> Colors['red'] + + >>> Colors['blue'] is Colors.blue + True + >>> Colors['magenta'] + Traceback (most recent call last): + ... + ValueError: magenta + >>> Colors[99] + Traceback (most recent call last): + ... + ValueError: 99 + +The integer equivalent values serve another purpose. You may not define two +enumeration values with the same integer value:: + + >>> class Bad(Enum): + ... cartman = 1 + ... stan = 2 + ... kyle = 3 + ... kenny = 3 # Oops! + ... butters = 4 + Traceback (most recent call last): + ... + TypeError: Multiple enum values: 3 + +You also may not duplicate values in derived enumerations:: + + >>> class BadColors(Colors): + ... yellow = 4 + ... chartreuse = 2 # Oops! + Traceback (most recent call last): + ... + TypeError: Multiple enum values: 2 + +The Enum class support iteration. Enumeration values are returned in the +sorted order of their integer equivalent values:: + + >>> [v.name for v in MoreColors] + ['red', 'green', 'blue', 'pink', 'cyan'] + >>> [int(v) for v in MoreColors] + [1, 2, 3, 4, 5] + +Enumeration values are hashable, so they can be used in dictionaries and sets:: + + >>> apples = {} + >>> apples[Colors.red] = 'red delicious' + >>> apples[Colors.green] = 'granny smith' + >>> for color in sorted(apples, key=int): + ... print(color.name, '->', apples[color]) + red -> red delicious + green -> granny smith + + +Pickling +-------- + +Enumerations created with the class syntax can also be pickled and unpickled:: + + >>> from enum.tests.fruit import Fruit + >>> from pickle import dumps, loads + >>> Fruit.tomato is loads(dumps(Fruit.tomato)) + True + + +Convenience API +--------------- + +You can also create enumerations using the convenience function ``make()``, +which takes an iterable object or dictionary to provide the item names and +values. ``make()`` is a module-level function. + +The first argument to ``make()`` is the name of the enumeration, and it returns +the so-named `Enum` subclass. The second argument is a *source* which can be +either an iterable or a dictionary. In the most basic usage, *source* returns +a sequence of strings which name the enumeration items. In this case, the +values are automatically assigned starting from 1:: + + >>> import enum + >>> enum.make('Animals', ('ant', 'bee', 'cat', 'dog')) + + +The items in source can also be 2-tuples, where the first item is the +enumeration value name and the second is the integer value to assign to the +value. If 2-tuples are used, all items must be 2-tuples:: + + >>> def enumiter(): + ... start = 1 + ... while True: + ... yield start + ... start <<= 1 + >>> enum.make('Flags', zip(list('abcdefg'), enumiter())) + + + +Proposed variations +=================== + +Some variations were proposed during the discussions in the mailing list. +Here's some of the more popular ones. + + +Not having to specify values for enums +-------------------------------------- + +Michael Foord proposed (and Tim Delaney provided a proof-of-concept +implementation) to use metaclass magic that makes this possible:: + + class Color(Enum): + red, green, blue + +The values get actually assigned only when first looked up. + +Pros: cleaner syntax that requires less typing for a very common task (just +listing enumeration names without caring about the values). + +Cons: involves much magic in the implementation, which makes even the +definition of such enums baffling when first seen. Besides, explicit is +better than implicit. + + +Using special names or forms to auto-assign enum values +------------------------------------------------------- + +A different approach to avoid specifying enum values is to use a special name +or form to auto assign them. For example:: + + class Color(Enum): + red = None # auto-assigned to 0 + green = None # auto-assigned to 1 + blue = None # auto-assigned to 2 + +More flexibly:: + + class Color(Enum): + red = 7 + green = None # auto-assigned to 8 + blue = 19 + purple = None # auto-assigned to 20 + +Some variations on this theme: + +#. A special name ``auto`` imported from the enum package. +#. Georg Brandl proposed ellipsis (``...``) instead of ``None`` to achieve the + same effect. + +Pros: no need to manually enter values. Makes it easier to change the enum and +extend it, especially for large enumerations. + +Cons: actually longer to type in many simple cases. The argument of explicit +vs. implicit applies here as well. + + +Use-cases in the standard library +================================= + +The Python standard library has many places where the usage of enums would be +beneficial to replace other idioms currently used to represent them. Such +usages can be divided to two categories: user-code facing constants, and +internal constants. + +User-code facing constants like ``os.SEEK_*``, ``socket`` module constants, +decimal rounding modes, HTML error codes could benefit from being enums had +they been implemented this way from the beginning. At this point, however, at +the risk of breaking user code (that relies on the constants' actual values +rather than their meaning) such a change cannot be made. This does not mean +that future uses in the stdlib can't use an enum for defining new user-code +facing constants. + +Internal constants are not seen by user code but are employed internally by +stdlib modules. It appears that nothing should stand in the way of +implementing such constants with enums. Some examples uncovered by a very +partial skim through the stdlib: ``binhex``, ``imaplib``, ``http/client``, +``urllib/robotparser``, ``idlelib``, ``concurrent.futures``, ``turtledemo``. + +In addition, looking at the code of the Twisted library, there are many use +cases for replacing internal state constants with enums. The same can be said +about a lot of networking code (especially implementation of protocols) and +can be seen in test protocols written with the Tulip library as well. + + +Differences from PEP 354 +======================== + +Unlike PEP 354, enumeration values are not defined as a sequence of strings, +but as attributes of a class. This design was chosen because it was felt that +class syntax is more readable. + +Unlike PEP 354, enumeration values require an explicit integer value. This +difference recognizes that enumerations often represent real-world values, or +must interoperate with external real-world systems. For example, to store an +enumeration in a database, it is better to convert it to an integer on the way +in and back to an enumeration on the way out. Providing an integer value also +provides an explicit ordering. However, there is no automatic conversion to +and from the integer values, because explicit is better than implicit. + +Unlike PEP 354, this implementation does use a metaclass to define the +enumeration's syntax, and allows for extended base-enumerations so that the +common values in derived classes are identical (a singleton model). While PEP +354 dismisses this approach for its complexity, in practice any perceived +complexity, though minimal, is hidden from users of the enumeration. + +Unlike PEP 354, enumeration values can only be tested by identity comparison. +This is to emphasize the fact that enumeration values are singletons, much +like ``None``. + + +Acknowledgments +=============== + +This PEP describes the ``flufl.enum`` package by Barry Warsaw. ``flufl.enum`` +is based on an example by Jeremy Hylton. It has been modified and extended +by Barry Warsaw for use in the GNU Mailman [5]_ project. Ben Finney is the +author of the earlier enumeration PEP 354. + + +References +========== + +.. [1] http://pythonhosted.org/flufl.enum/docs/using.html +.. [2] http://www.python.org/dev/peps/pep-0354/ +.. [3] http://mail.python.org/pipermail/python-ideas/2013-January/019003.html +.. [4] http://mail.python.org/pipermail/python-ideas/2013-February/019373.html +.. [5] http://www.list.org + + +Copyright +========= + +This document has been placed in the public domain. + + +Todo +==== + + * Mark PEP 354 "superseded by" this one, if accepted + * New package name within stdlib - enum? (top-level) + * For make, can we add an API like namedtuple's? + make('Animals, 'ant bee cat dog') + I.e. when make sees a string argument it splits it, making it similar to a + tuple but with far less manual quote typing. OTOH, it just saves a ".split" + so may not be worth the effort ? + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: + diff --git a/pep-0436.txt b/pep-0436.txt new file mode 100644 --- /dev/null +++ b/pep-0436.txt @@ -0,0 +1,480 @@ +PEP: 436 +Title: The Argument Clinic DSL +Version: $Revision$ +Last-Modified: $Date$ +Author: Larry Hastings +Discussions-To: Python-Dev +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 22-Feb-2013 + + +Abstract +======== + +This document proposes "Argument Clinic", a DSL designed to facilitate +argument processing for built-in functions in the implementation of +CPython. + + +Rationale and Goals +=================== + +The primary implementation of Python, "CPython", is written in a +mixture of Python and C. One of the implementation details of CPython +is what are called "built-in" functions -- functions available to +Python programs but written in C. When a Python program calls a +built-in function and passes in arguments, those arguments must be +translated from Python values into C values. This process is called +"parsing arguments". + +As of CPython 3.3, arguments to functions are primarily parsed with +one of two functions: the original ``PyArg_ParseTuple()``, [1]_ and +the more modern ``PyArg_ParseTupleAndKeywords()``. [2]_ The former +function only handles positional parameters; the latter also +accommodates keyword and keyword-only parameters, and is preferred for +new code. + +``PyArg_ParseTuple()`` was a reasonable approach when it was first +conceived. The programmer specified the translation for the arguments +in a "format string": [3]_ each parameter matched to a "format unit", +a one-or-two character sequence telling ``PyArg_ParseTuple()`` what +Python types to accept and how to translate them into the appropriate +C value for that parameter. There were only a dozen or so of these +"format units", and each one was distinct and easy to understand. + +Over the years the ``PyArg_Parse`` interface has been extended in +numerous ways. The modern API is quite complex, to the point that it +is somewhat painful to use. Consider: + + * There are now forty different "format units"; a few are even three + characters long. This makes it difficult to understand what the + format string says without constantly cross-indexing it with the + documentation. + * There are also six meta-format units that may be buried in the + format string. (They are: ``"()|$:;"``.) + * The more format units are added, the less likely it is the + implementer can pick an easy-to-use mnemonic for the format unit, + because the character of choice is probably already in use. In + other words, the more format units we have, the more obtuse the + format units become. + * Several format units are nearly identical to others, having only + subtle differences. This makes understanding the exact semantics + of the format string even harder. + * The docstring is specified as a static C string, which is mildly + bothersome to read and edit. + * When adding a new parameter to a function using + ``PyArg_ParseTupleAndKeywords()``, it's necessary to touch six + different places in the code: [4]_ + + * Declaring the variable to store the argument. + * Passing in a pointer to that variable in the correct spot in + ``PyArg_ParseTupleAndKeywords()``, also passing in any + "length" or "converter" arguments in the correct order. + * Adding the name of the argument in the correct spot of the + "keywords" array passed in to + ``PyArg_ParseTupleAndKeywords()``. + * Adding the format unit to the correct spot in the format + string. + * Adding the parameter to the prototype in the docstring. + * Documenting the parameter in the docstring. + + * There is currently no mechanism for builtin functions to provide + their "signature" information (see ``inspect.getfullargspec`` and + ``inspect.Signature``). Adding this information using a mechanism + similar to the existing ``PyArg_Parse`` functions would require + repeating ourselves yet again. + +The goal of Argument Clinic is to replace this API with a mechanism +inheriting none of these downsides: + + * You need specify each parameter only once. + * All information about a parameter is kept together in one place. + * For each parameter, you specify its type in C; Argument Clinic + handles the translation from Python value into C value for you. + * Argument Clinic also allows for fine-tuning of argument processing + behavior with highly-readable "flags", both per-parameter and + applying across the whole function. + * Docstrings are written in plain text. + * From this, Argument Clinic generates for you all the mundane, + repetitious code and data structures CPython needs internally. + Once you've specified the interface, the next step is simply to + write your implementation using native C types. Every detail of + argument parsing is handled for you. + +Future goals of Argument Clinic include: + + * providing signature information for builtins, and + * speed improvements to the generated code. + + +DSL Syntax Summary +================== + +The Argument Clinic DSL is specified as a comment embedded in a C +file, as follows. The "Example" column on the right shows you sample +input to the Argument Clinic DSL, and the "Section" column on the left +specifies what each line represents in turn. + +:: + + +-----------------------+-----------------------------------------------------+ + | Section | Example | + +-----------------------+-----------------------------------------------------+ + | Clinic DSL start | /*[clinic] | + | Function declaration | module.function_name -> return_annotation | + | Function flags | flag flag2 flag3=value | + | Parameter declaration | type name = default | + | Parameter flags | flag flag2 flag3=value | + | Parameter docstring | Lorem ipsum dolor sit amet, consectetur | + | | adipisicing elit, sed do eiusmod tempor | + | Function docstring | Lorem ipsum dolor sit amet, consectetur adipisicing | + | | elit, sed do eiusmod tempor incididunt ut labore et | + | Clinic DSL end | [clinic]*/ | + | Clinic output | ... | + | Clinic output end | /*[clinic end output:]*/ | + +-----------------------+-----------------------------------------------------+ + + +General Behavior Of the Argument Clinic DSL +------------------------------------------- + +All lines support ``#`` as a line comment delimiter *except* +docstrings. Blank lines are always ignored. + +Like Python itself, leading whitespace is significant in the Argument +Clinic DSL. The first line of the "function" section is the +declaration; all subsequent lines at the same indent are function +flags. Once you indent, the first line is a parameter declaration; +subsequent lines at that indent are parameter flags. Indent one more +time for the lines of the parameter docstring. Finally, dedent back +to the same level as the function declaration for the function +docstring. + + +Function Declaration +-------------------- + +The return annotation is optional. If skipped, the arrow ("``->``") +must also be omitted. + + +Parameter Declaration +--------------------- + +The "type" is a C type. If it's a pointer type, you must specify a +single space between the type and the "``*``", and zero spaces between +the "``*``" and the name. (e.g. "``PyObject *foo``", not "``PyObject* +foo``") + +The "name" must be a legal C identifier. + +The "default" is a Python value. Default values are optional; if not +specified you must omit the equals sign too. Parameters which don't +have a default are implicitly required. The default value is +dynamically assigned, "live" in the generated C code, and although +it's specified as a Python value, it's translated into a native C +value in the generated C code. + +It's explicitly permitted to end the parameter declaration line with a +semicolon, though the semicolon is optional. This is intended to +allow directly cutting and pasting in declarations from C code. +However, the preferred style is without the semicolon. + + +Flags +----- + +"Flags" are like "``make -D``" arguments. They're unordered. Flags +lines are parsed much like the shell (specifically, using +``shlex.split()`` [5]_ ). You can have as many flag lines as you +like. Specifying a flag twice is currently an error. + +Supported flags for functions: + +``basename`` + The basename to use for the generated C functions. By default this + is the name of the function from the DSL, only with periods replaced + by underscores. + +``positional-only`` + This function only supports positional parameters, not keyword + parameters. See `Functions With Positional-Only Parameters`_ below. + +Supported flags for parameters: + +``bitwise`` + If the Python integer passed in is signed, copy the bits directly + even if it is negative. Only valid for unsigned integer types. + +``converter`` + Backwards-compatibility support for parameter "converter" + functions. [6]_ The value should be the name of the converter + function in C. Only valid when the type of the parameter is + ``void *``. + +``default`` + The Python value to use in place of the parameter's actual default + in Python contexts. Specifically, when specified, this value will + be used for the parameter's default in the docstring, and in the + ``Signature``. (TBD: If the string is a valid Python expression + which can be rendered into a Python value using ``eval()``, then the + result of ``eval()`` on it will be used as the default in the + ``Signature``.) Ignored if there is no default. + +``encoding`` + Encoding to use when encoding a Unicode string to a ``char *``. + Only valid when the type of the parameter is ``char *``. + +``group=`` + This parameter is part of a group of options that must either all be + specified or none specified. Parameters in the same "group" must be + contiguous. The value of the group flag is the name used for the + group variable, and therefore must be legal as a C identifier. Only + valid for functions marked "``positional-only``"; see `Functions + With Positional-Only Parameters`_ below. + +``immutable`` + Only accept immutable values. + +``keyword-only`` + This parameter (and all subsequent parameters) is keyword-only. + Keyword-only parameters must also be optional parameters. Not valid + for positional-only functions. + +``length`` + This is an iterable type, and we also want its length. The DSL will + generate a second ``Py_ssize_t`` variable; its name will be this + parameter's name appended with "``_length``". + +``nullable`` + ``None`` is a legal argument for this parameter. If ``None`` is + supplied on the Python side, the equivalent C argument will be + ``NULL``. Only valid for pointer types. + +``required`` + Normally any parameter that has a default value is automatically + optional. A parameter that has "required" set will be considered + required (non-optional) even if it has a default value. The + generated documentation will also not show any default value. + +``types`` + Space-separated list of acceptable Python types for this object. + There are also four special-case types which represent Python + protocols: + + * buffer + * mapping + * number + * sequence + +``zeroes`` + This parameter is a string type, and its value should be allowed to + have embedded zeroes. Not valid for all varieties of string + parameters. + + +Python Code +----------- + +Argument Clinic also permits embedding Python code inside C files, +which is executed in-place when Argument Clinic processes the file. +Embedded code looks like this: + +:: + + /*[python] + + # this is python code! + print("/" + "* Hello world! *" + "/") + + [python]*/ + +Any Python code is valid. Python code sections in Argument Clinic can +also be used to modify Clinic's behavior at runtime; for example, see +`Extending Argument Clinic`_. + + +Output +====== + +Argument Clinic writes its output in-line in the C file, immediately +after the section of Clinic code. For "python" sections, the output +is everything printed using ``builtins.print``. For "clinic" +sections, the output is valid C code, including: + + * a ``#define`` providing the correct ``methoddef`` structure for the + function + * a prototype for the "impl" function -- this is what you'll write + to implement this function + * a function that handles all argument processing, which calls your + "impl" function + * the definition line of the "impl" function + * and a comment indicating the end of output. + +The intention is that you will write the body of your impl function +immediately after the output -- as in, you write a left-curly-brace +immediately after the end-of-output comment and write the +implementation of the builtin in the body there. (It's a bit strange +at first, but oddly convenient.) + +Argument Clinic will define the parameters of the impl function for +you. The function will take the "self" parameter passed in +originally, all the parameters you define, and possibly some extra +generated parameters ("length" parameters; also "group" parameters, +see next section). + +Argument Clinic also writes a checksum for the output section. This +is a valuable safety feature: if you modify the output by hand, Clinic +will notice that the checksum doesn't match, and will refuse to +overwrite the file. (You can force Clinic to overwrite with the +"``-f``" command-line argument; Clinic will also ignore the checksums +when using the "``-o``" command-line argument.) + + +Functions With Positional-Only Parameters +========================================= + +A significant fraction of Python builtins implemented in C use the +older positional-only API for processing arguments +(``PyArg_ParseTuple()``). In some instances, these builtins parse +their arguments differently based on how many arguments were passed +in. This can provide some bewildering flexibility: there may be +groups of optional parameters, which must either all be specified or +none specified. And occasionally these groups are on the *left!* (For +example: ``curses.window.addch()``.) + +Argument Clinic supports these legacy use-cases with a special set of +flags. First, set the flag "``positional-only``" on the entire +function. Then, for every group of parameters that is collectively +optional, add a "``group=``" flag with a unique string to all the +parameters in that group. Note that these groups are permitted on the +right *or left* of any required parameters! However, all groups +(including the group of required parameters) must be contiguous. + +The impl function generated by Clinic will add an extra parameter for +every group, "``int _group``". This argument will be nonzero +if the group was specified on this call, and zero if it was not. + +Note that when operating in this mode, you cannot specify default +arguments. You can simulate defaults by putting parameters in +individual groups and detecting whether or not they were specified; +generally speaking it's better to simply not use "positional-only" +where it isn't absolutely necessary. (TBD: It might be possible to +relax this restriction. But adding default arguments into the mix of +groups would seemingly make calculating which groups are active a good +deal harder.) + +Also, note that it's possible to specify a set of groups to a function +such that there are several valid mappings from the number of +arguments to a valid set of groups. If this happens, Clinic will exit +with an error message. This should not be a problem, as +positional-only operation is only intended for legacy use cases, and +all the legacy functions using this quirky behavior should have +unambiguous mappings. + + +Current Status +============== + +As of this writing, there is a working prototype implementation of +Argument Clinic available online. [7]_ The prototype implements the +syntax above, and generates code using the existing ``PyArg_Parse`` +APIs. It supports translating to all current format units except +``"w*"``. Sample functions using Argument Clinic exercise all major +features, including positional-only argument parsing. + + +Extending Argument Clinic +------------------------- + +The prototype also currently provides an experimental extension +mechanism, allowing adding support for new types on-the-fly. See +``Modules/posixmodule.c`` in the prototype for an example of its use. + + +Notes / TBD +=========== + +* Guido proposed having the "function docstring" be hand-written inline, + in the middle of the output, something like this: + + :: + + /*[clinic] + ... prototype and parameters (including parameter docstrings) go here + [clinic]*/ + ... some output ... + /*[clinic docstring start]*/ + ... hand-edited function docstring goes here <-- you edit this by hand! + /*[clinic docstring end]*/ + ... more output + /*[clinic output end]*/ + + I tried it this way and don't like it -- I think it's clumsy. I + prefer that everything you write goes in one place, rather than + having an island of hand-edited stuff in the middle of the DSL + output. + +* Do we need to support tuple unpacking? (The "``(OOO)``" style + format string.) Boy I sure hope not. + +* What about Python functions that take no arguments? This syntax + doesn't provide for that. Perhaps a lone indented "None" should + mean "no arguments"? + +* This approach removes some dynamism / flexibility. With the + existing syntax one could theoretically pass in different encodings + at runtime for the "``es``"/"``et``" format units. AFAICT CPython + doesn't do this itself, however it's possible external users might + do this. (Trivia: there are no uses of "``es``" exercised by + regrtest, and all the uses of "``et``" exercised are in + socketmodule.c, except for one in _ssl.c. They're all static, + specifying the encoding ``"idna"``.) + +* Right now the "basename" flag on a function changes the ``#define + methoddef`` name too. Should it, or should the #define'd methoddef + name always be ``{module_name}_{function_name}`` ? + + +References +========== + +.. [1] ``PyArg_ParseTuple()``: + http://docs.python.org/3/c-api/arg.html#PyArg_ParseTuple + +.. [2] ``PyArg_ParseTupleAndKeywords()``: + http://docs.python.org/3/c-api/arg.html#PyArg_ParseTupleAndKeywords + +.. [3] ``PyArg_`` format units: + http://docs.python.org/3/c-api/arg.html#strings-and-buffers + +.. [4] Keyword parameters for extension functions: + http://docs.python.org/3/extending/extending.html#keyword-parameters-for-extension-functions + +.. [5] ``shlex.split()``: + http://docs.python.org/3/library/shlex.html#shlex.split + +.. [6] ``PyArg_`` "converter" functions, see ``"O&"`` in this section: + http://docs.python.org/3/c-api/arg.html#other-objects + +.. [7] Argument Clinic prototype: + https://bitbucket.org/larry/python-clinic/ + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Wed Mar 6 05:56:24 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 06 Mar 2013 05:56:24 +0100 Subject: [Python-checkins] Daily reference leaks (b87e9b8dc9ad): sum=12 Message-ID: results for b87e9b8dc9ad on branch "default" -------------------------------------------- test_support leaked [0, 0, -1] references, sum=-1 test_capi leaked [1, 1, 1] references, sum=3 test_capi leaked [2, 4, 4] memory blocks, sum=10 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogjYSFNG', '-x'] From python-checkins at python.org Wed Mar 6 10:32:46 2013 From: python-checkins at python.org (terry.reedy) Date: Wed, 6 Mar 2013 10:32:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Update_link_for_Visual_C+?= =?utf-8?q?+_Express_2010=2E_Old_link_gets_forwarded_to_2012_page=2E?= Message-ID: <3ZLVBQ1r8kzSgC@mail.python.org> http://hg.python.org/devguide/rev/e9fc41c11f6b changeset: 605:e9fc41c11f6b user: Terry Jan Reedy date: Wed Mar 06 04:29:49 2013 -0500 summary: Update link for Visual C++ Express 2010. Old link gets forwarded to 2012 page. files: setup.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -188,7 +188,7 @@ **Python 3.3** and later use Microsoft Visual Studio 2010. You can download Microsoft Visual C++ 2010 Express `from Microsoft's site -`_. +`_. Most Python versions prior to 3.3 use Microsoft Visual Studio 2008. You can download Microsoft Visual C++ 2008 Express Edition with SP1 -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Wed Mar 6 11:35:13 2013 From: python-checkins at python.org (terry.reedy) Date: Wed, 6 Mar 2013 11:35:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_link_for_VC++_2010_to?= =?utf-8?q?_one_for_2008=2E_Hide_both_urls_with_text_labels=2E?= Message-ID: <3ZLWZT4jhBz7Lpr@mail.python.org> http://hg.python.org/devguide/rev/1a2b7409e897 changeset: 606:1a2b7409e897 user: Terry Jan Reedy date: Wed Mar 06 05:34:42 2013 -0500 summary: Add link for VC++ 2010 to one for 2008. Hide both urls with text labels. files: setup.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -199,8 +199,10 @@ checkout contains the build files for the Python version you are building. The full version of Visual Studio is not necessary for common tasks with 32-bit builds; the gratis C++ Express versions linked above are sufficient. -The limitations of the Express versions are given at -http://msdn.microsoft.com/en-us/library/hs24szh9%28v=VS.90%29.aspx . +Their limitations are given `here (2008) +`_ +and `here (2010) +`_. To build from the Visual Studio GUI, open the ``pcbuild.sln`` solution file with Visual Studio. Choose the :menuselection:`Build Solution` option -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Wed Mar 6 11:37:33 2013 From: python-checkins at python.org (terry.reedy) Date: Wed, 6 Mar 2013 11:37:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_self_for_idlelib?= Message-ID: <3ZLWd973LBzQjJ@mail.python.org> http://hg.python.org/devguide/rev/4eec85c5226a changeset: 607:4eec85c5226a user: Terry Jan Reedy date: Wed Mar 06 05:37:12 2013 -0500 summary: Add self for idlelib files: experts.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -123,7 +123,7 @@ hmac html ezio.melotti http -idlelib kbk +idlelib kbk, terry.reedy imaplib imghdr imp -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Wed Mar 6 14:46:43 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 14:46:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_some_formatting?= Message-ID: <3ZLbqR65rhzN9V@mail.python.org> http://hg.python.org/cpython/rev/800875963e42 changeset: 82510:800875963e42 user: Eli Bendersky date: Wed Mar 06 05:45:57 2013 -0800 summary: Fix some formatting files: Modules/_ctypes/callproc.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1078,9 +1078,10 @@ args[0].ffi_type = &ffi_type_pointer; args[0].value.p = pIunk; pa = &args[1]; - } else + } else { #endif pa = &args[0]; + } /* Convert the arguments */ for (i = 0; i < n; ++i, ++pa) { @@ -1096,9 +1097,7 @@ if (argtypes && argtype_count > i) { PyObject *v; converter = PyTuple_GET_ITEM(argtypes, i); - v = PyObject_CallFunctionObjArgs(converter, - arg, - NULL); + v = PyObject_CallFunctionObjArgs(converter, arg, NULL); if (v == NULL) { _ctypes_extend_error(PyExc_ArgError, "argument %d: ", i+1); goto cleanup; @@ -1175,9 +1174,10 @@ retval = PyErr_SetFromWindowsErr(*(int *)resbuf); else retval = PyLong_FromLong(*(int *)resbuf); - } else + } else { #endif retval = GetResult(restype, resbuf, checker); + } cleanup: for (i = 0; i < argcount; ++i) Py_XDECREF(args[i].keep); @@ -1313,9 +1313,9 @@ NULL, #endif FUNCFLAG_HRESULT, /* flags */ - argtypes, /* self->argtypes */ - NULL, /* self->restype */ - NULL); /* checker */ + argtypes, /* self->argtypes */ + NULL, /* self->restype */ + NULL); /* checker */ return result; } @@ -1480,9 +1480,9 @@ NULL, #endif FUNCFLAG_CDECL, /* flags */ - NULL, /* self->argtypes */ - NULL, /* self->restype */ - NULL); /* checker */ + NULL, /* self->argtypes */ + NULL, /* self->restype */ + NULL); /* checker */ return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:22:33 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:22:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_call=5Fcommethod_was_only_?= =?utf-8?q?used_in_samples/Windows=2C_which_no_longer_exists=2E?= Message-ID: <3ZLccn66Dzz7LqV@mail.python.org> http://hg.python.org/cpython/rev/9efbe60aeb08 changeset: 82511:9efbe60aeb08 user: Eli Bendersky date: Wed Mar 06 06:21:46 2013 -0800 summary: call_commethod was only used in samples/Windows, which no longer exists. This method is dead code - not documented, not tested. As far as we know, it can be horribly broken. files: Misc/NEWS | 3 + Modules/_ctypes/callproc.c | 57 -------------------------- 2 files changed, 3 insertions(+), 57 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -881,6 +881,9 @@ `sha3_256`, `sha3_384` and `sha3_512`. As part of the patch some common code was moved from _hashopenssl.c to hashlib.h. +- ctypes.call_commethod was removed, since its only usage was in the defunct + samples directory. + Extension Modules ----------------- diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1263,62 +1263,6 @@ return Py_None; } -/* obsolete, should be removed */ -/* Only used by sample code (in samples\Windows\COM.py) */ -static PyObject * -call_commethod(PyObject *self, PyObject *args) -{ - IUnknown *pIunk; - int index; - PyObject *arguments; - PPROC *lpVtbl; - PyObject *result; - CDataObject *pcom; - PyObject *argtypes = NULL; - - if (!PyArg_ParseTuple(args, - "OiO!|O!", - &pcom, &index, - &PyTuple_Type, &arguments, - &PyTuple_Type, &argtypes)) - return NULL; - - if (argtypes && (PyTuple_GET_SIZE(arguments) != PyTuple_GET_SIZE(argtypes))) { - PyErr_Format(PyExc_TypeError, - "Method takes %d arguments (%d given)", - PyTuple_GET_SIZE(argtypes), PyTuple_GET_SIZE(arguments)); - return NULL; - } - - if (!CDataObject_Check(pcom) || (pcom->b_size != sizeof(void *))) { - PyErr_Format(PyExc_TypeError, - "COM Pointer expected instead of %s instance", - Py_TYPE(pcom)->tp_name); - return NULL; - } - - if ((*(void **)(pcom->b_ptr)) == NULL) { - PyErr_SetString(PyExc_ValueError, - "The COM 'this' pointer is NULL"); - return NULL; - } - - pIunk = (IUnknown *)(*(void **)(pcom->b_ptr)); - lpVtbl = (PPROC *)(pIunk->lpVtbl); - - result = _ctypes_callproc(lpVtbl[index], - arguments, -#ifdef MS_WIN32 - pIunk, - NULL, -#endif - FUNCFLAG_HRESULT, /* flags */ - argtypes, /* self->argtypes */ - NULL, /* self->restype */ - NULL); /* checker */ - return result; -} - static char copy_com_pointer_doc[] = "CopyComPointer(src, dst) -> HRESULT value\n"; @@ -1813,7 +1757,6 @@ {"FormatError", format_error, METH_VARARGS, format_error_doc}, {"LoadLibrary", load_library, METH_VARARGS, load_library_doc}, {"FreeLibrary", free_library, METH_VARARGS, free_library_doc}, - {"call_commethod", call_commethod, METH_VARARGS }, {"_check_HRESULT", check_hresult, METH_VARARGS}, #else {"dlopen", py_dl_open, METH_VARARGS, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:31:09 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:31:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_formatting_changes_tha?= =?utf-8?q?t_led_to_compilation_errors?= Message-ID: <3ZLcpj6KPfz7Lp8@mail.python.org> http://hg.python.org/cpython/rev/6bcec385d13d changeset: 82512:6bcec385d13d user: Eli Bendersky date: Wed Mar 06 06:30:23 2013 -0800 summary: Fix formatting changes that led to compilation errors files: Modules/_ctypes/callproc.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1078,10 +1078,9 @@ args[0].ffi_type = &ffi_type_pointer; args[0].value.p = pIunk; pa = &args[1]; - } else { + } else #endif pa = &args[0]; - } /* Convert the arguments */ for (i = 0; i < n; ++i, ++pa) { @@ -1174,10 +1173,9 @@ retval = PyErr_SetFromWindowsErr(*(int *)resbuf); else retval = PyLong_FromLong(*(int *)resbuf); - } else { + } else #endif retval = GetResult(restype, resbuf, checker); - } cleanup: for (i = 0; i < argcount; ++i) Py_XDECREF(args[i].keep); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:51:26 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:51:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_doc_gramma?= =?utf-8?q?r_and_line_width?= Message-ID: <3ZLdG63pCkzSlY@mail.python.org> http://hg.python.org/cpython/rev/09222815097b changeset: 82513:09222815097b branch: 3.2 parent: 82507:4f9de1b18cab user: Eli Bendersky date: Wed Mar 06 06:48:57 2013 -0800 summary: Fix doc grammar and line width files: Doc/library/ctypes.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -569,8 +569,8 @@ ValueError: too many initializers >>> -You can, however, build much more complicated structures. Structures can itself -contain other structures by using a structure as a field type. +You can, however, build much more complicated structures. A structure can +itself contain other structures by using a structure as a field type. Here is a RECT structure which contains two POINTs named *upperleft* and *lowerright*:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:51:27 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:51:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Fix_doc_grammar_and_line_width?= Message-ID: <3ZLdG76k4WzSqf@mail.python.org> http://hg.python.org/cpython/rev/2d8388759305 changeset: 82514:2d8388759305 branch: 3.3 parent: 82508:5e294202f93e parent: 82513:09222815097b user: Eli Bendersky date: Wed Mar 06 06:49:22 2013 -0800 summary: Fix doc grammar and line width files: Doc/library/ctypes.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -574,8 +574,8 @@ ValueError: too many initializers >>> -You can, however, build much more complicated structures. Structures can itself -contain other structures by using a structure as a field type. +You can, however, build much more complicated structures. A structure can +itself contain other structures by using a structure as a field type. Here is a RECT structure which contains two POINTs named *upperleft* and *lowerright*:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:51:29 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:51:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fix_doc_grammar_and_line_width?= Message-ID: <3ZLdG928NCzSns@mail.python.org> http://hg.python.org/cpython/rev/78a6d68a40aa changeset: 82515:78a6d68a40aa parent: 82512:6bcec385d13d parent: 82514:2d8388759305 user: Eli Bendersky date: Wed Mar 06 06:50:36 2013 -0800 summary: Fix doc grammar and line width files: Doc/library/ctypes.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -574,8 +574,8 @@ ValueError: too many initializers >>> -You can, however, build much more complicated structures. Structures can itself -contain other structures by using a structure as a field type. +You can, however, build much more complicated structures. A structure can +itself contain other structures by using a structure as a field type. Here is a RECT structure which contains two POINTs named *upperleft* and *lowerright*:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 15:54:25 2013 From: python-checkins at python.org (eli.bendersky) Date: Wed, 6 Mar 2013 15:54:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_doc_gramma?= =?utf-8?q?r_and_line_width?= Message-ID: <3ZLdKY32MszSmx@mail.python.org> http://hg.python.org/cpython/rev/cfc777407b03 changeset: 82516:cfc777407b03 branch: 2.7 parent: 82506:01a8fcc91d5a user: Eli Bendersky date: Wed Mar 06 06:53:39 2013 -0800 summary: Fix doc grammar and line width files: Doc/library/ctypes.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -568,8 +568,8 @@ ValueError: too many initializers >>> -You can, however, build much more complicated structures. Structures can itself -contain other structures by using a structure as a field type. +You can, however, build much more complicated structures. A structure can +itself contain other structures by using a structure as a field type. Here is a RECT structure which contains two POINTs named *upperleft* and *lowerright*:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 19:29:18 2013 From: python-checkins at python.org (victor.stinner) Date: Wed, 6 Mar 2013 19:29:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogX1B5VW5pY29kZV9X?= =?utf-8?q?riter=28=29_now_also_reuses_Unicode_singletons=3A?= Message-ID: <3ZLk5V74Vnz7LqK@mail.python.org> http://hg.python.org/cpython/rev/3dd2fa78fb89 changeset: 82517:3dd2fa78fb89 branch: 3.3 parent: 82514:2d8388759305 user: Victor Stinner date: Wed Mar 06 19:28:37 2013 +0100 summary: _PyUnicode_Writer() now also reuses Unicode singletons: empty string and latin1 single character files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12924,7 +12924,7 @@ writer->buffer = newbuffer; } assert(_PyUnicode_CheckConsistency(writer->buffer, 1)); - return writer->buffer; + return unicode_result_ready(writer->buffer); } void -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 6 19:29:20 2013 From: python-checkins at python.org (victor.stinner) Date: Wed, 6 Mar 2013 19:29:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogKE1lcmdlIDMuMykgX1B5VW5pY29kZV9Xcml0ZXIoKSBub3cgYWxzbyBy?= =?utf-8?q?euses_Unicode_singletons=3A?= Message-ID: <3ZLk5X2pYfzRhC@mail.python.org> http://hg.python.org/cpython/rev/fa59a85b373f changeset: 82518:fa59a85b373f parent: 82515:78a6d68a40aa parent: 82517:3dd2fa78fb89 user: Victor Stinner date: Wed Mar 06 19:29:09 2013 +0100 summary: (Merge 3.3) _PyUnicode_Writer() now also reuses Unicode singletons: empty string and latin1 single character files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12821,7 +12821,7 @@ writer->buffer = newbuffer; } assert(_PyUnicode_CheckConsistency(writer->buffer, 1)); - return writer->buffer; + return unicode_result_ready(writer->buffer); } void -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 01:23:51 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 7 Mar 2013 01:23:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MzYx?= =?utf-8?q?=3A_Use_cc_from_sysconfig_for_testing_flags=2E?= Message-ID: <3ZLsyb1Y5czSZL@mail.python.org> http://hg.python.org/cpython/rev/33208a574875 changeset: 82519:33208a574875 branch: 3.3 parent: 82517:3dd2fa78fb89 user: Stefan Krah date: Thu Mar 07 01:12:03 2013 +0100 summary: Issue #17361: Use cc from sysconfig for testing flags. files: setup.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -2013,8 +2013,8 @@ # Increase warning level for gcc: if 'gcc' in cc: - cmd = ("echo '' | gcc -Wextra -Wno-missing-field-initializers -E - " - "> /dev/null 2>&1") + cmd = ("echo '' | %s -Wextra -Wno-missing-field-initializers -E - " + "> /dev/null 2>&1" % cc) ret = os.system(cmd) if ret >> 8 == 0: extra_compile_args.extend(['-Wextra', -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 01:23:52 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 7 Mar 2013 01:23:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3ZLsyc4CB2z7LjR@mail.python.org> http://hg.python.org/cpython/rev/7780757c6bab changeset: 82520:7780757c6bab parent: 82518:fa59a85b373f parent: 82519:33208a574875 user: Stefan Krah date: Thu Mar 07 01:23:01 2013 +0100 summary: Merge 3.3. files: setup.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -2024,8 +2024,8 @@ # Increase warning level for gcc: if 'gcc' in cc: - cmd = ("echo '' | gcc -Wextra -Wno-missing-field-initializers -E - " - "> /dev/null 2>&1") + cmd = ("echo '' | %s -Wextra -Wno-missing-field-initializers -E - " + "> /dev/null 2>&1" % cc) ret = os.system(cmd) if ret >> 8 == 0: extra_compile_args.extend(['-Wextra', -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Mar 7 05:57:32 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 07 Mar 2013 05:57:32 +0100 Subject: [Python-checkins] Daily reference leaks (7780757c6bab): sum=13 Message-ID: results for 7780757c6bab on branch "default" -------------------------------------------- test_capi leaked [1, 1, 1] references, sum=3 test_capi leaked [2, 4, 4] memory blocks, sum=10 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogKpFPAY', '-x'] From python-checkins at python.org Thu Mar 7 13:51:33 2013 From: python-checkins at python.org (giampaolo.rodola) Date: Thu, 7 Mar 2013 13:51:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_PEP8-ify_ftplib=2Epy=3A_ge?= =?utf-8?q?t_rid_of_multiple_statements_on_one_line_=28if_cond=3A_=2E=2E?= =?utf-8?b?Lik=?= Message-ID: <3ZMBYK0g0NzSxG@mail.python.org> http://hg.python.org/cpython/rev/d01870bc43b5 changeset: 82521:d01870bc43b5 user: Giampaolo Rodola' date: Thu Mar 07 13:51:20 2013 +0100 summary: PEP8-ify ftplib.py: get rid of multiple statements on one line (if cond: ...) files: Lib/ftplib.py | 86 +++++++++++++++++++++++++------------- 1 files changed, 57 insertions(+), 29 deletions(-) diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -42,7 +42,7 @@ import warnings from socket import _GLOBAL_DEFAULT_TIMEOUT -__all__ = ["FTP","Netrc"] +__all__ = ["FTP", "Netrc"] # Magic number from MSG_OOB = 0x1 # Process data out of band @@ -184,7 +184,8 @@ # Internal: send one line to the server, appending CRLF def putline(self, line): line = line + CRLF - if self.debugging > 1: print('*put*', self.sanitize(line)) + if self.debugging > 1: + print('*put*', self.sanitize(line)) self.sock.sendall(line.encode(self.encoding)) # Internal: send one command to the server (through putline()) @@ -198,9 +199,12 @@ line = self.file.readline() if self.debugging > 1: print('*get*', self.sanitize(line)) - if not line: raise EOFError - if line[-2:] == CRLF: line = line[:-2] - elif line[-1:] in CRLF: line = line[:-1] + if not line: + raise EOFError + if line[-2:] == CRLF: + line = line[:-2] + elif line[-1:] in CRLF: + line = line[:-1] return line # Internal: get a response from the server, which may possibly @@ -223,7 +227,8 @@ # Raise various errors if the response indicates an error def getresp(self): resp = self.getmultiline() - if self.debugging: print('*resp*', self.sanitize(resp)) + if self.debugging: + print('*resp*', self.sanitize(resp)) self.lastresp = resp[:3] c = resp[:1] if c in {'1', '2', '3'}: @@ -247,7 +252,8 @@ IP and Synch; that doesn't seem to work with the servers I've tried. Instead, just send the ABOR command as OOB data.''' line = b'ABOR' + B_CRLF - if self.debugging > 1: print('*put urgent*', self.sanitize(line)) + if self.debugging > 1: + print('*put urgent*', self.sanitize(line)) self.sock.sendall(line, MSG_OOB) resp = self.getmultiline() if resp[:3] not in {'426', '225', '226'}: @@ -388,9 +394,12 @@ def login(self, user = '', passwd = '', acct = ''): '''Login, default anonymous.''' - if not user: user = 'anonymous' - if not passwd: passwd = '' - if not acct: acct = '' + if not user: + user = 'anonymous' + if not passwd: + passwd = '' + if not acct: + acct = '' if user == 'anonymous' and passwd in {'', '-'}: # If there is no anonymous ftp password specified # then we'll just use anonymous@ @@ -401,8 +410,10 @@ # host or country. passwd = passwd + 'anonymous@' resp = self.sendcmd('USER ' + user) - if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd) - if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct) + if resp[0] == '3': + resp = self.sendcmd('PASS ' + passwd) + if resp[0] == '3': + resp = self.sendcmd('ACCT ' + acct) if resp[0] != '2': raise error_reply(resp) return resp @@ -442,13 +453,15 @@ Returns: The response code. """ - if callback is None: callback = print_line + if callback is None: + callback = print_line resp = self.sendcmd('TYPE A') with self.transfercmd(cmd) as conn, \ conn.makefile('r', encoding=self.encoding) as fp: while 1: line = fp.readline() - if self.debugging > 2: print('*retr*', repr(line)) + if self.debugging > 2: + print('*retr*', repr(line)) if not line: break if line[-2:] == CRLF: @@ -477,9 +490,11 @@ with self.transfercmd(cmd, rest) as conn: while 1: buf = fp.read(blocksize) - if not buf: break + if not buf: + break conn.sendall(buf) - if callback: callback(buf) + if callback: + callback(buf) return self.voidresp() def storlines(self, cmd, fp, callback=None): @@ -498,12 +513,14 @@ with self.transfercmd(cmd) as conn: while 1: buf = fp.readline() - if not buf: break + if not buf: + break if buf[-2:] != B_CRLF: if buf[-1] in B_CRLF: buf = buf[:-1] buf = buf + B_CRLF conn.sendall(buf) - if callback: callback(buf) + if callback: + callback(buf) return self.voidresp() def acct(self, password): @@ -768,14 +785,16 @@ return self.voidresp() def retrlines(self, cmd, callback = None): - if callback is None: callback = print_line + if callback is None: + callback = print_line resp = self.sendcmd('TYPE A') conn = self.transfercmd(cmd) fp = conn.makefile('r', encoding=self.encoding) with fp, conn: while 1: line = fp.readline() - if self.debugging > 2: print('*retr*', repr(line)) + if self.debugging > 2: + print('*retr*', repr(line)) if not line: break if line[-2:] == CRLF: @@ -793,9 +812,11 @@ with self.transfercmd(cmd, rest) as conn: while 1: buf = fp.read(blocksize) - if not buf: break + if not buf: + break conn.sendall(buf) - if callback: callback(buf) + if callback: + callback(buf) # shutdown ssl layer if isinstance(conn, ssl.SSLSocket): conn.unwrap() @@ -806,12 +827,15 @@ with self.transfercmd(cmd) as conn: while 1: buf = fp.readline() - if not buf: break + if not buf: + break if buf[-2:] != B_CRLF: - if buf[-1] in B_CRLF: buf = buf[:-1] + if buf[-1] in B_CRLF: + buf = buf[:-1] buf = buf + B_CRLF conn.sendall(buf) - if callback: callback(buf) + if callback: + callback(buf) # shutdown ssl layer if isinstance(conn, ssl.SSLSocket): conn.unwrap() @@ -924,7 +948,8 @@ def ftpcp(source, sourcename, target, targetname = '', type = 'I'): '''Copy file from one FTP-instance to another.''' - if not targetname: targetname = sourcename + if not targetname: + targetname = sourcename type = 'TYPE ' + type source.voidcmd(type) target.voidcmd(type) @@ -934,9 +959,11 @@ # transfer request. # So: STOR before RETR, because here the target is a "user". treply = target.sendcmd('STOR ' + targetname) - if treply[:3] not in {'125', '150'}: raise error_proto # RFC 959 + if treply[:3] not in {'125', '150'}: + raise error_proto # RFC 959 sreply = source.sendcmd('RETR ' + sourcename) - if sreply[:3] not in {'125', '150'}: raise error_proto # RFC 959 + if sreply[:3] not in {'125', '150'}: + raise error_proto # RFC 959 source.voidresp() target.voidresp() @@ -968,7 +995,8 @@ in_macro = 0 while 1: line = fp.readline() - if not line: break + if not line: + break if in_macro and line.strip(): macro_lines.append(line) continue -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 14:03:57 2013 From: python-checkins at python.org (giampaolo.rodola) Date: Thu, 7 Mar 2013 14:03:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Refactor_ftplib_by_getting?= =?utf-8?q?_rid_of_4_methods_=28retr*=28=29_and_stor*=28=29=29_which_were?= Message-ID: <3ZMBqd2TtSz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/154d6335a2c6 changeset: 82522:154d6335a2c6 user: Giampaolo Rodola' date: Thu Mar 07 14:03:27 2013 +0100 summary: Refactor ftplib by getting rid of 4 methods (retr*() and stor*()) which were duplicated in TLS_FTP class. files: Lib/ftplib.py | 86 ++++++-------------------------------- 1 files changed, 15 insertions(+), 71 deletions(-) diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -439,6 +439,9 @@ if not data: break callback(data) + # shutdown ssl layer + if isinstance(conn, _SSLSocket): + conn.unwrap() return self.voidresp() def retrlines(self, cmd, callback = None): @@ -469,6 +472,9 @@ elif line[-1:] == '\n': line = line[:-1] callback(line) + # shutdown ssl layer + if isinstance(conn, _SSLSocket): + conn.unwrap() return self.voidresp() def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None): @@ -495,6 +501,9 @@ conn.sendall(buf) if callback: callback(buf) + # shutdown ssl layer + if isinstance(conn, _SSLSocket): + conn.unwrap() return self.voidresp() def storlines(self, cmd, fp, callback=None): @@ -521,6 +530,9 @@ conn.sendall(buf) if callback: callback(buf) + # shutdown ssl layer + if isinstance(conn, _SSLSocket): + conn.unwrap() return self.voidresp() def acct(self, password): @@ -655,8 +667,10 @@ try: import ssl except ImportError: - pass + _SSLSocket = None else: + _SSLSocket = ssl.SSLSocket + class FTP_TLS(FTP): '''A FTP subclass which adds TLS support to FTP as described in RFC-4217. @@ -771,76 +785,6 @@ ssl_version=self.ssl_version) return conn, size - def retrbinary(self, cmd, callback, blocksize=8192, rest=None): - self.voidcmd('TYPE I') - with self.transfercmd(cmd, rest) as conn: - while 1: - data = conn.recv(blocksize) - if not data: - break - callback(data) - # shutdown ssl layer - if isinstance(conn, ssl.SSLSocket): - conn.unwrap() - return self.voidresp() - - def retrlines(self, cmd, callback = None): - if callback is None: - callback = print_line - resp = self.sendcmd('TYPE A') - conn = self.transfercmd(cmd) - fp = conn.makefile('r', encoding=self.encoding) - with fp, conn: - while 1: - line = fp.readline() - if self.debugging > 2: - print('*retr*', repr(line)) - if not line: - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[-1:] == '\n': - line = line[:-1] - callback(line) - # shutdown ssl layer - if isinstance(conn, ssl.SSLSocket): - conn.unwrap() - return self.voidresp() - - def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None): - self.voidcmd('TYPE I') - with self.transfercmd(cmd, rest) as conn: - while 1: - buf = fp.read(blocksize) - if not buf: - break - conn.sendall(buf) - if callback: - callback(buf) - # shutdown ssl layer - if isinstance(conn, ssl.SSLSocket): - conn.unwrap() - return self.voidresp() - - def storlines(self, cmd, fp, callback=None): - self.voidcmd('TYPE A') - with self.transfercmd(cmd) as conn: - while 1: - buf = fp.readline() - if not buf: - break - if buf[-2:] != B_CRLF: - if buf[-1] in B_CRLF: - buf = buf[:-1] - buf = buf + B_CRLF - conn.sendall(buf) - if callback: - callback(buf) - # shutdown ssl layer - if isinstance(conn, ssl.SSLSocket): - conn.unwrap() - return self.voidresp() - def abort(self): # overridden as we can't pass MSG_OOB flag to sendall() line = b'ABOR' + B_CRLF -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 14:45:15 2013 From: python-checkins at python.org (nick.coghlan) Date: Thu, 7 Mar 2013 14:45:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQ2xvc2UgIzE1NDY1?= =?utf-8?q?=3A_Document_C_API_version_macros?= Message-ID: <3ZMClH4KWKz7Ltk@mail.python.org> http://hg.python.org/cpython/rev/adeafab9a18f changeset: 82523:adeafab9a18f branch: 3.3 parent: 82519:33208a574875 user: Nick Coghlan date: Thu Mar 07 23:14:44 2013 +1000 summary: Close #15465: Document C API version macros Mostly moving the existing macro docs over from the standard library docs to the C API docs where they belong. Patch by Kushal Das. files: Doc/c-api/apiabiversion.rst | 39 +++++++++++++++++++++++++ Doc/c-api/index.rst | 1 + Doc/c-api/stable.rst | 20 +++++++----- Doc/library/sys.rst | 24 +-------------- Misc/NEWS | 3 + 5 files changed, 55 insertions(+), 32 deletions(-) diff --git a/Doc/c-api/apiabiversion.rst b/Doc/c-api/apiabiversion.rst new file mode 100644 --- /dev/null +++ b/Doc/c-api/apiabiversion.rst @@ -0,0 +1,39 @@ +.. highlightlang:: c + +.. _apiabiversion: + +*********************** +API and ABI Versioning +*********************** + +``PY_VERSION_HEX`` is the Python version number encoded in a single integer. + +For example if the ``PY_VERSION_HEX`` is set to ``0x030401a2``, the underlying +version information can be found by treating it as a 32 bit number in +the following manner: + + +-------+-------------------------+------------------------------------------------+ + | Bytes | Bits (big endian order) | Meaning | + +=======+=========================+================================================+ + | ``1`` | ``1-8`` | ``PY_MAJOR_VERSION`` (the ``3`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``2`` | ``9-16`` | ``PY_MINOR_VERSION`` (the ``4`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``3`` | ``17-24`` | ``PY_MICRO_VERSION`` (the ``1`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``4`` | ``25-28`` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, | + | | | ``0xB`` for beta, ``0xC`` for release | + | | | candidate and ``0xF`` for final), in this | + | | | case it is alpha. | + | +-------------------------+------------------------------------------------+ + | | ``29-32`` | ``PY_RELEASE_SERIAL`` (the ``2`` in | + | | | ``3.4.1a2``, zero for final releases) | + +-------+-------------------------+------------------------------------------------+ + +Thus ``3.4.1a2`` is hexversion ``0x030401a2``. + +All the given macros are defined in :source:`Include/patchlevel.h`. + diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -23,3 +23,4 @@ memory.rst objimpl.rst stable.rst + apiabiversion.rst diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -2,9 +2,9 @@ .. _stable: -********************************** -Stable Appliction Binary Interface -********************************** +*********************************** +Stable Application Binary Interface +*********************************** Traditionally, the C API of Python will change with every release. Most changes will be source-compatible, typically by only adding API, @@ -23,13 +23,15 @@ Since Python 3.2, a subset of the API has been declared to guarantee a stable ABI. Extension modules wishing to use this API need to define -Py_LIMITED_API. A number of interpreter details then become hidden +``Py_LIMITED_API``. A number of interpreter details then become hidden from the extension module; in return, a module is built that works -on any 3.x version (x>=2) without recompilation. In some cases, the -stable ABI needs to be extended with new functions. Extensions modules -wishing to use these new APIs need to set Py_LIMITED_API to the -PY_VERSION_HEX value of the minimum Python version they want to -support (e.g. 0x03030000 for Python 3.3). Such modules will work +on any 3.x version (x>=2) without recompilation. + +In some cases, the stable ABI needs to be extended with new functions. +Extension modules wishing to use these new APIs need to set +``Py_LIMITED_API`` to the ``PY_VERSION_HEX`` value (see +:ref:`apiabiversion`) of the minimum Python version they want to +support (e.g. ``0x03030000`` for Python 3.3). Such modules will work on all subsequent Python releases, but fail to load (because of missing symbols) on the older releases. diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -598,29 +598,7 @@ :term:`struct sequence` :data:`sys.version_info` may be used for a more human-friendly encoding of the same information. - The ``hexversion`` is a 32-bit number with the following layout: - - +-------------------------+------------------------------------------------+ - | Bits (big endian order) | Meaning | - +=========================+================================================+ - | :const:`1-8` | ``PY_MAJOR_VERSION`` (the ``2`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`9-16` | ``PY_MINOR_VERSION`` (the ``1`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`17-24` | ``PY_MICRO_VERSION`` (the ``0`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`25-28` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, | - | | ``0xB`` for beta, ``0xC`` for release | - | | candidate and ``0xF`` for final) | - +-------------------------+------------------------------------------------+ - | :const:`29-32` | ``PY_RELEASE_SERIAL`` (the ``3`` in | - | | ``2.1.0a3``, zero for final releases) | - +-------------------------+------------------------------------------------+ - - Thus ``2.1.0a3`` is hexversion ``0x020100a3``. + More details of ``hexversion`` can be found at :ref:`apiabiversion` .. data:: implementation diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -797,6 +797,9 @@ Documentation ------------- +- Issue #15465: Document the versioning macros in the C API docs rather than + the standard library docs. Patch by Kushal Das. + - Issue #16406: Combine the pages for uploading and registering to PyPI. - Issue #16403: Document how distutils uses the maintainer field in -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 14:45:17 2013 From: python-checkins at python.org (nick.coghlan) Date: Thu, 7 Mar 2013 14:45:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_fix_for_=2315465_from_3=2E3?= Message-ID: <3ZMClK1QTmz7LtX@mail.python.org> http://hg.python.org/cpython/rev/a1373861f62f changeset: 82524:a1373861f62f parent: 82522:154d6335a2c6 parent: 82523:adeafab9a18f user: Nick Coghlan date: Thu Mar 07 23:45:03 2013 +1000 summary: Merge fix for #15465 from 3.3 files: Doc/c-api/apiabiversion.rst | 39 +++++++++++++++++++++++++ Doc/c-api/index.rst | 1 + Doc/c-api/stable.rst | 20 +++++++----- Doc/library/sys.rst | 24 +-------------- Misc/NEWS | 3 + 5 files changed, 55 insertions(+), 32 deletions(-) diff --git a/Doc/c-api/apiabiversion.rst b/Doc/c-api/apiabiversion.rst new file mode 100644 --- /dev/null +++ b/Doc/c-api/apiabiversion.rst @@ -0,0 +1,39 @@ +.. highlightlang:: c + +.. _apiabiversion: + +*********************** +API and ABI Versioning +*********************** + +``PY_VERSION_HEX`` is the Python version number encoded in a single integer. + +For example if the ``PY_VERSION_HEX`` is set to ``0x030401a2``, the underlying +version information can be found by treating it as a 32 bit number in +the following manner: + + +-------+-------------------------+------------------------------------------------+ + | Bytes | Bits (big endian order) | Meaning | + +=======+=========================+================================================+ + | ``1`` | ``1-8`` | ``PY_MAJOR_VERSION`` (the ``3`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``2`` | ``9-16`` | ``PY_MINOR_VERSION`` (the ``4`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``3`` | ``17-24`` | ``PY_MICRO_VERSION`` (the ``1`` in | + | | | ``3.4.1a2``) | + +-------+-------------------------+------------------------------------------------+ + | ``4`` | ``25-28`` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, | + | | | ``0xB`` for beta, ``0xC`` for release | + | | | candidate and ``0xF`` for final), in this | + | | | case it is alpha. | + | +-------------------------+------------------------------------------------+ + | | ``29-32`` | ``PY_RELEASE_SERIAL`` (the ``2`` in | + | | | ``3.4.1a2``, zero for final releases) | + +-------+-------------------------+------------------------------------------------+ + +Thus ``3.4.1a2`` is hexversion ``0x030401a2``. + +All the given macros are defined in :source:`Include/patchlevel.h`. + diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -23,3 +23,4 @@ memory.rst objimpl.rst stable.rst + apiabiversion.rst diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -2,9 +2,9 @@ .. _stable: -********************************** -Stable Appliction Binary Interface -********************************** +*********************************** +Stable Application Binary Interface +*********************************** Traditionally, the C API of Python will change with every release. Most changes will be source-compatible, typically by only adding API, @@ -23,13 +23,15 @@ Since Python 3.2, a subset of the API has been declared to guarantee a stable ABI. Extension modules wishing to use this API need to define -Py_LIMITED_API. A number of interpreter details then become hidden +``Py_LIMITED_API``. A number of interpreter details then become hidden from the extension module; in return, a module is built that works -on any 3.x version (x>=2) without recompilation. In some cases, the -stable ABI needs to be extended with new functions. Extensions modules -wishing to use these new APIs need to set Py_LIMITED_API to the -PY_VERSION_HEX value of the minimum Python version they want to -support (e.g. 0x03030000 for Python 3.3). Such modules will work +on any 3.x version (x>=2) without recompilation. + +In some cases, the stable ABI needs to be extended with new functions. +Extension modules wishing to use these new APIs need to set +``Py_LIMITED_API`` to the ``PY_VERSION_HEX`` value (see +:ref:`apiabiversion`) of the minimum Python version they want to +support (e.g. ``0x03030000`` for Python 3.3). Such modules will work on all subsequent Python releases, but fail to load (because of missing symbols) on the older releases. diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -613,29 +613,7 @@ :term:`struct sequence` :data:`sys.version_info` may be used for a more human-friendly encoding of the same information. - The ``hexversion`` is a 32-bit number with the following layout: - - +-------------------------+------------------------------------------------+ - | Bits (big endian order) | Meaning | - +=========================+================================================+ - | :const:`1-8` | ``PY_MAJOR_VERSION`` (the ``2`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`9-16` | ``PY_MINOR_VERSION`` (the ``1`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`17-24` | ``PY_MICRO_VERSION`` (the ``0`` in | - | | ``2.1.0a3``) | - +-------------------------+------------------------------------------------+ - | :const:`25-28` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, | - | | ``0xB`` for beta, ``0xC`` for release | - | | candidate and ``0xF`` for final) | - +-------------------------+------------------------------------------------+ - | :const:`29-32` | ``PY_RELEASE_SERIAL`` (the ``3`` in | - | | ``2.1.0a3``, zero for final releases) | - +-------------------------+------------------------------------------------+ - - Thus ``2.1.0a3`` is hexversion ``0x020100a3``. + More details of ``hexversion`` can be found at :ref:`apiabiversion` .. data:: implementation diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1071,6 +1071,9 @@ Documentation ------------- +- Issue #15465: Document the versioning macros in the C API docs rather than + the standard library docs. Patch by Kushal Das. + - Issue #16406: Combine the pages for uploading and registering to PyPI. - Issue #16403: Document how distutils uses the maintainer field in -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 17:39:11 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 17:39:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzExNzMyOiBtYWtl?= =?utf-8?q?_suppress=5Fcrash=5Fpopup=28=29_work_on_Windows_XP_and_Windows_?= =?utf-8?q?Server_2003=2E?= Message-ID: <3ZMHbz0V8fz7Ltj@mail.python.org> http://hg.python.org/cpython/rev/6ccefddc13fd changeset: 82525:6ccefddc13fd branch: 3.3 parent: 82523:adeafab9a18f user: Ezio Melotti date: Thu Mar 07 18:37:13 2013 +0200 summary: #11732: make suppress_crash_popup() work on Windows XP and Windows Server 2003. files: Lib/test/support.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -1911,10 +1911,12 @@ def suppress_crash_popup(): """Disable Windows Error Reporting dialogs using SetErrorMode.""" # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + # GetErrorMode is not available on Windows XP and Windows Server 2003, + # but SetErrorMode returns the previous value, so we can use that import ctypes k32 = ctypes.windll.kernel32 - old_error_mode = k32.GetErrorMode() SEM_NOGPFAULTERRORBOX = 0x02 + old_error_mode = k32.SetErrorMode(SEM_NOGPFAULTERRORBOX) k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) try: yield -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 17:39:12 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 17:39:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExNzMyOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZMHc03Dr6z7Lkg@mail.python.org> http://hg.python.org/cpython/rev/831035bda9b7 changeset: 82526:831035bda9b7 parent: 82524:a1373861f62f parent: 82525:6ccefddc13fd user: Ezio Melotti date: Thu Mar 07 18:38:45 2013 +0200 summary: #11732: merge with 3.3. files: Lib/test/support.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -1913,10 +1913,12 @@ def suppress_crash_popup(): """Disable Windows Error Reporting dialogs using SetErrorMode.""" # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + # GetErrorMode is not available on Windows XP and Windows Server 2003, + # but SetErrorMode returns the previous value, so we can use that import ctypes k32 = ctypes.windll.kernel32 - old_error_mode = k32.GetErrorMode() SEM_NOGPFAULTERRORBOX = 0x02 + old_error_mode = k32.SetErrorMode(SEM_NOGPFAULTERRORBOX) k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) try: yield -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 17:46:25 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 17:46:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzExNzMyOiBhZGQg?= =?utf-8?q?a_new_suppress=5Fcrash=5Fpopup=28=29_context_manager_to_test=2E?= =?utf-8?q?support_that?= Message-ID: <3ZMHmK04gPzSDW@mail.python.org> http://hg.python.org/cpython/rev/c0c440dcb8dd changeset: 82527:c0c440dcb8dd branch: 3.2 parent: 82513:09222815097b user: Ezio Melotti date: Thu Mar 07 18:44:29 2013 +0200 summary: #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_ctypes. files: Doc/library/test.rst | 7 +++++++ Lib/test/support.py | 26 +++++++++++++++++++++++++- Lib/test/test_capi.py | 11 ++++++----- Misc/NEWS | 3 +++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -365,6 +365,13 @@ assert s.getvalue() == "hello\n" +.. function:: suppress_crash_popup() + + A context manager that disables Windows Error Reporting dialogs using + `SetErrorMode `_. + On other platforms it's a no-op. + + .. function:: import_module(name, deprecated=False) This function imports and returns the named module. Unlike a normal diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -56,7 +56,7 @@ "reap_children", "cpython_only", "check_impl_detail", "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", - "import_fresh_module", "failfast", "run_with_tz" + "import_fresh_module", "failfast", "run_with_tz", "suppress_crash_popup", ] class Error(Exception): @@ -1775,6 +1775,30 @@ msg = "Requires functional symlink implementation" return test if ok else unittest.skip(msg)(test) + +if sys.platform.startswith('win'): + @contextlib.contextmanager + def suppress_crash_popup(): + """Disable Windows Error Reporting dialogs using SetErrorMode.""" + # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + # GetErrorMode is not available on Windows XP and Windows Server 2003, + # but SetErrorMode returns the previous value, so we can use that + import ctypes + k32 = ctypes.windll.kernel32 + SEM_NOGPFAULTERRORBOX = 0x02 + old_error_mode = k32.SetErrorMode(SEM_NOGPFAULTERRORBOX) + k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) + try: + yield + finally: + k32.SetErrorMode(old_error_mode) +else: + # this is a no-op for other platforms + @contextlib.contextmanager + def suppress_crash_popup(): + yield + + def patch(test_instance, object_to_patch, attr_name, new_value): """Override 'object_to_patch'.'attr_name' with 'new_value'. diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -46,11 +46,12 @@ @unittest.skipUnless(threading, 'Threading required for this test.') def test_no_FatalError_infinite_loop(self): - p = subprocess.Popen([sys.executable, "-c", - 'import _testcapi;' - '_testcapi.crash_no_current_thread()'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + with support.suppress_crash_popup(): + p = subprocess.Popen([sys.executable, "-c", + 'import _testcapi;' + '_testcapi.crash_no_current_thread()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) (out, err) = p.communicate() self.assertEqual(out, b'') # This used to cause an infinite loop. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -950,6 +950,9 @@ Tests ----- +- Issue #11732: add a new suppress_crash_popup() context manager to test.support + that disables crash popups on Windows and use it in test_ctypes. + - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. - Issue #17249: convert a test in test_capi to use unittest and reap threads. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 17:46:26 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 17:46:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2311732=3A_null_merge_with_3=2E2=2E?= Message-ID: <3ZMHmL38m6z7Lkd@mail.python.org> http://hg.python.org/cpython/rev/89d62bc81e47 changeset: 82528:89d62bc81e47 branch: 3.3 parent: 82525:6ccefddc13fd parent: 82527:c0c440dcb8dd user: Ezio Melotti date: Thu Mar 07 18:45:48 2013 +0200 summary: #11732: null merge with 3.2. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 17:46:27 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 17:46:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=2311732=3A_null_merge_with_3=2E3=2E?= Message-ID: <3ZMHmM5x7mzSvS@mail.python.org> http://hg.python.org/cpython/rev/7e818490d297 changeset: 82529:7e818490d297 parent: 82526:831035bda9b7 parent: 82528:89d62bc81e47 user: Ezio Melotti date: Thu Mar 07 18:46:09 2013 +0200 summary: #11732: null merge with 3.3. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 18:56:27 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 18:56:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_typo_in_Mi?= =?utf-8?q?sc/NEWS_entry=2E?= Message-ID: <3ZMKK73FmmzS5Y@mail.python.org> http://hg.python.org/cpython/rev/caf964ed20f1 changeset: 82530:caf964ed20f1 branch: 3.2 parent: 82527:c0c440dcb8dd user: Ezio Melotti date: Thu Mar 07 19:53:19 2013 +0200 summary: Fix typo in Misc/NEWS entry. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -951,7 +951,7 @@ ----- - Issue #11732: add a new suppress_crash_popup() context manager to test.support - that disables crash popups on Windows and use it in test_ctypes. + that disables crash popups on Windows and use it in test_capi. - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 18:56:28 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 18:56:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_typo_fix_in_Misc/NEWS_entry_from_3=2E2=2E?= Message-ID: <3ZMKK866WyzS5Y@mail.python.org> http://hg.python.org/cpython/rev/25f0237d32ed changeset: 82531:25f0237d32ed branch: 3.3 parent: 82528:89d62bc81e47 parent: 82530:caf964ed20f1 user: Ezio Melotti date: Thu Mar 07 19:55:08 2013 +0200 summary: Merge typo fix in Misc/NEWS entry from 3.2. 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 @@ -642,7 +642,7 @@ - Issue #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_faulthandler and - test_ctypes. + test_capi. - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 18:56:30 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 18:56:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_typo_fix_in_Misc/NEWS_entry_from_3=2E3=2E?= Message-ID: <3ZMKKB26RDzSZL@mail.python.org> http://hg.python.org/cpython/rev/bab568ac7e7a changeset: 82532:bab568ac7e7a parent: 82529:7e818490d297 parent: 82531:25f0237d32ed user: Ezio Melotti date: Thu Mar 07 19:56:15 2013 +0200 summary: Merge typo fix in Misc/NEWS entry from 3.3. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -897,7 +897,7 @@ - Issue #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_faulthandler and - test_ctypes. + test_capi. - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 20:19:16 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Mar 2013 20:19:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_memory_leak_introduced?= =?utf-8?q?_in_15190138d3f3=2E?= Message-ID: <3ZMM8h14rbzSlx@mail.python.org> http://hg.python.org/cpython/rev/c261b74533bf changeset: 82533:c261b74533bf user: Ezio Melotti date: Thu Mar 07 21:18:45 2013 +0200 summary: Fix memory leak introduced in 15190138d3f3. files: Modules/_testcapimodule.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1423,11 +1423,15 @@ if (wide == NULL) return NULL; PyUnicode_AS_UNICODE(wide)[0] = invalid[0]; - if (_PyUnicode_Ready(wide) < 0) + if (_PyUnicode_Ready(wide) < 0) { + Py_DECREF(wide); PyErr_Clear(); - else + } + else { + Py_DECREF(wide); return raiseTestError("test_widechar", "PyUnicode_Ready() didn't fail"); + } #endif Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 23:31:56 2013 From: python-checkins at python.org (r.david.murray) Date: Thu, 7 Mar 2013 23:31:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE0NjQ1OiBHZW5l?= =?utf-8?q?rator_now_emits_correct_linesep_for_all_parts=2E?= Message-ID: <3ZMRR006q6zRtV@mail.python.org> http://hg.python.org/cpython/rev/30c0f0dd0b94 changeset: 82534:30c0f0dd0b94 branch: 3.2 parent: 82530:caf964ed20f1 user: R David Murray date: Thu Mar 07 16:38:03 2013 -0500 summary: #14645: Generator now emits correct linesep for all parts. Previously the parts of the message retained whatever linesep they had on read, which means if the messages weren't read in univeral newline mode, the line endings could well be inconsistent. In general sending it via smtplib would result in them getting fixed, but it is better to generate them correctly to begin with. Also, the new send_message method of smtplib does not do the fixup, so that method is producing rfc-invalid output without this fix. files: Lib/email/generator.py | 22 ++++++++++++-- Lib/email/test/test_email.py | 35 ++++++++++++++++++++++++ Misc/NEWS | 5 +++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -119,6 +119,19 @@ # BytesGenerator overrides this to encode strings to bytes. return s + def _write_lines(self, lines): + # We have to transform the line endings. + if not lines: + return + lines = lines.splitlines(True) + for line in lines[:-1]: + self.write(line.rstrip('\r\n')) + self.write(self._NL) + laststripped = lines[-1].rstrip('\r\n') + self.write(laststripped) + if len(lines[-1])!=len(laststripped): + self.write(self._NL) + def _write(self, msg): # We can't write the headers yet because of the following scenario: # say a multipart message includes the boundary string somewhere in @@ -198,7 +211,7 @@ payload = msg.get_payload() if self._mangle_from_: payload = fcre.sub('>From ', payload) - self.write(payload) + self._write_lines(payload) # Default body handler _writeBody = _handle_text @@ -237,7 +250,8 @@ preamble = fcre.sub('>From ', msg.preamble) else: preamble = msg.preamble - self.write(preamble + self._NL) + self._write_lines(preamble) + self.write(self._NL) # dash-boundary transport-padding CRLF self.write('--' + boundary + self._NL) # body-part @@ -259,7 +273,7 @@ epilogue = fcre.sub('>From ', msg.epilogue) else: epilogue = msg.epilogue - self.write(epilogue) + self._write_lines(epilogue) def _handle_multipart_signed(self, msg): # The contents of signed parts has to stay unmodified in order to keep @@ -393,7 +407,7 @@ if _has_surrogates(msg._payload): if self._mangle_from_: msg._payload = fcre.sub(">From ", msg._payload) - self.write(msg._payload) + self._write_lines(msg._payload) else: super(BytesGenerator,self)._handle_text(msg) diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -68,6 +68,7 @@ with openfile(findfile(filename)) as fp: return email.message_from_file(fp) + maxDiff = None # Test various aspects of the Message class's API @@ -2907,6 +2908,40 @@ email.utils.make_msgid(domain='testdomain-string')[-19:], '@testdomain-string>') + def test_Generator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt) + s = StringIO() + g = email.generator.Generator(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), msgtxt_nl) + + def test_BytesGenerator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue().decode('ascii'), msgtxt) + + def test_BytesGenerator_linend_with_non_ascii(self): + # Issue 14645. + with openfile('msg_26.txt', 'rb') as f: + msgtxt = f.read() + msgtxt = msgtxt.replace(b'with attachment', b'fo\xf6') + msgtxt_nl = msgtxt.replace(b'\r\n', b'\n') + msg = email.message_from_bytes(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue(), msgtxt) + # Test the iterator/generators class TestIterators(TestEmailBase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,11 @@ Library ------- +- Issue #14645: The email generator classes now produce output using the + specified linesep throughout. Previously if the prolog, epilog, or + body were stored with a different linesep, that linesep was used. This + fix corrects an RFC non-compliance issue with smtplib.send_message. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 23:31:57 2013 From: python-checkins at python.org (r.david.murray) Date: Thu, 7 Mar 2013 23:31:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge=3A_=2314645=3A_Generator_now_emits_correct_linesep_for_a?= =?utf-8?q?ll_parts=2E?= Message-ID: <3ZMRR145bFz7Lkx@mail.python.org> http://hg.python.org/cpython/rev/1b9dc00c4d57 changeset: 82535:1b9dc00c4d57 branch: 3.3 parent: 82531:25f0237d32ed parent: 82534:30c0f0dd0b94 user: R David Murray date: Thu Mar 07 16:43:58 2013 -0500 summary: Merge: #14645: Generator now emits correct linesep for all parts. Previously the parts of the message retained whatever linesep they had on read, which means if the messages weren't read in univeral newline mode, the line endings could well be inconsistent. In general sending it via smtplib would result in them getting fixed, but it is better to generate them correctly to begin with. Also, the new send_message method of smtplib does not do the fixup, so that method is producing rfc-invalid output without this fix. files: Lib/email/generator.py | 22 ++++++++++-- Lib/test/test_email/test_email.py | 34 +++++++++++++++++++ Misc/NEWS | 5 ++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -146,6 +146,19 @@ # BytesGenerator overrides this to encode strings to bytes. return s + def _write_lines(self, lines): + # We have to transform the line endings. + if not lines: + return + lines = lines.splitlines(True) + for line in lines[:-1]: + self.write(line.rstrip('\r\n')) + self.write(self._NL) + laststripped = lines[-1].rstrip('\r\n') + self.write(laststripped) + if len(lines[-1])!=len(laststripped): + self.write(self._NL) + def _write(self, msg): # We can't write the headers yet because of the following scenario: # say a multipart message includes the boundary string somewhere in @@ -217,7 +230,7 @@ payload = msg.get_payload() if self._mangle_from_: payload = fcre.sub('>From ', payload) - self.write(payload) + self._write_lines(payload) # Default body handler _writeBody = _handle_text @@ -256,7 +269,8 @@ preamble = fcre.sub('>From ', msg.preamble) else: preamble = msg.preamble - self.write(preamble + self._NL) + self._write_lines(preamble) + self.write(self._NL) # dash-boundary transport-padding CRLF self.write('--' + boundary + self._NL) # body-part @@ -278,7 +292,7 @@ epilogue = fcre.sub('>From ', msg.epilogue) else: epilogue = msg.epilogue - self.write(epilogue) + self._write_lines(epilogue) def _handle_multipart_signed(self, msg): # The contents of signed parts has to stay unmodified in order to keep @@ -402,7 +416,7 @@ if _has_surrogates(msg._payload) and not self.policy.cte_type=='7bit': if self._mangle_from_: msg._payload = fcre.sub(">From ", msg._payload) - self.write(msg._payload) + self._write_lines(msg._payload) else: super(BytesGenerator,self)._handle_text(msg) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3111,6 +3111,40 @@ email.utils.make_msgid(domain='testdomain-string')[-19:], '@testdomain-string>') + def test_Generator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt) + s = StringIO() + g = email.generator.Generator(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), msgtxt_nl) + + def test_BytesGenerator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue().decode('ascii'), msgtxt) + + def test_BytesGenerator_linend_with_non_ascii(self): + # Issue 14645. + with openfile('msg_26.txt', 'rb') as f: + msgtxt = f.read() + msgtxt = msgtxt.replace(b'with attachment', b'fo\xf6') + msgtxt_nl = msgtxt.replace(b'\r\n', b'\n') + msg = email.message_from_bytes(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue(), msgtxt) + # Test the iterator/generators class TestIterators(TestEmailBase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,11 @@ Library ------- +- Issue #14645: The email generator classes now produce output using the + specified linesep throughout. Previously if the prolog, epilog, or + body were stored with a different linesep, that linesep was used. This + fix corrects an RFC non-compliance issue with smtplib.send_message. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 7 23:31:59 2013 From: python-checkins at python.org (r.david.murray) Date: Thu, 7 Mar 2013 23:31:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2314645=3A_Generator_now_emits_correct_linesep?= =?utf-8?q?_for_all_parts=2E?= Message-ID: <3ZMRR31L0Xz7Lkx@mail.python.org> http://hg.python.org/cpython/rev/6b69c11b0ad0 changeset: 82536:6b69c11b0ad0 parent: 82533:c261b74533bf parent: 82535:1b9dc00c4d57 user: R David Murray date: Thu Mar 07 17:31:21 2013 -0500 summary: Merge: #14645: Generator now emits correct linesep for all parts. Previously the parts of the message retained whatever linesep they had on read, which means if the messages weren't read in univeral newline mode, the line endings could well be inconsistent. In general sending it via smtplib would result in them getting fixed, but it is better to generate them correctly to begin with. Also, the new send_message method of smtplib does not do the fixup, so that method is producing rfc-invalid output without this fix. files: Lib/email/generator.py | 22 ++++++++++-- Lib/test/test_email/test_email.py | 34 +++++++++++++++++++ Misc/NEWS | 5 ++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -146,6 +146,19 @@ # BytesGenerator overrides this to encode strings to bytes. return s + def _write_lines(self, lines): + # We have to transform the line endings. + if not lines: + return + lines = lines.splitlines(True) + for line in lines[:-1]: + self.write(line.rstrip('\r\n')) + self.write(self._NL) + laststripped = lines[-1].rstrip('\r\n') + self.write(laststripped) + if len(lines[-1])!=len(laststripped): + self.write(self._NL) + def _write(self, msg): # We can't write the headers yet because of the following scenario: # say a multipart message includes the boundary string somewhere in @@ -217,7 +230,7 @@ payload = msg.get_payload() if self._mangle_from_: payload = fcre.sub('>From ', payload) - self.write(payload) + self._write_lines(payload) # Default body handler _writeBody = _handle_text @@ -256,7 +269,8 @@ preamble = fcre.sub('>From ', msg.preamble) else: preamble = msg.preamble - self.write(preamble + self._NL) + self._write_lines(preamble) + self.write(self._NL) # dash-boundary transport-padding CRLF self.write('--' + boundary + self._NL) # body-part @@ -278,7 +292,7 @@ epilogue = fcre.sub('>From ', msg.epilogue) else: epilogue = msg.epilogue - self.write(epilogue) + self._write_lines(epilogue) def _handle_multipart_signed(self, msg): # The contents of signed parts has to stay unmodified in order to keep @@ -402,7 +416,7 @@ if _has_surrogates(msg._payload) and not self.policy.cte_type=='7bit': if self._mangle_from_: msg._payload = fcre.sub(">From ", msg._payload) - self.write(msg._payload) + self._write_lines(msg._payload) else: super(BytesGenerator,self)._handle_text(msg) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3111,6 +3111,40 @@ email.utils.make_msgid(domain='testdomain-string')[-19:], '@testdomain-string>') + def test_Generator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt) + s = StringIO() + g = email.generator.Generator(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), msgtxt_nl) + + def test_BytesGenerator_linend(self): + # Issue 14645. + with openfile('msg_26.txt', newline='\n') as f: + msgtxt = f.read() + msgtxt_nl = msgtxt.replace('\r\n', '\n') + msg = email.message_from_string(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue().decode('ascii'), msgtxt) + + def test_BytesGenerator_linend_with_non_ascii(self): + # Issue 14645. + with openfile('msg_26.txt', 'rb') as f: + msgtxt = f.read() + msgtxt = msgtxt.replace(b'with attachment', b'fo\xf6') + msgtxt_nl = msgtxt.replace(b'\r\n', b'\n') + msg = email.message_from_bytes(msgtxt_nl) + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(msg, linesep='\r\n') + self.assertEqual(s.getvalue(), msgtxt) + # Test the iterator/generators class TestIterators(TestEmailBase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -275,6 +275,11 @@ Library ------- +- Issue #14645: The email generator classes now produce output using the + specified linesep throughout. Previously if the prolog, epilog, or + body were stored with a different linesep, that linesep was used. This + fix corrects an RFC non-compliance issue with smtplib.send_message. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 00:17:46 2013 From: python-checkins at python.org (r.david.murray) Date: Fri, 8 Mar 2013 00:17:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_PEP8_fixup_on_?= =?utf-8?q?previous_patch=2C_remove_unused_import_in_test=5Femail=2E?= Message-ID: <3ZMSRt0F1Jz7LkQ@mail.python.org> http://hg.python.org/cpython/rev/c8b2ed53b884 changeset: 82537:c8b2ed53b884 branch: 3.2 parent: 82534:30c0f0dd0b94 user: R David Murray date: Thu Mar 07 18:15:13 2013 -0500 summary: PEP8 fixup on previous patch, remove unused import in test_email. files: Lib/email/generator.py | 2 +- Lib/email/test/test_email.py | 1 - 2 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -129,7 +129,7 @@ self.write(self._NL) laststripped = lines[-1].rstrip('\r\n') self.write(laststripped) - if len(lines[-1])!=len(laststripped): + if len(lines[-1]) != len(laststripped): self.write(self._NL) def _write(self, msg): diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -9,7 +9,6 @@ import base64 import difflib import unittest -import warnings import textwrap from io import StringIO, BytesIO -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 00:17:47 2013 From: python-checkins at python.org (r.david.murray) Date: Fri, 8 Mar 2013 00:17:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge=3A_PEP8_fixup_on_previous_patch=2C_remove_unused_imports?= =?utf-8?q?_in_test=5Femail=2E?= Message-ID: <3ZMSRv3FLzz7Ll7@mail.python.org> http://hg.python.org/cpython/rev/cffc9378b602 changeset: 82538:cffc9378b602 branch: 3.3 parent: 82535:1b9dc00c4d57 parent: 82537:c8b2ed53b884 user: R David Murray date: Thu Mar 07 18:16:47 2013 -0500 summary: Merge: PEP8 fixup on previous patch, remove unused imports in test_email. files: Lib/email/generator.py | 2 +- Lib/test/test_email/test_email.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -156,7 +156,7 @@ self.write(self._NL) laststripped = lines[-1].rstrip('\r\n') self.write(laststripped) - if len(lines[-1])!=len(laststripped): + if len(lines[-1]) != len(laststripped): self.write(self._NL) def _write(self, msg): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2,14 +2,10 @@ # Contact: email-sig at python.org # email package unit tests -import os import re -import sys import time import base64 -import difflib import unittest -import warnings import textwrap from io import StringIO, BytesIO @@ -37,7 +33,7 @@ from email import base64mime from email import quoprimime -from test.support import run_unittest, unlink +from test.support import unlink from test.test_email import openfile, TestEmailBase NL = '\n' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 00:17:48 2013 From: python-checkins at python.org (r.david.murray) Date: Fri, 8 Mar 2013 00:17:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_PEP8_fixup_on_previous_patch=2C_remove_unused_i?= =?utf-8?q?mports_in_test=5Femail=2E?= Message-ID: <3ZMSRw5pbCz7LlY@mail.python.org> http://hg.python.org/cpython/rev/9aafc005a611 changeset: 82539:9aafc005a611 parent: 82536:6b69c11b0ad0 parent: 82538:cffc9378b602 user: R David Murray date: Thu Mar 07 18:17:19 2013 -0500 summary: Merge: PEP8 fixup on previous patch, remove unused imports in test_email. files: Lib/email/generator.py | 2 +- Lib/test/test_email/test_email.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -156,7 +156,7 @@ self.write(self._NL) laststripped = lines[-1].rstrip('\r\n') self.write(laststripped) - if len(lines[-1])!=len(laststripped): + if len(lines[-1]) != len(laststripped): self.write(self._NL) def _write(self, msg): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2,14 +2,10 @@ # Contact: email-sig at python.org # email package unit tests -import os import re -import sys import time import base64 -import difflib import unittest -import warnings import textwrap from io import StringIO, BytesIO @@ -37,7 +33,7 @@ from email import base64mime from email import quoprimime -from test.support import run_unittest, unlink +from test.support import unlink from test.test_email import openfile, TestEmailBase NL = '\n' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 02:33:56 2013 From: python-checkins at python.org (victor.stinner) Date: Fri, 8 Mar 2013 02:33:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MjIz?= =?utf-8?q?=3A_the_test_is_specific_to_32-bit_wchar=5Ft_type?= Message-ID: <3ZMWT01MpyzQQP@mail.python.org> http://hg.python.org/cpython/rev/1fd165883a65 changeset: 82540:1fd165883a65 branch: 3.3 parent: 82538:cffc9378b602 user: Victor Stinner date: Fri Mar 08 02:33:06 2013 +0100 summary: Issue #17223: the test is specific to 32-bit wchar_t type Skip the test on Windows. files: Lib/test/test_array.py | 14 +++----------- 1 files changed, 3 insertions(+), 11 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 @@ -24,15 +24,7 @@ except struct.error: have_long_long = False -try: - import ctypes - sizeof_wchar = ctypes.sizeof(ctypes.c_wchar) -except ImportError: - import sys - if sys.platform == 'win32': - sizeof_wchar = 2 - else: - sizeof_wchar = 4 +sizeof_wchar = array.array('u').itemsize class ArraySubclass(array.array): @@ -1076,8 +1068,8 @@ # U+FFFFFFFF is an invalid code point in Unicode 6.0 invalid_str = b'\xff\xff\xff\xff' else: - # invalid UTF-16 surrogate pair - invalid_str = b'\xff\xdf\x61\x00' + # PyUnicode_FromUnicode() cannot fail with 16-bit wchar_t + self.skipTest("specific to 32-bit wchar_t") a = array.array('u', invalid_str) self.assertRaises(ValueError, a.tounicode) self.assertRaises(ValueError, str, a) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 02:33:57 2013 From: python-checkins at python.org (victor.stinner) Date: Fri, 8 Mar 2013 02:33:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E3=29_Issue_=2317223=3A_the_test_is_specific?= =?utf-8?q?_to_32-bit_wchar=5Ft_type?= Message-ID: <3ZMWT14DW1zQs0@mail.python.org> http://hg.python.org/cpython/rev/42970cbfc982 changeset: 82541:42970cbfc982 parent: 82539:9aafc005a611 parent: 82540:1fd165883a65 user: Victor Stinner date: Fri Mar 08 02:33:44 2013 +0100 summary: (Merge 3.3) Issue #17223: the test is specific to 32-bit wchar_t type Skip the test on Windows. files: Lib/test/test_array.py | 14 +++----------- 1 files changed, 3 insertions(+), 11 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 @@ -24,15 +24,7 @@ except struct.error: have_long_long = False -try: - import ctypes - sizeof_wchar = ctypes.sizeof(ctypes.c_wchar) -except ImportError: - import sys - if sys.platform == 'win32': - sizeof_wchar = 2 - else: - sizeof_wchar = 4 +sizeof_wchar = array.array('u').itemsize class ArraySubclass(array.array): @@ -1076,8 +1068,8 @@ # U+FFFFFFFF is an invalid code point in Unicode 6.0 invalid_str = b'\xff\xff\xff\xff' else: - # invalid UTF-16 surrogate pair - invalid_str = b'\xff\xdf\x61\x00' + # PyUnicode_FromUnicode() cannot fail with 16-bit wchar_t + self.skipTest("specific to 32-bit wchar_t") a = array.array('u', invalid_str) self.assertRaises(ValueError, a.tounicode) self.assertRaises(ValueError, str, a) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 04:17:27 2013 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 8 Mar 2013 04:17:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_PyDict=5FSetDefault=2E?= =?utf-8?q?_=28closes_=2317327=29?= Message-ID: <3ZMYmR2nDyz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/a0b750ea3397 changeset: 82542:a0b750ea3397 user: Benjamin Peterson date: Thu Mar 07 22:16:29 2013 -0500 summary: Add PyDict_SetDefault. (closes #17327) Patch by Stefan Behnel and I. files: Doc/c-api/dict.rst | 9 +++++++ Doc/data/refcounts.dat | 5 ++++ Include/dictobject.h | 2 + Misc/NEWS | 2 + Objects/dictobject.c | 34 ++++++++++++++++++++--------- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -110,6 +110,15 @@ :c:type:`char\*`, rather than a :c:type:`PyObject\*`. +.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default) + + This is the same the Python-level :meth:`dict.setdefault`. If present, it + returns the value corresponding to *key* from the dictionary *p*. If the key + is not in the dict, it is inserted with value *defaultobj* and *defaultobj* + is inserted. This function evaluates the hash function of *key* only once, + instead of evaluating it independently for the lookup and the insertion. + + .. c:function:: PyObject* PyDict_Items(PyObject *p) Return a :c:type:`PyListObject` containing all the items from the dictionary. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -220,6 +220,11 @@ PyDict_GetItemString:PyObject*:p:0: PyDict_GetItemString:char*:key:: +PyDict_SetDefault:PyObject*::0: +PyDict_SetDefault:PyObject*:p:0: +PyDict_SetDefault:PyObject*:key:0:conditionally +1 if inserted into the dict +PyDict_SetDefault:PyObject*:default:0:conditionally +1 if inserted into the dict + PyDict_Items:PyObject*::+1: PyDict_Items:PyObject*:p:0: diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -53,6 +53,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key); +PyAPI_FUNC(PyObject *) PyDict_SetDefault( + PyObject *mp, PyObject *key, PyObject *defaultobj); PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #17327: Add PyDict_SetDefault. + - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2211,19 +2211,19 @@ return val; } -static PyObject * -dict_setdefault(register PyDictObject *mp, PyObject *args) +PyObject * +PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) { - PyObject *key; - PyObject *failobj = Py_None; + PyDictObject *mp = (PyDictObject *)d; PyObject *val = NULL; Py_hash_t hash; PyDictKeyEntry *ep; PyObject **value_addr; - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) + if (!PyDict_Check(d)) { + PyErr_BadInternalCall(); return NULL; - + } if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { hash = PyObject_Hash(key); @@ -2241,20 +2241,32 @@ return NULL; ep = find_empty_slot(mp, key, hash, &value_addr); } - Py_INCREF(failobj); + Py_INCREF(defaultobj); Py_INCREF(key); - MAINTAIN_TRACKING(mp, key, failobj); + MAINTAIN_TRACKING(mp, key, defaultobj); ep->me_key = key; ep->me_hash = hash; - *value_addr = failobj; - val = failobj; + *value_addr = defaultobj; + val = defaultobj; mp->ma_keys->dk_usable--; mp->ma_used++; } - Py_INCREF(val); return val; } +static PyObject * +dict_setdefault(PyDictObject *mp, PyObject *args) +{ + PyObject *key, *val; + PyObject *defaultobj = Py_None; + + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj)) + return NULL; + + val = PyDict_SetDefault(mp, key, defaultobj); + Py_XINCREF(val); + return val; +} static PyObject * dict_clear(register PyDictObject *mp) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Mar 8 05:57:03 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 08 Mar 2013 05:57:03 +0100 Subject: [Python-checkins] Daily reference leaks (42970cbfc982): sum=0 Message-ID: results for 42970cbfc982 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogeY0qxE', '-x'] From python-checkins at python.org Fri Mar 8 10:51:32 2013 From: python-checkins at python.org (vinay.sajip) Date: Fri, 8 Mar 2013 10:51:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317384=3A_Consolid?= =?utf-8?q?ated_cleanup_operations_in_tests=2E?= Message-ID: <3ZMkW83fZNzNs3@mail.python.org> http://hg.python.org/cpython/rev/85325bce9982 changeset: 82543:85325bce9982 user: Vinay Sajip date: Fri Mar 08 09:50:57 2013 +0000 summary: Issue #17384: Consolidated cleanup operations in tests. files: Lib/test/test_logging.py | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 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 @@ -3396,6 +3396,12 @@ self.assertEqual(logging.root.level, self.original_logging_level) def test_filename(self): + + def cleanup(h1, h2, fn): + h1.close() + h2.close() + os.remove(fn) + logging.basicConfig(filename='test.log') self.assertEqual(len(logging.root.handlers), 1) @@ -3403,19 +3409,23 @@ self.assertIsInstance(handler, logging.FileHandler) expected = logging.FileHandler('test.log', 'a') - self.addCleanup(expected.close) self.assertEqual(handler.stream.mode, expected.stream.mode) self.assertEqual(handler.stream.name, expected.stream.name) - self.addCleanup(os.remove, 'test.log') + self.addCleanup(cleanup, handler, expected, 'test.log') def test_filemode(self): + + def cleanup(h1, h2, fn): + h1.close() + h2.close() + os.remove(fn) + logging.basicConfig(filename='test.log', filemode='wb') handler = logging.root.handlers[0] expected = logging.FileHandler('test.log', 'wb') - self.addCleanup(expected.close) self.assertEqual(handler.stream.mode, expected.stream.mode) - self.addCleanup(os.remove, 'test.log') + self.addCleanup(cleanup, handler, expected, 'test.log') def test_stream(self): stream = io.StringIO() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 14:33:58 2013 From: python-checkins at python.org (eli.bendersky) Date: Fri, 8 Mar 2013 14:33:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3Mzc4?= =?utf-8?q?=3A_ctypes_documentation_fix=2E?= Message-ID: <3ZMqRp6TS8zQfD@mail.python.org> http://hg.python.org/cpython/rev/76be5efa0d86 changeset: 82544:76be5efa0d86 branch: 3.2 parent: 82537:c8b2ed53b884 user: Eli Bendersky date: Fri Mar 08 05:31:54 2013 -0800 summary: Issue #17378: ctypes documentation fix. Document that ctypes automatically applies byref() when argtypes declares POINTER. files: Doc/library/ctypes.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -817,6 +817,11 @@ 3 >>> +In addition, if a function argument is explicitly declared to be a pointer type +(such as ``POINTER(c_int)``) in :attr:`argtypes`, an object of the pointed +type (``c_int`` in this case) can be passed to the function. ctypes will apply +the required :func:`byref` conversion in this case automatically. + To set a POINTER type field to ``NULL``, you can assign ``None``:: >>> bar.values = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 14:34:00 2013 From: python-checkins at python.org (eli.bendersky) Date: Fri, 8 Mar 2013 14:34:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2317378=3A_ctypes_documentation_fix=2E?= Message-ID: <3ZMqRr1xKczQrd@mail.python.org> http://hg.python.org/cpython/rev/2cd2d8f8f72f changeset: 82545:2cd2d8f8f72f branch: 3.3 parent: 82540:1fd165883a65 parent: 82544:76be5efa0d86 user: Eli Bendersky date: Fri Mar 08 05:32:45 2013 -0800 summary: Issue #17378: ctypes documentation fix. Document that ctypes automatically applies byref() when argtypes declares POINTER. files: Doc/library/ctypes.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -822,6 +822,11 @@ 3 >>> +In addition, if a function argument is explicitly declared to be a pointer type +(such as ``POINTER(c_int)``) in :attr:`argtypes`, an object of the pointed +type (``c_int`` in this case) can be passed to the function. ctypes will apply +the required :func:`byref` conversion in this case automatically. + To set a POINTER type field to ``NULL``, you can assign ``None``:: >>> bar.values = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 14:34:01 2013 From: python-checkins at python.org (eli.bendersky) Date: Fri, 8 Mar 2013 14:34:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2317378=3A_ctypes_documentation_fix=2E?= Message-ID: <3ZMqRs4PQCzQlS@mail.python.org> http://hg.python.org/cpython/rev/58c07ba40926 changeset: 82546:58c07ba40926 parent: 82543:85325bce9982 parent: 82545:2cd2d8f8f72f user: Eli Bendersky date: Fri Mar 08 05:33:05 2013 -0800 summary: Issue #17378: ctypes documentation fix. Document that ctypes automatically applies byref() when argtypes declares POINTER. files: Doc/library/ctypes.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -822,6 +822,11 @@ 3 >>> +In addition, if a function argument is explicitly declared to be a pointer type +(such as ``POINTER(c_int)``) in :attr:`argtypes`, an object of the pointed +type (``c_int`` in this case) can be passed to the function. ctypes will apply +the required :func:`byref` conversion in this case automatically. + To set a POINTER type field to ``NULL``, you can assign ``None``:: >>> bar.values = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 14:35:51 2013 From: python-checkins at python.org (eli.bendersky) Date: Fri, 8 Mar 2013 14:35:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2luZyAjMTcz?= =?utf-8?q?78=3A_ctypes_documentation_fix=2E?= Message-ID: <3ZMqTz1nH8zMgy@mail.python.org> http://hg.python.org/cpython/rev/2dd77a12e7bf changeset: 82547:2dd77a12e7bf branch: 2.7 parent: 82516:cfc777407b03 user: Eli Bendersky date: Fri Mar 08 05:34:58 2013 -0800 summary: Closing #17378: ctypes documentation fix. Document that ctypes automatically applies byref() when argtypes declares POINTER. files: Doc/library/ctypes.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -816,6 +816,11 @@ 3 >>> +In addition, if a function argument is explicitly declared to be a pointer type +(such as ``POINTER(c_int)``) in :attr:`argtypes`, an object of the pointed +type (``c_int`` in this case) can be passed to the function. ctypes will apply +the required :func:`byref` conversion in this case automatically. + To set a POINTER type field to ``NULL``, you can assign ``None``:: >>> bar.values = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 8 14:36:56 2013 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 8 Mar 2013 14:36:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_fix_warning_=28closes_=231?= =?utf-8?q?7327=29?= Message-ID: <3ZMqWD4PsVzQrd@mail.python.org> http://hg.python.org/cpython/rev/ca9a85c36e09 changeset: 82548:ca9a85c36e09 parent: 82546:58c07ba40926 user: Benjamin Peterson date: Fri Mar 08 08:36:49 2013 -0500 summary: fix warning (closes #17327) files: Objects/dictobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2263,7 +2263,7 @@ if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj)) return NULL; - val = PyDict_SetDefault(mp, key, defaultobj); + val = PyDict_SetDefault((PyObject *)mp, key, defaultobj); Py_XINCREF(val); return val; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 00:27:39 2013 From: python-checkins at python.org (vinay.sajip) Date: Sat, 9 Mar 2013 00:27:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Mzc2?= =?utf-8?q?=3A_Clarified_documentation_for_TimedRotatingFileHandler_weekda?= =?utf-8?q?y?= Message-ID: <3ZN4cq3Pf1zP9C@mail.python.org> http://hg.python.org/cpython/rev/56b74b9c81c3 changeset: 82549:56b74b9c81c3 branch: 2.7 parent: 82547:2dd77a12e7bf user: Vinay Sajip date: Fri Mar 08 23:22:22 2013 +0000 summary: Issue #17376: Clarified documentation for TimedRotatingFileHandler weekday rotation. files: Doc/library/logging.handlers.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -236,11 +236,15 @@ +----------------+-----------------------+ | ``'D'`` | Days | +----------------+-----------------------+ - | ``'W'`` | Week day (0=Monday) | + | ``'W0'-'W6'`` | Weekday (0=Monday) | +----------------+-----------------------+ | ``'midnight'`` | Roll over at midnight | +----------------+-----------------------+ + When using weekday-based rotation, specify 'W0' for Monday, 'W1' for + Tuesday, and so on up to 'W6' for Sunday. In this case, the value passed for + *interval* isn't used. + The system will save old log files by appending extensions to the filename. The extensions are date-and-time based, using the strftime format ``%Y-%m-%d_%H-%M-%S`` or a leading portion thereof, depending on the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 00:27:40 2013 From: python-checkins at python.org (vinay.sajip) Date: Sat, 9 Mar 2013 00:27:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3Mzc2?= =?utf-8?q?=3A_Clarified_documentation_for_TimedRotatingFileHandler_weekda?= =?utf-8?q?y?= Message-ID: <3ZN4cr6SMHzP9C@mail.python.org> http://hg.python.org/cpython/rev/83f07e3a53f4 changeset: 82550:83f07e3a53f4 branch: 3.2 parent: 82544:76be5efa0d86 user: Vinay Sajip date: Fri Mar 08 23:24:30 2013 +0000 summary: Issue #17376: Clarified documentation for TimedRotatingFileHandler weekday rotation. files: Doc/library/logging.handlers.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -236,11 +236,15 @@ +----------------+-----------------------+ | ``'D'`` | Days | +----------------+-----------------------+ - | ``'W'`` | Week day (0=Monday) | + | ``'W0'-'W6'`` | Weekday (0=Monday) | +----------------+-----------------------+ | ``'midnight'`` | Roll over at midnight | +----------------+-----------------------+ + When using weekday-based rotation, specify 'W0' for Monday, 'W1' for + Tuesday, and so on up to 'W6' for Sunday. In this case, the value passed for + *interval* isn't used. + The system will save old log files by appending extensions to the filename. The extensions are date-and-time based, using the strftime format ``%Y-%m-%d_%H-%M-%S`` or a leading portion thereof, depending on the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 00:27:42 2013 From: python-checkins at python.org (vinay.sajip) Date: Sat, 9 Mar 2013 00:27:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2317376=3A_Merged_clarification_from_3=2E2=2E?= Message-ID: <3ZN4ct20vNzQ81@mail.python.org> http://hg.python.org/cpython/rev/12239c13db72 changeset: 82551:12239c13db72 branch: 3.3 parent: 82545:2cd2d8f8f72f parent: 82550:83f07e3a53f4 user: Vinay Sajip date: Fri Mar 08 23:26:43 2013 +0000 summary: Issue #17376: Merged clarification from 3.2. files: Doc/library/logging.handlers.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -317,11 +317,15 @@ +----------------+-----------------------+ | ``'D'`` | Days | +----------------+-----------------------+ - | ``'W'`` | Week day (0=Monday) | + | ``'W0'-'W6'`` | Weekday (0=Monday) | +----------------+-----------------------+ | ``'midnight'`` | Roll over at midnight | +----------------+-----------------------+ + When using weekday-based rotation, specify 'W0' for Monday, 'W1' for + Tuesday, and so on up to 'W6' for Sunday. In this case, the value passed for + *interval* isn't used. + The system will save old log files by appending extensions to the filename. The extensions are date-and-time based, using the strftime format ``%Y-%m-%d_%H-%M-%S`` or a leading portion thereof, depending on the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 00:27:43 2013 From: python-checkins at python.org (vinay.sajip) Date: Sat, 9 Mar 2013 00:27:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2317376=3A_Merged_clarification_from_3=2E3=2E?= Message-ID: <3ZN4cv4m8lzQNY@mail.python.org> http://hg.python.org/cpython/rev/a8047d1376d5 changeset: 82552:a8047d1376d5 parent: 82548:ca9a85c36e09 parent: 82551:12239c13db72 user: Vinay Sajip date: Fri Mar 08 23:27:24 2013 +0000 summary: Closes #17376: Merged clarification from 3.3. files: Doc/library/logging.handlers.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -317,11 +317,15 @@ +----------------+-----------------------+ | ``'D'`` | Days | +----------------+-----------------------+ - | ``'W'`` | Week day (0=Monday) | + | ``'W0'-'W6'`` | Weekday (0=Monday) | +----------------+-----------------------+ | ``'midnight'`` | Roll over at midnight | +----------------+-----------------------+ + When using weekday-based rotation, specify 'W0' for Monday, 'W1' for + Tuesday, and so on up to 'W6' for Sunday. In this case, the value passed for + *interval* isn't used. + The system will save old log files by appending extensions to the filename. The extensions are date-and-time based, using the strftime format ``%Y-%m-%d_%H-%M-%S`` or a leading portion thereof, depending on the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 01:41:00 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 01:41:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3MzMy?= =?utf-8?q?=3A_fix_json_doc_typo_/convered/converted/_found_by_Ernie_Hersh?= =?utf-8?b?ZXku?= Message-ID: <3ZN6FS2CZyzQDL@mail.python.org> http://hg.python.org/cpython/rev/9bd2fc35f311 changeset: 82553:9bd2fc35f311 branch: 2.7 parent: 82549:56b74b9c81c3 user: Terry Jan Reedy date: Fri Mar 08 19:35:15 2013 -0500 summary: Issue #17332: fix json doc typo /convered/converted/ found by Ernie Hershey. files: Doc/library/json.rst | 2 +- Misc/ACKS | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -197,7 +197,7 @@ Keys in key/value pairs of JSON are always of the type :class:`str`. When a dictionary is converted into JSON, all the keys of the dictionary are - coerced to strings. As a result of this, if a dictionary is convered + coerced to strings. As a result of this, if a dictionary is converted into JSON and then back into a dictionary, the dictionary may not equal the original one. That is, ``loads(dumps(x)) != x`` if x has non-string keys. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -409,6 +409,7 @@ Ivan Herman J?rgen Hermann Gary Herron +Ernie Hershey Thomas Herve Bernhard Herzog Magnus L. Hetland -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 01:41:01 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 01:41:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3MzMy?= =?utf-8?q?=3A_fix_json_doc_typo_/convered/converted/_found_by_Ernie_Hersh?= =?utf-8?b?ZXku?= Message-ID: <3ZN6FT5KjpzQDL@mail.python.org> http://hg.python.org/cpython/rev/55fd9810c9ab changeset: 82554:55fd9810c9ab branch: 3.2 parent: 82550:83f07e3a53f4 user: Terry Jan Reedy date: Fri Mar 08 19:35:15 2013 -0500 summary: Issue #17332: fix json doc typo /convered/converted/ found by Ernie Hershey. files: Doc/library/json.rst | 2 +- Misc/ACKS | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -195,7 +195,7 @@ Keys in key/value pairs of JSON are always of the type :class:`str`. When a dictionary is converted into JSON, all the keys of the dictionary are - coerced to strings. As a result of this, if a dictionary is convered + coerced to strings. As a result of this, if a dictionary is converted into JSON and then back into a dictionary, the dictionary may not equal the original one. That is, ``loads(dumps(x)) != x`` if x has non-string keys. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -446,6 +446,7 @@ Ivan Herman J?rgen Hermann Gary Herron +Ernie Hershey Thomas Herve Bernhard Herzog Magnus L. Hetland -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 01:41:03 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 01:41:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2317332=3A_fix_json_doc_typo_/convered/converted/_found?= =?utf-8?q?_by_Ernie_Hershey=2E?= Message-ID: <3ZN6FW1CvRzQLp@mail.python.org> http://hg.python.org/cpython/rev/8817a09e012c changeset: 82555:8817a09e012c branch: 3.3 parent: 82551:12239c13db72 parent: 82554:55fd9810c9ab user: Terry Jan Reedy date: Fri Mar 08 19:39:30 2013 -0500 summary: Issue #17332: fix json doc typo /convered/converted/ found by Ernie Hershey. files: Doc/library/json.rst | 2 +- Misc/ACKS | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -195,7 +195,7 @@ Keys in key/value pairs of JSON are always of the type :class:`str`. When a dictionary is converted into JSON, all the keys of the dictionary are - coerced to strings. As a result of this, if a dictionary is convered + coerced to strings. As a result of this, if a dictionary is converted into JSON and then back into a dictionary, the dictionary may not equal the original one. That is, ``loads(dumps(x)) != x`` if x has non-string keys. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -490,6 +490,7 @@ Ivan Herman J?rgen Hermann Gary Herron +Ernie Hershey Thomas Herve Bernhard Herzog Magnus L. Hetland -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 01:41:04 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 01:41:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2317332=3A_fix_json_doc_typo_/convered/converted/?= =?utf-8?q?_found_by_Ernie_Hershey=2E?= Message-ID: <3ZN6FX3y8BzQM1@mail.python.org> http://hg.python.org/cpython/rev/d86f5686cef9 changeset: 82556:d86f5686cef9 parent: 82552:a8047d1376d5 parent: 82555:8817a09e012c user: Terry Jan Reedy date: Fri Mar 08 19:40:17 2013 -0500 summary: Issue #17332: fix json doc typo /convered/converted/ found by Ernie Hershey. files: Doc/library/json.rst | 2 +- Misc/ACKS | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -192,7 +192,7 @@ Keys in key/value pairs of JSON are always of the type :class:`str`. When a dictionary is converted into JSON, all the keys of the dictionary are - coerced to strings. As a result of this, if a dictionary is convered + coerced to strings. As a result of this, if a dictionary is converted into JSON and then back into a dictionary, the dictionary may not equal the original one. That is, ``loads(dumps(x)) != x`` if x has non-string keys. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -493,6 +493,7 @@ Ivan Herman J?rgen Hermann Gary Herron +Ernie Hershey Thomas Herve Bernhard Herzog Magnus L. Hetland -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 05:02:38 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 9 Mar 2013 05:02:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Mzc1?= =?utf-8?q?=3A__Add_docstrings_to_the_threading_module=2E?= Message-ID: <3ZNBk63LHqzPyP@mail.python.org> http://hg.python.org/cpython/rev/e0ef2bde35c3 changeset: 82557:e0ef2bde35c3 branch: 2.7 parent: 82553:9bd2fc35f311 user: Raymond Hettinger date: Fri Mar 08 21:02:13 2013 -0700 summary: Issue #17375: Add docstrings to the threading module. files: Lib/threading.py | 351 ++++++++++++++++++++++++++++++++++- 1 files changed, 346 insertions(+), 5 deletions(-) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -87,10 +87,22 @@ _trace_hook = None def setprofile(func): + """Set a profile function for all threads started from the threading module. + + The func will be passed to sys.setprofile() for each thread, before its + run() method is called. + + """ global _profile_hook _profile_hook = func def settrace(func): + """Set a trace function for all threads started from the threading module. + + The func will be passed to sys.settrace() for each thread, before its run() + method is called. + + """ global _trace_hook _trace_hook = func @@ -99,9 +111,22 @@ Lock = _allocate_lock def RLock(*args, **kwargs): + """Factory function that returns a new reentrant lock. + + A reentrant lock must be released by the thread that acquired it. Once a + thread has acquired a reentrant lock, the same thread may acquire it again + without blocking; the thread must release it once for each time it has + acquired it. + + """ return _RLock(*args, **kwargs) class _RLock(_Verbose): + """A reentrant lock must be released by the thread that acquired it. Once a + thread has acquired a reentrant lock, the same thread may acquire it + again without blocking; the thread must release it once for each time it + has acquired it. + """ def __init__(self, verbose=None): _Verbose.__init__(self, verbose) @@ -119,6 +144,26 @@ self.__class__.__name__, owner, self.__count) def acquire(self, blocking=1): + """Acquire a lock, blocking or non-blocking. + + When invoked without arguments: if this thread already owns the lock, + increment the recursion level by one, and return immediately. Otherwise, + if another thread owns the lock, block until the lock is unlocked. Once + the lock is unlocked (not owned by any thread), then grab ownership, set + the recursion level to one, and return. If more than one thread is + blocked waiting until the lock is unlocked, only one at a time will be + able to grab ownership of the lock. There is no return value in this + case. + + When invoked with the blocking argument set to true, do the same thing + as when called without arguments, and return true. + + When invoked with the blocking argument set to false, do not block. If a + call without an argument would block, return false immediately; + otherwise, do the same thing as when called without arguments, and + return true. + + """ me = _get_ident() if self.__owner == me: self.__count = self.__count + 1 @@ -139,6 +184,21 @@ __enter__ = acquire def release(self): + """Release a lock, decrementing the recursion level. + + If after the decrement it is zero, reset the lock to unlocked (not owned + by any thread), and if any other threads are blocked waiting for the + lock to become unlocked, allow exactly one of them to proceed. If after + the decrement the recursion level is still nonzero, the lock remains + locked and owned by the calling thread. + + Only call this method when the calling thread owns the lock. A + RuntimeError is raised if this method is called when the lock is + unlocked. + + There is no return value. + + """ if self.__owner != _get_ident(): raise RuntimeError("cannot release un-acquired lock") self.__count = count = self.__count - 1 @@ -179,9 +239,22 @@ def Condition(*args, **kwargs): + """Factory function that returns a new condition variable object. + + A condition variable allows one or more threads to wait until they are + notified by another thread. + + If the lock argument is given and not None, it must be a Lock or RLock + object, and it is used as the underlying lock. Otherwise, a new RLock object + is created and used as the underlying lock. + + """ return _Condition(*args, **kwargs) class _Condition(_Verbose): + """Condition variables allow one or more threads to wait until they are + notified by another thread. + """ def __init__(self, lock=None, verbose=None): _Verbose.__init__(self, verbose) @@ -233,6 +306,28 @@ return True def wait(self, timeout=None): + """Wait until notified or until a timeout occurs. + + If the calling thread has not acquired the lock when this method is + called, a RuntimeError is raised. + + This method releases the underlying lock, and then blocks until it is + awakened by a notify() or notifyAll() call for the same condition + variable in another thread, or until the optional timeout occurs. Once + awakened or timed out, it re-acquires the lock and returns. + + When the timeout argument is present and not None, it should be a + floating point number specifying a timeout for the operation in seconds + (or fractions thereof). + + When the underlying lock is an RLock, it is not released using its + release() method, since this may not actually unlock the lock when it + was acquired multiple times recursively. Instead, an internal interface + of the RLock class is used, which really unlocks it even when it has + been recursively acquired several times. Another internal interface is + then used to restore the recursion level when the lock is reacquired. + + """ if not self._is_owned(): raise RuntimeError("cannot wait on un-acquired lock") waiter = _allocate_lock() @@ -275,6 +370,15 @@ self._acquire_restore(saved_state) def notify(self, n=1): + """Wake up one or more threads waiting on this condition, if any. + + If the calling thread has not acquired the lock when this method is + called, a RuntimeError is raised. + + This method wakes up at most n of the threads waiting for the condition + variable; it is a no-op if no threads are waiting. + + """ if not self._is_owned(): raise RuntimeError("cannot notify on un-acquired lock") __waiters = self.__waiters @@ -293,15 +397,35 @@ pass def notifyAll(self): + """Wake up all threads waiting on this condition. + + If the calling thread has not acquired the lock when this method + is called, a RuntimeError is raised. + + """ self.notify(len(self.__waiters)) notify_all = notifyAll def Semaphore(*args, **kwargs): + """A factory function that returns a new semaphore. + + Semaphores manage a counter representing the number of release() calls minus + the number of acquire() calls, plus an initial value. The acquire() method + blocks if necessary until it can return without making the counter + negative. If not given, value defaults to 1. + + """ return _Semaphore(*args, **kwargs) class _Semaphore(_Verbose): + """Semaphores manage a counter representing the number of release() calls + minus the number of acquire() calls, plus an initial value. The acquire() + method blocks if necessary until it can return without making the counter + negative. If not given, value defaults to 1. + + """ # After Tim Peters' semaphore class, but not quite the same (no maximum) @@ -313,6 +437,25 @@ self.__value = value def acquire(self, blocking=1): + """Acquire a semaphore, decrementing the internal counter by one. + + When invoked without arguments: if the internal counter is larger than + zero on entry, decrement it by one and return immediately. If it is zero + on entry, block, waiting until some other thread has called release() to + make it larger than zero. This is done with proper interlocking so that + if multiple acquire() calls are blocked, release() will wake exactly one + of them up. The implementation may pick one at random, so the order in + which blocked threads are awakened should not be relied on. There is no + return value in this case. + + When invoked with blocking set to true, do the same thing as when called + without arguments, and return true. + + When invoked with blocking set to false, do not block. If a call without + an argument would block, return false immediately; otherwise, do the + same thing as when called without arguments, and return true. + + """ rc = False self.__cond.acquire() while self.__value == 0: @@ -334,6 +477,12 @@ __enter__ = acquire def release(self): + """Release a semaphore, incrementing the internal counter by one. + + When the counter is zero on entry and another thread is waiting for it + to become larger than zero again, wake up that thread. + + """ self.__cond.acquire() self.__value = self.__value + 1 if __debug__: @@ -347,24 +496,64 @@ def BoundedSemaphore(*args, **kwargs): + """A factory function that returns a new bounded semaphore. + + A bounded semaphore checks to make sure its current value doesn't exceed its + initial value. If it does, ValueError is raised. In most situations + semaphores are used to guard resources with limited capacity. + + If the semaphore is released too many times it's a sign of a bug. If not + given, value defaults to 1. + + Like regular semaphores, bounded semaphores manage a counter representing + the number of release() calls minus the number of acquire() calls, plus an + initial value. The acquire() method blocks if necessary until it can return + without making the counter negative. If not given, value defaults to 1. + + """ return _BoundedSemaphore(*args, **kwargs) class _BoundedSemaphore(_Semaphore): - """Semaphore that checks that # releases is <= # acquires""" + """A bounded semaphore checks to make sure its current value doesn't exceed + its initial value. If it does, ValueError is raised. In most situations + semaphores are used to guard resources with limited capacity. + """ + def __init__(self, value=1, verbose=None): _Semaphore.__init__(self, value, verbose) self._initial_value = value def release(self): + """Release a semaphore, incrementing the internal counter by one. + + When the counter is zero on entry and another thread is waiting for it + to become larger than zero again, wake up that thread. + + If the number of releases exceeds the number of acquires, + raise a ValueError. + + """ if self._Semaphore__value >= self._initial_value: - raise ValueError, "Semaphore released too many times" + raise ValueError("Semaphore released too many times") return _Semaphore.release(self) def Event(*args, **kwargs): + """A factory function that returns a new event. + + Events manage a flag that can be set to true with the set() method and reset + to false with the clear() method. The wait() method blocks until the flag is + true. + + """ return _Event(*args, **kwargs) class _Event(_Verbose): + """A factory function that returns a new event object. An event manages a + flag that can be set to true with the set() method and reset to false + with the clear() method. The wait() method blocks until the flag is true. + + """ # After Tim Peters' event class (without is_posted()) @@ -378,11 +567,18 @@ self.__cond.__init__() def isSet(self): + 'Return true if and only if the internal flag is true.' return self.__flag is_set = isSet def set(self): + """Set the internal flag to true. + + All threads waiting for the flag to become true are awakened. Threads + that call wait() once the flag is true will not block at all. + + """ self.__cond.acquire() try: self.__flag = True @@ -391,6 +587,12 @@ self.__cond.release() def clear(self): + """Reset the internal flag to false. + + Subsequently, threads calling wait() will block until set() is called to + set the internal flag to true again. + + """ self.__cond.acquire() try: self.__flag = False @@ -398,6 +600,20 @@ self.__cond.release() def wait(self, timeout=None): + """Block until the internal flag is true. + + If the internal flag is true on entry, return immediately. Otherwise, + block until another thread calls set() to set the flag to true, or until + the optional timeout occurs. + + When the timeout argument is present and not None, it should be a + floating point number specifying a timeout for the operation in seconds + (or fractions thereof). + + This method returns the internal flag on exit, so it will always return + True except if a timeout is given and the operation times out. + + """ self.__cond.acquire() try: if not self.__flag: @@ -422,7 +638,11 @@ # Main class for threads class Thread(_Verbose): + """A class that represents a thread of control. + This class can be safely subclassed in a limited fashion. + + """ __initialized = False # Need to store a reference to sys.exc_info for printing # out exceptions when a thread tries to use a global var. during interp. @@ -435,6 +655,27 @@ def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None): + """This constructor should always be called with keyword arguments. Arguments are: + + *group* should be None; reserved for future extension when a ThreadGroup + class is implemented. + + *target* is the callable object to be invoked by the run() + method. Defaults to None, meaning nothing is called. + + *name* is the thread name. By default, a unique name is constructed of + the form "Thread-N" where N is a small decimal number. + + *args* is the argument tuple for the target invocation. Defaults to (). + + *kwargs* is a dictionary of keyword arguments for the target + invocation. Defaults to {}. + + If a subclass overrides the constructor, it must make sure to invoke + the base class constructor (Thread.__init__()) before doing anything + else to the thread. + +""" assert group is None, "group argument must be None for now" _Verbose.__init__(self, verbose) if kwargs is None: @@ -483,6 +724,15 @@ return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) def start(self): + """Start the thread's activity. + + It must be called at most once per thread object. It arranges for the + object's run() method to be invoked in a separate thread of control. + + This method will raise a RuntimeError if called more than once on the + same thread object. + + """ if not self.__initialized: raise RuntimeError("thread.__init__() not called") if self.__started.is_set(): @@ -500,6 +750,14 @@ self.__started.wait() def run(self): + """Method representing the thread's activity. + + You may override this method in a subclass. The standard run() method + invokes the callable object passed to the object's constructor as the + target argument, if any, with sequential and keyword arguments taken + from the args and kwargs arguments, respectively. + + """ try: if self.__target: self.__target(*self.__args, **self.__kwargs) @@ -651,6 +909,29 @@ raise def join(self, timeout=None): + """Wait until the thread terminates. + + This blocks the calling thread until the thread whose join() method is + called terminates -- either normally or through an unhandled exception + or until the optional timeout occurs. + + When the timeout argument is present and not None, it should be a + floating point number specifying a timeout for the operation in seconds + (or fractions thereof). As join() always returns None, you must call + isAlive() after join() to decide whether a timeout happened -- if the + thread is still alive, the join() call timed out. + + When the timeout argument is not present or None, the operation will + block until the thread terminates. + + A thread can be join()ed many times. + + join() raises a RuntimeError if an attempt is made to join the current + thread as that would cause a deadlock. It is also an error to join() a + thread before it has been started and attempts to do so raises the same + exception. + + """ if not self.__initialized: raise RuntimeError("Thread.__init__() not called") if not self.__started.is_set(): @@ -685,6 +966,12 @@ @property def name(self): + """A string used for identification purposes only. + + It has no semantics. Multiple threads may be given the same name. The + initial name is set by the constructor. + + """ assert self.__initialized, "Thread.__init__() not called" return self.__name @@ -695,10 +982,24 @@ @property def ident(self): + """Thread identifier of this thread or None if it has not been started. + + This is a nonzero integer. See the thread.get_ident() function. Thread + identifiers may be recycled when a thread exits and another thread is + created. The identifier is available even after the thread has exited. + + """ assert self.__initialized, "Thread.__init__() not called" return self.__ident def isAlive(self): + """Return whether the thread is alive. + + This method returns True just before the run() method starts until just + after the run() method terminates. The module function enumerate() + returns a list of all alive threads. + + """ assert self.__initialized, "Thread.__init__() not called" return self.__started.is_set() and not self.__stopped @@ -706,6 +1007,17 @@ @property def daemon(self): + """A boolean value indicating whether this thread is a daemon thread (True) or not (False). + + This must be set before start() is called, otherwise RuntimeError is + raised. Its initial value is inherited from the creating thread; the + main thread is not a daemon thread and therefore all threads created in + the main thread default to daemon = False. + + The entire Python program exits when no alive non-daemon threads are + left. + + """ assert self.__initialized, "Thread.__init__() not called" return self.__daemonic @@ -732,14 +1044,24 @@ # The timer class was contributed by Itamar Shtull-Trauring def Timer(*args, **kwargs): + """Factory function to create a Timer object. + + Timers call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + + """ return _Timer(*args, **kwargs) class _Timer(Thread): """Call a function after a specified number of seconds: - t = Timer(30.0, f, args=[], kwargs={}) - t.start() - t.cancel() # stop the timer's action if it's still waiting + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ def __init__(self, interval, function, args=[], kwargs={}): @@ -828,6 +1150,12 @@ # Global API functions def currentThread(): + """Return the current Thread object, corresponding to the caller's thread of control. + + If the caller's thread of control was not created through the threading + module, a dummy thread object with limited functionality is returned. + + """ try: return _active[_get_ident()] except KeyError: @@ -837,6 +1165,12 @@ current_thread = currentThread def activeCount(): + """Return the number of Thread objects currently alive. + + The returned count is equal to the length of the list returned by + enumerate(). + + """ with _active_limbo_lock: return len(_active) + len(_limbo) @@ -847,6 +1181,13 @@ return _active.values() + _limbo.values() def enumerate(): + """Return a list of all Thread objects currently alive. + + The list includes daemonic threads, dummy thread objects created by + current_thread(), and the main thread. It excludes terminated threads and + threads that have not yet been started. + + """ with _active_limbo_lock: return _active.values() + _limbo.values() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 05:15:17 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 9 Mar 2013 05:15:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Improve_commen?= =?utf-8?q?ts_and_variable_names=2E?= Message-ID: <3ZNC0j4rlWzQDJ@mail.python.org> http://hg.python.org/cpython/rev/1af9f7df3a96 changeset: 82558:1af9f7df3a96 branch: 3.3 parent: 82555:8817a09e012c user: Raymond Hettinger date: Fri Mar 08 21:11:55 2013 -0700 summary: Improve comments and variable names. files: Lib/functools.py | 51 ++++++++++++++++++++++++++--------- 1 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -17,7 +17,7 @@ from _thread import RLock except: class RLock: - 'Dummy reentrant lock' + 'Dummy reentrant lock for builds without threads' def __enter__(self): pass def __exit__(self, exctype, excinst, exctb): pass @@ -146,6 +146,12 @@ _CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"]) class _HashedSeq(list): + """ This class guarantees that hash() will be called no more than once + per element. This is important because the lru_cache() will hash + the key multiple times on a cache miss. + + """ + __slots__ = 'hashvalue' def __init__(self, tup, hash=hash): @@ -159,7 +165,16 @@ kwd_mark = (object(),), fasttypes = {int, str, frozenset, type(None)}, sorted=sorted, tuple=tuple, type=type, len=len): - 'Make a cache key from optionally typed positional and keyword arguments' + """Make a cache key from optionally typed positional and keyword arguments + + The key is constructed in a way that is flat as possible rather than + as a nested structure that would take more memory. + + If there is only a single argument and its data type is known to cache + its hash value, then that argument is returned without a wrapper. This + saves space and improves lookup speed. + + """ key = args if kwds: sorted_items = sorted(kwds.items()) @@ -217,7 +232,7 @@ if maxsize == 0: def wrapper(*args, **kwds): - # no caching, just a statistics update after a successful call + # No caching -- just a statistics update after a successful call nonlocal misses result = user_function(*args, **kwds) misses += 1 @@ -226,7 +241,7 @@ elif maxsize is None: def wrapper(*args, **kwds): - # simple caching without ordering or size limit + # Simple caching without ordering or size limit nonlocal hits, misses, currsize key = make_key(args, kwds, typed) result = cache_get(key, sentinel) @@ -242,14 +257,14 @@ else: def wrapper(*args, **kwds): - # size limited caching that tracks accesses by recency + # Size limited caching that tracks accesses by recency nonlocal root, hits, misses, currsize, full key = make_key(args, kwds, typed) with lock: link = cache_get(key) if link is not None: - # move the link to the front of the circular queue - link_prev, link_next, key, result = link + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link link_prev[NEXT] = link_next link_next[PREV] = link_prev last = root[PREV] @@ -261,26 +276,34 @@ result = user_function(*args, **kwds) with lock: if key in cache: - # getting here means that this same key was added to the - # cache while the lock was released. since the link + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link # update is already done, we need only return the # computed result and update the count of misses. pass elif full: - # use the old root to store the new key and result + # Use the old root to store the new key and result. oldroot = root oldroot[KEY] = key oldroot[RESULT] = result - # empty the oldest link and make it the new root + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. root = oldroot[NEXT] oldkey = root[KEY] - oldvalue = root[RESULT] + oldresult = root[RESULT] root[KEY] = root[RESULT] = None - # now update the cache dictionary for the new links + # Now update the cache dictionary. del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. cache[key] = oldroot else: - # put result in a new link at the front of the queue + # Put result in a new link at the front of the queue. last = root[PREV] link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 05:15:19 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 9 Mar 2013 05:15:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZNC0l1VrmzQKt@mail.python.org> http://hg.python.org/cpython/rev/f87346952c10 changeset: 82559:f87346952c10 parent: 82556:d86f5686cef9 parent: 82558:1af9f7df3a96 user: Raymond Hettinger date: Fri Mar 08 21:14:46 2013 -0700 summary: merge files: Lib/functools.py | 47 ++++++++++++++++++++++++++--------- 1 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -20,7 +20,7 @@ from _thread import RLock except: class RLock: - 'Dummy reentrant lock' + 'Dummy reentrant lock for builds without threads' def __enter__(self): pass def __exit__(self, exctype, excinst, exctb): pass @@ -172,6 +172,12 @@ _CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"]) class _HashedSeq(list): + """ This class guarantees that hash() will be called no more than once + per element. This is important because the lru_cache() will hash + the key multiple times on a cache miss. + + """ + __slots__ = 'hashvalue' def __init__(self, tup, hash=hash): @@ -185,7 +191,16 @@ kwd_mark = (object(),), fasttypes = {int, str, frozenset, type(None)}, sorted=sorted, tuple=tuple, type=type, len=len): - 'Make a cache key from optionally typed positional and keyword arguments' + """Make a cache key from optionally typed positional and keyword arguments + + The key is constructed in a way that is flat as possible rather than + as a nested structure that would take more memory. + + If there is only a single argument and its data type is known to cache + its hash value, then that argument is returned without a wrapper. This + saves space and improves lookup speed. + + """ key = args if kwds: sorted_items = sorted(kwds.items()) @@ -242,7 +257,7 @@ if maxsize == 0: def wrapper(*args, **kwds): - # no caching, just a statistics update after a successful call + # No caching -- just a statistics update after a successful call nonlocal misses result = user_function(*args, **kwds) misses += 1 @@ -272,8 +287,8 @@ with lock: link = cache_get(key) if link is not None: - # move the link to the front of the circular queue - link_prev, link_next, key, result = link + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link link_prev[NEXT] = link_next link_next[PREV] = link_prev last = root[PREV] @@ -285,26 +300,34 @@ result = user_function(*args, **kwds) with lock: if key in cache: - # getting here means that this same key was added to the - # cache while the lock was released. since the link + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link # update is already done, we need only return the # computed result and update the count of misses. pass elif full: - # use the old root to store the new key and result + # Use the old root to store the new key and result. oldroot = root oldroot[KEY] = key oldroot[RESULT] = result - # empty the oldest link and make it the new root + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. root = oldroot[NEXT] oldkey = root[KEY] - oldvalue = root[RESULT] + oldresult = root[RESULT] root[KEY] = root[RESULT] = None - # now update the cache dictionary for the new links + # Now update the cache dictionary. del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. cache[key] = oldroot else: - # put result in a new link at the front of the queue + # Put result in a new link at the front of the queue. last = root[PREV] link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Mar 9 05:58:21 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 09 Mar 2013 05:58:21 +0100 Subject: [Python-checkins] Daily reference leaks (d86f5686cef9): sum=1 Message-ID: results for d86f5686cef9 on branch "default" -------------------------------------------- test_unittest leaked [0, -1, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogndO2qh', '-x'] From python-checkins at python.org Sat Mar 9 08:05:29 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 9 Mar 2013 08:05:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Sync-up_with_3?= =?utf-8?q?=2E4_to_make_maintenance_easier=2E?= Message-ID: <3ZNGn561zRzQLy@mail.python.org> http://hg.python.org/cpython/rev/a9fa8a18d18d changeset: 82560:a9fa8a18d18d branch: 3.3 parent: 82558:1af9f7df3a96 user: Raymond Hettinger date: Fri Mar 08 23:01:07 2013 -0800 summary: Sync-up with 3.4 to make maintenance easier. files: Lib/functools.py | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -222,7 +222,7 @@ def decorating_function(user_function): cache = {} - hits = misses = currsize = 0 + hits = misses = 0 full = False cache_get = cache.get # bound method to lookup a key or return None lock = RLock() # because linkedlist updates aren't threadsafe @@ -242,7 +242,7 @@ def wrapper(*args, **kwds): # Simple caching without ordering or size limit - nonlocal hits, misses, currsize + nonlocal hits, misses key = make_key(args, kwds, typed) result = cache_get(key, sentinel) if result is not sentinel: @@ -251,14 +251,13 @@ result = user_function(*args, **kwds) cache[key] = result misses += 1 - currsize += 1 return result else: def wrapper(*args, **kwds): # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, currsize, full + nonlocal root, hits, misses, full key = make_key(args, kwds, typed) with lock: link = cache_get(key) @@ -307,23 +306,22 @@ last = root[PREV] link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link - currsize += 1 - full = (currsize >= maxsize) + full = (len(cache) >= maxsize) misses += 1 return result def cache_info(): """Report cache statistics""" with lock: - return _CacheInfo(hits, misses, maxsize, currsize) + return _CacheInfo(hits, misses, maxsize, len(cache)) def cache_clear(): """Clear the cache and cache statistics""" - nonlocal hits, misses, currsize, full + nonlocal hits, misses, full with lock: cache.clear() root[:] = [root, root, None, None] - hits = misses = currsize = 0 + hits = misses = 0 full = False wrapper.cache_info = cache_info -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:05:31 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 9 Mar 2013 08:05:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZNGn71ltDzQn6@mail.python.org> http://hg.python.org/cpython/rev/02ffc9f94aab changeset: 82561:02ffc9f94aab parent: 82559:f87346952c10 parent: 82560:a9fa8a18d18d user: Raymond Hettinger date: Fri Mar 08 23:04:47 2013 -0800 summary: merge files: Lib/functools.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -266,7 +266,7 @@ elif maxsize is None: def wrapper(*args, **kwds): - # simple caching without ordering or size limit + # Simple caching without ordering or size limit nonlocal hits, misses key = make_key(args, kwds, typed) result = cache_get(key, sentinel) @@ -281,7 +281,7 @@ else: def wrapper(*args, **kwds): - # size limited caching that tracks accesses by recency + # Size limited caching that tracks accesses by recency nonlocal root, hits, misses, full key = make_key(args, kwds, typed) with lock: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:26:49 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 08:26:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2NjQy?= =?utf-8?q?=3A_sched=2Escheduler_timefunc_initial_default_is_time=2Emonoto?= =?utf-8?q?nic=2E?= Message-ID: <3ZNHFj514szQKt@mail.python.org> http://hg.python.org/cpython/rev/258028711466 changeset: 82562:258028711466 branch: 3.3 parent: 82558:1af9f7df3a96 user: Terry Jan Reedy date: Sat Mar 09 02:14:27 2013 -0500 summary: Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte files: Doc/library/sched.rst | 5 +++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/library/sched.rst b/Doc/library/sched.rst --- a/Doc/library/sched.rst +++ b/Doc/library/sched.rst @@ -14,12 +14,13 @@ The :mod:`sched` module defines a class which implements a general purpose event scheduler: -.. class:: scheduler(timefunc=time.time, delayfunc=time.sleep) +.. class:: scheduler(timefunc=time.monotonic, delayfunc=time.sleep) The :class:`scheduler` class defines a generic interface to scheduling events. It needs two functions to actually deal with the "outside world" --- *timefunc* should be callable without arguments, and return a number (the "time", in any - units whatsoever). The *delayfunc* function should be callable with one + units whatsoever). If time.monotonic is not available, the *timefunc* default + is time.time instead. The *delayfunc* function should be callable with one argument, compatible with the output of *timefunc*, and should delay that many time units. *delayfunc* will also be called with the argument ``0`` after each event is run to allow other threads an opportunity to run in multi-threaded diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -44,6 +44,7 @@ Ankur Ankan Jon Anglin Heidi Annexstad +Ramchandra Apte ?ric Araujo Alicia Arlen Jeffrey Armstrong diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -802,6 +802,9 @@ Documentation ------------- +- Issue #16642: sched.scheduler timefunc initial default is time.monotonic. + Patch by Ramchandra Apte + - Issue #15465: Document the versioning macros in the C API docs rather than the standard library docs. Patch by Kushal Das. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:26:51 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 08:26:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_closes_issue_16643_=28not_=2E=2E=2E=2E2_as_in_l?= =?utf-8?q?ast_commit_message=29?= Message-ID: <3ZNHFl0gPfzQn9@mail.python.org> http://hg.python.org/cpython/rev/ca56baa46d35 changeset: 82563:ca56baa46d35 parent: 82559:f87346952c10 parent: 82562:258028711466 user: Terry Jan Reedy date: Sat Mar 09 02:19:33 2013 -0500 summary: Merge: closes issue 16643 (not ....2 as in last commit message) files: Doc/library/sched.rst | 5 +++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/library/sched.rst b/Doc/library/sched.rst --- a/Doc/library/sched.rst +++ b/Doc/library/sched.rst @@ -14,12 +14,13 @@ The :mod:`sched` module defines a class which implements a general purpose event scheduler: -.. class:: scheduler(timefunc=time.time, delayfunc=time.sleep) +.. class:: scheduler(timefunc=time.monotonic, delayfunc=time.sleep) The :class:`scheduler` class defines a generic interface to scheduling events. It needs two functions to actually deal with the "outside world" --- *timefunc* should be callable without arguments, and return a number (the "time", in any - units whatsoever). The *delayfunc* function should be callable with one + units whatsoever). If time.monotonic is not available, the *timefunc* default + is time.time instead. The *delayfunc* function should be callable with one argument, compatible with the output of *timefunc*, and should delay that many time units. *delayfunc* will also be called with the argument ``0`` after each event is run to allow other threads an opportunity to run in multi-threaded diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -44,6 +44,7 @@ Ankur Ankan Jon Anglin Heidi Annexstad +Ramchandra Apte ?ric Araujo Alicia Arlen Jeffrey Armstrong diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1078,6 +1078,9 @@ Documentation ------------- +- Issue #16642: sched.scheduler timefunc initial default is time.monotonic. + Patch by Ramchandra Apte + - Issue #15465: Document the versioning macros in the C API docs rather than the standard library docs. Patch by Kushal Das. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:26:52 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 08:26:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3ZNHFm3FhqzQqQ@mail.python.org> http://hg.python.org/cpython/rev/a4de286f9f4b changeset: 82564:a4de286f9f4b parent: 82563:ca56baa46d35 parent: 82561:02ffc9f94aab user: Terry Jan Reedy date: Sat Mar 09 02:22:03 2013 -0500 summary: Merge heads files: Lib/functools.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -266,7 +266,7 @@ elif maxsize is None: def wrapper(*args, **kwds): - # simple caching without ordering or size limit + # Simple caching without ordering or size limit nonlocal hits, misses key = make_key(args, kwds, typed) result = cache_get(key, sentinel) @@ -281,7 +281,7 @@ else: def wrapper(*args, **kwds): - # size limited caching that tracks accesses by recency + # Size limited caching that tracks accesses by recency nonlocal root, hits, misses, full key = make_key(args, kwds, typed) with lock: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:26:53 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 08:26:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuMyk6?= =?utf-8?q?_Merge_heads?= Message-ID: <3ZNHFn63QxzQKt@mail.python.org> http://hg.python.org/cpython/rev/032681806a0a changeset: 82565:032681806a0a branch: 3.3 parent: 82562:258028711466 parent: 82560:a9fa8a18d18d user: Terry Jan Reedy date: Sat Mar 09 02:25:18 2013 -0500 summary: Merge heads files: Lib/functools.py | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -222,7 +222,7 @@ def decorating_function(user_function): cache = {} - hits = misses = currsize = 0 + hits = misses = 0 full = False cache_get = cache.get # bound method to lookup a key or return None lock = RLock() # because linkedlist updates aren't threadsafe @@ -242,7 +242,7 @@ def wrapper(*args, **kwds): # Simple caching without ordering or size limit - nonlocal hits, misses, currsize + nonlocal hits, misses key = make_key(args, kwds, typed) result = cache_get(key, sentinel) if result is not sentinel: @@ -251,14 +251,13 @@ result = user_function(*args, **kwds) cache[key] = result misses += 1 - currsize += 1 return result else: def wrapper(*args, **kwds): # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, currsize, full + nonlocal root, hits, misses, full key = make_key(args, kwds, typed) with lock: link = cache_get(key) @@ -307,23 +306,22 @@ last = root[PREV] link = [last, root, key, result] last[NEXT] = root[PREV] = cache[key] = link - currsize += 1 - full = (currsize >= maxsize) + full = (len(cache) >= maxsize) misses += 1 return result def cache_info(): """Report cache statistics""" with lock: - return _CacheInfo(hits, misses, maxsize, currsize) + return _CacheInfo(hits, misses, maxsize, len(cache)) def cache_clear(): """Clear the cache and cache statistics""" - nonlocal hits, misses, currsize, full + nonlocal hits, misses, full with lock: cache.clear() root[:] = [root, root, None, None] - hits = misses = currsize = 0 + hits = misses = 0 full = False wrapper.cache_info = cache_info -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 08:26:55 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Mar 2013 08:26:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3ZNHFq1XVPzQXR@mail.python.org> http://hg.python.org/cpython/rev/d0fcb4c9f231 changeset: 82566:d0fcb4c9f231 parent: 82564:a4de286f9f4b parent: 82565:032681806a0a user: Terry Jan Reedy date: Sat Mar 09 02:26:07 2013 -0500 summary: Merge with 3.3 files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 14:56:21 2013 From: python-checkins at python.org (eli.bendersky) Date: Sat, 9 Mar 2013 14:56:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Add_warning_in?= =?utf-8?q?_ctypes_documentation_for_=2316575_and_=2316576?= Message-ID: <3ZNRv908rkzQP3@mail.python.org> http://hg.python.org/cpython/rev/0acd9408b6f1 changeset: 82567:0acd9408b6f1 branch: 3.2 parent: 82554:55fd9810c9ab user: Eli Bendersky date: Sat Mar 09 05:54:00 2013 -0800 summary: Add warning in ctypes documentation for #16575 and #16576 files: Doc/library/ctypes.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -603,6 +603,13 @@ .. _ctypes-structureunion-alignment-byte-order: +.. warning:: + + :mod:`ctypes` does not support passing unions or structures with bit-fields + to functions by value. While this may work on 32-bit x86, it's not + guaranteed by the library to work in the general case. Unions and + structures with bit-fields should always be passed to functions by pointer. + Structure/union alignment and byte order ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 14:56:22 2013 From: python-checkins at python.org (eli.bendersky) Date: Sat, 9 Mar 2013 14:56:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Add_warning_in_ctypes_documentation_for_=2316575_and_=2316576?= Message-ID: <3ZNRvB32drzQwc@mail.python.org> http://hg.python.org/cpython/rev/bfc159f8e4b4 changeset: 82568:bfc159f8e4b4 branch: 3.3 parent: 82565:032681806a0a parent: 82567:0acd9408b6f1 user: Eli Bendersky date: Sat Mar 09 05:54:32 2013 -0800 summary: Add warning in ctypes documentation for #16575 and #16576 files: Doc/library/ctypes.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -608,6 +608,13 @@ .. _ctypes-structureunion-alignment-byte-order: +.. warning:: + + :mod:`ctypes` does not support passing unions or structures with bit-fields + to functions by value. While this may work on 32-bit x86, it's not + guaranteed by the library to work in the general case. Unions and + structures with bit-fields should always be passed to functions by pointer. + Structure/union alignment and byte order ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 14:56:23 2013 From: python-checkins at python.org (eli.bendersky) Date: Sat, 9 Mar 2013 14:56:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Add_warning_in_ctypes_documentation_for_=2316575_and_=23?= =?utf-8?q?16576?= Message-ID: <3ZNRvC6CBqzQxl@mail.python.org> http://hg.python.org/cpython/rev/502624235c7b changeset: 82569:502624235c7b parent: 82566:d0fcb4c9f231 parent: 82568:bfc159f8e4b4 user: Eli Bendersky date: Sat Mar 09 05:55:24 2013 -0800 summary: Add warning in ctypes documentation for #16575 and #16576 files: Doc/library/ctypes.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -608,6 +608,13 @@ .. _ctypes-structureunion-alignment-byte-order: +.. warning:: + + :mod:`ctypes` does not support passing unions or structures with bit-fields + to functions by value. While this may work on 32-bit x86, it's not + guaranteed by the library to work in the general case. Unions and + structures with bit-fields should always be passed to functions by pointer. + Structure/union alignment and byte order ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 14:57:31 2013 From: python-checkins at python.org (eli.bendersky) Date: Sat, 9 Mar 2013 14:57:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Add_warning_in?= =?utf-8?q?_ctypes_documentation_for_=2316575_and_=2316576?= Message-ID: <3ZNRwW18tWzPBN@mail.python.org> http://hg.python.org/cpython/rev/eece32440a52 changeset: 82570:eece32440a52 branch: 2.7 parent: 82557:e0ef2bde35c3 user: Eli Bendersky date: Sat Mar 09 05:56:35 2013 -0800 summary: Add warning in ctypes documentation for #16575 and #16576 files: Doc/library/ctypes.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -602,6 +602,13 @@ .. _ctypes-structureunion-alignment-byte-order: +.. warning:: + + :mod:`ctypes` does not support passing unions or structures with bit-fields + to functions by value. While this may work on 32-bit x86, it's not + guaranteed by the library to work in the general case. Unions and + structures with bit-fields should always be passed to functions by pointer. + Structure/union alignment and byte order ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 16:13:45 2013 From: python-checkins at python.org (eli.bendersky) Date: Sat, 9 Mar 2013 16:13:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316954=3A_Add_docs?= =?utf-8?q?trings_for_ElementTree?= Message-ID: <3ZNTcT3PrSzQSF@mail.python.org> http://hg.python.org/cpython/rev/f27d7c1eac4d changeset: 82571:f27d7c1eac4d parent: 82569:502624235c7b user: Eli Bendersky date: Sat Mar 09 07:12:48 2013 -0800 summary: Issue #16954: Add docstrings for ElementTree Based on patch by David Lam files: Lib/xml/etree/ElementTree.py | 1062 ++++++++++----------- Misc/ACKS | 1 + 2 files changed, 486 insertions(+), 577 deletions(-) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1,23 +1,40 @@ +"""Lightweight XML support for Python. + + XML is an inherently hierarchical data format, and the most natural way to + represent it is with a tree. This module has two classes for this purpose: + + 1. ElementTree represents the whole XML document as a tree and + + 2. Element represents a single node in this tree. + + Interactions with the whole document (reading and writing to/from files) are + usually done on the ElementTree level. Interactions with a single XML element + and its sub-elements are done on the Element level. + + Element is a flexible container object designed to store hierarchical data + structures in memory. It can be described as a cross between a list and a + dictionary. Each Element has a number of properties associated with it: + + 'tag' - a string containing the element's name. + + 'attributes' - a Python dictionary storing the element's attributes. + + 'text' - a string containing the element's text content. + + 'tail' - an optional string containing text after the element's end tag. + + And a number of child elements stored in a Python sequence. + + To create an element instance, use the Element constructor, + or the SubElement factory function. + + You can also use the ElementTree class to wrap an element structure + and convert it to and from XML. + +""" + # # ElementTree -# $Id: ElementTree.py 3440 2008-07-18 14:45:01Z fredrik $ -# -# light-weight XML support for Python 2.3 and later. -# -# history (since 1.2.6): -# 2005-11-12 fl added tostringlist/fromstringlist helpers -# 2006-07-05 fl merged in selected changes from the 1.3 sandbox -# 2006-07-05 fl removed support for 2.1 and earlier -# 2007-06-21 fl added deprecation/future warnings -# 2007-08-25 fl added doctype hook, added parser version attribute etc -# 2007-08-26 fl added new serializer code (better namespace handling, etc) -# 2007-08-27 fl warn for broken /tag searches on tree level -# 2007-09-02 fl added html/text methods to serializer (experimental) -# 2007-09-05 fl added method argument to tostring/tostringlist -# 2007-09-06 fl improved error handling -# 2007-09-13 fl added itertext, iterfind; assorted cleanups -# 2007-12-15 fl added C14N hooks, copy method (experimental) -# # Copyright (c) 1999-2008 by Fredrik Lundh. All rights reserved. # # fredrik at pythonware.com @@ -75,28 +92,6 @@ VERSION = "1.3.0" -## -# The Element type is a flexible container object, designed to -# store hierarchical data structures in memory. The type can be -# described as a cross between a list and a dictionary. -#

-# Each element has a number of properties associated with it: -#

    -#
  • a tag. This is a string identifying what kind of data -# this element represents (the element type, in other words).
  • -#
  • a number of attributes, stored in a Python dictionary.
  • -#
  • a text string.
  • -#
  • an optional tail string.
  • -#
  • a number of child elements, stored in a Python sequence
  • -#
-# -# To create an element instance, use the {@link #Element} constructor -# or the {@link #SubElement} factory function. -#

-# The {@link #ElementTree} class can be used to wrap an element -# structure, and convert it from and to XML. -## - import sys import re import warnings @@ -106,81 +101,68 @@ from . import ElementPath -## -# Parser error. This is a subclass of SyntaxError. -#

-# In addition to the exception value, an exception instance contains a -# specific exception code in the code attribute, and the line and -# column of the error in the position attribute. +class ParseError(SyntaxError): + """An error when parsing an XML document. -class ParseError(SyntaxError): + In addition to its exception value, a ParseError contains + two extra attributes: + 'code' - the specific exception code + 'position' - the line and column of the error + + """ pass # -------------------------------------------------------------------- -## -# Checks if an object appears to be a valid element object. -# -# @param An element instance. -# @return A true value if this is an element object. -# @defreturn flag def iselement(element): - # FIXME: not sure about this; - # isinstance(element, Element) or look for tag/attrib/text attributes + """Return True if *element* appears to be an Element.""" return hasattr(element, 'tag') -## -# Element class. This class defines the Element interface, and -# provides a reference implementation of this interface. -#

-# The element name, attribute names, and attribute values can be -# either ASCII strings (ordinary Python strings containing only 7-bit -# ASCII characters) or Unicode strings. -# -# @param tag The element name. -# @param attrib An optional dictionary, containing element attributes. -# @param **extra Additional attributes, given as keyword arguments. -# @see Element -# @see SubElement -# @see Comment -# @see ProcessingInstruction class Element: - # text...tail + """An XML element. - ## - # (Attribute) Element tag. + This class is the reference implementation of the Element interface. + + An element's length is its number of subelements. That means if you + you want to check if an element is truly empty, you should check BOTH + its length AND its text attribute. + + The element tag, attribute names, and attribute values can be either + bytes or strings. + + *tag* is the element name. *attrib* is an optional dictionary containing + element attributes. *extra* are additional element attributes given as + keyword arguments. + + Example form: + text...tail + + """ tag = None - - ## - # (Attribute) Element attribute dictionary. Where possible, use - # {@link #Element.get}, - # {@link #Element.set}, - # {@link #Element.keys}, and - # {@link #Element.items} to access - # element attributes. + """The element's name.""" attrib = None - - ## - # (Attribute) Text before first subelement. This is either a - # string or the value None. Note that if there was no text, this - # attribute may be either None or an empty string, depending on - # the parser. + """Dictionary of the element's attributes.""" text = None + """ + Text before first subelement. This is either a string or the value None. + Note that if there is no text, this attribute may be either + None or the empty string, depending on the parser. - ## - # (Attribute) Text after this element's end tag, but before the - # next sibling element's start tag. This is either a string or - # the value None. Note that if there was no text, this attribute - # may be either None or an empty string, depending on the parser. + """ - tail = None # text after end tag, if any + tail = None + """ + Text after this element's end tag, but before the next sibling element's + start tag. This is either a string or the value None. Note that if there + was no text, this attribute may be either None or an empty string, + depending on the parser. - # constructor + """ def __init__(self, tag, attrib={}, **extra): if not isinstance(attrib, dict): @@ -195,36 +177,30 @@ def __repr__(self): return "" % (repr(self.tag), id(self)) - ## - # Creates a new element object of the same type as this element. - # - # @param tag Element tag. - # @param attrib Element attributes, given as a dictionary. - # @return A new element instance. + def makeelement(self, tag, attrib): + """Create a new element with the same type. - def makeelement(self, tag, attrib): + *tag* is a string containing the element name. + *attrib* is a dictionary containing the element attributes. + + Do not call this method, use the SubElement factory function instead. + + """ return self.__class__(tag, attrib) - ## - # (Experimental) Copies the current element. This creates a - # shallow copy; subelements will be shared with the original tree. - # - # @return A new element instance. + def copy(self): + """Return copy of current element. - def copy(self): + This creates a shallow copy. Subelements will be shared with the + original tree. + + """ elem = self.makeelement(self.tag, self.attrib) elem.text = self.text elem.tail = self.tail elem[:] = self return elem - ## - # Returns the number of subelements. Note that this only counts - # full elements; to check if there's any content in an element, you - # have to check both the length and the text attribute. - # - # @return The number of subelements. - def __len__(self): return len(self._children) @@ -236,23 +212,9 @@ ) return len(self._children) != 0 # emulate old behaviour, for now - ## - # Returns the given subelement, by index. - # - # @param index What subelement to return. - # @return The given subelement. - # @exception IndexError If the given element does not exist. - def __getitem__(self, index): return self._children[index] - ## - # Replaces the given subelement, by index. - # - # @param index What subelement to replace. - # @param element The new element value. - # @exception IndexError If the given element does not exist. - def __setitem__(self, index, element): # if isinstance(index, slice): # for elt in element: @@ -261,46 +223,35 @@ # assert iselement(element) self._children[index] = element - ## - # Deletes the given subelement, by index. - # - # @param index What subelement to delete. - # @exception IndexError If the given element does not exist. - def __delitem__(self, index): del self._children[index] - ## - # Adds a subelement to the end of this element. In document order, - # the new element will appear after the last existing subelement (or - # directly after the text, if it's the first subelement), but before - # the end tag for this element. - # - # @param element The element to add. + def append(self, subelement): + """Add *subelement* to the end of this element. - def append(self, element): - self._assert_is_element(element) - self._children.append(element) + The new element will appear in document order after the last existing + subelement (or directly after the text, if it's the first subelement), + but before the end tag for this element. - ## - # Appends subelements from a sequence. - # - # @param elements A sequence object with zero or more elements. - # @since 1.3 + """ + self._assert_is_element(subelement) + self._children.append(subelement) def extend(self, elements): + """Append subelements from a sequence. + + *elements* is a sequence with zero or more elements. + + """ for element in elements: self._assert_is_element(element) self._children.extend(elements) - ## - # Inserts a subelement at the given position in this element. - # - # @param index Where to insert the new subelement. - def insert(self, index, element): - self._assert_is_element(element) - self._children.insert(index, element) + def insert(self, index, subelement): + """Insert *subelement* at position *index*.""" + self._assert_is_element(subelement) + self._children.insert(index, subelement) def _assert_is_element(self, e): # Need to refer to the actual Python implementation, not the @@ -308,29 +259,28 @@ if not isinstance(e, _Element): raise TypeError('expected an Element, not %s' % type(e).__name__) - ## - # Removes a matching subelement. Unlike the find methods, - # this method compares elements based on identity, not on tag - # value or contents. To remove subelements by other means, the - # easiest way is often to use a list comprehension to select what - # elements to keep, and use slice assignment to update the parent - # element. - # - # @param element What element to remove. - # @exception ValueError If a matching element could not be found. - def remove(self, element): + def remove(self, subelement): + """Remove matching subelement. + + Unlike the find methods, this method compares elements based on + identity, NOT ON tag value or contents. To remove subelements by + other means, the easiest way is to use a list comprehension to + select what elements to keep, and then use slice assignment to update + the parent element. + + ValueError is raised if a matching element could not be found. + + """ # assert iselement(element) - self._children.remove(element) - - ## - # (Deprecated) Returns all subelements. The elements are returned - # in document order. - # - # @return A list of subelements. - # @defreturn list of Element instances + self._children.remove(subelement) def getchildren(self): + """(Deprecated) Return all subelements. + + Elements are returned in document order. + + """ warnings.warn( "This method will be removed in future versions. " "Use 'list(elem)' or iteration over elem instead.", @@ -338,124 +288,132 @@ ) return self._children - ## - # Finds the first matching subelement, by tag name or path. - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return The first matching element, or None if no element was found. - # @defreturn Element or None def find(self, path, namespaces=None): + """Find first matching element by tag name or path. + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return the first matching element, or None if no element was found. + + """ return ElementPath.find(self, path, namespaces) - ## - # Finds text for the first matching subelement, by tag name or path. - # - # @param path What element to look for. - # @param default What to return if the element was not found. - # @keyparam namespaces Optional namespace prefix map. - # @return The text content of the first matching element, or the - # default value no element was found. Note that if the element - # is found, but has no text content, this method returns an - # empty string. - # @defreturn string def findtext(self, path, default=None, namespaces=None): + """Find text for first matching element by tag name or path. + + *path* is a string having either an element tag or an XPath, + *default* is the value to return if the element was not found, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return text content of first matching element, or default value if + none was found. Note that if an element is found having no text + content, the empty string is returned. + + """ return ElementPath.findtext(self, path, default, namespaces) - ## - # Finds all matching subelements, by tag name or path. - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return A list or other sequence containing all matching elements, - # in document order. - # @defreturn list of Element instances def findall(self, path, namespaces=None): + """Find all matching subelements by tag name or path. + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Returns list containing all matching elements in document order. + + """ return ElementPath.findall(self, path, namespaces) - ## - # Finds all matching subelements, by tag name or path. - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return An iterator or sequence containing all matching elements, - # in document order. - # @defreturn a generated sequence of Element instances def iterfind(self, path, namespaces=None): + """Find all matching subelements by tag name or path. + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return an iterable yielding all matching elements in document order. + + """ return ElementPath.iterfind(self, path, namespaces) - ## - # Resets an element. This function removes all subelements, clears - # all attributes, and sets the text and tail attributes - # to None. def clear(self): + """Reset element. + + This function removes all subelements, clears all attributes, and sets + the text and tail attributes to None. + + """ self.attrib.clear() self._children = [] self.text = self.tail = None - ## - # Gets an element attribute. Equivalent to attrib.get, but - # some implementations may handle this a bit more efficiently. - # - # @param key What attribute to look for. - # @param default What to return if the attribute was not found. - # @return The attribute value, or the default value, if the - # attribute was not found. - # @defreturn string or None def get(self, key, default=None): + """Get element attribute. + + Equivalent to attrib.get, but some implementations may handle this a + bit more efficiently. *key* is what attribute to look for, and + *default* is what to return if the attribute was not found. + + Returns a string containing the attribute value, or the default if + attribute was not found. + + """ return self.attrib.get(key, default) - ## - # Sets an element attribute. Equivalent to attrib[key] = value, - # but some implementations may handle this a bit more efficiently. - # - # @param key What attribute to set. - # @param value The attribute value. def set(self, key, value): + """Set element attribute. + + Equivalent to attrib[key] = value, but some implementations may handle + this a bit more efficiently. *key* is what attribute to set, and + *value* is the attribute value to set it to. + + """ self.attrib[key] = value - ## - # Gets a list of attribute names. The names are returned in an - # arbitrary order (just like for an ordinary Python dictionary). - # Equivalent to attrib.keys(). - # - # @return A list of element attribute names. - # @defreturn list of strings def keys(self): + """Get list of attribute names. + + Names are returned in an arbitrary order, just like an ordinary + Python dict. Equivalent to attrib.keys() + + """ return self.attrib.keys() - ## - # Gets element attributes, as a sequence. The attributes are - # returned in an arbitrary order. Equivalent to attrib.items(). - # - # @return A list of (name, value) tuples for all attributes. - # @defreturn list of (string, string) tuples def items(self): + """Get element attributes as a sequence. + + The attributes are returned in arbitrary order. Equivalent to + attrib.items(). + + Return a list of (name, value) tuples. + + """ return self.attrib.items() - ## - # Creates a tree iterator. The iterator loops over this element - # and all subelements, in document order, and returns all elements - # with a matching tag. - #

- # If the tree structure is modified during iteration, new or removed - # elements may or may not be included. To get a stable set, use the - # list() function on the iterator, and loop over the resulting list. - # - # @param tag What tags to look for (default is to return all elements). - # @return An iterator containing all the matching elements. - # @defreturn iterator def iter(self, tag=None): + """Create tree iterator. + + The iterator loops over the element and all subelements in document + order, returning all elements with a matching tag. + + If the tree structure is modified during iteration, new or removed + elements may or may not be included. To get a stable set, use the + list() function on the iterator, and loop over the resulting list. + + *tag* is what tags to look for (default is to return all elements) + + Return an iterator containing all the matching elements. + + """ if tag == "*": tag = None if tag is None or self.tag == tag: @@ -473,15 +431,14 @@ ) return list(self.iter(tag)) - ## - # Creates a text iterator. The iterator loops over this element - # and all subelements, in document order, and returns all inner - # text. - # - # @return An iterator containing all inner text. - # @defreturn iterator def itertext(self): + """Create text iterator. + + The iterator loops over the element and all subelements in document + order, returning all inner text. + + """ tag = self.tag if not isinstance(tag, str) and tag is not None: return @@ -495,55 +452,50 @@ # compatibility _Element = _ElementInterface = Element -## -# Subelement factory. This function creates an element instance, and -# appends it to an existing element. -#

-# The element name, attribute names, and attribute values can be -# either 8-bit ASCII strings or Unicode strings. -# -# @param parent The parent element. -# @param tag The subelement name. -# @param attrib An optional dictionary, containing element attributes. -# @param **extra Additional attributes, given as keyword arguments. -# @return An element instance. -# @defreturn Element def SubElement(parent, tag, attrib={}, **extra): + """Subelement factory which creates an element instance, and appends it + to an existing parent. + + The element tag, attribute names, and attribute values can be either + bytes or Unicode strings. + + *parent* is the parent element, *tag* is the subelements name, *attrib* is + an optional directory containing element attributes, *extra* are + additional attributes given as keyword arguments. + + """ attrib = attrib.copy() attrib.update(extra) element = parent.makeelement(tag, attrib) parent.append(element) return element -## -# Comment element factory. This factory function creates a special -# element that will be serialized as an XML comment by the standard -# serializer. -#

-# The comment string can be either an 8-bit ASCII string or a Unicode -# string. -# -# @param text A string containing the comment string. -# @return An element instance, representing a comment. -# @defreturn Element def Comment(text=None): + """Comment element factory. + + This function creates a special element which the standard serializer + serializes as an XML comment. + + *text* is a string containing the comment string. + + """ element = Element(Comment) element.text = text return element -## -# PI element factory. This factory function creates a special element -# that will be serialized as an XML processing instruction by the standard -# serializer. -# -# @param target A string containing the PI target. -# @param text A string containing the PI contents, if any. -# @return An element instance, representing a PI. -# @defreturn Element def ProcessingInstruction(target, text=None): + """Processing Instruction element factory. + + This function creates a special element which the standard serializer + serializes as an XML comment. + + *target* is a string containing the processing instruction, *text* is a + string containing the processing instruction contents, if any. + + """ element = Element(ProcessingInstruction) element.text = target if text: @@ -552,17 +504,21 @@ PI = ProcessingInstruction -## -# QName wrapper. This can be used to wrap a QName attribute value, in -# order to get proper namespace handling on output. -# -# @param text A string containing the QName value, in the form {uri}local, -# or, if the tag argument is given, the URI part of a QName. -# @param tag Optional tag. If given, the first argument is interpreted as -# an URI, and this argument is interpreted as a local name. -# @return An opaque object, representing the QName. class QName: + """Qualified name wrapper. + + This class can be used to wrap a QName attribute value in order to get + proper namespace handing on output. + + *text_or_uri* is a string containing the QName value either in the form + {uri}local, or if the tag argument is given, the URI part of a QName. + + *tag* is an optional argument which if given, will make the first + argument (text_or_uri) be interpreted as a URI, and this argument (tag) + be interpreted as a local name. + + """ def __init__(self, text_or_uri, tag=None): if tag: text_or_uri = "{%s}%s" % (text_or_uri, tag) @@ -600,55 +556,49 @@ # -------------------------------------------------------------------- -## -# ElementTree wrapper class. This class represents an entire element -# hierarchy, and adds some extra support for serialization to and from -# standard XML. -# -# @param element Optional root element. -# @keyparam file Optional file handle or file name. If given, the -# tree is initialized with the contents of this XML file. class ElementTree: + """An XML element hierarchy. + This class also provides support for serialization to and from + standard XML. + + *element* is an optional root element node, + *file* is an optional file handle or file name of an XML file whose + contents will be used to initialize the tree with. + + """ def __init__(self, element=None, file=None): # assert element is None or iselement(element) self._root = element # first node if file: self.parse(file) - ## - # Gets the root element for this tree. - # - # @return An element instance. - # @defreturn Element - def getroot(self): + """Return root element of this tree.""" return self._root - ## - # Replaces the root element for this tree. This discards the - # current contents of the tree, and replaces it with the given - # element. Use with care. - # - # @param element An element instance. + def _setroot(self, element): + """Replace root element of this tree. - def _setroot(self, element): + This will discard the current contents of the tree and replace it + with the given element. Use with care! + + """ # assert iselement(element) self._root = element - ## - # Loads an external XML document into this element tree. - # - # @param source A file name or file object. If a file object is - # given, it only has to implement a read(n) method. - # @keyparam parser An optional parser instance. If not given, the - # standard {@link XMLParser} parser is used. - # @return The document root element. - # @defreturn Element - # @exception ParseError If the parser fails to parse the document. + def parse(self, source, parser=None): + """Load external XML document into element tree. - def parse(self, source, parser=None): + *source* is a file name or file object, *parser* is an optional parser + instance that defaults to XMLParser. + + ParseError is raised if the parser fails to parse the document. + + Returns the root element of the given source document. + + """ close_source = False if not hasattr(source, "read"): source = open(source, "rb") @@ -667,15 +617,15 @@ if close_source: source.close() - ## - # Creates a tree iterator for the root element. The iterator loops - # over all elements in this tree, in document order. - # - # @param tag What tags to look for (default is to return all elements) - # @return An iterator. - # @defreturn iterator + def iter(self, tag=None): + """Create and return tree iterator for the root element. - def iter(self, tag=None): + The iterator loops over all elements in this tree, in document order. + + *tag* is a string with the tag name to iterate over + (default is to return all elements). + + """ # assert self._root is not None return self._root.iter(tag) @@ -689,16 +639,17 @@ ) return list(self.iter(tag)) - ## - # Finds the first toplevel element with given tag. - # Same as getroot().find(path). - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return The first matching element, or None if no element was found. - # @defreturn Element or None + def find(self, path, namespaces=None): + """Find first matching element by tag name or path. - def find(self, path, namespaces=None): + Same as getroot().find(path), which is Element.find() + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return the first matching element, or None if no element was found. + + """ # assert self._root is not None if path[:1] == "/": path = "." + path @@ -710,20 +661,17 @@ ) return self._root.find(path, namespaces) - ## - # Finds the element text for the first toplevel element with given - # tag. Same as getroot().findtext(path). - # - # @param path What toplevel element to look for. - # @param default What to return if the element was not found. - # @keyparam namespaces Optional namespace prefix map. - # @return The text content of the first matching element, or the - # default value no element was found. Note that if the element - # is found, but has no text content, this method returns an - # empty string. - # @defreturn string + def findtext(self, path, default=None, namespaces=None): + """Find first matching element by tag name or path. - def findtext(self, path, default=None, namespaces=None): + Same as getroot().findtext(path), which is Element.findtext() + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return the first matching element, or None if no element was found. + + """ # assert self._root is not None if path[:1] == "/": path = "." + path @@ -735,17 +683,17 @@ ) return self._root.findtext(path, default, namespaces) - ## - # Finds all toplevel elements with the given tag. - # Same as getroot().findall(path). - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return A list or iterator containing all matching elements, - # in document order. - # @defreturn list of Element instances + def findall(self, path, namespaces=None): + """Find all matching subelements by tag name or path. - def findall(self, path, namespaces=None): + Same as getroot().findall(path), which is Element.findall(). + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return list containing all matching elements in document order. + + """ # assert self._root is not None if path[:1] == "/": path = "." + path @@ -757,17 +705,17 @@ ) return self._root.findall(path, namespaces) - ## - # Finds all matching subelements, by tag name or path. - # Same as getroot().iterfind(path). - # - # @param path What element to look for. - # @keyparam namespaces Optional namespace prefix map. - # @return An iterator or sequence containing all matching elements, - # in document order. - # @defreturn a generated sequence of Element instances + def iterfind(self, path, namespaces=None): + """Find all matching subelements by tag name or path. - def iterfind(self, path, namespaces=None): + Same as getroot().iterfind(path), which is element.iterfind() + + *path* is a string having either an element tag or an XPath, + *namespaces* is an optional mapping from namespace prefix to full name. + + Return an iterable yielding all matching elements in document order. + + """ # assert self._root is not None if path[:1] == "/": path = "." + path @@ -785,18 +733,27 @@ default_namespace=None, method=None, *, short_empty_elements=True): - """Write the element tree to a file, as XML. 'file_or_filename' is a - file name or a file object opened for writing. - 'encoding' is the output encoding (default is US-ASCII). - 'xml_declaration' controls if an XML declaration should be added - to the output. Use False for never, True for always, None for only - if not US-ASCII or UTF-8 or Unicode (default is None). - 'default_namespace' sets the default XML namespace (for "xmlns"). - 'method' is either "xml" (default), "html", "text" or "c14n". - The keyword-only 'short_empty_elements' parameter controls the - formatting of elements that contain no content. If True (default), - they are emitted as a single self-closed tag, otherwise they are - emitted as a pair of start/end tags. + """Write element tree to a file as XML. + + Arguments: + *file_or_filename* -- file name or a file object opened for writing + + *encoding* -- the output encoding (default: US-ASCII) + + *xml_declaration* -- bool indicating if an XML declaration should be + added to the output. If None, an XML declaration + is added if encoding IS NOT either of: + US-ASCII, UTF-8, or Unicode + + *default_namespace* -- sets the default XML namespace (for "xmlns") + + *method* -- either "xml" (default), "html, "text", or "c14n" + + *short_empty_elements* -- controls the formatting of elements + that contain no content. If True (default) + they are emitted as a single self-closed + tag, otherwise they are emitted as a pair + of start/end tags """ if not method: @@ -1071,18 +1028,19 @@ # "c14n": _serialize_c14n, } -## -# Registers a namespace prefix. The registry is global, and any -# existing mapping for either the given prefix or the namespace URI -# will be removed. -# -# @param prefix Namespace prefix. -# @param uri Namespace uri. Tags and attributes in this namespace -# will be serialized with the given prefix, if at all possible. -# @exception ValueError If the prefix is reserved, or is otherwise -# invalid. def register_namespace(prefix, uri): + """Register a namespace prefix. + + The registry is global, and any existing mapping for either the + given prefix or the namespace URI will be removed. + + *prefix* is the namespace prefix, *uri* is a namespace uri. Tags and + attributes in this namespace will be serialized with prefix if possible. + + ValueError is raised if prefix is reserved or is invalid. + + """ if re.match("ns\d+$", prefix): raise ValueError("Prefix format reserved for internal use") for k, v in list(_namespace_map.items()): @@ -1158,42 +1116,27 @@ # -------------------------------------------------------------------- -## -# Generates a string representation of an XML element, including all -# subelements. If encoding is "unicode", the return type is a string; -# otherwise it is a bytes array. -# -# @param element An Element instance. -# @keyparam encoding Optional output encoding (default is US-ASCII). -# Use "unicode" to return a Unicode string. -# @keyparam method Optional output method ("xml", "html", "text" or -# "c14n"; default is "xml"). -# @return An (optionally) encoded string containing the XML data. -# @defreturn string - def tostring(element, encoding=None, method=None, *, short_empty_elements=True): + """Generate string representation of XML element. + + All subelements are included. If encoding is "unicode", a string + is returned. Otherwise a bytestring is returned. + + *element* is an Element instance, *encoding* is an optional output + encoding defaulting to US-ASCII, *method* is an optional output which can + be one of "xml" (default), "html", "text" or "c14n". + + Returns an (optionally) encoded string containing the XML data. + + """ stream = io.StringIO() if encoding == 'unicode' else io.BytesIO() ElementTree(element).write(stream, encoding, method=method, short_empty_elements=short_empty_elements) return stream.getvalue() -## -# Generates a string representation of an XML element, including all -# subelements. -# -# @param element An Element instance. -# @keyparam encoding Optional output encoding (default is US-ASCII). -# Use "unicode" to return a Unicode string. -# @keyparam method Optional output method ("xml", "html", "text" or -# "c14n"; default is "xml"). -# @return A sequence object containing the XML data. -# @defreturn sequence -# @since 1.3 - class _ListDataStream(io.BufferedIOBase): - """ An auxiliary stream accumulating into a list reference - """ + """An auxiliary stream accumulating into a list reference.""" def __init__(self, lst): self.lst = lst @@ -1217,16 +1160,17 @@ short_empty_elements=short_empty_elements) return lst -## -# Writes an element tree or element structure to sys.stdout. This -# function should be used for debugging only. -#

-# The exact output format is implementation dependent. In this -# version, it's written as an ordinary XML file. -# -# @param elem An element tree or an individual element. def dump(elem): + """Write element tree or element structure to sys.stdout. + + This function should be used for debugging only. + + *elem* is either an ElementTree, or a single Element. The exact output + format is implementation dependent. In this version, it's written as an + ordinary XML file. + + """ # debugging if not isinstance(elem, ElementTree): elem = ElementTree(elem) @@ -1238,31 +1182,36 @@ # -------------------------------------------------------------------- # parsing -## -# Parses an XML document into an element tree. -# -# @param source A filename or file object containing XML data. -# @param parser An optional parser instance. If not given, the -# standard {@link XMLParser} parser is used. -# @return An ElementTree instance def parse(source, parser=None): + """Parse XML document into element tree. + + *source* is a filename or file object containing XML data, + *parser* is an optional parser instance defaulting to XMLParser. + + Return an ElementTree instance. + + """ tree = ElementTree() tree.parse(source, parser) return tree -## -# Parses an XML document into an element tree incrementally, and reports -# what's going on to the user. -# -# @param source A filename or file object containing XML data. -# @param events A list of events to report back. If omitted, only "end" -# events are reported. -# @param parser An optional parser instance. If not given, the -# standard {@link XMLParser} parser is used. -# @return A (event, elem) iterator. def iterparse(source, events=None, parser=None): + """Incrementally parse XML document into ElementTree. + + This class also reports what's going on to the user based on the + *events* it is initialized with. The supported events are the strings + "start", "end", "start-ns" and "end-ns" (the "ns" events are used to get + detailed namespace information). If *events* is omitted, only + "end" events are reported. + + *source* is a filename or file object containing XML data, *events* is + a list of events to report back, *parser* is an optional parser instance. + + Returns an iterator providing (event, elem) pairs. + + """ close_source = False if not hasattr(source, "read"): source = open(source, "rb") @@ -1349,33 +1298,34 @@ def __iter__(self): return self -## -# Parses an XML document from a string constant. This function can -# be used to embed "XML literals" in Python code. -# -# @param source A string containing XML data. -# @param parser An optional parser instance. If not given, the -# standard {@link XMLParser} parser is used. -# @return An Element instance. -# @defreturn Element def XML(text, parser=None): + """Parse XML document from string constant. + + This function can be used to embed "XML Literals" in Python code. + + *text* is a string containing XML data, *parser* is an + optional parser instance, defaulting to the standard XMLParser. + + Returns an Element instance. + + """ if not parser: parser = XMLParser(target=TreeBuilder()) parser.feed(text) return parser.close() -## -# Parses an XML document from a string constant, and also returns -# a dictionary which maps from element id:s to elements. -# -# @param source A string containing XML data. -# @param parser An optional parser instance. If not given, the -# standard {@link XMLParser} parser is used. -# @return A tuple containing an Element instance and a dictionary. -# @defreturn (Element, dictionary) def XMLID(text, parser=None): + """Parse XML document from string constant for its IDs. + + *text* is a string containing XML data, *parser* is an + optional parser instance, defaulting to the standard XMLParser. + + Returns an (Element, dict) tuple, in which the + dict maps element id:s to elements. + + """ if not parser: parser = XMLParser(target=TreeBuilder()) parser.feed(text) @@ -1387,27 +1337,18 @@ ids[id] = elem return tree, ids -## -# Parses an XML document from a string constant. Same as {@link #XML}. -# -# @def fromstring(text) -# @param source A string containing XML data. -# @return An Element instance. -# @defreturn Element - fromstring = XML - -## -# Parses an XML document from a sequence of string fragments. -# -# @param sequence A list or other sequence containing XML data fragments. -# @param parser An optional parser instance. If not given, the -# standard {@link XMLParser} parser is used. -# @return An Element instance. -# @defreturn Element -# @since 1.3 +"""Parse XML document from string constant. Alias for XML().""" def fromstringlist(sequence, parser=None): + """Parse XML document from sequence of string fragments. + + *sequence* is a list of other sequence, *parser* is an optional parser + instance, defaulting to the standard XMLParser. + + Returns an Element instance. + + """ if not parser: parser = XMLParser(target=TreeBuilder()) for text in sequence: @@ -1416,19 +1357,20 @@ # -------------------------------------------------------------------- -## -# Generic element structure builder. This builder converts a sequence -# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link -# #TreeBuilder.end} method calls to a well-formed element structure. -#

-# You can use this class to build an element structure using a custom XML -# parser, or a parser for some other XML-like format. -# -# @param element_factory Optional element factory. This factory -# is called to create new Element instances, as necessary. class TreeBuilder: + """Generic element structure builder. + This builder converts a sequence of start, data, and end method + calls to a well-formed element structure. + + You can use this class to build an element structure using a custom XML + parser, or a parser for some other XML-like format. + + *element_factory* is an optional element factory which is called + to create new Element instances, as necessary. + + """ def __init__(self, element_factory=None): self._data = [] # data collector self._elem = [] # element stack @@ -1438,14 +1380,8 @@ element_factory = Element self._factory = element_factory - ## - # Flushes the builder buffers, and returns the toplevel document - # element. - # - # @return An Element instance. - # @defreturn Element - def close(self): + """Flush builder buffers and return toplevel document Element.""" assert len(self._elem) == 0, "missing end tags" assert self._last is not None, "missing toplevel element" return self._last @@ -1462,24 +1398,19 @@ self._last.text = text self._data = [] - ## - # Adds text to the current element. - # - # @param data A string. This should be either an 8-bit string - # containing ASCII text, or a Unicode string. def data(self, data): + """Add text to current element.""" self._data.append(data) - ## - # Opens a new element. - # - # @param tag The element name. - # @param attrib A dictionary containing element attributes. - # @return The opened element. - # @defreturn Element def start(self, tag, attrs): + """Open new element and return it. + + *tag* is the element name, *attrs* is a dict containing element + attributes. + + """ self._flush() self._last = elem = self._factory(tag, attrs) if self._elem: @@ -1488,14 +1419,13 @@ self._tail = 0 return elem - ## - # Closes the current element. - # - # @param tag The element name. - # @return The closed element. - # @defreturn Element def end(self, tag): + """Close and return current Element. + + *tag* is the element name. + + """ self._flush() self._last = self._elem.pop() assert self._last.tag == tag,\ @@ -1504,20 +1434,18 @@ self._tail = 1 return self._last -## -# Element structure builder for XML source data, based on the -# expat parser. -# -# @keyparam target Target object. If omitted, the builder uses an -# instance of the standard {@link #TreeBuilder} class. -# @keyparam html Predefine HTML entities. This flag is not supported -# by the current implementation. -# @keyparam encoding Optional encoding. If given, the value overrides -# the encoding specified in the XML file. -# @see #ElementTree -# @see #TreeBuilder +# also see ElementTree and TreeBuilder class XMLParser: + """Element structure builder for XML source data based on the expat parser. + + *html* are predefined HTML entities (not supported currently), + *target* is an optional target object which defaults to an instance of the + standard TreeBuilder class, *encoding* is an optional encoding string + which if given, overrides the encoding specified in the XML file: + http://www.iana.org/assignments/character-sets + + """ def __init__(self, html=0, target=None, encoding=None): try: @@ -1659,15 +1587,13 @@ self.doctype(name, pubid, system[1:-1]) self._doctype = None - ## - # (Deprecated) Handles a doctype declaration. - # - # @param name Doctype name. - # @param pubid Public identifier. - # @param system System identifier. + def doctype(self, name, pubid, system): + """(Deprecated) Handle doctype declaration - def doctype(self, name, pubid, system): - """This method of XMLParser is deprecated.""" + *name* is the Doctype name, *pubid* is the public identifier, + and *system* is the system identifier. + + """ warnings.warn( "This method of XMLParser is deprecated. Define doctype() " "method on the TreeBuilder target.", @@ -1677,24 +1603,15 @@ # sentinel, if doctype is redefined in a subclass __doctype = doctype - ## - # Feeds data to the parser. - # - # @param data Encoded data. - def feed(self, data): + """Feed encoded data to parser.""" try: self.parser.Parse(data, 0) except self._error as v: self._raiseerror(v) - ## - # Finishes feeding data to the parser. - # - # @return An element structure. - # @defreturn Element - def close(self): + """Finish feeding data to parser and return element structure.""" try: self.parser.Parse("", 1) # end of data except self._error as v: @@ -1721,7 +1638,9 @@ # Overwrite 'ElementTree.parse' and 'iterparse' to use the C XMLParser class ElementTree(ElementTree): + __doc__ = ElementTree.__doc__ def parse(self, source, parser=None): + __doc__ = ElementTree.parse.__doc__ close_source = False if not hasattr(source, 'read'): source = open(source, 'rb') @@ -1743,25 +1662,14 @@ source.close() class iterparse: - """Parses an XML section into an element tree incrementally. - - Reports what?s going on to the user. 'source' is a filename or file - object containing XML data. 'events' is a list of events to report back. - The supported events are the strings "start", "end", "start-ns" and - "end-ns" (the "ns" events are used to get detailed namespace - information). If 'events' is omitted, only "end" events are reported. - 'parser' is an optional parser instance. If not given, the standard - XMLParser parser is used. Returns an iterator providing - (event, elem) pairs. - """ - + __doc__ = iterparse.__doc__ root = None - def __init__(self, file, events=None, parser=None): + def __init__(self, source, events=None, parser=None): self._close_file = False - if not hasattr(file, 'read'): - file = open(file, 'rb') + if not hasattr(source, 'read'): + source = open(source, 'rb') self._close_file = True - self._file = file + self._file = source self._events = [] self._index = 0 self._error = None diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -677,6 +677,7 @@ Erno Kuusela Ross Lagerwall Cameron Laird +David Lam Thomas Lamb Jean-Baptiste "Jiba" Lamy Ronan Lamy -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 20:25:33 2013 From: python-checkins at python.org (brett.cannon) Date: Sat, 9 Mar 2013 20:25:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Touch_up_the_P?= =?utf-8?q?ython_2_to_3_porting_guide?= Message-ID: <3ZNbC153DjzMFN@mail.python.org> http://hg.python.org/cpython/rev/e671a81e5966 changeset: 82572:e671a81e5966 branch: 3.3 parent: 82568:bfc159f8e4b4 user: Brett Cannon date: Sat Mar 09 14:22:35 2013 -0500 summary: Touch up the Python 2 to 3 porting guide files: Doc/howto/pyporting.rst | 61 +++++++++++++++++++++------- Misc/NEWS | 2 + 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -21,21 +21,21 @@ Choosing a Strategy =================== -When a project makes the decision that it's time to support both Python 2 & 3, +When a project chooses to support both Python 2 & 3, a decision needs to be made as to how to go about accomplishing that goal. The chosen strategy will depend on how large the project's existing -codebase is and how much divergence you want from your Python 2 codebase from -your Python 3 one (e.g., starting a new version with Python 3). - -If your project is brand-new or does not have a large codebase, then you may -want to consider writing/porting :ref:`all of your code for Python 3 -and use 3to2 ` to port your code for Python 2. +codebase is and how much divergence you want from your current Python 2 codebase +(e.g., changing your code to work simultaneously with Python 2 and 3). If you would prefer to maintain a codebase which is semantically **and** syntactically compatible with Python 2 & 3 simultaneously, you can write :ref:`use_same_source`. While this tends to lead to somewhat non-idiomatic code, it does mean you keep a rapid development process for you, the developer. +If your project is brand-new or does not have a large codebase, then you may +want to consider writing/porting :ref:`all of your code for Python 3 +and use 3to2 ` to port your code for Python 2. + Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can @@ -55,10 +55,10 @@ consider. One is make sure you have a robust test suite. You need to make sure everything -continues to work, just like when you support a new minor version of Python. -This means making sure your test suite is thorough and is ported properly -between Python 2 & 3. You will also most likely want to use something like tox_ -to automate testing between both a Python 2 and Python 3 VM. +continues to work, just like when you support a new minor/feature release of +Python. This means making sure your test suite is thorough and is ported +properly between Python 2 & 3. You will also most likely want to use something +like tox_ to automate testing between both a Python 2 and Python 3 interpreter. Two, once your project has Python 3 support, make sure to add the proper classifier on the Cheeseshop_ (PyPI_). To have your project listed as Python 3 @@ -98,7 +98,8 @@ Four, read all the approaches. Just because some bit of advice applies to one approach more than another doesn't mean that some advice doesn't apply to other -strategies. +strategies. This is especially true of whether you decide to use 2to3 or be +source-compatible; tips for one approach almost always apply to the other. Five, drop support for older Python versions if possible. `Python 2.5`_ introduced a lot of useful syntax and libraries which have become idiomatic @@ -108,6 +109,14 @@ of Python which you believe can be your minimum support version and work from there. +Six, target the newest version of Python 3 that you can. Beyond just the usual +bugfixes, compatibility has continued to improve between Python 2 and 3 as time +has passed. This is especially true for Python 3.3 where the ``u`` prefix for +strings is allowed, making source-compatible Python code easier. + +Seven, make sure to look at the `Other Resources`_ for tips from other people +which may help you out. + .. _tox: http://codespeak.net/tox/ .. _Cheeseshop: @@ -169,8 +178,8 @@ prefer this approach compared to using :ref:`use_same_source` or simply keeping a separate Python 3 codebase. -Below are the typical steps taken by a project which uses a 2to3-based approach -to supporting Python 2 & 3. +Below are the typical steps taken by a project which tries to support +Python 2 & 3 while keeping the code directly executable by Python 2. Support Python 2.7 @@ -215,7 +224,9 @@ you use this future statement or not, you **must** make sure you know exactly which Python 2 strings you want to be bytes, and which are to be strings. This means you should, **at minimum** mark all strings that are meant to be text -strings with a ``u`` prefix if you do not use this future statement. +strings with a ``u`` prefix if you do not use this future statement. Python 3.3 +allows strings to continue to have the ``u`` prefix (it's a no-op in that case) +to make it easier for code to be source-compatible between Python 2 & 3. Bytes literals @@ -226,6 +237,15 @@ what is and is not a Python 3 string. When you run 2to3 on code, all Python 2 strings become Python 3 strings **unless** they are prefixed with ``b``. +This point cannot be stressed enough: make sure you know what all of your string +literals in Python 2 are meant to become in Python 3. Any string literal that +should be treated as bytes should have the ``b`` prefix. Any string literal +that should be Unicode/text in Python 2 should either have the ``u`` literal +(supported, but ignored, in Python 3.3 and later) or you should have +``from __future__ import unicode_literals`` at the top of the file. But the key +point is you should know how Python 3 will treat everyone one of your string +literals and you should mark them as appropriate. + There are some differences between byte literals in Python 2 and those in Python 3 thanks to the bytes type just being an alias to ``str`` in Python 2. Probably the biggest "gotcha" is that indexing results in different values. In @@ -264,6 +284,16 @@ than Python 2.5, use the __future__ statement. +Mark all Unicode strings with a ``u`` prefix +''''''''''''''''''''''''''''''''''''''''''''' + +While Python 2.6 has a ``__future__`` statement to automatically cause Python 2 +to treat all string literals as Unicode, Python 2.5 does not have that shortcut. +This means you should go through and mark all string literals with a ``u`` +prefix to turn them explicitly into Unicode strings where appropriate. That +leaves all unmarked string literals to be considered byte literals in Python 3. + + Handle Common "Gotchas" ----------------------- @@ -708,6 +738,7 @@ * http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ * http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide/ * http://wiki.python.org/moin/PortingPythonToPy3k +* https://wiki.ubuntu.com/Python/3 If you feel there is something missing from this document that should be added, please email the python-porting_ mailing list. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1110,6 +1110,8 @@ Documentation ------------- +- Touched up the Python 2 to 3 porting guide. + - Issue #14674: Add a discussion of the `json` module's standard compliance. Patch by Chris Rebert. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 20:25:35 2013 From: python-checkins at python.org (brett.cannon) Date: Sat, 9 Mar 2013 20:25:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZNbC31zffzNwJ@mail.python.org> http://hg.python.org/cpython/rev/f521fddc5092 changeset: 82573:f521fddc5092 parent: 82571:f27d7c1eac4d parent: 82572:e671a81e5966 user: Brett Cannon date: Sat Mar 09 14:25:08 2013 -0500 summary: merge files: Doc/howto/pyporting.rst | 61 +++++++++++++++++++++------- Misc/NEWS | 2 + 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -21,21 +21,21 @@ Choosing a Strategy =================== -When a project makes the decision that it's time to support both Python 2 & 3, +When a project chooses to support both Python 2 & 3, a decision needs to be made as to how to go about accomplishing that goal. The chosen strategy will depend on how large the project's existing -codebase is and how much divergence you want from your Python 2 codebase from -your Python 3 one (e.g., starting a new version with Python 3). - -If your project is brand-new or does not have a large codebase, then you may -want to consider writing/porting :ref:`all of your code for Python 3 -and use 3to2 ` to port your code for Python 2. +codebase is and how much divergence you want from your current Python 2 codebase +(e.g., changing your code to work simultaneously with Python 2 and 3). If you would prefer to maintain a codebase which is semantically **and** syntactically compatible with Python 2 & 3 simultaneously, you can write :ref:`use_same_source`. While this tends to lead to somewhat non-idiomatic code, it does mean you keep a rapid development process for you, the developer. +If your project is brand-new or does not have a large codebase, then you may +want to consider writing/porting :ref:`all of your code for Python 3 +and use 3to2 ` to port your code for Python 2. + Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can @@ -55,10 +55,10 @@ consider. One is make sure you have a robust test suite. You need to make sure everything -continues to work, just like when you support a new minor version of Python. -This means making sure your test suite is thorough and is ported properly -between Python 2 & 3. You will also most likely want to use something like tox_ -to automate testing between both a Python 2 and Python 3 VM. +continues to work, just like when you support a new minor/feature release of +Python. This means making sure your test suite is thorough and is ported +properly between Python 2 & 3. You will also most likely want to use something +like tox_ to automate testing between both a Python 2 and Python 3 interpreter. Two, once your project has Python 3 support, make sure to add the proper classifier on the Cheeseshop_ (PyPI_). To have your project listed as Python 3 @@ -98,7 +98,8 @@ Four, read all the approaches. Just because some bit of advice applies to one approach more than another doesn't mean that some advice doesn't apply to other -strategies. +strategies. This is especially true of whether you decide to use 2to3 or be +source-compatible; tips for one approach almost always apply to the other. Five, drop support for older Python versions if possible. `Python 2.5`_ introduced a lot of useful syntax and libraries which have become idiomatic @@ -108,6 +109,14 @@ of Python which you believe can be your minimum support version and work from there. +Six, target the newest version of Python 3 that you can. Beyond just the usual +bugfixes, compatibility has continued to improve between Python 2 and 3 as time +has passed. This is especially true for Python 3.3 where the ``u`` prefix for +strings is allowed, making source-compatible Python code easier. + +Seven, make sure to look at the `Other Resources`_ for tips from other people +which may help you out. + .. _tox: http://codespeak.net/tox/ .. _Cheeseshop: @@ -169,8 +178,8 @@ prefer this approach compared to using :ref:`use_same_source` or simply keeping a separate Python 3 codebase. -Below are the typical steps taken by a project which uses a 2to3-based approach -to supporting Python 2 & 3. +Below are the typical steps taken by a project which tries to support +Python 2 & 3 while keeping the code directly executable by Python 2. Support Python 2.7 @@ -215,7 +224,9 @@ you use this future statement or not, you **must** make sure you know exactly which Python 2 strings you want to be bytes, and which are to be strings. This means you should, **at minimum** mark all strings that are meant to be text -strings with a ``u`` prefix if you do not use this future statement. +strings with a ``u`` prefix if you do not use this future statement. Python 3.3 +allows strings to continue to have the ``u`` prefix (it's a no-op in that case) +to make it easier for code to be source-compatible between Python 2 & 3. Bytes literals @@ -226,6 +237,15 @@ what is and is not a Python 3 string. When you run 2to3 on code, all Python 2 strings become Python 3 strings **unless** they are prefixed with ``b``. +This point cannot be stressed enough: make sure you know what all of your string +literals in Python 2 are meant to become in Python 3. Any string literal that +should be treated as bytes should have the ``b`` prefix. Any string literal +that should be Unicode/text in Python 2 should either have the ``u`` literal +(supported, but ignored, in Python 3.3 and later) or you should have +``from __future__ import unicode_literals`` at the top of the file. But the key +point is you should know how Python 3 will treat everyone one of your string +literals and you should mark them as appropriate. + There are some differences between byte literals in Python 2 and those in Python 3 thanks to the bytes type just being an alias to ``str`` in Python 2. Probably the biggest "gotcha" is that indexing results in different values. In @@ -264,6 +284,16 @@ than Python 2.5, use the __future__ statement. +Mark all Unicode strings with a ``u`` prefix +''''''''''''''''''''''''''''''''''''''''''''' + +While Python 2.6 has a ``__future__`` statement to automatically cause Python 2 +to treat all string literals as Unicode, Python 2.5 does not have that shortcut. +This means you should go through and mark all string literals with a ``u`` +prefix to turn them explicitly into Unicode strings where appropriate. That +leaves all unmarked string literals to be considered byte literals in Python 3. + + Handle Common "Gotchas" ----------------------- @@ -708,6 +738,7 @@ * http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ * http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide/ * http://wiki.python.org/moin/PortingPythonToPy3k +* https://wiki.ubuntu.com/Python/3 If you feel there is something missing from this document that should be added, please email the python-porting_ mailing list. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1409,6 +1409,8 @@ Documentation ------------- +- Touched up the Python 2 to 3 porting guide. + - Issue #14674: Add a discussion of the `json` module's standard compliance. Patch by Chris Rebert. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 21:21:53 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 9 Mar 2013 21:21:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExOTYzOiBhdm9p?= =?utf-8?q?d_printing_messages_in_test=5Fparser=2E__Initial_patch_by_?= =?utf-8?q?=C3=89ric_Araujo=2E?= Message-ID: <3ZNcS14bT2zQwc@mail.python.org> http://hg.python.org/cpython/rev/9ee8c00f7e63 changeset: 82574:9ee8c00f7e63 branch: 2.7 parent: 82570:eece32440a52 user: Ezio Melotti date: Sat Mar 09 22:17:33 2013 +0200 summary: #11963: avoid printing messages in test_parser. Initial patch by ?ric Araujo. files: Lib/test/test_parser.py | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -3,6 +3,7 @@ import sys import struct from test import test_support as support +from test.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, @@ -579,7 +580,7 @@ class ParserStackLimitTestCase(unittest.TestCase): - """try to push the parser to/over it's limits. + """try to push the parser to/over its limits. see http://bugs.python.org/issue1881 for a discussion """ def _nested_expression(self, level): @@ -592,8 +593,10 @@ def test_trigger_memory_error(self): e = self._nested_expression(100) - print >>sys.stderr, "Expecting 's_push: parser stack overflow' in next line" - self.assertRaises(MemoryError, parser.expr, e) + rc, out, err = assert_python_failure('-c', e) + # parsing the expression will result in an error message + # followed by a MemoryError (see #11963) + self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 21:21:55 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 9 Mar 2013 21:21:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzExOTYzOiBhdm9p?= =?utf-8?q?d_printing_messages_in_test=5Fparser=2E__Initial_patch_by_?= =?utf-8?q?=C3=89ric_Araujo=2E?= Message-ID: <3ZNcS30YHKzRbP@mail.python.org> http://hg.python.org/cpython/rev/10a82140f36d changeset: 82575:10a82140f36d branch: 3.2 parent: 82567:0acd9408b6f1 user: Ezio Melotti date: Sat Mar 09 22:17:33 2013 +0200 summary: #11963: avoid printing messages in test_parser. Initial patch by ?ric Araujo. files: Lib/test/test_parser.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -4,6 +4,7 @@ import operator import struct from test import support +from test.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, @@ -607,10 +608,10 @@ def test_trigger_memory_error(self): e = self._nested_expression(100) - print("Expecting 's_push: parser stack overflow' in next line", - file=sys.stderr) - sys.stderr.flush() - self.assertRaises(MemoryError, parser.expr, e) + rc, out, err = assert_python_failure('-c', e) + # parsing the expression will result in an error message + # followed by a MemoryError (see #11963) + self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 21:21:56 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 9 Mar 2013 21:21:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2311963=3A_merge_with_3=2E2=2E?= Message-ID: <3ZNcS43Q85zRnJ@mail.python.org> http://hg.python.org/cpython/rev/185c923f21ec changeset: 82576:185c923f21ec branch: 3.3 parent: 82572:e671a81e5966 parent: 82575:10a82140f36d user: Ezio Melotti date: Sat Mar 09 22:20:23 2013 +0200 summary: #11963: merge with 3.2. files: Lib/test/test_parser.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -4,6 +4,7 @@ import operator import struct from test import support +from test.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, @@ -611,10 +612,10 @@ def test_trigger_memory_error(self): e = self._nested_expression(100) - print("Expecting 's_push: parser stack overflow' in next line", - file=sys.stderr) - sys.stderr.flush() - self.assertRaises(MemoryError, parser.expr, e) + rc, out, err = assert_python_failure('-c', e) + # parsing the expression will result in an error message + # followed by a MemoryError (see #11963) + self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 9 21:21:57 2013 From: python-checkins at python.org (ezio.melotti) Date: Sat, 9 Mar 2013 21:21:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExOTYzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZNcS560fDzQxL@mail.python.org> http://hg.python.org/cpython/rev/acf6ffc57fcf changeset: 82577:acf6ffc57fcf parent: 82573:f521fddc5092 parent: 82576:185c923f21ec user: Ezio Melotti date: Sat Mar 09 22:21:32 2013 +0200 summary: #11963: merge with 3.3. files: Lib/test/test_parser.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -4,6 +4,7 @@ import operator import struct from test import support +from test.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, @@ -611,10 +612,10 @@ def test_trigger_memory_error(self): e = self._nested_expression(100) - print("Expecting 's_push: parser stack overflow' in next line", - file=sys.stderr) - sys.stderr.flush() - self.assertRaises(MemoryError, parser.expr, e) + rc, out, err = assert_python_failure('-c', e) + # parsing the expression will result in an error message + # followed by a MemoryError (see #11963) + self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 02:30:12 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 02:30:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExOTYzOiBmaXgg?= =?utf-8?q?Windows_buildbots=2E?= Message-ID: <3ZNlHm6Y99zQlF@mail.python.org> http://hg.python.org/cpython/rev/61ec83956ba6 changeset: 82578:61ec83956ba6 branch: 2.7 parent: 82574:9ee8c00f7e63 user: Ezio Melotti date: Sun Mar 10 03:25:45 2013 +0200 summary: #11963: fix Windows buildbots. files: Lib/test/test_parser.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -596,7 +596,8 @@ rc, out, err = assert_python_failure('-c', e) # parsing the expression will result in an error message # followed by a MemoryError (see #11963) - self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') + self.assertIn(b's_push: parser stack overflow', err) + self.assertIn(b'MemoryError', err) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 02:30:14 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 02:30:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzExOTYzOiBmaXgg?= =?utf-8?q?Windows_buildbots=2E?= Message-ID: <3ZNlHp243fzQlF@mail.python.org> http://hg.python.org/cpython/rev/64b87578c071 changeset: 82579:64b87578c071 branch: 3.2 parent: 82575:10a82140f36d user: Ezio Melotti date: Sun Mar 10 03:25:45 2013 +0200 summary: #11963: fix Windows buildbots. files: Lib/test/test_parser.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -611,7 +611,8 @@ rc, out, err = assert_python_failure('-c', e) # parsing the expression will result in an error message # followed by a MemoryError (see #11963) - self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') + self.assertIn(b's_push: parser stack overflow', err) + self.assertIn(b'MemoryError', err) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 02:30:15 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 02:30:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2311963=3A_merge_with_3=2E2=2E?= Message-ID: <3ZNlHq4pHmzRYn@mail.python.org> http://hg.python.org/cpython/rev/f683ca2b30e3 changeset: 82580:f683ca2b30e3 branch: 3.3 parent: 82576:185c923f21ec parent: 82579:64b87578c071 user: Ezio Melotti date: Sun Mar 10 03:27:26 2013 +0200 summary: #11963: merge with 3.2. files: Lib/test/test_parser.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -615,7 +615,8 @@ rc, out, err = assert_python_failure('-c', e) # parsing the expression will result in an error message # followed by a MemoryError (see #11963) - self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') + self.assertIn(b's_push: parser stack overflow', err) + self.assertIn(b'MemoryError', err) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 02:30:17 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 02:30:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExOTYzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZNlHs0RDVzRhN@mail.python.org> http://hg.python.org/cpython/rev/65147d2422dc changeset: 82581:65147d2422dc parent: 82577:acf6ffc57fcf parent: 82580:f683ca2b30e3 user: Ezio Melotti date: Sun Mar 10 03:29:55 2013 +0200 summary: #11963: merge with 3.3. files: Lib/test/test_parser.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -615,7 +615,8 @@ rc, out, err = assert_python_failure('-c', e) # parsing the expression will result in an error message # followed by a MemoryError (see #11963) - self.assertEqual(err, b's_push: parser stack overflow\nMemoryError') + self.assertIn(b's_push: parser stack overflow', err) + self.assertIn(b'MemoryError', err) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 03:28:43 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 03:28:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE0NDg5OiBmaXgg?= =?utf-8?q?wrong_link=2E?= Message-ID: <3ZNmbH2z6RzR2M@mail.python.org> http://hg.python.org/cpython/rev/aea3167355fc changeset: 82582:aea3167355fc branch: 2.7 parent: 82578:61ec83956ba6 user: Ezio Melotti date: Sun Mar 10 04:28:28 2013 +0200 summary: #14489: fix wrong link. files: Doc/library/functions.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -19,7 +19,7 @@ :func:`bytearray` :func:`float` :func:`list` :func:`raw_input` :func:`unichr` :func:`callable` :func:`format` :func:`locals` :func:`reduce` :func:`unicode` :func:`chr` |func-frozenset|_ :func:`long` :func:`reload` :func:`vars` -:func:`classmethod` :func:`getattr` :func:`map` :func:`repr` :func:`xrange` +:func:`classmethod` :func:`getattr` :func:`map` |func-repr|_ :func:`xrange` :func:`cmp` :func:`globals` :func:`max` :func:`reversed` :func:`zip` :func:`compile` :func:`hasattr` |func-memoryview|_ :func:`round` :func:`__import__` :func:`complex` :func:`hash` :func:`min` |func-set|_ :func:`apply` @@ -34,6 +34,7 @@ .. |func-dict| replace:: ``dict()`` .. |func-frozenset| replace:: ``frozenset()`` .. |func-memoryview| replace:: ``memoryview()`` +.. |func-repr| replace:: ``repr()`` .. |func-set| replace:: ``set()`` @@ -1179,6 +1180,7 @@ continue to use the old class definition. The same is true for derived classes. +.. _func-repr: .. function:: repr(object) Return a string containing a printable representation of an object. This is -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Mar 10 05:58:08 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 10 Mar 2013 05:58:08 +0100 Subject: [Python-checkins] Daily reference leaks (65147d2422dc): sum=0 Message-ID: results for 65147d2422dc on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogGrvz6O', '-x'] From python-checkins at python.org Sun Mar 10 17:37:39 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:37:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3MzUx?= =?utf-8?q?=3A_Modernize_the_pure_Python_property=28=29_example=2E?= Message-ID: <3ZP7Qq0kntzRf4@mail.python.org> http://hg.python.org/cpython/rev/513c4aaf70d7 changeset: 82583:513c4aaf70d7 branch: 2.7 user: Raymond Hettinger date: Sun Mar 10 09:36:52 2013 -0700 summary: Issue #17351: Modernize the pure Python property() example. files: Doc/howto/descriptor.rst | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -218,25 +218,36 @@ self.fget = fget self.fset = fset self.fdel = fdel + if doc is None and fget is not None: + doc = fget.__doc__ self.__doc__ = doc def __get__(self, obj, objtype=None): if obj is None: return self if self.fget is None: - raise AttributeError, "unreadable attribute" + raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self, obj, value): if self.fset is None: - raise AttributeError, "can't set attribute" + raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: - raise AttributeError, "can't delete attribute" + raise AttributeError("can't delete attribute") self.fdel(obj) + def getter(self, fget): + return type(self)(fget, self.fset, self.fdel, self.__doc__) + + def setter(self, fset): + return type(self)(self.fget, fset, self.fdel, self.__doc__) + + def deleter(self, fdel): + return type(self)(self.fget, self.fset, fdel, self.__doc__) + The :func:`property` builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 17:42:43 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:42:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MzUx?= =?utf-8?q?=3A_Modernize_the_pure_Python_property=28=29_example=2E?= Message-ID: <3ZP7Xg35gPzRvh@mail.python.org> http://hg.python.org/cpython/rev/bb7e01b5d362 changeset: 82584:bb7e01b5d362 branch: 3.3 parent: 82580:f683ca2b30e3 user: Raymond Hettinger date: Sun Mar 10 09:41:18 2013 -0700 summary: Issue #17351: Modernize the pure Python property() example. files: Doc/howto/descriptor.rst | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -210,25 +210,36 @@ self.fget = fget self.fset = fset self.fdel = fdel + if doc is None and fget is not None: + doc = fget.__doc__ self.__doc__ = doc def __get__(self, obj, objtype=None): if obj is None: return self if self.fget is None: - raise AttributeError, "unreadable attribute" + raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self, obj, value): if self.fset is None: - raise AttributeError, "can't set attribute" + raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: - raise AttributeError, "can't delete attribute" + raise AttributeError("can't delete attribute") self.fdel(obj) + def getter(self, fget): + return type(self)(fget, self.fset, self.fdel, self.__doc__) + + def setter(self, fset): + return type(self)(self.fget, fset, self.fdel, self.__doc__) + + def deleter(self, fdel): + return type(self)(self.fget, self.fset, fdel, self.__doc__) + The :func:`property` builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 17:42:44 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:42:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZP7Xh68cQzRxV@mail.python.org> http://hg.python.org/cpython/rev/115c43340025 changeset: 82585:115c43340025 parent: 82581:65147d2422dc parent: 82584:bb7e01b5d362 user: Raymond Hettinger date: Sun Mar 10 09:42:22 2013 -0700 summary: merge files: Doc/howto/descriptor.rst | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -210,25 +210,36 @@ self.fget = fget self.fset = fset self.fdel = fdel + if doc is None and fget is not None: + doc = fget.__doc__ self.__doc__ = doc def __get__(self, obj, objtype=None): if obj is None: return self if self.fget is None: - raise AttributeError, "unreadable attribute" + raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self, obj, value): if self.fset is None: - raise AttributeError, "can't set attribute" + raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: - raise AttributeError, "can't delete attribute" + raise AttributeError("can't delete attribute") self.fdel(obj) + def getter(self, fget): + return type(self)(fget, self.fset, self.fdel, self.__doc__) + + def setter(self, fset): + return type(self)(self.fget, fset, self.fdel, self.__doc__) + + def deleter(self, fdel): + return type(self)(self.fget, self.fset, fdel, self.__doc__) + The :func:`property` builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 17:49:20 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:49:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Classmethod_ex?= =?utf-8?q?ample_needs_to_inherit_from_object?= Message-ID: <3ZP7hJ4qxSzRq7@mail.python.org> http://hg.python.org/cpython/rev/3c39df4b886e changeset: 82586:3c39df4b886e branch: 2.7 parent: 82583:513c4aaf70d7 user: Raymond Hettinger date: Sun Mar 10 09:49:08 2013 -0700 summary: Classmethod example needs to inherit from object files: Doc/howto/descriptor.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -409,7 +409,7 @@ :func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure Python equivalent is:: - class Dict: + class Dict(object): . . . def fromkeys(klass, iterable, value=None): "Emulate dict_fromkeys() in Objects/dictobject.c" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 17:51:50 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:51:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Inherit_from_o?= =?utf-8?q?bject=28=29_for_consistency?= Message-ID: <3ZP7lB1lFZzRq7@mail.python.org> http://hg.python.org/cpython/rev/5eca56b68840 changeset: 82587:5eca56b68840 branch: 3.3 parent: 82584:bb7e01b5d362 user: Raymond Hettinger date: Sun Mar 10 09:50:37 2013 -0700 summary: Inherit from object() for consistency files: Doc/howto/descriptor.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -401,7 +401,7 @@ :func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure Python equivalent is:: - class Dict: + class Dict(object): . . . def fromkeys(klass, iterable, value=None): "Emulate dict_fromkeys() in Objects/dictobject.c" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 17:51:52 2013 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 10 Mar 2013 17:51:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZP7lD0HcSzRq7@mail.python.org> http://hg.python.org/cpython/rev/60cb72c7fd75 changeset: 82588:60cb72c7fd75 parent: 82585:115c43340025 parent: 82587:5eca56b68840 user: Raymond Hettinger date: Sun Mar 10 09:51:37 2013 -0700 summary: merge files: Doc/howto/descriptor.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -401,7 +401,7 @@ :func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure Python equivalent is:: - class Dict: + class Dict(object): . . . def fromkeys(klass, iterable, value=None): "Emulate dict_fromkeys() in Objects/dictobject.c" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 19:33:12 2013 From: python-checkins at python.org (daniel.holth) Date: Sun, 10 Mar 2013 19:33:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_wheel_clarifications?= Message-ID: <3ZPB083NjNzRtH@mail.python.org> http://hg.python.org/peps/rev/5bfc679af551 changeset: 4788:5bfc679af551 user: Daniel Holth date: Sun Mar 10 13:33:33 2013 -0400 summary: wheel clarifications files: pep-0427.txt | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/pep-0427.txt b/pep-0427.txt --- a/pep-0427.txt +++ b/pep-0427.txt @@ -96,6 +96,9 @@ point to the correct interpreter. Unix installers may need to add the +x bit to these files if the archive was created on Windows. + The ``b'#!pythonw'`` convention is allowed. ``b'#!pythonw'`` indicates + a GUI script instead of a console script. + Generate script wrappers. In wheel, scripts packaged on Unix systems will certainly not have accompanying .exe wrappers. Windows installers may want to add them @@ -288,6 +291,8 @@ { "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" } +(The hash value is the same format used in RECORD.) + If RECORD.p7s is used, it must contain a detached S/MIME format signature of RECORD. @@ -361,6 +366,19 @@ Signed packages are only a basic building block in a secure package update system. Wheel only provides the building block. +What's the deal with "purelib" vs. "platlib"? + Wheel preserves the historic "purelib" vs. "platlib" distinction + even though both map to the same install location in any system the + author could find. + + For example, a wheel with "Root-Is-Purelib: false" with all its files + in ``{name}-{version}.data/purelib`` is equivalent to a wheel with + "Root-Is-Purelib: true" with those same files in the root, and it + is legal to have files in both the "purelib" and "platlib" categories. + + In practice a wheel should have only one of "purelib" or "platlib" + depending on whether it is pure Python or not and those files should + be at the root. References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Mar 10 19:33:13 2013 From: python-checkins at python.org (daniel.holth) Date: Sun, 10 Mar 2013 19:33:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_update_e-mail?= Message-ID: <3ZPB0968HXzRy0@mail.python.org> http://hg.python.org/peps/rev/4dbfd9610fce changeset: 4789:4dbfd9610fce user: Daniel Holth date: Sun Mar 10 13:33:55 2013 -0400 summary: update e-mail files: pep-0425.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0425.txt b/pep-0425.txt --- a/pep-0425.txt +++ b/pep-0425.txt @@ -2,7 +2,7 @@ Title: Compatibility Tags for Built Distributions Version: $Revision$ Last-Modified: 07-Aug-2012 -Author: Daniel Holth +Author: Daniel Holth Status: Accepted Type: Standards Track -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Mar 10 19:33:15 2013 From: python-checkins at python.org (daniel.holth) Date: Sun, 10 Mar 2013 19:33:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_426=3A_extensions_are_0?= =?utf-8?b?Li4x?= Message-ID: <3ZPB0C1k8jzS35@mail.python.org> http://hg.python.org/peps/rev/4fc7b84ee3e7 changeset: 4790:4fc7b84ee3e7 user: Daniel Holth date: Sun Mar 10 13:34:21 2013 -0400 summary: PEP 426: extensions are 0..1 files: pep-0426.txt | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -2,7 +2,7 @@ Title: Metadata for Python Software Packages 2.0 Version: $Revision$ Last-Modified: $Date$ -Author: Daniel Holth , +Author: Daniel Holth , Donald Stufft , Nick Coghlan BDFL-Delegate: Nick Coghlan @@ -527,13 +527,22 @@ An ASCII string, not containing whitespace or the ``/`` character, that indicates the presence of extended metadata. The additional fields defined by the extension are then prefixed with the name of the extension -and the ``/`` character. +and the ``/`` character. The additional fields are optional (0..1). For example:: Extension: Chili Chili/Type: Poblano Chili/Heat: Mild + Chili/json: { + "type" : "Poblano", + "heat" : "Mild" } + +The special ``{extension name}/json`` permits embedded JSON. It may be +parsed automatically by a future tool. + +Values in extension fields must still respect the general formatting +requirements for metadata headers. To avoid name conflicts, it is recommended that distribution names be used to identify metadata extensions. This practice will also make it easier to @@ -543,9 +552,6 @@ ``Extension: Chili`` field may appear before or after the corresponding extension fields ``Chili/Type:`` etc. -Values in extension fields must still respect the general formatting -requirements for metadata headers. - A bare ``Extension: Name`` entry with no corresponding extension fields is permitted. It may, for example, indicate the expected presence of an additional metadata file rather than the presence of extension fields. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Mar 10 19:33:16 2013 From: python-checkins at python.org (daniel.holth) Date: Sun, 10 Mar 2013 19:33:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_426=3A_optional_features_?= =?utf-8?q?or_=22extra_dependencies=22?= Message-ID: <3ZPB0D45kdzS1Q@mail.python.org> http://hg.python.org/peps/rev/82a2053a7bff changeset: 4791:82a2053a7bff user: Daniel Holth date: Sun Mar 10 13:54:12 2013 -0400 summary: PEP 426: optional features or "extra dependencies" files: pep-0426.txt | 21 +++++++++++++-------- 1 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -1199,14 +1199,15 @@ ================= Distributions may use the ``Provides-Extra`` field to declare additional -features that they provide. Environment markers may then be used to indicate +features provided through "extra" dependencies, usually corresponding to a +``try: import x ...`` block. Environment markers may be used to indicate that particular dependencies are needed only when a particular optional feature has been requested. -Other distributions then require an optional feature by placing it -inside square brackets after the distribution name when declaring the -dependency. Multiple features can be requisted by separating them with a -comma within the brackets. +Other distributions require the feature by placing it inside +square brackets after the distribution name when declaring the +dependency. Multiple features can be requisted by separating them with +a comma within the brackets. The full set of dependency requirements is then the union of the sets created by first evaluating the `Requires-Dist` fields with `extra` @@ -1220,9 +1221,13 @@ Setup-Requires-Dist: beaglevote[test, doc] -> requires beaglevote, sphinx, nose at setup time -It is legal to specify `Provides-Extra` without referencing it in any -`Requires-Dist`. It is an error to request a feature name that has -not been declared with `Provides-Extra`. +It is an error to request a feature name that has not been declared with +`Provides-Extra` but it is legal to specify `Provides-Extra` without +referencing it in any `Requires-Dist`. + +In the example, if ``beaglevote`` grew the ability to generate PDF +without extra dependencies, it should continue to ``Provides-Extra: +pdf`` for the benefit of dependent distributions. The following feature names are implicitly defined for all distributions: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Mar 10 19:33:17 2013 From: python-checkins at python.org (daniel.holth) Date: Sun, 10 Mar 2013 19:33:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_426=3A_trailing_0=27s_pol?= =?utf-8?q?icy_for_=3D=3D?= Message-ID: <3ZPB0F6k5HzRwp@mail.python.org> http://hg.python.org/peps/rev/ae5d9b9df1a6 changeset: 4792:ae5d9b9df1a6 user: Daniel Holth date: Sun Mar 10 14:32:53 2013 -0400 summary: PEP 426: trailing 0's policy for == files: pep-0426.txt | 24 +++++++++++++----------- 1 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -601,9 +601,11 @@ .. note:: - Some hard to read version identifiers are permitted by this scheme - in order to better accommodate the wide range of versioning practices - across existing public and private Python projects. + Some hard to read version identifiers are permitted by this scheme in + order to better accommodate the wide range of versioning practices + across existing public and private Python projects, given the + constraint that the package index is not yet sophisticated enough to + allow the introduction of a simpler, backwards-incompatible scheme. Accordingly, some of the versioning practices which are technically permitted by the PEP are strongly discouraged for new projects. Where @@ -1059,17 +1061,17 @@ The ordered comparison operators ``<``, ``>``, ``<=``, ``>=`` are based on the consistent ordering defined by the standard `Version scheme`_. -The ``==`` and ``!=`` operators are based on string comparisons - in order -to match, the version being checked must start with exactly that sequence of -characters. +The ``==`` and ``!=`` operators are based on a kind of prefix comparison - +trailing ``0``s are implied when comparing numeric version parts of different +lengths. ``1.0 == 1 == 1.0.0``, and ``1.0a1 == ``1.0.0.0a1``. .. note:: - The use of ``==`` when defining dependencies for published distributions - is strongly discouraged, as it greatly complicates the deployment of - security fixes (the strict version comparison operator is intended - primarily for use when defining dependencies for particular - applications while using a shared distribution index). + The use of ``==`` when defining dependencies for published + distributions is strongly discouraged as it greatly complicates the + deployment of security fixes. The strict version comparison operator + is intended primarily for use when defining dependencies for repeatable + *deployments of applications* while using a shared distribution index. Handling of pre-releases -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Mar 10 19:56:50 2013 From: python-checkins at python.org (terry.reedy) Date: Sun, 10 Mar 2013 19:56:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?ZGV2Z3VpZGU6ICcuOjonIGRpc3BsYXlzIGFz?= =?utf-8?q?_=27=2E=3A=27=2E_Reported_in_email_by_Bob_Hanson=2E?= Message-ID: <3ZPBWQ5mWJzS35@mail.python.org> http://hg.python.org/devguide/rev/05280745b1b1 changeset: 608:05280745b1b1 user: Terry Jan Reedy date: Sun Mar 10 14:54:31 2013 -0400 summary: '.::' displays as '.:'. Reported in email by Bob Hanson. files: setup.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -137,7 +137,7 @@ More flags are available to ``configure``, but this is the minimum you should do to get a pydebug build of CPython. -Once ``configure`` is done, you can then compile CPython.:: +Once ``configure`` is done, you can then compile CPython with:: make -s -j2 -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Mar 10 19:57:31 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 19:57:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_typo_in_PyDict=5FSetDe?= =?utf-8?q?fault_docs=2E?= Message-ID: <3ZPBXC0mnYzQst@mail.python.org> http://hg.python.org/cpython/rev/c33781454880 changeset: 82589:c33781454880 user: Ezio Melotti date: Sun Mar 10 20:57:16 2013 +0200 summary: Fix typo in PyDict_SetDefault docs. files: Doc/c-api/dict.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -112,7 +112,7 @@ .. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default) - This is the same the Python-level :meth:`dict.setdefault`. If present, it + This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key is not in the dict, it is inserted with value *defaultobj* and *defaultobj* is inserted. This function evaluates the hash function of *key* only once, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Mar 10 23:37:15 2013 From: python-checkins at python.org (ezio.melotti) Date: Sun, 10 Mar 2013 23:37:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExOTYzOiByZW1v?= =?utf-8?q?ve_human_verification_from_test=5Fsubprocess=2E?= Message-ID: <3ZPHPl5C1nzSZq@mail.python.org> http://hg.python.org/cpython/rev/d25749c32bb4 changeset: 82590:d25749c32bb4 branch: 2.7 parent: 82586:3c39df4b886e user: Ezio Melotti date: Mon Mar 11 00:34:33 2013 +0200 summary: #11963: remove human verification from test_subprocess. files: Lib/test/test_subprocess.py | 48 ++++++++++++++++++------ Misc/NEWS | 2 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -150,16 +150,27 @@ self.assertEqual(p.stdin, None) def test_stdout_none(self): - # .stdout is None when not redirected - p = subprocess.Popen([sys.executable, "-c", - 'print " this bit of output is from a ' - 'test of stdout in a different ' - 'process ..."'], - stdin=subprocess.PIPE, stderr=subprocess.PIPE) - self.addCleanup(p.stdin.close) + # .stdout is None when not redirected, and the child's stdout will + # be inherited from the parent. In order to test this we run a + # subprocess in a subprocess: + # this_test + # \-- subprocess created by this test (parent) + # \-- subprocess created by the parent subprocess (child) + # The parent doesn't specify stdout, so the child will use the + # parent's stdout. This test checks that the message printed by the + # child goes to the parent stdout. The parent also checks that the + # child's stdout is None. See #11963. + code = ('import sys; from subprocess import Popen, PIPE;' + 'p = Popen([sys.executable, "-c", "print \'test_stdout_none\'"],' + ' stdin=PIPE, stderr=PIPE);' + 'p.wait(); assert p.stdout is None;') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) self.addCleanup(p.stderr.close) - p.wait() - self.assertEqual(p.stdout, None) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), 'test_stdout_none') def test_stderr_none(self): # .stderr is None when not redirected @@ -308,9 +319,22 @@ def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), '.\n'))" - rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) - self.assertEqual(rc, 2) + # To avoid printing the '.\n' on stdout, we do something similar to + # test_stdout_none (see above). The parent subprocess calls the child + # subprocess passing stdout=1, and this test uses stdout=PIPE in + # order to capture and check the output of the parent. See #11963. + code = ('import sys, subprocess; ' + 'rc = subprocess.call([sys.executable, "-c", ' + ' "import os, sys; sys.exit(os.write(sys.stdout.fileno(), ' + '\'.\\\\n\'))"], stdout=1); ' + 'assert rc == 2') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) + self.addCleanup(p.stderr.close) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out, '.\n') def test_cwd(self): tmpdir = tempfile.gettempdir() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -812,6 +812,8 @@ Tests ----- +- Issue #11963: remove human verification from test_parser and test_subprocess. + - Issue #17249: convert a test in test_capi to use unittest and reap threads. - We now run both test_email.py and test_email_renamed.py when running the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 01:58:08 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 Mar 2013 01:58:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_code_to_increment_a?= =?utf-8?q?nd_decrement_using_the_cleaner_+=3D_1_and_-=3D_1_style=2E?= Message-ID: <3ZPLXJ4jMhzRxZ@mail.python.org> http://hg.python.org/cpython/rev/28b86525ef07 changeset: 82591:28b86525ef07 parent: 82589:c33781454880 user: Raymond Hettinger date: Sun Mar 10 15:13:35 2013 -0700 summary: Update code to increment and decrement using the cleaner += 1 and -= 1 style. files: Lib/threading.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -79,7 +79,7 @@ def acquire(self, blocking=True, timeout=-1): me = get_ident() if self._owner == me: - self._count = self._count + 1 + self._count += 1 return 1 rc = self._block.acquire(blocking, timeout) if rc: @@ -261,7 +261,7 @@ break self._cond.wait(timeout) else: - self._value = self._value - 1 + self._value -= 1 rc = True self._cond.release() return rc @@ -270,7 +270,7 @@ def release(self): self._cond.acquire() - self._value = self._value + 1 + self._value += 1 self._cond.notify() self._cond.release() @@ -506,7 +506,7 @@ _counter = 0 def _newname(template="Thread-%d"): global _counter - _counter = _counter + 1 + _counter += 1 return template % _counter # Active thread administration -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 01:58:10 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 Mar 2013 01:58:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317385=3A_Fix_quad?= =?utf-8?q?ratic_behavior_in_threading=2ECondition?= Message-ID: <3ZPLXL0jVYzS7C@mail.python.org> http://hg.python.org/cpython/rev/0f86b51f8f8b changeset: 82592:0f86b51f8f8b user: Raymond Hettinger date: Sun Mar 10 17:57:28 2013 -0700 summary: Issue #17385: Fix quadratic behavior in threading.Condition files: Lib/threading.py | 10 ++++++++-- Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -10,6 +10,12 @@ from time import time as _time from traceback import format_exc as _format_exc from _weakrefset import WeakSet +try: + from _itertools import islice as _slice + from _collections import deque as _deque +except ImportError: + from itertools import islice as _islice + from collections import deque as _deque # Note regarding PEP 8 compliant names # This threading model was originally inspired by Java, and inherited @@ -146,7 +152,7 @@ self._is_owned = lock._is_owned except AttributeError: pass - self._waiters = [] + self._waiters = _deque() def __enter__(self): return self._lock.__enter__() @@ -217,7 +223,7 @@ if not self._is_owned(): raise RuntimeError("cannot notify on un-acquired lock") __waiters = self._waiters - waiters = __waiters[:n] + waiters = _deque(_islice(__waiters, n)) if not waiters: return for waiter in waiters: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -277,6 +277,9 @@ Library ------- +_ Issue #17385: Fix quadratic behavior in threading.Condition. The FIFO + queue now uses a deque instead of a list. + - Issue #14645: The email generator classes now produce output using the specified linesep throughout. Previously if the prolog, epilog, or body were stored with a different linesep, that linesep was used. This -- Repository URL: http://hg.python.org/cpython From ezio.melotti at gmail.com Mon Mar 11 02:14:37 2013 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Mon, 11 Mar 2013 03:14:37 +0200 Subject: [Python-checkins] cpython: Issue #17385: Fix quadratic behavior in threading.Condition In-Reply-To: <3ZPLXL0jVYzS7C@mail.python.org> References: <3ZPLXL0jVYzS7C@mail.python.org> Message-ID: Hi, On Mon, Mar 11, 2013 at 2:58 AM, raymond.hettinger wrote: > http://hg.python.org/cpython/rev/0f86b51f8f8b > changeset: 82592:0f86b51f8f8b > user: Raymond Hettinger > date: Sun Mar 10 17:57:28 2013 -0700 > summary: > Issue #17385: Fix quadratic behavior in threading.Condition > > files: > Lib/threading.py | 10 ++++++++-- > Misc/NEWS | 3 +++ > 2 files changed, 11 insertions(+), 2 deletions(-) > > > diff --git a/Lib/threading.py b/Lib/threading.py > --- a/Lib/threading.py > +++ b/Lib/threading.py > @@ -10,6 +10,12 @@ > from time import time as _time > from traceback import format_exc as _format_exc > from _weakrefset import WeakSet > +try: > + from _itertools import islice as _slice > + from _collections import deque as _deque > +except ImportError: > + from itertools import islice as _islice > + from collections import deque as _deque > Shouldn't the one in the 'try' be _islice too? Best Regards, Ezio Melotti From python-checkins at python.org Mon Mar 11 02:21:25 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 02:21:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExOTYzOiBmaXgg?= =?utf-8?q?Windows_buildbots=2E?= Message-ID: <3ZPM391JbSzRvs@mail.python.org> http://hg.python.org/cpython/rev/3e14aafeca04 changeset: 82593:3e14aafeca04 branch: 2.7 parent: 82590:d25749c32bb4 user: Ezio Melotti date: Mon Mar 11 03:21:08 2013 +0200 summary: #11963: fix Windows buildbots. files: Lib/test/test_subprocess.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -319,22 +319,22 @@ def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - # To avoid printing the '.\n' on stdout, we do something similar to + # To avoid printing the text on stdout, we do something similar to # test_stdout_none (see above). The parent subprocess calls the child # subprocess passing stdout=1, and this test uses stdout=PIPE in # order to capture and check the output of the parent. See #11963. code = ('import sys, subprocess; ' 'rc = subprocess.call([sys.executable, "-c", ' ' "import os, sys; sys.exit(os.write(sys.stdout.fileno(), ' - '\'.\\\\n\'))"], stdout=1); ' - 'assert rc == 2') + '\'test with stdout=1\'))"], stdout=1); ' + 'assert rc == 18') p = subprocess.Popen([sys.executable, "-c", code], stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.addCleanup(p.stdout.close) self.addCleanup(p.stderr.close) out, err = p.communicate() self.assertEqual(p.returncode, 0, err) - self.assertEqual(out, '.\n') + self.assertEqual(out.rstrip(), 'test with stdout=1') def test_cwd(self): tmpdir = tempfile.gettempdir() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 04:34:50 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 Mar 2013 04:34:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Improve_variable_names?= Message-ID: <3ZPQ1607qjzSXm@mail.python.org> http://hg.python.org/cpython/rev/79943dee0aca changeset: 82594:79943dee0aca parent: 82592:0f86b51f8f8b user: Raymond Hettinger date: Sun Mar 10 20:34:16 2013 -0700 summary: Improve variable names files: Lib/threading.py | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -222,14 +222,14 @@ def notify(self, n=1): if not self._is_owned(): raise RuntimeError("cannot notify on un-acquired lock") - __waiters = self._waiters - waiters = _deque(_islice(__waiters, n)) - if not waiters: + all_waiters = self._waiters + waiters_to_notify = _deque(_islice(all_waiters, n)) + if not waiters_to_notify: return - for waiter in waiters: + for waiter in waiters_to_notify: waiter.release() try: - __waiters.remove(waiter) + all_waiters.remove(waiter) except ValueError: pass -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 05:03:22 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 05:03:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzExOTYzOiByZW1v?= =?utf-8?q?ve_human_verification_from_test=5Fparser_and_test=5Fsubprocess?= =?utf-8?q?=2E?= Message-ID: <3ZPQf23hvjzSQK@mail.python.org> http://hg.python.org/cpython/rev/222505a5aeac changeset: 82595:222505a5aeac branch: 3.2 parent: 82579:64b87578c071 user: Ezio Melotti date: Mon Mar 11 05:53:34 2013 +0200 summary: #11963: remove human verification from test_parser and test_subprocess. files: Lib/test/test_subprocess.py | 48 ++++++++++++++++++------ Misc/NEWS | 2 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -157,16 +157,27 @@ self.assertEqual(p.stdin, None) def test_stdout_none(self): - # .stdout is None when not redirected - p = subprocess.Popen([sys.executable, "-c", - 'print(" this bit of output is from a ' - 'test of stdout in a different ' - 'process ...")'], - stdin=subprocess.PIPE, stderr=subprocess.PIPE) - self.addCleanup(p.stdin.close) + # .stdout is None when not redirected, and the child's stdout will + # be inherited from the parent. In order to test this we run a + # subprocess in a subprocess: + # this_test + # \-- subprocess created by this test (parent) + # \-- subprocess created by the parent subprocess (child) + # The parent doesn't specify stdout, so the child will use the + # parent's stdout. This test checks that the message printed by the + # child goes to the parent stdout. The parent also checks that the + # child's stdout is None. See #11963. + code = ('import sys; from subprocess import Popen, PIPE;' + 'p = Popen([sys.executable, "-c", "print(\'test_stdout_none\')"],' + ' stdin=PIPE, stderr=PIPE);' + 'p.wait(); assert p.stdout is None;') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) self.addCleanup(p.stderr.close) - p.wait() - self.assertEqual(p.stdout, None) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test_stdout_none') def test_stderr_none(self): # .stderr is None when not redirected @@ -406,9 +417,22 @@ def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), b'.\n'))" - rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) - self.assertEqual(rc, 2) + # To avoid printing the text on stdout, we do something similar to + # test_stdout_none (see above). The parent subprocess calls the child + # subprocess passing stdout=1, and this test uses stdout=PIPE in + # order to capture and check the output of the parent. See #11963. + code = ('import sys, subprocess; ' + 'rc = subprocess.call([sys.executable, "-c", ' + ' "import os, sys; sys.exit(os.write(sys.stdout.fileno(), ' + 'b\'test with stdout=1\'))"], stdout=1); ' + 'assert rc == 18') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) + self.addCleanup(p.stderr.close) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test with stdout=1') def test_env(self): newenv = os.environ.copy() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -955,6 +955,8 @@ Tests ----- +- Issue #11963: remove human verification from test_parser and test_subprocess. + - Issue #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_capi. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 05:03:24 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 05:03:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2311963=3A_merge_with_3=2E2=2E?= Message-ID: <3ZPQf41s2CzScP@mail.python.org> http://hg.python.org/cpython/rev/cc08036b37a4 changeset: 82596:cc08036b37a4 branch: 3.3 parent: 82587:5eca56b68840 parent: 82595:222505a5aeac user: Ezio Melotti date: Mon Mar 11 05:59:55 2013 +0200 summary: #11963: merge with 3.2. files: Lib/test/test_subprocess.py | 48 ++++++++++++++++++------ Misc/NEWS | 2 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -184,16 +184,27 @@ self.assertEqual(p.stdin, None) def test_stdout_none(self): - # .stdout is None when not redirected - p = subprocess.Popen([sys.executable, "-c", - 'print(" this bit of output is from a ' - 'test of stdout in a different ' - 'process ...")'], - stdin=subprocess.PIPE, stderr=subprocess.PIPE) - self.addCleanup(p.stdin.close) + # .stdout is None when not redirected, and the child's stdout will + # be inherited from the parent. In order to test this we run a + # subprocess in a subprocess: + # this_test + # \-- subprocess created by this test (parent) + # \-- subprocess created by the parent subprocess (child) + # The parent doesn't specify stdout, so the child will use the + # parent's stdout. This test checks that the message printed by the + # child goes to the parent stdout. The parent also checks that the + # child's stdout is None. See #11963. + code = ('import sys; from subprocess import Popen, PIPE;' + 'p = Popen([sys.executable, "-c", "print(\'test_stdout_none\')"],' + ' stdin=PIPE, stderr=PIPE);' + 'p.wait(); assert p.stdout is None;') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) self.addCleanup(p.stderr.close) - p.wait() - self.assertEqual(p.stdout, None) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test_stdout_none') def test_stderr_none(self): # .stderr is None when not redirected @@ -471,9 +482,22 @@ def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), b'.\n'))" - rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) - self.assertEqual(rc, 2) + # To avoid printing the text on stdout, we do something similar to + # test_stdout_none (see above). The parent subprocess calls the child + # subprocess passing stdout=1, and this test uses stdout=PIPE in + # order to capture and check the output of the parent. See #11963. + code = ('import sys, subprocess; ' + 'rc = subprocess.call([sys.executable, "-c", ' + ' "import os, sys; sys.exit(os.write(sys.stdout.fileno(), ' + 'b\'test with stdout=1\'))"], stdout=1); ' + 'assert rc == 18') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) + self.addCleanup(p.stderr.close) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test with stdout=1') def test_stdout_devnull(self): p = subprocess.Popen([sys.executable, "-c", diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -645,6 +645,8 @@ Tests ----- +- Issue #11963: remove human verification from test_parser and test_subprocess. + - Issue #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_faulthandler and test_capi. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 05:03:25 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 05:03:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExOTYzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZPQf562ZmzScP@mail.python.org> http://hg.python.org/cpython/rev/629dba9f6746 changeset: 82597:629dba9f6746 parent: 82594:79943dee0aca parent: 82596:cc08036b37a4 user: Ezio Melotti date: Mon Mar 11 06:03:05 2013 +0200 summary: #11963: merge with 3.3. files: Lib/test/test_subprocess.py | 48 ++++++++++++++++++------ Misc/NEWS | 2 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -184,16 +184,27 @@ self.assertEqual(p.stdin, None) def test_stdout_none(self): - # .stdout is None when not redirected - p = subprocess.Popen([sys.executable, "-c", - 'print(" this bit of output is from a ' - 'test of stdout in a different ' - 'process ...")'], - stdin=subprocess.PIPE, stderr=subprocess.PIPE) - self.addCleanup(p.stdin.close) + # .stdout is None when not redirected, and the child's stdout will + # be inherited from the parent. In order to test this we run a + # subprocess in a subprocess: + # this_test + # \-- subprocess created by this test (parent) + # \-- subprocess created by the parent subprocess (child) + # The parent doesn't specify stdout, so the child will use the + # parent's stdout. This test checks that the message printed by the + # child goes to the parent stdout. The parent also checks that the + # child's stdout is None. See #11963. + code = ('import sys; from subprocess import Popen, PIPE;' + 'p = Popen([sys.executable, "-c", "print(\'test_stdout_none\')"],' + ' stdin=PIPE, stderr=PIPE);' + 'p.wait(); assert p.stdout is None;') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) self.addCleanup(p.stderr.close) - p.wait() - self.assertEqual(p.stdout, None) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test_stdout_none') def test_stderr_none(self): # .stderr is None when not redirected @@ -471,9 +482,22 @@ def test_stdout_filedes_of_stdout(self): # stdout is set to 1 (#1531862). - cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), b'.\n'))" - rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) - self.assertEqual(rc, 2) + # To avoid printing the text on stdout, we do something similar to + # test_stdout_none (see above). The parent subprocess calls the child + # subprocess passing stdout=1, and this test uses stdout=PIPE in + # order to capture and check the output of the parent. See #11963. + code = ('import sys, subprocess; ' + 'rc = subprocess.call([sys.executable, "-c", ' + ' "import os, sys; sys.exit(os.write(sys.stdout.fileno(), ' + 'b\'test with stdout=1\'))"], stdout=1); ' + 'assert rc == 18') + p = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) + self.addCleanup(p.stderr.close) + out, err = p.communicate() + self.assertEqual(p.returncode, 0, err) + self.assertEqual(out.rstrip(), b'test with stdout=1') def test_stdout_devnull(self): p = subprocess.Popen([sys.executable, "-c", diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -905,6 +905,8 @@ Tests ----- +- Issue #11963: remove human verification from test_parser and test_subprocess. + - Issue #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_faulthandler and test_capi. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Mar 11 05:58:55 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 11 Mar 2013 05:58:55 +0100 Subject: [Python-checkins] Daily reference leaks (0f86b51f8f8b): sum=0 Message-ID: results for 0f86b51f8f8b on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogUoj_bc', '-x'] From python-checkins at python.org Mon Mar 11 06:27:07 2013 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 Mar 2013 06:27:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315806=3A_Add_cont?= =?utf-8?b?ZXh0bGliLmlnbm9yZWQoKS4=?= Message-ID: <3ZPSVg1RCXzSQK@mail.python.org> http://hg.python.org/cpython/rev/406b47c64480 changeset: 82598:406b47c64480 user: Raymond Hettinger date: Sun Mar 10 22:26:51 2013 -0700 summary: Issue #15806: Add contextlib.ignored(). files: Doc/library/contextlib.rst | 20 ++++++++++++++++++++ Lib/contextlib.py | 14 +++++++++++++- Lib/test/test_contextlib.py | 22 ++++++++++++++++++++++ Misc/NEWS | 3 +++ 4 files changed, 58 insertions(+), 1 deletions(-) diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -94,6 +94,26 @@ without needing to explicitly close ``page``. Even if an error occurs, ``page.close()`` will be called when the :keyword:`with` block is exited. +.. function:: ignored(*exceptions) + + Return a context manager that ignores the specified expections if they + occur in the body of a with-statement. + + For example:: + + from contextlib import ignored + + with ignored(OSError): + os.remove('somefile.tmp') + + This code is equivalent to:: + + try: + os.remove('somefile.tmp') + except OSError: + pass + + .. versionadded:: 3.4 .. class:: ContextDecorator() diff --git a/Lib/contextlib.py b/Lib/contextlib.py --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -4,7 +4,7 @@ from collections import deque from functools import wraps -__all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack"] +__all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack", "ignored"] class ContextDecorator(object): @@ -140,6 +140,18 @@ def __exit__(self, *exc_info): self.thing.close() + at contextmanager +def ignored(*exceptions): + """Context manager to ignore specifed exceptions + + with ignored(OSError): + os.remove(somefile) + + """ + try: + yield + except exceptions: + pass # Inspired by discussions on http://bugs.python.org/issue13585 class ExitStack(object): 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 @@ -594,6 +594,28 @@ stack.push(cm) self.assertIs(stack._exit_callbacks[-1], cm) +class TestIgnored(unittest.TestCase): + + def test_no_exception(self): + + with ignored(ValueError): + self.assertEqual(pow(2, 5), 32) + + def test_exact_exception(self): + + with ignored(TypeError): + len(5) + + def test_multiple_exception_args(self): + + with ignored(ZeroDivisionError, TypeError): + len(5) + + def test_exception_hierarchy(self): + + with ignored(LookupError): + 'Hello'[50] + # This is needed to make the test actually run under regrtest.py! def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,9 @@ _ Issue #17385: Fix quadratic behavior in threading.Condition. The FIFO queue now uses a deque instead of a list. +- Issue #15806: Add contextlib.ignored(). This creates a context manager + to ignore specified exceptions, replacing the "except Exc: pass" idiom. + - Issue #14645: The email generator classes now produce output using the specified linesep throughout. Previously if the prolog, epilog, or body were stored with a different linesep, that linesep was used. This -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 07:57:33 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 07:57:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_debug_print=2E?= Message-ID: <3ZPVW12nMNzS7h@mail.python.org> http://hg.python.org/cpython/rev/2dc08789ad3e changeset: 82599:2dc08789ad3e user: Ezio Melotti date: Mon Mar 11 08:57:17 2013 +0200 summary: Remove debug print. files: Lib/test/test_multiprocessing.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1748,7 +1748,6 @@ with multiprocessing.Pool(2) as p: r = p.map_async(sqr, L) self.assertEqual(r.get(), expected) - print(p._state) self.assertRaises(ValueError, p.map_async, sqr, L) def raising(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 08:14:24 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 08:14:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE2MDA0OiBBZGQg?= =?utf-8?q?=60make_touch=60=2E?= Message-ID: <3ZPVtS3mkkzSHQ@mail.python.org> http://hg.python.org/cpython/rev/da3f4774b939 changeset: 82600:da3f4774b939 branch: 2.7 parent: 82593:3e14aafeca04 user: Ezio Melotti date: Mon Mar 11 09:14:09 2013 +0200 summary: #16004: Add `make touch`. files: Makefile.pre.in | 6 +++++- Misc/NEWS | 2 ++ 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1250,6 +1250,10 @@ etags Include/*.h; \ for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done +# Touch generated files +touch: + touch Include/Python-ast.h Python/Python-ast.c + # Sanitation targets -- clean leaves libraries, executables and tags # files, which clobber removes as well pycremoval: @@ -1339,7 +1343,7 @@ .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean -.PHONY: smelly funny patchcheck altmaninstall +.PHONY: smelly funny patchcheck touch altmaninstall .PHONY: gdbhooks # IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -874,6 +874,8 @@ Build ----- +- Issue #16004: Add `make touch`. + - Issue #5033: Fix building of the sqlite3 extension module when the SQLite library version has "beta" in it. Patch by Andreas Pelme. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 08:43:41 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 08:43:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzUxOiByZW1v?= =?utf-8?q?ve_=22object=22_inheritance_from_docs=2E__Patch_by_Phil_Elson?= =?utf-8?q?=2E?= Message-ID: <3ZPWXF6ZBgzRpR@mail.python.org> http://hg.python.org/cpython/rev/4f745f7d6fca changeset: 82601:4f745f7d6fca branch: 3.2 parent: 82595:222505a5aeac user: Ezio Melotti date: Mon Mar 11 09:30:21 2013 +0200 summary: #17351: remove "object" inheritance from docs. Patch by Phil Elson. files: Doc/howto/descriptor.rst | 6 +++--- Doc/howto/logging-cookbook.rst | 6 +++--- Doc/howto/sorting.rst | 2 +- Doc/library/functions.rst | 2 +- Misc/ACKS | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -224,17 +224,17 @@ if obj is None: return self if self.fget is None: - raise AttributeError, "unreadable attribute" + raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self, obj, value): if self.fset is None: - raise AttributeError, "can't set attribute" + raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: - raise AttributeError, "can't delete attribute" + raise AttributeError("can't delete attribute") self.fdel(obj) The :func:`property` builtin helps whenever a user interface has granted diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1036,7 +1036,7 @@ call ``str()`` on that object to get the actual format string. Consider the following two classes:: - class BraceMessage(object): + class BraceMessage: def __init__(self, fmt, *args, **kwargs): self.fmt = fmt self.args = args @@ -1045,7 +1045,7 @@ def __str__(self): return self.fmt.format(*self.args, **self.kwargs) - class DollarMessage(object): + class DollarMessage: def __init__(self, fmt, **kwargs): self.fmt = fmt self.kwargs = kwargs @@ -1345,7 +1345,7 @@ import random import time - class MyHandler(object): + class MyHandler: """ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -225,7 +225,7 @@ def cmp_to_key(mycmp): 'Convert a cmp= function into a key= function' - class K(object): + class K: def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -317,7 +317,7 @@ ['Struct', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', 'unpack', 'unpack_from'] - >>> class Shape(object): + >>> class Shape: def __dir__(self): return ['area', 'perimeter', 'location'] >>> s = Shape() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -303,6 +303,7 @@ Andrew Eland Julien ?lie Lance Ellinghaus +Phil Elson David Ely Jeff Epler Tom Epperly -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 08:43:43 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 08:43:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317351=3A_merge_with_3=2E2=2E?= Message-ID: <3ZPWXH3kJVzS2h@mail.python.org> http://hg.python.org/cpython/rev/8b1d3fa3b389 changeset: 82602:8b1d3fa3b389 branch: 3.3 parent: 82596:cc08036b37a4 parent: 82601:4f745f7d6fca user: Ezio Melotti date: Mon Mar 11 09:42:40 2013 +0200 summary: #17351: merge with 3.2. files: Doc/howto/logging-cookbook.rst | 6 ++-- Doc/howto/sorting.rst | 2 +- Doc/library/contextlib.rst | 2 +- Doc/library/functions.rst | 2 +- Doc/library/unittest.mock-examples.rst | 16 +++++++------- Doc/library/unittest.mock.rst | 16 +++++++------- Misc/ACKS | 1 + 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1036,7 +1036,7 @@ call ``str()`` on that object to get the actual format string. Consider the following two classes:: - class BraceMessage(object): + class BraceMessage: def __init__(self, fmt, *args, **kwargs): self.fmt = fmt self.args = args @@ -1045,7 +1045,7 @@ def __str__(self): return self.fmt.format(*self.args, **self.kwargs) - class DollarMessage(object): + class DollarMessage: def __init__(self, fmt, **kwargs): self.fmt = fmt self.kwargs = kwargs @@ -1372,7 +1372,7 @@ import random import time - class MyHandler(object): + class MyHandler: """ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -225,7 +225,7 @@ def cmp_to_key(mycmp): 'Convert a cmp= function into a key= function' - class K(object): + class K: def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -361,7 +361,7 @@ from contextlib import contextmanager, ExitStack - class ResourceManager(object): + class ResourceManager: def __init__(self, acquire_resource, release_resource, check_resource_ok=None): self.acquire_resource = acquire_resource diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -324,7 +324,7 @@ '__initializing__', '__loader__', '__name__', '__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', 'unpack', 'unpack_from'] - >>> class Shape(object): + >>> class Shape: ... def __dir__(self): ... return ['area', 'perimeter', 'location'] >>> s = Shape() diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -45,7 +45,7 @@ This example tests that calling `ProductionClass().method` results in a call to the `something` method: - >>> class ProductionClass(object): + >>> class ProductionClass: ... def method(self): ... self.something(1, 2, 3) ... def something(self, a, b, c): @@ -69,7 +69,7 @@ The simple `ProductionClass` below has a `closer` method. If it is called with an object then it calls `close` on it. - >>> class ProductionClass(object): + >>> class ProductionClass: ... def closer(self, something): ... something.close() ... @@ -398,7 +398,7 @@ Where you use `patch` to create a mock for you, you can get a reference to the mock using the "as" form of the with statement: - >>> class ProductionClass(object): + >>> class ProductionClass: ... def method(self): ... pass ... @@ -446,7 +446,7 @@ So, suppose we have some code that looks a little bit like this: - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.backend = BackendProvider() ... def method(self): @@ -554,7 +554,7 @@ Here's an example class with an "iter" method implemented as a generator: - >>> class Foo(object): + >>> class Foo: ... def iter(self): ... for i in [1, 2, 3]: ... yield i @@ -664,7 +664,7 @@ It will have `self` passed in as the first argument, which is exactly what I wanted: - >>> class Foo(object): + >>> class Foo: ... def foo(self): ... pass ... @@ -1183,7 +1183,7 @@ You can see in this example how a 'standard' call to `assert_called_with` isn't sufficient: - >>> class Foo(object): + >>> class Foo: ... def __init__(self, a, b): ... self.a, self.b = a, b ... @@ -1210,7 +1210,7 @@ And a matcher object that can use comparison functions like this for its equality operation would look something like this: - >>> class Matcher(object): + >>> class Matcher: ... def __init__(self, compare, some_obj): ... self.compare = compare ... self.some_obj = some_obj 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 @@ -695,7 +695,7 @@ Fetching a `PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. - >>> class Foo(object): + >>> class Foo: ... @property ... def foo(self): ... return 'something' @@ -1031,7 +1031,7 @@ To configure return values on methods of *instances* on the patched class you must do this on the `return_value`. For example: - >>> class Class(object): + >>> class Class: ... def method(self): ... pass ... @@ -1204,7 +1204,7 @@ magic methods `__getitem__`, `__setitem__`, `__delitem__` and either `__iter__` or `__contains__`. - >>> class Container(object): + >>> class Container: ... def __init__(self): ... self.values = {} ... def __getitem__(self, name): @@ -1378,7 +1378,7 @@ >>> value = 3 >>> >>> @patch('__main__.value', 'not three') - ... class Thing(object): + ... class Thing: ... def foo_one(self): ... print value ... def foo_two(self): @@ -2137,7 +2137,7 @@ `autospec` can't know about any dynamically created attributes and restricts the api to visible attributes. - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.a = 33 ... @@ -2180,7 +2180,7 @@ .. code-block:: python - class Something(object): + class Something: a = 33 This brings up another issue. It is relatively common to provide a default @@ -2191,7 +2191,7 @@ `autospec` doesn't use a spec for members that are set to `None`. These will just be ordinary mocks (well - `MagicMocks`): - >>> class Something(object): + >>> class Something: ... member = None ... >>> mock = create_autospec(Something) @@ -2206,7 +2206,7 @@ the spec. Thankfully `patch` supports this - you can simply pass the alternative object as the `autospec` argument: - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.a = 33 ... diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -331,6 +331,7 @@ Julien ?lie Lance Ellinghaus Daniel Ellis +Phil Elson David Ely Jeff Epler Jeff McNeil -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 08:43:45 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 08:43:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzUxOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZPWXK0zQ1zSj5@mail.python.org> http://hg.python.org/cpython/rev/b10a9d4f08eb changeset: 82603:b10a9d4f08eb parent: 82599:2dc08789ad3e parent: 82602:8b1d3fa3b389 user: Ezio Melotti date: Mon Mar 11 09:43:25 2013 +0200 summary: #17351: merge with 3.3. files: Doc/howto/logging-cookbook.rst | 6 ++-- Doc/howto/sorting.rst | 2 +- Doc/library/contextlib.rst | 2 +- Doc/library/functions.rst | 2 +- Doc/library/unittest.mock-examples.rst | 16 +++++++------- Doc/library/unittest.mock.rst | 16 +++++++------- Misc/ACKS | 1 + 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1034,7 +1034,7 @@ call ``str()`` on that object to get the actual format string. Consider the following two classes:: - class BraceMessage(object): + class BraceMessage: def __init__(self, fmt, *args, **kwargs): self.fmt = fmt self.args = args @@ -1043,7 +1043,7 @@ def __str__(self): return self.fmt.format(*self.args, **self.kwargs) - class DollarMessage(object): + class DollarMessage: def __init__(self, fmt, **kwargs): self.fmt = fmt self.kwargs = kwargs @@ -1370,7 +1370,7 @@ import random import time - class MyHandler(object): + class MyHandler: """ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -225,7 +225,7 @@ def cmp_to_key(mycmp): 'Convert a cmp= function into a key= function' - class K(object): + class K: def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -381,7 +381,7 @@ from contextlib import contextmanager, ExitStack - class ResourceManager(object): + class ResourceManager: def __init__(self, acquire_resource, release_resource, check_resource_ok=None): self.acquire_resource = acquire_resource diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -324,7 +324,7 @@ '__initializing__', '__loader__', '__name__', '__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', 'unpack', 'unpack_from'] - >>> class Shape(object): + >>> class Shape: ... def __dir__(self): ... return ['area', 'perimeter', 'location'] >>> s = Shape() diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -45,7 +45,7 @@ This example tests that calling `ProductionClass().method` results in a call to the `something` method: - >>> class ProductionClass(object): + >>> class ProductionClass: ... def method(self): ... self.something(1, 2, 3) ... def something(self, a, b, c): @@ -69,7 +69,7 @@ The simple `ProductionClass` below has a `closer` method. If it is called with an object then it calls `close` on it. - >>> class ProductionClass(object): + >>> class ProductionClass: ... def closer(self, something): ... something.close() ... @@ -412,7 +412,7 @@ Where you use `patch` to create a mock for you, you can get a reference to the mock using the "as" form of the with statement: - >>> class ProductionClass(object): + >>> class ProductionClass: ... def method(self): ... pass ... @@ -460,7 +460,7 @@ So, suppose we have some code that looks a little bit like this: - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.backend = BackendProvider() ... def method(self): @@ -568,7 +568,7 @@ Here's an example class with an "iter" method implemented as a generator: - >>> class Foo(object): + >>> class Foo: ... def iter(self): ... for i in [1, 2, 3]: ... yield i @@ -678,7 +678,7 @@ It will have `self` passed in as the first argument, which is exactly what I wanted: - >>> class Foo(object): + >>> class Foo: ... def foo(self): ... pass ... @@ -1197,7 +1197,7 @@ You can see in this example how a 'standard' call to `assert_called_with` isn't sufficient: - >>> class Foo(object): + >>> class Foo: ... def __init__(self, a, b): ... self.a, self.b = a, b ... @@ -1224,7 +1224,7 @@ And a matcher object that can use comparison functions like this for its equality operation would look something like this: - >>> class Matcher(object): + >>> class Matcher: ... def __init__(self, compare, some_obj): ... self.compare = compare ... self.some_obj = some_obj 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 @@ -715,7 +715,7 @@ Fetching a `PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. - >>> class Foo(object): + >>> class Foo: ... @property ... def foo(self): ... return 'something' @@ -1051,7 +1051,7 @@ To configure return values on methods of *instances* on the patched class you must do this on the `return_value`. For example: - >>> class Class(object): + >>> class Class: ... def method(self): ... pass ... @@ -1224,7 +1224,7 @@ magic methods `__getitem__`, `__setitem__`, `__delitem__` and either `__iter__` or `__contains__`. - >>> class Container(object): + >>> class Container: ... def __init__(self): ... self.values = {} ... def __getitem__(self, name): @@ -1398,7 +1398,7 @@ >>> value = 3 >>> >>> @patch('__main__.value', 'not three') - ... class Thing(object): + ... class Thing: ... def foo_one(self): ... print value ... def foo_two(self): @@ -2157,7 +2157,7 @@ `autospec` can't know about any dynamically created attributes and restricts the api to visible attributes. - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.a = 33 ... @@ -2200,7 +2200,7 @@ .. code-block:: python - class Something(object): + class Something: a = 33 This brings up another issue. It is relatively common to provide a default @@ -2211,7 +2211,7 @@ `autospec` doesn't use a spec for members that are set to `None`. These will just be ordinary mocks (well - `MagicMocks`): - >>> class Something(object): + >>> class Something: ... member = None ... >>> mock = create_autospec(Something) @@ -2226,7 +2226,7 @@ the spec. Thankfully `patch` supports this - you can simply pass the alternative object as the `autospec` argument: - >>> class Something(object): + >>> class Something: ... def __init__(self): ... self.a = 33 ... diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -334,6 +334,7 @@ Julien ?lie Lance Ellinghaus Daniel Ellis +Phil Elson David Ely Jeff Epler Jeff McNeil -- Repository URL: http://hg.python.org/cpython From brett at python.org Mon Mar 11 14:22:38 2013 From: brett at python.org (Brett Cannon) Date: Mon, 11 Mar 2013 09:22:38 -0400 Subject: [Python-checkins] cpython (2.7): #16004: Add `make touch`. In-Reply-To: <3ZPVtS3mkkzSHQ@mail.python.org> References: <3ZPVtS3mkkzSHQ@mail.python.org> Message-ID: Should this also touch Python/importlib.h? On Mon, Mar 11, 2013 at 3:14 AM, ezio.melotti wrote: > http://hg.python.org/cpython/rev/da3f4774b939 > changeset: 82600:da3f4774b939 > branch: 2.7 > parent: 82593:3e14aafeca04 > user: Ezio Melotti > date: Mon Mar 11 09:14:09 2013 +0200 > summary: > #16004: Add `make touch`. > > files: > Makefile.pre.in | 6 +++++- > Misc/NEWS | 2 ++ > 2 files changed, 7 insertions(+), 1 deletions(-) > > > diff --git a/Makefile.pre.in b/Makefile.pre.in > --- a/Makefile.pre.in > +++ b/Makefile.pre.in > @@ -1250,6 +1250,10 @@ > etags Include/*.h; \ > for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done > > +# Touch generated files > +touch: > + touch Include/Python-ast.h Python/Python-ast.c > + > # Sanitation targets -- clean leaves libraries, executables and tags > # files, which clobber removes as well > pycremoval: > @@ -1339,7 +1343,7 @@ > .PHONY: frameworkinstall frameworkinstallframework > frameworkinstallstructure > .PHONY: frameworkinstallmaclib frameworkinstallapps > frameworkinstallunixtools > .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber > distclean > -.PHONY: smelly funny patchcheck altmaninstall > +.PHONY: smelly funny patchcheck touch altmaninstall > .PHONY: gdbhooks > > # IF YOU PUT ANYTHING HERE IT WILL GO AWAY > diff --git a/Misc/NEWS b/Misc/NEWS > --- a/Misc/NEWS > +++ b/Misc/NEWS > @@ -874,6 +874,8 @@ > Build > ----- > > +- Issue #16004: Add `make touch`. > + > - Issue #5033: Fix building of the sqlite3 extension module when the > SQLite library version has "beta" in it. Patch by Andreas Pelme. > > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brett at python.org Mon Mar 11 14:23:07 2013 From: brett at python.org (Brett Cannon) Date: Mon, 11 Mar 2013 09:23:07 -0400 Subject: [Python-checkins] cpython (2.7): #16004: Add `make touch`. In-Reply-To: References: <3ZPVtS3mkkzSHQ@mail.python.org> Message-ID: On Mon, Mar 11, 2013 at 9:22 AM, Brett Cannon wrote: > Should this also touch Python/importlib.h? > > nm, noticed this was added on 2.7 and not default. > > On Mon, Mar 11, 2013 at 3:14 AM, ezio.melotti wrote: > >> http://hg.python.org/cpython/rev/da3f4774b939 >> changeset: 82600:da3f4774b939 >> branch: 2.7 >> parent: 82593:3e14aafeca04 >> user: Ezio Melotti >> date: Mon Mar 11 09:14:09 2013 +0200 >> summary: >> #16004: Add `make touch`. >> >> files: >> Makefile.pre.in | 6 +++++- >> Misc/NEWS | 2 ++ >> 2 files changed, 7 insertions(+), 1 deletions(-) >> >> >> diff --git a/Makefile.pre.in b/Makefile.pre.in >> --- a/Makefile.pre.in >> +++ b/Makefile.pre.in >> @@ -1250,6 +1250,10 @@ >> etags Include/*.h; \ >> for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done >> >> +# Touch generated files >> +touch: >> + touch Include/Python-ast.h Python/Python-ast.c >> + >> # Sanitation targets -- clean leaves libraries, executables and tags >> # files, which clobber removes as well >> pycremoval: >> @@ -1339,7 +1343,7 @@ >> .PHONY: frameworkinstall frameworkinstallframework >> frameworkinstallstructure >> .PHONY: frameworkinstallmaclib frameworkinstallapps >> frameworkinstallunixtools >> .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber >> distclean >> -.PHONY: smelly funny patchcheck altmaninstall >> +.PHONY: smelly funny patchcheck touch altmaninstall >> .PHONY: gdbhooks >> >> # IF YOU PUT ANYTHING HERE IT WILL GO AWAY >> diff --git a/Misc/NEWS b/Misc/NEWS >> --- a/Misc/NEWS >> +++ b/Misc/NEWS >> @@ -874,6 +874,8 @@ >> Build >> ----- >> >> +- Issue #16004: Add `make touch`. >> + >> - Issue #5033: Fix building of the sqlite3 extension module when the >> SQLite library version has "beta" in it. Patch by Andreas Pelme. >> >> >> -- >> Repository URL: http://hg.python.org/cpython >> >> _______________________________________________ >> Python-checkins mailing list >> Python-checkins at python.org >> http://mail.python.org/mailman/listinfo/python-checkins >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Mon Mar 11 17:31:49 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 Mar 2013 17:31:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_useless_words_=28?= =?utf-8?q?=2317327=29?= Message-ID: <3ZPlFd0G97zQcx@mail.python.org> http://hg.python.org/cpython/rev/89174df2ee45 changeset: 82604:89174df2ee45 user: Benjamin Peterson date: Mon Mar 11 11:31:29 2013 -0500 summary: remove useless words (#17327) files: Doc/c-api/dict.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -114,9 +114,9 @@ This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key - is not in the dict, it is inserted with value *defaultobj* and *defaultobj* - is inserted. This function evaluates the hash function of *key* only once, - instead of evaluating it independently for the lookup and the insertion. + is not in the dict, it is inserted with value *defaultobj* and *defaultobj*. + This function evaluates the hash function of *key* only once, instead of + evaluating it independently for the lookup and the insertion. .. c:function:: PyObject* PyDict_Items(PyObject *p) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 17:36:07 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 Mar 2013 17:36:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_more_useless_words?= Message-ID: <3ZPlLb0w3VzQwB@mail.python.org> http://hg.python.org/cpython/rev/606bc9d21337 changeset: 82605:606bc9d21337 user: Benjamin Peterson date: Mon Mar 11 11:35:47 2013 -0500 summary: remove more useless words files: Doc/c-api/dict.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -114,9 +114,9 @@ This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key - is not in the dict, it is inserted with value *defaultobj* and *defaultobj*. - This function evaluates the hash function of *key* only once, instead of - evaluating it independently for the lookup and the insertion. + is not in the dict, it is inserted with value *defaultobj*. This function + evaluates the hash function of *key* only once, instead of evaluating it + independently for the lookup and the insertion. .. c:function:: PyObject* PyDict_Items(PyObject *p) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 17:50:35 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 Mar 2013 17:50:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_say_defaultobj_is_returned?= =?utf-8?b?ICgjMTczMjcp?= Message-ID: <3ZPlgH5VJvzQd9@mail.python.org> http://hg.python.org/cpython/rev/8948dd77b095 changeset: 82606:8948dd77b095 user: Benjamin Peterson date: Mon Mar 11 11:50:21 2013 -0500 summary: say defaultobj is returned (#17327) files: Doc/c-api/dict.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -114,9 +114,9 @@ This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key - is not in the dict, it is inserted with value *defaultobj*. This function - evaluates the hash function of *key* only once, instead of evaluating it - independently for the lookup and the insertion. + is not in the dict, it is inserted with value *defaultobj* and *defautobj* is + returned. This function evaluates the hash function of *key* only once, + instead of evaluating it independently for the lookup and the insertion. .. c:function:: PyObject* PyDict_Items(PyObject *p) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 18:17:32 2013 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 Mar 2013 18:17:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_fix_spelling_=28=2317327?= =?utf-8?q?=29?= Message-ID: <3ZPmGN4FFFzR08@mail.python.org> http://hg.python.org/cpython/rev/f6f39ebd3121 changeset: 82607:f6f39ebd3121 user: Benjamin Peterson date: Mon Mar 11 12:17:19 2013 -0500 summary: fix spelling (#17327) files: Doc/c-api/dict.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -114,8 +114,8 @@ This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key - is not in the dict, it is inserted with value *defaultobj* and *defautobj* is - returned. This function evaluates the hash function of *key* only once, + is not in the dict, it is inserted with value *defaultobj* and *defaultobj* + is returned. This function evaluates the hash function of *key* only once, instead of evaluating it independently for the lookup and the insertion. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 20:39:35 2013 From: python-checkins at python.org (ezio.melotti) Date: Mon, 11 Mar 2013 20:39:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2317395=3A_wait_for_live_?= =?utf-8?q?children_in_test=5Fmultiprocessing=2E?= Message-ID: <3ZPqQH21bFzQyS@mail.python.org> http://hg.python.org/cpython/rev/2966e5a55396 changeset: 82608:2966e5a55396 user: Ezio Melotti date: Mon Mar 11 21:39:18 2013 +0200 summary: #17395: wait for live children in test_multiprocessing. files: Lib/test/test_multiprocessing.py | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2998,7 +2998,13 @@ @classmethod def tearDownClass(cls): - multiprocessing.active_children() # discard dead process objs + # only the manager process should be returned by active_children() + # but this can take a bit on slow machines, so wait a few seconds + # if there are other children too (see #17395) + t = 0.01 + while len(multiprocessing.active_children()) > 1 and t < 5: + time.sleep(t) + t *= 2 gc.collect() # do garbage collection if cls.manager._number_of_objects() != 0: # This is not really an error since some tests do not -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:29:05 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:29:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_removed_doubled_words_in_Doc/*=2C_Mac/*=2C_and_Tool/*?= Message-ID: <3ZPsrd07fxzQwH@mail.python.org> http://hg.python.org/cpython/rev/1ecb712fcf22 changeset: 82609:1ecb712fcf22 branch: 2.7 parent: 82600:da3f4774b939 user: Terry Jan Reedy date: Mon Mar 11 17:09:58 2013 -0400 summary: Issue #17047: removed doubled words in Doc/*, Mac/*, and Tool/* found by Serhiy Storchaka and Matthew Barnett files: Doc/c-api/intro.rst | 2 +- Doc/library/xml.dom.rst | 2 +- Mac/README | 2 +- Tools/msi/msilib.py | 2 +- Tools/pybench/README | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -424,7 +424,7 @@ .. index:: single: sum_sequence() A simple example of detecting exceptions and passing them on is shown in the -:c:func:`sum_sequence` example above. It so happens that that example doesn't +:c:func:`sum_sequence` example above. It so happens that this example doesn't need to clean up any owned references when it detects an error. The following example function shows some error cleanup. First, to remind you why you like Python, we show the equivalent Python code:: diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -374,7 +374,7 @@ Add a new child node to this node at the end of the list of children, returning *newChild*. If the node was already in - in the tree, it is removed first. + the tree, it is removed first. .. method:: Node.insertBefore(newChild, refChild) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -33,7 +33,7 @@ * ``--enable-universalsdk[=PATH]`` - Create a universal binary build of of Python. This can be used with both + Create a universal binary build of Python. This can be used with both regular and framework builds. The optional argument specifies which OSX SDK should be used to perform the diff --git a/Tools/msi/msilib.py b/Tools/msi/msilib.py --- a/Tools/msi/msilib.py +++ b/Tools/msi/msilib.py @@ -516,7 +516,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Tools/pybench/README b/Tools/pybench/README --- a/Tools/pybench/README +++ b/Tools/pybench/README @@ -3,7 +3,7 @@ PYBENCH - A Python Benchmark Suite ________________________________________________________________________ - Extendable suite of of low-level benchmarks for measuring + Extendable suite of low-level benchmarks for measuring the performance of the Python implementation (interpreter, compiler or VM). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:29:06 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:29:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_removed_doubled_words_in_Doc/*=2C_Mac/*=2C_and_Tool/*?= Message-ID: <3ZPsrf4KCXzQwH@mail.python.org> http://hg.python.org/cpython/rev/e37647470fcf changeset: 82610:e37647470fcf branch: 3.2 parent: 82601:4f745f7d6fca user: Terry Jan Reedy date: Mon Mar 11 17:23:46 2013 -0400 summary: Issue #17047: removed doubled words in Doc/*, Mac/*, and Tool/* found by Serhiy Storchaka and Matthew Barnett files: Doc/c-api/intro.rst | 2 +- Doc/c-api/long.rst | 4 ++-- Doc/library/xml.dom.rst | 2 +- Mac/README | 2 +- Tools/msi/msilib.py | 2 +- Tools/pybench/README | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -433,7 +433,7 @@ .. index:: single: sum_sequence() A simple example of detecting exceptions and passing them on is shown in the -:c:func:`sum_sequence` example above. It so happens that that example doesn't +:c:func:`sum_sequence` example above. It so happens that this example doesn't need to clean up any owned references when it detects an error. The following example function shows some error cleanup. First, to remind you why you like Python, we show the equivalent Python code:: diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -189,7 +189,7 @@ .. c:function:: size_t PyLong_AsSize_t(PyObject *pylong) - Return a C :c:type:`size_t` representation of of *pylong*. *pylong* must be + Return a C :c:type:`size_t` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a @@ -201,7 +201,7 @@ .. index:: single: OverflowError (built-in exception) - Return a C :c:type:`unsigned PY_LONG_LONG` representation of of *pylong*. + Return a C :c:type:`unsigned PY_LONG_LONG` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for an diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -357,7 +357,7 @@ Add a new child node to this node at the end of the list of children, returning *newChild*. If the node was already in - in the tree, it is removed first. + the tree, it is removed first. .. method:: Node.insertBefore(newChild, refChild) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -30,7 +30,7 @@ * ``--enable-universalsdk[=PATH]`` - Create a universal binary build of of Python. This can be used with both + Create a universal binary build of Python. This can be used with both regular and framework builds. The optional argument specifies which OSX SDK should be used to perform the diff --git a/Tools/msi/msilib.py b/Tools/msi/msilib.py --- a/Tools/msi/msilib.py +++ b/Tools/msi/msilib.py @@ -489,7 +489,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Tools/pybench/README b/Tools/pybench/README --- a/Tools/pybench/README +++ b/Tools/pybench/README @@ -3,7 +3,7 @@ PYBENCH - A Python Benchmark Suite ________________________________________________________________________ - Extendable suite of of low-level benchmarks for measuring + Extendable suite of low-level benchmarks for measuring the performance of the Python implementation (interpreter, compiler or VM). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:29:08 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:29:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_with_3=2E2=3A_Issue_=2317047=3A_removed_doubled_words_in?= =?utf-8?q?_Doc/*=2C?= Message-ID: <3ZPsrh153fzQwH@mail.python.org> http://hg.python.org/cpython/rev/629322a13b53 changeset: 82611:629322a13b53 branch: 3.3 parent: 82602:8b1d3fa3b389 parent: 82610:e37647470fcf user: Terry Jan Reedy date: Mon Mar 11 17:26:33 2013 -0400 summary: Merge with 3.2: Issue #17047: removed doubled words in Doc/*, Mac/*, and Tool/* found by Serhiy Storchaka and Matthew Barnett files: Doc/c-api/intro.rst | 2 +- Doc/c-api/long.rst | 4 ++-- Doc/library/xml.dom.rst | 2 +- Mac/README | 2 +- Tools/msi/msilib.py | 2 +- Tools/pybench/README | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -433,7 +433,7 @@ .. index:: single: sum_sequence() A simple example of detecting exceptions and passing them on is shown in the -:c:func:`sum_sequence` example above. It so happens that that example doesn't +:c:func:`sum_sequence` example above. It so happens that this example doesn't need to clean up any owned references when it detects an error. The following example function shows some error cleanup. First, to remind you why you like Python, we show the equivalent Python code:: diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -203,7 +203,7 @@ .. c:function:: size_t PyLong_AsSize_t(PyObject *pylong) - Return a C :c:type:`size_t` representation of of *pylong*. *pylong* must be + Return a C :c:type:`size_t` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a @@ -215,7 +215,7 @@ .. index:: single: OverflowError (built-in exception) - Return a C :c:type:`unsigned PY_LONG_LONG` representation of of *pylong*. + Return a C :c:type:`unsigned PY_LONG_LONG` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for an diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -357,7 +357,7 @@ Add a new child node to this node at the end of the list of children, returning *newChild*. If the node was already in - in the tree, it is removed first. + the tree, it is removed first. .. method:: Node.insertBefore(newChild, refChild) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -37,7 +37,7 @@ * ``--enable-universalsdk[=PATH]`` - Create a universal binary build of of Python. This can be used with both + Create a universal binary build of Python. This can be used with both regular and framework builds. The optional argument specifies which OS X SDK should be used to perform the diff --git a/Tools/msi/msilib.py b/Tools/msi/msilib.py --- a/Tools/msi/msilib.py +++ b/Tools/msi/msilib.py @@ -491,7 +491,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Tools/pybench/README b/Tools/pybench/README --- a/Tools/pybench/README +++ b/Tools/pybench/README @@ -3,7 +3,7 @@ PYBENCH - A Python Benchmark Suite ________________________________________________________________________ - Extendable suite of of low-level benchmarks for measuring + Extendable suite of low-level benchmarks for measuring the performance of the Python implementation (interpreter, compiler or VM). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:29:09 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:29:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3=3A_Issue_=2317047=3A_removed_doubled_wo?= =?utf-8?q?rds_in_Doc/*=2C?= Message-ID: <3ZPsrj51KjzRvT@mail.python.org> http://hg.python.org/cpython/rev/c187c145b4c4 changeset: 82612:c187c145b4c4 parent: 82608:2966e5a55396 parent: 82611:629322a13b53 user: Terry Jan Reedy date: Mon Mar 11 17:27:28 2013 -0400 summary: Merge with 3.3: Issue #17047: removed doubled words in Doc/*, Mac/*, and Tool/* found by Serhiy Storchaka and Matthew Barnett files: Doc/c-api/intro.rst | 2 +- Doc/c-api/long.rst | 4 ++-- Doc/library/xml.dom.rst | 2 +- Mac/README | 2 +- Tools/msi/msilib.py | 2 +- Tools/pybench/README | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -433,7 +433,7 @@ .. index:: single: sum_sequence() A simple example of detecting exceptions and passing them on is shown in the -:c:func:`sum_sequence` example above. It so happens that that example doesn't +:c:func:`sum_sequence` example above. It so happens that this example doesn't need to clean up any owned references when it detects an error. The following example function shows some error cleanup. First, to remind you why you like Python, we show the equivalent Python code:: diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -203,7 +203,7 @@ .. c:function:: size_t PyLong_AsSize_t(PyObject *pylong) - Return a C :c:type:`size_t` representation of of *pylong*. *pylong* must be + Return a C :c:type:`size_t` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a @@ -215,7 +215,7 @@ .. index:: single: OverflowError (built-in exception) - Return a C :c:type:`unsigned PY_LONG_LONG` representation of of *pylong*. + Return a C :c:type:`unsigned PY_LONG_LONG` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for an diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -357,7 +357,7 @@ Add a new child node to this node at the end of the list of children, returning *newChild*. If the node was already in - in the tree, it is removed first. + the tree, it is removed first. .. method:: Node.insertBefore(newChild, refChild) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -37,7 +37,7 @@ * ``--enable-universalsdk[=PATH]`` - Create a universal binary build of of Python. This can be used with both + Create a universal binary build of Python. This can be used with both regular and framework builds. The optional argument specifies which OS X SDK should be used to perform the diff --git a/Tools/msi/msilib.py b/Tools/msi/msilib.py --- a/Tools/msi/msilib.py +++ b/Tools/msi/msilib.py @@ -491,7 +491,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Tools/pybench/README b/Tools/pybench/README --- a/Tools/pybench/README +++ b/Tools/pybench/README @@ -3,7 +3,7 @@ PYBENCH - A Python Benchmark Suite ________________________________________________________________________ - Extendable suite of of low-level benchmarks for measuring + Extendable suite of low-level benchmarks for measuring the performance of the Python implementation (interpreter, compiler or VM). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:47:08 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:47:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_remove_doubled_words_found_in_2=2E7_to_3=2E4_Modules/*=2C?= Message-ID: <3ZPtFS2qxvzRrF@mail.python.org> http://hg.python.org/cpython/rev/e145dddb9d93 changeset: 82613:e145dddb9d93 branch: 2.7 parent: 82609:1ecb712fcf22 user: Terry Jan Reedy date: Mon Mar 11 17:41:44 2013 -0400 summary: Issue #17047: remove doubled words found in 2.7 to 3.4 Modules/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Modules/_ctypes/callproc.c | 4 ++-- Modules/_ctypes/libffi/src/dlmalloc.c | 12 ++++++------ Modules/_ctypes/libffi/src/ia64/ffi.c | 4 ++-- Modules/_heapqmodule.c | 4 ++-- Modules/_io/iobase.c | 2 +- Modules/expat/xmltok.c | 2 +- Modules/ossaudiodev.c | 2 +- Modules/zlib/deflate.c | 4 ++-- Modules/zlib/zlib.h | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -25,8 +25,8 @@ 2. After several checks, _build_callargs() is called which returns another tuple 'callargs'. This may be the same tuple as 'inargs', a slice of - 'inargs', or a completely fresh tuple, depending on several things (is is a - COM method, are 'paramflags' available). + 'inargs', or a completely fresh tuple, depending on several things (is it a + COM method?, are 'paramflags' available?). 3. _build_callargs also calculates bitarrays containing indexes into the callargs tuple, specifying how to build the return value(s) of diff --git a/Modules/_ctypes/libffi/src/dlmalloc.c b/Modules/_ctypes/libffi/src/dlmalloc.c --- a/Modules/_ctypes/libffi/src/dlmalloc.c +++ b/Modules/_ctypes/libffi/src/dlmalloc.c @@ -100,7 +100,7 @@ If you don't like either of these options, you can define CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has + else. And if you are sure that your program using malloc has no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. @@ -599,7 +599,7 @@ declaration needed is the mallinfo struct that is returned (by-copy) by mallinfo(). The malloinfo struct contains a bunch of fields that are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of + instead filled by mallinfo() with other numbers that might be of interest. HAVE_USR_INCLUDE_MALLOC_H should be set if you have a @@ -1564,7 +1564,7 @@ Each freshly allocated chunk must have both cinuse and pinuse set. That is, each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any + ensured by making all allocations from the `lowest' part of any found chunk. Further, no free chunk physically borders another one, so each free chunk is known to be preceded and followed by either inuse chunks or the ends of memory. @@ -1770,12 +1770,12 @@ of the same size are arranged in a circularly-linked list, with only the oldest chunk (the next to be used, in our FIFO ordering) actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node + parent pointer.) If a chunk with the same size as an existing node is inserted, it is linked off the existing node using pointers that work in the same way as fd/bk pointers of small chunks. Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each + smallest is 0x100 <= x < 0x180), which is divided in half at each tree level, with the chunks in the smaller half of the range (0x100 <= x < 0x140 for the top nose) in the left subtree and the larger half (0x140 <= x < 0x180) in the right subtree. This is, of course, @@ -3380,7 +3380,7 @@ least-preferred order): 1. A call to MORECORE that can normally contiguously extend memory. (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) + main space is mmapped or a previous contiguous call failed) 2. A call to MMAP new space (disabled if not HAVE_MMAP). Note that under the default settings, if MORECORE is unable to fulfill a request, and HAVE_MMAP is true, then mmap is diff --git a/Modules/_ctypes/libffi/src/ia64/ffi.c b/Modules/_ctypes/libffi/src/ia64/ffi.c --- a/Modules/_ctypes/libffi/src/ia64/ffi.c +++ b/Modules/_ctypes/libffi/src/ia64/ffi.c @@ -84,7 +84,7 @@ #define ldf_fill(result, addr) \ asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); -/* Return the size of the C type associated with with TYPE. Which will +/* Return the size of the C type associated with TYPE, which will be one of the FFI_IA64_TYPE_HFA_* values. */ static size_t @@ -184,7 +184,7 @@ break; case FFI_TYPE_LONGDOUBLE: - /* Similarly, except that that HFA is true for double extended, + /* Similarly, except that HFA is true for double extended, but not quad precision. Both have sizeof == 16, so tell the difference based on the precision. */ if (LDBL_MANT_DIG == 64 && nested) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -139,7 +139,7 @@ } } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -478,7 +478,7 @@ childpos = 2*pos + 1; } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -74,7 +74,7 @@ PyDoc_STRVAR(iobase_seek_doc, "Change stream position.\n" "\n" - "Change the stream position to byte offset offset. offset is\n" + "Change the stream position to the given byte offset. The offset is\n" "interpreted relative to the position indicated by whence. Values\n" "for whence are:\n" "\n" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -1584,7 +1584,7 @@ if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only - way this can fail to be big-endian UTF-16 if it it's an + way this can fail to be big-endian UTF-16 is if it is an external parsed general entity that's labelled as UTF-16LE. */ diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -215,7 +215,7 @@ */ /* _do_ioctl_1() is a private helper function used for the OSS ioctls -- - SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C + SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C like this: ioctl(fd, SNDCTL_DSP_cmd, &arg) diff --git a/Modules/zlib/deflate.c b/Modules/zlib/deflate.c --- a/Modules/zlib/deflate.c +++ b/Modules/zlib/deflate.c @@ -163,7 +163,7 @@ /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ @@ -176,7 +176,7 @@ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive + * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ diff --git a/Modules/zlib/zlib.h b/Modules/zlib/zlib.h --- a/Modules/zlib/zlib.h +++ b/Modules/zlib/zlib.h @@ -764,7 +764,7 @@ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which + case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:47:10 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:47:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_remove_doubled_words_found_in_2=2E7_to_3=2E4_Modules/*=2C?= Message-ID: <3ZPtFV0GNCzRsn@mail.python.org> http://hg.python.org/cpython/rev/e9ba9f21a828 changeset: 82614:e9ba9f21a828 branch: 3.2 parent: 82610:e37647470fcf user: Terry Jan Reedy date: Mon Mar 11 17:42:46 2013 -0400 summary: Issue #17047: remove doubled words found in 2.7 to 3.4 Modules/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Modules/_ctypes/callproc.c | 4 ++-- Modules/_ctypes/libffi/src/dlmalloc.c | 12 ++++++------ Modules/_ctypes/libffi/src/ia64/ffi.c | 4 ++-- Modules/_heapqmodule.c | 4 ++-- Modules/_io/iobase.c | 2 +- Modules/expat/xmltok.c | 2 +- Modules/ossaudiodev.c | 2 +- Modules/zlib/deflate.c | 4 ++-- Modules/zlib/inftrees.h | 2 +- Modules/zlib/zlib.h | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -20,8 +20,8 @@ 2. After several checks, _build_callargs() is called which returns another tuple 'callargs'. This may be the same tuple as 'inargs', a slice of - 'inargs', or a completely fresh tuple, depending on several things (is is a - COM method, are 'paramflags' available). + 'inargs', or a completely fresh tuple, depending on several things (is it a + COM method?, are 'paramflags' available?). 3. _build_callargs also calculates bitarrays containing indexes into the callargs tuple, specifying how to build the return value(s) of diff --git a/Modules/_ctypes/libffi/src/dlmalloc.c b/Modules/_ctypes/libffi/src/dlmalloc.c --- a/Modules/_ctypes/libffi/src/dlmalloc.c +++ b/Modules/_ctypes/libffi/src/dlmalloc.c @@ -100,7 +100,7 @@ If you don't like either of these options, you can define CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has + else. And if you are sure that your program using malloc has no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. @@ -599,7 +599,7 @@ declaration needed is the mallinfo struct that is returned (by-copy) by mallinfo(). The malloinfo struct contains a bunch of fields that are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of + instead filled by mallinfo() with other numbers that might be of interest. HAVE_USR_INCLUDE_MALLOC_H should be set if you have a @@ -1564,7 +1564,7 @@ Each freshly allocated chunk must have both cinuse and pinuse set. That is, each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any + ensured by making all allocations from the `lowest' part of any found chunk. Further, no free chunk physically borders another one, so each free chunk is known to be preceded and followed by either inuse chunks or the ends of memory. @@ -1770,12 +1770,12 @@ of the same size are arranged in a circularly-linked list, with only the oldest chunk (the next to be used, in our FIFO ordering) actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node + parent pointer.) If a chunk with the same size as an existing node is inserted, it is linked off the existing node using pointers that work in the same way as fd/bk pointers of small chunks. Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each + smallest is 0x100 <= x < 0x180), which is divided in half at each tree level, with the chunks in the smaller half of the range (0x100 <= x < 0x140 for the top nose) in the left subtree and the larger half (0x140 <= x < 0x180) in the right subtree. This is, of course, @@ -3380,7 +3380,7 @@ least-preferred order): 1. A call to MORECORE that can normally contiguously extend memory. (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) + main space is mmapped or a previous contiguous call failed) 2. A call to MMAP new space (disabled if not HAVE_MMAP). Note that under the default settings, if MORECORE is unable to fulfill a request, and HAVE_MMAP is true, then mmap is diff --git a/Modules/_ctypes/libffi/src/ia64/ffi.c b/Modules/_ctypes/libffi/src/ia64/ffi.c --- a/Modules/_ctypes/libffi/src/ia64/ffi.c +++ b/Modules/_ctypes/libffi/src/ia64/ffi.c @@ -84,7 +84,7 @@ #define ldf_fill(result, addr) \ asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); -/* Return the size of the C type associated with with TYPE. Which will +/* Return the size of the C type associated with TYPE, which will be one of the FFI_IA64_TYPE_HFA_* values. */ static size_t @@ -184,7 +184,7 @@ break; case FFI_TYPE_LONGDOUBLE: - /* Similarly, except that that HFA is true for double extended, + /* Similarly, except that HFA is true for double extended, but not quad precision. Both have sizeof == 16, so tell the difference based on the precision. */ if (LDBL_MANT_DIG == 64 && nested) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -116,7 +116,7 @@ } } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -456,7 +456,7 @@ childpos = 2*pos + 1; } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -75,7 +75,7 @@ PyDoc_STRVAR(iobase_seek_doc, "Change stream position.\n" "\n" - "Change the stream position to byte offset offset. offset is\n" + "Change the stream position to the given byte offset. The offset is\n" "interpreted relative to the position indicated by whence. Values\n" "for whence are:\n" "\n" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -1584,7 +1584,7 @@ if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only - way this can fail to be big-endian UTF-16 if it it's an + way this can fail to be big-endian UTF-16 is if it is an external parsed general entity that's labelled as UTF-16LE. */ diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -215,7 +215,7 @@ */ /* _do_ioctl_1() is a private helper function used for the OSS ioctls -- - SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C + SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C like this: ioctl(fd, SNDCTL_DSP_cmd, &arg) diff --git a/Modules/zlib/deflate.c b/Modules/zlib/deflate.c --- a/Modules/zlib/deflate.c +++ b/Modules/zlib/deflate.c @@ -157,7 +157,7 @@ /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ @@ -170,7 +170,7 @@ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive + * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ diff --git a/Modules/zlib/inftrees.h b/Modules/zlib/inftrees.h --- a/Modules/zlib/inftrees.h +++ b/Modules/zlib/inftrees.h @@ -41,7 +41,7 @@ examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. + returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and diff --git a/Modules/zlib/zlib.h b/Modules/zlib/zlib.h --- a/Modules/zlib/zlib.h +++ b/Modules/zlib/zlib.h @@ -812,7 +812,7 @@ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in + success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:47:11 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:47:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_3=2E2=2C_Issue_=2317047=3A_remove_doubled_words_found_in?= =?utf-8?q?_2=2E7_to_3=2E4?= Message-ID: <3ZPtFW5MlKzRkZ@mail.python.org> http://hg.python.org/cpython/rev/a42195046e39 changeset: 82615:a42195046e39 branch: 3.3 parent: 82611:629322a13b53 parent: 82614:e9ba9f21a828 user: Terry Jan Reedy date: Mon Mar 11 17:45:12 2013 -0400 summary: Merge 3.2, Issue #17047: remove doubled words found in 2.7 to 3.4 Modules/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Modules/_ctypes/callproc.c | 4 ++-- Modules/_ctypes/libffi/src/dlmalloc.c | 12 ++++++------ Modules/_ctypes/libffi/src/ia64/ffi.c | 4 ++-- Modules/_heapqmodule.c | 4 ++-- Modules/_io/iobase.c | 2 +- Modules/expat/xmltok.c | 2 +- Modules/ossaudiodev.c | 2 +- Modules/zlib/deflate.c | 4 ++-- Modules/zlib/inftrees.h | 2 +- Modules/zlib/zlib.h | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -20,8 +20,8 @@ 2. After several checks, _build_callargs() is called which returns another tuple 'callargs'. This may be the same tuple as 'inargs', a slice of - 'inargs', or a completely fresh tuple, depending on several things (is is a - COM method, are 'paramflags' available). + 'inargs', or a completely fresh tuple, depending on several things (is it a + COM method?, are 'paramflags' available?). 3. _build_callargs also calculates bitarrays containing indexes into the callargs tuple, specifying how to build the return value(s) of diff --git a/Modules/_ctypes/libffi/src/dlmalloc.c b/Modules/_ctypes/libffi/src/dlmalloc.c --- a/Modules/_ctypes/libffi/src/dlmalloc.c +++ b/Modules/_ctypes/libffi/src/dlmalloc.c @@ -100,7 +100,7 @@ If you don't like either of these options, you can define CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has + else. And if you are sure that your program using malloc has no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. @@ -607,7 +607,7 @@ declaration needed is the mallinfo struct that is returned (by-copy) by mallinfo(). The malloinfo struct contains a bunch of fields that are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of + instead filled by mallinfo() with other numbers that might be of interest. HAVE_USR_INCLUDE_MALLOC_H should be set if you have a @@ -1621,7 +1621,7 @@ Each freshly allocated chunk must have both cinuse and pinuse set. That is, each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any + ensured by making all allocations from the `lowest' part of any found chunk. Further, no free chunk physically borders another one, so each free chunk is known to be preceded and followed by either inuse chunks or the ends of memory. @@ -1827,12 +1827,12 @@ of the same size are arranged in a circularly-linked list, with only the oldest chunk (the next to be used, in our FIFO ordering) actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node + parent pointer.) If a chunk with the same size as an existing node is inserted, it is linked off the existing node using pointers that work in the same way as fd/bk pointers of small chunks. Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each + smallest is 0x100 <= x < 0x180), which is divided in half at each tree level, with the chunks in the smaller half of the range (0x100 <= x < 0x140 for the top nose) in the left subtree and the larger half (0x140 <= x < 0x180) in the right subtree. This is, of course, @@ -3442,7 +3442,7 @@ least-preferred order): 1. A call to MORECORE that can normally contiguously extend memory. (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) + main space is mmapped or a previous contiguous call failed) 2. A call to MMAP new space (disabled if not HAVE_MMAP). Note that under the default settings, if MORECORE is unable to fulfill a request, and HAVE_MMAP is true, then mmap is diff --git a/Modules/_ctypes/libffi/src/ia64/ffi.c b/Modules/_ctypes/libffi/src/ia64/ffi.c --- a/Modules/_ctypes/libffi/src/ia64/ffi.c +++ b/Modules/_ctypes/libffi/src/ia64/ffi.c @@ -85,7 +85,7 @@ #define ldf_fill(result, addr) \ asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); -/* Return the size of the C type associated with with TYPE. Which will +/* Return the size of the C type associated with TYPE, which will be one of the FFI_IA64_TYPE_HFA_* values. */ static size_t @@ -185,7 +185,7 @@ break; case FFI_TYPE_LONGDOUBLE: - /* Similarly, except that that HFA is true for double extended, + /* Similarly, except that HFA is true for double extended, but not quad precision. Both have sizeof == 16, so tell the difference based on the precision. */ if (LDBL_MANT_DIG == 64 && nested) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -116,7 +116,7 @@ } } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -456,7 +456,7 @@ childpos = 2*pos + 1; } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -76,7 +76,7 @@ PyDoc_STRVAR(iobase_seek_doc, "Change stream position.\n" "\n" - "Change the stream position to byte offset offset. offset is\n" + "Change the stream position to the given byte offset. The offset is\n" "interpreted relative to the position indicated by whence. Values\n" "for whence are:\n" "\n" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -1584,7 +1584,7 @@ if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only - way this can fail to be big-endian UTF-16 if it it's an + way this can fail to be big-endian UTF-16 is if it is an external parsed general entity that's labelled as UTF-16LE. */ diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -230,7 +230,7 @@ } /* _do_ioctl_1() is a private helper function used for the OSS ioctls -- - SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C + SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C like this: ioctl(fd, SNDCTL_DSP_cmd, &arg) diff --git a/Modules/zlib/deflate.c b/Modules/zlib/deflate.c --- a/Modules/zlib/deflate.c +++ b/Modules/zlib/deflate.c @@ -157,7 +157,7 @@ /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ @@ -170,7 +170,7 @@ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive + * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ diff --git a/Modules/zlib/inftrees.h b/Modules/zlib/inftrees.h --- a/Modules/zlib/inftrees.h +++ b/Modules/zlib/inftrees.h @@ -41,7 +41,7 @@ examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. + returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and diff --git a/Modules/zlib/zlib.h b/Modules/zlib/zlib.h --- a/Modules/zlib/zlib.h +++ b/Modules/zlib/zlib.h @@ -812,7 +812,7 @@ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in + success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 22:47:13 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 22:47:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E3=2C_issue_=2317047=3A_remove_doubled_words_fo?= =?utf-8?q?und_in_2=2E7_to_3=2E4?= Message-ID: <3ZPtFY2f2YzRpR@mail.python.org> http://hg.python.org/cpython/rev/4bd13f45d3a2 changeset: 82616:4bd13f45d3a2 parent: 82612:c187c145b4c4 parent: 82615:a42195046e39 user: Terry Jan Reedy date: Mon Mar 11 17:46:07 2013 -0400 summary: Merge 3.3, issue #17047: remove doubled words found in 2.7 to 3.4 Modules/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Modules/_ctypes/callproc.c | 4 ++-- Modules/_ctypes/libffi/src/dlmalloc.c | 12 ++++++------ Modules/_ctypes/libffi/src/ia64/ffi.c | 4 ++-- Modules/_heapqmodule.c | 4 ++-- Modules/_io/iobase.c | 2 +- Modules/expat/xmltok.c | 2 +- Modules/ossaudiodev.c | 2 +- Modules/zlib/deflate.c | 4 ++-- Modules/zlib/inftrees.h | 2 +- Modules/zlib/zlib.h | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -20,8 +20,8 @@ 2. After several checks, _build_callargs() is called which returns another tuple 'callargs'. This may be the same tuple as 'inargs', a slice of - 'inargs', or a completely fresh tuple, depending on several things (is is a - COM method, are 'paramflags' available). + 'inargs', or a completely fresh tuple, depending on several things (is it a + COM method?, are 'paramflags' available?). 3. _build_callargs also calculates bitarrays containing indexes into the callargs tuple, specifying how to build the return value(s) of diff --git a/Modules/_ctypes/libffi/src/dlmalloc.c b/Modules/_ctypes/libffi/src/dlmalloc.c --- a/Modules/_ctypes/libffi/src/dlmalloc.c +++ b/Modules/_ctypes/libffi/src/dlmalloc.c @@ -100,7 +100,7 @@ If you don't like either of these options, you can define CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has + else. And if you are sure that your program using malloc has no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. @@ -607,7 +607,7 @@ declaration needed is the mallinfo struct that is returned (by-copy) by mallinfo(). The malloinfo struct contains a bunch of fields that are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of + instead filled by mallinfo() with other numbers that might be of interest. HAVE_USR_INCLUDE_MALLOC_H should be set if you have a @@ -1621,7 +1621,7 @@ Each freshly allocated chunk must have both cinuse and pinuse set. That is, each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any + ensured by making all allocations from the `lowest' part of any found chunk. Further, no free chunk physically borders another one, so each free chunk is known to be preceded and followed by either inuse chunks or the ends of memory. @@ -1827,12 +1827,12 @@ of the same size are arranged in a circularly-linked list, with only the oldest chunk (the next to be used, in our FIFO ordering) actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node + parent pointer.) If a chunk with the same size as an existing node is inserted, it is linked off the existing node using pointers that work in the same way as fd/bk pointers of small chunks. Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each + smallest is 0x100 <= x < 0x180), which is divided in half at each tree level, with the chunks in the smaller half of the range (0x100 <= x < 0x140 for the top nose) in the left subtree and the larger half (0x140 <= x < 0x180) in the right subtree. This is, of course, @@ -3442,7 +3442,7 @@ least-preferred order): 1. A call to MORECORE that can normally contiguously extend memory. (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) + main space is mmapped or a previous contiguous call failed) 2. A call to MMAP new space (disabled if not HAVE_MMAP). Note that under the default settings, if MORECORE is unable to fulfill a request, and HAVE_MMAP is true, then mmap is diff --git a/Modules/_ctypes/libffi/src/ia64/ffi.c b/Modules/_ctypes/libffi/src/ia64/ffi.c --- a/Modules/_ctypes/libffi/src/ia64/ffi.c +++ b/Modules/_ctypes/libffi/src/ia64/ffi.c @@ -85,7 +85,7 @@ #define ldf_fill(result, addr) \ asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); -/* Return the size of the C type associated with with TYPE. Which will +/* Return the size of the C type associated with TYPE, which will be one of the FFI_IA64_TYPE_HFA_* values. */ static size_t @@ -185,7 +185,7 @@ break; case FFI_TYPE_LONGDOUBLE: - /* Similarly, except that that HFA is true for double extended, + /* Similarly, except that HFA is true for double extended, but not quad precision. Both have sizeof == 16, so tell the difference based on the precision. */ if (LDBL_MANT_DIG == 64 && nested) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -116,7 +116,7 @@ } } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); @@ -456,7 +456,7 @@ childpos = 2*pos + 1; } - /* The leaf at pos is empty now. Put newitem there, and and bubble + /* The leaf at pos is empty now. Put newitem there, and bubble it up to its final resting place (by sifting its parents down). */ Py_DECREF(PyList_GET_ITEM(heap, pos)); PyList_SET_ITEM(heap, pos, newitem); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -76,7 +76,7 @@ PyDoc_STRVAR(iobase_seek_doc, "Change stream position.\n" "\n" - "Change the stream position to byte offset offset. offset is\n" + "Change the stream position to the given byte offset. The offset is\n" "interpreted relative to the position indicated by whence. Values\n" "for whence are:\n" "\n" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -1584,7 +1584,7 @@ if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only - way this can fail to be big-endian UTF-16 if it it's an + way this can fail to be big-endian UTF-16 is if it is an external parsed general entity that's labelled as UTF-16LE. */ diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -230,7 +230,7 @@ } /* _do_ioctl_1() is a private helper function used for the OSS ioctls -- - SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C + SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C like this: ioctl(fd, SNDCTL_DSP_cmd, &arg) diff --git a/Modules/zlib/deflate.c b/Modules/zlib/deflate.c --- a/Modules/zlib/deflate.c +++ b/Modules/zlib/deflate.c @@ -157,7 +157,7 @@ /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ @@ -170,7 +170,7 @@ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive + * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ diff --git a/Modules/zlib/inftrees.h b/Modules/zlib/inftrees.h --- a/Modules/zlib/inftrees.h +++ b/Modules/zlib/inftrees.h @@ -41,7 +41,7 @@ examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. + returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and diff --git a/Modules/zlib/zlib.h b/Modules/zlib/zlib.h --- a/Modules/zlib/zlib.h +++ b/Modules/zlib/zlib.h @@ -812,7 +812,7 @@ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in + success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:00:09 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:00:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_remove_doubled_words_found_in_2=2E7_to_3=2E4_Lib/*=2C?= Message-ID: <3ZPtXT6mDczRhJ@mail.python.org> http://hg.python.org/cpython/rev/cd0191a9b5c9 changeset: 82617:cd0191a9b5c9 branch: 2.7 parent: 82613:e145dddb9d93 user: Terry Jan Reedy date: Mon Mar 11 17:56:17 2013 -0400 summary: Issue #17047: remove doubled words found in 2.7 to 3.4 Lib/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Lib/_pyio.py | 2 +- Lib/distutils/command/install.py | 4 +- Lib/distutils/tests/test_install.py | 2 +- Lib/ftplib.py | 4 +- Lib/idlelib/extend.txt | 4 +- Lib/idlelib/rpc.py | 2 +- Lib/lib-tk/Tix.py | 44 ++++++++-------- Lib/lib-tk/turtle.py | 4 +- Lib/lib2to3/pgen2/grammar.py | 4 +- Lib/msilib/__init__.py | 2 +- Lib/test/test_descrtut.py | 2 +- Lib/test/test_socket.py | 2 +- 12 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -298,7 +298,7 @@ def seek(self, pos, whence=0): """Change stream position. - Change the stream position to byte offset offset. offset is + Change the stream position to byte offset pos. Argument pos is interpreted relative to the position indicated by whence. Values for whence are: diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -265,8 +265,8 @@ if self.user and (self.prefix or self.exec_prefix or self.home or self.install_base or self.install_platbase): - raise DistutilsOptionError("can't combine user with with prefix/" - "exec_prefix/home or install_(plat)base") + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") # Next, stuff that's wrong (or dubious) only on certain platforms. if os.name != "posix": diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -166,7 +166,7 @@ cmd.home = 'home' self.assertRaises(DistutilsOptionError, cmd.finalize_options) - # can't combine user with with prefix/exec_prefix/home or + # can't combine user with prefix/exec_prefix/home or # install_(plat)base cmd.prefix = None cmd.user = 'user' diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -454,7 +454,7 @@ blocksize: The maximum data size to read from fp and send over the connection at once. [default: 8192] callback: An optional single parameter callable that is called on - on each block of data after it is sent. [default: None] + each block of data after it is sent. [default: None] rest: Passed to transfercmd(). [default: None] Returns: @@ -477,7 +477,7 @@ cmd: A STOR command. fp: A file-like object with a readline() method. callback: An optional single parameter callable that is called on - on each line after it is sent. [default: None] + each line after it is sent. [default: None] Returns: The response code. diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt --- a/Lib/idlelib/extend.txt +++ b/Lib/idlelib/extend.txt @@ -54,7 +54,7 @@ implement. (They are also not required to create keybindings, but in that case there must be empty bindings in cofig-extensions.def) -Here is a complete example example: +Here is a complete example: class ZoomHeight: @@ -72,7 +72,7 @@ "...Do what you want here..." The final piece of the puzzle is the file "config-extensions.def", which is -used to to configure the loading of extensions and to establish key (or, more +used to configure the loading of extensions and to establish key (or, more generally, event) bindings to the virtual events defined in the extensions. See the comments at the top of config-extensions.def for information. It's diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -2,7 +2,7 @@ For security reasons, GvR requested that Idle's Python execution server process connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. +only one client per server, this was not a limitation. +---------------------------------+ +-------------+ | SocketServer.BaseRequestHandler | | SocketIO | diff --git a/Lib/lib-tk/Tix.py b/Lib/lib-tk/Tix.py --- a/Lib/lib-tk/Tix.py +++ b/Lib/lib-tk/Tix.py @@ -1902,38 +1902,39 @@ self.tk.call(self, 'set', x, y, *args) def size_column(self, index, **kw): - """Queries or sets the size of the column given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given column. + """Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. INDEX can also be the string "default"; in this case, this command queries or sets the default size of all columns. - When no option-value pair is given, this command returns a tuple - containing the current size setting of the given column. When - option-value pairs are given, the corresponding options of the + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the size setting of the given column are changed. Options may be one - of the follwing: + of the follwing: pad0 pixels Specifies the paddings to the left of a column. pad1 pixels - Specifies the paddings to the right of a column. + Specifies the paddings to the right of a column. size val - Specifies the width of a column . - Val may be: "auto" -- the width of the column is set the - the widest cell in the column; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the width of a column. Val may be: + "auto" -- the width of the column is set to the + width of the widest cell in the column; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the width of the column to the given number of characters.""" return self.tk.split(self.tk.call(self._w, 'size', 'column', index, *self._options({}, kw))) def size_row(self, index, **kw): - """Queries or sets the size of the row given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given row . + """Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . INDEX can also be the string "default"; in this case, this command queries or sets the default size of all rows. - When no option-value pair is given, this command returns a list con- - taining the current size setting of the given row . When option-value + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value pairs are given, the corresponding options of the size setting of the given row are changed. Options may be one of the follwing: pad0 pixels @@ -1941,10 +1942,11 @@ pad1 pixels Specifies the paddings to the bottom of a row. size val - Specifies the height of a row. - Val may be: "auto" -- the height of the row is set the - the highest cell in the row; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the height of a row. Val may be: + "auto" -- the height of the row is set to the + height of the highest cell in the row; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the height of the row to the given number of characters.""" return self.tk.split(self.tk.call( diff --git a/Lib/lib-tk/turtle.py b/Lib/lib-tk/turtle.py --- a/Lib/lib-tk/turtle.py +++ b/Lib/lib-tk/turtle.py @@ -811,8 +811,8 @@ class Terminator (Exception): """Will be raised in TurtleScreen.update, if _RUNNING becomes False. - Thus stops execution of turtle graphics script. Main purpose: use in - in the Demo-Viewer turtle.Demo.py. + This stops execution of a turtle graphics script. + Main purpose: use in the Demo-Viewer turtle.Demo.py. """ pass diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -20,7 +20,7 @@ class Grammar(object): - """Pgen parsing tables tables conversion class. + """Pgen parsing tables conversion class. Once initialized, this class supplies the grammar tables for the parsing engine implemented by parse.py. The parsing engine @@ -45,7 +45,7 @@ these two are each other's inverse. states -- a list of DFAs, where each DFA is a list of - states, each state is is a list of arcs, and each + states, each state is a list of arcs, and each arc is a (i, j) pair where i is a label and j is a state number. The DFA number is the index into this list. (This name is slightly confusing.) diff --git a/Lib/msilib/__init__.py b/Lib/msilib/__init__.py --- a/Lib/msilib/__init__.py +++ b/Lib/msilib/__init__.py @@ -326,7 +326,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -329,7 +329,7 @@ ... return self.__set(inst, value) Now let's define a class with an attribute x defined by a pair of methods, -getx() and and setx(): +getx() and setx(): >>> class C(object): ... diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -415,7 +415,7 @@ # Try same call with optional protocol omitted port2 = socket.getservbyname(service) eq(port, port2) - # Try udp, but don't barf it it doesn't exist + # Try udp, but don't barf if it doesn't exist try: udpport = socket.getservbyname(service, 'udp') except socket.error: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:00:11 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:00:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_remove_doubled_words_found_in_2=2E7_to_3=2E4_Lib/*=2C?= Message-ID: <3ZPtXW4GXFzRkk@mail.python.org> http://hg.python.org/cpython/rev/3f5f961262ec changeset: 82618:3f5f961262ec branch: 3.2 parent: 82614:e9ba9f21a828 user: Terry Jan Reedy date: Mon Mar 11 17:57:08 2013 -0400 summary: Issue #17047: remove doubled words found in 2.7 to 3.4 Lib/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Lib/_pyio.py | 2 +- Lib/concurrent/futures/_base.py | 2 +- Lib/distutils/command/install.py | 4 +- Lib/distutils/tests/test_install.py | 2 +- Lib/ftplib.py | 4 +- Lib/idlelib/extend.txt | 4 +- Lib/idlelib/rpc.py | 2 +- Lib/lib2to3/pgen2/grammar.py | 4 +- Lib/msilib/__init__.py | 2 +- Lib/test/test_descrtut.py | 2 +- Lib/test/test_socket.py | 2 +- Lib/tkinter/tix.py | 44 ++++++++-------- Lib/turtle.py | 4 +- 13 files changed, 40 insertions(+), 38 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -298,7 +298,7 @@ def seek(self, pos, whence=0): """Change stream position. - Change the stream position to byte offset offset. offset is + Change the stream position to byte offset pos. Argument pos is interpreted relative to the position indicated by whence. Values for whence are ints: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -519,7 +519,7 @@ """Returns a iterator equivalent to map(fn, iter). Args: - fn: A callable that will take take as many arguments as there are + fn: A callable that will take as many arguments as there are passed iterables. timeout: The maximum number of seconds to wait. If None, then there is no limit on the wait time. diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -278,8 +278,8 @@ if self.user and (self.prefix or self.exec_prefix or self.home or self.install_base or self.install_platbase): - raise DistutilsOptionError("can't combine user with with prefix/" - "exec_prefix/home or install_(plat)base") + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") # Next, stuff that's wrong (or dubious) only on certain platforms. if os.name != "posix": diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -165,7 +165,7 @@ cmd.home = 'home' self.assertRaises(DistutilsOptionError, cmd.finalize_options) - # can't combine user with with prefix/exec_prefix/home or + # can't combine user with prefix/exec_prefix/home or # install_(plat)base cmd.prefix = None cmd.user = 'user' diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -464,7 +464,7 @@ blocksize: The maximum data size to read from fp and send over the connection at once. [default: 8192] callback: An optional single parameter callable that is called on - on each block of data after it is sent. [default: None] + each block of data after it is sent. [default: None] rest: Passed to transfercmd(). [default: None] Returns: @@ -486,7 +486,7 @@ cmd: A STOR command. fp: A file-like object with a readline() method. callback: An optional single parameter callable that is called on - on each line after it is sent. [default: None] + each line after it is sent. [default: None] Returns: The response code. diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt --- a/Lib/idlelib/extend.txt +++ b/Lib/idlelib/extend.txt @@ -54,7 +54,7 @@ implement. (They are also not required to create keybindings, but in that case there must be empty bindings in cofig-extensions.def) -Here is a complete example example: +Here is a complete example: class ZoomHeight: @@ -72,7 +72,7 @@ "...Do what you want here..." The final piece of the puzzle is the file "config-extensions.def", which is -used to to configure the loading of extensions and to establish key (or, more +used to configure the loading of extensions and to establish key (or, more generally, event) bindings to the virtual events defined in the extensions. See the comments at the top of config-extensions.def for information. It's diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -2,7 +2,7 @@ For security reasons, GvR requested that Idle's Python execution server process connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. +only one client per server, this was not a limitation. +---------------------------------+ +-------------+ | socketserver.BaseRequestHandler | | SocketIO | diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -20,7 +20,7 @@ class Grammar(object): - """Pgen parsing tables tables conversion class. + """Pgen parsing tables conversion class. Once initialized, this class supplies the grammar tables for the parsing engine implemented by parse.py. The parsing engine @@ -45,7 +45,7 @@ these two are each other's inverse. states -- a list of DFAs, where each DFA is a list of - states, each state is is a list of arcs, and each + states, each state is a list of arcs, and each arc is a (i, j) pair where i is a label and j is a state number. The DFA number is the index into this list. (This name is slightly confusing.) diff --git a/Lib/msilib/__init__.py b/Lib/msilib/__init__.py --- a/Lib/msilib/__init__.py +++ b/Lib/msilib/__init__.py @@ -325,7 +325,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -316,7 +316,7 @@ ... return self.__set(inst, value) Now let's define a class with an attribute x defined by a pair of methods, -getx() and and setx(): +getx() and setx(): >>> class C(object): ... diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -442,7 +442,7 @@ # Try same call with optional protocol omitted port2 = socket.getservbyname(service) eq(port, port2) - # Try udp, but don't barf it it doesn't exist + # Try udp, but don't barf if it doesn't exist try: udpport = socket.getservbyname(service, 'udp') except socket.error: diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py --- a/Lib/tkinter/tix.py +++ b/Lib/tkinter/tix.py @@ -1901,38 +1901,39 @@ self.tk.call(self, 'set', x, y, *args) def size_column(self, index, **kw): - """Queries or sets the size of the column given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given column. + """Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. INDEX can also be the string "default"; in this case, this command queries or sets the default size of all columns. - When no option-value pair is given, this command returns a tuple - containing the current size setting of the given column. When - option-value pairs are given, the corresponding options of the + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the size setting of the given column are changed. Options may be one - of the follwing: + of the follwing: pad0 pixels Specifies the paddings to the left of a column. pad1 pixels - Specifies the paddings to the right of a column. + Specifies the paddings to the right of a column. size val - Specifies the width of a column . - Val may be: "auto" -- the width of the column is set the - the widest cell in the column; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the width of a column. Val may be: + "auto" -- the width of the column is set to the + width of the widest cell in the column; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the width of the column to the given number of characters.""" return self.tk.split(self.tk.call(self._w, 'size', 'column', index, *self._options({}, kw))) def size_row(self, index, **kw): - """Queries or sets the size of the row given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given row . + """Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . INDEX can also be the string "default"; in this case, this command queries or sets the default size of all rows. - When no option-value pair is given, this command returns a list con- - taining the current size setting of the given row . When option-value + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value pairs are given, the corresponding options of the size setting of the given row are changed. Options may be one of the follwing: pad0 pixels @@ -1940,10 +1941,11 @@ pad1 pixels Specifies the paddings to the bottom of a row. size val - Specifies the height of a row. - Val may be: "auto" -- the height of the row is set the - the highest cell in the row; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the height of a row. Val may be: + "auto" -- the height of the row is set to the + height of the highest cell in the row; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the height of the row to the given number of characters.""" return self.tk.split(self.tk.call( diff --git a/Lib/turtle.py b/Lib/turtle.py --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -857,8 +857,8 @@ class Terminator (Exception): """Will be raised in TurtleScreen.update, if _RUNNING becomes False. - Thus stops execution of turtle graphics script. Main purpose: use in - in the Demo-Viewer turtle.Demo.py. + This stops execution of a turtle graphics script. + Main purpose: use in the Demo-Viewer turtle.Demo.py. """ pass -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:00:13 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:00:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_3=2E2=2C_issue_=2317047=3A_remove_doubled_words_found_in?= =?utf-8?q?_2=2E7_to?= Message-ID: <3ZPtXY1RnyzRld@mail.python.org> http://hg.python.org/cpython/rev/0547f89aa620 changeset: 82619:0547f89aa620 branch: 3.3 parent: 82615:a42195046e39 parent: 82618:3f5f961262ec user: Terry Jan Reedy date: Mon Mar 11 17:58:27 2013 -0400 summary: Merge 3.2, issue #17047: remove doubled words found in 2.7 to 3.4 Lib/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Lib/_pyio.py | 2 +- Lib/concurrent/futures/_base.py | 2 +- Lib/distutils/command/install.py | 4 +- Lib/distutils/tests/test_install.py | 2 +- Lib/ftplib.py | 4 +- Lib/idlelib/extend.txt | 4 +- Lib/idlelib/rpc.py | 2 +- Lib/lib2to3/pgen2/grammar.py | 4 +- Lib/msilib/__init__.py | 2 +- Lib/test/test_descrtut.py | 2 +- Lib/test/test_socket.py | 2 +- Lib/tkinter/tix.py | 44 ++++++++-------- Lib/turtle.py | 4 +- 13 files changed, 40 insertions(+), 38 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -303,7 +303,7 @@ def seek(self, pos, whence=0): """Change stream position. - Change the stream position to byte offset offset. offset is + Change the stream position to byte offset pos. Argument pos is interpreted relative to the position indicated by whence. Values for whence are ints: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -518,7 +518,7 @@ """Returns a iterator equivalent to map(fn, iter). Args: - fn: A callable that will take take as many arguments as there are + fn: A callable that will take as many arguments as there are passed iterables. timeout: The maximum number of seconds to wait. If None, then there is no limit on the wait time. diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -278,8 +278,8 @@ if self.user and (self.prefix or self.exec_prefix or self.home or self.install_base or self.install_platbase): - raise DistutilsOptionError("can't combine user with with prefix/" - "exec_prefix/home or install_(plat)base") + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") # Next, stuff that's wrong (or dubious) only on certain platforms. if os.name != "posix": diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -165,7 +165,7 @@ cmd.home = 'home' self.assertRaises(DistutilsOptionError, cmd.finalize_options) - # can't combine user with with prefix/exec_prefix/home or + # can't combine user with prefix/exec_prefix/home or # install_(plat)base cmd.prefix = None cmd.user = 'user' diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -466,7 +466,7 @@ blocksize: The maximum data size to read from fp and send over the connection at once. [default: 8192] callback: An optional single parameter callable that is called on - on each block of data after it is sent. [default: None] + each block of data after it is sent. [default: None] rest: Passed to transfercmd(). [default: None] Returns: @@ -488,7 +488,7 @@ cmd: A STOR command. fp: A file-like object with a readline() method. callback: An optional single parameter callable that is called on - on each line after it is sent. [default: None] + each line after it is sent. [default: None] Returns: The response code. diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt --- a/Lib/idlelib/extend.txt +++ b/Lib/idlelib/extend.txt @@ -54,7 +54,7 @@ implement. (They are also not required to create keybindings, but in that case there must be empty bindings in cofig-extensions.def) -Here is a complete example example: +Here is a complete example: class ZoomHeight: @@ -72,7 +72,7 @@ "...Do what you want here..." The final piece of the puzzle is the file "config-extensions.def", which is -used to to configure the loading of extensions and to establish key (or, more +used to configure the loading of extensions and to establish key (or, more generally, event) bindings to the virtual events defined in the extensions. See the comments at the top of config-extensions.def for information. It's diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -2,7 +2,7 @@ For security reasons, GvR requested that Idle's Python execution server process connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. +only one client per server, this was not a limitation. +---------------------------------+ +-------------+ | socketserver.BaseRequestHandler | | SocketIO | diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -20,7 +20,7 @@ class Grammar(object): - """Pgen parsing tables tables conversion class. + """Pgen parsing tables conversion class. Once initialized, this class supplies the grammar tables for the parsing engine implemented by parse.py. The parsing engine @@ -45,7 +45,7 @@ these two are each other's inverse. states -- a list of DFAs, where each DFA is a list of - states, each state is is a list of arcs, and each + states, each state is a list of arcs, and each arc is a (i, j) pair where i is a label and j is a state number. The DFA number is the index into this list. (This name is slightly confusing.) diff --git a/Lib/msilib/__init__.py b/Lib/msilib/__init__.py --- a/Lib/msilib/__init__.py +++ b/Lib/msilib/__init__.py @@ -325,7 +325,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -319,7 +319,7 @@ ... return self.__set(inst, value) Now let's define a class with an attribute x defined by a pair of methods, -getx() and and setx(): +getx() and setx(): >>> class C(object): ... diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -842,7 +842,7 @@ # Try same call with optional protocol omitted port2 = socket.getservbyname(service) eq(port, port2) - # Try udp, but don't barf it it doesn't exist + # Try udp, but don't barf if it doesn't exist try: udpport = socket.getservbyname(service, 'udp') except socket.error: diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py --- a/Lib/tkinter/tix.py +++ b/Lib/tkinter/tix.py @@ -1901,38 +1901,39 @@ self.tk.call(self, 'set', x, y, *args) def size_column(self, index, **kw): - """Queries or sets the size of the column given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given column. + """Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. INDEX can also be the string "default"; in this case, this command queries or sets the default size of all columns. - When no option-value pair is given, this command returns a tuple - containing the current size setting of the given column. When - option-value pairs are given, the corresponding options of the + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the size setting of the given column are changed. Options may be one - of the follwing: + of the follwing: pad0 pixels Specifies the paddings to the left of a column. pad1 pixels - Specifies the paddings to the right of a column. + Specifies the paddings to the right of a column. size val - Specifies the width of a column . - Val may be: "auto" -- the width of the column is set the - the widest cell in the column; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the width of a column. Val may be: + "auto" -- the width of the column is set to the + width of the widest cell in the column; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the width of the column to the given number of characters.""" return self.tk.split(self.tk.call(self._w, 'size', 'column', index, *self._options({}, kw))) def size_row(self, index, **kw): - """Queries or sets the size of the row given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given row . + """Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . INDEX can also be the string "default"; in this case, this command queries or sets the default size of all rows. - When no option-value pair is given, this command returns a list con- - taining the current size setting of the given row . When option-value + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value pairs are given, the corresponding options of the size setting of the given row are changed. Options may be one of the follwing: pad0 pixels @@ -1940,10 +1941,11 @@ pad1 pixels Specifies the paddings to the bottom of a row. size val - Specifies the height of a row. - Val may be: "auto" -- the height of the row is set the - the highest cell in the row; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the height of a row. Val may be: + "auto" -- the height of the row is set to the + height of the highest cell in the row; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the height of the row to the given number of characters.""" return self.tk.split(self.tk.call( diff --git a/Lib/turtle.py b/Lib/turtle.py --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -856,8 +856,8 @@ class Terminator (Exception): """Will be raised in TurtleScreen.update, if _RUNNING becomes False. - Thus stops execution of turtle graphics script. Main purpose: use in - in the Demo-Viewer turtle.Demo.py. + This stops execution of a turtle graphics script. + Main purpose: use in the Demo-Viewer turtle.Demo.py. """ pass -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:00:14 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:00:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E3=2C_issue_=2317047=3A_remove_doubled_words_fo?= =?utf-8?q?und_in_2=2E7_to?= Message-ID: <3ZPtXZ5rVyzRld@mail.python.org> http://hg.python.org/cpython/rev/01aa93888917 changeset: 82620:01aa93888917 parent: 82616:4bd13f45d3a2 parent: 82619:0547f89aa620 user: Terry Jan Reedy date: Mon Mar 11 17:59:07 2013 -0400 summary: Merge 3.3, issue #17047: remove doubled words found in 2.7 to 3.4 Lib/*, as reported by Serhiy Storchaka and Matthew Barnett. files: Lib/_pyio.py | 2 +- Lib/concurrent/futures/_base.py | 2 +- Lib/distutils/command/install.py | 4 +- Lib/distutils/tests/test_install.py | 2 +- Lib/ftplib.py | 4 +- Lib/idlelib/extend.txt | 4 +- Lib/idlelib/rpc.py | 2 +- Lib/lib2to3/pgen2/grammar.py | 4 +- Lib/msilib/__init__.py | 2 +- Lib/test/test_descrtut.py | 2 +- Lib/test/test_socket.py | 2 +- Lib/tkinter/tix.py | 44 ++++++++-------- Lib/turtle.py | 4 +- 13 files changed, 40 insertions(+), 38 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -303,7 +303,7 @@ def seek(self, pos, whence=0): """Change stream position. - Change the stream position to byte offset offset. offset is + Change the stream position to byte offset pos. Argument pos is interpreted relative to the position indicated by whence. Values for whence are ints: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -517,7 +517,7 @@ """Returns a iterator equivalent to map(fn, iter). Args: - fn: A callable that will take take as many arguments as there are + fn: A callable that will take as many arguments as there are passed iterables. timeout: The maximum number of seconds to wait. If None, then there is no limit on the wait time. diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -263,8 +263,8 @@ if self.user and (self.prefix or self.exec_prefix or self.home or self.install_base or self.install_platbase): - raise DistutilsOptionError("can't combine user with with prefix/" - "exec_prefix/home or install_(plat)base") + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") # Next, stuff that's wrong (or dubious) only on certain platforms. if os.name != "posix": diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -165,7 +165,7 @@ cmd.home = 'home' self.assertRaises(DistutilsOptionError, cmd.finalize_options) - # can't combine user with with prefix/exec_prefix/home or + # can't combine user with prefix/exec_prefix/home or # install_(plat)base cmd.prefix = None cmd.user = 'user' diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -486,7 +486,7 @@ blocksize: The maximum data size to read from fp and send over the connection at once. [default: 8192] callback: An optional single parameter callable that is called on - on each block of data after it is sent. [default: None] + each block of data after it is sent. [default: None] rest: Passed to transfercmd(). [default: None] Returns: @@ -513,7 +513,7 @@ cmd: A STOR command. fp: A file-like object with a readline() method. callback: An optional single parameter callable that is called on - on each line after it is sent. [default: None] + each line after it is sent. [default: None] Returns: The response code. diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt --- a/Lib/idlelib/extend.txt +++ b/Lib/idlelib/extend.txt @@ -54,7 +54,7 @@ implement. (They are also not required to create keybindings, but in that case there must be empty bindings in cofig-extensions.def) -Here is a complete example example: +Here is a complete example: class ZoomHeight: @@ -72,7 +72,7 @@ "...Do what you want here..." The final piece of the puzzle is the file "config-extensions.def", which is -used to to configure the loading of extensions and to establish key (or, more +used to configure the loading of extensions and to establish key (or, more generally, event) bindings to the virtual events defined in the extensions. See the comments at the top of config-extensions.def for information. It's diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -2,7 +2,7 @@ For security reasons, GvR requested that Idle's Python execution server process connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. +only one client per server, this was not a limitation. +---------------------------------+ +-------------+ | socketserver.BaseRequestHandler | | SocketIO | diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -20,7 +20,7 @@ class Grammar(object): - """Pgen parsing tables tables conversion class. + """Pgen parsing tables conversion class. Once initialized, this class supplies the grammar tables for the parsing engine implemented by parse.py. The parsing engine @@ -45,7 +45,7 @@ these two are each other's inverse. states -- a list of DFAs, where each DFA is a list of - states, each state is is a list of arcs, and each + states, each state is a list of arcs, and each arc is a (i, j) pair where i is a label and j is a state number. The DFA number is the index into this list. (This name is slightly confusing.) diff --git a/Lib/msilib/__init__.py b/Lib/msilib/__init__.py --- a/Lib/msilib/__init__.py +++ b/Lib/msilib/__init__.py @@ -325,7 +325,7 @@ def add_file(self, file, src=None, version=None, language=None): """Add a file to the current component of the directory, starting a new one - one if there is no current component. By default, the file name in the source + if there is no current component. By default, the file name in the source and the file table will be identical. If the src file is specified, it is interpreted relative to the current directory. Optionally, a version and a language can be specified for the entry in the File table.""" diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -319,7 +319,7 @@ ... return self.__set(inst, value) Now let's define a class with an attribute x defined by a pair of methods, -getx() and and setx(): +getx() and setx(): >>> class C(object): ... diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -872,7 +872,7 @@ # Try same call with optional protocol omitted port2 = socket.getservbyname(service) eq(port, port2) - # Try udp, but don't barf it it doesn't exist + # Try udp, but don't barf if it doesn't exist try: udpport = socket.getservbyname(service, 'udp') except OSError: diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py --- a/Lib/tkinter/tix.py +++ b/Lib/tkinter/tix.py @@ -1901,38 +1901,39 @@ self.tk.call(self, 'set', x, y, *args) def size_column(self, index, **kw): - """Queries or sets the size of the column given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given column. + """Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. INDEX can also be the string "default"; in this case, this command queries or sets the default size of all columns. - When no option-value pair is given, this command returns a tuple - containing the current size setting of the given column. When - option-value pairs are given, the corresponding options of the + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the size setting of the given column are changed. Options may be one - of the follwing: + of the follwing: pad0 pixels Specifies the paddings to the left of a column. pad1 pixels - Specifies the paddings to the right of a column. + Specifies the paddings to the right of a column. size val - Specifies the width of a column . - Val may be: "auto" -- the width of the column is set the - the widest cell in the column; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the width of a column. Val may be: + "auto" -- the width of the column is set to the + width of the widest cell in the column; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the width of the column to the given number of characters.""" return self.tk.split(self.tk.call(self._w, 'size', 'column', index, *self._options({}, kw))) def size_row(self, index, **kw): - """Queries or sets the size of the row given by - INDEX. INDEX may be any non-negative - integer that gives the position of a given row . + """Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . INDEX can also be the string "default"; in this case, this command queries or sets the default size of all rows. - When no option-value pair is given, this command returns a list con- - taining the current size setting of the given row . When option-value + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value pairs are given, the corresponding options of the size setting of the given row are changed. Options may be one of the follwing: pad0 pixels @@ -1940,10 +1941,11 @@ pad1 pixels Specifies the paddings to the bottom of a row. size val - Specifies the height of a row. - Val may be: "auto" -- the height of the row is set the - the highest cell in the row; a valid Tk screen distance - unit; or a real number following by the word chars + Specifies the height of a row. Val may be: + "auto" -- the height of the row is set to the + height of the highest cell in the row; + a valid Tk screen distance unit; + or a real number following by the word chars (e.g. 3.4chars) that sets the height of the row to the given number of characters.""" return self.tk.split(self.tk.call( diff --git a/Lib/turtle.py b/Lib/turtle.py --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -856,8 +856,8 @@ class Terminator (Exception): """Will be raised in TurtleScreen.update, if _RUNNING becomes False. - Thus stops execution of turtle graphics script. Main purpose: use in - in the Demo-Viewer turtle.Demo.py. + This stops execution of a turtle graphics script. + Main purpose: use in the Demo-Viewer turtle.Demo.py. """ pass -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:40:13 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:40:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_remove_doubled_words_added_in_3=2E3?= Message-ID: <3ZPvQj6jhWzRYr@mail.python.org> http://hg.python.org/cpython/rev/e9ada209b67f changeset: 82621:e9ada209b67f branch: 3.3 parent: 82619:0547f89aa620 user: Terry Jan Reedy date: Mon Mar 11 18:34:00 2013 -0400 summary: Issue #17047: remove doubled words added in 3.3 as reported by Serhiy Storchaka and Matthew Barnett. files: Doc/library/email.policy.rst | 2 +- Doc/library/ipaddress.rst | 6 +++--- Doc/library/stdtypes.rst | 2 +- Doc/library/unittest.mock.rst | 2 +- Lib/email/_encoded_words.py | 2 +- Lib/email/_header_value_parser.py | 2 +- Lib/email/mime/text.py | 2 +- Lib/email/policy.py | 2 +- Lib/test/test_decimal.py | 2 +- Lib/tkinter/__init__.py | 2 +- Lib/unittest/mock.py | 2 +- Modules/socketmodule.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -327,7 +327,7 @@ each resulting line to the ``max_line_length``. If ``cte_type`` is ``7bit``, non-ascii binary data is CTE encoded using the ``unknown-8bit`` charset. Otherwise the original source header is used, with its existing - line breaks and and any (RFC invalid) binary data it may contain. + line breaks and any (RFC invalid) binary data it may contain. .. note:: diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -393,7 +393,7 @@ .. attribute:: is_link_local These attributes are true for the network as a whole if they are true - true for both the network address and the broadcast address + for both the network address and the broadcast address .. attribute:: network_address @@ -452,7 +452,7 @@ .. method:: overlaps(other) ``True`` if this network is partly or wholly contained in *other* or - or *other* is wholly contained in this network. + *other* is wholly contained in this network. .. method:: address_exclude(network) @@ -582,7 +582,7 @@ .. attribute:: is_site_local These attribute is true for the network as a whole if it is true - true for both the network address and the broadcast address + for both the network address and the broadcast address Operators diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2637,7 +2637,7 @@ >>> z.nbytes 48 - Cast 1D/unsigned char to to 2D/unsigned long:: + Cast 1D/unsigned char to 2D/unsigned long:: >>> buf = struct.pack("L"*6, *list(range(6))) >>> x = memoryview(buf) 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 @@ -988,7 +988,7 @@ you pass in `create=True`, and the attribute doesn't exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards. This is useful for writing tests against - attributes that your production code creates at runtime. It is off by by + attributes that your production code creates at runtime. It is off by default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py --- a/Lib/email/_encoded_words.py +++ b/Lib/email/_encoded_words.py @@ -14,7 +14,7 @@ # cte (Content Transfer Encoding) is either 'q' or 'b' (ignoring case). In # theory other letters could be used for other encodings, but in practice this # (almost?) never happens. There could be a public API for adding entries -# to to the CTE tables, but YAGNI for now. 'q' is Quoted Printable, 'b' is +# to the CTE tables, but YAGNI for now. 'q' is Quoted Printable, 'b' is # Base64. The meaning of encoded_string should be obvious. 'lang' is optional # as indicated by the brackets (they are not part of the syntax) but is almost # never encountered in practice. diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1864,7 +1864,7 @@ """ dtext = / obs-dtext obs-dtext = obs-NO-WS-CTL / quoted-pair - We allow anything except the excluded characters, but but if we find any + We allow anything except the excluded characters, but if we find any ASCII other than the RFC defined printable ASCII an NonPrintableDefect is added to the token's defects list. Quoted pairs are converted to their unquoted values, so what is returned is a ptext token, in this case a diff --git a/Lib/email/mime/text.py b/Lib/email/mime/text.py --- a/Lib/email/mime/text.py +++ b/Lib/email/mime/text.py @@ -26,7 +26,7 @@ Content-Transfer-Encoding header will also be set. """ - # If no _charset was specified, check to see see if there are non-ascii + # If no _charset was specified, check to see if there are non-ascii # characters present. If not, use 'us-ascii', otherwise use utf-8. # XXX: This can be removed once #7304 is fixed. if _charset is None: diff --git a/Lib/email/policy.py b/Lib/email/policy.py --- a/Lib/email/policy.py +++ b/Lib/email/policy.py @@ -23,7 +23,7 @@ """+ PROVISIONAL - The API extensions enabled by this this policy are currently provisional. + The API extensions enabled by this policy are currently provisional. Refer to the documentation for details. This policy adds new header parsing and folding algorithms. Instead of diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4492,7 +4492,7 @@ x = Decimal(2**578) ** Decimal("-0.5") def test_py_immutability_operations(self): - # Do operations and check that it didn't change change internal objects. + # Do operations and check that it didn't change internal objects. Decimal = P.Decimal DefaultContext = P.DefaultContext setcontext = P.setcontext diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -3152,7 +3152,7 @@ def peer_create(self, newPathName, cnf={}, **kw): # new in Tk 8.5 """Creates a peer text widget with the given newPathName, and any optional standard configuration options. By default the peer will - have the same start and and end line as the parent widget, but + have the same start and end line as the parent widget, but these can be overriden with the standard configuration options.""" self.tk.call(self._w, 'peer', 'create', newPathName, *self._options(cnf, kw)) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1417,7 +1417,7 @@ you pass in `create=True`, and the attribute doesn't exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards. This is useful for writing tests against - attributes that your production code creates at runtime. It is off by by + attributes that your production code creates at runtime. It is off by default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3609,7 +3609,7 @@ the next header, it checks its (uninitialized) cmsg_len member to see if the "message" fits in the buffer, and returns NULL if it doesn't. Zero-filling the buffer - ensures that that doesn't happen. */ + ensures that this doesn't happen. */ memset(controlbuf, 0, controllen); for (i = 0; i < ncmsgbufs; i++) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:40:15 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:40:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3=2C_issue_=2317047=3A_remove_doubled_wor?= =?utf-8?q?ds_added_in_3=2E3=2C?= Message-ID: <3ZPvQl5PjRzRkk@mail.python.org> http://hg.python.org/cpython/rev/908d45fdbecd changeset: 82622:908d45fdbecd parent: 82620:01aa93888917 parent: 82621:e9ada209b67f user: Terry Jan Reedy date: Mon Mar 11 18:36:38 2013 -0400 summary: Merge with 3.3, issue #17047: remove doubled words added in 3.3, as reported by Serhiy Storchaka and Matthew Barnett. files: Doc/library/email.policy.rst | 2 +- Doc/library/ipaddress.rst | 6 +++--- Doc/library/stdtypes.rst | 2 +- Doc/library/unittest.mock.rst | 2 +- Lib/email/_encoded_words.py | 2 +- Lib/email/_header_value_parser.py | 2 +- Lib/email/mime/text.py | 2 +- Lib/email/policy.py | 2 +- Lib/test/test_decimal.py | 2 +- Lib/tkinter/__init__.py | 2 +- Lib/unittest/mock.py | 2 +- Modules/socketmodule.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -327,7 +327,7 @@ each resulting line to the ``max_line_length``. If ``cte_type`` is ``7bit``, non-ascii binary data is CTE encoded using the ``unknown-8bit`` charset. Otherwise the original source header is used, with its existing - line breaks and and any (RFC invalid) binary data it may contain. + line breaks and any (RFC invalid) binary data it may contain. .. note:: diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -393,7 +393,7 @@ .. attribute:: is_link_local These attributes are true for the network as a whole if they are true - true for both the network address and the broadcast address + for both the network address and the broadcast address .. attribute:: network_address @@ -452,7 +452,7 @@ .. method:: overlaps(other) ``True`` if this network is partly or wholly contained in *other* or - or *other* is wholly contained in this network. + *other* is wholly contained in this network. .. method:: address_exclude(network) @@ -582,7 +582,7 @@ .. attribute:: is_site_local These attribute is true for the network as a whole if it is true - true for both the network address and the broadcast address + for both the network address and the broadcast address Operators diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2637,7 +2637,7 @@ >>> z.nbytes 48 - Cast 1D/unsigned char to to 2D/unsigned long:: + Cast 1D/unsigned char to 2D/unsigned long:: >>> buf = struct.pack("L"*6, *list(range(6))) >>> x = memoryview(buf) 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 @@ -1008,7 +1008,7 @@ you pass in `create=True`, and the attribute doesn't exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards. This is useful for writing tests against - attributes that your production code creates at runtime. It is off by by + attributes that your production code creates at runtime. It is off by default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py --- a/Lib/email/_encoded_words.py +++ b/Lib/email/_encoded_words.py @@ -14,7 +14,7 @@ # cte (Content Transfer Encoding) is either 'q' or 'b' (ignoring case). In # theory other letters could be used for other encodings, but in practice this # (almost?) never happens. There could be a public API for adding entries -# to to the CTE tables, but YAGNI for now. 'q' is Quoted Printable, 'b' is +# to the CTE tables, but YAGNI for now. 'q' is Quoted Printable, 'b' is # Base64. The meaning of encoded_string should be obvious. 'lang' is optional # as indicated by the brackets (they are not part of the syntax) but is almost # never encountered in practice. diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1863,7 +1863,7 @@ """ dtext = / obs-dtext obs-dtext = obs-NO-WS-CTL / quoted-pair - We allow anything except the excluded characters, but but if we find any + We allow anything except the excluded characters, but if we find any ASCII other than the RFC defined printable ASCII an NonPrintableDefect is added to the token's defects list. Quoted pairs are converted to their unquoted values, so what is returned is a ptext token, in this case a diff --git a/Lib/email/mime/text.py b/Lib/email/mime/text.py --- a/Lib/email/mime/text.py +++ b/Lib/email/mime/text.py @@ -26,7 +26,7 @@ Content-Transfer-Encoding header will also be set. """ - # If no _charset was specified, check to see see if there are non-ascii + # If no _charset was specified, check to see if there are non-ascii # characters present. If not, use 'us-ascii', otherwise use utf-8. # XXX: This can be removed once #7304 is fixed. if _charset is None: diff --git a/Lib/email/policy.py b/Lib/email/policy.py --- a/Lib/email/policy.py +++ b/Lib/email/policy.py @@ -23,7 +23,7 @@ """+ PROVISIONAL - The API extensions enabled by this this policy are currently provisional. + The API extensions enabled by this policy are currently provisional. Refer to the documentation for details. This policy adds new header parsing and folding algorithms. Instead of diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4492,7 +4492,7 @@ x = Decimal(2**578) ** Decimal("-0.5") def test_py_immutability_operations(self): - # Do operations and check that it didn't change change internal objects. + # Do operations and check that it didn't change internal objects. Decimal = P.Decimal DefaultContext = P.DefaultContext setcontext = P.setcontext diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -3113,7 +3113,7 @@ def peer_create(self, newPathName, cnf={}, **kw): # new in Tk 8.5 """Creates a peer text widget with the given newPathName, and any optional standard configuration options. By default the peer will - have the same start and and end line as the parent widget, but + have the same start and end line as the parent widget, but these can be overriden with the standard configuration options.""" self.tk.call(self._w, 'peer', 'create', newPathName, *self._options(cnf, kw)) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1444,7 +1444,7 @@ you pass in `create=True`, and the attribute doesn't exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards. This is useful for writing tests against - attributes that your production code creates at runtime. It is off by by + attributes that your production code creates at runtime. It is off by default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3546,7 +3546,7 @@ the next header, it checks its (uninitialized) cmsg_len member to see if the "message" fits in the buffer, and returns NULL if it doesn't. Zero-filling the buffer - ensures that that doesn't happen. */ + ensures that this doesn't happen. */ memset(controlbuf, 0, controllen); for (i = 0; i < ncmsgbufs; i++) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Mar 11 23:40:17 2013 From: python-checkins at python.org (terry.reedy) Date: Mon, 11 Mar 2013 23:40:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317047=3A_remove_d?= =?utf-8?q?oubled_words_added_in_3=2E4=2C?= Message-ID: <3ZPvQn1VCjzRty@mail.python.org> http://hg.python.org/cpython/rev/0a26a8b13193 changeset: 82623:0a26a8b13193 user: Terry Jan Reedy date: Mon Mar 11 18:38:13 2013 -0400 summary: Issue #17047: remove doubled words added in 3.4, as reported by Serhiy Storchaka and Matthew Barnett. files: Doc/library/ssl.rst | 2 +- Include/pyport.h | 2 +- Lib/argparse.py | 2 +- Misc/HISTORY | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -824,7 +824,7 @@ will not contain return meaningful values nor can they be called safely. The *server_name_callback* function must return ``None`` to allow the - the TLS negotiation to continue. If a TLS failure is required, a constant + TLS negotiation to continue. If a TLS failure is required, a constant :const:`ALERT_DESCRIPTION_* ` can be returned. Other return values will result in a TLS fatal error with :const:`ALERT_DESCRIPTION_INTERNAL_ERROR`. diff --git a/Include/pyport.h b/Include/pyport.h --- a/Include/pyport.h +++ b/Include/pyport.h @@ -881,7 +881,7 @@ /* * Convenient macros to deal with endianness of the platform. WORDS_BIGENDIAN is * detected by configure and defined in pyconfig.h. The code in pyconfig.h - * also also takes care of Apple's universal builds. + * also takes care of Apple's universal builds. */ #ifdef WORDS_BIGENDIAN diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1141,7 +1141,7 @@ - bufsize -- The file's desired buffer size. Accepts the same values as the builtin open() function. - encoding -- The file's encoding. Accepts the same values as the - the builtin open() function. + builtin open() function. - errors -- A string indicating how encoding and decoding errors are to be handled. Accepts the same value as the builtin open() function. """ diff --git a/Misc/HISTORY b/Misc/HISTORY --- a/Misc/HISTORY +++ b/Misc/HISTORY @@ -778,7 +778,7 @@ - Issue #14626: Large refactoring of functions / parameters in the os module. Many functions now support "dir_fd" and "follow_symlinks" parameters; - some also support accepting an open file descriptor in place of of a path + some also support accepting an open file descriptor in place of a path string. Added os.support_* collections as LBYL helpers. Removed many functions only previously seen in 3.3 alpha releases (often starting with "f" or "l", or ending with "at"). Originally suggested by Serhiy Storchaka; @@ -1412,7 +1412,7 @@ - Issue #14399: zipfile now recognizes that the archive has been modified even if only the comment is changed. In addition, the TypeError that results from - trying to set a non-binary value as a comment is now now raised at the time + trying to set a non-binary value as a comment is now raised at the time the comment is set rather than at the time the zipfile is written. - trace.CoverageResults.is_ignored_filename() now ignores any name that starts @@ -3052,7 +3052,7 @@ check or set the MACOSX_DEPLOYMENT_TARGET environment variable for the interpreter process. This could cause failures in non-Distutils subprocesses and was unreliable since tests or user programs could modify the interpreter - environment after Distutils set it. Instead, have Distutils set the the + environment after Distutils set it. Instead, have Distutils set the deployment target only in the environment of each build subprocess. It is still possible to globally override the default by setting MACOSX_DEPLOYMENT_TARGET before launching the interpreter; its value must be -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 04:06:34 2013 From: python-checkins at python.org (daniel.holth) Date: Tue, 12 Mar 2013 04:06:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_425=3A_enlarge_FAQ?= Message-ID: <3ZQ1L225MnzQP9@mail.python.org> http://hg.python.org/peps/rev/c842f2fd7170 changeset: 4793:c842f2fd7170 user: Daniel Holth date: Mon Mar 11 23:06:02 2013 -0400 summary: PEP 425: enlarge FAQ files: pep-0425.txt | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/pep-0425.txt b/pep-0425.txt --- a/pep-0425.txt +++ b/pep-0425.txt @@ -259,6 +259,14 @@ too, but with longer tags. Recall that all "pure Python" built distributions just use 'py'. +Why is the ABI tag (the second tag) sometimes "none" in the reference implementation? + Since Python 2 does not have an easy way to get to the SOABI + (the concept comes from newer versions of Python 3) the reference + implentation at the time of writing guesses "none". Ideally it + would detect "py27(d|m|u)" analagous to newer versions of Python, + but in the meantime "none" is a good enough way to say "don't know". + + References ========== @@ -275,7 +283,7 @@ ================ The author thanks Paul Moore, Nick Coghlan, Mark Abramowitz, and -Mr. Michele Lacchia for their valuable advice and help with this effort. +Mr. Michele Lacchia for their valuable help and advice. Copyright ========= -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Tue Mar 12 05:58:54 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 12 Mar 2013 05:58:54 +0100 Subject: [Python-checkins] Daily reference leaks (0a26a8b13193): sum=2 Message-ID: results for 0a26a8b13193 on branch "default" -------------------------------------------- test_support leaked [0, -1, 1] references, sum=0 test_support leaked [0, -1, 3] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogE47LGT', '-x'] From python-checkins at python.org Tue Mar 12 06:50:24 2013 From: python-checkins at python.org (terry.reedy) Date: Tue, 12 Mar 2013 06:50:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NzA3?= =?utf-8?q?=3A_add_news_entry?= Message-ID: <3ZQ4z44QVLzRXr@mail.python.org> http://hg.python.org/cpython/rev/c162e2ff15bd changeset: 82624:c162e2ff15bd branch: 2.7 parent: 82617:cd0191a9b5c9 user: Terry Jan Reedy date: Tue Mar 12 01:26:28 2013 -0400 summary: Issue #14707: add news entry files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -944,6 +944,9 @@ Documentation ------------- +- Issue #14707: remove doubled words in docs and docstrings + reported by Serhiy Storchaka and Matthew Barnett. + - Issue #16406: combine the pages for uploading and registering to PyPI. - Issue #16403: Document how distutils uses the maintainer field in -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 06:51:05 2013 From: python-checkins at python.org (ezio.melotti) Date: Tue, 12 Mar 2013 06:51:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MDY2OiB0ZXN0?= =?utf-8?q?=5Frobotparser_now_works_with_unittest_test_discovery=2E__Patch?= =?utf-8?q?_by?= Message-ID: <3ZQ4zs2CstzRXr@mail.python.org> http://hg.python.org/cpython/rev/fa051c6276a0 changeset: 82625:fa051c6276a0 branch: 3.3 parent: 82621:e9ada209b67f user: Ezio Melotti date: Tue Mar 12 07:49:12 2013 +0200 summary: #17066: test_robotparser now works with unittest test discovery. Patch by Zachary Ware. files: Lib/test/test_robotparser.py | 16 ++++++++++------ Misc/NEWS | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -6,7 +6,10 @@ from test import support class RobotTestCase(unittest.TestCase): - def __init__(self, index, parser, url, good, agent): + def __init__(self, index=None, parser=None, url=None, good=None, agent=None): + # workaround to make unittest discovery work (see #17066) + if not isinstance(index, int): + return unittest.TestCase.__init__(self) if good: self.str = "RobotTest(%d, good, %s)" % (index, url) @@ -269,10 +272,11 @@ self.assertTrue( parser.can_fetch("*", "http://www.python.org/robots.txt")) -def test_main(): - support.run_unittest(NetworkTestCase) - support.run_unittest(tests) +def load_tests(loader, suite, pattern): + suite = unittest.makeSuite(NetworkTestCase) + suite.addTest(tests) + return suite if __name__=='__main__': - support.verbose = 1 - test_main() + support.use_resources = ['network'] + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -662,6 +662,9 @@ - Issue #15539: Added regression tests for Tools/scripts/pindent.py. +- Issue #17066: test_robotparser now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17334: test_index now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 06:51:06 2013 From: python-checkins at python.org (ezio.melotti) Date: Tue, 12 Mar 2013 06:51:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MDY2OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZQ4zt4tkPzRgm@mail.python.org> http://hg.python.org/cpython/rev/8fdce849d0b3 changeset: 82626:8fdce849d0b3 parent: 82623:0a26a8b13193 parent: 82625:fa051c6276a0 user: Ezio Melotti date: Tue Mar 12 07:50:53 2013 +0200 summary: #17066: merge with 3.3. files: Lib/test/test_robotparser.py | 16 ++++++++++------ Misc/NEWS | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -6,7 +6,10 @@ from test import support class RobotTestCase(unittest.TestCase): - def __init__(self, index, parser, url, good, agent): + def __init__(self, index=None, parser=None, url=None, good=None, agent=None): + # workaround to make unittest discovery work (see #17066) + if not isinstance(index, int): + return unittest.TestCase.__init__(self) if good: self.str = "RobotTest(%d, good, %s)" % (index, url) @@ -269,10 +272,11 @@ self.assertTrue( parser.can_fetch("*", "http://www.python.org/robots.txt")) -def test_main(): - support.run_unittest(NetworkTestCase) - support.run_unittest(tests) +def load_tests(loader, suite, pattern): + suite = unittest.makeSuite(NetworkTestCase) + suite.addTest(tests) + return suite if __name__=='__main__': - support.verbose = 1 - test_main() + support.use_resources = ['network'] + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -934,6 +934,9 @@ - Issue #16836: Enable IPv6 support even if IPv6 is disabled on the build host. +- Issue #17066: test_robotparser now works with unittest test discovery. + Patch by Zachary Ware. + - Issue #17334: test_index now works with unittest test discovery. Patch by Zachary Ware. -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Tue Mar 12 07:14:58 2013 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 12 Mar 2013 02:14:58 -0400 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <3ZQ4z44QVLzRXr@mail.python.org> References: <3ZQ4z44QVLzRXr@mail.python.org> Message-ID: <513EC7E2.90400@udel.edu> On 3/12/2013 1:50 AM, terry.reedy wrote: > http://hg.python.org/cpython/rev/c162e2ff15bd > changeset: 82624:c162e2ff15bd > branch: 2.7 > parent: 82617:cd0191a9b5c9 > user: Terry Jan Reedy > date: Tue Mar 12 01:26:28 2013 -0400 > summary: > Issue #14707: add news entry > > files: > Misc/NEWS | 3 +++ > 1 files changed, 3 insertions(+), 0 deletions(-) > > > diff --git a/Misc/NEWS b/Misc/NEWS > --- a/Misc/NEWS > +++ b/Misc/NEWS > @@ -944,6 +944,9 @@ > Documentation > ------------- > > +- Issue #14707: remove doubled words in docs and docstrings > + reported by Serhiy Storchaka and Matthew Barnett. > + > - Issue #16406: combine the pages for uploading and registering to PyPI. > > - Issue #16403: Document how distutils uses the maintainer field in The above was easy. When I tried to transplant this patch to 3.2, export and import, or directly edit 3.2 NEWS with Notepad++ or IDLE, hg makes a 319kb patch that deletes and add the entire file in chunks. I did not think I should commit and push that. The failure of transplant and import are perhaps understandable because 3.2 has a gratuitous case difference with /combine/Combine/. - Issue #16406: Combine the pages for uploading and registering to PyPI. But the inability to make a proper diff from direct edit is something else. If I add just a single blank line, even that generates a mega patch. Same with 3.3 NEWS. I also tried deleting the file to make hg regenerate from the repository database. Anyone have any idea what the problem is? Has anything changed with hg, windows, line endings and this text file in the last few months? I just pushed patches for about 20 scattered files in Docs, Lib, Modules, and Tools earlier today, so the problem seems to be specific to NEWS. tjr From python-checkins at python.org Tue Mar 12 07:19:45 2013 From: python-checkins at python.org (terry.reedy) Date: Tue, 12 Mar 2013 07:19:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_issue_numb?= =?utf-8?q?er?= Message-ID: <3ZQ5cx53sXzR5F@mail.python.org> http://hg.python.org/cpython/rev/a1bebf2c33e7 changeset: 82627:a1bebf2c33e7 branch: 2.7 parent: 82624:c162e2ff15bd user: Terry Jan Reedy date: Tue Mar 12 02:19:09 2013 -0400 summary: Fix issue number 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 @@ -944,7 +944,7 @@ Documentation ------------- -- Issue #14707: remove doubled words in docs and docstrings +- Issue #17047: remove doubled words in docs and docstrings reported by Serhiy Storchaka and Matthew Barnett. - Issue #16406: combine the pages for uploading and registering to PyPI. -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Tue Mar 12 07:28:11 2013 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 12 Mar 2013 02:28:11 -0400 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <513EC7E2.90400@udel.edu> References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> Message-ID: <513ECAFB.8010908@udel.edu> This should be issue 17047 On 3/12/2013 2:14 AM, Terry Reedy wrote: > On 3/12/2013 1:50 AM, terry.reedy wrote: >> http://hg.python.org/cpython/rev/c162e2ff15bd >> changeset: 82624:c162e2ff15bd >> branch: 2.7 >> parent: 82617:cd0191a9b5c9 >> user: Terry Jan Reedy >> date: Tue Mar 12 01:26:28 2013 -0400 >> summary: >> Issue #14707: add news entry >> >> files: >> Misc/NEWS | 3 +++ >> 1 files changed, 3 insertions(+), 0 deletions(-) >> >> >> diff --git a/Misc/NEWS b/Misc/NEWS >> --- a/Misc/NEWS >> +++ b/Misc/NEWS >> @@ -944,6 +944,9 @@ >> Documentation >> ------------- >> >> +- Issue #14707: remove doubled words in docs and docstrings >> + reported by Serhiy Storchaka and Matthew Barnett. >> + >> - Issue #16406: combine the pages for uploading and registering to >> PyPI. >> >> - Issue #16403: Document how distutils uses the maintainer field in > > The above was easy. When I tried to transplant this patch to 3.2, export > and import, or directly edit 3.2 NEWS with Notepad++ or IDLE, hg makes a > 319kb patch that deletes and add the entire file in chunks. I did not > think I should commit and push that. > > The failure of transplant and import are perhaps understandable because > 3.2 has a gratuitous case difference with /combine/Combine/. > > - Issue #16406: Combine the pages for uploading and registering to PyPI. > > But the inability to make a proper diff from direct edit is something > else. If I add just a single blank line, even that generates a mega > patch. Same with 3.3 NEWS. I also tried deleting the file to make hg > regenerate from the repository database. > > Anyone have any idea what the problem is? Has anything changed with hg, > windows, line endings and this text file in the last few months? I just > pushed patches for about 20 scattered files in Docs, Lib, Modules, and > Tools earlier today, so the problem seems to be specific to NEWS. > > tjr > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins From ezio.melotti at gmail.com Tue Mar 12 07:52:18 2013 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Tue, 12 Mar 2013 08:52:18 +0200 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <513EC7E2.90400@udel.edu> References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> Message-ID: Hi, On Tue, Mar 12, 2013 at 8:14 AM, Terry Reedy wrote: > On 3/12/2013 1:50 AM, terry.reedy wrote: >> >> http://hg.python.org/cpython/rev/c162e2ff15bd >> changeset: 82624:c162e2ff15bd >> branch: 2.7 >> parent: 82617:cd0191a9b5c9 >> user: Terry Jan Reedy >> date: Tue Mar 12 01:26:28 2013 -0400 >> summary: >> Issue #14707: add news entry >> >> files: >> Misc/NEWS | 3 +++ >> 1 files changed, 3 insertions(+), 0 deletions(-) >> >> >> diff --git a/Misc/NEWS b/Misc/NEWS >> --- a/Misc/NEWS >> +++ b/Misc/NEWS >> @@ -944,6 +944,9 @@ >> Documentation >> ------------- >> >> +- Issue #14707: remove doubled words in docs and docstrings >> + reported by Serhiy Storchaka and Matthew Barnett. >> + >> - Issue #16406: combine the pages for uploading and registering to PyPI. >> >> - Issue #16403: Document how distutils uses the maintainer field in > > > The above was easy. When I tried to transplant this patch to 3.2, export and > import, or directly edit 3.2 NEWS with Notepad++ or IDLE, hg makes a 319kb > patch that deletes and add the entire file in chunks. I did not think I > should commit and push that. > What are the exact commands you used? Are your clones up to date (i.e. did you do "hg pull" and "hg up" before "hg graft")? If not, you should pull/update. Does "hg heads ." show you more than one head? If so you should do "hg merge". Is your clone "clean" (i.e. does "hg status" show anything as 'M')? If not, you should do "hg revert -ar 3.2" or "hg up -C 3.2". Once your clone is clean you can just edit Misc/NEWS manually since it's easier than trying to graft the 2 changesets you made on 2.7 to add and edit the Misc/NEWS entry. You can also check with "hg in" and "hg out" if there's something you haven't pulled/pushed yet, but that shouldn't be a problem. > The failure of transplant and import are perhaps understandable because 3.2 > has a gratuitous case difference with /combine/Combine/. > > - Issue #16406: Combine the pages for uploading and registering to PyPI. > > But the inability to make a proper diff from direct edit is something else. > If I add just a single blank line, even that generates a mega patch. Same > with 3.3 NEWS. I also tried deleting the file to make hg regenerate from the > repository database. > > Anyone have any idea what the problem is? Has anything changed with hg, > windows, line endings and this text file in the last few months? I just > pushed patches for about 20 scattered files in Docs, Lib, Modules, and Tools > earlier today, so the problem seems to be specific to NEWS. > Not sure about this, but in the meanwhile you could try what I suggested above -- if that doesn't work we can find some other solution. (If you prefer you can come on #python-dev too.) Best Regards, Ezio Melotti > tjr > From python-checkins at python.org Tue Mar 12 14:07:13 2013 From: python-checkins at python.org (eli.bendersky) Date: Tue, 12 Mar 2013 14:07:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzExMzY3?= =?utf-8?q?=3A_fix_documentation_of_some_find*_methods_in_ElementTree?= Message-ID: <3ZQGg50ZdHzRhJ@mail.python.org> http://hg.python.org/cpython/rev/958217164846 changeset: 82628:958217164846 branch: 3.2 parent: 82618:3f5f961262ec user: Eli Bendersky date: Tue Mar 12 06:01:22 2013 -0700 summary: Issue #11367: fix documentation of some find* methods in ElementTree files: Doc/library/xml.etree.elementtree.rst | 15 +++------------ Lib/xml/etree/ElementTree.py | 11 ++++------- Misc/ACKS | 1 + 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -412,26 +412,17 @@ .. method:: find(match) - Finds the first toplevel element matching *match*. *match* may be a tag - name or path. Same as getroot().find(match). Returns the first matching - element, or ``None`` if no element was found. + Same as :meth:`Element.find`, starting at the root of the tree. .. method:: findall(match) - Finds all matching subelements, by tag name or path. Same as - getroot().findall(match). *match* may be a tag name or path. Returns a - list containing all matching elements, in document order. + Same as :meth:`Element.findall`, starting at the root of the tree. .. method:: findtext(match, default=None) - Finds the element text for the first toplevel element with given tag. - Same as getroot().findtext(match). *match* may be a tag name or path. - *default* is the value to return if the element was not found. Returns - the text content of the first matching element, or the default value no - element was found. Note that if the element is found, but has no text - content, this method returns an empty string. + Same as :meth:`Element.findtext`, starting at the root of the tree. .. method:: getiterator(tag=None) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -705,8 +705,7 @@ return list(self.iter(tag)) ## - # Finds the first toplevel element with given tag. - # Same as getroot().find(path). + # Same as getroot().find(path), starting at the root of the tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. @@ -726,10 +725,9 @@ return self._root.find(path, namespaces) ## - # Finds the element text for the first toplevel element with given - # tag. Same as getroot().findtext(path). + # Same as getroot().findtext(path), starting at the root of the tree. # - # @param path What toplevel element to look for. + # @param path What element to look for. # @param default What to return if the element was not found. # @keyparam namespaces Optional namespace prefix map. # @return The text content of the first matching element, or the @@ -751,8 +749,7 @@ return self._root.findtext(path, default, namespaces) ## - # Finds all toplevel elements with the given tag. - # Same as getroot().findall(path). + # Same as getroot().findall(path), starting at the root of the tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -436,6 +436,7 @@ Rycharde Hawkes Ben Hayden Jochen Hayek +Henrik Heimbuerger Christian Heimes Thomas Heller Malte Helmert -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 14:07:14 2013 From: python-checkins at python.org (eli.bendersky) Date: Tue, 12 Mar 2013 14:07:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2311367=3A_fix_documentation_of_some_find*_methods_in_E?= =?utf-8?q?lementTree?= Message-ID: <3ZQGg63b3mzRyw@mail.python.org> http://hg.python.org/cpython/rev/4012d4b41b2b changeset: 82629:4012d4b41b2b branch: 3.3 parent: 82625:fa051c6276a0 parent: 82628:958217164846 user: Eli Bendersky date: Tue Mar 12 06:04:33 2013 -0700 summary: Issue #11367: fix documentation of some find* methods in ElementTree files: Lib/xml/etree/ElementTree.py | 11 ++++------- Misc/ACKS | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -692,8 +692,7 @@ return list(self.iter(tag)) ## - # Finds the first toplevel element with given tag. - # Same as getroot().find(path). + # Same as getroot().find(path), starting at the root of the tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. @@ -713,10 +712,9 @@ return self._root.find(path, namespaces) ## - # Finds the element text for the first toplevel element with given - # tag. Same as getroot().findtext(path). + # Same as getroot().findtext(path), starting at the root of the tree. # - # @param path What toplevel element to look for. + # @param path What element to look for. # @param default What to return if the element was not found. # @keyparam namespaces Optional namespace prefix map. # @return The text content of the first matching element, or the @@ -738,8 +736,7 @@ return self._root.findtext(path, default, namespaces) ## - # Finds all toplevel elements with the given tag. - # Same as getroot().findall(path). + # Same as getroot().findall(path), starting at the root of the tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -480,6 +480,7 @@ Rycharde Hawkes Ben Hayden Jochen Hayek +Henrik Heimbuerger Christian Heimes Thomas Heller Malte Helmert -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 14:07:15 2013 From: python-checkins at python.org (eli.bendersky) Date: Tue, 12 Mar 2013 14:07:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2311367=3A_fix_documentation_of_some_find*_method?= =?utf-8?q?s_in_ElementTree?= Message-ID: <3ZQGg76DS9zRwd@mail.python.org> http://hg.python.org/cpython/rev/7ae2c90f1ba2 changeset: 82630:7ae2c90f1ba2 parent: 82626:8fdce849d0b3 parent: 82629:4012d4b41b2b user: Eli Bendersky date: Tue Mar 12 06:06:06 2013 -0700 summary: Issue #11367: fix documentation of some find* methods in ElementTree 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 @@ -483,6 +483,7 @@ Rycharde Hawkes Ben Hayden Jochen Hayek +Henrik Heimbuerger Christian Heimes Thomas Heller Malte Helmert -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Mar 12 14:09:09 2013 From: python-checkins at python.org (eli.bendersky) Date: Tue, 12 Mar 2013 14:09:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzExMzY3?= =?utf-8?q?=3A_fix_documentation_of_some_find*_methods_in_ElementTree?= Message-ID: <3ZQGjK72VlzRkN@mail.python.org> http://hg.python.org/cpython/rev/8e6db2462a77 changeset: 82631:8e6db2462a77 branch: 2.7 parent: 82627:a1bebf2c33e7 user: Eli Bendersky date: Tue Mar 12 06:08:04 2013 -0700 summary: Issue #11367: fix documentation of some find* methods in ElementTree files: Doc/library/xml.etree.elementtree.rst | 15 +++------------ Lib/xml/etree/ElementTree.py | 12 +++++------- Misc/ACKS | 1 + 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -711,26 +711,17 @@ .. method:: find(match) - Finds the first toplevel element matching *match*. *match* may be a tag - name or path. Same as getroot().find(match). Returns the first matching - element, or ``None`` if no element was found. + Same as :meth:`Element.find`, starting at the root of the tree. .. method:: findall(match) - Finds all matching subelements, by tag name or path. Same as - getroot().findall(match). *match* may be a tag name or path. Returns a - list containing all matching elements, in document order. + Same as :meth:`Element.findall`, starting at the root of the tree. .. method:: findtext(match, default=None) - Finds the element text for the first toplevel element with given tag. - Same as getroot().findtext(match). *match* may be a tag name or path. - *default* is the value to return if the element was not found. Returns - the text content of the first matching element, or the default value no - element was found. Note that if the element is found, but has no text - content, this method returns an empty string. + Same as :meth:`Element.findtext`, starting at the root of the tree. .. method:: getiterator(tag=None) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -683,8 +683,8 @@ return list(self.iter(tag)) ## - # Finds the first toplevel element with given tag. - # Same as getroot().find(path). + # Same as getroot().find(path), starting at the root of the + # tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. @@ -704,10 +704,9 @@ return self._root.find(path, namespaces) ## - # Finds the element text for the first toplevel element with given - # tag. Same as getroot().findtext(path). + # Same as getroot().findtext(path), starting at the root of the tree. # - # @param path What toplevel element to look for. + # @param path What element to look for. # @param default What to return if the element was not found. # @keyparam namespaces Optional namespace prefix map. # @return The text content of the first matching element, or the @@ -729,8 +728,7 @@ return self._root.findtext(path, default, namespaces) ## - # Finds all toplevel elements with the given tag. - # Same as getroot().findall(path). + # Same as getroot().findall(path), starting at the root of the tree. # # @param path What element to look for. # @keyparam namespaces Optional namespace prefix map. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -398,6 +398,7 @@ Rycharde Hawkes Ben Hayden Jochen Hayek +Henrik Heimbuerger Christian Heimes Thomas Heller Malte Helmert -- Repository URL: http://hg.python.org/cpython From ncoghlan at gmail.com Tue Mar 12 16:26:07 2013 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 13 Mar 2013 01:26:07 +1000 Subject: [Python-checkins] cpython (2.7): #16004: Add `make touch`. In-Reply-To: References: <3ZPVtS3mkkzSHQ@mail.python.org> Message-ID: On 11 Mar 2013 06:23, "Brett Cannon" wrote: > > > > > On Mon, Mar 11, 2013 at 9:22 AM, Brett Cannon wrote: >> >> Should this also touch Python/importlib.h? >> > > nm, noticed this was added on 2.7 and not default. Default already had it, this was a back port so that "make touch" could be given as a consistent fix for certain build problems in the devguide. (Specifically, make trying to rebuild those files when you don't yet have the necessary pieces available to do so) Cheers, Nick. > >> >> >> On Mon, Mar 11, 2013 at 3:14 AM, ezio.melotti wrote: >>> >>> http://hg.python.org/cpython/rev/da3f4774b939 >>> changeset: 82600:da3f4774b939 >>> branch: 2.7 >>> parent: 82593:3e14aafeca04 >>> user: Ezio Melotti >>> date: Mon Mar 11 09:14:09 2013 +0200 >>> summary: >>> #16004: Add `make touch`. >>> >>> files: >>> Makefile.pre.in | 6 +++++- >>> Misc/NEWS | 2 ++ >>> 2 files changed, 7 insertions(+), 1 deletions(-) >>> >>> >>> diff --git a/Makefile.pre.in b/Makefile.pre.in >>> --- a/Makefile.pre.in >>> +++ b/Makefile.pre.in >>> @@ -1250,6 +1250,10 @@ >>> etags Include/*.h; \ >>> for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done >>> >>> +# Touch generated files >>> +touch: >>> + touch Include/Python-ast.h Python/Python-ast.c >>> + >>> # Sanitation targets -- clean leaves libraries, executables and tags >>> # files, which clobber removes as well >>> pycremoval: >>> @@ -1339,7 +1343,7 @@ >>> .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure >>> .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools >>> .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean >>> -.PHONY: smelly funny patchcheck altmaninstall >>> +.PHONY: smelly funny patchcheck touch altmaninstall >>> .PHONY: gdbhooks >>> >>> # IF YOU PUT ANYTHING HERE IT WILL GO AWAY >>> diff --git a/Misc/NEWS b/Misc/NEWS >>> --- a/Misc/NEWS >>> +++ b/Misc/NEWS >>> @@ -874,6 +874,8 @@ >>> Build >>> ----- >>> >>> +- Issue #16004: Add `make touch`. >>> + >>> - Issue #5033: Fix building of the sqlite3 extension module when the >>> SQLite library version has "beta" in it. Patch by Andreas Pelme. >>> >>> >>> -- >>> Repository URL: http://hg.python.org/cpython >>> >>> _______________________________________________ >>> Python-checkins mailing list >>> Python-checkins at python.org >>> http://mail.python.org/mailman/listinfo/python-checkins >>> >> > > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Tue Mar 12 17:56:50 2013 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 Mar 2013 17:56:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_update_links_to_6=2E2=2E0?= Message-ID: <3ZQMm23B3hzPLH@mail.python.org> http://hg.python.org/cpython/rev/e1e5423815a4 changeset: 82632:e1e5423815a4 parent: 82630:7ae2c90f1ba2 user: Benjamin Peterson date: Tue Mar 12 11:56:38 2013 -0500 summary: update links to 6.2.0 files: Doc/library/unicodedata.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/unicodedata.rst b/Doc/library/unicodedata.rst --- a/Doc/library/unicodedata.rst +++ b/Doc/library/unicodedata.rst @@ -166,6 +166,6 @@ .. rubric:: Footnotes -.. [#] http://www.unicode.org/Public/6.1.0/ucd/NameAliases.txt +.. [#] http://www.unicode.org/Public/6.2.0/ucd/NameAliases.txt -.. [#] http://www.unicode.org/Public/6.1.0/ucd/NamedSequences.txt +.. [#] http://www.unicode.org/Public/6.2.0/ucd/NamedSequences.txt -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Tue Mar 12 18:19:55 2013 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 12 Mar 2013 13:19:55 -0400 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> Message-ID: <513F63BB.8060805@udel.edu> On 3/12/2013 2:52 AM, Ezio Melotti wrote: I am using the newly documented clone + 3 shares system. > What are the exact commands you used? Clicks on TortoiseHg HgWorkbench GUI ;-). > Are your clones up to date (i.e. did you do "hg pull" and "hg up" > before "hg graft")? There were no other pushes between my last de-double patch and this, and I am sure I ran my pull + 3*update .bat first. I have run it multiple times since. > Does "hg heads ." show you more than one head? The DAG window shows the normal one head per branch as appropriate for the particular branch display. At the moment, hg heads shows the four commits from Eli, 82628 to 82631 as heads plus old 2.6 and 3.1 heads. > Is your clone "clean" (i.e. does "hg status" show anything as 'M')? The status window is empty until I edit NEWS and click Refresh, at which point M Misc/News shows up with the megadiff. Right click/ Revert/yes and the file is reverted. > Once your clone is clean you can just edit Misc/NEWS manually Since the graft and import failed (producing no diff), I have been editing manually and that is when I get the megadiff. I added a couple of blank lines to ACKS and got a normal diff. Now, adding a blank line to 2.7 NEWS also gives a blank line. Could the failed graft have messed up the master copy in my cpython repository. I have tried deleting the NEWS file and reverting the deletion. hg update does not restore the file as it apparently thinks I actually want the uncommitted deletion. > it's easier than trying to graft the 2 changesets you made on 2.7 to > add and edit the Misc/NEWS entry. There was only one 2.7 changeset with only the NEWS patch. > You can also check with "hg in" and "hg out" if there's something you > haven't pulled/pushed yet, but that shouldn't be a problem. I tried both and got 'no changes'. > (If you prefer you can come on #python-dev too.) I may try that, but I suspect that my registration/nick has expired again and last time is was obnoxiously hard to get re-established. Terry From ezio.melotti at gmail.com Wed Mar 13 00:34:58 2013 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Wed, 13 Mar 2013 01:34:58 +0200 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <513F63BB.8060805@udel.edu> References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> <513F63BB.8060805@udel.edu> Message-ID: Hi, On Tue, Mar 12, 2013 at 7:19 PM, Terry Reedy wrote: > On 3/12/2013 2:52 AM, Ezio Melotti wrote: >> What are the exact commands you used? > > Clicks on TortoiseHg HgWorkbench GUI ;-). > I wonder if TortoiseHg is doing something wrong here. Maybe you could try from cmd too. >> Are your clones up to date (i.e. did you do "hg pull" and "hg up" >> before "hg graft")? > > There were no other pushes between my last de-double patch and this, and I > am sure I ran my pull + 3*update .bat first. I have run it multiple times > since. > Around the time you pushed on 2.7 I also pushed something, so that might have created some conflict. How does your .bat look like? One gotcha of the share extension is that if you use "hg pull -u" and there's nothing to pull because you already pulled in one of the shared clones, the update won't be executed (this is actually normal behaviour of "hg pull", but the consequences are especially noticeable while using shared clones). >> Does "hg heads ." show you more than one head? > > The DAG window shows the normal one head per branch as appropriate for the > particular branch display. At the moment, hg heads shows the four commits > from Eli, 82628 to 82631 as heads plus old 2.6 and 3.1 heads. > >> Is your clone "clean" (i.e. does "hg status" show anything as 'M')? > > The status window is empty until I edit NEWS and click Refresh, at which > point M Misc/News shows up with the megadiff. > Right click/ Revert/yes and the file is reverted. > >> Once your clone is clean you can just edit Misc/NEWS manually > > Since the graft and import failed (producing no diff), I have been editing > manually and that is when I get the megadiff. I added a couple of blank > lines to ACKS and got a normal diff. Now, adding a blank line to 2.7 NEWS > also gives a blank line. > > Could the failed graft have messed up the master copy in my cpython > repository. > That's possible. From "hg help graft": If a graft merge results in conflicts, the graft process is interrupted so that the current merge can be manually resolved. Once all conflicts are addressed, the graft process can be continued with the -c/--continue option. This doesn't mean that you copy is messed up though. "hg up -C 3.2" should restore it. When I graft/merge and there are conflicts I use kdiff3, and it takes just a few seconds to solve the conflicts usually (for Misc/NEWS is ctrl+2, ctrl+3, ctrl+s, alt+f4, that roughly translates too "include both the conflicting news, save and quit). > I have tried deleting the NEWS file and reverting the deletion. > hg update does not restore the file as it apparently thinks I actually want > the uncommitted deletion. > How did you delete it? I assume that if you do it from the TortoiseHG GUI, it will mark it as "deleted" ('D' in "hg status"). If you do it from cmd/file manager hg should see it as missing ('!' in "hg status") and you can use "hg revert Misc/NEWS" to restore it. >> it's easier than trying to graft the 2 changesets you made on 2.7 to >> add and edit the Misc/NEWS entry. > > There was only one 2.7 changeset with only the NEWS patch. > I was referring to the one that added the news + the one that fixed the issue id. >> You can also check with "hg in" and "hg out" if there's something you >> haven't pulled/pushed yet, but that shouldn't be a problem. > > I tried both and got 'no changes'. > >> (If you prefer you can come on #python-dev too.) > > I may try that, but I suspect that my registration/nick has expired again > and last time is was obnoxiously hard to get re-established. > There's no need to register your nick for #python-dev (there is for #python though). You can just fire up your favourite IRC client (or even http://webchat.freenode.net/) and join. (Registering the nick shouldn't be difficult though.) > Terry > From python-checkins at python.org Wed Mar 13 00:55:23 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 00:55:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3MzY4OiBGaXgg?= =?utf-8?q?an_off-by-one_error_in_the_Python_JSON_decoder_that_caused_a?= Message-ID: <3ZQY2z1hR0zNWy@mail.python.org> http://hg.python.org/cpython/rev/4a5ad099b176 changeset: 82633:4a5ad099b176 branch: 2.7 parent: 82631:8e6db2462a77 user: Ezio Melotti date: Wed Mar 13 01:49:57 2013 +0200 summary: #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. files: Lib/json/decoder.py | 2 +- Lib/json/tests/test_decode.py | 9 +++++++-- Misc/NEWS | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -163,7 +163,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/Lib/json/tests/test_decode.py b/Lib/json/tests/test_decode.py --- a/Lib/json/tests/test_decode.py +++ b/Lib/json/tests/test_decode.py @@ -40,10 +40,15 @@ self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(self.loads(s, - object_pairs_hook=OrderedDict, + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + # check that empty objects literals work (see #17368) + self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), + OrderedDict()) + self.assertEqual(self.loads('{"empty": {}}', + object_pairs_hook=OrderedDict), + OrderedDict([('empty', OrderedDict())])) def test_extra_data(self): s = '[1, 2, 3]5' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,6 +214,10 @@ Library ------- +- Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused + a failure while decoding empty object literals when object_pairs_hook was + specified. + - Issue #17278: Fix a crash in heapq.heappush() and heapq.heappop() when the list is being resized concurrently. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 00:55:24 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 00:55:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzY4OiBGaXgg?= =?utf-8?q?an_off-by-one_error_in_the_Python_JSON_decoder_that_caused_a?= Message-ID: <3ZQY304wXwzNyc@mail.python.org> http://hg.python.org/cpython/rev/40c36d873f41 changeset: 82634:40c36d873f41 branch: 3.2 parent: 82628:958217164846 user: Ezio Melotti date: Wed Mar 13 01:52:34 2013 +0200 summary: #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. files: Lib/json/decoder.py | 2 +- Lib/test/json_tests/test_decode.py | 14 ++++++++++---- Misc/NEWS | 4 ++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -167,7 +167,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/Lib/test/json_tests/test_decode.py b/Lib/test/json_tests/test_decode.py --- a/Lib/test/json_tests/test_decode.py +++ b/Lib/test/json_tests/test_decode.py @@ -25,16 +25,22 @@ p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] self.assertEqual(self.loads(s), eval(s)) - self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p) + self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) self.assertEqual(self.json.load(StringIO(s), object_pairs_hook=lambda x: x), p) - od = self.loads(s, object_pairs_hook = OrderedDict) + od = self.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(self.loads(s, object_pairs_hook = OrderedDict, - object_hook = lambda x: None), + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, + object_hook=lambda x: None), OrderedDict(p)) + # check that empty objects literals work (see #17368) + self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), + OrderedDict()) + self.assertEqual(self.loads('{"empty": {}}', + object_pairs_hook=OrderedDict), + OrderedDict([('empty', OrderedDict())])) def test_decoder_optimizations(self): # Several optimizations were made that skip over calls to diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,10 @@ Library ------- +- Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused + a failure while decoding empty object literals when object_pairs_hook was + specified. + - Issue #14645: The email generator classes now produce output using the specified linesep throughout. Previously if the prolog, epilog, or body were stored with a different linesep, that linesep was used. This -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 00:55:26 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 00:55:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317368=3A_merge_with_3=2E2=2E?= Message-ID: <3ZQY320WyqzNbr@mail.python.org> http://hg.python.org/cpython/rev/dd2fad6b47c0 changeset: 82635:dd2fad6b47c0 branch: 3.3 parent: 82629:4012d4b41b2b parent: 82634:40c36d873f41 user: Ezio Melotti date: Wed Mar 13 01:53:38 2013 +0200 summary: #17368: merge with 3.2. files: Lib/json/decoder.py | 2 +- Lib/test/json_tests/test_decode.py | 14 ++++++++++---- Misc/NEWS | 4 ++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -166,7 +166,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/Lib/test/json_tests/test_decode.py b/Lib/test/json_tests/test_decode.py --- a/Lib/test/json_tests/test_decode.py +++ b/Lib/test/json_tests/test_decode.py @@ -25,16 +25,22 @@ p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] self.assertEqual(self.loads(s), eval(s)) - self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p) + self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) self.assertEqual(self.json.load(StringIO(s), object_pairs_hook=lambda x: x), p) - od = self.loads(s, object_pairs_hook = OrderedDict) + od = self.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(self.loads(s, object_pairs_hook = OrderedDict, - object_hook = lambda x: None), + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, + object_hook=lambda x: None), OrderedDict(p)) + # check that empty objects literals work (see #17368) + self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), + OrderedDict()) + self.assertEqual(self.loads('{"empty": {}}', + object_pairs_hook=OrderedDict), + OrderedDict([('empty', OrderedDict())])) def test_decoder_optimizations(self): # Several optimizations were made that skip over calls to diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,10 @@ Library ------- +- Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused + a failure while decoding empty object literals when object_pairs_hook was + specified. + - Issue #14645: The email generator classes now produce output using the specified linesep throughout. Previously if the prolog, epilog, or body were stored with a different linesep, that linesep was used. This -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 00:55:27 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 00:55:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3MzY4OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZQY333FNQzP2T@mail.python.org> http://hg.python.org/cpython/rev/885ffda21849 changeset: 82636:885ffda21849 parent: 82632:e1e5423815a4 parent: 82635:dd2fad6b47c0 user: Ezio Melotti date: Wed Mar 13 01:55:07 2013 +0200 summary: #17368: merge with 3.3. files: Lib/json/decoder.py | 2 +- Lib/test/json_tests/test_decode.py | 14 ++++++++++---- Misc/NEWS | 4 ++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -158,7 +158,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/Lib/test/json_tests/test_decode.py b/Lib/test/json_tests/test_decode.py --- a/Lib/test/json_tests/test_decode.py +++ b/Lib/test/json_tests/test_decode.py @@ -25,16 +25,22 @@ p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] self.assertEqual(self.loads(s), eval(s)) - self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p) + self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) self.assertEqual(self.json.load(StringIO(s), object_pairs_hook=lambda x: x), p) - od = self.loads(s, object_pairs_hook = OrderedDict) + od = self.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(self.loads(s, object_pairs_hook = OrderedDict, - object_hook = lambda x: None), + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, + object_hook=lambda x: None), OrderedDict(p)) + # check that empty objects literals work (see #17368) + self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), + OrderedDict()) + self.assertEqual(self.loads('{"empty": {}}', + object_pairs_hook=OrderedDict), + OrderedDict([('empty', OrderedDict())])) def test_decoder_optimizations(self): # Several optimizations were made that skip over calls to diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -277,6 +277,10 @@ Library ------- +- Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused + a failure while decoding empty object literals when object_pairs_hook was + specified. + _ Issue #17385: Fix quadratic behavior in threading.Condition. The FIFO queue now uses a deque instead of a list. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 01:28:10 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 01:28:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3NDAyOiBhdm9p?= =?utf-8?q?d_shadowing_built-in_map_in_mmap_examples=2E__Initial_patch_by_?= =?utf-8?q?Aman?= Message-ID: <3ZQYmp16xzzP25@mail.python.org> http://hg.python.org/cpython/rev/c226133b1493 changeset: 82637:c226133b1493 branch: 2.7 parent: 82633:4a5ad099b176 user: Ezio Melotti date: Wed Mar 13 02:26:11 2013 +0200 summary: #17402: avoid shadowing built-in map in mmap examples. Initial patch by Aman Shah. files: Doc/library/mmap.rst | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -114,19 +114,19 @@ with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file - map = mmap.mmap(f.fileno(), 0) + mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods - print map.readline() # prints "Hello Python!" + print mm.readline() # prints "Hello Python!" # read content via slice notation - print map[:5] # prints "Hello" + print mm[:5] # prints "Hello" # update content using slice notation; # note that new content must have same size - map[6:] = " world!\n" + mm[6:] = " world!\n" # ... and read again using standard file methods - map.seek(0) - print map.readline() # prints "Hello world!" + mm.seek(0) + print mm.readline() # prints "Hello world!" # close the map - map.close() + mm.close() The next example demonstrates how to create an anonymous map and exchange @@ -135,16 +135,16 @@ import mmap import os - map = mmap.mmap(-1, 13) - map.write("Hello world!") + mm = mmap.mmap(-1, 13) + mm.write("Hello world!") pid = os.fork() if pid == 0: # In a child process - map.seek(0) - print map.readline() + mm.seek(0) + print mm.readline() - map.close() + mm.close() Memory-mapped file objects support the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 01:28:11 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 01:28:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3NDAyOiBhdm9p?= =?utf-8?q?d_shadowing_built-in_map_in_mmap_examples=2E__Initial_patch_by_?= =?utf-8?q?Aman?= Message-ID: <3ZQYmq3gvXzP4c@mail.python.org> http://hg.python.org/cpython/rev/df27ea4bdebd changeset: 82638:df27ea4bdebd branch: 3.2 parent: 82634:40c36d873f41 user: Ezio Melotti date: Wed Mar 13 02:27:00 2013 +0200 summary: #17402: avoid shadowing built-in map in mmap examples. Initial patch by Aman Shah. files: Doc/library/mmap.rst | 28 ++++++++++++++-------------- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -106,19 +106,19 @@ with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file - map = mmap.mmap(f.fileno(), 0) + mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods - print(map.readline()) # prints b"Hello Python!\n" + print(mm.readline()) # prints b"Hello Python!\n" # read content via slice notation - print(map[:5]) # prints b"Hello" + print(mm[:5]) # prints b"Hello" # update content using slice notation; # note that new content must have same size - map[6:] = b" world!\n" + mm[6:] = b" world!\n" # ... and read again using standard file methods - map.seek(0) - print(map.readline()) # prints b"Hello world!\n" + mm.seek(0) + print(mm.readline()) # prints b"Hello world!\n" # close the map - map.close() + mm.close() :class:`mmap` can also be used as a context manager in a :keyword:`with` @@ -126,8 +126,8 @@ import mmap - with mmap.mmap(-1, 13) as map: - map.write("Hello world!") + with mmap.mmap(-1, 13) as mm: + mm.write("Hello world!") .. versionadded:: 3.2 Context manager support. @@ -139,16 +139,16 @@ import mmap import os - map = mmap.mmap(-1, 13) - map.write(b"Hello world!") + mm = mmap.mmap(-1, 13) + mm.write(b"Hello world!") pid = os.fork() if pid == 0: # In a child process - map.seek(0) - print(map.readline()) + mm.seek(0) + print(mm.readline()) - map.close() + mm.close() Memory-mapped file objects support the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 01:28:12 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 01:28:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317402=3A_merge_with_3=2E2=2E?= Message-ID: <3ZQYmr6jHczP86@mail.python.org> http://hg.python.org/cpython/rev/bf0632a17ab4 changeset: 82639:bf0632a17ab4 branch: 3.3 parent: 82635:dd2fad6b47c0 parent: 82638:df27ea4bdebd user: Ezio Melotti date: Wed Mar 13 02:27:35 2013 +0200 summary: #17402: merge with 3.2. files: Doc/library/mmap.rst | 28 ++++++++++++++-------------- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -106,19 +106,19 @@ with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file - map = mmap.mmap(f.fileno(), 0) + mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods - print(map.readline()) # prints b"Hello Python!\n" + print(mm.readline()) # prints b"Hello Python!\n" # read content via slice notation - print(map[:5]) # prints b"Hello" + print(mm[:5]) # prints b"Hello" # update content using slice notation; # note that new content must have same size - map[6:] = b" world!\n" + mm[6:] = b" world!\n" # ... and read again using standard file methods - map.seek(0) - print(map.readline()) # prints b"Hello world!\n" + mm.seek(0) + print(mm.readline()) # prints b"Hello world!\n" # close the map - map.close() + mm.close() :class:`mmap` can also be used as a context manager in a :keyword:`with` @@ -126,8 +126,8 @@ import mmap - with mmap.mmap(-1, 13) as map: - map.write("Hello world!") + with mmap.mmap(-1, 13) as mm: + mm.write("Hello world!") .. versionadded:: 3.2 Context manager support. @@ -139,16 +139,16 @@ import mmap import os - map = mmap.mmap(-1, 13) - map.write(b"Hello world!") + mm = mmap.mmap(-1, 13) + mm.write(b"Hello world!") pid = os.fork() if pid == 0: # In a child process - map.seek(0) - print(map.readline()) + mm.seek(0) + print(mm.readline()) - map.close() + mm.close() Memory-mapped file objects support the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 01:28:14 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 01:28:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE3NDAyOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3ZQYmt2LpVzPBN@mail.python.org> http://hg.python.org/cpython/rev/b49971a1e70d changeset: 82640:b49971a1e70d parent: 82636:885ffda21849 parent: 82639:bf0632a17ab4 user: Ezio Melotti date: Wed Mar 13 02:27:53 2013 +0200 summary: #17402: merge with 3.3. files: Doc/library/mmap.rst | 28 ++++++++++++++-------------- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -106,19 +106,19 @@ with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file - map = mmap.mmap(f.fileno(), 0) + mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods - print(map.readline()) # prints b"Hello Python!\n" + print(mm.readline()) # prints b"Hello Python!\n" # read content via slice notation - print(map[:5]) # prints b"Hello" + print(mm[:5]) # prints b"Hello" # update content using slice notation; # note that new content must have same size - map[6:] = b" world!\n" + mm[6:] = b" world!\n" # ... and read again using standard file methods - map.seek(0) - print(map.readline()) # prints b"Hello world!\n" + mm.seek(0) + print(mm.readline()) # prints b"Hello world!\n" # close the map - map.close() + mm.close() :class:`mmap` can also be used as a context manager in a :keyword:`with` @@ -126,8 +126,8 @@ import mmap - with mmap.mmap(-1, 13) as map: - map.write("Hello world!") + with mmap.mmap(-1, 13) as mm: + mm.write("Hello world!") .. versionadded:: 3.2 Context manager support. @@ -139,16 +139,16 @@ import mmap import os - map = mmap.mmap(-1, 13) - map.write(b"Hello world!") + mm = mmap.mmap(-1, 13) + mm.write(b"Hello world!") pid = os.fork() if pid == 0: # In a child process - map.seek(0) - print(map.readline()) + mm.seek(0) + print(mm.readline()) - map.close() + mm.close() Memory-mapped file objects support the following methods: -- Repository URL: http://hg.python.org/cpython From root at python.org Wed Mar 13 01:51:02 2013 From: root at python.org (Cron Daemon) Date: Wed, 13 Mar 2013 01:51:02 +0100 Subject: [Python-checkins] Cron /home/docs/build-devguide Message-ID: abort: error: Name or service not known From solipsis at pitrou.net Wed Mar 13 06:01:27 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 13 Mar 2013 06:01:27 +0100 Subject: [Python-checkins] Daily reference leaks (b49971a1e70d): sum=1 Message-ID: results for b49971a1e70d on branch "default" -------------------------------------------- test_unittest leaked [-1, 2, 0] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogi0MroE', '-x'] From python-checkins at python.org Wed Mar 13 06:26:16 2013 From: python-checkins at python.org (ezio.melotti) Date: Wed, 13 Mar 2013 06:26:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_=2314468=3A_move_a_paragr?= =?utf-8?q?aph_and_link_to_the_list_of_branches=2E?= Message-ID: <3ZQhNm6pTlzNnT@mail.python.org> http://hg.python.org/devguide/rev/50e726533391 changeset: 609:50e726533391 user: Ezio Melotti date: Wed Mar 13 07:26:05 2013 +0200 summary: #14468: move a paragraph and link to the list of branches. files: committing.rst | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-) diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -305,11 +305,17 @@ while you only need to use ``hg pull`` once, you still need to use ``hg up`` in each clone to update its working copy). +If you don't want to specify ssh://hg at hg.python.org/cpython every time you pull +or push, you should add to the ``.hg/hgrc`` files of the clones:: + + [paths] + default = ssh://hg at hg.python.org/cpython + In order to apply a patch, commit, and merge it on all the branches, you can do as follow:: $ cd 2.7 - $ hg pull ssh://hg at hg.python.org/cpython + $ hg pull $ hg up $ hg import --no-c http://bugs.python.org/url/to/the/patch.diff $ # review, run tests, run `make patchcheck` @@ -328,13 +334,7 @@ $ hg up $ hg merge 3.3 $ hg ci -m '#12345: merge with 3.3.' - $ hg push ssh://hg at hg.python.org/cpython - -If you don't want to specify ssh://hg at hg.python.org/cpython every time, you -should add to the ``.hg/hgrc`` files of the clones:: - - [paths] - default = ssh://hg at hg.python.org/cpython + $ hg push Unless noted otherwise, the rest of the page will assume you are using the multiple clone approach, and explain in more detail these basic steps. @@ -345,12 +345,12 @@ Active branches --------------- -If you do ``hg branches`` you will see a list of branches. ``default`` is the -in-development branch, and is the only branch that receives new features. The -other branches only receive bug fixes (``2.7``, ``3.2``, ``3.3``), or security -fixes (``2.6``, ``3.1``). Depending on what you are committing (feature, bug -fix, or security fix), you should commit to the oldest branch applicable, and -then forward-port until the in-development branch. +If you do ``hg branches`` you will see a :ref:`list of branches `. +``default`` is the in-development branch, and is the only branch that receives +new features. The other branches only receive bug fixes or security fixes. +Depending on what you are committing (feature, bug fix, or security fix), you +should commit to the oldest branch applicable, and then forward-port until the +in-development branch. Merging order @@ -377,9 +377,9 @@ # Compile; run the test suite hg ci -m '#12345: fix some issue.' -Then you can switch to the ``3.x`` clone, merge, run the tests and commit:: +Then you can switch to the ``3.4`` clone, merge, run the tests and commit:: - cd ../3.x + cd ../3.4 hg merge 3.3 # Fix any conflicts; compile; run the test suite hg ci -m '#12345: merge with 3.3.' -- Repository URL: http://hg.python.org/devguide From tjreedy at udel.edu Wed Mar 13 08:41:13 2013 From: tjreedy at udel.edu (Terry Reedy) Date: Wed, 13 Mar 2013 03:41:13 -0400 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> <513F63BB.8060805@udel.edu> Message-ID: <51402D99.3020507@udel.edu> Bottom line: I decided to restart from scratch. I am still not sure if the glitch was hg, disk 1, disk 2, or Windows, or some combination. After making and posting a patch to the tracker today, I tried to annotate a file and got an error something like 'cannot find revision -1'. I then noticed that there was no dag in the workbench dag window, as if there were no revisions. When I looked in .hg/store, the big file seemed to be missing. So I wiped, defragmented and compacted, and reloaded TortoiseHg. Tomorrow I will re-clone and share the repository. Since this is the second time I have re-cloned from python.org, I will follow the advice I read somewhere to make a _backup clone that I leave alone until I need it, so I only have to pull from now until then when I do. On 3/12/2013 7:34 PM, Ezio Melotti wrote: > I wonder if TortoiseHg is doing something wrong here. Maybe you could > try from cmd too. Workbench has a 'command' window for typing hg commands which it should pass as is to Windows much as Command Prompt does. I tried some of the things you suggested there. > Around the time you pushed on 2.7 I also pushed something, so that > might have created some conflict. I do not remember seeing that. > How does your .bat look like? pull -u to cpython + update of each of the three shares, much like written in the devguide. > That's possible. From "hg help graft": > If a graft merge results in conflicts, the graft process is interrupted so > that the current merge can be manually resolved. Once all conflicts are > addressed, the graft process can be continued with the -c/--continue > option. When merge produces a conflict, a window appears offering options including using kdiff3 to resolve. When I tried the graft, the message in the command window was just 'aborted', and I do not remember getting the resolve window. > When I graft/merge and there are conflicts I use kdiff3, and it takes > just a few seconds to solve the conflicts usually (for Misc/NEWS is > ctrl+2, ctrl+3, ctrl+s, alt+f4, that roughly translates too "include > both the conflicting news, save and quit). Since I have perhaps never gotten that sequence right, that info will be helpful. > If you do it from cmd/file manager hg should see it as missing ('!' in > "hg status") and you can use "hg revert Misc/NEWS" to restore it. This. Thanks for trying to help. I will let you know if there are any more problems after the re-clone. I still need to comment on the tcl/tk.dll and tkinter situation, but will just mention now that I ran the four test_txxxx files on 3.3a0 (on Windows) and they seemed to finish and be ok other than altering the environment. Terry From ncoghlan at gmail.com Wed Mar 13 08:01:23 2013 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 13 Mar 2013 00:01:23 -0700 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <51402D99.3020507@udel.edu> References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> <513F63BB.8060805@udel.edu> <51402D99.3020507@udel.edu> Message-ID: On Wed, Mar 13, 2013 at 12:41 AM, Terry Reedy wrote: > Bottom line: I decided to restart from scratch. I am still not sure if the > glitch was hg, disk 1, disk 2, or Windows, or some combination. > > After making and posting a patch to the tracker today, I tried to annotate a > file and got an error something like 'cannot find revision -1'. I then > noticed that there was no dag in the workbench dag window, as if there were > no revisions. When I looked in .hg/store, the big file seemed to be missing. > So I wiped, defragmented and compacted, and reloaded TortoiseHg. Tomorrow I > will re-clone and share the repository. Since this is the second time I have > re-cloned from python.org, I will follow the advice I read somewhere to make > a _backup clone that I leave alone until I need it, so I only have to pull > from now until then when I do. I still keep a pristine clone around so "nuke it from orbit" remains an option. "hg histedit" lets me deal with most of my screw-ups these days, though. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia From ezio.melotti at gmail.com Wed Mar 13 09:06:55 2013 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Wed, 13 Mar 2013 10:06:55 +0200 Subject: [Python-checkins] CANNOT Patch 3.x NEWS [was cpython (2.7): Issue #14707: add news entry\ In-Reply-To: <51402D99.3020507@udel.edu> References: <3ZQ4z44QVLzRXr@mail.python.org> <513EC7E2.90400@udel.edu> <513F63BB.8060805@udel.edu> <51402D99.3020507@udel.edu> Message-ID: On Wed, Mar 13, 2013 at 9:41 AM, Terry Reedy wrote: > Bottom line: I decided to restart from scratch. I am still not sure if the > glitch was hg, disk 1, disk 2, or Windows, or some combination. > > After making and posting a patch to the tracker today, I tried to annotate a > file and got an error something like 'cannot find revision -1'. I then > noticed that there was no dag in the workbench dag window, as if there were > no revisions. When I looked in .hg/store, the big file seemed to be missing. Note that with the share extension, the "big file" (which I assume is the store/ directory) only exists in the "main" clone. In the shared clones you'll find an .hg/sharedpath file that contains the path to the original .hg/ that contains the store/ dir with all the changesets. > So I wiped, defragmented and compacted, and reloaded TortoiseHg. Tomorrow I > will re-clone and share the repository. Since this is the second time I have > re-cloned from python.org, I will follow the advice I read somewhere to make > a _backup clone that I leave alone until I need it, so I only have to pull > from now until then when I do. > Good idea :) >> On 3/12/2013 7:34 PM, Ezio Melotti wrote: >> I wonder if TortoiseHg is doing something wrong here. Maybe you could >> try from cmd too. > > Workbench has a 'command' window for typing hg commands which it should pass > as is to Windows much as Command Prompt does. I tried some of the things you > suggested there. > >> Around the time you pushed on 2.7 I also pushed something, so that >> might have created some conflict. > > I do not remember seeing that. > I pushed on 3.3/default about half an hour after you pushed on 2.7, so that might have caused a push race, if during that time you were doing the merges and eventually tried to push after me without having pulled/updated in the meanwhile. The problem you described doesn't seem to be related to push races though. >> How does your .bat look like? > > pull -u to cpython + update of each of the three shares, much like written > in the devguide. > It's better to avoid using "hg pull -u", because if there's nothing to pull the "update" won't be executed. Here it shouldn't be a big problem, but you could break it if you manually pull something in one of the shared clones, and then run the .bat. Unless you also have an explicit "hg up" in the clone where you do "hg pull -u", that clone won't be updated by the script. >> That's possible. From "hg help graft": >> If a graft merge results in conflicts, the graft process is interrupted so >> that the current merge can be manually resolved. Once all conflicts are >> addressed, the graft process can be continued with the -c/--continue >> option. > > When merge produces a conflict, a window appears offering options including > using kdiff3 to resolve. When I tried the graft, the message in the command > window was just 'aborted', and I do not remember getting the resolve window. > What version of HG are you using? >> When I graft/merge and there are conflicts I use kdiff3, and it takes >> just a few seconds to solve the conflicts usually (for Misc/NEWS is >> ctrl+2, ctrl+3, ctrl+s, alt+f4, that roughly translates too "include >> both the conflicting news, save and quit). > > Since I have perhaps never gotten that sequence right, that info will be > helpful. > Glad to help, however I got it the other way around. The 1st pane is the parent and you can just ignore it; the 2nd pane is the local copy and the 3rd pane is the one from the previous branch that you are merging. The bottom pane will be the resulting file. For Misc/NEWS (the file that usually conflicts), you want the newest NEWS entry first, so you do ctrl+3 to get the one you just added, and ctrl+2 to get the one that was there already. Note that for other files you usually want to get only one of the versions, usually the one you have in the 3rd pane, so that sequence only applies to Misc/NEWS. Another tip is to use ctrl+q instead of alt+f4. >> If you do it from cmd/file manager hg should see it as missing ('!' in >> "hg status") and you can use "hg revert Misc/NEWS" to restore it. > > This. > > Thanks for trying to help. I will let you know if there are any more > problems after the re-clone. > Sure, and if you find part of the devguide that are not clear let me know (I also just uploaded a new patch to http://bugs.python.org/issue14468 to add a few new Mercurial FAQs to the devguide). Best Regards, Ezio Melotti > I still need to comment on the tcl/tk.dll and tkinter situation, but will > just mention now that I ran the four test_txxxx files on 3.3a0 (on Windows) > and they seemed to finish and be ok other than altering the environment. > > > Terry From python-checkins at python.org Wed Mar 13 16:27:53 2013 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 13 Mar 2013 16:27:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_expose_O=5FPATH_if_possibl?= =?utf-8?q?e?= Message-ID: <3ZQxkx0LvRzQXR@mail.python.org> http://hg.python.org/cpython/rev/38e263d40d81 changeset: 82641:38e263d40d81 user: Benjamin Peterson date: Wed Mar 13 10:27:41 2013 -0500 summary: expose O_PATH if possible files: Doc/library/os.rst | 1 + Misc/NEWS | 2 ++ Modules/posixmodule.c | 3 +++ 3 files changed, 6 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 @@ -1137,6 +1137,7 @@ O_DIRECTORY O_NOFOLLOW O_NOATIME + O_PATH These constants are GNU extensions and not present if they are not defined by the C library. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -277,6 +277,8 @@ Library ------- +- Expose the O_PATH constant in the os module if it is available. + - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -10858,6 +10858,9 @@ #ifdef O_SEARCH if (ins(d, "O_SEARCH", (long)O_SEARCH)) return -1; #endif +#ifdef O_PATH + if (ins(d, "O_PATH", (long)O_PATH)) return -1; +#endif #ifdef O_TTY_INIT if (ins(d, "O_TTY_INIT", (long)O_TTY_INIT)) return -1; #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 17:38:26 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 17:38:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317222=3A_Document?= =?utf-8?q?_that_py=5Fcompile_now_uses_importlib_for_its_file?= Message-ID: <3ZQzJL3wFxzR0D@mail.python.org> http://hg.python.org/cpython/rev/55806d234653 changeset: 82642:55806d234653 user: Brett Cannon date: Wed Mar 13 09:37:42 2013 -0700 summary: Issue #17222: Document that py_compile now uses importlib for its file writing and thus its semantics. files: Doc/library/py_compile.rst | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -28,7 +28,7 @@ .. function:: compile(file, cfile=None, dfile=None, doraise=False, optimize=-1) - Compile a source file to byte-code and write out the byte-code cache file. + Compile a source file to byte-code and write out the byte-code cache file. The source code is loaded from the file name *file*. The byte-code is written to *cfile*, which defaults to the :PEP:`3147` path, ending in ``.pyc`` (``.pyo`` if optimization is enabled in the current interpreter). @@ -50,6 +50,11 @@ default was *file* + ``'c'`` (``'o'`` if optimization was enabled). Also added the *optimize* parameter. + .. versionchanged:: 3.4 + Changed code to use :mod:`importlib` for the byte-code cache file writing. + This means file creation/writing semantics now match what :mod:`importlib` + does, e.g. permissions, write-and-move semantics, etc. + .. function:: main(args=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 18:45:47 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 18:45:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317117=3A_Have_bot?= =?utf-8?q?h_import_itself_and_importlib=2Eutil=2Eset=5Floader=28=29?= Message-ID: <3ZR0p30JwfzQrp@mail.python.org> http://hg.python.org/cpython/rev/7647aae9481c changeset: 82643:7647aae9481c user: Brett Cannon date: Wed Mar 13 10:41:36 2013 -0700 summary: Issue #17117: Have both import itself and importlib.util.set_loader() set __loader__ on a module when set to None. Thanks to G?kcen Eraslan for the fix. files: Doc/library/importlib.rst | 4 + Doc/reference/import.rst | 16 +- Lib/importlib/_bootstrap.py | 9 +- Lib/test/test_importlib/import_/test___loader__.py | 44 + Lib/test/test_importlib/test_util.py | 42 +- Misc/ACKS | 1 + Misc/NEWS | 3 + Python/importlib.h | 6699 ++++----- 8 files changed, 3443 insertions(+), 3375 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -774,6 +774,10 @@ It is recommended that :func:`module_for_loader` be used over this decorator as it subsumes this functionality. + .. versionchanged:: 3.4 + Set ``__loader__`` if set to ``None`` as well if the attribute does not + exist. + .. decorator:: set_package diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -369,16 +369,18 @@ * The ``__loader__`` attribute must be set to the loader object that loaded the module. This is mostly for introspection and reloading, but can be used for additional loader-specific functionality, for example getting - data associated with a loader. + data associated with a loader. If the attribute is missing or set to ``None`` + then the import machinery will automatically set it **after** the module has + been imported. - * The module's ``__package__`` attribute should be set. Its value must be a + * The module's ``__package__`` attribute must be set. Its value must be a string, but it can be the same value as its ``__name__``. If the attribute is set to ``None`` or is missing, the import system will fill it in with a - more appropriate value. When the module is a package, its ``__package__`` - value should be set to its ``__name__``. When the module is not a package, - ``__package__`` should be set to the empty string for top-level modules, or - for submodules, to the parent package's name. See :pep:`366` for further - details. + more appropriate value **after** the module has been imported. + When the module is a package, its ``__package__`` value should be set to its + ``__name__``. When the module is not a package, ``__package__`` should be + set to the empty string for top-level modules, or for submodules, to the + parent package's name. See :pep:`366` for further details. This attribute is used instead of ``__name__`` to calculate explicit relative imports for main modules, as defined in :pep:`366`. diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -494,7 +494,7 @@ """Set __loader__ on the returned module.""" def set_loader_wrapper(self, *args, **kwargs): module = fxn(self, *args, **kwargs) - if not hasattr(module, '__loader__'): + if getattr(module, '__loader__', None) is None: module.__loader__ = self return module _wrap(set_loader_wrapper, fxn) @@ -875,12 +875,9 @@ module.__cached__ = module.__file__ else: module.__cached__ = module.__file__ - module.__package__ = name if self.is_package(name): module.__path__ = [_path_split(module.__file__)[0]] - else: - module.__package__ = module.__package__.rpartition('.')[0] - module.__loader__ = self + # __package__ and __loader set by @module_for_loader. _call_with_frames_removed(exec, code_object, module.__dict__) return module @@ -1551,7 +1548,7 @@ except AttributeError: pass # Set loader if need be. - if not hasattr(module, '__loader__'): + if getattr(module, '__loader__', None) is None: try: module.__loader__ = loader except AttributeError: diff --git a/Lib/test/test_importlib/import_/test___loader__.py b/Lib/test/test_importlib/import_/test___loader__.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_importlib/import_/test___loader__.py @@ -0,0 +1,44 @@ +import imp +import sys +import unittest + +from .. import util +from . import util as import_util + + +class LoaderMock: + + def find_module(self, fullname, path=None): + return self + + def load_module(self, fullname): + sys.modules[fullname] = self.module + return self.module + + +class LoaderAttributeTests(unittest.TestCase): + + def test___loader___missing(self): + module = imp.new_module('blah') + try: + del module.__loader__ + except AttributeError: + pass + loader = LoaderMock() + loader.module = module + with util.uncache('blah'), util.import_state(meta_path=[loader]): + module = import_util.import_('blah') + self.assertEqual(loader, module.__loader__) + + def test___loader___is_None(self): + module = imp.new_module('blah') + module.__loader__ = None + loader = LoaderMock() + loader.module = module + with util.uncache('blah'), util.import_state(meta_path=[loader]): + returned_module = import_util.import_('blah') + self.assertEqual(loader, module.__loader__) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -162,6 +162,37 @@ self.assertEqual(wrapped.__qualname__, fxn.__qualname__) +class SetLoaderTests(unittest.TestCase): + + """Tests importlib.util.set_loader().""" + + class DummyLoader: + @util.set_loader + def load_module(self, module): + return self.module + + def test_no_attribute(self): + loader = self.DummyLoader() + loader.module = imp.new_module('blah') + try: + del loader.module.__loader__ + except AttributeError: + pass + self.assertEqual(loader, loader.load_module('blah').__loader__) + + def test_attribute_is_None(self): + loader = self.DummyLoader() + loader.module = imp.new_module('blah') + loader.module.__loader__ = None + self.assertEqual(loader, loader.load_module('blah').__loader__) + + def test_not_reset(self): + loader = self.DummyLoader() + loader.module = imp.new_module('blah') + loader.module.__loader__ = 42 + self.assertEqual(42, loader.load_module('blah').__loader__) + + class ResolveNameTests(unittest.TestCase): """Tests importlib.util.resolve_name().""" @@ -195,14 +226,5 @@ util.resolve_name('..bacon', 'spam') -def test_main(): - from test import support - support.run_unittest( - ModuleForLoaderTests, - SetPackageTests, - ResolveNameTests - ) - - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -339,6 +339,7 @@ Jeff Epler Jeff McNeil Tom Epperly +G?kcen Eraslan Stoffel Erasmus J?rgen A. Erhard Michael Ernst diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #17117: Import and @importlib.util.set_loader now set __loader__ when + it has a value of None or the attribute doesn't exist. + - Issue #17327: Add PyDict_SetDefault. - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 18:45:48 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 18:45:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Normalize_whitespace?= Message-ID: <3ZR0p435yqzR3K@mail.python.org> http://hg.python.org/cpython/rev/abbc9ae0a384 changeset: 82644:abbc9ae0a384 user: Brett Cannon date: Wed Mar 13 10:45:33 2013 -0700 summary: Normalize whitespace files: Lib/test/test_importlib/import_/test___loader__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/import_/test___loader__.py b/Lib/test/test_importlib/import_/test___loader__.py --- a/Lib/test/test_importlib/import_/test___loader__.py +++ b/Lib/test/test_importlib/import_/test___loader__.py @@ -41,4 +41,4 @@ if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 19:03:08 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 19:03:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317176=3A_Document?= =?utf-8?q?_that_imp=2ENullImporter_is_no_longer_inserted?= Message-ID: <3ZR1B42ny7zRRj@mail.python.org> http://hg.python.org/cpython/rev/8e390e4784b0 changeset: 82645:8e390e4784b0 user: Brett Cannon date: Wed Mar 13 10:46:22 2013 -0700 summary: Issue #17176: Document that imp.NullImporter is no longer inserted into sys.path_importer_cache. files: Doc/library/imp.rst | 9 +++++---- Doc/library/sys.rst | 9 ++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -326,16 +326,17 @@ with an existing directory or empty string raises :exc:`ImportError`. Otherwise, a :class:`NullImporter` instance is returned. - Python adds instances of this type to ``sys.path_importer_cache`` for any path - entries that are not directories and are not handled by any other path hooks on - ``sys.path_hooks``. Instances have only one method: - + Instances have only one method: .. method:: NullImporter.find_module(fullname [, path]) This method always returns ``None``, indicating that the requested module could not be found. + .. versionchanged:: 3.3 + ``None`` is inserted into ``sys.path_importer_cache`` instead of an + instance of :class:`NullImporter`. + .. _examples-imp: diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -785,12 +785,15 @@ A dictionary acting as a cache for :term:`finder` objects. The keys are paths that have been passed to :data:`sys.path_hooks` and the values are the finders that are found. If a path is a valid file system path but no - explicit finder is found on :data:`sys.path_hooks` then ``None`` is - stored to represent the implicit default finder should be used. If the path - is not an existing path then :class:`imp.NullImporter` is set. + finder is found on :data:`sys.path_hooks` then ``None`` is + stored. Originally specified in :pep:`302`. + .. versionchanged:: 3.3 + ``None`` is stored instead of :class:`imp.NullImporter` when no finder + is found. + .. data:: platform -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 19:03:09 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 19:03:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3MTc2?= =?utf-8?q?=3A_Document_that_imp=2ENullImporter_is_no_longer?= Message-ID: <3ZR1B55YntzRXb@mail.python.org> http://hg.python.org/cpython/rev/e470370b4701 changeset: 82646:e470370b4701 branch: 3.3 parent: 82639:bf0632a17ab4 user: Brett Cannon date: Wed Mar 13 10:58:50 2013 -0700 summary: Issue #17176: Document that imp.NullImporter is no longer automatically used by import. files: Doc/library/imp.rst | 9 +++++---- Doc/library/sys.rst | 9 ++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -326,16 +326,17 @@ with an existing directory or empty string raises :exc:`ImportError`. Otherwise, a :class:`NullImporter` instance is returned. - Python adds instances of this type to ``sys.path_importer_cache`` for any path - entries that are not directories and are not handled by any other path hooks on - ``sys.path_hooks``. Instances have only one method: - + Instances have only one method: .. method:: NullImporter.find_module(fullname [, path]) This method always returns ``None``, indicating that the requested module could not be found. + .. versionchanged:: 3.3 + ``None`` is inserted into ``sys.path_importer_cache`` instead of an + instance of :class:`NullImporter`. + .. _examples-imp: diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -770,12 +770,15 @@ A dictionary acting as a cache for :term:`finder` objects. The keys are paths that have been passed to :data:`sys.path_hooks` and the values are the finders that are found. If a path is a valid file system path but no - explicit finder is found on :data:`sys.path_hooks` then ``None`` is - stored to represent the implicit default finder should be used. If the path - is not an existing path then :class:`imp.NullImporter` is set. + finder is found on :data:`sys.path_hooks` then ``None`` is + stored. Originally specified in :pep:`302`. + .. versionchanged:: 3.3 + ``None`` is stored instead of :class:`imp.NullImporter` when no finder + is found. + .. data:: platform -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 19:03:11 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 19:03:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3ZR1B71NVXzQrp@mail.python.org> http://hg.python.org/cpython/rev/d965366e5ebd changeset: 82647:d965366e5ebd parent: 82645:8e390e4784b0 parent: 82646:e470370b4701 user: Brett Cannon date: Wed Mar 13 11:02:29 2013 -0700 summary: merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 19:09:58 2013 From: python-checkins at python.org (brett.cannon) Date: Wed, 13 Mar 2013 19:09:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317099=3A_Have_imp?= =?utf-8?q?ortlib=2Efind=5Floader=28=29_raise_ValueError_when?= Message-ID: <3ZR1Ky6LGLzRHR@mail.python.org> http://hg.python.org/cpython/rev/cee04627bdd0 changeset: 82648:cee04627bdd0 user: Brett Cannon date: Wed Mar 13 11:09:08 2013 -0700 summary: Issue #17099: Have importlib.find_loader() raise ValueError when __loader__ is not set on a module. This brings the exception in line with when __loader__ is None (which is equivalent to not having the attribute defined). files: Doc/library/importlib.rst | 8 +++++++- Lib/importlib/__init__.py | 2 ++ Lib/test/test_importlib/test_api.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ 4 files changed, 26 insertions(+), 1 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -90,7 +90,7 @@ Find the loader for a module, optionally within the specified *path*. If the module is in :attr:`sys.modules`, then ``sys.modules[name].__loader__`` is - returned (unless the loader would be ``None``, in which case + returned (unless the loader would be ``None`` or is not set, in which case :exc:`ValueError` is raised). Otherwise a search using :attr:`sys.meta_path` is done. ``None`` is returned if no loader is found. @@ -99,6 +99,12 @@ will need to import all parent packages of the submodule and use the correct argument to *path*. + .. versionadded:: 3.3 + + .. versionchanged:: 3.4 + If ``__loader__`` is not set, raise :exc:`ValueError`, just like when the + attribute is set to ``None``. + .. function:: invalidate_caches() Invalidate the internal caches of finders stored at diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -68,6 +68,8 @@ return loader except KeyError: pass + except AttributeError: + raise ValueError('{}.__loader__ is not set'.format(name)) return _bootstrap._find_module(name, path) diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -116,6 +116,20 @@ with self.assertRaises(ValueError): importlib.find_loader(name) + def test_sys_modules_loader_is_not_set(self): + # Should raise ValueError + # Issue #17099 + name = 'some_mod' + with util.uncache(name): + module = imp.new_module(name) + try: + del module.__loader__ + except AttributeError: + pass + sys.modules[name] = module + with self.assertRaises(ValueError): + importlib.find_loader(name) + def test_success(self): # Return the loader found on sys.meta_path. name = 'some_mod' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,9 @@ Library ------- +- Issue #17099: Have importlib.find_loader() raise ValueError when __loader__ + is not set, harmonizing with what happens when the attribute is set to None. + - Expose the O_PATH constant in the os module if it is available. - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 20:06:50 2013 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 13 Mar 2013 20:06:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_make_some_freezing_related?= =?utf-8?q?_stuff_const?= Message-ID: <3ZR2bZ6yhbzR0j@mail.python.org> http://hg.python.org/cpython/rev/a06fc2c2342a changeset: 82649:a06fc2c2342a user: Benjamin Peterson date: Wed Mar 13 14:06:39 2013 -0500 summary: make some freezing related stuff const files: Include/import.h | 6 +++--- Modules/_freeze_importlib.c | 6 +++--- Python/frozen.c | 4 ++-- Python/importlib.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Include/import.h b/Include/import.h --- a/Include/import.h +++ b/Include/import.h @@ -113,15 +113,15 @@ #ifndef Py_LIMITED_API struct _frozen { - char *name; /* ASCII encoded string */ - unsigned char *code; + const char *name; /* ASCII encoded string */ + const unsigned char *code; int size; }; /* Embedding apps may change this pointer to point to their favorite collection of frozen modules: */ -PyAPI_DATA(struct _frozen *) PyImport_FrozenModules; +PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules; #endif #ifdef __cplusplus diff --git a/Modules/_freeze_importlib.c b/Modules/_freeze_importlib.c --- a/Modules/_freeze_importlib.c +++ b/Modules/_freeze_importlib.c @@ -17,7 +17,7 @@ of frozen modules instead, left deliberately blank so as to avoid unintentional import of a stale version of _frozen_importlib. */ -static struct _frozen _PyImport_FrozenModules[] = { +const static struct _frozen _PyImport_FrozenModules[] = { {0, 0, 0} /* sentinel */ }; @@ -25,7 +25,7 @@ /* On Windows, this links with the regular pythonXY.dll, so this variable comes from frozen.obj. In the Makefile, frozen.o is not linked into this executable, so we define the variable here. */ -struct _frozen *PyImport_FrozenModules; +const struct _frozen *PyImport_FrozenModules; #endif const char header[] = "/* Auto-generated by Modules/_freeze_importlib.c */"; @@ -105,7 +105,7 @@ return 1; } fprintf(outfile, "%s\n", header); - fprintf(outfile, "unsigned char _Py_M__importlib[] = {\n"); + fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n"); for (n = 0; n < data_size; n += 16) { size_t i, end = Py_MIN(n + 16, data_size); fprintf(outfile, " "); diff --git a/Python/frozen.c b/Python/frozen.c --- a/Python/frozen.c +++ b/Python/frozen.c @@ -28,7 +28,7 @@ #define SIZE (int)sizeof(M___hello__) -static struct _frozen _PyImport_FrozenModules[] = { +static const struct _frozen _PyImport_FrozenModules[] = { /* importlib */ {"_frozen_importlib", _Py_M__importlib, (int)sizeof(_Py_M__importlib)}, /* Test module */ @@ -42,4 +42,4 @@ /* Embedding apps may change this pointer to point to their favorite collection of frozen modules: */ -struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules; +const struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 21:40:31 2013 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 13 Mar 2013 21:40:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE3MzA3IC0gRXhh?= =?utf-8?q?mple_of_HTTP_PUT_Request_using_httplib?= Message-ID: <3ZR4gg1Q80zR34@mail.python.org> http://hg.python.org/cpython/rev/4edde40afee6 changeset: 82650:4edde40afee6 branch: 2.7 parent: 82637:c226133b1493 user: Senthil Kumaran date: Wed Mar 13 13:30:25 2013 -0700 summary: #17307 - Example of HTTP PUT Request using httplib files: Doc/library/httplib.rst | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Doc/library/httplib.rst b/Doc/library/httplib.rst --- a/Doc/library/httplib.rst +++ b/Doc/library/httplib.rst @@ -612,3 +612,20 @@ 'Redirecting to http://bugs.python.org/issue12524' >>> conn.close() +Client side ``HTTP PUT`` requests are very similar to ``POST`` requests. The +difference lies only the server side where HTTP server will allow resources to +be created via ``PUT`` request. Here is an example session that shows how to do +``PUT`` request using httplib:: + + >>> # This creates an HTTP message + >>> # with the content of BODY as the enclosed representation + >>> # for the resource http://localhost:8080/foobar + ... + >>> import httplib + >>> BODY = "***filecontents***" + >>> conn = httplib.HTTPConnection("localhost", 8080) + >>> conn.request("PUT", "/file", BODY) + >>> response = conn.getresponse() + >>> print resp.status, response.reason + 200, OK + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 21:40:32 2013 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 13 Mar 2013 21:40:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3MzA3IC0gRXhh?= =?utf-8?q?mple_of_HTTP_PUT_Request_using_http=2Eclient?= Message-ID: <3ZR4gh44PZzRFH@mail.python.org> http://hg.python.org/cpython/rev/d4ab6556ff97 changeset: 82651:d4ab6556ff97 branch: 3.2 parent: 82638:df27ea4bdebd user: Senthil Kumaran date: Wed Mar 13 13:38:33 2013 -0700 summary: #17307 - Example of HTTP PUT Request using http.client files: Doc/library/http.client.rst | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -612,6 +612,22 @@ b'Redirecting to http://bugs.python.org/issue12524' >>> conn.close() +Client side ``HTTP PUT`` requests are very similar to ``POST`` requests. The +difference lies only the server side where HTTP server will allow resources to +be created via ``PUT`` request. Here is an example session that shows how to do +``PUT`` request using http.client:: + + >>> # This creates an HTTP message + >>> # with the content of BODY as the enclosed representation + >>> # for the resource http://localhost:8080/foobar + ... + >>> import http.client + >>> BODY = "***filecontents***" + >>> conn = http.client.HTTPConnection("localhost", 8080) + >>> conn.request("PUT", "/file", BODY) + >>> response = conn.getresponse() + >>> print(resp.status, response.reason) + 200, OK .. _httpmessage-objects: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 21:40:34 2013 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 13 Mar 2013 21:40:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2317307_-_merge_from_3=2E2?= Message-ID: <3ZR4gk04ydzRRj@mail.python.org> http://hg.python.org/cpython/rev/9941a9bbfeb6 changeset: 82652:9941a9bbfeb6 branch: 3.3 parent: 82646:e470370b4701 parent: 82651:d4ab6556ff97 user: Senthil Kumaran date: Wed Mar 13 13:42:47 2013 -0700 summary: #17307 - merge from 3.2 files: Doc/library/http.client.rst | 18 ++++++++++++++++++ Doc/library/urllib.request.rst | 9 +++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -633,6 +633,24 @@ b'Redirecting to http://bugs.python.org/issue12524' >>> conn.close() +Client side ``HTTP PUT`` requests are very similar to ``POST`` requests. The +difference lies only the server side where HTTP server will allow resources to +be created via ``PUT`` request. It should be noted that custom HTTP methods ++are also handled in :class:`urllib.request.Request` by sending the appropriate ++method attribute.Here is an example session that shows how to do ``PUT`` +request using http.client:: + + >>> # This creates an HTTP message + >>> # with the content of BODY as the enclosed representation + >>> # for the resource http://localhost:8080/foobar + ... + >>> import http.client + >>> BODY = "***filecontents***" + >>> conn = http.client.HTTPConnection("localhost", 8080) + >>> conn.request("PUT", "/file", BODY) + >>> response = conn.getresponse() + >>> print(resp.status, response.reason) + 200, OK .. _httpmessage-objects: diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -1109,6 +1109,15 @@ data = sys.stdin.read() print('Content-type: text-plain\n\nGot Data: "%s"' % data) +Here is an example of doing a ``PUT`` request using :class:`Request`:: + + import urllib.request + DATA=b'some data' + req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT') + f = urllib.request.urlopen(req) + print(f.status) + print(f.reason) + Use of Basic HTTP Authentication:: import urllib.request -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Mar 13 21:40:35 2013 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 13 Mar 2013 21:40:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=2317307_-_merge_from_3=2E3?= Message-ID: <3ZR4gl4wq0zRH1@mail.python.org> http://hg.python.org/cpython/rev/57e5409a998e changeset: 82653:57e5409a998e parent: 82649:a06fc2c2342a parent: 82652:9941a9bbfeb6 user: Senthil Kumaran date: Wed Mar 13 13:43:23 2013 -0700 summary: #17307 - merge from 3.3 files: Doc/library/http.client.rst | 18 ++++++++++++++++++ Doc/library/urllib.request.rst | 9 +++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -633,6 +633,24 @@ b'Redirecting to http://bugs.python.org/issue12524' >>> conn.close() +Client side ``HTTP PUT`` requests are very similar to ``POST`` requests. The +difference lies only the server side where HTTP server will allow resources to +be created via ``PUT`` request. It should be noted that custom HTTP methods ++are also handled in :class:`urllib.request.Request` by sending the appropriate ++method attribute.Here is an example session that shows how to do ``PUT`` +request using http.client:: + + >>> # This creates an HTTP message + >>> # with the content of BODY as the enclosed representation + >>> # for the resource http://localhost:8080/foobar + ... + >>> import http.client + >>> BODY = "***filecontents***" + >>> conn = http.client.HTTPConnection("localhost", 8080) + >>> conn.request("PUT", "/file", BODY) + >>> response = conn.getresponse() + >>> print(resp.status, response.reason) + 200, OK .. _httpmessage-objects: diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -1141,6 +1141,15 @@ data = sys.stdin.read() print('Content-type: text-plain\n\nGot Data: "%s"' % data) +Here is an example of doing a ``PUT`` request using :class:`Request`:: + + import urllib.request + DATA=b'some data' + req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT') + f = urllib.request.urlopen(req) + print(f.status) + print(f.reason) + Use of Basic HTTP Authentication:: import urllib.request -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 02:42:09 2013 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 Mar 2013 02:42:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3Mzg2?= =?utf-8?q?_make=2Ebat_must_run_with_Python_2_until_Sphinx_runs_with_Pytho?= =?utf-8?q?n_3=2E?= Message-ID: <3ZRCMj04XJzRH1@mail.python.org> http://hg.python.org/cpython/rev/9b45873e5a68 changeset: 82654:9b45873e5a68 branch: 3.2 parent: 82651:d4ab6556ff97 user: Terry Jan Reedy date: Wed Mar 13 21:33:50 2013 -0400 summary: Issue #17386 make.bat must run with Python 2 until Sphinx runs with Python 3. If PYTHON is undefined, this fails without the launcher (installed with 3.3 or from PyPI), but this is better than always failing. Patch from Zachary Ware. files: Doc/make.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -2,7 +2,7 @@ setlocal set SVNROOT=http://svn.python.org/projects -if "%PYTHON%" EQU "" set PYTHON=..\pcbuild\python +if "%PYTHON%" EQU "" set PYTHON=py -2 if "%HTMLHELP%" EQU "" set HTMLHELP=%ProgramFiles%\HTML Help Workshop\hhc.exe if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/sphinxext/patchlevel.py`) do set DISTVERSION=%%v -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 02:42:10 2013 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 Mar 2013 02:42:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_with_3=2E2=3A_Issue_=2317386?= Message-ID: <3ZRCMk2qjBzRx7@mail.python.org> http://hg.python.org/cpython/rev/e45db319e590 changeset: 82655:e45db319e590 branch: 3.3 parent: 82652:9941a9bbfeb6 parent: 82654:9b45873e5a68 user: Terry Jan Reedy date: Wed Mar 13 21:35:07 2013 -0400 summary: Merge with 3.2: Issue #17386 files: Doc/make.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -2,7 +2,7 @@ setlocal set SVNROOT=http://svn.python.org/projects -if "%PYTHON%" EQU "" set PYTHON=..\pcbuild\python +if "%PYTHON%" EQU "" set PYTHON=py -2 if "%HTMLHELP%" EQU "" set HTMLHELP=%ProgramFiles%\HTML Help Workshop\hhc.exe if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/sphinxext/patchlevel.py`) do set DISTVERSION=%%v -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 02:42:11 2013 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 Mar 2013 02:42:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3=3A_Issue_=2317386?= Message-ID: <3ZRCMl5WJGzRwZ@mail.python.org> http://hg.python.org/cpython/rev/99e72eae35bb changeset: 82656:99e72eae35bb parent: 82653:57e5409a998e parent: 82655:e45db319e590 user: Terry Jan Reedy date: Wed Mar 13 21:35:46 2013 -0400 summary: Merge with 3.3: Issue #17386 files: Doc/make.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -2,7 +2,7 @@ setlocal set SVNROOT=http://svn.python.org/projects -if "%PYTHON%" EQU "" set PYTHON=..\pcbuild\python +if "%PYTHON%" EQU "" set PYTHON=py -2 if "%HTMLHELP%" EQU "" set HTMLHELP=%ProgramFiles%\HTML Help Workshop\hhc.exe if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/sphinxext/patchlevel.py`) do set DISTVERSION=%%v -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Mar 14 06:01:52 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 14 Mar 2013 06:01:52 +0100 Subject: [Python-checkins] Daily reference leaks (99e72eae35bb): sum=2 Message-ID: results for 99e72eae35bb on branch "default" -------------------------------------------- test_unittest leaked [-1, 2, 1] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogATjIgq', '-x'] From python-checkins at python.org Thu Mar 14 06:43:35 2013 From: python-checkins at python.org (nick.coghlan) Date: Thu, 14 Mar 2013 06:43:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_PEP_headers?= Message-ID: <3ZRJkH2TbhzS00@mail.python.org> http://hg.python.org/peps/rev/f9164cc21a74 changeset: 4794:f9164cc21a74 user: Nick Coghlan date: Wed Mar 13 22:43:28 2013 -0700 summary: Fix PEP headers files: pep-0425.txt | 4 ++-- pep-0427.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0425.txt b/pep-0425.txt --- a/pep-0425.txt +++ b/pep-0425.txt @@ -2,7 +2,7 @@ Title: Compatibility Tags for Built Distributions Version: $Revision$ Last-Modified: 07-Aug-2012 -Author: Daniel Holth BDFL-Delegate: Nick Coghlan Status: Accepted Type: Standards Track @@ -265,7 +265,7 @@ implentation at the time of writing guesses "none". Ideally it would detect "py27(d|m|u)" analagous to newer versions of Python, but in the meantime "none" is a good enough way to say "don't know". - + References ========== diff --git a/pep-0427.txt b/pep-0427.txt --- a/pep-0427.txt +++ b/pep-0427.txt @@ -2,7 +2,7 @@ Title: The Wheel Binary Package Format 1.0 Version: $Revision$ Last-Modified: $Date$ -Author: Daniel Holth +Author: Daniel Holth BDFL-Delegate: Nick Coghlan Discussions-To: Status: Accepted -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 06:54:30 2013 From: python-checkins at python.org (nick.coghlan) Date: Thu, 14 Mar 2013 06:54:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_alternative_argument_clin?= =?utf-8?q?ic_DSL_PEP?= Message-ID: <3ZRJyt3fHqzS1Q@mail.python.org> http://hg.python.org/peps/rev/46f45025b61f changeset: 4795:46f45025b61f user: Nick Coghlan date: Wed Mar 13 22:54:21 2013 -0700 summary: Add alternative argument clinic DSL PEP files: pep-0437.txt | 359 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 359 insertions(+), 0 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt new file mode 100644 --- /dev/null +++ b/pep-0437.txt @@ -0,0 +1,359 @@ +PEP: 0437 +Title: A DSL for specifying signatures, annotations and argument converters +Version: $Revision$ +Last-Modified: $Date$ +Author: Stefan Krah +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 2013-03-11 +Python-Version: 3.4 +Post-History: +Resolution: + +Abstract +======== + +The Python C-API currently has no mechanism for specifying and auto-generating +function signatures, annotations or custom argument converters. + +There are several possible approaches to the problem. Cython uses *cdef* +definitions in *.pyx* files to generate the required information. However, +CPython's C-API functions often require additional initialization and +cleanup snippets that would be hard to specify in a *cdef*. + +PEP 436 proposes a domain specific language (DSL) enclosed in C comments +that largely resembles a per-parameter configuration file. A preprocessor +reads the comment and emits an argument parsing function, docstrings and +a header for the function that utilizes the results of the parsing step. + +The latter function is subsequently referred to as the *implementation +function*. + + +Rationale +========= + +Opinions differ regarding the suitability of the PEP 436 DSL in the context +of a C file. This PEP proposes an alternative DSL. The specific issues with +PEP 436 that spurred the counter proposal will be explained in the final +section of this PEP. + + +Scope +===== + +The PEP focuses exclusively on the DSL. Topics like the location of docstrings +are outside the scope of this PEP. It is however vital that the DSL is suitable +for generating custom argument parsers, a feature that is already implemented +in Cython. Therefore, one of the goals of this PEP is to keep the DSL close +to existing solutions, thus facilitating a possible inclusion of the relevant +parts of Cython into the CPython source tree. + + +DSL overview +============ + +Type safety and annotations +--------------------------- + +A conversion from a Python to a C value is fully defined by the type of +the converter function. The PyArg_Parse* family of functions accepts +custom converters in addition to the well-known default converters "i", +"f", etc. + +This PEP views the default converters as abstract functions, regardless +of how they are actually implemented. + + +Include/converters.h +-------------------- + +Converter functions must be forward-declared. All converter functions +shall be entered into the file Include/converters.h. The file is read +by the preprocessor prior to translating .c files. This is an excerpt:: + + /*[converter] + ##### Default converters ##### + "s": str -> const char *res; + "s*": [str, bytes, bytearray, rw_buffer] -> Py_buffer &res; + [...] + "es#": str -> (const char *res_encoding, char **res, Py_ssize_t *res_length); + [...] + ##### Custom converters ##### + path_converter: [str, bytes, int] -> path_t &res; + OS_STAT_DIR_FD_CONVERTER: [int, None] -> int res; + [converter_end]*/ + + +Converters are specified by their name, Python input type(s) and C output +type(s). Default converters must be have quoted names, custom converters +must have regular names. A Python type is given by its name. If a function +accepts multiple Python types, the set is written in list form. + +Since the default converters may have multiple implicit return values, +the C output type(s) are written according to the following convention: + +The main return value must be named *res*. This is a placeholder for +the actual variable name given later in the DSL. Additional implicit +return values must be prefixed by *res_*. + +By default the variables are passed by value to the implementation function. +If the address should be passed instead, *res* must be prefixed with an +ampersand. + + +Additional declarations may be placed into .c files. Duplicate declarations +are allowed as long as the function types are identical. + + +TBD: Make a list of fantasy types like *rw_buffer*. + + +Function specifications +----------------------- + +Keyword arguments +^^^^^^^^^^^^^^^^^ + +This example contains the definition of os.stat. The individual sections +will be explained in detail. Grammatically, the whole define block consists +of a function specification and an output section. The function specification +in turn consists of a declaration section, a C-declaration section and a +cleanup code section. Sections within the function specification are +separated in yacc style by '%%':: + + + /*[define posix_stat] + def os.stat(path: path_converter, *, dir_fd: OS_STAT_DIR_FD_CONVERTER = None, + follow_symlinks: "p" = True) -> os.stat_result: pass + %% + path_t path = PATH_T_INITIALIZE("stat", 0, 1); + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + %% + path_cleanup(&path); + [define_end]*/ + + + + /*[define_output_end]*/ + + +Define block +~~~~~~~~~~~~ + +The function specification block starts with a ``/*[define`` token, followed +by an optional C function name, followed by a right bracket. If the C function +name is not given, it is generated from the declaration name. In the example, +omitting the name *posix_stat* would result in a C function name of *os_stat*. + + +Declaration +~~~~~~~~~~~ + +The required declaration is (almost) a valid Python function definition. The +'def' keyword and the function body are redundant, but the author of this PEP +finds the definition more readable if they are present. + +The function name may be a path instead of a plain identifier. Each argument +is annotated with the name of the converter function that will be applied to it. + +Default values are given in the usual Python manner and may be any valid +Python expression. + +The return value may be any Python expression. Usually it will be the name +of an object, but alternative return values could be specified in list form. + + +C-declarations +~~~~~~~~~~~~~~ + +This section contains C variable declarations. Since the converter functions +have been declared beforehand, the preprocessor can type-check the declarations. + + +Cleanup +~~~~~~~ + +The cleanup section contains literal C code that will be inserted unmodified +after the implementation function. + + +Output +~~~~~~ + +The output section contains the code emitted by the preprocessor. + + +Positional-only arguments +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Functions that do not take keyword arguments are indicated by the presence +of the *slash* special parameter:: + + /*[define stat_float_times] + def os.stat_float_times(/, newval: "i") -> os.stat_result: pass + %% + int newval = -1; + [define_end]*/ + +The preprocessor translates this definition to a PyArg_ParseTuple() call. +All arguments to the right of the slash are optional arguments. + + +Left and right optional arguments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some legacy functions contain optional arguments groups both to the left and +right of a central parameter. It is debatable whether a new tool should support +such functions. For completeness' sake, this is the proposed syntax:: + + /*[define] + def curses.window.addch(y: "i", x: "i", ch: "O", attr: "l") -> None + where groups = [[ch], [ch, attr], [y, x, ch], [y, x, ch, attr]] + %% + int newval = -1; + [define_end]*/ + +Here *ch* is the central parameter, *attr* can optionally be added on the +right, and the group [y, x] can optionally be added on the left. + +Essentially the rule is that all ordered combinations of the central +parameter and the optional groups must be possible such that no two +combinations have the same length. + +This is concisely expressed by putting the central parameter first in +the list and subsequently adding the optional arguments groups to the +left and right. + + +Flexibility in formatting +========================= + +If the above os.stat example is considered too compact, it can easily be +formatted this way:: + + /*[define posix_stat] + def os.stat(path: path_converter, + *, + dir_fd: OS_STAT_DIR_FD_CONVERTER = None, + follow_symlinks: "p" = True) + -> os.stat_result: pass + %% + path_t path = PATH_T_INITIALIZE("stat", 0, 1); + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + %% + path_cleanup(&path); + [define_end]*/ + + + + /*[define_output_end]*/ + + +Easy validation of the definition +================================= + +How can an inexperienced user validate a definition like os.stat? Simply +by changing os.stat to os_stat, defining missing converters and pasting +the definition into the Python interactive interpreter! + +In fact, a converters.py module could be auto-generated from converters.h. + + +Reference implementation +======================== + +A reference implementation is available at `issue 16612`_. Since this PEP +was written under time constraints and the author is unfamiliar with the +PLY toolchain, the software is written in Standard ML and utilizes the +ml-yacc/ml-lex toolchain. + +The grammar is conflict-free and available in ml-yacc readable BNF form. + +Two tools are available: + + * *printsemant* reads a converter header and a .c file and dumps + the semantically checked parse tree to stdout. + + * *preprocess* reads a converter header and a .c file and dumps + the preprocessed .c file to stdout. + + +Known deficiencies: + + * The Python 'test' expression is not semantically checked. The syntax + however is checked since it is part of the grammar. + + * The lexer does not handle triple quoted strings. + + * The *preprocess* tool does not emit code for the left-and-right optional + arguments case. The *printsemant* tool can deal with this case. + + * Since the *preprocess* tool generates the output from the parse + tree, the original indentation of the define block is lost. + + +Grammar +======= + + TBD: The grammar exists in ml-yacc readable form, but should probably be + included here in EBNF notation. + + +Comparison with PEP 436 +======================= + +The author of this PEP has the following concerns about the DSL proposed +in PEP 436: + + * The whitespace sensitive configuration file like syntax looks out + of place in a C file. + + * The structure of the function definition gets lost in the per-parameter + specifications. Keywords like positional-only, required and keyword-only + are scattered across too many different places. + + By contrast, in the alternative DSL the structure of the function + definition can be understood at a single glance. + + * The PEP 436 DSL has 14 documented flags and at least one undocumented + (allow_fd) flag. Figuring out which of the 2**15 possible combinations + are valid places an unnecessary burden on the user. + + Experience with the PEP-3118 buffer flags has shown that sorting out + (and exhaustively testing!) valid combinations is an extremely tedious + task. The PEP-3118 flags are still not well understood by many people. + + By contrast, the alternative DSL has a central file Include/converters.h + that can be quickly searched for the desired converter. Many of the + converters are already known, perhaps even memorized by people (due + to frequent use). + + * The PEP 436 DSL allows too much freedom. Types can apparently be omitted, + the preprocessor accepts (and ignores) unknown keywords, sometimes adding + white space after a docstring results in an assertion error. + + The alternative DSL on the other hand allows no such freedoms. Omitting + converter or return value annotations is plainly a syntax error. The + LALR(1) grammar is unambiguous and specified for the complete translation + unit. + + +Copyright +========= + +This document is licensed under the `Open Publication License`_. + + +References and Footnotes +======================== + +.. _issue 16612: http://bugs.python.org/issue16612 + +.. _Open Publication License: http://www.opencontent.org/openpub/ + + + -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 08:21:00 2013 From: python-checkins at python.org (ezio.melotti) Date: Thu, 14 Mar 2013 08:21:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_=2315121=3A_document_the_?= =?utf-8?q?=22email=22_component=2E?= Message-ID: <3ZRLth60cBzR0j@mail.python.org> http://hg.python.org/devguide/rev/2889f71c9e20 changeset: 610:2889f71c9e20 user: Ezio Melotti date: Thu Mar 14 09:20:48 2013 +0200 summary: #15121: document the "email" component. files: triaging.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/triaging.rst b/triaging.rst --- a/triaging.rst +++ b/triaging.rst @@ -90,6 +90,8 @@ The packaging module in `Lib/packaging`_. Documentation The documentation in Doc_ (used to build the HTML doc at http://docs.python.org/). +email + The email package and related modules. Extension Modules C modules in Modules_. IDLE -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Thu Mar 14 12:41:21 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 14 Mar 2013 12:41:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_-_Fix_typos_and_curses=2Ewind?= =?utf-8?q?ow=2Eaddch_definition=2E?= Message-ID: <3ZRSg50NZxzRnv@mail.python.org> http://hg.python.org/peps/rev/1c5f1077ab31 changeset: 4796:1c5f1077ab31 user: Stefan Krah date: Thu Mar 14 12:40:29 2013 +0100 summary: - Fix typos and curses.window.addch definition. - Point out that the C variable declaration and cleanup sections are in fact optional. - Mention that C declaration parsing needs to be improved in the reference implementation. files: pep-0437.txt | 35 ++++++++++++++++++----------------- 1 files changed, 18 insertions(+), 17 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -87,9 +87,9 @@ Converters are specified by their name, Python input type(s) and C output -type(s). Default converters must be have quoted names, custom converters -must have regular names. A Python type is given by its name. If a function -accepts multiple Python types, the set is written in list form. +type(s). Default converters must have quoted names, custom converters must +have regular names. A Python type is given by its name. If a function accepts +multiple Python types, the set is written in list form. Since the default converters may have multiple implicit return values, the C output type(s) are written according to the following convention: @@ -116,13 +116,12 @@ Keyword arguments ^^^^^^^^^^^^^^^^^ -This example contains the definition of os.stat. The individual sections -will be explained in detail. Grammatically, the whole define block consists -of a function specification and an output section. The function specification -in turn consists of a declaration section, a C-declaration section and a -cleanup code section. Sections within the function specification are -separated in yacc style by '%%':: - +This example contains the definition of os.stat. The individual sections will +be explained in detail. Grammatically, the whole define block consists of a +function specification and an output section. The function specification in +turn consists of a declaration section, an optional C-declaration section and +an optional cleanup code section. Sections within the function specification +are separated in yacc style by '%%':: /*[define posix_stat] def os.stat(path: path_converter, *, dir_fd: OS_STAT_DIR_FD_CONVERTER = None, @@ -169,15 +168,16 @@ C-declarations ~~~~~~~~~~~~~~ -This section contains C variable declarations. Since the converter functions -have been declared beforehand, the preprocessor can type-check the declarations. +This optional section contains C variable declarations. Since the converter +functions have been declared beforehand, the preprocessor can type-check +the declarations. Cleanup ~~~~~~~ -The cleanup section contains literal C code that will be inserted unmodified -after the implementation function. +The optional cleanup section contains literal C code that will be inserted +unmodified after the implementation function. Output @@ -210,10 +210,8 @@ such functions. For completeness' sake, this is the proposed syntax:: /*[define] - def curses.window.addch(y: "i", x: "i", ch: "O", attr: "l") -> None + def curses.window.addch(y: "i", x: "i", ch: "O", attr: "l") -> None: pass where groups = [[ch], [ch, attr], [y, x, ch], [y, x, ch, attr]] - %% - int newval = -1; [define_end]*/ Here *ch* is the central parameter, *attr* can optionally be added on the @@ -289,6 +287,9 @@ * The lexer does not handle triple quoted strings. + * C declarations are parsed in a primitive way. The final implementation + should utilize 'declarator' and 'init-declarator' from the C grammar. + * The *preprocess* tool does not emit code for the left-and-right optional arguments case. The *printsemant* tool can deal with this case. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 12:50:26 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 14 Mar 2013 12:50:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Make_it_clear_that_the_locati?= =?utf-8?q?on_of_the_docstring_*specification*_is_a_valid?= Message-ID: <3ZRSsZ2fMqzRw0@mail.python.org> http://hg.python.org/peps/rev/528a18494b0a changeset: 4797:528a18494b0a user: Stefan Krah date: Thu Mar 14 12:50:00 2013 +0100 summary: Make it clear that the location of the docstring *specification* is a valid topic for this PEP. After all, some people prefer to include docstrings inside the DSL comment. files: pep-0437.txt | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -43,12 +43,14 @@ Scope ===== -The PEP focuses exclusively on the DSL. Topics like the location of docstrings -are outside the scope of this PEP. It is however vital that the DSL is suitable -for generating custom argument parsers, a feature that is already implemented -in Cython. Therefore, one of the goals of this PEP is to keep the DSL close -to existing solutions, thus facilitating a possible inclusion of the relevant -parts of Cython into the CPython source tree. +The PEP focuses exclusively on the DSL. Topics like the output locations of +docstrings or the generated code are outside the scope of this PEP. + +It is however vital that the DSL is suitable for generating custom argument +parsers, a feature that is already implemented in Cython. Therefore, one of +the goals of this PEP is to keep the DSL close to existing solutions, thus +facilitating a possible inclusion of the relevant parts of Cython into the +CPython source tree. DSL overview -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 13:05:28 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 14 Mar 2013 13:05:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Mention_possibility_of_=28lim?= =?utf-8?q?ited!=29_type-checking_of_converter_definitions=2E?= Message-ID: <3ZRTBw6rFYzR2d@mail.python.org> http://hg.python.org/peps/rev/3256d33dbb4e changeset: 4798:3256d33dbb4e user: Stefan Krah date: Thu Mar 14 13:04:59 2013 +0100 summary: Mention possibility of (limited!) type-checking of converter definitions. files: pep-0437.txt | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -108,6 +108,10 @@ Additional declarations may be placed into .c files. Duplicate declarations are allowed as long as the function types are identical. +It is encouraged to declare custom converter types a second time right +above the converter function definition. The preprocessor will then catch +any mismatch between the declarations. + TBD: Make a list of fantasy types like *rw_buffer*. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 13:12:15 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 14 Mar 2013 13:12:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Deprecate_PY=5FSSIZE=5FT=5FCL?= =?utf-8?q?EAN=3A_Always_assume_Py=5Fssize=5Ft_for_length_arguments=2E?= Message-ID: <3ZRTLl2qlgzMKB@mail.python.org> http://hg.python.org/peps/rev/3980c63df840 changeset: 4799:3980c63df840 user: Stefan Krah date: Thu Mar 14 13:11:37 2013 +0100 summary: Deprecate PY_SSIZE_T_CLEAN: Always assume Py_ssize_t for length arguments. files: pep-0437.txt | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -113,6 +113,10 @@ any mismatch between the declarations. +In order to keep the converter complexity manageable, PY_SSIZE_T_CLEAN will +be deprecated and Py_ssize_t will be assumed for all length arguments. + + TBD: Make a list of fantasy types like *rw_buffer*. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 15:18:51 2013 From: python-checkins at python.org (stefan.krah) Date: Thu, 14 Mar 2013 15:18:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_fork=5Fexec_example=2E?= Message-ID: <3ZRX8q0yT5zQd9@mail.python.org> http://hg.python.org/peps/rev/06fe3dcc6f37 changeset: 4800:06fe3dcc6f37 user: Stefan Krah date: Thu Mar 14 15:18:24 2013 +0100 summary: Add fork_exec example. files: pep-0437.txt | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -261,6 +261,28 @@ /*[define_output_end]*/ +Benefits of a compact notation +============================== + +The advantages of a concise notation are especially obvious when a large +number of parameters is involved. The argument parsing part of +``_posixsubprocess.fork_exec`` is fully specified by this definition:: + + /*[define subprocess_fork_exec] + def _posixsubprocess.fork_exec( + process_args: "O", executable_list: "O", + close_fds: "p", py_fds_to_keep: "O", + cwd_obj: "O", env_list: "O", + p2cread: "i", p2cwrite: "i", c2pread: "i", c2pwrite: "i", + errread: "i", errwrite: "i", errpipe_read: "i", errpipe_write: "i", + restore_signals: "i", call_setsid: "i", preexec_fn: "i", /) -> int: pass + [define_end]*/ + + +Note that the *preprocess* tool currently emits a redundant C-declaration +section for this example, so the output is longer than necessary. + + Easy validation of the definition ================================= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Mar 14 19:59:48 2013 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 14 Mar 2013 19:59:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Mjk5?= =?utf-8?q?=3A_Add_test_coverage_for_cPickle_with_file_objects_and_general?= =?utf-8?q?_IO?= Message-ID: <3ZRfP063HhzRXs@mail.python.org> http://hg.python.org/cpython/rev/8a0b5c9f04c2 changeset: 82657:8a0b5c9f04c2 branch: 2.7 parent: 82650:4edde40afee6 user: Serhiy Storchaka date: Thu Mar 14 20:59:09 2013 +0200 summary: Issue #17299: Add test coverage for cPickle with file objects and general IO objects. Original patch by Aman Shah. files: Lib/test/test_cpickle.py | 135 ++++++++++++++++++++++----- Misc/ACKS | 1 + Misc/NEWS | 3 + 3 files changed, 114 insertions(+), 25 deletions(-) diff --git a/Lib/test/test_cpickle.py b/Lib/test/test_cpickle.py --- a/Lib/test/test_cpickle.py +++ b/Lib/test/test_cpickle.py @@ -1,11 +1,45 @@ -import cPickle, unittest -from cStringIO import StringIO +import cPickle +import cStringIO +import io +import unittest from test.pickletester import (AbstractPickleTests, AbstractPickleModuleTests, AbstractPicklerUnpicklerObjectTests, BigmemPickleTests) from test import test_support +class cStringIOMixin: + output = input = cStringIO.StringIO + + def close(self, f): + pass + +class BytesIOMixin: + output = input = io.BytesIO + + def close(self, f): + pass + +class FileIOMixin: + + def output(self): + return open(test_support.TESTFN, 'w+') + + def input(self, data): + f = open(test_support.TESTFN, 'w+') + try: + f.write(data) + f.seek(0) + return f + except: + f.close() + raise + + def close(self, f): + f.close() + test_support.unlink(test_support.TESTFN) + + class cPickleTests(AbstractPickleTests, AbstractPickleModuleTests): def setUp(self): @@ -18,19 +52,35 @@ class cPicklePicklerTests(AbstractPickleTests): def dumps(self, arg, proto=0): - f = StringIO() - p = cPickle.Pickler(f, proto) - p.dump(arg) - f.seek(0) - return f.read() + f = self.output() + try: + p = cPickle.Pickler(f, proto) + p.dump(arg) + f.seek(0) + return f.read() + finally: + self.close(f) def loads(self, buf): - f = StringIO(buf) - p = cPickle.Unpickler(f) - return p.load() + f = self.input(buf) + try: + p = cPickle.Unpickler(f) + return p.load() + finally: + self.close(f) error = cPickle.BadPickleGet +class cStringIOCPicklerTests(cStringIOMixin, cPicklePicklerTests): + pass + +class BytesIOCPicklerTests(BytesIOMixin, cPicklePicklerTests): + pass + +class FileIOCPicklerTests(FileIOMixin, cPicklePicklerTests): + pass + + class cPickleListPicklerTests(AbstractPickleTests): def dumps(self, arg, proto=0): @@ -39,26 +89,45 @@ return p.getvalue() def loads(self, *args): - f = StringIO(args[0]) - p = cPickle.Unpickler(f) - return p.load() + f = self.input(args[0]) + try: + p = cPickle.Unpickler(f) + return p.load() + finally: + self.close(f) error = cPickle.BadPickleGet +class cStringIOCPicklerListTests(cStringIOMixin, cPickleListPicklerTests): + pass + +class BytesIOCPicklerListTests(BytesIOMixin, cPickleListPicklerTests): + pass + +class FileIOCPicklerListTests(FileIOMixin, cPickleListPicklerTests): + pass + + class cPickleFastPicklerTests(AbstractPickleTests): def dumps(self, arg, proto=0): - f = StringIO() - p = cPickle.Pickler(f, proto) - p.fast = 1 - p.dump(arg) - f.seek(0) - return f.read() + f = self.output() + try: + p = cPickle.Pickler(f, proto) + p.fast = 1 + p.dump(arg) + f.seek(0) + return f.read() + finally: + self.close(f) def loads(self, *args): - f = StringIO(args[0]) - p = cPickle.Unpickler(f) - return p.load() + f = self.input(args[0]) + try: + p = cPickle.Unpickler(f) + return p.load() + finally: + self.close(f) error = cPickle.BadPickleGet @@ -98,6 +167,16 @@ b = self.loads(self.dumps(a)) self.assertEqual(a, b) +class cStringIOCPicklerFastTests(cStringIOMixin, cPickleFastPicklerTests): + pass + +class BytesIOCPicklerFastTests(BytesIOMixin, cPickleFastPicklerTests): + pass + +class FileIOCPicklerFastTests(FileIOMixin, cPickleFastPicklerTests): + pass + + class cPicklePicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests): pickler_class = cPickle.Pickler @@ -140,9 +219,15 @@ def test_main(): test_support.run_unittest( cPickleTests, - cPicklePicklerTests, - cPickleListPicklerTests, - cPickleFastPicklerTests, + cStringIOCPicklerTests, + BytesIOCPicklerTests, + FileIOCPicklerTests, + cStringIOCPicklerListTests, + BytesIOCPicklerListTests, + FileIOCPicklerListTests, + cStringIOCPicklerFastTests, + BytesIOCPicklerFastTests, + FileIOCPicklerFastTests, cPickleDeepRecursive, cPicklePicklerUnpicklerObjectTests, cPickleBigmemPickleTests, diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -910,6 +910,7 @@ Pete Sevander Denis Severson Ian Seyer +Aman Shah Ha Shao Mark Shannon Richard Shapiro diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -816,6 +816,9 @@ Tests ----- +- Issue #17299: Add test coverage for cPickle with file objects and general IO + objects. Original patch by Aman Shah. + - Issue #11963: remove human verification from test_parser and test_subprocess. - Issue #17249: convert a test in test_capi to use unittest and reap threads. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 20:43:29 2013 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 14 Mar 2013 20:43:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEyODUw?= =?utf-8?q?86=3A_Get_rid_of_the_refcounting_hack_and_speed_up_urllib=2Eunq?= =?utf-8?b?dW90ZSgpLg==?= Message-ID: <3ZRgMP2SxMzR5p@mail.python.org> http://hg.python.org/cpython/rev/4927899bea8d changeset: 82658:4927899bea8d branch: 2.7 user: Serhiy Storchaka date: Thu Mar 14 21:31:09 2013 +0200 summary: Issue #1285086: Get rid of the refcounting hack and speed up urllib.unquote(). files: Lib/urllib.py | 32 ++++++++++++++++++++------- Lib/urlparse.py | 42 +++++++++++++++++++++++++++++------- Misc/NEWS | 2 + 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/Lib/urllib.py b/Lib/urllib.py --- a/Lib/urllib.py +++ b/Lib/urllib.py @@ -28,6 +28,7 @@ import time import sys import base64 +import re from urlparse import urljoin as basejoin @@ -1198,22 +1199,35 @@ _hexdig = '0123456789ABCDEFabcdef' _hextochr = dict((a + b, chr(int(a + b, 16))) for a in _hexdig for b in _hexdig) +_asciire = re.compile('([\x00-\x7f]+)') def unquote(s): """unquote('abc%20def') -> 'abc def'.""" - res = s.split('%') + if _is_unicode(s): + if '%' not in s: + return s + bits = _asciire.split(s) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote(str(bits[i])).decode('latin1')) + append(bits[i + 1]) + return ''.join(res) + + bits = s.split('%') # fastpath - if len(res) == 1: + if len(bits) == 1: return s - s = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - s += _hextochr[item[:2]] + item[2:] + append(_hextochr[item[:2]]) + append(item[2:]) except KeyError: - s += '%' + item - except UnicodeDecodeError: - s += unichr(int(item[:2], 16)) + item[2:] - return s + append('%') + append(item) + return ''.join(res) def unquote_plus(s): """unquote('%7e/abc+def') -> '~/abc def'""" diff --git a/Lib/urlparse.py b/Lib/urlparse.py --- a/Lib/urlparse.py +++ b/Lib/urlparse.py @@ -28,6 +28,8 @@ """ +import re + __all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag", "urlsplit", "urlunsplit", "parse_qs", "parse_qsl"] @@ -311,6 +313,15 @@ else: return url, '' +try: + unicode +except NameError: + def _is_unicode(x): + return 0 +else: + def _is_unicode(x): + return isinstance(x, unicode) + # unquote method for parse_qs and parse_qsl # Cannot use directly from urllib as it would create a circular reference # because urllib uses urlparse methods (urljoin). If you update this function, @@ -319,22 +330,35 @@ _hexdig = '0123456789ABCDEFabcdef' _hextochr = dict((a+b, chr(int(a+b,16))) for a in _hexdig for b in _hexdig) +_asciire = re.compile('([\x00-\x7f]+)') def unquote(s): """unquote('abc%20def') -> 'abc def'.""" - res = s.split('%') + if _is_unicode(s): + if '%' not in s: + return s + bits = _asciire.split(s) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote(str(bits[i])).decode('latin1')) + append(bits[i + 1]) + return ''.join(res) + + bits = s.split('%') # fastpath - if len(res) == 1: + if len(bits) == 1: return s - s = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - s += _hextochr[item[:2]] + item[2:] + append(_hextochr[item[:2]]) + append(item[2:]) except KeyError: - s += '%' + item - except UnicodeDecodeError: - s += unichr(int(item[:2], 16)) + item[2:] - return s + append('%') + append(item) + return ''.join(res) def parse_qs(qs, keep_blank_values=0, strict_parsing=0): """Parse a query given as a string argument. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,6 +214,8 @@ Library ------- +- Issue #1285086: Get rid of the refcounting hack and speed up urllib.unquote(). + - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 20:43:30 2013 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 14 Mar 2013 20:43:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEyODUw?= =?utf-8?q?86=3A_Get_rid_of_the_refcounting_hack_and_speed_up?= Message-ID: <3ZRgMQ6crDzR9l@mail.python.org> http://hg.python.org/cpython/rev/3cb07925fcb9 changeset: 82659:3cb07925fcb9 branch: 3.2 parent: 82654:9b45873e5a68 user: Serhiy Storchaka date: Thu Mar 14 21:31:37 2013 +0200 summary: Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). files: Lib/urllib/parse.py | 63 ++++++++++++++------------------ Misc/NEWS | 3 + 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -27,6 +27,7 @@ test_urlparse.py provides a good indicator of parsing behavior. """ +import re import sys import collections @@ -470,6 +471,10 @@ defrag = url return _coerce_result(DefragResult(defrag, frag)) +_hexdig = '0123456789ABCDEFabcdef' +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) + for a in _hexdig for b in _hexdig} + def unquote_to_bytes(string): """unquote_to_bytes('abc%20def') -> b'abc def'.""" # Note: strings are encoded as UTF-8. This is only an issue if it contains @@ -480,16 +485,21 @@ return b'' if isinstance(string, str): string = string.encode('utf-8') - res = string.split(b'%') - if len(res) == 1: + bits = string.split(b'%') + if len(bits) == 1: return string - string = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - string += bytes([int(item[:2], 16)]) + item[2:] - except ValueError: - string += b'%' + item - return string + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b'%') + append(item) + return b''.join(res) + +_asciire = re.compile('([\x00-\x7f]+)') def unquote(string, encoding='utf-8', errors='replace'): """Replace %xx escapes by their single-character equivalent. The optional @@ -501,39 +511,20 @@ unquote('abc%20def') -> 'abc def'. """ - if string == '': - return string - res = string.split('%') - if len(res) == 1: + if '%' not in string: + string.split return string if encoding is None: encoding = 'utf-8' if errors is None: errors = 'replace' - # pct_sequence: contiguous sequence of percent-encoded bytes, decoded - pct_sequence = b'' - string = res[0] - for item in res[1:]: - try: - if not item: - raise ValueError - pct_sequence += bytes.fromhex(item[:2]) - rest = item[2:] - if not rest: - # This segment was just a single percent-encoded character. - # May be part of a sequence of code units, so delay decoding. - # (Stored in pct_sequence). - continue - except ValueError: - rest = '%' + item - # Encountered non-percent-encoded characters. Flush the current - # pct_sequence. - string += pct_sequence.decode(encoding, errors) + rest - pct_sequence = b'' - if pct_sequence: - # Flush the final pct_sequence - string += pct_sequence.decode(encoding, errors) - return string + bits = _asciire.split(string) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + append(bits[i + 1]) + return ''.join(res) def parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace'): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,9 @@ Library ------- +- Issue #1285086: Get rid of the refcounting hack and speed up + urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). + - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 20:43:32 2013 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 14 Mar 2013 20:43:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=231285086=3A_Get_rid_of_the_refcounting_hack_and_speed_?= =?utf-8?q?up?= Message-ID: <3ZRgMS3xDxzRjJ@mail.python.org> http://hg.python.org/cpython/rev/209a9c2de9bd changeset: 82660:209a9c2de9bd branch: 3.3 parent: 82655:e45db319e590 parent: 82659:3cb07925fcb9 user: Serhiy Storchaka date: Thu Mar 14 21:33:35 2013 +0200 summary: Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). files: Lib/urllib/parse.py | 63 ++++++++++++++------------------ Misc/NEWS | 3 + 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -27,6 +27,7 @@ test_urlparse.py provides a good indicator of parsing behavior. """ +import re import sys import collections @@ -470,6 +471,10 @@ defrag = url return _coerce_result(DefragResult(defrag, frag)) +_hexdig = '0123456789ABCDEFabcdef' +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) + for a in _hexdig for b in _hexdig} + def unquote_to_bytes(string): """unquote_to_bytes('abc%20def') -> b'abc def'.""" # Note: strings are encoded as UTF-8. This is only an issue if it contains @@ -480,16 +485,21 @@ return b'' if isinstance(string, str): string = string.encode('utf-8') - res = string.split(b'%') - if len(res) == 1: + bits = string.split(b'%') + if len(bits) == 1: return string - string = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - string += bytes([int(item[:2], 16)]) + item[2:] - except ValueError: - string += b'%' + item - return string + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b'%') + append(item) + return b''.join(res) + +_asciire = re.compile('([\x00-\x7f]+)') def unquote(string, encoding='utf-8', errors='replace'): """Replace %xx escapes by their single-character equivalent. The optional @@ -501,39 +511,20 @@ unquote('abc%20def') -> 'abc def'. """ - if string == '': - return string - res = string.split('%') - if len(res) == 1: + if '%' not in string: + string.split return string if encoding is None: encoding = 'utf-8' if errors is None: errors = 'replace' - # pct_sequence: contiguous sequence of percent-encoded bytes, decoded - pct_sequence = b'' - string = res[0] - for item in res[1:]: - try: - if not item: - raise ValueError - pct_sequence += bytes.fromhex(item[:2]) - rest = item[2:] - if not rest: - # This segment was just a single percent-encoded character. - # May be part of a sequence of code units, so delay decoding. - # (Stored in pct_sequence). - continue - except ValueError: - rest = '%' + item - # Encountered non-percent-encoded characters. Flush the current - # pct_sequence. - string += pct_sequence.decode(encoding, errors) + rest - pct_sequence = b'' - if pct_sequence: - # Flush the final pct_sequence - string += pct_sequence.decode(encoding, errors) - return string + bits = _asciire.split(string) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + append(bits[i + 1]) + return ''.join(res) def parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace'): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,9 @@ Library ------- +- Issue #1285086: Get rid of the refcounting hack and speed up + urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). + - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused a failure while decoding empty object literals when object_pairs_hook was specified. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 20:43:34 2013 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 14 Mar 2013 20:43:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=231285086=3A_Get_rid_of_the_refcounting_hack_and_?= =?utf-8?q?speed_up?= Message-ID: <3ZRgMV0krvzRld@mail.python.org> http://hg.python.org/cpython/rev/9367411a261e changeset: 82661:9367411a261e parent: 82656:99e72eae35bb parent: 82660:209a9c2de9bd user: Serhiy Storchaka date: Thu Mar 14 21:34:55 2013 +0200 summary: Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). files: Lib/urllib/parse.py | 63 ++++++++++++++------------------ Misc/NEWS | 3 + 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -27,6 +27,7 @@ test_urlparse.py provides a good indicator of parsing behavior. """ +import re import sys import collections @@ -470,6 +471,10 @@ defrag = url return _coerce_result(DefragResult(defrag, frag)) +_hexdig = '0123456789ABCDEFabcdef' +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) + for a in _hexdig for b in _hexdig} + def unquote_to_bytes(string): """unquote_to_bytes('abc%20def') -> b'abc def'.""" # Note: strings are encoded as UTF-8. This is only an issue if it contains @@ -480,16 +485,21 @@ return b'' if isinstance(string, str): string = string.encode('utf-8') - res = string.split(b'%') - if len(res) == 1: + bits = string.split(b'%') + if len(bits) == 1: return string - string = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - string += bytes([int(item[:2], 16)]) + item[2:] - except ValueError: - string += b'%' + item - return string + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b'%') + append(item) + return b''.join(res) + +_asciire = re.compile('([\x00-\x7f]+)') def unquote(string, encoding='utf-8', errors='replace'): """Replace %xx escapes by their single-character equivalent. The optional @@ -501,39 +511,20 @@ unquote('abc%20def') -> 'abc def'. """ - if string == '': - return string - res = string.split('%') - if len(res) == 1: + if '%' not in string: + string.split return string if encoding is None: encoding = 'utf-8' if errors is None: errors = 'replace' - # pct_sequence: contiguous sequence of percent-encoded bytes, decoded - pct_sequence = b'' - string = res[0] - for item in res[1:]: - try: - if not item: - raise ValueError - pct_sequence += bytes.fromhex(item[:2]) - rest = item[2:] - if not rest: - # This segment was just a single percent-encoded character. - # May be part of a sequence of code units, so delay decoding. - # (Stored in pct_sequence). - continue - except ValueError: - rest = '%' + item - # Encountered non-percent-encoded characters. Flush the current - # pct_sequence. - string += pct_sequence.decode(encoding, errors) + rest - pct_sequence = b'' - if pct_sequence: - # Flush the final pct_sequence - string += pct_sequence.decode(encoding, errors) - return string + bits = _asciire.split(string) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + append(bits[i + 1]) + return ''.join(res) def parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace'): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,9 @@ Library ------- +- Issue #1285086: Get rid of the refcounting hack and speed up + urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). + - Issue #17099: Have importlib.find_loader() raise ValueError when __loader__ is not set, harmonizing with what happens when the attribute is set to None. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 22:41:29 2013 From: python-checkins at python.org (eli.bendersky) Date: Thu, 14 Mar 2013 22:41:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Small_cosmetic_fixes?= Message-ID: <3ZRjzY05RCzPKr@mail.python.org> http://hg.python.org/cpython/rev/ef551f885f5f changeset: 82662:ef551f885f5f parent: 82656:99e72eae35bb user: Eli Bendersky date: Thu Mar 14 14:39:51 2013 -0700 summary: Small cosmetic fixes files: Doc/library/filecmp.rst | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst --- a/Doc/library/filecmp.rst +++ b/Doc/library/filecmp.rst @@ -56,8 +56,8 @@ .. class:: dircmp(a, b, ignore=None, hide=None) Construct a new directory comparison object, to compare the directories *a* - and *b*. *ignore* is a list of names to ignore, and defaults to - :attr:`filecmp.DEFAULT_IGNORES`. *hide* is a list of names to hide, and + and *b*. *ignore* is a list of names to ignore, and defaults to + :attr:`filecmp.DEFAULT_IGNORES`. *hide* is a list of names to hide, and defaults to ``[os.curdir, os.pardir]``. The :class:`dircmp` class compares files by doing *shallow* comparisons @@ -65,18 +65,15 @@ The :class:`dircmp` class provides the following methods: - .. method:: report() Print (to :data:`sys.stdout`) a comparison between *a* and *b*. - .. method:: report_partial_closure() Print a comparison between *a* and *b* and common immediate subdirectories. - .. method:: report_full_closure() Print a comparison between *a* and *b* and common subdirectories @@ -133,7 +130,7 @@ .. attribute:: common_files - Files in both *a* and *b* + Files in both *a* and *b*. .. attribute:: common_funny -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Mar 14 22:41:30 2013 From: python-checkins at python.org (eli.bendersky) Date: Thu, 14 Mar 2013 22:41:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3ZRjzZ42SVzQrN@mail.python.org> http://hg.python.org/cpython/rev/c25bc2587c48 changeset: 82663:c25bc2587c48 parent: 82662:ef551f885f5f parent: 82661:9367411a261e user: Eli Bendersky date: Thu Mar 14 14:41:23 2013 -0700 summary: Merge files: Lib/urllib/parse.py | 63 ++++++++++++++------------------ Misc/NEWS | 3 + 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -27,6 +27,7 @@ test_urlparse.py provides a good indicator of parsing behavior. """ +import re import sys import collections @@ -470,6 +471,10 @@ defrag = url return _coerce_result(DefragResult(defrag, frag)) +_hexdig = '0123456789ABCDEFabcdef' +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) + for a in _hexdig for b in _hexdig} + def unquote_to_bytes(string): """unquote_to_bytes('abc%20def') -> b'abc def'.""" # Note: strings are encoded as UTF-8. This is only an issue if it contains @@ -480,16 +485,21 @@ return b'' if isinstance(string, str): string = string.encode('utf-8') - res = string.split(b'%') - if len(res) == 1: + bits = string.split(b'%') + if len(bits) == 1: return string - string = res[0] - for item in res[1:]: + res = [bits[0]] + append = res.append + for item in bits[1:]: try: - string += bytes([int(item[:2], 16)]) + item[2:] - except ValueError: - string += b'%' + item - return string + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b'%') + append(item) + return b''.join(res) + +_asciire = re.compile('([\x00-\x7f]+)') def unquote(string, encoding='utf-8', errors='replace'): """Replace %xx escapes by their single-character equivalent. The optional @@ -501,39 +511,20 @@ unquote('abc%20def') -> 'abc def'. """ - if string == '': - return string - res = string.split('%') - if len(res) == 1: + if '%' not in string: + string.split return string if encoding is None: encoding = 'utf-8' if errors is None: errors = 'replace' - # pct_sequence: contiguous sequence of percent-encoded bytes, decoded - pct_sequence = b'' - string = res[0] - for item in res[1:]: - try: - if not item: - raise ValueError - pct_sequence += bytes.fromhex(item[:2]) - rest = item[2:] - if not rest: - # This segment was just a single percent-encoded character. - # May be part of a sequence of code units, so delay decoding. - # (Stored in pct_sequence). - continue - except ValueError: - rest = '%' + item - # Encountered non-percent-encoded characters. Flush the current - # pct_sequence. - string += pct_sequence.decode(encoding, errors) + rest - pct_sequence = b'' - if pct_sequence: - # Flush the final pct_sequence - string += pct_sequence.decode(encoding, errors) - return string + bits = _asciire.split(string) + res = [bits[0]] + append = res.append + for i in range(1, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + append(bits[i + 1]) + return ''.join(res) def parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace'): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,9 @@ Library ------- +- Issue #1285086: Get rid of the refcounting hack and speed up + urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). + - Issue #17099: Have importlib.find_loader() raise ValueError when __loader__ is not set, harmonizing with what happens when the attribute is set to None. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 00:32:42 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 00:32:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3NDEy?= =?utf-8?q?=3A_update_2=2E7_Doc/make=2Ebat_to_also_use_sphinx-1=2E0=2E7=2E?= Message-ID: <3ZRmRt14CyzNCJ@mail.python.org> http://hg.python.org/cpython/rev/7338e7ec47f0 changeset: 82664:7338e7ec47f0 branch: 2.7 parent: 82658:4927899bea8d user: Terry Jan Reedy date: Thu Mar 14 19:32:22 2013 -0400 summary: Issue #17412: update 2.7 Doc/make.bat to also use sphinx-1.0.7. files: Doc/make.bat | 2 +- Misc/NEWS | 2 ++ 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -34,7 +34,7 @@ goto end :checkout -svn co %SVNROOT%/external/Sphinx-0.6.7/sphinx tools/sphinx +svn co %SVNROOT%/external/Sphinx-1.0.7/sphinx tools/sphinx svn co %SVNROOT%/external/docutils-0.6/docutils tools/docutils svn co %SVNROOT%/external/Jinja-2.3.1/jinja2 tools/jinja2 svn co %SVNROOT%/external/Pygments-1.3.1/pygments tools/pygments diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -953,6 +953,8 @@ Documentation ------------- +- Issue #17412: update 2.7 Doc/make.bat to also use sphinx-1.0.7. + - Issue #17047: remove doubled words in docs and docstrings reported by Serhiy Storchaka and Matthew Barnett. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Mar 15 06:01:24 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 15 Mar 2013 06:01:24 +0100 Subject: [Python-checkins] Daily reference leaks (c25bc2587c48): sum=0 Message-ID: results for c25bc2587c48 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog1hqtG8', '-x'] From python-checkins at python.org Fri Mar 15 07:42:43 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 07:42:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_VC++_2010_registratio?= =?utf-8?q?n_requirement=2E_Remove_obsolete_link=2E_Steve_Dower_of?= Message-ID: <3ZRy030ybkzRtR@mail.python.org> http://hg.python.org/devguide/rev/0690d03cef69 changeset: 611:0690d03cef69 user: Terry Jan Reedy date: Fri Mar 15 02:42:26 2013 -0400 summary: Add VC++ 2010 registration requirement. Remove obsolete link. Steve Dower of Microsoft is working to determine the officil replacement. files: setup.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -189,11 +189,12 @@ **Python 3.3** and later 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 +Windows Live account. Most Python versions prior to 3.3 use Microsoft Visual Studio 2008. You can download Microsoft Visual C++ 2008 Express Edition with SP1 -`here `_. -You may need to select the file named ``vcsetup.exe``. +from a new location yet to be determined. Regardless of Visual Studio version, the ``PCbuild`` directory of a source checkout contains the build files for the Python version you are building. -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Fri Mar 15 08:04:45 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 08:04:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317414=3A_Add_time?= =?utf-8?q?it=2C_repeat=2C_and_default=5Ftimer_to_timeit=2E=5F=5Fall=5F=5F?= =?utf-8?q?=2E?= Message-ID: <3ZRyTT0DV9zRxl@mail.python.org> http://hg.python.org/cpython/rev/dda8a6b8a351 changeset: 82665:dda8a6b8a351 parent: 82663:c25bc2587c48 user: Terry Jan Reedy date: Fri Mar 15 03:04:25 2013 -0400 summary: Issue #17414: Add timeit, repeat, and default_timer to timeit.__all__. Revise module docstring and update itertools import and use. files: Lib/timeit.py | 44 ++++++++++++++------------------------ Misc/ACKS | 2 + Misc/NEWS | 2 + 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -31,38 +31,29 @@ If -n is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds. -The difference in default timer function is because on Windows, -clock() has microsecond granularity but time()'s granularity is 1/60th -of a second; on Unix, clock() has 1/100th of a second granularity and -time() is much more precise. On either platform, the default timer -functions measure wall clock time, not the CPU time. This means that -other processes running on the same computer may interfere with the -timing. The best thing to do when accurate timing is necessary is to -repeat the timing a few times and use the best time. The -r option is -good for this; the default of 3 repetitions is probably enough in most -cases. On Unix, you can use clock() to measure CPU time. +Note: there is a certain baseline overhead associated with executing a +pass statement. It differs between versions. The code here doesn't try +to hide it, but you should be aware of it. The baseline overhead can be +measured by invoking the program without arguments. -Note: there is a certain baseline overhead associated with executing a -pass statement. The code here doesn't try to hide it, but you should -be aware of it. The baseline overhead can be measured by invoking the -program without arguments. +Classes: -The baseline overhead differs between Python versions! Also, to -fairly compare older Python versions to Python 2.3, you may want to -use python -O for the older versions to avoid timing SET_LINENO -instructions. + Timer + +Functions: + + timeit(string, string) -> float + repeat(string, string) -> list + default_timer() -> float + """ import gc import sys import time -try: - import itertools -except ImportError: - # Must be an older Python version (see timeit() below) - itertools = None +import itertools -__all__ = ["Timer"] +__all__ = ["Timer", "timeit", "repeat", "default_timer"] dummy_src_name = "" default_number = 1000000 @@ -180,10 +171,7 @@ to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor. """ - if itertools: - it = itertools.repeat(None, number) - else: - it = [None] * number + it = itertools.repeat(None, number) gcold = gc.isenabled() gc.disable() try: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -449,6 +449,7 @@ Dag Gruneau Filip Gruszczy?ski Thomas Guettler +Anuj Gupta Michael Guravage Lars Gust?bel Thomas G?ttler @@ -1359,3 +1360,4 @@ Kai Zhu Tarek Ziad? Peter ?strand + diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,8 @@ Library ------- +- Issue #17414: Add timeit, repeat, and default_timer to timeit.__all__. + - Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 08:42:13 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 08:42:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3MDQ3?= =?utf-8?q?=3A_Add_news_entry?= Message-ID: <3ZRzJj4yNYzRwR@mail.python.org> http://hg.python.org/cpython/rev/4b28a6a3eda6 changeset: 82666:4b28a6a3eda6 branch: 3.2 parent: 82659:3cb07925fcb9 user: Terry Jan Reedy date: Fri Mar 15 03:33:11 2013 -0400 summary: Issue #17047: Add news entry files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1108,6 +1108,9 @@ Documentation ------------- +- Issue #17047: remove doubled words in docs and docstrings + reported by Serhiy Storchaka and Matthew Barnett. + - Issue #16406: Combine the pages for uploading and registering to PyPI. - Issue #16403: Document how distutils uses the maintainer field in -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 08:42:15 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 08:42:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_with_3=2E2=3A_issue_=2317047_news_entry?= Message-ID: <3ZRzJl0sw1zS2q@mail.python.org> http://hg.python.org/cpython/rev/937989570b42 changeset: 82667:937989570b42 branch: 3.3 parent: 82660:209a9c2de9bd parent: 82666:4b28a6a3eda6 user: Terry Jan Reedy date: Fri Mar 15 03:39:38 2013 -0400 summary: Merge with 3.2: issue #17047 news entry files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -817,6 +817,9 @@ - Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte +- Issue #17047: remove doubled words in docs and docstrings + reported by Serhiy Storchaka and Matthew Barnett. + - Issue #15465: Document the versioning macros in the C API docs rather than the standard library docs. Patch by Kushal Das. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 08:42:16 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 08:42:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E2=3A_closes_issue_=2317047?= Message-ID: <3ZRzJm3XmXzS04@mail.python.org> http://hg.python.org/cpython/rev/f0a3c2006adb changeset: 82668:f0a3c2006adb parent: 82665:dda8a6b8a351 parent: 82667:937989570b42 user: Terry Jan Reedy date: Fri Mar 15 03:41:35 2013 -0400 summary: Merge with 3.2: closes issue #17047 files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1109,6 +1109,9 @@ - Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte +- Issue #17047: remove doubled words in docs and docstrings + reported by Serhiy Storchaka and Matthew Barnett. + - Issue #15465: Document the versioning macros in the C API docs rather than the standard library docs. Patch by Kushal Das. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 15:26:02 2013 From: python-checkins at python.org (eli.bendersky) Date: Fri, 15 Mar 2013 15:26:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_mention_of_IntEnum=2C_s?= =?utf-8?q?ummarizing_the_language_summit_and_later_discussions?= Message-ID: <3ZS8Gf4DhjzMgy@mail.python.org> http://hg.python.org/peps/rev/bd190f281dad changeset: 4801:bd190f281dad user: Eli Bendersky date: Fri Mar 15 07:25:45 2013 -0700 summary: Add a mention of IntEnum, summarizing the language summit and later discussions on the subject. Note that this is still in draft stage and decisions can change (and have changed more than once over the past few days). files: pep-0435.txt | 72 ++++++++++++++++++++++++++++++++++++--- 1 files changed, 65 insertions(+), 7 deletions(-) diff --git a/pep-0435.txt b/pep-0435.txt --- a/pep-0435.txt +++ b/pep-0435.txt @@ -34,9 +34,25 @@ previous attempt that was rejected in 2005. Recently a new set of discussions was initiated [3]_ on the ``python-ideas`` mailing list. Many new ideas were proposed in several threads; after a lengthy discussion Guido proposed adding -``flufl.enum`` to the standard library [4]_. This PEP is an attempt to -formalize this decision as well as discuss a number of variations that can be -considered for inclusion. +``flufl.enum`` to the standard library [4]_. During the PyCon 2013 language +summit the issue was discussed further. It became clear that many developers +want to see an enum that subclasses ``int``, which can allow us to replace +many integer constants in the standard library by enums with friendly string +representations, without ceding backwards compatibility. An additional +discussion among several interested core developers led to the proposal of +having ``IntEnum`` as a special case of ``Enum``. + +The key dividing issue between ``Enum`` and ``IntEnum`` is whether comparing +to integers is semantically meaningful. For most uses of enumerations, it's +a **feature** to reject comparison to integers; enums that compare to integers +lead, through transitivity, to comparisons between enums of unrelated types, +which isn't desirable in most cases. For some uses, however, greater +interoperatiliby with integers is desired. For instance, this is the case for +replacing existing standard library constants (such as ``socket.AF_INET``) +with enumerations. + +This PEP is an attempt to formalize this decision as well as discuss a number +of variations that were discussed and can be considered for inclusion. Motivation @@ -153,9 +169,9 @@ >>> Colors.blue is MoreColors.blue True -However, these are not doing comparisons against the integer equivalent -values, because if you define an enumeration with similar item names and -integer values, they will not be identical:: +However, these are not doing comparisons against the integer equivalent values, +because if you define an enumeration with similar item names and integer values, +they will not be identical:: >>> class OtherColors(Enum): ... red = 1 @@ -174,7 +190,7 @@ 2 Ordered comparisons between enumeration values are *not* supported. Enums are -not integers:: +not integers (but see ``IntEnum`` below):: >>> Colors.red < Colors.blue Traceback (most recent call last): @@ -342,6 +358,48 @@ green -> granny smith +IntEnum +------- + +A variation of ``Enum`` is proposed that also subclasses ``int`` - ``IntEnum``. +Such enumerations behave much more similarly to integers. In particular, they +can be compared to integers; by extensions, enumerations of different types can +also be compared to each other:: + + >>> from enum import IntEnum + >>> class Shape(IntEnum): + ... circle = 1 + ... square = 2 + ... + >>> class Request(IntEnum): + ... post = 1 + ... get = 2 + ... + >>> Shape == 1 + False + >>> Shape.circle == 1 + True + >>> Shape.circle == Request.post + True + +However they still can't be compared to ``Enum``:: + + >>> from enum import Enum, IntEnum + >>> class Shape(IntEnum): + ... circle = 1 + ... square = 2 + ... + >>> class Colors(Enum): + ... red = 1 + ... green = 2 + ... + >>> Shape.circle == Colors.red + False + +For the vast majority of code, ``Enum`` is recommended. Only if a greater +degree of interoperatility with integers is required and ``Enum`` does not +fit the bill, ``IntEnum`` should be used. + Pickling -------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Mar 15 15:50:26 2013 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 15 Mar 2013 15:50:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=231291_http=2Eserver=27s_?= =?utf-8?q?send=5Ferror_takes_an_optional_explain_argument?= Message-ID: <3ZS8pp6R1NzP5j@mail.python.org> http://hg.python.org/cpython/rev/59292f366b53 changeset: 82669:59292f366b53 user: Senthil Kumaran date: Fri Mar 15 07:53:21 2013 -0700 summary: #1291 http.server's send_error takes an optional explain argument files: Doc/library/http.server.rst | 12 ++++++++---- Lib/http/server.py | 18 ++++++++++++------ Lib/test/test_httpservers.py | 10 ++++++++++ Misc/NEWS | 3 +++ 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -170,15 +170,19 @@ .. versionadded:: 3.2 - .. method:: send_error(code, message=None) + .. method:: send_error(code, message=None, explain=None) Sends and logs a complete error reply to the client. The numeric *code* - specifies the HTTP error code, with *message* as optional, more specific text. A - complete set of headers is sent, followed by text composed using the - :attr:`error_message_format` class variable. + specifies the HTTP error code, with *message* as optional, more specific + text, usually referring to short message response. The *explain* + argument can be used to send a detailed information about the error in + response content body. A complete set of headers is sent, followed by + text composed using the :attr:`error_message_format` class variable. .. versionchanged:: 3.4 The error response includes a Content-Length header. + explain argument was added. + .. method:: send_response(code, message=None) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -401,12 +401,17 @@ while not self.close_connection: self.handle_one_request() - def send_error(self, code, message=None): + def send_error(self, code, message=None, explain=None): """Send and log an error reply. - Arguments are the error code, and a detailed message. - The detailed message defaults to the short entry matching the - response code. + Arguments are + * code: an HTTP error code + 3 digits + * message: a simple optional 1 line reason phrase. + *( HTAB / SP / VCHAR / %x80-FF ) + defaults to short entry matching the response code + * explain: a detailed message defaults to the long entry + matching the response code. This sends an error response (so it must be called before any output has been generated), logs the error, and finally sends @@ -420,11 +425,12 @@ shortmsg, longmsg = '???', '???' if message is None: message = shortmsg - explain = longmsg + if explain is None: + explain = longmsg self.log_error("code %d, message %s", code, message) # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) content = (self.error_message_format % - {'code': code, 'message': _quote_html(message), 'explain': explain}) + {'code': code, 'message': _quote_html(message), 'explain': _quote_html(explain)}) body = content.encode('UTF-8', 'replace') self.send_response(code, message) self.send_header("Content-Type", self.error_content_type) 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 @@ -95,6 +95,10 @@ def do_NOTFOUND(self): self.send_error(404) + def do_EXPLAINERROR(self): + self.send_error(999, "Short Message", + "This is a long \n explaination") + def do_CUSTOM(self): self.send_response(999) self.send_header('Content-Type', 'text/html') @@ -206,6 +210,12 @@ res = self.con.getresponse() self.assertEqual(res.status, 999) + def test_return_explain_error(self): + self.con.request('EXPLAINERROR', '/') + res = self.con.getresponse() + self.assertEqual(res.status, 999) + self.assertTrue(int(res.getheader('Content-Length'))) + def test_latin1_header(self): self.con.request('LATINONEHEADER', '/', headers={ 'X-Special-Incoming': '?rger mit Unicode' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,9 @@ Library ------- +- Issue #12921: http.server's send_error takes an explain argument to send more + information in response. Patch contributed by Karl. + - Issue #17414: Add timeit, repeat, and default_timer to timeit.__all__. - Issue #1285086: Get rid of the refcounting hack and speed up -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 21:34:39 2013 From: python-checkins at python.org (ezio.melotti) Date: Fri, 15 Mar 2013 21:34:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_=2314468=3A_add_FAQs_abou?= =?utf-8?q?t_merge_conflicts=2C_null_merges=2C_and_heads_merges=2E?= Message-ID: <3ZSJRz4lsnzPBg@mail.python.org> http://hg.python.org/devguide/rev/7a707540391e changeset: 612:7a707540391e user: Ezio Melotti date: Fri Mar 15 22:34:23 2013 +0200 summary: #14468: add FAQs about merge conflicts, null merges, and heads merges. files: committing.rst | 7 ++ faq.rst | 109 +++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -339,6 +339,11 @@ Unless noted otherwise, the rest of the page will assume you are using the multiple clone approach, and explain in more detail these basic steps. +For more advanced explanations about :ref:`null merges `, +:ref:`heads merges `, :ref:`merge conflicts +`, etc., see the :ref:`FAQs for core developers +`. + .. _share extension: http://mercurial.selenic.com/wiki/ShareExtension @@ -364,6 +369,8 @@ Python version. +.. _branch-merge: + Merging between different branches (within the same major version) ------------------------------------------------------------------ diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -728,6 +728,8 @@ .. _configuration options: http://www.selenic.com/mercurial/hgrc.5.html +.. _core-devs-faqs: + For core developers ------------------- @@ -767,47 +769,86 @@ option in the ``[ui]`` section. -.. _hg-merge: +.. _hg-merge-conflicts: -How do I find out which revisions need merging? -''''''''''''''''''''''''''''''''''''''''''''''' +How do I solve merge conflicts? +''''''''''''''''''''''''''''''' -In unambiguous cases, Mercurial will find out for you if you simply try:: +The easiest way is to install KDiff3 --- Mercurial will open it automatically +in case of conflicts, and you can then use it to solve the conflicts and +save the resulting file(s). KDiff3 will also take care of marking the +conflicts as resolved. +If you don't use a merge tool, you can use ``hg resolve --list`` to list the +conflicting files, resolve the conflicts manually, and the use +``hg resolve --mark `` to mark these conflicts as resolved. +You can also use ``hg resolve -am`` to mark all the conflicts as resolved. + +.. note:: + Mercurial will use KDiff3 automatically if it's installed and it can find + it --- you don't need to change any settings. KDiff3 is also already + included in the installer of TortoiseHg. For more information, see + http://mercurial.selenic.com/wiki/KDiff3. + + +.. _hg-null-merge: + +How do I make a null merge? +''''''''''''''''''''''''''' + +If you committed something (e.g. on 3.2) that shouldn't be ported on newer +branches (e.g. on 3.3), you have to do a *null merge*:: + + cd 3.3 + hg merge 3.2 + hg revert -ar 3.3 + hg resolve -am # needed only if the merge created conflicts + hg ci -m '#12345: null merge with 3.2.' + +Before committing, ``hg status`` should list all the merged files as ``M``, +but ``hg diff`` should produce no output. This will record the merge without +actually changing the content of the files. + + +.. _hg-heads-merge: + +I got "abort: push creates new remote heads!" while pushing, what do I do? +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +If you see this message while pushing, it means that you committed something +on a clone that was not up to date, thus creating a new head. +This usually happens for two reasons: + +1. You forgot to run ``hg pull`` and/or ``hg up`` before committing; +2. Someone else pushed on the main repo just before you, causing a push race; + +First of all you should pull the new changesets using ``hg pull``. Then you can +use ``hg heads`` to see which branches have multiple heads. + +If only one branch has multiple heads, you can do:: + + cd default + hg heads . + hg up csid-of-the-other-head hg merge + hg ci -m 'Merge heads.' -If that fails and Mercurial asks for explicit revisions, running:: +``hg heads .`` will show you the two heads of the current branch: the one you +pulled and the one you created with your commit (you can also specify a branch +with ``hg heads ``). While not strictly necessary, it is highly +recommended to switch to the other head before merging. This way you will be +merging only your changeset with the rest, and in case of conflicts it will be +a lot easier. - hg heads +If more than one branch has multiple heads, you have to repeat these steps for +each branch. Since this creates new changesets, you will also have to +:ref:`merge them between branches `. For example, if both ``3.3`` +and ``default`` have multiple heads, you should first merge heads in ``3.3``, +then merge heads in ``default``, and finally merge ``3.3`` with ``default`` +using ``hg merge 3.3`` as usual. -will give you the list of branch heads in your local repository. If you are -working only in a particular named branch, for example ``default``, do:: - - hg heads default - -to display the heads on that branch. - - -How do I list the files in conflict after a merge? -'''''''''''''''''''''''''''''''''''''''''''''''''' - -Use:: - - hg resolve --list - -(abbreviated ``hg resolve -l``) - - -How I mark a file resolved after I have resolved merge conflicts? -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Type:: - - hg resolve --mark - -(abbreviated ``hg resolve -m ``) - -If you are sure you have resolved all conflicts, use ``hg resolve -am``. +In order to avoid this, you should *always remember to pull and update before +committing*. How do I undo the changes made in a recent commit? -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Fri Mar 15 21:52:04 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 21:52:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Mzk4?= =?utf-8?q?=3A_document_url_argument_of_RobotFileParser?= Message-ID: <3ZSJr404JjzS8Q@mail.python.org> http://hg.python.org/cpython/rev/274e68e2a5a6 changeset: 82670:274e68e2a5a6 branch: 2.7 parent: 82664:7338e7ec47f0 user: Terry Jan Reedy date: Fri Mar 15 16:49:22 2013 -0400 summary: Issue #17398: document url argument of RobotFileParser files: Doc/library/robotparser.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/robotparser.rst b/Doc/library/robotparser.rst --- a/Doc/library/robotparser.rst +++ b/Doc/library/robotparser.rst @@ -26,10 +26,10 @@ structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. -.. class:: RobotFileParser() +.. class:: RobotFileParser(url='') - This class provides a set of methods to read, parse and answer questions - about a single :file:`robots.txt` file. + This class provides methods to read, parse and answer questions about the + :file:`robots.txt` file at *url*. .. method:: set_url(url) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 21:52:05 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 21:52:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE3Mzk4?= =?utf-8?q?=3A_document_url_argument_of_RobotFileParser?= Message-ID: <3ZSJr52f3DzS49@mail.python.org> http://hg.python.org/cpython/rev/4be7f8da7adf changeset: 82671:4be7f8da7adf branch: 3.2 parent: 82666:4b28a6a3eda6 user: Terry Jan Reedy date: Fri Mar 15 16:50:23 2013 -0400 summary: Issue #17398: document url argument of RobotFileParser files: Doc/library/urllib.robotparser.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -19,10 +19,10 @@ structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. -.. class:: RobotFileParser() +.. class:: RobotFileParser(url='') - This class provides a set of methods to read, parse and answer questions - about a single :file:`robots.txt` file. + This class provides methods to read, parse and answer questions about the + :file:`robots.txt` file at *url*. .. method:: set_url(url) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 21:52:06 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 21:52:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_with_3=2E2?= Message-ID: <3ZSJr657JpzS8Q@mail.python.org> http://hg.python.org/cpython/rev/166fb6ecb55a changeset: 82672:166fb6ecb55a branch: 3.3 parent: 82667:937989570b42 parent: 82671:4be7f8da7adf user: Terry Jan Reedy date: Fri Mar 15 16:50:54 2013 -0400 summary: Merge with 3.2 files: Doc/library/urllib.robotparser.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -19,10 +19,10 @@ structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. -.. class:: RobotFileParser() +.. class:: RobotFileParser(url='') - This class provides a set of methods to read, parse and answer questions - about a single :file:`robots.txt` file. + This class provides methods to read, parse and answer questions about the + :file:`robots.txt` file at *url*. .. method:: set_url(url) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 21:52:08 2013 From: python-checkins at python.org (terry.reedy) Date: Fri, 15 Mar 2013 21:52:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3ZSJr80hkmzS91@mail.python.org> http://hg.python.org/cpython/rev/46e6a8b742d9 changeset: 82673:46e6a8b742d9 parent: 82669:59292f366b53 parent: 82672:166fb6ecb55a user: Terry Jan Reedy date: Fri Mar 15 16:51:21 2013 -0400 summary: Merge with 3.3 files: Doc/library/urllib.robotparser.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -19,10 +19,10 @@ structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. -.. class:: RobotFileParser() +.. class:: RobotFileParser(url='') - This class provides a set of methods to read, parse and answer questions - about a single :file:`robots.txt` file. + This class provides methods to read, parse and answer questions about the + :file:`robots.txt` file at *url*. .. method:: set_url(url) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Mar 15 22:51:31 2013 From: python-checkins at python.org (georg.brandl) Date: Fri, 15 Mar 2013 22:51:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_437=3A_Add_standard_=22lo?= =?utf-8?q?cal_variables=22_footer=2E?= Message-ID: <3ZSL8g1fx8zS9v@mail.python.org> http://hg.python.org/peps/rev/470f041a461c changeset: 4802:470f041a461c user: Georg Brandl date: Fri Mar 15 22:51:01 2013 +0100 summary: PEP 437: Add standard "local variables" footer. files: pep-0437.txt | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/pep-0437.txt b/pep-0437.txt --- a/pep-0437.txt +++ b/pep-0437.txt @@ -389,4 +389,12 @@ .. _Open Publication License: http://www.opencontent.org/openpub/ - + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Mar 15 22:51:32 2013 From: python-checkins at python.org (georg.brandl) Date: Fri, 15 Mar 2013 22:51:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_PEP_438=3A_Transitioning_?= =?utf-8?q?to_release-file_hosting_on_PyPI=2C_submitted_by_Holger?= Message-ID: <3ZSL8h6kXSzS9v@mail.python.org> http://hg.python.org/peps/rev/021c1f97ee13 changeset: 4803:021c1f97ee13 user: Georg Brandl date: Fri Mar 15 22:51:25 2013 +0100 summary: Add PEP 438: Transitioning to release-file hosting on PyPI, submitted by Holger Krekel. files: pep-0438.txt | 387 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 387 insertions(+), 0 deletions(-) diff --git a/pep-0438.txt b/pep-0438.txt new file mode 100644 --- /dev/null +++ b/pep-0438.txt @@ -0,0 +1,387 @@ +PEP: 438 +Title: Transitioning to release-file hosting on PyPI +Version: $Revision$ +Last-Modified: $Date$ +Author: Holger Krekel , Carl Meyer +Discussions-To: catalog-sig at python.org +Status: Draft +Type: Process +Content-Type: text/x-rst +Created: 15-Mar-2013 +Post-History: + + +Abstract +======== + +This PEP proposes a backward-compatible two-phase transition process +to speed up, simplify and robustify installing from the +pypi.python.org (PyPI) package index. To ease the transition and +minimize client-side friction, **no changes to distutils or existing +installation tools are required in order to benefit from the first +transition phase, which will result in faster, more reliable installs +for most existing packages**. + +The first transition phase implements an easy and explicit means for a +package maintainer to control which release file links are served to +present-day installation tools. The first phase also includes the +implementation of analysis tools for present-day packages, to support +communication with package maintainers and the automated setting of +default modes for controlling release file links. The first phase +also will default newly-registered projects on PyPI to only serve +links to release files which were uploaded to PyPI. + +The second transition phase concerns end-user installation tools, +which shall default to only install release files that are hosted on +PyPI and tell the user if external release files exist, offering a +choice to automatically use those external files. + + +Rationale +========= + +.. _history: + +History and motivations for external hosting +-------------------------------------------- + +When PyPI went online, it offered release registration but had no +facility to host release files itself. When hosting was added, no +automated downloading tool existed yet. When Philip Eby implemented +automated downloading (through setuptools), he made the choice to +allow people to use download hosts of their choice. The finding of +externally-hosted packages was implemented as follows: + +#. The PyPI ``simple/`` index for a package contains all links found + by scraping them from that package's long_description metadata for + any release. Links in the "Download-URL" and "Home-page" metadata + fields are given ``rel=download`` and ``rel=homepage`` attributes, + respectively. + +#. Any of these links whose target is a file whose name appears to be + in the form of an installable source or binary distribution, with + name in the form "packagename-version.ARCHIVEEXT", is considered a + potential installation candidate by installation tools. + +#. Similarly, any links suffixed with an "#egg=packagename-version" + fragment are considered an installation candidate. + +#. Additionally, the ``rel=homepage`` and ``rel=download`` links are + crawled by installation tools and, if HTML, are themselves scraped + for release-file links in the above formats. + +Today, most packages released on PyPI host their release files on +PyPI, but a small percentage (XXX need updated data) rely on external +hosting. + +There are many reasons [2]_ why people have chosen external +hosting. To cite just a few: + +- release processes and scripts have been developed already and upload + to external sites + +- it takes too long to upload large files from some places in the + world + +- export restrictions e.g. for crypto-related software + +- company policies which require offering open source packages through + own sites + +- problems with integrating uploading to PyPI into one's release + process (because of release policies) + +- desiring download statistics different from those maintained by PyPI + +- perceived bad reliability of PyPI + +- not aware that PyPI offers file-hosting + +Irrespective of the present-day validity of these reasons, there +clearly is a history why people choose to host files externally and it +even was for some time the only way you could do things. This PEP +takes the position that there are at least some valid reasons for +external hosting. + +Problem +------- + +**Today, python package installers (pip, easy_install, buildout, and +others) often need to query many non-PyPI URLs even if there are no +externally hosted files**. Apart from querying pypi.python.org's +simple index pages, also all homepages and download pages ever +specified with any release of a package are crawled by an installer. +The need for installers to crawl external sites slows down +installation and makes for a brittle and unreliable installation +process. Those sites and packages also don't take part in the +:pep:`381` mirroring infrastructure, further decreasing reliability +and speed of automated installation processes around the world. + +Most packages are hosted directly on pypi.python.org [1]_. Even for +these packages, installers still crawl their homepage and +download-url, if specified. Many package uploaders are not aware that +specifying the "homepage" or "download-url" in their package metadata +will needlessly slow down the installation process for all users. + +Relying on third party sites also opens up more attack vectors for +injecting malicious packages into sites using automated installs. A +simple attack might just involve getting hold of an old now-unused +homepage domain and placing malicious packages there. Moreover, +performing a Man-in-The-Middle (MITM) attack between an installation +site and any of the download sites can inject malicious packages on +the installation site. As many homepages and download locations are +using HTTP and not HTTPS, such attacks are not hard to launch. Such +MITM attacks can easily happen even for packages which never intended +to host files externally as their homepages are contacted by +installers anyway. + +There is currently no way for package maintainers to avoid +external-link crawling, other than removing all homepage/download url +metadata for all historic releases. While a script [3]_ has been +written to perform this action, it is not a good general solution +because it removes useful metadata from PyPI releases. + +Even if the sites referenced by "Homepage" and "Download-URL" links +were not scraped for further links, there is no obvious way under the +current system for a package owner to link to an installable file from +a long_description metadata field (which is shown as package +documentation on ``/pypi/PKG``) without installation tools +automatically considering that file a candidate for installation. +Conversely, there is no way to explicitly register multiple external +release files without putting them in metadata fields. + + +Goals +----- + +These are the goals to be achieved by implementation of this PEP: + +* Package owners should be able to explicitly control which files are + presented by PyPI to installer tools as installation + candidates. Installation should not be slowed and made less reliable + by extensive and unnecessary crawling of links that package owners + did not explicitly nominate as installation files. + +* It should remain possible for package owners to choose to host their + release files on their own hosting, external to PyPI. It should be + easy for a user to request the installation of such releases using + automated installer tools. + +* Automated installer tools should not install externally-hosted + packages **by default**, but only when explicitly authorized to do + so by the user. When tools refuse to install such a package by + default, they should tell the user exactly which external link(s) + they would need to follow, and what option(s) the user can provide + to authorize the tool to follow those links. PyPI should provide all + necessary metadata for installer tools to implement this easily and + within a single request/reply interaction. + +* Migration from the status quo to the above points should be gradual + and minimize breakage. This includes tooling that makes it easy for + package owners with an existing release process that uploads to + non-PyPI hosting to also upload those release files to PyPI. + + +Solution / two transition phases +================================ + +The first transition phase introduces a "hosting-mode" field for each +project on PyPI, allowing package owners explicit control of which +release file links are served to present-day installation tools in the +machine-readable ``simple/`` index. The first transition will, after +successful hosting-mode manipulations by individual early-adopters, +set a default hosting mode for existing packages, based on automated +analysis. **Maintainers will be notified one month ahead of any such +automated change**. At completion of the first transition phase, +**all present-day existing release and installation processes and +tools are expected to continue working**. Any remaining errors or +problems are expected to only relate to installation of individual +packages and can be easily corrected by package maintainers or PyPI +admins if maintainers are not reachable. + +Also in the first phase, each link served in the ``simple/`` index +will be explicitly marked as ``rel="internal"`` (hosted by the index +itself) or ``rel="external"`` (linking to an external site that is not +part of the index). + +In the second transition phase, PyPI client installation tools shall +be updated to default to only install ``rel="internal"`` packages +unless a user specifies option(s) to permit installing from external +links. + +Maintainers of packages which currently host release files on non-PyPI +sites shall receive instructions and tools to ease "re-hosting" of +their historic and future package release files. This re-hosting tool +MUST be available before automated hosting-mode changes are announced +to package maintainers. + + +Implementation +============== + +Hosting modes +------------- + +The foundation of the first transition phase is the introduction of +three "modes" of PyPI hosting for a package, affecting which links are +generated for the ``simple/`` index. These modes are implemented +without requiring changes to installation tools via changes to the +algorithm for generating the machine-readable ``simple/`` index. + +The modes are: + +- ``pypi-scrape-crawl``: no change from the current situation of + generating machine-readable links for installation tools, as + outlined in the history_. + +- ``pypi-scrape``: for a package in this mode, links to be added to + the ``simple/`` index are still scraped from package + metadata. However, the "Home-page" and "Download-url" links are + given ``rel=ext-homepage`` and ``rel=ext-download`` attributes + instead of ``rel=homepage`` and ``rel=download``. The effect of this + (with no change in installation tools necessary) is that these links + will not be followed and scraped for further candidate links by + present-day installation tools: only installable files directly + hosted from PyPI or linked directly from PyPI metadata will be + considered for installation. Installation tools MAY evolve to offer + an option to use the new rel-attribution to crawl external pages but + MUST NOT default to it. + +- ``pypi-explicit``: for a package in this mode, only links to release + files uploaded to PyPI, and external links to release files + explicitly nominated by the package owner (via a new interface + exposed by PyPI) will be added to the ``simple/`` index. + +Thus the hope is that eventually all projects on PyPI can be migrated +to the ``pypi-explicit`` mode, while preserving the ability to install +release files hosted externally via installer tools. Deprecation of +hosting modes to eventually only allow the ``pypi-explicit`` mode is +NOT REGULATED by this PEP but is expected to become feasible some time +after successful implementation of the transition phases described in +this PEP. It is expected that deprecation requires **a new process to +deal with abandoned packages** because of unreachable maintainers for +still popular packages. + + +First transition phase (PyPI) +----------------------------- + +The proposed solution consists of multiple implementation and +communication steps: + +#. Implement in PyPI the three modes described above, with an + interface for package owners to select the mode for each package + and register explicit external file URLs. + +#. For packages in all modes, label all links in the ``simple/`` index + with ``rel="internal"`` or ``rel="external"``, to make it easier + for client tools to distinguish the types of links in the second + transition phase. + +#. Default all newly-registered packages to ``pypi-explicit`` mode + (package owners can still switch to the other modes as desired). + +#. Determine (via an automated analysis tool) which packages have all + installable files available on PyPI itself (group A), which have + all installable files linked directly from PyPI metadata (group B), + and which have installable versions available that are linked only + from external homepage/download HTML pages (group C). + +#. Send mail to maintainers of projects in group A that their project + will be automatically configured to ``pypi-explicit`` mode in one + month, and similarly to maintainers of projects in group B that + their project will be automatically configured to ``pypi-scrape`` + mode. Inform them that this change is not expected to affect + installability of their project at all, but will result in faster + and safer installs for their users. Encourage them to set this + mode themselves sooner to benefit their users. + +#. Send mail to maintainers of packages in group C that their package + hosting mode is ``pypi-scrape-crawl``, list the URLs which + currently are crawled, and suggest that they either re-host their + packages directly on PyPI and switch to ``pypi-explicit``, or at + least provide direct links to release files in PyPI metadata and + switch to ``pypi-scrape``. Provide instructions and tools to help + with these transitions. + + +Second transition phase (installer tools) +----------------------------------------- + +For the second transition phase, maintainers of installation tools are +asked to release two updates. + +The first update shall provide clear warnings if externally-hosted +release files (that is, files whose link is ``rel="external"``) are +selected for download, for which projects and URLs exactly this +happens, and warn that in future versions externally-hosted downloads +will be disabled by default. + +The second update should change the default mode to allow only +installation of ``rel="internal"`` package files, and allow +installation of externally-hosted packages only when the user supplies +an option (ideally an option specifying exactly which external domains +are to be trusted as download sources). When download of an +externally-hosted package is disallowed, the user should be notified, +with instructions for how to make the install succeed and warnings +about the implication (that a file will be downloaded from a site that +is not part of the package index). + + +Open Questions / tasks +====================== + +- Should we introduce some form of PyPI API versioning in this PEP? + (it might complicate matters and delay the implementation but is + often seen as good practise). + +- Do another round of discussions with installation tool authors and + see about incorporating their feedback. There is one known issue in + particular from Philip J. Eby who considers a host-based pattern + matching algorithm preferable to interpreting "rel" attributes. + + +References +========== + +.. [1] Donald Stufft, ratio of externally hosted versus pypi-hosted, + http://mail.python.org/pipermail/catalog-sig/2013-March/005549.html + (XXX need to update this data for all easy_install-supported formats) + +.. [2] Marc-Andre Lemburg, reasons for external hosting, + http://mail.python.org/pipermail/catalog-sig/2013-March/005626.html + +.. [3] Holger Krekel, script to remove homepage/download metadata for + all releases + http://mail.python.org/pipermail/catalog-sig/2013-February/005423.html + + +Acknowledgments +=============== + +Philip Eby for precise information and the basic ideas to implement +the transition via server-side changes only. + +Donald Stufft for pushing away from external hosting and offering to +implement both a Pull Request for the necessary PyPI changes and the +analysis tool to drive the transition phase 1. + +Marc-Andre Lemburg, Nick Coghlan and catalog-sig in general for +thinking through issues regarding getting rid of "external hosting". + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Mar 16 01:46:56 2013 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 Mar 2013 01:46:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE3NDMxOiBGaXgg?= =?utf-8?q?missing_import_of_BytesFeedParser_in_email=2Eparser=2E?= Message-ID: <3ZSQ345gCfzS7C@mail.python.org> http://hg.python.org/cpython/rev/4e6cf15e55c1 changeset: 82674:4e6cf15e55c1 branch: 3.2 parent: 82671:4be7f8da7adf user: R David Murray date: Fri Mar 15 20:38:15 2013 -0400 summary: #17431: Fix missing import of BytesFeedParser in email.parser. Initial patch contributed by Edmond Burnett. files: Lib/email/parser.py | 2 +- Lib/email/test/test_email.py | 4 ++++ Misc/ACKS | 1 + Misc/NEWS | 2 ++ 4 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/email/parser.py b/Lib/email/parser.py --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -9,7 +9,7 @@ import warnings from io import StringIO, TextIOWrapper -from email.feedparser import FeedParser +from email.feedparser import FeedParser, BytesFeedParser from email.message import Message diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -38,6 +38,10 @@ from test.support import findfile, run_unittest, unlink from email.test import __file__ as landmark +# These imports are documented to work, but we are testing them using a +# different path, so we import them here just to make sure they are importable. +from email.parser import FeedParser, BytesFeedParser + NL = '\n' EMPTYSTRING = '' diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -156,6 +156,7 @@ Dick Bulterman Bill Bumgarner Jimmy Burgett +Edmond Burnett Tommy Burnette Roger Burnham Alastair Burt diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -233,6 +233,8 @@ Library ------- +- Issue #17431: Fix missing import of BytesFeedParser in email.parser. + - Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 01:46:58 2013 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 Mar 2013 01:46:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge=3A_=2317431=3A_Fix_missing_import_of_BytesFeedParser_in_?= =?utf-8?q?email=2Eparser=2E?= Message-ID: <3ZSQ361Kk3zSCQ@mail.python.org> http://hg.python.org/cpython/rev/45f6925906bf changeset: 82675:45f6925906bf branch: 3.3 parent: 82672:166fb6ecb55a parent: 82674:4e6cf15e55c1 user: R David Murray date: Fri Mar 15 20:42:29 2013 -0400 summary: Merge: #17431: Fix missing import of BytesFeedParser in email.parser. files: Lib/email/parser.py | 2 +- Lib/test/test_email/test_email.py | 4 ++++ Misc/ACKS | 1 + Misc/NEWS | 2 ++ 4 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/email/parser.py b/Lib/email/parser.py --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -9,7 +9,7 @@ import warnings from io import StringIO, TextIOWrapper -from email.feedparser import FeedParser +from email.feedparser import FeedParser, BytesFeedParser from email.message import Message from email._policybase import compat32 diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -36,6 +36,10 @@ from test.support import unlink from test.test_email import openfile, TestEmailBase +# These imports are documented to work, but we are testing them using a +# different path, so we import them here just to make sure they are importable. +from email.parser import FeedParser, BytesFeedParser + NL = '\n' EMPTYSTRING = '' SPACE = ' ' diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -172,6 +172,7 @@ Dick Bulterman Bill Bumgarner Jimmy Burgett +Edmond Burnett Tommy Burnette Roger Burnham Alastair Burt diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -193,6 +193,8 @@ Library ------- +- Issue #17431: Fix missing import of BytesFeedParser in email.parser. + - Issue #1285086: Get rid of the refcounting hack and speed up urllib.parse.unquote() and urllib.parse.unquote_to_bytes(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 01:46:59 2013 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 Mar 2013 01:46:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2317431=3A_Fix_missing_import_of_BytesFeedPars?= =?utf-8?q?er_in_email=2Eparser=2E?= Message-ID: <3ZSQ374JQ2zSBh@mail.python.org> http://hg.python.org/cpython/rev/b7c1ed5ce714 changeset: 82676:b7c1ed5ce714 parent: 82673:46e6a8b742d9 parent: 82675:45f6925906bf user: R David Murray date: Fri Mar 15 20:45:11 2013 -0400 summary: Merge: #17431: Fix missing import of BytesFeedParser in email.parser. files: Lib/email/parser.py | 2 +- Lib/test/test_email/test_email.py | 4 ++++ Misc/ACKS | 1 + Misc/NEWS | 2 ++ 4 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/email/parser.py b/Lib/email/parser.py --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -9,7 +9,7 @@ import warnings from io import StringIO, TextIOWrapper -from email.feedparser import FeedParser +from email.feedparser import FeedParser, BytesFeedParser from email.message import Message from email._policybase import compat32 diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -36,6 +36,10 @@ from test.support import unlink from test.test_email import openfile, TestEmailBase +# These imports are documented to work, but we are testing them using a +# different path, so we import them here just to make sure they are importable. +from email.parser import FeedParser, BytesFeedParser + NL = '\n' EMPTYSTRING = '' SPACE = ' ' diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -173,6 +173,7 @@ Dick Bulterman Bill Bumgarner Jimmy Burgett +Edmond Burnett Tommy Burnette Roger Burnham Alastair Burt diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,8 @@ Library ------- +- Issue #17431: Fix missing import of BytesFeedParser in email.parser. + - Issue #12921: http.server's send_error takes an explain argument to send more information in response. Patch contributed by Karl. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 02:08:18 2013 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 Mar 2013 02:08:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_FeedParser_and?= =?utf-8?q?_BytesFeedParser_to_email=2Eparser=2E=5F=5Fall=5F=5F=2E?= Message-ID: <3ZSQWk54KwzS8Y@mail.python.org> http://hg.python.org/cpython/rev/07e0cd0d39b3 changeset: 82677:07e0cd0d39b3 user: R David Murray date: Fri Mar 15 21:00:48 2013 -0400 summary: Add missing FeedParser and BytesFeedParser to email.parser.__all__. files: Lib/email/parser.py | 3 ++- Misc/NEWS | 2 ++ 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/email/parser.py b/Lib/email/parser.py --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -4,7 +4,8 @@ """A parser of RFC 2822 and MIME email messages.""" -__all__ = ['Parser', 'HeaderParser', 'BytesParser', 'BytesHeaderParser'] +__all__ = ['Parser', 'HeaderParser', 'BytesParser', 'BytesHeaderParser', + 'FeedParser', 'BytesFeedParser'] import warnings from io import StringIO, TextIOWrapper diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -280,6 +280,8 @@ Library ------- +- Added missing FeedParser and BytesFeedParser to email.parser.__all__. + - Issue #17431: Fix missing import of BytesFeedParser in email.parser. - Issue #12921: http.server's send_error takes an explain argument to send more -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Mar 16 06:01:36 2013 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 16 Mar 2013 06:01:36 +0100 Subject: [Python-checkins] Daily reference leaks (07e0cd0d39b3): sum=0 Message-ID: results for 07e0cd0d39b3 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogAX999N', '-x'] From python-checkins at python.org Sat Mar 16 08:01:55 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:01:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIyAxMDY1?= =?utf-8?q?2=3A_make_tcl/tk_tests_run_after_=5F=5Fall=5F=5F_test=2C_patch_?= =?utf-8?q?by_Zachary_Ware=2E?= Message-ID: <3ZSZMl5GY2zSHQ@mail.python.org> http://hg.python.org/cpython/rev/b923234b60cb changeset: 82678:b923234b60cb branch: 3.2 parent: 82674:4e6cf15e55c1 user: Terry Jan Reedy date: Sat Mar 16 02:37:06 2013 -0400 summary: Issue # 10652: make tcl/tk tests run after __all__ test, patch by Zachary Ware. files: Lib/test/test_tcl.py | 3 +++ Lib/test/test_tk.py | 3 +++ Lib/test/test_ttk_guionly.py | 3 +++ Lib/test/test_ttk_textonly.py | 3 +++ Misc/NEWS | 3 +++ 5 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -8,6 +8,9 @@ # Skip this test if the _tkinter module wasn't built. _tkinter = support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter import Tcl from _tkinter import TclError diff --git a/Lib/test/test_tk.py b/Lib/test/test_tk.py --- a/Lib/test/test_tk.py +++ b/Lib/test/test_tk.py @@ -2,6 +2,9 @@ # Skip test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_guionly.py b/Lib/test/test_ttk_guionly.py --- a/Lib/test/test_ttk_guionly.py +++ b/Lib/test/test_ttk_guionly.py @@ -5,6 +5,9 @@ # Skip this test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -4,6 +4,9 @@ # Skip this test if _tkinter does not exist. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter.test import runtktests def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -964,6 +964,9 @@ Tests ----- +- Issue # 10652: make tcl/tk tests run after __all__ test, patch by + Zachary Ware. + - Issue #11963: remove human verification from test_parser and test_subprocess. - Issue #11732: add a new suppress_crash_popup() context manager to test.support -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:01:57 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:01:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=23_10652=3A_make_tcl/tk_tests_run_after_=5F=5Fall=5F=5F?= =?utf-8?q?_test=2C_patch_by_Zachary_Ware=2E?= Message-ID: <3ZSZMn0pnkzSJb@mail.python.org> http://hg.python.org/cpython/rev/596e8855895e changeset: 82679:596e8855895e branch: 3.3 parent: 82675:45f6925906bf parent: 82678:b923234b60cb user: Terry Jan Reedy date: Sat Mar 16 02:51:18 2013 -0400 summary: Issue # 10652: make tcl/tk tests run after __all__ test, patch by Zachary Ware. files: Lib/test/test_tcl.py | 3 +++ Lib/test/test_tk.py | 3 +++ Lib/test/test_ttk_guionly.py | 3 +++ Lib/test/test_ttk_textonly.py | 3 +++ Misc/NEWS | 3 +++ 5 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -8,6 +8,9 @@ # Skip this test if the _tkinter module wasn't built. _tkinter = support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter import Tcl from _tkinter import TclError diff --git a/Lib/test/test_tk.py b/Lib/test/test_tk.py --- a/Lib/test/test_tk.py +++ b/Lib/test/test_tk.py @@ -2,6 +2,9 @@ # Skip test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_guionly.py b/Lib/test/test_ttk_guionly.py --- a/Lib/test/test_ttk_guionly.py +++ b/Lib/test/test_ttk_guionly.py @@ -5,6 +5,9 @@ # Skip this test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -4,6 +4,9 @@ # Skip this test if _tkinter does not exist. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter.test import runtktests def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -654,6 +654,9 @@ Tests ----- +- Issue #10652: make tcl/tk tests run after __all__ test, patch by + Zachary Ware. + - Issue #11963: remove human verification from test_parser and test_subprocess. - Issue #11732: add a new suppress_crash_popup() context manager to test.support -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:01:58 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:01:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3ZSZMp3VT8zS4D@mail.python.org> http://hg.python.org/cpython/rev/44efcdf221f7 changeset: 82680:44efcdf221f7 parent: 82677:07e0cd0d39b3 parent: 82679:596e8855895e user: Terry Jan Reedy date: Sat Mar 16 02:52:24 2013 -0400 summary: Merge with 3.3 files: Lib/test/test_tcl.py | 3 +++ Lib/test/test_tk.py | 3 +++ Lib/test/test_ttk_guionly.py | 3 +++ Lib/test/test_ttk_textonly.py | 3 +++ Misc/NEWS | 3 +++ 5 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -8,6 +8,9 @@ # Skip this test if the _tkinter module wasn't built. _tkinter = support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter import Tcl from _tkinter import TclError diff --git a/Lib/test/test_tk.py b/Lib/test/test_tk.py --- a/Lib/test/test_tk.py +++ b/Lib/test/test_tk.py @@ -2,6 +2,9 @@ # Skip test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_guionly.py b/Lib/test/test_ttk_guionly.py --- a/Lib/test/test_ttk_guionly.py +++ b/Lib/test/test_ttk_guionly.py @@ -5,6 +5,9 @@ # Skip this test if _tkinter wasn't built. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + # Skip test if tk cannot be initialized. from tkinter.test.support import check_tk_availability check_tk_availability() diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -4,6 +4,9 @@ # Skip this test if _tkinter does not exist. support.import_module('_tkinter') +# Make sure tkinter._fix runs to set up the environment +support.import_fresh_module('tkinter') + from tkinter.test import runtktests def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -932,6 +932,9 @@ Tests ----- +- Issue #10652: make tcl/tk tests run after __all__ test, patch by + Zachary Ware. + - Issue #11963: remove human verification from test_parser and test_subprocess. - Issue #11732: add a new suppress_crash_popup() context manager to test.support -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:01:59 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:01:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_typo?= Message-ID: <3ZSZMq6DYhzSLX@mail.python.org> http://hg.python.org/cpython/rev/cec135cb059c changeset: 82681:cec135cb059c branch: 3.2 parent: 82678:b923234b60cb user: Terry Jan Reedy date: Sat Mar 16 02:53:09 2013 -0400 summary: 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 @@ -964,7 +964,7 @@ Tests ----- -- Issue # 10652: make tcl/tk tests run after __all__ test, patch by +- Issue #10652: make tcl/tk tests run after __all__ test, patch by Zachary Ware. - Issue #11963: remove human verification from test_parser and test_subprocess. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:02:01 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:02:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2312345=3A_null_merge_with_3=2E2=2E?= Message-ID: <3ZSZMs1pcdzSJs@mail.python.org> http://hg.python.org/cpython/rev/761b370f2cfd changeset: 82682:761b370f2cfd branch: 3.3 parent: 82679:596e8855895e parent: 82681:cec135cb059c user: Terry Jan Reedy date: Sat Mar 16 02:58:15 2013 -0400 summary: #12345: null merge with 3.2. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:02:02 2013 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 Mar 2013 08:02:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=2310652_null_merge_from_3=2E3_which_had_wrong_issue_=23?= Message-ID: <3ZSZMt4gdQzSJ6@mail.python.org> http://hg.python.org/cpython/rev/7c76b70075db changeset: 82683:7c76b70075db parent: 82680:44efcdf221f7 parent: 82682:761b370f2cfd user: Terry Jan Reedy date: Sat Mar 16 03:01:02 2013 -0400 summary: #10652 null merge from 3.3 which had wrong issue # files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Mar 16 08:03:51 2013 From: python-checkins at python.org (georg.brandl) Date: Sat, 16 Mar 2013 08:03:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Remove_row-spa?= =?utf-8?q?nning_cell=2C_which_the_Sphinx_text_writer_does_not_support=2E?= Message-ID: <3ZSZPz67XfzNPV@mail.python.org> http://hg.python.org/cpython/rev/6541691f5315 changeset: 82684:6541691f5315 branch: 3.3 parent: 82675:45f6925906bf user: Georg Brandl date: Sat Mar