diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py index ef82d81b7b7..e906292e17d 100644 --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -347,7 +347,7 @@ class ModifiedInterpreter(InteractiveInterpreter): rpcpid = None def spawn_subprocess(self): - if self.subprocess_arglist == None: + if self.subprocess_arglist is None: self.subprocess_arglist = self.build_subprocess_arglist() args = self.subprocess_arglist self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) diff --git a/Lib/site.py b/Lib/site.py index 14fa5703b45..3ecc5684cdb 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -112,7 +112,7 @@ def addbuilddir(): s = "build/lib.%s-%.3s" % (get_platform(), sys.version) if hasattr(sys, 'gettotalrefcount'): s += '-pydebug' - s = os.path.join(os.path.dirname(sys.path[-1]), s) + s = os.path.join(os.path.dirname(sys.path.pop()), s) sys.path.append(s) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index d0cd8552b97..c37b0bf37d7 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -612,12 +612,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, if module not in save_modules and module.startswith("test."): support.unload(module) - # The lists won't be sorted if running with -r - good.sort() - bad.sort() - skipped.sort() - environment_changed.sort() - if good and not quiet: if not bad and not skipped and len(good) > 1: print("All", end=' ') @@ -1128,7 +1122,8 @@ def printlist(x, width=70, indent=4): from textwrap import fill blanks = ' ' * indent - print(fill(' '.join(str(elt) for elt in x), width, + # Print the sorted list: 'x' may be a '--random' list or a set() + print(fill(' '.join(str(elt) for elt in sorted(x)), width, initial_indent=blanks, subsequent_indent=blanks)) # Map sys.platform to a string containing the basenames of tests diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 6cf5e3e781b..71ec2969d7b 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -298,14 +298,22 @@ class CGIHTTPServerTestCase(BaseTestCase): self.cgi_dir = os.path.join(self.parent_dir, 'cgi-bin') os.mkdir(self.cgi_dir) + # The shebang line should be pure ASCII: use symlink if possible. + # See issue #7668. + if hasattr(os, 'symlink'): + self.pythonexe = os.path.join(self.parent_dir, 'python') + os.symlink(sys.executable, self.pythonexe) + else: + self.pythonexe = sys.executable + self.file1_path = os.path.join(self.cgi_dir, 'file1.py') with open(self.file1_path, 'w') as file1: - file1.write(cgi_file1 % sys.executable) + file1.write(cgi_file1 % self.pythonexe) os.chmod(self.file1_path, 0o777) self.file2_path = os.path.join(self.cgi_dir, 'file2.py') with open(self.file2_path, 'w') as file2: - file2.write(cgi_file2 % sys.executable) + file2.write(cgi_file2 % self.pythonexe) os.chmod(self.file2_path, 0o777) self.cwd = os.getcwd() @@ -314,6 +322,8 @@ class CGIHTTPServerTestCase(BaseTestCase): def tearDown(self): try: os.chdir(self.cwd) + if self.pythonexe != sys.executable: + os.remove(self.pythonexe) os.remove(self.file1_path) os.remove(self.file2_path) os.rmdir(self.cgi_dir) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 035860bd961..6d12d12cd57 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -63,6 +63,16 @@ HAVE_GETVALUE = not getattr(_multiprocessing, WIN32 = (sys.platform == "win32") +# +# Some tests require ctypes +# + +try: + from ctypes import Structure, Value, copy, c_int, c_double +except ImportError: + Structure = object + c_int = c_double = None + # # Creates a wrapper for a function which records the time it takes to finish # @@ -506,7 +516,7 @@ class _TestQueue(BaseTestCase): queue = self.JoinableQueue() if sys.version_info < (2, 5) and not hasattr(queue, 'task_done'): - return + self.skipTest("requires 'queue.task_done()' method") workers = [self.Process(target=self._test_task_done, args=(queue,)) for i in range(4)] @@ -783,6 +793,8 @@ class _TestEvent(BaseTestCase): class _TestValue(BaseTestCase): + ALLOWED_TYPES = ('processes',) + codes_values = [ ('i', 4343, 24234), ('d', 3.625, -4.25), @@ -795,10 +807,8 @@ class _TestValue(BaseTestCase): sv.value = cv[2] + @unittest.skipIf(c_int is None, "requires _ctypes") def test_value(self, raw=False): - if self.TYPE != 'processes': - return - if raw: values = [self.RawValue(code, value) for code, value, _ in self.codes_values] @@ -816,13 +826,12 @@ class _TestValue(BaseTestCase): for sv, cv in zip(values, self.codes_values): self.assertEqual(sv.value, cv[2]) + @unittest.skipIf(c_int is None, "requires _ctypes") def test_rawvalue(self): self.test_value(raw=True) + @unittest.skipIf(c_int is None, "requires _ctypes") def test_getobj_getlock(self): - if self.TYPE != 'processes': - return - val1 = self.Value('i', 5) lock1 = val1.get_lock() obj1 = val1.get_obj() @@ -850,14 +859,14 @@ class _TestValue(BaseTestCase): class _TestArray(BaseTestCase): + ALLOWED_TYPES = ('processes',) + def f(self, seq): for i in range(1, len(seq)): seq[i] += seq[i-1] + @unittest.skipIf(c_int is None, "requires _ctypes") def test_array(self, raw=False): - if self.TYPE != 'processes': - return - seq = [680, 626, 934, 821, 150, 233, 548, 982, 714, 831] if raw: arr = self.RawArray('i', seq) @@ -880,13 +889,12 @@ class _TestArray(BaseTestCase): self.assertEqual(list(arr[:]), seq) + @unittest.skipIf(c_int is None, "requires _ctypes") def test_rawarray(self): self.test_array(raw=True) + @unittest.skipIf(c_int is None, "requires _ctypes") def test_getobj_getlock_obj(self): - if self.TYPE != 'processes': - return - arr1 = self.Array('i', list(range(10))) lock1 = arr1.get_lock() obj1 = arr1.get_obj() @@ -1570,12 +1578,6 @@ class _TestHeap(BaseTestCase): # # -try: - from ctypes import Structure, Value, copy, c_int, c_double -except ImportError: - Structure = object - c_int = c_double = None - class _Foo(Structure): _fields_ = [ ('x', c_int), @@ -1595,10 +1597,8 @@ class _TestSharedCTypes(BaseTestCase): for i in range(len(arr)): arr[i] *= 2 + @unittest.skipIf(c_int is None, "requires _ctypes") def test_sharedctypes(self, lock=False): - if c_int is None: - return - x = Value('i', 7, lock=lock) y = Value(c_double, 1.0/3.0, lock=lock) foo = Value(_Foo, 3, 2, lock=lock) @@ -1621,10 +1621,8 @@ class _TestSharedCTypes(BaseTestCase): def test_synchronize(self): self.test_sharedctypes(lock=True) + @unittest.skipIf(c_int is None, "requires _ctypes") def test_copy(self): - if c_int is None: - return - foo = _Foo(2, 5.0) bar = copy(foo) foo.x = 0 @@ -1696,13 +1694,17 @@ class _TestImportStar(BaseTestCase): ALLOWED_TYPES = ('processes',) def test_import(self): - modules = ( + modules = [ 'multiprocessing', 'multiprocessing.connection', 'multiprocessing.heap', 'multiprocessing.managers', 'multiprocessing.pool', 'multiprocessing.process', - 'multiprocessing.reduction', 'multiprocessing.sharedctypes', + 'multiprocessing.reduction', 'multiprocessing.synchronize', 'multiprocessing.util' - ) + ] + + if c_int is not None: + # This module requires _ctypes + modules.append('multiprocessing.sharedctypes') for name in modules: __import__(name) @@ -1782,12 +1784,12 @@ class _TestLogging(BaseTestCase): class TestInvalidHandle(unittest.TestCase): + @unittest.skipIf(WIN32, "skipped on Windows") def test_invalid_handles(self): - if WIN32: - return conn = _multiprocessing.Connection(44977608) self.assertRaises(IOError, conn.poll) self.assertRaises(IOError, _multiprocessing.Connection, -1) + # # Functions used to create test cases from the base ones in this module # @@ -1804,7 +1806,7 @@ def get_attributes(Source, names): def create_test_cases(Mixin, type): result = {} glob = globals() - Type = type[0].upper() + type[1:] + Type = type.capitalize() for name in list(glob.keys()): if name.startswith('_Test'): diff --git a/Lib/test/test_pep277.py b/Lib/test/test_pep277.py index 1465d54e752..aba1368997b 100644 --- a/Lib/test/test_pep277.py +++ b/Lib/test/test_pep277.py @@ -15,11 +15,6 @@ filenames = [ '\u66e8\u66e9\u66eb', '\u66e8\u05e9\u3093\u0434\u0393\xdf', # Specific code points: fn, NFC(fn) and NFKC(fn) all differents - '\u2000\u2000\u2000A', - '\u2001\u2001\u2001A', - '\u2003\u2003\u2003A', # == NFC('\u2001\u2001\u2001A') - '\u0020\u0020\u0020A', # '\u0020' == ' ' == NFKC('\u2000') - # '\u0020' == NFKC('\u2001') == NFKC('\u2003') '\u1fee\u1ffd', # Specific code points: NFC(fn), NFD(fn), NFKC(fn) and NFKD(fn) all differents '\u0385\u03d3\u03d4', @@ -28,6 +23,22 @@ filenames = [ '\u1e9b\u1fc1\u1fcd\u1fce\u1fcf\u1fdd\u1fde\u1fdf\u1fed', ] +# Mac OS X decomposes Unicode names, using Normal Form D. +# http://developer.apple.com/mac/library/qa/qa2001/qa1173.html +# "However, most volume formats do not follow the exact specification for +# these normal forms. For example, HFS Plus uses a variant of Normal Form D +# in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through +# U+2FAFF are not decomposed." +if sys.platform != 'darwin': + filenames.extend([ + # Specific code points: fn, NFC(fn) and NFKC(fn) all differents + '\u1fee\u1ffd\ufad1', + '\u2000\u2000\u2000A', + '\u2001\u2001\u2001A', + '\u2003\u2003\u2003A', # == NFC('\u2001\u2001\u2001A') + '\u0020\u0020\u0020A', # '\u0020' == ' ' == NFKC('\u2000') == + # NFKC('\u2001') == NFKC('\u2003') +]) # Destroy directory dirname and all files under it, to one level. def deltree(dirname): @@ -114,8 +125,7 @@ class UnicodeFileTests(unittest.TestCase): files = set(normalize('NFD', file) for file in files) for name in others: if sys.platform == 'darwin' and normalize('NFD', name) in files: - # Mac OS X decomposes Unicode names, using Normal Form D. - # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html + # Mac OS X decomposes Unicode names. See comment above. os.stat(name) continue self._apply_failure(open, name, IOError) @@ -131,8 +141,7 @@ class UnicodeFileTests(unittest.TestCase): f1 = os.listdir(support.TESTFN.encode(sys.getfilesystemencoding())) f2 = os.listdir(support.TESTFN) if sys.platform == 'darwin': - # Mac OS X returns canonically decomposed Unicode (Normal Form D) - # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html + # Mac OS X decomposes Unicode names. See comment above. sf0 = set(normalize('NFD', f) for f in self.files) f2 = [normalize('NFD', f) for f in f2] sf2 = set(os.path.join(support.TESTFN, f) for f in f2) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index dda704e22f5..7bd71914b4a 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -27,11 +27,15 @@ def warnings_state(module): except NameError: pass original_warnings = warning_tests.warnings + original_filters = module.filters try: + module.filters = original_filters[:] + module.simplefilter("once") warning_tests.warnings = module yield finally: warning_tests.warnings = original_warnings + module.filters = original_filters class BaseTest(unittest.TestCase): @@ -194,6 +198,7 @@ class WarnTests(unittest.TestCase): def test_message(self): with original_warnings.catch_warnings(record=True, module=self.module) as w: + self.module.simplefilter("once") for i in range(4): text = 'multi %d' %i # Different text on each call. self.module.warn(text) @@ -206,6 +211,7 @@ class WarnTests(unittest.TestCase): for ob in (Warning, None, 42): with original_warnings.catch_warnings(record=True, module=self.module) as w: + self.module.simplefilter("once") self.module.warn(ob) # Don't directly compare objects since # ``Warning() != Warning()``. diff --git a/Lib/turtle.py b/Lib/turtle.py index 1355d564adb..6f0605984fd 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -778,7 +778,7 @@ class TurtleScreenBase(object): # needs amendment if not isinstance(self.cv, ScrolledCanvas): return self.canvwidth, self.canvheight - if canvwidth is None and canvheight is None and bg is None: + if canvwidth is canvheight is bg is None: return self.cv.canvwidth, self.cv.canvheight if canvwidth is not None: self.canvwidth = canvwidth @@ -1046,7 +1046,7 @@ class TurtleScreen(TurtleScreenBase): >>> mode() 'logo' """ - if mode == None: + if mode is None: return self._mode mode = mode.lower() if mode not in ["standard", "logo", "world"]: @@ -1385,7 +1385,7 @@ class TurtleScreen(TurtleScreenBase): ### repeatedly pressing the up-arrow key, ### consequently drawing a hexagon """ - if fun == None: + if fun is None: if key in self._keys: self._keys.remove(key) elif key not in self._keys: @@ -1418,7 +1418,7 @@ class TurtleScreen(TurtleScreenBase): ### or by keeping pressed the up-arrow key. ### consequently drawing a hexagon. """ - if fun == None: + if fun is None: if key in self._keys: self._keys.remove(key) elif key is not None and key not in self._keys: @@ -1540,7 +1540,7 @@ class TNavigator(object): def _setmode(self, mode=None): """Set turtle-mode to 'standard', 'world' or 'logo'. """ - if mode == None: + if mode is None: return self._mode if mode not in ["standard", "logo", "world"]: return @@ -2795,7 +2795,7 @@ class RawTurtle(TPen, TNavigator): >>> turtle.shapesize(5, 5, 12) >>> turtle.shapesize(outline=8) """ - if stretch_wid is stretch_len is outline == None: + if stretch_wid is stretch_len is outline is None: stretch_wid, stretch_len = self._stretchfactor return stretch_wid, stretch_len, self._outlinewidth if stretch_wid == 0 or stretch_len == 0: diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py index 68a723ae433..fe658492f33 100644 --- a/Lib/unittest/test/test_assertions.py +++ b/Lib/unittest/test/test_assertions.py @@ -1,7 +1,5 @@ import unittest -import warnings - class Test_Assertions(unittest.TestCase): def test_AlmostEqual(self): @@ -108,11 +106,9 @@ class TestLongMessage(unittest.TestCase): self.testableTrue._formatMessage(object(), 'foo') def test_formatMessage_unicode_error(self): - with warnings.catch_warnings(record=True): - # This causes a UnicodeWarning due to its craziness - one = ''.join(chr(i) for i in range(255)) - # this used to cause a UnicodeDecodeError constructing msg - self.testableTrue._formatMessage(one, '\uFFFD') + one = ''.join(chr(i) for i in range(255)) + # this used to cause a UnicodeDecodeError constructing msg + self.testableTrue._formatMessage(one, '\uFFFD') def assertMessages(self, methodName, args, errors): def getMethod(i): diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index c9f346f3534..08c4a7b20af 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1,6 +1,5 @@ import re import sys -import warnings from copy import deepcopy from test import support @@ -496,12 +495,10 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing): with self.assertRaises(self.failureException): self.assertDictContainsSubset({'a': 1, 'c': 1}, {'a': 1}) - with warnings.catch_warnings(record=True): - # silence the UnicodeWarning - one = ''.join(chr(i) for i in range(255)) - # this used to cause a UnicodeDecodeError constructing the failure msg - with self.assertRaises(self.failureException): - self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'}) + one = ''.join(chr(i) for i in range(255)) + # this used to cause a UnicodeDecodeError constructing the failure msg + with self.assertRaises(self.failureException): + self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'}) def testAssertEqual(self): equal_pairs = [ @@ -615,9 +612,9 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing): # hashable types, but not orderable self.assertRaises(self.failureException, self.assertItemsEqual, [], [divmod, 'x', 1, 5j, 2j, frozenset()]) - # comparing dicts raises a py3k warning + # comparing dicts self.assertItemsEqual([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}]) - # comparing heterogenous non-hashable sequences raises a py3k warning + # comparing heterogenous non-hashable sequences self.assertItemsEqual([1, 'x', divmod, []], [divmod, [], 'x', 1]) self.assertRaises(self.failureException, self.assertItemsEqual, [], [divmod, [], 'x', 1, 5j, 2j, set()]) @@ -852,10 +849,9 @@ test case (self.assertSameElements, ([1, 1, 2, 3], [1, 2, 3])) ) for meth, args in old: - with warnings.catch_warnings(record=True) as w: + with support.check_warnings(('', DeprecationWarning)) as w: meth(*args) - self.assertEqual(len(w), 1) - self.assertIs(w[0].category, DeprecationWarning) + self.assertEqual(len(w.warnings), 1) def testDeepcopy(self): # Issue: 5660 diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index 9002466b5e7..967b662b4da 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -308,12 +308,11 @@ OldResult = type('OldResult', (object,), classDict) class Test_OldTestResult(unittest.TestCase): def assertOldResultWarning(self, test, failures): - with warnings.catch_warnings(record=True) as log: + with support.check_warnings(("TestResult has no add.+ method,", + RuntimeWarning)): result = OldResult() test.run(result) self.assertEqual(len(result.failures), failures) - warning, = log - self.assertIs(warning.category, RuntimeWarning) def testOldTestResult(self): class Test(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index b7c926971a1..3de388e6405 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -302,6 +302,9 @@ Library some methods (such as oss_mixer_device.fileno()) were not available. Initial patch by Bertrand Janin. +- Issue #8205: Remove the "Modules" directory from sys.path when Python is + running from the build directory (POSIX only). + - Issue #7512: shutil.copystat() could raise an OSError when the filesystem didn't support chflags() (for example ZFS under FreeBSD). The error is now silenced. @@ -950,8 +953,8 @@ Documentation Tests ----- -- Issue #8180: Fix test_pep277 on OS X and add more tests for special Unicode - normalization cases. +- Issue #8180 and #8207: Fix test_pep277 on OS X and add more tests for special + Unicode normalization cases. - Issue #7783: test.support.open_urlresource invalidates the outdated files from the local cache.