From e52e3786c67e16b7b8adba71227f9e3c5350d7a6 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Fri, 17 Jul 2009 09:18:18 +0000 Subject: Merged revisions 73995,74002,74005,74007-74008,74011,74019-74023 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73995 | vinay.sajip | 2009-07-13 07:21:05 -0400 (Mon, 13 Jul 2009) | 1 line Issue #6314: logging: Extra checks on the "level" argument in more places. ........ r74002 | marc-andre.lemburg | 2009-07-13 16:23:49 -0400 (Mon, 13 Jul 2009) | 6 lines Use a new global DEV_NULL instead of hard-coding /dev/null into the system command helper functions. See #6479 for some motivation. ........ r74005 | marc-andre.lemburg | 2009-07-13 17:28:33 -0400 (Mon, 13 Jul 2009) | 6 lines Use a different VER command output parser to address the localization issues mentioned in #3410. Prepare for Windows 7 (still commented out). ........ r74007 | michael.foord | 2009-07-14 13:58:12 -0400 (Tue, 14 Jul 2009) | 1 line Move TestRunner initialisation into unittest.TestProgram.runTests. Fixes issue 6418. ........ r74008 | benjamin.peterson | 2009-07-14 20:46:42 -0400 (Tue, 14 Jul 2009) | 1 line update year ........ r74011 | ezio.melotti | 2009-07-15 13:07:04 -0400 (Wed, 15 Jul 2009) | 1 line methods' names pep8ification ........ r74019 | amaury.forgeotdarc | 2009-07-15 17:29:27 -0400 (Wed, 15 Jul 2009) | 2 lines #6076 Add a title to the IDLE Preferences window. ........ r74020 | georg.brandl | 2009-07-16 03:18:07 -0400 (Thu, 16 Jul 2009) | 1 line #5910: fix kqueue for calls with more than one event. ........ r74021 | georg.brandl | 2009-07-16 03:33:04 -0400 (Thu, 16 Jul 2009) | 1 line #6486: start with built in functions rather than "built in objects". ........ r74022 | georg.brandl | 2009-07-16 03:38:35 -0400 (Thu, 16 Jul 2009) | 1 line #6481: fix typo in os.system() replacement. ........ r74023 | jesse.noller | 2009-07-16 10:23:04 -0400 (Thu, 16 Jul 2009) | 1 line Issue 6433: multiprocessing.pool.map hangs on empty list ........ --- Doc/copyright.rst | 2 +- Doc/library/intro.rst | 5 +++-- Doc/library/subprocess.rst | 2 +- Lib/idlelib/configDialog.py | 1 + Lib/multiprocessing/pool.py | 2 ++ Lib/platform.py | 41 +++++++++++++++++++++++++++++++++++----- Lib/test/test_kqueue.py | 16 ++++++++++++++++ Lib/test/test_multiprocessing.py | 6 ++++++ Lib/test/test_unittest.py | 9 --------- Lib/unittest.py | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 11 +++++++++++ Modules/selectmodule.c | 7 ++++--- 13 files changed, 84 insertions(+), 23 deletions(-) diff --git a/Doc/copyright.rst b/Doc/copyright.rst index 376b1c4..ec78a38 100644 --- a/Doc/copyright.rst +++ b/Doc/copyright.rst @@ -4,7 +4,7 @@ Copyright Python and this documentation is: -Copyright © 2001-2008 Python Software Foundation. All rights reserved. +Copyright © 2001-2009 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff --git a/Doc/library/intro.rst b/Doc/library/intro.rst index ce1691d..a0f2d63 100644 --- a/Doc/library/intro.rst +++ b/Doc/library/intro.rst @@ -43,8 +43,9 @@ browse the table of contents (in front of the manual), or look for a specific function, module or term in the index (in the back). And finally, if you enjoy learning about random subjects, you choose a random page number (see module :mod:`random`) and read a section or two. Regardless of the order in which you -read the sections of this manual, it helps to start with chapter :ref:`builtin`, -as the remainder of the manual assumes familiarity with this material. +read the sections of this manual, it helps to start with chapter +:ref:`built-in-funcs`, as the remainder of the manual assumes familiarity with +this material. Let the show begin! diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index d0e655d..169801b 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -420,7 +420,7 @@ Replacing :func:`os.system` sts = os.system("mycmd" + " myarg") ==> p = Popen("mycmd" + " myarg", shell=True) - sts = os.waitpid(p.pid, 0) + sts = os.waitpid(p.pid, 0)[1] Notes: diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py index 20ed827..6482119 100644 --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -30,6 +30,7 @@ class ConfigDialog(Toplevel): self.wm_withdraw() self.configure(borderwidth=5) + self.title('IDLE Preferences') self.geometry("+%d+%d" % (parent.winfo_rootx()+20, parent.winfo_rooty()+30)) #Theme Elements. Each theme element key is its display name. diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py index 5c1805f..d3ecc9b 100644 --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -208,6 +208,8 @@ class Pool(object): chunksize, extra = divmod(len(iterable), len(self._pool) * 4) if extra: chunksize += 1 + if len(iterable) == 0: + chunksize = 0 task_batches = Pool._get_tasks(func, iterable, chunksize) result = MapResult(self._cache, chunksize, len(iterable), callback) diff --git a/Lib/platform.py b/Lib/platform.py index 21e098b..640098f 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -32,6 +32,7 @@ # # # +# 1.0.7 - added DEV_NULL # 1.0.6 - added linux_distribution() # 1.0.5 - fixed Java support to allow running the module on Jython # 1.0.4 - added IronPython support @@ -89,7 +90,7 @@ __copyright__ = """ Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com - Copyright (c) 2000-2008, eGenix.com Software GmbH; mailto:info@egenix.com + Copyright (c) 2000-2009, eGenix.com Software GmbH; mailto:info@egenix.com Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee or royalty is hereby granted, @@ -108,10 +109,25 @@ __copyright__ = """ """ -__version__ = '1.0.6' +__version__ = '1.0.7' import sys, os, re +### Globals & Constants + +# Determine the platform's /dev/null device +try: + DEV_NULL = os.devnull +except AttributeError: + # os.devnull was added in Python 2.4, so emulate it for earlier + # Python versions + if sys.platform in ('dos','win32','win16','os2'): + # Use the old CP/M NUL as device name + DEV_NULL = 'NUL' + else: + # Standard Unix uses /dev/null + DEV_NULL = '/dev/null' + ### Platform specific APIs _libc_search = re.compile(r'(__libc_init)' @@ -446,7 +462,16 @@ def _norm_version(version, build=''): _ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) ' '.*' - 'Version ([\d.]+))', re.ASCII) + '\[.* ([\d.]+)\])') + +# Examples of VER command output: +# +# Windows 2000: Microsoft Windows 2000 [Version 5.00.2195] +# Windows XP: Microsoft Windows XP [Version 5.1.2600] +# Windows Vista: Microsoft Windows [Version 6.0.6002] +# +# Note that the "Version" string gets localized on different +# Windows versions. def _syscmd_ver(system='', release='', version='', @@ -578,6 +603,7 @@ def win32_ver(release='',version='',csd='',ptype=''): version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF) if csd[:13] == 'Service Pack ': csd = 'SP' + csd[13:] + if plat == VER_PLATFORM_WIN32_WINDOWS: regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion' # Try to guess the release name @@ -592,6 +618,7 @@ def win32_ver(release='',version='',csd='',ptype=''): release = 'postMe' elif maj == 5: release = '2000' + elif plat == VER_PLATFORM_WIN32_NT: regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' if maj <= 4: @@ -620,8 +647,12 @@ def win32_ver(release='',version='',csd='',ptype=''): release = 'Vista' else: release = '2008Server' + #elif min == 1: + # # Windows 7 release candidate uses version 6.1.7100 + # release = '7RC' else: release = 'post2008Server' + else: if not release: # E.g. Win3.1 with win32s @@ -902,7 +933,7 @@ def _syscmd_uname(option,default=''): # XXX Others too ? return default try: - f = os.popen('uname %s 2> /dev/null' % option) + f = os.popen('uname %s 2> %s' % (option, DEV_NULL)) except (AttributeError,os.error): return default output = f.read().strip() @@ -927,7 +958,7 @@ def _syscmd_file(target,default=''): return default target = _follow_symlinks(target) try: - f = os.popen('file "%s" 2> /dev/null' % target) + f = os.popen('file "%s" 2> %s' % (target, DEV_NULL)) except (AttributeError,os.error): return default output = f.read().strip() diff --git a/Lib/test/test_kqueue.py b/Lib/test/test_kqueue.py index dd1ecc8..5ba21a2 100644 --- a/Lib/test/test_kqueue.py +++ b/Lib/test/test_kqueue.py @@ -163,6 +163,22 @@ class TestKQueue(unittest.TestCase): server.close() serverSocket.close() + def testPair(self): + kq = select.kqueue() + a, b = socket.socketpair() + + a.send(b'foo') + event1 = select.kevent(a, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE) + event2 = select.kevent(b, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE) + r = kq.control([event1, event2], 1, 1) + self.assertTrue(r) + self.assertFalse(r[0].flags & select.KQ_EV_ERROR) + self.assertEquals(b.recv(r[0].data), b'foo') + + a.close() + b.close() + kq.close() + def test_main(): support.run_unittest(TestKQueue) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 9d58cdc..2189ff5 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -990,6 +990,12 @@ class _TestPool(BaseTestCase): self.assertEqual(pmap(sqr, list(range(100)), chunksize=20), list(map(sqr, list(range(100))))) + def test_map_chunksize(self): + try: + self.pool.map_async(sqr, [], chunksize=1).get(timeout=TIMEOUT1) + except multiprocessing.TimeoutError: + self.fail("pool.map_async with chunksize stalled on null list") + def test_async(self): res = self.pool.apply_async(sqr, (7, TIMEOUT1,)) get = TimingWrapper(res.get) diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index af684c0..991740c 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -3303,15 +3303,6 @@ class Test_TestProgram(TestCase): self.assertEqual(runner.test, test) self.assertEqual(program.verbosity, 2) - - def testTestProgram_testRunnerArgument(self): - program = object.__new__(TestProgram) - program.parseArgs = lambda _: None - program.runTests = lambda: None - program.__init__(testRunner=None) - self.assertEqual(program.testRunner, unittest.TextTestRunner) - - class FooBar(unittest.TestCase): def testPass(self): assert True diff --git a/Lib/unittest.py b/Lib/unittest.py index 611088b..d45f8d3 100644 --- a/Lib/unittest.py +++ b/Lib/unittest.py @@ -1684,8 +1684,6 @@ class TestProgram(object): argv=None, testRunner=None, testLoader=defaultTestLoader, exit=True, verbosity=1): - if testRunner is None: - testRunner = TextTestRunner if isinstance(module, str): self.module = __import__(module) for part in module.split('.')[1:]: @@ -1775,6 +1773,8 @@ class TestProgram(object): self.test = loader.discover(start_dir, pattern, top_level_dir) def runTests(self): + if self.testRunner is None: + self.testRunner = TextTestRunner if isinstance(self.testRunner, type): try: testRunner = self.testRunner(verbosity=self.verbosity) diff --git a/Misc/ACKS b/Misc/ACKS index 0fa88ed..179a279 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -197,6 +197,7 @@ Walter D Hans Eckardt Grant Edwards John Ehresman +Eric Eisner Andrew Eland Lance Ellinghaus David Ely diff --git a/Misc/NEWS b/Misc/NEWS index eed368f..2b15812 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -908,6 +908,13 @@ Library It's `distutils.util.get_compiler_versions`. Added deprecation warnings for the obsolete get_versions() functions. +- Issue #6433: fixed issues with multiprocessing.pool.map hanging on empty list + +- Issue #6314: logging: Extra checks on the "level" argument in more places. + +- Issue #2622: Fixed an ImportError when importing email.messsage from a + standalone application built with py2exe or py2app. + - Issue #6459: distutils.command.build_ext.get_export_symbols now uses the "PyInit" prefix, rather than "init". @@ -920,6 +927,10 @@ Library - Issue #6403: Fixed package path usage in build_ext. +- Issues #5155, 5313, 5331: multiprocessing.Process._bootstrap was + unconditionally calling "os.close(sys.stdin.fileno())" resulting in file + descriptor errors + - Issue #6365: Distutils build_ext inplace mode was copying the compiled extension in a subdirectory if the extension name had dots. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index d40e8b5..bb24f14 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1492,7 +1492,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) if (nevents < 0) { PyErr_Format(PyExc_ValueError, "Length of eventlist must be 0 or positive, got %d", - nchanges); + nevents); return NULL; } @@ -1550,6 +1550,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) PyErr_NoMemory(); return NULL; } + i = 0; while ((ei = PyIter_Next(it)) != NULL) { if (!kqueue_event_Check(ei)) { Py_DECREF(ei); @@ -1558,7 +1559,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) "select.kevent objects"); goto error; } else { - chl[i] = ((kqueue_event_Object *)ei)->e; + chl[i++] = ((kqueue_event_Object *)ei)->e; } Py_DECREF(ei); } @@ -1589,7 +1590,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) goto error; } - for (i=0; i < gotevents; i++) { + for (i = 0; i < gotevents; i++) { kqueue_event_Object *ch; ch = PyObject_New(kqueue_event_Object, &kqueue_event_Type); -- cgit v0.12