Project

General

Profile

1 1876 aaronmk
# Dictionaries
2
3 1885 aaronmk
import itertools
4 2651 aaronmk
import UserDict
5 1876 aaronmk
6 1907 aaronmk
import util
7
8 2657 aaronmk
def is_dict(value): return hasattr(value, 'keys')
9 2649 aaronmk
10 2651 aaronmk
class DictProxy(UserDict.DictMixin):
11
    '''A proxy that forwards all accesses to an inner dict.'''
12
13
    def __init__(self, inner): self.inner = inner
14
15
    def keys(self): return self.inner.keys()
16
17
    def __getitem__(self, key): return self.inner[key]
18
19
    def __setitem__(self, key, value): self.inner[key] = value
20
21 2670 aaronmk
class IdCompared:
22
    '''A value that's compared using `is` instead of ==.
23
    Do not use this for strings as they are interned, causing `is` to have the
24
    same meaning as ==.
25
    '''
26
27
    def __init__(self, value): self.value = value
28
29
    def __eq__(self, other):
30
        return (other != None and other.__class__ == self.__class__
31
            and other.value is self.value)
32
33
    def __hash__(self): return id(self.value)
34
35 1885 aaronmk
class IdDict(dict):
36
    '''A dict that stores objects by id()'''
37
38
    def add(self, *values):
39
        for value in values: self[id(value)] = value
40
        return self
41
42
    def add_vars(self, vars_): return self.add(*vars_.values())
43
44 1876 aaronmk
class MergeDict:
45
    '''A dict that checks each of several dicts'''
46 1885 aaronmk
47 1876 aaronmk
    def __init__(self, *dicts): self.dicts = dicts
48
49
    def __getitem__(self, key):
50
        for dict_ in self.dicts:
51
            try: return dict_[key]
52
            except KeyError: pass
53
        raise # reraise last KeyError
54 1907 aaronmk
55 1911 aaronmk
56
class AttrsDictView:
57
    '''A dict view of an object's attributes
58
    @pre If you want __iter__() to work, value must have a __dict__
59
    '''
60
61
    def __init__(self, value): self.value = value
62
63
    def __iter__(self): return iter(self.value.__dict__)
64
65
    def __getitem__(self, key): return getattr(self.value, key)
66
67 1907 aaronmk
def make_hashable(value):
68
    if isinstance(value, list): value = tuple(value)
69
    elif isinstance(value, dict): value = util.NamedTuple(**value)
70
    return value
71 2384 aaronmk
72
def join(dict0, dict1):
73
    '''Joins dict0 (A->B mapping) to dict1 (B->C mapping) SQL-style.
74
    If a value in dict0 has no key in dict1, uses the value itself.
75
    '''
76
    new_dict = {}
77
    for out, in_ in dict0.iteritems():
78
        new_dict[out] = dict1.get(in_, in_) # use in_ if no match found
79
    return new_dict