forked from tableau/document-api-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmultilookup_dict.py
More file actions
66 lines (50 loc) · 1.74 KB
/
multilookup_dict.py
File metadata and controls
66 lines (50 loc) · 1.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import weakref
_no_default_value = object()
def _resolve_value(key, value):
retval = None
try:
if hasattr(value, 'get'):
retval = value.get(key, None)
if retval is None:
retval = getattr(value, key, None)
except AttributeError:
# We should never hit this.
retval = None
return retval
def _build_index(key, d):
return {_resolve_value(key, v): k
for k, v in d.items()
if _resolve_value(key, v) is not None}
# TODO: Improve this to be more generic
class MultiLookupDict(dict):
def __init__(self, args=None):
if args is None:
args = {}
super(MultiLookupDict, self).__init__(args)
self._indexes = {
'alias': weakref.WeakValueDictionary(),
'caption': weakref.WeakValueDictionary()
}
self._populate_indexes()
def _populate_indexes(self):
self._indexes['alias'] = _build_index('alias', self)
self._indexes['caption'] = _build_index('caption', self)
def _get_real_key(self, key):
if key in self._indexes['alias']:
return self._indexes['alias'][key]
if key in self._indexes['caption']:
return self._indexes['caption'][key]
return key
def __setitem__(self, key, value):
real_key = self._get_real_key(key)
dict.__setitem__(self, real_key, value)
def get(self, key, default_value=_no_default_value):
try:
return self[key]
except KeyError:
if default_value is not _no_default_value:
return default_value
raise
def __getitem__(self, key):
real_key = self._get_real_key(key)
return dict.__getitem__(self, real_key)