diff options
Diffstat (limited to 'lib/python2.7/test/test_iterlen.py')
-rw-r--r-- | lib/python2.7/test/test_iterlen.py | 257 |
1 files changed, 0 insertions, 257 deletions
diff --git a/lib/python2.7/test/test_iterlen.py b/lib/python2.7/test/test_iterlen.py deleted file mode 100644 index 88f43c7..0000000 --- a/lib/python2.7/test/test_iterlen.py +++ /dev/null @@ -1,257 +0,0 @@ -""" Test Iterator Length Transparency - -Some functions or methods which accept general iterable arguments have -optional, more efficient code paths if they know how many items to expect. -For instance, map(func, iterable), will pre-allocate the exact amount of -space required whenever the iterable can report its length. - -The desired invariant is: len(it)==len(list(it)). - -A complication is that an iterable and iterator can be the same object. To -maintain the invariant, an iterator needs to dynamically update its length. -For instance, an iterable such as xrange(10) always reports its length as ten, -but it=iter(xrange(10)) starts at ten, and then goes to nine after it.next(). -Having this capability means that map() can ignore the distinction between -map(func, iterable) and map(func, iter(iterable)). - -When the iterable is immutable, the implementation can straight-forwardly -report the original length minus the cumulative number of calls to next(). -This is the case for tuples, xrange objects, and itertools.repeat(). - -Some containers become temporarily immutable during iteration. This includes -dicts, sets, and collections.deque. Their implementation is equally simple -though they need to permanently set their length to zero whenever there is -an attempt to iterate after a length mutation. - -The situation slightly more involved whenever an object allows length mutation -during iteration. Lists and sequence iterators are dynamically updatable. -So, if a list is extended during iteration, the iterator will continue through -the new items. If it shrinks to a point before the most recent iteration, -then no further items are available and the length is reported at zero. - -Reversed objects can also be wrapped around mutable objects; however, any -appends after the current position are ignored. Any other approach leads -to confusion and possibly returning the same item more than once. - -The iterators not listed above, such as enumerate and the other itertools, -are not length transparent because they have no way to distinguish between -iterables that report static length and iterators whose length changes with -each call (i.e. the difference between enumerate('abc') and -enumerate(iter('abc')). - -""" - -import unittest -from test import test_support -from itertools import repeat -from collections import deque -from __builtin__ import len as _len - -n = 10 - -def len(obj): - try: - return _len(obj) - except TypeError: - try: - # note: this is an internal undocumented API, - # don't rely on it in your own programs - return obj.__length_hint__() - except AttributeError: - raise TypeError - -class TestInvariantWithoutMutations(unittest.TestCase): - - def test_invariant(self): - it = self.it - for i in reversed(xrange(1, n+1)): - self.assertEqual(len(it), i) - it.next() - self.assertEqual(len(it), 0) - self.assertRaises(StopIteration, it.next) - self.assertEqual(len(it), 0) - -class TestTemporarilyImmutable(TestInvariantWithoutMutations): - - def test_immutable_during_iteration(self): - # objects such as deques, sets, and dictionaries enforce - # length immutability during iteration - - it = self.it - self.assertEqual(len(it), n) - it.next() - self.assertEqual(len(it), n-1) - self.mutate() - self.assertRaises(RuntimeError, it.next) - self.assertEqual(len(it), 0) - -## ------- Concrete Type Tests ------- - -class TestRepeat(TestInvariantWithoutMutations): - - def setUp(self): - self.it = repeat(None, n) - - def test_no_len_for_infinite_repeat(self): - # The repeat() object can also be infinite - self.assertRaises(TypeError, len, repeat(None)) - -class TestXrange(TestInvariantWithoutMutations): - - def setUp(self): - self.it = iter(xrange(n)) - -class TestXrangeCustomReversed(TestInvariantWithoutMutations): - - def setUp(self): - self.it = reversed(xrange(n)) - -class TestTuple(TestInvariantWithoutMutations): - - def setUp(self): - self.it = iter(tuple(xrange(n))) - -## ------- Types that should not be mutated during iteration ------- - -class TestDeque(TestTemporarilyImmutable): - - def setUp(self): - d = deque(xrange(n)) - self.it = iter(d) - self.mutate = d.pop - -class TestDequeReversed(TestTemporarilyImmutable): - - def setUp(self): - d = deque(xrange(n)) - self.it = reversed(d) - self.mutate = d.pop - -class TestDictKeys(TestTemporarilyImmutable): - - def setUp(self): - d = dict.fromkeys(xrange(n)) - self.it = iter(d) - self.mutate = d.popitem - -class TestDictItems(TestTemporarilyImmutable): - - def setUp(self): - d = dict.fromkeys(xrange(n)) - self.it = d.iteritems() - self.mutate = d.popitem - -class TestDictValues(TestTemporarilyImmutable): - - def setUp(self): - d = dict.fromkeys(xrange(n)) - self.it = d.itervalues() - self.mutate = d.popitem - -class TestSet(TestTemporarilyImmutable): - - def setUp(self): - d = set(xrange(n)) - self.it = iter(d) - self.mutate = d.pop - -## ------- Types that can mutate during iteration ------- - -class TestList(TestInvariantWithoutMutations): - - def setUp(self): - self.it = iter(range(n)) - - def test_mutation(self): - d = range(n) - it = iter(d) - it.next() - it.next() - self.assertEqual(len(it), n-2) - d.append(n) - self.assertEqual(len(it), n-1) # grow with append - d[1:] = [] - self.assertEqual(len(it), 0) - self.assertEqual(list(it), []) - d.extend(xrange(20)) - self.assertEqual(len(it), 0) - -class TestListReversed(TestInvariantWithoutMutations): - - def setUp(self): - self.it = reversed(range(n)) - - def test_mutation(self): - d = range(n) - it = reversed(d) - it.next() - it.next() - self.assertEqual(len(it), n-2) - d.append(n) - self.assertEqual(len(it), n-2) # ignore append - d[1:] = [] - self.assertEqual(len(it), 0) - self.assertEqual(list(it), []) # confirm invariant - d.extend(xrange(20)) - self.assertEqual(len(it), 0) - -## -- Check to make sure exceptions are not suppressed by __length_hint__() - - -class BadLen(object): - def __iter__(self): return iter(range(10)) - def __len__(self): - raise RuntimeError('hello') - -class BadLengthHint(object): - def __iter__(self): return iter(range(10)) - def __length_hint__(self): - raise RuntimeError('hello') - -class NoneLengthHint(object): - def __iter__(self): return iter(range(10)) - def __length_hint__(self): - return None - -class TestLengthHintExceptions(unittest.TestCase): - - def test_issue1242657(self): - self.assertRaises(RuntimeError, list, BadLen()) - self.assertRaises(RuntimeError, list, BadLengthHint()) - self.assertRaises(RuntimeError, [].extend, BadLen()) - self.assertRaises(RuntimeError, [].extend, BadLengthHint()) - self.assertRaises(RuntimeError, zip, BadLen()) - self.assertRaises(RuntimeError, zip, BadLengthHint()) - self.assertRaises(RuntimeError, filter, None, BadLen()) - self.assertRaises(RuntimeError, filter, None, BadLengthHint()) - self.assertRaises(RuntimeError, map, chr, BadLen()) - self.assertRaises(RuntimeError, map, chr, BadLengthHint()) - b = bytearray(range(10)) - self.assertRaises(RuntimeError, b.extend, BadLen()) - self.assertRaises(RuntimeError, b.extend, BadLengthHint()) - - def test_invalid_hint(self): - # Make sure an invalid result doesn't muck-up the works - self.assertEqual(list(NoneLengthHint()), list(range(10))) - - -def test_main(): - unittests = [ - TestRepeat, - TestXrange, - TestXrangeCustomReversed, - TestTuple, - TestDeque, - TestDequeReversed, - TestDictKeys, - TestDictItems, - TestDictValues, - TestSet, - TestList, - TestListReversed, - TestLengthHintExceptions, - ] - test_support.run_unittest(*unittests) - -if __name__ == "__main__": - test_main() |