Added some tests to modeltests/many_to_one that demonstrate a post-queryset-refactor...
[fdr-django.git] / django / utils / itercompat.py
blob3742d6c5d8e09406d3a9a4480ae8b62922c5071b
1 """
2 Providing iterator functions that are not in all version of Python we support.
3 Where possible, we try to use the system-native version and only fall back to
4 these implementations if necessary.
5 """
7 import itertools
9 def compat_tee(iterable):
10 """
11 Return two independent iterators from a single iterable.
13 Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
14 """
15 # Note: Using a dictionary and a list as the default arguments here is
16 # deliberate and safe in this instance.
17 def gen(next, data={}, cnt=[0]):
18 dpop = data.pop
19 for i in itertools.count():
20 if i == cnt[0]:
21 item = data[i] = next()
22 cnt[0] += 1
23 else:
24 item = dpop(i)
25 yield item
26 next = iter(iterable).next
27 return gen(next), gen(next)
29 def groupby(iterable, keyfunc=None):
30 """
31 Taken from http://docs.python.org/lib/itertools-functions.html
32 """
33 if keyfunc is None:
34 keyfunc = lambda x:x
35 iterable = iter(iterable)
36 l = [iterable.next()]
37 lastkey = keyfunc(l[0])
38 for item in iterable:
39 key = keyfunc(item)
40 if key != lastkey:
41 yield lastkey, l
42 lastkey = key
43 l = [item]
44 else:
45 l.append(item)
46 yield lastkey, l
48 # Not really in itertools, since it's a builtin in Python 2.4 and later, but it
49 # does operate as an iterator.
50 def reversed(data):
51 for index in xrange(len(data)-1, -1, -1):
52 yield data[index]
54 if hasattr(itertools, 'tee'):
55 tee = itertools.tee
56 else:
57 tee = compat_tee
58 if hasattr(itertools, 'groupby'):
59 groupby = itertools.groupby
61 def is_iterable(x):
62 "A implementation independent way of checking for iterables"
63 try:
64 iter(x)
65 except TypeError:
66 return False
67 else:
68 return True