diff options
Diffstat (limited to 'Lib')
43 files changed, 862 insertions, 216 deletions
diff --git a/Lib/_weakrefset.py b/Lib/_weakrefset.py index 4265369..6a98b88 100644 --- a/Lib/_weakrefset.py +++ b/Lib/_weakrefset.py @@ -63,7 +63,7 @@ class WeakSet: yield item def __len__(self): - return sum(x() is not None for x in self.data) + return len(self.data) - len(self._pending_removals) def __contains__(self, item): try: @@ -114,36 +114,21 @@ class WeakSet: def update(self, other): if self._pending_removals: self._commit_removals() - if isinstance(other, self.__class__): - self.data.update(other.data) - else: - for element in other: - self.add(element) + for element in other: + self.add(element) def __ior__(self, other): self.update(other) return self - # Helper functions for simple delegating methods. - def _apply(self, other, method): - if not isinstance(other, self.__class__): - other = self.__class__(other) - newdata = method(other.data) - newset = self.__class__() - newset.data = newdata - return newset - def difference(self, other): - return self._apply(other, self.data.difference) + newset = self.copy() + newset.difference_update(other) + return newset __sub__ = difference def difference_update(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.difference_update(ref(item) for item in other) + self.__isub__(other) def __isub__(self, other): if self._pending_removals: self._commit_removals() @@ -154,13 +139,11 @@ class WeakSet: return self def intersection(self, other): - return self._apply(other, self.data.intersection) + return self.__class__(item for item in other if item in self) __and__ = intersection def intersection_update(self, other): - if self._pending_removals: - self._commit_removals() - self.data.intersection_update(ref(item) for item in other) + self.__iand__(other) def __iand__(self, other): if self._pending_removals: self._commit_removals() @@ -169,17 +152,17 @@ class WeakSet: def issubset(self, other): return self.data.issubset(ref(item) for item in other) - __lt__ = issubset + __le__ = issubset - def __le__(self, other): - return self.data <= set(ref(item) for item in other) + def __lt__(self, other): + return self.data < set(ref(item) for item in other) def issuperset(self, other): return self.data.issuperset(ref(item) for item in other) - __gt__ = issuperset + __ge__ = issuperset - def __ge__(self, other): - return self.data >= set(ref(item) for item in other) + def __gt__(self, other): + return self.data > set(ref(item) for item in other) def __eq__(self, other): if not isinstance(other, self.__class__): @@ -187,27 +170,24 @@ class WeakSet: return self.data == set(ref(item) for item in other) def symmetric_difference(self, other): - return self._apply(other, self.data.symmetric_difference) + newset = self.copy() + newset.symmetric_difference_update(other) + return newset __xor__ = symmetric_difference def symmetric_difference_update(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.symmetric_difference_update(ref(item) for item in other) + self.__ixor__(other) def __ixor__(self, other): if self._pending_removals: self._commit_removals() if self is other: self.data.clear() else: - self.data.symmetric_difference_update(ref(item) for item in other) + self.data.symmetric_difference_update(ref(item, self._remove) for item in other) return self def union(self, other): - return self._apply(other, self.data.union) + return self.__class__(e for s in (self, other) for e in s) __or__ = union def isdisjoint(self, other): diff --git a/Lib/distutils/tests/test_bdist_msi.py b/Lib/distutils/tests/test_bdist_msi.py index 9308c79..15d8bdf 100644 --- a/Lib/distutils/tests/test_bdist_msi.py +++ b/Lib/distutils/tests/test_bdist_msi.py @@ -1,12 +1,11 @@ """Tests for distutils.command.bdist_msi.""" -import unittest import sys - +import unittest from test.support import run_unittest - from distutils.tests import support -@unittest.skipUnless(sys.platform=="win32", "These tests are only for win32") + +@unittest.skipUnless(sys.platform == 'win32', 'these tests require Windows') class BDistMSITestCase(support.TempdirManager, support.LoggingSilencer, unittest.TestCase): @@ -14,10 +13,11 @@ class BDistMSITestCase(support.TempdirManager, def test_minimal(self): # minimal test XXX need more tests from distutils.command.bdist_msi import bdist_msi - pkg_pth, dist = self.create_dist() + project_dir, dist = self.create_dist() cmd = bdist_msi(dist) cmd.ensure_finalized() + def test_suite(): return unittest.makeSuite(BDistMSITestCase) diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py index fd71dac..1ba2a1a 100644 --- a/Lib/distutils/tests/test_sdist.py +++ b/Lib/distutils/tests/test_sdist.py @@ -6,6 +6,7 @@ import warnings import zipfile from os.path import join from textwrap import dedent +from test.support import captured_stdout, check_warnings, run_unittest try: import zlib @@ -13,7 +14,6 @@ try: except ImportError: ZLIB_SUPPORT = False -from test.support import captured_stdout, check_warnings, run_unittest from distutils.command.sdist import sdist, show_formats from distutils.core import Distribution @@ -326,6 +326,7 @@ class SDistTestCase(PyPIRCCommandTestCase): # filling data_files by pointing files in package_data dist.package_data = {'somecode': ['*.txt']} self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#') + cmd.formats = ['gztar'] cmd.ensure_finalized() cmd.run() diff --git a/Lib/email/__init__.py b/Lib/email/__init__.py index bd316fd..ff16f6a 100644 --- a/Lib/email/__init__.py +++ b/Lib/email/__init__.py @@ -11,6 +11,7 @@ __all__ = [ 'charset', 'encoders', 'errors', + 'feedparser', 'generator', 'header', 'iterators', diff --git a/Lib/email/feedparser.py b/Lib/email/feedparser.py index 60a8325..aa8a2ff 100644 --- a/Lib/email/feedparser.py +++ b/Lib/email/feedparser.py @@ -19,7 +19,7 @@ the current message. Defects are just instances that live on the message object's .defects attribute. """ -__all__ = ['FeedParser'] +__all__ = ['FeedParser', 'BytesFeedParser'] import re diff --git a/Lib/email/generator.py b/Lib/email/generator.py index f0e7a95..04c0210 100644 --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -4,7 +4,7 @@ """Classes to generate plain text from a message object tree.""" -__all__ = ['Generator', 'DecodedGenerator'] +__all__ = ['Generator', 'DecodedGenerator', 'BytesGenerator'] import re import sys @@ -360,7 +360,7 @@ class BytesGenerator(Generator): for h, v in msg._headers: self.write('%s: ' % h) if isinstance(v, Header): - self.write(v.encode(maxlinelen=self._maxheaderlen)+NL) + self.write(v.encode(maxlinelen=self._maxheaderlen)+self._NL) elif _has_surrogates(v): # If we have raw 8bit data in a byte string, we have no idea # what the encoding is. There is no safe way to split this diff --git a/Lib/email/header.py b/Lib/email/header.py index 2e687b7..3250d36 100644 --- a/Lib/email/header.py +++ b/Lib/email/header.py @@ -283,7 +283,12 @@ class Header: # character set, otherwise an early error is thrown. output_charset = charset.output_codec or 'us-ascii' if output_charset != _charset.UNKNOWN8BIT: - s.encode(output_charset, errors) + try: + s.encode(output_charset, errors) + except UnicodeEncodeError: + if output_charset!='us-ascii': + raise + charset = UTF8 self._chunks.append((s, charset)) def encode(self, splitchars=';, \t', maxlinelen=None, linesep='\n'): diff --git a/Lib/email/parser.py b/Lib/email/parser.py index 6caaff5..1c931ea 100644 --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -4,7 +4,7 @@ """A parser of RFC 2822 and MIME email messages.""" -__all__ = ['Parser', 'HeaderParser'] +__all__ = ['Parser', 'HeaderParser', 'BytesParser'] import warnings from io import StringIO, TextIOWrapper diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py index 102e15b..5db34dc 100644 --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -619,6 +619,19 @@ class TestMessageAPI(TestEmailBase): msg['Dummy'] = 'dummy\nX-Injected-Header: test' self.assertRaises(errors.HeaderParseError, msg.as_string) + def test_unicode_header_defaults_to_utf8_encoding(self): + # Issue 14291 + m = MIMEText('abc\n') + m['Subject'] = 'É test' + self.assertEqual(str(m),textwrap.dedent("""\ + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Subject: =?utf-8?q?=C3=89_test?= + + abc + """)) + # Test the email.encoders module class TestEncoders(unittest.TestCase): @@ -1060,9 +1073,13 @@ Subject: =?iso-8859-1?q?Britische_Regierung_gibt_gr=FCnes_Licht_f=FCr_Offshore-W 'f\xfcr Offshore-Windkraftprojekte ' '<a-very-long-address@example.com>') msg['Reply-To'] = header_string - self.assertRaises(UnicodeEncodeError, msg.as_string) + eq(msg.as_string(maxheaderlen=78), """\ +Reply-To: =?utf-8?q?Britische_Regierung_gibt_gr=C3=BCnes_Licht_f=C3=BCr_Offs?= + =?utf-8?q?hore-Windkraftprojekte_=3Ca-very-long-address=40example=2Ecom=3E?= + +""") msg = Message() - msg['Reply-To'] = Header(header_string, 'utf-8', + msg['Reply-To'] = Header(header_string, header_name='Reply-To') eq(msg.as_string(maxheaderlen=78), """\ Reply-To: =?utf-8?q?Britische_Regierung_gibt_gr=C3=BCnes_Licht_f=C3=BCr_Offs?= @@ -1226,7 +1243,6 @@ List: List-Unsubscribe: =?utf-8?q?_folding_white_space_works?=""")+'\n') - # Test mangling of "From " lines in the body of a message class TestFromMangling(unittest.TestCase): def setUp(self): @@ -2502,14 +2518,11 @@ class TestMiscellaneous(TestEmailBase): def test__all__(self): module = __import__('email') - # Can't use sorted() here due to Python 2.3 compatibility - all = module.__all__[:] - all.sort() - self.assertEqual(all, [ - 'base64mime', 'charset', 'encoders', 'errors', 'generator', - 'header', 'iterators', 'message', 'message_from_binary_file', - 'message_from_bytes', 'message_from_file', - 'message_from_string', 'mime', 'parser', + self.assertEqual(sorted(module.__all__), [ + 'base64mime', 'charset', 'encoders', 'errors', 'feedparser', + 'generator', 'header', 'iterators', 'message', + 'message_from_binary_file', 'message_from_bytes', + 'message_from_file', 'message_from_string', 'mime', 'parser', 'quoprimime', 'utils', ]) @@ -3424,6 +3437,30 @@ class Test8BitBytesHandling(unittest.TestCase): g.flatten(msg) self.assertEqual(s.getvalue(), source) + def test_bytes_generator_b_encoding_linesep(self): + # Issue 14062: b encoding was tacking on an extra \n. + m = Message() + # This has enough non-ascii that it should always end up b encoded. + m['Subject'] = Header('žluťoučký kůň') + s = BytesIO() + g = email.generator.BytesGenerator(s) + g.flatten(m, linesep='\r\n') + self.assertEqual( + s.getvalue(), + b'Subject: =?utf-8?b?xb5sdcWlb3XEjWvDvSBrxa/FiA==?=\r\n\r\n') + + def test_generator_b_encoding_linesep(self): + # Since this broke in ByteGenerator, test Generator for completeness. + m = Message() + # This has enough non-ascii that it should always end up b encoded. + m['Subject'] = Header('žluťoučký kůň') + s = StringIO() + g = email.generator.Generator(s) + g.flatten(m, linesep='\r\n') + self.assertEqual( + s.getvalue(), + 'Subject: =?utf-8?b?xb5sdcWlb3XEjWvDvSBrxa/FiA==?=\r\n\r\n') + maxDiff = None diff --git a/Lib/http/server.py b/Lib/http/server.py index 6642729..537df90 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -850,7 +850,14 @@ def _url_collapse_path_split(path): # Filter out blank non trailing parts before consuming the '..'. path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] if path_parts: - tail_part = path_parts.pop() + # Special case for CGI's for PATH_INFO + if path.startswith('/cgi-bin') or path.startswith('/htbin'): + tail_part = [] + while path_parts[-1] not in ('cgi-bin','htbin'): + tail_part.insert(0,path_parts.pop()) + tail_part = "/".join(tail_part) + else: + tail_part = path_parts.pop() else: tail_part = '' head_parts = [] diff --git a/Lib/idlelib/CallTipWindow.py b/Lib/idlelib/CallTipWindow.py index 27ed085..a2431f8 100644 --- a/Lib/idlelib/CallTipWindow.py +++ b/Lib/idlelib/CallTipWindow.py @@ -22,6 +22,7 @@ class CallTip: self.parenline = self.parencol = None self.lastline = None self.hideid = self.checkhideid = None + self.checkhide_after_id = None def position_window(self): """Check if needs to reposition the window, and if so - do it.""" @@ -102,7 +103,10 @@ class CallTip: self.hidetip() else: self.position_window() - self.widget.after(CHECKHIDE_TIME, self.checkhide_event) + if self.checkhide_after_id is not None: + self.widget.after_cancel(self.checkhide_after_id) + self.checkhide_after_id = \ + self.widget.after(CHECKHIDE_TIME, self.checkhide_event) def hide_event(self, event): if not self.tipwindow: diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py index f32404c..3968e6a 100644 --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -11,10 +11,14 @@ from __future__ import with_statement # Testing imports from . import support from .support import driver, test_dir +from test.support import verbose # Python imports import os +import sys import unittest +import warnings +import subprocess # Local imports from lib2to3.pgen2 import tokenize @@ -171,10 +175,12 @@ class TestParserIdempotency(support.TestCase): try: tree = driver.parse_string(source) except ParseError as err: - print('ParseError on file', filepath, err) + if verbose > 0: + warnings.warn('ParseError on file %s (%s)' % (filepath, err)) continue new = str(tree) - if diff(filepath, new): + x = diff(filepath, new) + if x: self.fail("Idempotency failed: %s" % filepath) def test_extended_unpacking(self): @@ -183,6 +189,7 @@ class TestParserIdempotency(support.TestCase): driver.parse_string("(z, *y, w) = m\n") driver.parse_string("for *z, m in d: pass\n") + class TestLiterals(GrammarTest): def validate(self, s): @@ -221,7 +228,7 @@ def diff(fn, result): with open('@', 'w') as f: f.write(str(result)) fn = fn.replace('"', '\\"') - return os.system('diff -u "%s" @' % fn) + return subprocess.call(['diff', '-u', fn, '@'], stdout=(subprocess.DEVNULL if verbose < 1 else None)) finally: try: os.remove("@") diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 3faad4f..4191b22 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,9 +16,9 @@ """ Logging package for Python. Based on PEP 282 and comments thereto in -comp.lang.python, and influenced by Apache's log4j system. +comp.lang.python. -Copyright (C) 2001-2011 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved. To use, simply 'import logging' and log away! """ @@ -917,8 +917,12 @@ class StreamHandler(Handler): """ Flushes the stream. """ - if self.stream and hasattr(self.stream, "flush"): - self.stream.flush() + self.acquire() + try: + if self.stream and hasattr(self.stream, "flush"): + self.stream.flush() + finally: + self.release() def emit(self, record): """ @@ -969,12 +973,16 @@ class FileHandler(StreamHandler): """ Closes the stream. """ - if self.stream: - self.flush() - if hasattr(self.stream, "close"): - self.stream.close() - StreamHandler.close(self) - self.stream = None + self.acquire() + try: + if self.stream: + self.flush() + if hasattr(self.stream, "close"): + self.stream.close() + StreamHandler.close(self) + self.stream = None + finally: + self.release() def _open(self): """ diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 4a6b959..73ce031 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1,4 +1,4 @@ -# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,10 +16,9 @@ """ Additional handlers for the logging package for Python. The core package is -based on PEP 282 and comments thereto in comp.lang.python, and influenced by -Apache's log4j system. +based on PEP 282 and comments thereto in comp.lang.python. -Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved. To use, simply 'import logging.handlers' and log away! """ @@ -271,9 +270,10 @@ class TimedRotatingFileHandler(BaseRotatingHandler): dstAtRollover = time.localtime(newRolloverAt)[-1] if dstNow != dstAtRollover: if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour - newRolloverAt = newRolloverAt - 3600 + addend = -3600 else: # DST bows out before next rollover, so we need to add an hour - newRolloverAt = newRolloverAt + 3600 + addend = 3600 + newRolloverAt += addend result = newRolloverAt return result @@ -324,11 +324,20 @@ class TimedRotatingFileHandler(BaseRotatingHandler): self.stream.close() self.stream = None # get the time that this sequence started at and make it a TimeTuple + currentTime = int(time.time()) + dstNow = time.localtime(currentTime)[-1] t = self.rolloverAt - self.interval if self.utc: timeTuple = time.gmtime(t) else: timeTuple = time.localtime(t) + dstThen = timeTuple[-1] + if dstNow != dstThen: + if dstNow: + addend = 3600 + else: + addend = -3600 + timeTuple = time.localtime(t + addend) dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple) if os.path.exists(dfn): os.remove(dfn) @@ -338,19 +347,18 @@ class TimedRotatingFileHandler(BaseRotatingHandler): os.remove(s) self.mode = 'w' self.stream = self._open() - currentTime = int(time.time()) newRolloverAt = self.computeRollover(currentTime) while newRolloverAt <= currentTime: newRolloverAt = newRolloverAt + self.interval #If DST changes and midnight or weekly rollover, adjust for this. if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc: - dstNow = time.localtime(currentTime)[-1] dstAtRollover = time.localtime(newRolloverAt)[-1] if dstNow != dstAtRollover: if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour - newRolloverAt = newRolloverAt - 3600 + addend = -3600 else: # DST bows out before next rollover, so we need to add an hour - newRolloverAt = newRolloverAt + 3600 + addend = 3600 + newRolloverAt += addend self.rolloverAt = newRolloverAt class WatchedFileHandler(logging.FileHandler): @@ -554,10 +562,14 @@ class SocketHandler(logging.Handler): """ Closes the socket. """ - if self.sock: - self.sock.close() - self.sock = None - logging.Handler.close(self) + self.acquire() + try: + if self.sock: + self.sock.close() + self.sock = None + logging.Handler.close(self) + finally: + self.release() class DatagramHandler(SocketHandler): """ @@ -752,9 +764,13 @@ class SysLogHandler(logging.Handler): """ Closes the socket. """ - if self.unixsocket: - self.socket.close() - logging.Handler.close(self) + self.acquire() + try: + if self.unixsocket: + self.socket.close() + logging.Handler.close(self) + finally: + self.release() def mapPriority(self, levelName): """ @@ -1095,7 +1111,11 @@ class BufferingHandler(logging.Handler): This version just zaps the buffer to empty. """ - self.buffer = [] + self.acquire() + try: + self.buffer = [] + finally: + self.release() def close(self): """ @@ -1145,18 +1165,26 @@ class MemoryHandler(BufferingHandler): The record buffer is also cleared by this operation. """ - if self.target: - for record in self.buffer: - self.target.handle(record) - self.buffer = [] + self.acquire() + try: + if self.target: + for record in self.buffer: + self.target.handle(record) + self.buffer = [] + finally: + self.release() def close(self): """ Flush, set the target to None and lose the buffer. """ self.flush() - self.target = None - BufferingHandler.close(self) + self.acquire() + try: + self.target = None + BufferingHandler.close(self) + finally: + self.release() class QueueHandler(logging.Handler): @@ -179,14 +179,19 @@ def subn(pattern, repl, string, count=0, flags=0): def split(pattern, string, maxsplit=0, flags=0): """Split the source string by the occurrences of the pattern, - returning a list containing the resulting substrings.""" + returning a list containing the resulting substrings. If + capturing parentheses are used in pattern, then the text of all + groups in the pattern are also returned as part of the resulting + list. If maxsplit is nonzero, at most maxsplit splits occur, + and the remainder of the string is returned as the final element + of the list.""" return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. - If one or more groups are present in the pattern, return a - list of groups; this will be a list of tuples if the pattern + If one or more capturing groups are present in the pattern, return + a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result.""" diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 017f58d..179f41a 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1075,7 +1075,17 @@ class Popen(object): def terminate(self): """Terminates the process """ - _subprocess.TerminateProcess(self._handle, 1) + try: + _subprocess.TerminateProcess(self._handle, 1) + except OSError as e: + # ERROR_ACCESS_DENIED (winerror 5) is received when the + # process already died. + if e.winerror != 5: + raise + rc = _subprocess.GetExitCodeProcess(self._handle) + if rc == _subprocess.STILL_ACTIVE: + raise + self.returncode = rc kill = terminate diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 135a90e..714a116 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -677,10 +677,10 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, if bad: print(count(len(bad), "test"), "failed:") printlist(bad) - if environment_changed: - print("{} altered the execution environment:".format( - count(len(environment_changed), "test"))) - printlist(environment_changed) + if environment_changed: + print("{} altered the execution environment:".format( + count(len(environment_changed), "test"))) + printlist(environment_changed) if skipped and not quiet: print(count(len(skipped), "test"), "skipped:") printlist(skipped) @@ -890,7 +890,9 @@ class saved_test_environment: 'logging._handlers', 'logging._handlerList', 'shutil.archive_formats', 'shutil.unpack_formats', 'sys.warnoptions', 'threading._dangling', - 'multiprocessing.process._dangling') + 'multiprocessing.process._dangling', + 'support.TESTFN', + ) def get_sys_argv(self): return id(sys.argv), sys.argv, sys.argv[:] @@ -1020,6 +1022,21 @@ class saved_test_environment: multiprocessing.process._dangling.clear() multiprocessing.process._dangling.update(saved) + def get_support_TESTFN(self): + if os.path.isfile(support.TESTFN): + result = 'f' + elif os.path.isdir(support.TESTFN): + result = 'd' + else: + result = None + return result + def restore_support_TESTFN(self, saved_value): + if saved_value is None: + if os.path.isfile(support.TESTFN): + os.unlink(support.TESTFN) + elif os.path.isdir(support.TESTFN): + shutil.rmtree(support.TESTFN) + def resource_info(self): for name in self.resources: method_suffix = name.replace('.', '_') diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index 236f9b6..ee4ad6b 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -1,7 +1,8 @@ -from test.support import findfile, run_unittest, TESTFN +from test.support import findfile, run_unittest, TESTFN, captured_stdout, unlink import unittest import os import io +import struct import aifc @@ -20,10 +21,8 @@ class AIFCTest(unittest.TestCase): self.fout.close() except (aifc.Error, AttributeError): pass - try: - os.remove(TESTFN) - except OSError: - pass + unlink(TESTFN) + unlink(TESTFN + '.aiff') def test_skipunknown(self): #Issue 2245 @@ -32,6 +31,7 @@ class AIFCTest(unittest.TestCase): def test_params(self): f = self.f = aifc.open(self.sndfilepath) + self.assertEqual(f.getfp().name, self.sndfilepath) self.assertEqual(f.getnchannels(), 2) self.assertEqual(f.getsampwidth(), 2) self.assertEqual(f.getframerate(), 48000) @@ -45,6 +45,7 @@ class AIFCTest(unittest.TestCase): def test_read(self): f = self.f = aifc.open(self.sndfilepath) + self.assertEqual(f.readframes(0), b'') self.assertEqual(f.tell(), 0) self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4') f.rewind() @@ -58,6 +59,10 @@ class AIFCTest(unittest.TestCase): self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad') f.setpos(pos0) self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4') + with self.assertRaises(aifc.Error): + f.setpos(-1) + with self.assertRaises(aifc.Error): + f.setpos(f.getnframes() + 1) def test_write(self): f = self.f = aifc.open(self.sndfilepath) @@ -92,8 +97,6 @@ class AIFCTest(unittest.TestCase): self.assertEqual(f.getparams()[0:3], fout.getparams()[0:3]) self.assertEqual(fout.getcomptype(), b'ULAW') self.assertEqual(fout.getcompname(), b'foo') - # XXX: this test fails, not sure if it should succeed or not - # self.assertEqual(f.readframes(5), fout.readframes(5)) def test_close(self): class Wrapfile(object): @@ -112,7 +115,7 @@ class AIFCTest(unittest.TestCase): def test_write_header_comptype_sampwidth(self): for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): - fout = self.fout = aifc.open(io.BytesIO(), 'wb') + fout = aifc.open(io.BytesIO(), 'wb') fout.setnchannels(1) fout.setframerate(1) fout.setcomptype(comptype, b'') @@ -121,7 +124,7 @@ class AIFCTest(unittest.TestCase): fout.initfp(None) def test_write_markers_values(self): - fout = self.fout = aifc.open(io.BytesIO(), 'wb') + fout = aifc.open(io.BytesIO(), 'wb') self.assertEqual(fout.getmarkers(), None) fout.setmark(1, 0, b'foo1') fout.setmark(1, 1, b'foo2') @@ -179,6 +182,148 @@ class AIFCLowLevelTest(unittest.TestCase): with self.assertRaises(ValueError): aifc._write_string(f, b'too long' * 255) + def test_wrong_open_mode(self): + with self.assertRaises(aifc.Error): + aifc.open(TESTFN, 'wrong_mode') + + def test_read_wrong_form(self): + b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0)) + b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG') + self.assertRaises(aifc.Error, aifc.open, b1) + self.assertRaises(aifc.Error, aifc.open, b2) + + def test_read_no_comm_chunk(self): + b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') + self.assertRaises(aifc.Error, aifc.open, b) + + def test_read_wrong_compression_type(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) + b += b'WRNG' + struct.pack('B', 0) + self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b)) + + def test_read_wrong_marks(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFF' + b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 + b += b'MARK' + struct.pack('>LhB', 3, 1, 1) + with captured_stdout() as s: + f = aifc.open(io.BytesIO(b)) + self.assertEqual( + s.getvalue(), + 'Warning: MARK chunk contains only 0 markers instead of 1\n') + self.assertEqual(f.getmarkers(), None) + + def test_read_comm_kludge_compname_even(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00' + b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 + with captured_stdout() as s: + f = aifc.open(io.BytesIO(b)) + self.assertEqual(s.getvalue(), 'Warning: bad COMM chunk size\n') + self.assertEqual(f.getcompname(), b'even') + + def test_read_comm_kludge_compname_odd(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 3) + b'odd' + b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 + with captured_stdout() as s: + f = aifc.open(io.BytesIO(b)) + self.assertEqual(s.getvalue(), 'Warning: bad COMM chunk size\n') + self.assertEqual(f.getcompname(), b'odd') + + def test_write_params_raises(self): + fout = aifc.open(io.BytesIO(), 'wb') + wrong_params = (0, 0, 0, 0, b'WRNG', '') + self.assertRaises(aifc.Error, fout.setparams, wrong_params) + self.assertRaises(aifc.Error, fout.getparams) + self.assertRaises(aifc.Error, fout.setnchannels, 0) + self.assertRaises(aifc.Error, fout.getnchannels) + self.assertRaises(aifc.Error, fout.setsampwidth, 0) + self.assertRaises(aifc.Error, fout.getsampwidth) + self.assertRaises(aifc.Error, fout.setframerate, 0) + self.assertRaises(aifc.Error, fout.getframerate) + self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '') + fout.aiff() + fout.setnchannels(1) + fout.setsampwidth(1) + fout.setframerate(1) + fout.setnframes(1) + fout.writeframes(b'\x00') + self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1)) + self.assertRaises(aifc.Error, fout.setnchannels, 1) + self.assertRaises(aifc.Error, fout.setsampwidth, 1) + self.assertRaises(aifc.Error, fout.setframerate, 1) + self.assertRaises(aifc.Error, fout.setnframes, 1) + self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '') + self.assertRaises(aifc.Error, fout.aiff) + self.assertRaises(aifc.Error, fout.aifc) + + def test_write_params_singles(self): + fout = aifc.open(io.BytesIO(), 'wb') + fout.aifc() + fout.setnchannels(1) + fout.setsampwidth(2) + fout.setframerate(3) + fout.setnframes(4) + fout.setcomptype(b'NONE', b'name') + self.assertEqual(fout.getnchannels(), 1) + self.assertEqual(fout.getsampwidth(), 2) + self.assertEqual(fout.getframerate(), 3) + self.assertEqual(fout.getnframes(), 0) + self.assertEqual(fout.tell(), 0) + self.assertEqual(fout.getcomptype(), b'NONE') + self.assertEqual(fout.getcompname(), b'name') + fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels()) + self.assertEqual(fout.getnframes(), 4) + self.assertEqual(fout.tell(), 4) + + def test_write_params_bunch(self): + fout = aifc.open(io.BytesIO(), 'wb') + fout.aifc() + p = (1, 2, 3, 4, b'NONE', b'name') + fout.setparams(p) + self.assertEqual(fout.getparams(), p) + fout.initfp(None) + + def test_write_header_raises(self): + fout = aifc.open(io.BytesIO(), 'wb') + self.assertRaises(aifc.Error, fout.close) + fout.setnchannels(1) + self.assertRaises(aifc.Error, fout.close) + fout.setsampwidth(1) + self.assertRaises(aifc.Error, fout.close) + fout.initfp(None) + + def test_write_header_comptype_raises(self): + for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): + fout = aifc.open(io.BytesIO(), 'wb') + fout.setsampwidth(1) + fout.setcomptype(comptype, b'') + self.assertRaises(aifc.Error, fout.close) + fout.initfp(None) + + def test_write_markers_raises(self): + fout = aifc.open(io.BytesIO(), 'wb') + self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'') + self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'') + self.assertRaises(aifc.Error, fout.setmark, 1, 0, None) + self.assertRaises(aifc.Error, fout.getmark, 1) + fout.initfp(None) + + def test_write_aiff_by_extension(self): + sampwidth = 2 + fout = self.fout = aifc.open(TESTFN + '.aiff', 'wb') + 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') + self.assertEqual(f.getcomptype(), b'NONE') + f.close() + def test_main(): run_unittest(AIFCTest) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index be9f05e..f4ce615 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -195,12 +195,6 @@ class AST_Tests(unittest.TestCase): with self.assertRaises(AttributeError): x.vararg - with self.assertRaises(AttributeError): - x.foobar = 21 - - with self.assertRaises(AttributeError): - ast.AST(lineno=2) - with self.assertRaises(TypeError): # "_ast.AST constructor takes 0 positional arguments" ast.AST(2) diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 93c623c..ca94504 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -2,6 +2,7 @@ import unittest from test import support import base64 import binascii +import os import sys import subprocess @@ -227,6 +228,10 @@ class BaseXYTestCase(unittest.TestCase): class TestMain(unittest.TestCase): + def tearDown(self): + if os.path.exists(support.TESTFN): + os.unlink(support.TESTFN) + def get_output(self, *args, **options): args = (sys.executable, '-m', 'base64') + args return subprocess.check_output(args, **options) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py index 9951e93..3031fb3 100644 --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -118,6 +118,11 @@ def gen_result(data, environ): class CgiTests(unittest.TestCase): + def test_escape(self): + self.assertEqual("test & string", cgi.escape("test & string")) + self.assertEqual("<test string>", cgi.escape("<test string>")) + self.assertEqual(""test string"", cgi.escape('"test string"', True)) + def test_strict(self): for orig, expect in parse_strict_test_cases: # Test basic parsing diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 92304b4..141d791 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1,8 +1,10 @@ import builtins +import gc import sys import types import math import unittest +import weakref from copy import deepcopy from test import support @@ -1186,7 +1188,6 @@ order (MRO) for bases """ self.assertEqual(Counted.counter, 0) # Test lookup leaks [SF bug 572567] - import gc if hasattr(gc, 'get_objects'): class G(object): def __eq__(self, other): @@ -4380,7 +4381,6 @@ order (MRO) for bases """ self.assertRaises(AttributeError, getattr, C(), "attr") self.assertEqual(descr.counter, 4) - import gc class EvilGetattribute(object): # This used to segfault def __getattr__(self, name): @@ -4393,6 +4393,9 @@ order (MRO) for bases """ self.assertRaises(AttributeError, getattr, EvilGetattribute(), "attr") + def test_type___getattribute__(self): + self.assertRaises(TypeError, type.__getattribute__, list, type) + def test_abstractmethods(self): # type pretends not to have __abstractmethods__. self.assertRaises(AttributeError, getattr, type, "__abstractmethods__") @@ -4429,6 +4432,21 @@ order (MRO) for bases """ foo = Foo() str(foo) + def test_cycle_through_dict(self): + # See bug #1469629 + class X(dict): + def __init__(self): + dict.__init__(self) + self.__dict__ = self + x = X() + x.attr = 42 + wr = weakref.ref(x) + del x + support.gc_collect() + self.assertIsNone(wr()) + for o in gc.get_objects(): + self.assertIsNot(type(o), X) + class DictProxyTests(unittest.TestCase): def setUp(self): class C(object): diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 1507e42..d2740a3 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -299,6 +299,26 @@ class DictTest(unittest.TestCase): x.fail = True self.assertRaises(Exc, d.setdefault, x, []) + def test_setdefault_atomic(self): + # Issue #13521: setdefault() calls __hash__ and __eq__ only once. + class Hashed(object): + def __init__(self): + self.hash_count = 0 + self.eq_count = 0 + def __hash__(self): + self.hash_count += 1 + return 42 + def __eq__(self, other): + self.eq_count += 1 + return id(self) == id(other) + hashed1 = Hashed() + y = {hashed1: 5} + hashed2 = Hashed() + y.setdefault(hashed2, []) + self.assertEqual(hashed1.hash_count, 1) + self.assertEqual(hashed2.hash_count, 1) + self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1) + def test_popitem(self): # dict.popitem() for copymode in -1, +1: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 0a7ddd4..7a2dd0c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -38,7 +38,7 @@ class ExceptionTests(unittest.TestCase): try: try: import marshal - marshal.loads('') + marshal.loads(b'') except EOFError: pass finally: diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 26e132f..084ae0c 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -6,6 +6,7 @@ import math import numbers import operator import fractions +import sys import unittest from copy import copy, deepcopy from pickle import dumps, loads @@ -76,6 +77,9 @@ class DummyRational(object): def __float__(self): assert False, "__float__ should not be invoked" +class DummyFraction(fractions.Fraction): + """Dummy Fraction subclass for copy and deepcopy testing.""" + class GcdTest(unittest.TestCase): def testMisc(self): @@ -286,9 +290,14 @@ class FractionTest(unittest.TestCase): self.assertEqual(F(201, 200).limit_denominator(100), F(1)) self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101)) self.assertEqual(F(0).limit_denominator(10000), F(0)) + for i in (0, -1): + self.assertRaisesMessage( + ValueError, "max_denominator should be at least 1", + F(1).limit_denominator, i) def testConversions(self): self.assertTypedEquals(-1, math.trunc(F(-11, 10))) + self.assertTypedEquals(1, math.trunc(F(11, 10))) self.assertTypedEquals(-2, math.floor(F(-11, 10))) self.assertTypedEquals(-1, math.ceil(F(-11, 10))) self.assertTypedEquals(-1, math.ceil(F(-10, 10))) @@ -329,6 +338,7 @@ class FractionTest(unittest.TestCase): self.assertEqual(F(8, 27), F(2, 3) ** F(3)) self.assertEqual(F(27, 8), F(2, 3) ** F(-3)) self.assertTypedEquals(2.0, F(4) ** F(1, 2)) + self.assertEqual(F(1, 1), +F(1, 1)) z = pow(F(-1), F(1, 2)) self.assertAlmostEqual(z.real, 0) self.assertEqual(z.imag, 1) @@ -395,6 +405,10 @@ class FractionTest(unittest.TestCase): TypeError, "unsupported operand type(s) for +: 'Fraction' and 'Decimal'", operator.add, F(3,11), Decimal('3.1415926')) + self.assertRaisesMessage( + TypeError, + "unsupported operand type(s) for +: 'Decimal' and 'Fraction'", + operator.add, Decimal('3.1415926'), F(3,11)) def testComparisons(self): self.assertTrue(F(1, 2) < F(2, 3)) @@ -538,9 +552,12 @@ class FractionTest(unittest.TestCase): self.assertEqual("7", str(F(7, 1))) def testHash(self): + hmod = sys.hash_info.modulus + hinf = sys.hash_info.inf self.assertEqual(hash(2.5), hash(F(5, 2))) self.assertEqual(hash(10**50), hash(F(10**50))) self.assertNotEqual(hash(float(10**23)), hash(F(10**23))) + self.assertEqual(hinf, hash(F(1, hmod))) # Check that __hash__ produces the same value as hash(), for # consistency with int and Decimal. (See issue #10356.) self.assertEqual(hash(F(-1)), F(-1).__hash__()) @@ -574,9 +591,14 @@ class FractionTest(unittest.TestCase): def test_copy_deepcopy_pickle(self): r = F(13, 7) + dr = DummyFraction(13, 7) self.assertEqual(r, loads(dumps(r))) self.assertEqual(id(r), id(copy(r))) self.assertEqual(id(r), id(deepcopy(r))) + self.assertNotEqual(id(dr), id(copy(dr))) + self.assertNotEqual(id(dr), id(deepcopy(dr))) + self.assertTypedEquals(dr, copy(dr)) + self.assertTypedEquals(dr, deepcopy(dr)) def test_slots(self): # Issue 4998 diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index e83c048..4d58e4b 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -377,6 +377,7 @@ class CGIHTTPServerTestCase(BaseTestCase): '/.//': ('/', ''), 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), + '/cgi-bin/file1.py/PATH-INFO': ('/cgi-bin', 'file1.py/PATH-INFO'), 'a': ('/', 'a'), '/a': ('/', 'a'), '//a': ('/', 'a'), diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index ef64366..8f76e18 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -7,6 +7,7 @@ import email import email.message import re import io +import shutil import tempfile from test import support import unittest @@ -38,12 +39,7 @@ class TestBase(unittest.TestCase): def _delete_recursively(self, target): # Delete a file or delete a directory recursively if os.path.isdir(target): - for path, dirs, files in os.walk(target, topdown=False): - for name in files: - os.remove(os.path.join(path, name)) - for name in dirs: - os.rmdir(os.path.join(path, name)) - os.rmdir(target) + shutil.rmtree(target) elif os.path.exists(target): os.remove(target) @@ -115,10 +111,10 @@ class TestMailbox(TestBase): self.assertMailboxEmpty() def test_add_that_raises_leaves_mailbox_empty(self): - # XXX This test will start failing when Message learns to handle - # non-ASCII string headers, and a different internal failure will - # need to be found or manufactured. - with self.assertRaises(ValueError): + def raiser(*args, **kw): + raise Exception("a fake error") + support.patch(self, email.generator.BytesGenerator, 'flatten', raiser) + with self.assertRaises(Exception): self._box.add(email.message_from_string("From: Alphöso")) self.assertEqual(len(self._box), 0) self._box.close() @@ -2029,6 +2025,10 @@ class MaildirTestCase(unittest.TestCase): def setUp(self): # create a new maildir mailbox to work with: self._dir = support.TESTFN + if os.path.isdir(self._dir): + shutil.rmtree(self._dir) + elif os.path.isfile(self._dir): + os.unlink(self._dir) os.mkdir(self._dir) os.mkdir(os.path.join(self._dir, "cur")) os.mkdir(os.path.join(self._dir, "tmp")) diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index cd100f9..96a70ec 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from test import support +import array import marshal import sys import unittest @@ -137,6 +138,27 @@ class ContainerTestCase(unittest.TestCase, HelperMixin): for constructor in (set, frozenset): self.helper(constructor(self.d.keys())) + +class BufferTestCase(unittest.TestCase, HelperMixin): + + def test_bytearray(self): + b = bytearray(b"abc") + self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + def test_memoryview(self): + b = memoryview(b"abc") + self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + def test_array(self): + a = array.array('B', b"abc") + new = marshal.loads(marshal.dumps(a)) + self.assertEqual(new, b"abc") + + class BugsTestCase(unittest.TestCase): def test_bug_5888452(self): # Simple-minded check for SF 588452: Debug build crashes @@ -162,7 +184,7 @@ class BugsTestCase(unittest.TestCase): pass def test_loads_recursion(self): - s = 'c' + ('X' * 4*4) + '{' * 2**20 + s = b'c' + (b'X' * 4*4) + b'{' * 2**20 self.assertRaises(ValueError, marshal.loads, s) def test_recursion_limit(self): @@ -235,6 +257,11 @@ class BugsTestCase(unittest.TestCase): finally: support.unlink(support.TESTFN) + def test_loads_reject_unicode_strings(self): + # Issue #14177: marshal.loads() should not accept unicode strings + unicode_string = 'T' + self.assertRaises(TypeError, marshal.loads, unicode_string) + def test_main(): support.run_unittest(IntTestCase, @@ -243,6 +270,7 @@ def test_main(): CodeTestCase, ContainerTestCase, ExceptionTestCase, + BufferTestCase, BugsTestCase) if __name__ == "__main__": diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index f3fa1b8..4a69b00 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -350,13 +350,31 @@ class MinidomTest(unittest.TestCase): def testGetAttrList(self): pass - def testGetAttrValues(self): pass + def testGetAttrValues(self): + pass - def testGetAttrLength(self): pass + def testGetAttrLength(self): + pass - def testGetAttribute(self): pass + def testGetAttribute(self): + dom = Document() + child = dom.appendChild( + dom.createElementNS("http://www.python.org", "python:abc")) + self.assertEqual(child.getAttribute('missing'), '') - def testGetAttributeNS(self): pass + def testGetAttributeNS(self): + dom = Document() + child = dom.appendChild( + dom.createElementNS("http://www.python.org", "python:abc")) + child.setAttributeNS("http://www.w3.org", "xmlns:python", + "http://www.python.org") + self.assertEqual(child.getAttributeNS("http://www.w3.org", "python"), + 'http://www.python.org') + self.assertEqual(child.getAttributeNS("http://www.w3.org", "other"), + '') + child2 = child.appendChild(dom.createElement('abc')) + self.assertEqual(child2.getAttributeNS("http://www.python.org", "missing"), + '') def testGetAttributeNode(self): pass diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py index 8287a5d..86ad9c0 100644 --- a/Lib/test/test_queue.py +++ b/Lib/test/test_queue.py @@ -82,7 +82,7 @@ class BlockingTestMixin: self.fail("trigger thread ended but event never set") -class BaseQueueTest(unittest.TestCase, BlockingTestMixin): +class BaseQueueTestMixin(BlockingTestMixin): def setUp(self): self.cum = 0 self.cumlock = threading.Lock() @@ -229,13 +229,13 @@ class BaseQueueTest(unittest.TestCase, BlockingTestMixin): with self.assertRaises(queue.Full): q.put_nowait(4) -class QueueTest(BaseQueueTest): +class QueueTest(BaseQueueTestMixin, unittest.TestCase): type2test = queue.Queue -class LifoQueueTest(BaseQueueTest): +class LifoQueueTest(BaseQueueTestMixin, unittest.TestCase): type2test = queue.LifoQueue -class PriorityQueueTest(BaseQueueTest): +class PriorityQueueTest(BaseQueueTestMixin, unittest.TestCase): type2test = queue.PriorityQueue diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index fe8bc34..940ba39 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,4 +1,5 @@ -from test.support import verbose, run_unittest +from test.support import verbose, run_unittest, gc_collect +import io import re from re import Scanner import sys @@ -16,6 +17,17 @@ import unittest class ReTests(unittest.TestCase): + def test_keep_buffer(self): + # See bug 14212 + b = bytearray(b'x') + it = re.finditer(b'a', b) + with self.assertRaises(BufferError): + b.extend(b'x'*400) + list(it) + del it + gc_collect() + b.extend(b'x'*400) + def test_weakref(self): s = 'QabbbcR' x = re.compile('ab+c') @@ -355,6 +367,32 @@ class ReTests(unittest.TestCase): self.assertEqual(re.search(r"\d\D\w\W\s\S", "1aa! a", re.UNICODE).group(0), "1aa! a") + def test_string_boundaries(self): + # See http://bugs.python.org/issue10713 + self.assertEqual(re.search(r"\b(abc)\b", "abc").group(1), + "abc") + # There's a word boundary at the start of a string. + self.assertTrue(re.match(r"\b", "abc")) + # A non-empty string includes a non-boundary zero-length match. + self.assertTrue(re.search(r"\B", "abc")) + # There is no non-boundary match at the start of a string. + self.assertFalse(re.match(r"\B", "abc")) + # However, an empty string contains no word boundaries, and also no + # non-boundaries. + self.assertEqual(re.search(r"\B", ""), None) + # This one is questionable and different from the perlre behaviour, + # but describes current behavior. + self.assertEqual(re.search(r"\b", ""), None) + # A single word-character string has two boundaries, but no + # non-boundary gaps. + self.assertEqual(len(re.findall(r"\b", "a")), 2) + self.assertEqual(len(re.findall(r"\B", "a")), 0) + # If there are no words, there are no boundaries + self.assertEqual(len(re.findall(r"\b", " ")), 0) + self.assertEqual(len(re.findall(r"\b", " ")), 0) + # Can match around the whitespace. + self.assertEqual(len(re.findall(r"\B", " ")), 2) + def test_bigcharset(self): self.assertEqual(re.match("([\u2222\u2223])", "\u2222").group(1), "\u2222") @@ -780,6 +818,16 @@ class ReTests(unittest.TestCase): self.assertRaises(OverflowError, _sre.compile, "abc", 0, [long_overflow]) self.assertRaises(TypeError, _sre.compile, {}, 0, []) + def test_compile(self): + # Test return value when given string and pattern as parameter + pattern = re.compile('random pattern') + self.assertIsInstance(pattern, re._pattern_type) + same_pattern = re.compile(pattern) + self.assertIsInstance(same_pattern, re._pattern_type) + self.assertIs(same_pattern, pattern) + # Test behaviour when not given a string or pattern as parameter + self.assertRaises(TypeError, re.compile, 0) + def run_re_tests(): from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 89c08ed..98d759b 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -38,9 +38,9 @@ class LocaleTime_Tests(unittest.TestCase): comparison = testing[self.time_tuple[tuple_position]] self.assertIn(strftime_output, testing, "%s: not found in tuple" % error_msg) - self.assertTrue(comparison == strftime_output, - "%s: position within tuple incorrect; %s != %s" % - (error_msg, comparison, strftime_output)) + self.assertEqual(comparison, strftime_output, + "%s: position within tuple incorrect; %s != %s" % + (error_msg, comparison, strftime_output)) def test_weekday(self): # Make sure that full and abbreviated weekday names are correct in @@ -65,8 +65,8 @@ class LocaleTime_Tests(unittest.TestCase): "AM/PM representation not in tuple") if self.time_tuple[3] < 12: position = 0 else: position = 1 - self.assertTrue(strftime_output == self.LT_ins.am_pm[position], - "AM/PM representation in the wrong position within the tuple") + self.assertEqual(self.LT_ins.am_pm[position], strftime_output, + "AM/PM representation in the wrong position within the tuple") def test_timezone(self): # Make sure timezone is correct @@ -86,17 +86,14 @@ class LocaleTime_Tests(unittest.TestCase): # output. magic_date = (1999, 3, 17, 22, 44, 55, 2, 76, 0) strftime_output = time.strftime("%c", magic_date) - self.assertTrue(strftime_output == time.strftime(self.LT_ins.LC_date_time, - magic_date), - "LC_date_time incorrect") + self.assertEqual(time.strftime(self.LT_ins.LC_date_time, magic_date), + strftime_output, "LC_date_time incorrect") strftime_output = time.strftime("%x", magic_date) - self.assertTrue(strftime_output == time.strftime(self.LT_ins.LC_date, - magic_date), - "LC_date incorrect") + self.assertEqual(time.strftime(self.LT_ins.LC_date, magic_date), + strftime_output, "LC_date incorrect") strftime_output = time.strftime("%X", magic_date) - self.assertTrue(strftime_output == time.strftime(self.LT_ins.LC_time, - magic_date), - "LC_time incorrect") + self.assertEqual(time.strftime(self.LT_ins.LC_time, magic_date), + strftime_output, "LC_time incorrect") LT = _strptime.LocaleTime() LT.am_pm = ('', '') self.assertTrue(LT.LC_time, "LocaleTime's LC directives cannot handle " @@ -168,8 +165,8 @@ class TimeRETests(unittest.TestCase): # Fixes bug #661354 test_locale = _strptime.LocaleTime() test_locale.timezone = (frozenset(), frozenset()) - self.assertTrue(_strptime.TimeRE(test_locale).pattern("%Z") == '', - "with timezone == ('',''), TimeRE().pattern('%Z') != ''") + self.assertEqual(_strptime.TimeRE(test_locale).pattern("%Z"), '', + "with timezone == ('',''), TimeRE().pattern('%Z') != ''") def test_matching_with_escapes(self): # Make sure a format that requires escaping of characters works @@ -195,7 +192,7 @@ class TimeRETests(unittest.TestCase): # so as to not allow to subpatterns to end up next to each other and # "steal" characters from each other. pattern = self.time_re.pattern('%j %H') - self.assertTrue(not re.match(pattern, "180")) + self.assertFalse(re.match(pattern, "180")) self.assertTrue(re.match(pattern, "18 0")) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index fb0b834..6150e88 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -989,6 +989,27 @@ class POSIXProcessTestCase(BaseTestCase): getattr(p, method)(*args) return p + def _kill_dead_process(self, method, *args): + # Do not inherit file handles from the parent. + # It should fix failures on some platforms. + p = subprocess.Popen([sys.executable, "-c", """if 1: + import sys, time + sys.stdout.write('x\\n') + sys.stdout.flush() + """], + close_fds=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + # Wait for the interpreter to be completely initialized before + # sending any signal. + p.stdout.read(1) + # The process should end after this + time.sleep(1) + # This shouldn't raise even though the child is now dead + getattr(p, method)(*args) + p.communicate() + def test_send_signal(self): p = self._kill_process('send_signal', signal.SIGINT) _, stderr = p.communicate() @@ -1007,6 +1028,18 @@ class POSIXProcessTestCase(BaseTestCase): self.assertStderrEqual(stderr, b'') self.assertEqual(p.wait(), -signal.SIGTERM) + def test_send_signal_dead(self): + # Sending a signal to a dead process + self._kill_dead_process('send_signal', signal.SIGINT) + + def test_kill_dead(self): + # Killing a dead process + self._kill_dead_process('kill') + + def test_terminate_dead(self): + # Terminating a dead process + self._kill_dead_process('terminate') + def check_close_std_fds(self, fds): # Issue #9905: test that subprocess pipes still work properly with # some standard fds closed @@ -1568,6 +1601,31 @@ class Win32ProcessTestCase(BaseTestCase): returncode = p.wait() self.assertNotEqual(returncode, 0) + def _kill_dead_process(self, method, *args): + p = subprocess.Popen([sys.executable, "-c", """if 1: + import sys, time + sys.stdout.write('x\\n') + sys.stdout.flush() + sys.exit(42) + """], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + self.addCleanup(p.stdout.close) + self.addCleanup(p.stderr.close) + self.addCleanup(p.stdin.close) + # Wait for the interpreter to be completely initialized before + # sending any signal. + p.stdout.read(1) + # The process should end after this + time.sleep(1) + # This shouldn't raise even though the child is now dead + getattr(p, method)(*args) + _, stderr = p.communicate() + self.assertStderrEqual(stderr, b'') + rc = p.wait() + self.assertEqual(rc, 42) + def test_send_signal(self): self._kill_process('send_signal', signal.SIGTERM) @@ -1577,6 +1635,15 @@ class Win32ProcessTestCase(BaseTestCase): def test_terminate(self): self._kill_process('terminate') + def test_send_signal_dead(self): + self._kill_dead_process('send_signal', signal.SIGTERM) + + def test_kill_dead(self): + self._kill_dead_process('kill') + + def test_terminate_dead(self): + self._kill_dead_process('terminate') + # The module says: # "NB This only works (and is only relevant) for UNIX." diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py new file mode 100644 index 0000000..1682124 --- /dev/null +++ b/Lib/test/test_tools.py @@ -0,0 +1,39 @@ +"""Tests for scripts in the Tools directory. + +This file contains regression tests for some of the scripts found in the +Tools directory of a Python checkout or tarball, such as reindent.py. +""" + +import os +import unittest +import sysconfig +from test import support +from test.script_helper import assert_python_ok + +if not sysconfig.is_python_build(): + # XXX some installers do contain the tools, should we detect that + # and run the tests in that case too? + raise unittest.SkipTest('test irrelevant for an installed Python') + +srcdir = sysconfig.get_config_var('projectbase') +basepath = os.path.join(os.getcwd(), srcdir, 'Tools') + + +class ReindentTests(unittest.TestCase): + script = os.path.join(basepath, 'scripts', 'reindent.py') + + def test_noargs(self): + assert_python_ok(self.script) + + def test_help(self): + rc, out, err = assert_python_ok(self.script, '-h') + self.assertEqual(out, b'') + self.assertGreater(err, b'') + + +def test_main(): + support.run_unittest(ReindentTests) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 259a181..19b06a0 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -891,12 +891,15 @@ class UnicodeTest(string_tests.CommonTest, self.assertEqual('{foo._x}'.format_map({'foo': C(20)}), '20') # test various errors - self.assertRaises(TypeError, '{'.format_map) - self.assertRaises(TypeError, '}'.format_map) - self.assertRaises(TypeError, 'a{'.format_map) - self.assertRaises(TypeError, 'a}'.format_map) - self.assertRaises(TypeError, '{a'.format_map) - self.assertRaises(TypeError, '}a'.format_map) + self.assertRaises(TypeError, ''.format_map) + self.assertRaises(TypeError, 'a'.format_map) + + self.assertRaises(ValueError, '{'.format_map, {}) + self.assertRaises(ValueError, '}'.format_map, {}) + self.assertRaises(ValueError, 'a{'.format_map, {}) + self.assertRaises(ValueError, 'a}'.format_map, {}) + self.assertRaises(ValueError, '{a'.format_map, {}) + self.assertRaises(ValueError, '}a'.format_map, {}) # issue #12579: can't supply positional params to format_map self.assertRaises(ValueError, '{}'.format_map, {'a' : 2}) diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 8b5bbc3..74b9a87 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -812,11 +812,71 @@ class Object: def __hash__(self): return hash(self.arg) +class RefCycle: + def __init__(self): + self.cycle = self + class MappingTestCase(TestBase): COUNT = 10 + def check_len_cycles(self, dict_type, cons): + N = 20 + items = [RefCycle() for i in range(N)] + dct = dict_type(cons(o) for o in items) + # Keep an iterator alive + it = dct.items() + try: + next(it) + except StopIteration: + pass + del items + gc.collect() + n1 = len(dct) + del it + gc.collect() + n2 = len(dct) + # one item may be kept alive inside the iterator + self.assertIn(n1, (0, 1)) + self.assertEqual(n2, 0) + + def test_weak_keyed_len_cycles(self): + self.check_len_cycles(weakref.WeakKeyDictionary, lambda k: (k, 1)) + + def test_weak_valued_len_cycles(self): + self.check_len_cycles(weakref.WeakValueDictionary, lambda k: (1, k)) + + def check_len_race(self, dict_type, cons): + # Extended sanity checks for len() in the face of cyclic collection + self.addCleanup(gc.set_threshold, *gc.get_threshold()) + for th in range(1, 100): + N = 20 + gc.collect(0) + gc.set_threshold(th, th, th) + items = [RefCycle() for i in range(N)] + dct = dict_type(cons(o) for o in items) + del items + # All items will be collected at next garbage collection pass + it = dct.items() + try: + next(it) + except StopIteration: + pass + n1 = len(dct) + del it + n2 = len(dct) + self.assertGreaterEqual(n1, 0) + self.assertLessEqual(n1, N) + self.assertGreaterEqual(n2, 0) + self.assertLessEqual(n2, n1) + + def test_weak_keyed_len_race(self): + self.check_len_race(weakref.WeakKeyDictionary, lambda k: (k, 1)) + + def test_weak_valued_len_race(self): + self.check_len_race(weakref.WeakValueDictionary, lambda k: (1, k)) + def test_weak_values(self): # # This exercises d.copy(), d.items(), d[], del d[], len(d). diff --git a/Lib/test/test_weakset.py b/Lib/test/test_weakset.py index 3cddf40..4d3878f 100644 --- a/Lib/test/test_weakset.py +++ b/Lib/test/test_weakset.py @@ -17,6 +17,10 @@ import contextlib class Foo: pass +class RefCycle: + def __init__(self): + self.cycle = self + class TestWeakSet(unittest.TestCase): @@ -24,6 +28,12 @@ class TestWeakSet(unittest.TestCase): # need to keep references to them self.items = [ustr(c) for c in ('a', 'b', 'c')] self.items2 = [ustr(c) for c in ('x', 'y', 'z')] + self.ab_items = [ustr(c) for c in 'ab'] + self.abcde_items = [ustr(c) for c in 'abcde'] + self.def_items = [ustr(c) for c in 'def'] + self.ab_weakset = WeakSet(self.ab_items) + self.abcde_weakset = WeakSet(self.abcde_items) + self.def_weakset = WeakSet(self.def_items) self.letters = [ustr(c) for c in string.ascii_letters] self.s = WeakSet(self.items) self.d = dict.fromkeys(self.items) @@ -67,6 +77,11 @@ class TestWeakSet(unittest.TestCase): x = WeakSet(self.items + self.items2) c = C(self.items2) self.assertEqual(self.s.union(c), x) + del c + self.assertEqual(len(u), len(self.items) + len(self.items2)) + self.items2.pop() + gc.collect() + self.assertEqual(len(u), len(self.items) + len(self.items2)) def test_or(self): i = self.s.union(self.items2) @@ -74,14 +89,19 @@ class TestWeakSet(unittest.TestCase): self.assertEqual(self.s | frozenset(self.items2), i) def test_intersection(self): - i = self.s.intersection(self.items2) + s = WeakSet(self.letters) + i = s.intersection(self.items2) for c in self.letters: - self.assertEqual(c in i, c in self.d and c in self.items2) - self.assertEqual(self.s, WeakSet(self.items)) + self.assertEqual(c in i, c in self.items2 and c in self.letters) + self.assertEqual(s, WeakSet(self.letters)) self.assertEqual(type(i), WeakSet) for C in set, frozenset, dict.fromkeys, list, tuple: x = WeakSet([]) - self.assertEqual(self.s.intersection(C(self.items2)), x) + self.assertEqual(i.intersection(C(self.items)), x) + self.assertEqual(len(i), len(self.items2)) + self.items2.pop() + gc.collect() + self.assertEqual(len(i), len(self.items2)) def test_isdisjoint(self): self.assertTrue(self.s.isdisjoint(WeakSet(self.items2))) @@ -112,6 +132,10 @@ class TestWeakSet(unittest.TestCase): self.assertEqual(self.s, WeakSet(self.items)) self.assertEqual(type(i), WeakSet) self.assertRaises(TypeError, self.s.symmetric_difference, [[]]) + self.assertEqual(len(i), len(self.items) + len(self.items2)) + self.items2.pop() + gc.collect() + self.assertEqual(len(i), len(self.items) + len(self.items2)) def test_xor(self): i = self.s.symmetric_difference(self.items2) @@ -119,22 +143,28 @@ class TestWeakSet(unittest.TestCase): self.assertEqual(self.s ^ frozenset(self.items2), i) def test_sub_and_super(self): - pl, ql, rl = map(lambda s: [ustr(c) for c in s], ['ab', 'abcde', 'def']) - p, q, r = map(WeakSet, (pl, ql, rl)) - self.assertTrue(p < q) - self.assertTrue(p <= q) - self.assertTrue(q <= q) - self.assertTrue(q > p) - self.assertTrue(q >= p) - self.assertFalse(q < r) - self.assertFalse(q <= r) - self.assertFalse(q > r) - self.assertFalse(q >= r) + self.assertTrue(self.ab_weakset <= self.abcde_weakset) + self.assertTrue(self.abcde_weakset <= self.abcde_weakset) + self.assertTrue(self.abcde_weakset >= self.ab_weakset) + self.assertFalse(self.abcde_weakset <= self.def_weakset) + self.assertFalse(self.abcde_weakset >= self.def_weakset) self.assertTrue(set('a').issubset('abc')) self.assertTrue(set('abc').issuperset('a')) self.assertFalse(set('a').issubset('cbs')) self.assertFalse(set('cbs').issuperset('a')) + def test_lt(self): + self.assertTrue(self.ab_weakset < self.abcde_weakset) + self.assertFalse(self.abcde_weakset < self.def_weakset) + self.assertFalse(self.ab_weakset < self.ab_weakset) + self.assertFalse(WeakSet() < WeakSet()) + + def test_gt(self): + self.assertTrue(self.abcde_weakset > self.ab_weakset) + self.assertFalse(self.abcde_weakset > self.def_weakset) + self.assertFalse(self.ab_weakset > self.ab_weakset) + self.assertFalse(WeakSet() > WeakSet()) + def test_gc(self): # Create a nest of cycles to exercise overall ref count check s = WeakSet(Foo() for i in range(1000)) @@ -359,6 +389,49 @@ class TestWeakSet(unittest.TestCase): s.clear() self.assertEqual(len(s), 0) + def test_len_cycles(self): + N = 20 + items = [RefCycle() for i in range(N)] + s = WeakSet(items) + del items + it = iter(s) + try: + next(it) + except StopIteration: + pass + gc.collect() + n1 = len(s) + del it + gc.collect() + n2 = len(s) + # one item may be kept alive inside the iterator + self.assertIn(n1, (0, 1)) + self.assertEqual(n2, 0) + + def test_len_race(self): + # Extended sanity checks for len() in the face of cyclic collection + self.addCleanup(gc.set_threshold, *gc.get_threshold()) + for th in range(1, 100): + N = 20 + gc.collect(0) + gc.set_threshold(th, th, th) + items = [RefCycle() for i in range(N)] + s = WeakSet(items) + del items + # All items will be collected at next garbage collection pass + it = iter(s) + try: + next(it) + except StopIteration: + pass + n1 = len(s) + del it + n2 = len(s) + self.assertGreaterEqual(n1, 0) + self.assertLessEqual(n1, N) + self.assertGreaterEqual(n2, 0) + self.assertLessEqual(n2, n1) + def test_main(verbose=None): support.run_unittest(TestWeakSet) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index dffa2ca..60081e2 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -66,24 +66,11 @@ class ChecksumTestCase(unittest.TestCase): # Issue #10276 - check that inputs >=4GB are handled correctly. class ChecksumBigBufferTestCase(unittest.TestCase): - def setUp(self): - with open(support.TESTFN, "wb+") as f: - f.seek(_4G) - f.write(b"asdf") - f.flush() - self.mapping = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) - - def tearDown(self): - self.mapping.close() - support.unlink(support.TESTFN) - - @unittest.skipUnless(mmap, "mmap() is not available.") - @unittest.skipUnless(sys.maxsize > _4G, "Can't run on a 32-bit system.") - @unittest.skipUnless(support.is_resource_enabled("largefile"), - "May use lots of disk space.") - def test_big_buffer(self): - self.assertEqual(zlib.crc32(self.mapping), 3058686908) - self.assertEqual(zlib.adler32(self.mapping), 82837919) + @bigmemtest(size=_4G + 4, memuse=1, dry_run=False) + def test_big_buffer(self, size): + data = b"nyan" * (_1G + 1) + self.assertEqual(zlib.crc32(data), 1044521549) + self.assertEqual(zlib.adler32(data), 2256789997) class ExceptionTestCase(unittest.TestCase): diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index ab36400..541884e 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -34,6 +34,11 @@ def _make_failed_test(classname, methodname, exception, suiteClass): TestClass = type(classname, (case.TestCase,), attrs) return suiteClass((TestClass(methodname),)) +def _jython_aware_splitext(path): + if path.lower().endswith('$py.class'): + return path[:-9] + return os.path.splitext(path)[0] + class TestLoader(object): """ @@ -221,7 +226,7 @@ class TestLoader(object): return os.path.dirname(full_path) def _get_name_from_path(self, path): - path = os.path.splitext(os.path.normpath(path))[0] + path = _jython_aware_splitext(os.path.normpath(path)) _relpath = os.path.relpath(path, self._top_level_dir) assert not os.path.isabs(_relpath), "Path must be within the project" @@ -258,11 +263,11 @@ class TestLoader(object): yield _make_failed_import_test(name, self.suiteClass) else: mod_file = os.path.abspath(getattr(module, '__file__', full_path)) - realpath = os.path.splitext(mod_file)[0] - fullpath_noext = os.path.splitext(full_path)[0] + realpath = _jython_aware_splitext(mod_file) + fullpath_noext = _jython_aware_splitext(full_path) if realpath.lower() != fullpath_noext.lower(): module_dir = os.path.dirname(realpath) - mod_name = os.path.splitext(os.path.basename(full_path))[0] + mod_name = _jython_aware_splitext(os.path.basename(full_path)) expected_dir = os.path.dirname(full_path) msg = ("%r module incorrectly imported from %r. Expected %r. " "Is this module globally installed?") diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 94b713e..fe2cfcd 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1062,8 +1062,9 @@ class AbstractHTTPHandler(BaseHandler): if request.data is not None: # POST data = request.data if isinstance(data, str): - raise TypeError("POST data should be bytes" - " or an iterable of bytes. It cannot be str.") + msg = "POST data should be bytes or an iterable of bytes."\ + "It cannot be str" + raise TypeError(msg) if not request.has_header('Content-type'): request.add_unredirected_header( 'Content-type', diff --git a/Lib/urllib/response.py b/Lib/urllib/response.py index 8c6dcca..ffaa5fa 100644 --- a/Lib/urllib/response.py +++ b/Lib/urllib/response.py @@ -61,11 +61,11 @@ class addclosehook(addbase): self.hookargs = hookargs def close(self): - addbase.close(self) if self.closehook: self.closehook(*self.hookargs) self.closehook = None self.hookargs = None + addbase.close(self) class addinfo(addbase): """class to add an info() method to an open file.""" diff --git a/Lib/weakref.py b/Lib/weakref.py index 468f8f1..fcb6b74 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -78,7 +78,7 @@ class WeakValueDictionary(collections.MutableMapping): del self.data[key] def __len__(self): - return sum(wr() is not None for wr in self.data.values()) + return len(self.data) - len(self._pending_removals) def __contains__(self, key): try: @@ -290,7 +290,7 @@ class WeakKeyDictionary(collections.MutableMapping): return self.data[ref(key)] def __len__(self): - return len(self.data) + return len(self.data) - len(self._pending_removals) def __repr__(self): return "<WeakKeyDictionary at %s>" % id(self) diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index d7ed3f3..fd17026 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -1,4 +1,4 @@ -"""XML-RPC Servers. +r"""XML-RPC Servers. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a |