Project

General

Profile

1
# Dictionaries
2

    
3
import itertools
4
import UserDict
5

    
6
import util
7

    
8
def is_dict(value): return hasattr(value, 'keys')
9

    
10
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
class IdDict(dict):
22
    '''A dict that stores objects by id()'''
23
    
24
    def add(self, *values):
25
        for value in values: self[id(value)] = value
26
        return self
27
    
28
    def add_vars(self, vars_): return self.add(*vars_.values())
29

    
30
class MergeDict:
31
    '''A dict that checks each of several dicts'''
32
    
33
    def __init__(self, *dicts): self.dicts = dicts
34
    
35
    def __getitem__(self, key):
36
        for dict_ in self.dicts:
37
            try: return dict_[key]
38
            except KeyError: pass
39
        raise # reraise last KeyError
40

    
41

    
42
class AttrsDictView:
43
    '''A dict view of an object's attributes
44
    @pre If you want __iter__() to work, value must have a __dict__
45
    '''
46
    
47
    def __init__(self, value): self.value = value
48
    
49
    def __iter__(self): return iter(self.value.__dict__)
50
    
51
    def __getitem__(self, key): return getattr(self.value, key)
52

    
53
def make_hashable(value):
54
    if isinstance(value, list): value = tuple(value)
55
    elif isinstance(value, dict): value = util.NamedTuple(**value)
56
    return value
57

    
58
def join(dict0, dict1):
59
    '''Joins dict0 (A->B mapping) to dict1 (B->C mapping) SQL-style.
60
    If a value in dict0 has no key in dict1, uses the value itself.
61
    '''
62
    new_dict = {}
63
    for out, in_ in dict0.iteritems():
64
        new_dict[out] = dict1.get(in_, in_) # use in_ if no match found
65
    return new_dict
(11-11/36)