summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/anydbm.py24
-rw-r--r--Lib/collections.py230
-rw-r--r--Lib/distutils/command/sdist.py25
-rw-r--r--Lib/getpass.py2
-rw-r--r--Lib/subprocess.py11
-rw-r--r--Lib/tarfile.py2
-rw-r--r--Lib/test/string_tests.py57
-rw-r--r--Lib/test/test_bytes.py62
-rw-r--r--Lib/test/test_collections.py9
-rw-r--r--Lib/test/test_pydoc.py10
-rw-r--r--Lib/test/test_startfile.py6
-rw-r--r--Lib/test/test_str.py13
-rw-r--r--Lib/test/test_tarfile.py28
-rw-r--r--Lib/test/test_unicode.py11
-rw-r--r--Lib/test/test_zipfile.py222
-rw-r--r--Lib/unittest/case.py8
-rw-r--r--Lib/unittest/test/test_case.py36
17 files changed, 512 insertions, 244 deletions
diff --git a/Lib/anydbm.py b/Lib/anydbm.py
index 8b01ef3ea4..ba7e90510a 100644
--- a/Lib/anydbm.py
+++ b/Lib/anydbm.py
@@ -29,17 +29,8 @@ It has the following interface (key and data are strings):
list = d.keys() # return a list of all existing keys (slow!)
Future versions may change the order in which implementations are
-tested for existence, add interfaces to other dbm-like
+tested for existence, and add interfaces to other dbm-like
implementations.
-
-The open function has an optional second argument. This can be 'r',
-for read-only access, 'w', for read-write access of an existing
-database, 'c' for read-write access to a new or existing database, and
-'n' for read-write access to a new database. The default is 'r'.
-
-Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
-only if it doesn't exist; and 'n' always creates a new database.
-
"""
class error(Exception):
@@ -63,7 +54,18 @@ if not _defaultmod:
error = tuple(_errors)
-def open(file, flag = 'r', mode = 0666):
+def open(file, flag='r', mode=0666):
+ """Open or create database at path given by *file*.
+
+ Optional argument *flag* can be 'r' (default) for read-only access, 'w'
+ for read-write access of an existing database, 'c' for read-write access
+ to a new or existing database, and 'n' for read-write access to a new
+ database.
+
+ Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
+ only if it doesn't exist; and 'n' always creates a new database.
+ """
+
# guess the type of an existing database
from whichdb import whichdb
result=whichdb(file)
diff --git a/Lib/collections.py b/Lib/collections.py
index bb6b15dbcc..d87c55d36b 100644
--- a/Lib/collections.py
+++ b/Lib/collections.py
@@ -6,37 +6,16 @@ import _abcoll
__all__ += _abcoll.__all__
from _collections import deque, defaultdict
-from operator import itemgetter as _itemgetter, eq as _eq
+from operator import itemgetter as _itemgetter
from keyword import iskeyword as _iskeyword
import sys as _sys
import heapq as _heapq
-from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \
- ifilter as _ifilter, imap as _imap
+from itertools import repeat as _repeat, chain as _chain, starmap as _starmap
+
try:
- from thread import get_ident
+ from thread import get_ident as _get_ident
except ImportError:
- from dummy_thread import get_ident
-
-def _recursive_repr(user_function):
- 'Decorator to make a repr function return "..." for a recursive call'
- repr_running = set()
-
- def wrapper(self):
- key = id(self), get_ident()
- if key in repr_running:
- return '...'
- repr_running.add(key)
- try:
- result = user_function(self)
- finally:
- repr_running.discard(key)
- return result
-
- # Can't use functools.wraps() here because of bootstrap issues
- wrapper.__module__ = getattr(user_function, '__module__')
- wrapper.__doc__ = getattr(user_function, '__doc__')
- wrapper.__name__ = getattr(user_function, '__name__')
- return wrapper
+ from dummy_thread import get_ident as _get_ident
################################################################################
@@ -48,17 +27,17 @@ class OrderedDict(dict):
# An inherited dict maps keys to values.
# The inherited dict provides __getitem__, __len__, __contains__, and get.
# The remaining methods are order-aware.
- # Big-O running times for all methods are the same as for regular dictionaries.
+ # Big-O running times for all methods are the same as regular dictionaries.
- # The internal self.__map dictionary maps keys to links in a doubly linked list.
+ # The internal self.__map dict maps keys to links in a doubly linked list.
# The circular doubly linked list starts and ends with a sentinel element.
# The sentinel element never gets deleted (this simplifies the algorithm).
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
def __init__(self, *args, **kwds):
- '''Initialize an ordered dictionary. Signature is the same as for
- regular dictionaries, but keyword arguments are not recommended
- because their insertion order is arbitrary.
+ '''Initialize an ordered dictionary. The signature is the same as
+ regular dictionaries, but keyword arguments are not recommended because
+ their insertion order is arbitrary.
'''
if len(args) > 1:
@@ -66,17 +45,15 @@ class OrderedDict(dict):
try:
self.__root
except AttributeError:
- self.__root = root = [None, None, None] # sentinel node
- PREV = 0
- NEXT = 1
- root[PREV] = root[NEXT] = root
+ self.__root = root = [] # sentinel node
+ root[:] = [root, root, None]
self.__map = {}
self.__update(*args, **kwds)
def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__):
'od.__setitem__(i, y) <==> od[i]=y'
- # Setting a new item creates a new link which goes at the end of the linked
- # list, and the inherited dictionary is updated with the new key/value pair.
+ # Setting a new item creates a new link at the end of the linked list,
+ # and the inherited dictionary is updated with the new key/value pair.
if key not in self:
root = self.__root
last = root[PREV]
@@ -85,79 +62,82 @@ class OrderedDict(dict):
def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__):
'od.__delitem__(y) <==> del od[y]'
- # Deleting an existing item uses self.__map to find the link which is
- # then removed by updating the links in the predecessor and successor nodes.
+ # Deleting an existing item uses self.__map to find the link which gets
+ # removed by updating the links in the predecessor and successor nodes.
dict_delitem(self, key)
- link = self.__map.pop(key)
- link_prev = link[PREV]
- link_next = link[NEXT]
+ link_prev, link_next, key = self.__map.pop(key)
link_prev[NEXT] = link_next
link_next[PREV] = link_prev
- def __iter__(self, NEXT=1, KEY=2):
+ def __iter__(self):
'od.__iter__() <==> iter(od)'
# Traverse the linked list in order.
+ NEXT, KEY = 1, 2
root = self.__root
curr = root[NEXT]
while curr is not root:
yield curr[KEY]
curr = curr[NEXT]
- def __reversed__(self, PREV=0, KEY=2):
+ def __reversed__(self):
'od.__reversed__() <==> reversed(od)'
# Traverse the linked list in reverse order.
+ PREV, KEY = 0, 2
root = self.__root
curr = root[PREV]
while curr is not root:
yield curr[KEY]
curr = curr[PREV]
- def __reduce__(self):
- 'Return state information for pickling'
- items = [[k, self[k]] for k in self]
- tmp = self.__map, self.__root
- del self.__map, self.__root
- inst_dict = vars(self).copy()
- self.__map, self.__root = tmp
- if inst_dict:
- return (self.__class__, (items,), inst_dict)
- return self.__class__, (items,)
-
def clear(self):
'od.clear() -> None. Remove all items from od.'
- try:
- for node in self.__map.itervalues():
- del node[:]
- self.__root[:] = [self.__root, self.__root, None]
- self.__map.clear()
- except AttributeError:
- pass
+ for node in self.__map.itervalues():
+ del node[:]
+ root = self.__root
+ root[:] = [root, root, None]
+ self.__map.clear()
dict.clear(self)
- update = __update = MutableMapping.update
- keys = MutableMapping.keys
- values = MutableMapping.values
- items = MutableMapping.items
- iterkeys = MutableMapping.iterkeys
- itervalues = MutableMapping.itervalues
- iteritems = MutableMapping.iteritems
- __ne__ = MutableMapping.__ne__
+ # -- the following methods do not depend on the internal structure --
- def viewkeys(self):
- "od.viewkeys() -> a set-like object providing a view on od's keys"
- return KeysView(self)
+ def keys(self):
+ 'od.keys() -> list of keys in od'
+ return list(self)
- def viewvalues(self):
- "od.viewvalues() -> an object providing a view on od's values"
- return ValuesView(self)
+ def values(self):
+ 'od.values() -> list of values in od'
+ return [self[key] for key in self]
- def viewitems(self):
- "od.viewitems() -> a set-like object providing a view on od's items"
- return ItemsView(self)
+ def items(self):
+ 'od.items() -> list of (key, value) pairs in od'
+ return [(key, self[key]) for key in self]
+
+ def iterkeys(self):
+ 'od.iterkeys() -> an iterator over the keys in od'
+ return iter(self)
+
+ def itervalues(self):
+ 'od.itervalues -> an iterator over the values in od'
+ for k in self:
+ yield self[k]
+
+ def iteritems(self):
+ 'od.iteritems -> an iterator over the (key, value) pairs in od'
+ for k in self:
+ yield (k, self[k])
+
+ update = MutableMapping.update
+
+ __update = update # let subclasses override update without breaking __init__
__marker = object()
def pop(self, key, default=__marker):
+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
+ value. If key is not found, d is returned if given, otherwise KeyError
+ is raised.
+
+ '''
if key in self:
result = self[key]
del self[key]
@@ -184,12 +164,28 @@ class OrderedDict(dict):
value = self.pop(key)
return key, value
- @_recursive_repr
- def __repr__(self):
+ def __repr__(self, _repr_running={}):
'od.__repr__() <==> repr(od)'
- if not self:
- return '%s()' % (self.__class__.__name__,)
- return '%s(%r)' % (self.__class__.__name__, self.items())
+ call_key = id(self), _get_ident()
+ if call_key in _repr_running:
+ return '...'
+ _repr_running[call_key] = 1
+ try:
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, self.items())
+ finally:
+ del _repr_running[call_key]
+
+ def __reduce__(self):
+ 'Return state information for pickling'
+ items = [[k, self[k]] for k in self]
+ inst_dict = vars(self).copy()
+ for k in vars(OrderedDict()):
+ inst_dict.pop(k, None)
+ if inst_dict:
+ return (self.__class__, (items,), inst_dict)
+ return self.__class__, (items,)
def copy(self):
'od.copy() -> a shallow copy of od'
@@ -197,14 +193,14 @@ class OrderedDict(dict):
@classmethod
def fromkeys(cls, iterable, value=None):
- '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
- and values equal to v (which defaults to None).
+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
+ If not specified, the value defaults to None.
'''
- d = cls()
+ self = cls()
for key in iterable:
- d[key] = value
- return d
+ self[key] = value
+ return self
def __eq__(self, other):
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
@@ -212,10 +208,27 @@ class OrderedDict(dict):
'''
if isinstance(other, OrderedDict):
- return len(self)==len(other) and \
- all(_imap(_eq, self.iteritems(), other.iteritems()))
+ return len(self)==len(other) and self.items() == other.items()
return dict.__eq__(self, other)
+ def __ne__(self, other):
+ 'od.__ne__(y) <==> od!=y'
+ return not self == other
+
+ # -- the following methods support python 3.x style dictionary views --
+
+ def viewkeys(self):
+ "od.viewkeys() -> a set-like object providing a view on od's keys"
+ return KeysView(self)
+
+ def viewvalues(self):
+ "od.viewvalues() -> an object providing a view on od's values"
+ return ValuesView(self)
+
+ def viewitems(self):
+ "od.viewitems() -> a set-like object providing a view on od's items"
+ return ItemsView(self)
+
################################################################################
### namedtuple
@@ -516,8 +529,8 @@ class Counter(dict):
self.subtract(kwds)
def copy(self):
- 'Like dict.copy() but returns a Counter instance instead of a dict.'
- return Counter(self)
+ 'Return a shallow copy.'
+ return self.__class__(self)
def __reduce__(self):
return self.__class__, (dict(self),)
@@ -552,10 +565,13 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- newcount = self[elem] + other[elem]
+ for elem, count in self.items():
+ newcount = count + other[elem]
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count > 0:
+ result[elem] = count
return result
def __sub__(self, other):
@@ -568,10 +584,13 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- newcount = self[elem] - other[elem]
+ for elem, count in self.items():
+ newcount = count - other[elem]
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count < 0:
+ result[elem] = 0 - count
return result
def __or__(self, other):
@@ -584,11 +603,14 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- p, q = self[elem], other[elem]
- newcount = q if p < q else p
+ for elem, count in self.items():
+ other_count = other[elem]
+ newcount = other_count if count < other_count else count
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count > 0:
+ result[elem] = count
return result
def __and__(self, other):
@@ -601,11 +623,9 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- if len(self) < len(other):
- self, other = other, self
- for elem in _ifilter(self.__contains__, other):
- p, q = self[elem], other[elem]
- newcount = p if p < q else q
+ for elem, count in self.items():
+ other_count = other[elem]
+ newcount = count if count < other_count else other_count
if newcount > 0:
result[elem] = newcount
return result
diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py
index 0c3b0b55bf..cf8982bd9d 100644
--- a/Lib/distutils/command/sdist.py
+++ b/Lib/distutils/command/sdist.py
@@ -306,17 +306,20 @@ class sdist(Command):
rstrip_ws=1,
collapse_join=1)
- while 1:
- line = template.readline()
- if line is None: # end of file
- break
-
- try:
- self.filelist.process_template_line(line)
- except DistutilsTemplateError, msg:
- self.warn("%s, line %d: %s" % (template.filename,
- template.current_line,
- msg))
+ try:
+ while 1:
+ line = template.readline()
+ if line is None: # end of file
+ break
+
+ try:
+ self.filelist.process_template_line(line)
+ except DistutilsTemplateError, msg:
+ self.warn("%s, line %d: %s" % (template.filename,
+ template.current_line,
+ msg))
+ finally:
+ template.close()
def prune_file_list(self):
"""Prune off branches that might slip into the file list as created
diff --git a/Lib/getpass.py b/Lib/getpass.py
index 4745ea944c..2ac6fd7f38 100644
--- a/Lib/getpass.py
+++ b/Lib/getpass.py
@@ -62,7 +62,7 @@ def unix_getpass(prompt='Password: ', stream=None):
try:
old = termios.tcgetattr(fd) # a copy to save
new = old[:]
- new[3] &= ~(termios.ECHO|termios.ISIG) # 3 == 'lflags'
+ new[3] &= ~termios.ECHO # 3 == 'lflags'
tcsetattr_flags = termios.TCSAFLUSH
if hasattr(termios, 'TCSASOFT'):
tcsetattr_flags |= termios.TCSASOFT
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 25248dc0d3..3734acde33 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -441,8 +441,15 @@ __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call",
"check_output", "CalledProcessError"]
if mswindows:
- from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
- __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"])
+ from _subprocess import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP,
+ STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
+ STD_ERROR_HANDLE, SW_HIDE,
+ STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW)
+
+ __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP",
+ "STD_INPUT_HANDLE", "STD_OUTPUT_HANDLE",
+ "STD_ERROR_HANDLE", "SW_HIDE",
+ "STARTF_USESTDHANDLES", "STARTF_USESHOWWINDOW"])
try:
MAXFD = os.sysconf("SC_OPEN_MAX")
except:
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 47be1d49df..105a75880d 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2239,6 +2239,8 @@ class TarFile(object):
if hasattr(os, "symlink") and hasattr(os, "link"):
# For systems that support symbolic and hard links.
if tarinfo.issym():
+ if os.path.exists(targetpath):
+ os.unlink(targetpath)
os.symlink(tarinfo.linkname, targetpath)
else:
# See extract().
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index 546b486a84..5931f3d88b 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -1177,6 +1177,63 @@ class MixinStrUnicodeUserStringTest:
# mixed use of str and unicode
self.assertEqual('a/b/c'.rpartition(u'/'), ('a/b', '/', 'c'))
+ def test_none_arguments(self):
+ # issue 11828
+ s = 'hello'
+ self.checkequal(2, s, 'find', 'l', None)
+ self.checkequal(3, s, 'find', 'l', -2, None)
+ self.checkequal(2, s, 'find', 'l', None, -2)
+ self.checkequal(0, s, 'find', 'h', None, None)
+
+ self.checkequal(3, s, 'rfind', 'l', None)
+ self.checkequal(3, s, 'rfind', 'l', -2, None)
+ self.checkequal(2, s, 'rfind', 'l', None, -2)
+ self.checkequal(0, s, 'rfind', 'h', None, None)
+
+ self.checkequal(2, s, 'index', 'l', None)
+ self.checkequal(3, s, 'index', 'l', -2, None)
+ self.checkequal(2, s, 'index', 'l', None, -2)
+ self.checkequal(0, s, 'index', 'h', None, None)
+
+ self.checkequal(3, s, 'rindex', 'l', None)
+ self.checkequal(3, s, 'rindex', 'l', -2, None)
+ self.checkequal(2, s, 'rindex', 'l', None, -2)
+ self.checkequal(0, s, 'rindex', 'h', None, None)
+
+ self.checkequal(2, s, 'count', 'l', None)
+ self.checkequal(1, s, 'count', 'l', -2, None)
+ self.checkequal(1, s, 'count', 'l', None, -2)
+ self.checkequal(0, s, 'count', 'x', None, None)
+
+ self.checkequal(True, s, 'endswith', 'o', None)
+ self.checkequal(True, s, 'endswith', 'lo', -2, None)
+ self.checkequal(True, s, 'endswith', 'l', None, -2)
+ self.checkequal(False, s, 'endswith', 'x', None, None)
+
+ self.checkequal(True, s, 'startswith', 'h', None)
+ self.checkequal(True, s, 'startswith', 'l', -2, None)
+ self.checkequal(True, s, 'startswith', 'h', None, -2)
+ self.checkequal(False, s, 'startswith', 'x', None, None)
+
+ def test_find_etc_raise_correct_error_messages(self):
+ # issue 11828
+ s = 'hello'
+ x = 'x'
+ self.assertRaisesRegexp(TypeError, r'\bfind\b', s.find,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\brfind\b', s.rfind,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\bindex\b', s.index,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\brindex\b', s.rindex,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'^count\(', s.count,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'^startswith\(', s.startswith,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'^endswith\(', s.endswith,
+ x, None, None, None)
+
class MixinStrStringUserStringTest:
# Additional tests for 8bit strings, i.e. str, UserString and
# the string module
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 2026cdbde1..2ef1c8819f 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -456,6 +456,68 @@ class BaseBytesTest(unittest.TestCase):
self.assertEqual([ord(b[i:i+1]) for i in range(len(b))],
[0, 65, 127, 128, 255])
+ def test_none_arguments(self):
+ # issue 11828
+ b = self.type2test(b'hello')
+ l = self.type2test(b'l')
+ h = self.type2test(b'h')
+ x = self.type2test(b'x')
+ o = self.type2test(b'o')
+
+ self.assertEqual(2, b.find(l, None))
+ self.assertEqual(3, b.find(l, -2, None))
+ self.assertEqual(2, b.find(l, None, -2))
+ self.assertEqual(0, b.find(h, None, None))
+
+ self.assertEqual(3, b.rfind(l, None))
+ self.assertEqual(3, b.rfind(l, -2, None))
+ self.assertEqual(2, b.rfind(l, None, -2))
+ self.assertEqual(0, b.rfind(h, None, None))
+
+ self.assertEqual(2, b.index(l, None))
+ self.assertEqual(3, b.index(l, -2, None))
+ self.assertEqual(2, b.index(l, None, -2))
+ self.assertEqual(0, b.index(h, None, None))
+
+ self.assertEqual(3, b.rindex(l, None))
+ self.assertEqual(3, b.rindex(l, -2, None))
+ self.assertEqual(2, b.rindex(l, None, -2))
+ self.assertEqual(0, b.rindex(h, None, None))
+
+ self.assertEqual(2, b.count(l, None))
+ self.assertEqual(1, b.count(l, -2, None))
+ self.assertEqual(1, b.count(l, None, -2))
+ self.assertEqual(0, b.count(x, None, None))
+
+ self.assertEqual(True, b.endswith(o, None))
+ self.assertEqual(True, b.endswith(o, -2, None))
+ self.assertEqual(True, b.endswith(l, None, -2))
+ self.assertEqual(False, b.endswith(x, None, None))
+
+ self.assertEqual(True, b.startswith(h, None))
+ self.assertEqual(True, b.startswith(l, -2, None))
+ self.assertEqual(True, b.startswith(h, None, -2))
+ self.assertEqual(False, b.startswith(x, None, None))
+
+ def test_find_etc_raise_correct_error_messages(self):
+ # issue 11828
+ b = self.type2test(b'hello')
+ x = self.type2test(b'x')
+ self.assertRaisesRegexp(TypeError, r'\bfind\b', b.find,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\brfind\b', b.rfind,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\bindex\b', b.index,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\brindex\b', b.rindex,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\bcount\b', b.count,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\bstartswith\b', b.startswith,
+ x, None, None, None)
+ self.assertRaisesRegexp(TypeError, r'\bendswith\b', b.endswith,
+ x, None, None, None)
+
class ByteArrayTest(BaseBytesTest):
type2test = bytearray
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index f6a43fcb1f..8bdeb3d8f1 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -689,6 +689,15 @@ class TestCounter(unittest.TestCase):
self.assertEqual(len(dup), len(words))
self.assertEqual(type(dup), type(words))
+ def test_copy_subclass(self):
+ class MyCounter(Counter):
+ pass
+ c = MyCounter('slartibartfast')
+ d = c.copy()
+ self.assertEqual(d, c)
+ self.assertEqual(len(d), len(c))
+ self.assertEqual(type(d), type(c))
+
def test_conversions(self):
# Convert to: set, list, dict
s = 'she sells sea shells by the sea shore'
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index 2e67290d00..8591693238 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -6,6 +6,7 @@ import subprocess
import re
import pydoc
import inspect
+import keyword
import unittest
import xml.etree
import test.test_support
@@ -351,9 +352,16 @@ class TestDescriptions(unittest.TestCase):
self.assertIn('_asdict', helptext)
+class TestHelper(unittest.TestCase):
+ def test_keywords(self):
+ self.assertEqual(sorted(pydoc.Helper.keywords),
+ sorted(keyword.kwlist))
+
+
def test_main():
test.test_support.run_unittest(PyDocDocTest,
- TestDescriptions)
+ TestDescriptions,
+ TestHelper)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_startfile.py b/Lib/test/test_startfile.py
index 8eeae72eab..9dce8fd6ac 100644
--- a/Lib/test/test_startfile.py
+++ b/Lib/test/test_startfile.py
@@ -11,6 +11,7 @@ import unittest
from test import test_support
import os
from os import path
+from time import sleep
startfile = test_support.get_attribute(os, 'startfile')
@@ -26,11 +27,16 @@ class TestCase(unittest.TestCase):
empty = path.join(path.dirname(__file__), "empty.vbs")
startfile(empty)
startfile(empty, "open")
+ # Give the child process some time to exit before we finish.
+ # Otherwise the cleanup code will not be able to delete the cwd,
+ # because it is still in use.
+ sleep(0.1)
def test_empty_u(self):
empty = path.join(path.dirname(__file__), "empty.vbs")
startfile(unicode(empty, "mbcs"))
startfile(unicode(empty, "mbcs"), "open")
+ sleep(0.1)
def test_main():
test_support.run_unittest(TestCase)
diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py
index 4f88b28848..2ecf3276b4 100644
--- a/Lib/test/test_str.py
+++ b/Lib/test/test_str.py
@@ -414,7 +414,18 @@ class StrTest(
self.assertEqual('Andr\202 x'.decode('ascii', 'replace'),
'Andr\202 x'.decode(encoding='ascii', errors='replace'))
-
+ def test_startswith_endswith_errors(self):
+ with self.assertRaises(UnicodeDecodeError):
+ '\xff'.startswith(u'x')
+ with self.assertRaises(UnicodeDecodeError):
+ '\xff'.endswith(u'x')
+ for meth in ('foo'.startswith, 'foo'.endswith):
+ with self.assertRaises(TypeError) as cm:
+ meth(['f'])
+ exc = str(cm.exception)
+ self.assertIn('unicode', exc)
+ self.assertIn('str', exc)
+ self.assertIn('tuple', exc)
def test_main():
test_support.run_unittest(StrTest)
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index cda5262acc..f78f9ce03f 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -843,6 +843,34 @@ class WriteTest(WriteTestBase):
finally:
os.chdir(cwd)
+ @unittest.skipUnless(hasattr(os, 'symlink'), "needs os.symlink")
+ def test_extractall_symlinks(self):
+ # Test if extractall works properly when tarfile contains symlinks
+ tempdir = os.path.join(TEMPDIR, "testsymlinks")
+ temparchive = os.path.join(TEMPDIR, "testsymlinks.tar")
+ os.mkdir(tempdir)
+ try:
+ source_file = os.path.join(tempdir,'source')
+ target_file = os.path.join(tempdir,'symlink')
+ with open(source_file,'w') as f:
+ f.write('something\n')
+ os.symlink(source_file, target_file)
+ tar = tarfile.open(temparchive,'w')
+ tar.add(source_file, arcname=os.path.basename(source_file))
+ tar.add(target_file, arcname=os.path.basename(target_file))
+ tar.close()
+ # Let's extract it to the location which contains the symlink
+ tar = tarfile.open(temparchive,'r')
+ # this should not raise OSError: [Errno 17] File exists
+ try:
+ tar.extractall(path=tempdir)
+ except OSError:
+ self.fail("extractall failed with symlinked files")
+ finally:
+ tar.close()
+ finally:
+ os.unlink(temparchive)
+ shutil.rmtree(tempdir)
class StreamWriteTest(WriteTestBase):
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index ae4c355f48..bd43dbc57b 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -442,6 +442,17 @@ class UnicodeTest(
return u'\u1234'
self.assertEqual('%s' % Wrapper(), u'\u1234')
+ def test_startswith_endswith_errors(self):
+ for meth in (u'foo'.startswith, u'foo'.endswith):
+ with self.assertRaises(UnicodeDecodeError):
+ meth('\xff')
+ with self.assertRaises(TypeError) as cm:
+ meth(['f'])
+ exc = str(cm.exception)
+ self.assertIn('unicode', exc)
+ self.assertIn('str', exc)
+ self.assertIn('tuple', exc)
+
@test_support.run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
def test_format_float(self):
# should not format with a comma, but always with C locale
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 7c8c0c5542..c4a64a3b4b 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -115,20 +115,20 @@ class TestsWithSourceFile(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r", compression) as zipfp:
zipdata1 = []
- zipopen1 = zipfp.open(TESTFN)
- while True:
- read_data = zipopen1.read(256)
- if not read_data:
- break
- zipdata1.append(read_data)
+ with zipfp.open(TESTFN) as zipopen1:
+ while True:
+ read_data = zipopen1.read(256)
+ if not read_data:
+ break
+ zipdata1.append(read_data)
zipdata2 = []
- zipopen2 = zipfp.open("another.name")
- while True:
- read_data = zipopen2.read(256)
- if not read_data:
- break
- zipdata2.append(read_data)
+ with zipfp.open("another.name") as zipopen2:
+ while True:
+ read_data = zipopen2.read(256)
+ if not read_data:
+ break
+ zipdata2.append(read_data)
self.assertEqual(''.join(zipdata1), self.data)
self.assertEqual(''.join(zipdata2), self.data)
@@ -147,7 +147,8 @@ class TestsWithSourceFile(unittest.TestCase):
infos = zipfp.infolist()
data = ""
for info in infos:
- data += zipfp.open(info).read()
+ with zipfp.open(info) as f:
+ data += f.read()
self.assertTrue(data == "foobar" or data == "barfoo")
data = ""
for info in infos:
@@ -160,12 +161,12 @@ class TestsWithSourceFile(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r", compression) as zipfp:
zipdata1 = []
- zipopen1 = zipfp.open(TESTFN)
- while True:
- read_data = zipopen1.read(randint(1, 1024))
- if not read_data:
- break
- zipdata1.append(read_data)
+ with zipfp.open(TESTFN) as zipopen1:
+ while True:
+ read_data = zipopen1.read(randint(1, 1024))
+ if not read_data:
+ break
+ zipdata1.append(read_data)
self.assertEqual(''.join(zipdata1), self.data)
@@ -177,16 +178,14 @@ class TestsWithSourceFile(unittest.TestCase):
f = StringIO()
data = 'a\r\n' * 16 * 1024
- zipfp = zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED)
- zipfp.writestr(TESTFN, data)
- zipfp.close()
+ with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as zipfp:
+ zipfp.writestr(TESTFN, data)
data2 = ''
- zipfp = zipfile.ZipFile(f, 'r')
- zipopen = zipfp.open(TESTFN, 'rU')
- for line in zipopen:
- data2 += line
- zipfp.close()
+ with zipfile.ZipFile(f, 'r') as zipfp:
+ with zipfp.open(TESTFN, 'rU') as zipopen:
+ for line in zipopen:
+ data2 += line
self.assertEqual(data, data2.replace('\n', '\r\n'))
@@ -194,42 +193,41 @@ class TestsWithSourceFile(unittest.TestCase):
self.make_test_archive(f, compression)
# Read the ZIP archive
- zipfp = zipfile.ZipFile(f, "r")
- zipopen = zipfp.open(TESTFN)
-
- data = ''
- while True:
- read = zipopen.readline()
- if not read:
- break
- data += read
-
- read = zipopen.read(100)
- if not read:
- break
- data += read
+ with zipfile.ZipFile(f, "r") as zipfp:
+ with zipfp.open(TESTFN) as zipopen:
+ data = ''
+ while True:
+ read = zipopen.readline()
+ if not read:
+ break
+ data += read
+
+ read = zipopen.read(100)
+ if not read:
+ break
+ data += read
self.assertEqual(data, self.data)
- zipfp.close()
def zip_readline_test(self, f, compression):
self.make_test_archive(f, compression)
# Read the ZIP archive
with zipfile.ZipFile(f, "r") as zipfp:
- zipopen = zipfp.open(TESTFN)
- for line in self.line_gen:
- linedata = zipopen.readline()
- self.assertEqual(linedata, line + '\n')
+ with zipfp.open(TESTFN) as zipopen:
+ for line in self.line_gen:
+ linedata = zipopen.readline()
+ self.assertEqual(linedata, line + '\n')
def zip_readlines_test(self, f, compression):
self.make_test_archive(f, compression)
# Read the ZIP archive
with zipfile.ZipFile(f, "r") as zipfp:
- ziplines = zipfp.open(TESTFN).readlines()
- for line, zipline in zip(self.line_gen, ziplines):
- self.assertEqual(zipline, line + '\n')
+ with zipfp.open(TESTFN) as zo:
+ ziplines = zo.readlines()
+ for line, zipline in zip(self.line_gen, ziplines):
+ self.assertEqual(zipline, line + '\n')
def zip_iterlines_test(self, f, compression):
self.make_test_archive(f, compression)
@@ -301,9 +299,9 @@ class TestsWithSourceFile(unittest.TestCase):
# Get an open object for strfile
with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED) as zipfp:
- openobj = zipfp.open("strfile")
- self.assertEqual(openobj.read(1), '1')
- self.assertEqual(openobj.read(1), '2')
+ with zipfp.open("strfile") as openobj:
+ self.assertEqual(openobj.read(1), '1')
+ self.assertEqual(openobj.read(1), '2')
def test_absolute_arcnames(self):
with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
@@ -775,8 +773,8 @@ class OtherTests(unittest.TestCase):
self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
def test_empty_file_raises_BadZipFile(self):
- f = open(TESTFN, 'w')
- f.close()
+ with open(TESTFN, 'w') as f:
+ pass
self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN)
with open(TESTFN, 'w') as fp:
@@ -820,11 +818,11 @@ class OtherTests(unittest.TestCase):
with zipfile.ZipFile(TESTFN, mode="w") as zipf:
zipf.writestr("foo.txt", "O, for a Muse of Fire!")
# read the data to make sure the file is there
- f = zipf.open("foo.txt")
- for i in xrange(FIXEDTEST_SIZE):
- self.assertEqual(f.read(0), '')
+ with zipf.open("foo.txt") as f:
+ for i in xrange(FIXEDTEST_SIZE):
+ self.assertEqual(f.read(0), '')
- self.assertEqual(f.read(), "O, for a Muse of Fire!")
+ self.assertEqual(f.read(), "O, for a Muse of Fire!")
def test_open_non_existent_item(self):
"""Check that attempting to call open() for an item that doesn't
@@ -952,15 +950,15 @@ class OtherTests(unittest.TestCase):
def test_empty_zipfile(self):
# Check that creating a file in 'w' or 'a' mode and closing without
# adding any files to the archives creates a valid empty ZIP file
- zipf = zipfile.ZipFile(TESTFN, mode="w")
- zipf.close()
+ with zipfile.ZipFile(TESTFN, mode="w") as zipf:
+ pass
try:
zipf = zipfile.ZipFile(TESTFN, mode="r")
except zipfile.BadZipfile:
self.fail("Unable to create empty ZIP file in 'w' mode")
- zipf = zipfile.ZipFile(TESTFN, mode="a")
- zipf.close()
+ with zipfile.ZipFile(TESTFN, mode="a") as zipf:
+ pass
try:
zipf = zipfile.ZipFile(TESTFN, mode="r")
except:
@@ -970,8 +968,8 @@ class OtherTests(unittest.TestCase):
# Issue 1710703: Check that opening a file with less than 22 bytes
# raises a BadZipfile exception (rather than the previously unhelpful
# IOError)
- f = open(TESTFN, 'w')
- f.close()
+ with open(TESTFN, 'w') as f:
+ pass
self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN, 'r')
def tearDown(self):
@@ -1084,20 +1082,20 @@ class TestsWithRandomBinaryFiles(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r", compression) as zipfp:
zipdata1 = []
- zipopen1 = zipfp.open(TESTFN)
- while True:
- read_data = zipopen1.read(256)
- if not read_data:
- break
- zipdata1.append(read_data)
+ with zipfp.open(TESTFN) as zipopen1:
+ while True:
+ read_data = zipopen1.read(256)
+ if not read_data:
+ break
+ zipdata1.append(read_data)
zipdata2 = []
- zipopen2 = zipfp.open("another.name")
- while True:
- read_data = zipopen2.read(256)
- if not read_data:
- break
- zipdata2.append(read_data)
+ with zipfp.open("another.name") as zipopen2:
+ while True:
+ read_data = zipopen2.read(256)
+ if not read_data:
+ break
+ zipdata2.append(read_data)
testdata1 = ''.join(zipdata1)
self.assertEqual(len(testdata1), len(self.data))
@@ -1122,12 +1120,12 @@ class TestsWithRandomBinaryFiles(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r", compression) as zipfp:
zipdata1 = []
- zipopen1 = zipfp.open(TESTFN)
- while True:
- read_data = zipopen1.read(randint(1, 1024))
- if not read_data:
- break
- zipdata1.append(read_data)
+ with zipfp.open(TESTFN) as zipopen1:
+ while True:
+ read_data = zipopen1.read(randint(1, 1024))
+ if not read_data:
+ break
+ zipdata1.append(read_data)
testdata = ''.join(zipdata1)
self.assertEqual(len(testdata), len(self.data))
@@ -1167,12 +1165,11 @@ class TestsWithMultipleOpens(unittest.TestCase):
# Verify that (when the ZipFile is in control of creating file objects)
# multiple open() calls can be made without interfering with each other.
with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
- zopen1 = zipf.open('ones')
- zopen2 = zipf.open('twos')
- data1 = zopen1.read(500)
- data2 = zopen2.read(500)
- data1 += zopen1.read(500)
- data2 += zopen2.read(500)
+ with zipf.open('ones') as zopen1, zipf.open('twos') as zopen2:
+ data1 = zopen1.read(500)
+ data2 = zopen2.read(500)
+ data1 += zopen1.read(500)
+ data2 += zopen2.read(500)
self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
@@ -1180,12 +1177,11 @@ class TestsWithMultipleOpens(unittest.TestCase):
# Verify that (when the ZipFile is in control of creating file objects)
# multiple open() calls can be made without interfering with each other.
with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
- zopen1 = zipf.open('ones')
- data1 = zopen1.read(500)
- zopen2 = zipf.open('twos')
- data2 = zopen2.read(500)
- data1 += zopen1.read(500)
- data2 += zopen2.read(500)
+ with zipf.open('ones') as zopen1, zipf.open('twos') as zopen2:
+ data1 = zopen1.read(500)
+ data2 = zopen2.read(500)
+ data1 += zopen1.read(500)
+ data2 += zopen2.read(500)
self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
@@ -1244,7 +1240,8 @@ class UniversalNewlineTests(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r") as zipfp:
for sep, fn in self.arcfiles.items():
- zipdata = zipfp.open(fn, "rU").read()
+ with zipfp.open(fn, "rU") as fp:
+ zipdata = fp.read()
self.assertEqual(self.arcdata[sep], zipdata)
def readline_read_test(self, f, compression):
@@ -1253,18 +1250,18 @@ class UniversalNewlineTests(unittest.TestCase):
# Read the ZIP archive
zipfp = zipfile.ZipFile(f, "r")
for sep, fn in self.arcfiles.items():
- zipopen = zipfp.open(fn, "rU")
- data = ''
- while True:
- read = zipopen.readline()
- if not read:
- break
- data += read
-
- read = zipopen.read(5)
- if not read:
- break
- data += read
+ with zipfp.open(fn, "rU") as zipopen:
+ data = ''
+ while True:
+ read = zipopen.readline()
+ if not read:
+ break
+ data += read
+
+ read = zipopen.read(5)
+ if not read:
+ break
+ data += read
self.assertEqual(data, self.arcdata['\n'])
@@ -1276,10 +1273,10 @@ class UniversalNewlineTests(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r") as zipfp:
for sep, fn in self.arcfiles.items():
- zipopen = zipfp.open(fn, "rU")
- for line in self.line_gen:
- linedata = zipopen.readline()
- self.assertEqual(linedata, line + '\n')
+ with zipfp.open(fn, "rU") as zipopen:
+ for line in self.line_gen:
+ linedata = zipopen.readline()
+ self.assertEqual(linedata, line + '\n')
def readlines_test(self, f, compression):
self.make_test_archive(f, compression)
@@ -1287,7 +1284,8 @@ class UniversalNewlineTests(unittest.TestCase):
# Read the ZIP archive
with zipfile.ZipFile(f, "r") as zipfp:
for sep, fn in self.arcfiles.items():
- ziplines = zipfp.open(fn, "rU").readlines()
+ with zipfp.open(fn, "rU") as fp:
+ ziplines = fp.readlines()
for line, zipline in zip(self.line_gen, ziplines):
self.assertEqual(zipline, line + '\n')
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index ecb6a3e419..dcaae93aed 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -169,6 +169,10 @@ class TestCase(object):
maxDiff = 80*8
+ # If a string is longer than _diffThreshold, use normal comparison instead
+ # of difflib. See #11763.
+ _diffThreshold = 2**16
+
# Attribute used by TestSuite for classSetUp
_classSetupFailed = False
@@ -900,6 +904,10 @@ class TestCase(object):
'Second argument is not a string')
if first != second:
+ # don't use difflib if the strings are too long
+ if (len(first) > self._diffThreshold or
+ len(second) > self._diffThreshold):
+ self._baseAssertEqual(first, second, msg)
firstlines = first.splitlines(True)
secondlines = second.splitlines(True)
if len(firstlines) == 1 and first.strip('\r\n') == first:
diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py
index 06eeda1503..2e449c5c2a 100644
--- a/Lib/unittest/test/test_case.py
+++ b/Lib/unittest/test/test_case.py
@@ -667,6 +667,42 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
else:
self.fail('assertMultiLineEqual did not fail')
+ def testAssertEqual_diffThreshold(self):
+ # check threshold value
+ self.assertEqual(self._diffThreshold, 2**16)
+ # disable madDiff to get diff markers
+ self.maxDiff = None
+
+ # set a lower threshold value and add a cleanup to restore it
+ old_threshold = self._diffThreshold
+ self._diffThreshold = 2**8
+ self.addCleanup(lambda: setattr(self, '_diffThreshold', old_threshold))
+
+ # under the threshold: diff marker (^) in error message
+ s = u'x' * (2**7)
+ with self.assertRaises(self.failureException) as cm:
+ self.assertEqual(s + 'a', s + 'b')
+ self.assertIn('^', str(cm.exception))
+ self.assertEqual(s + 'a', s + 'a')
+
+ # over the threshold: diff not used and marker (^) not in error message
+ s = u'x' * (2**9)
+ # if the path that uses difflib is taken, _truncateMessage will be
+ # called -- replace it with explodingTruncation to verify that this
+ # doesn't happen
+ def explodingTruncation(message, diff):
+ raise SystemError('this should not be raised')
+ old_truncate = self._truncateMessage
+ self._truncateMessage = explodingTruncation
+ self.addCleanup(lambda: setattr(self, '_truncateMessage', old_truncate))
+
+ s1, s2 = s + 'a', s + 'b'
+ with self.assertRaises(self.failureException) as cm:
+ self.assertEqual(s1, s2)
+ self.assertNotIn('^', str(cm.exception))
+ self.assertEqual(str(cm.exception), '%r != %r' % (s1, s2))
+ self.assertEqual(s + 'a', s + 'a')
+
def testAssertItemsEqual(self):
a = object()
self.assertItemsEqual([1, 2, 3], [3, 2, 1])