~canonical-django/canonical-django/project-template

« back to all changes in this revision

Viewing changes to trunk/python-packages/django/utils/itercompat.py

  • Committer: Matthew Nuzum
  • Date: 2008-11-13 05:46:03 UTC
  • Revision ID: matthew.nuzum@canonical.com-20081113054603-v0kvr6z6xyexvqt3
adding to version control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
"""
 
6
 
 
7
import itertools
 
8
 
 
9
def compat_tee(iterable):
 
10
    """
 
11
    Return two independent iterators from a single iterable.
 
12
 
 
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)
 
28
 
 
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
 
47
 
 
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]
 
53
 
 
54
if hasattr(itertools, 'tee'):
 
55
    tee = itertools.tee
 
56
else:
 
57
    tee = compat_tee
 
58
if hasattr(itertools, 'groupby'):
 
59
    groupby = itertools.groupby
 
60
 
 
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
 
69
 
 
70
def sorted(in_value):
 
71
    "A naive implementation of sorted"
 
72
    out_value = in_value[:]
 
73
    out_value.sort()
 
74
    return out_value
 
75