Files
notifications-api/notifications_utils/insensitive_dict.py

60 lines
1.7 KiB
Python
Raw Normal View History

from functools import lru_cache
from ordered_set import OrderedSet
class InsensitiveDict(dict):
"""
`InsensitiveDict` behaves like an ordered dictionary, except it normalises
case, whitespace, hypens and underscores in keys.
In other words,
InsensitiveDict({'FIRST_NAME': 'example'}) == InsensitiveDict({'first name': 'example'})
>>> True
"""
KEY_TRANSLATION_TABLE = {ord(c): None for c in " _-"}
def __init__(self, row_dict):
for key, value in row_dict.items():
self[key] = value
@classmethod
def from_keys(cls, keys):
"""
This behaves like `dict.from_keys`, except:
- it normalises the keys to ignore case, whitespace, hypens and
underscores
- it stores the original, unnormalised key as the value of the
item so it can be retrieved later
"""
return cls({key: key for key in keys})
def keys(self):
return OrderedSet(super().keys())
def __getitem__(self, key):
return super().__getitem__(self.make_key(key))
def __setitem__(self, key, value):
super().__setitem__(self.make_key(key), value)
def __contains__(self, key):
return super().__contains__(self.make_key(key))
def get(self, key, default=None):
return self[key] if key in self else default
def copy(self):
return self.__class__(super().copy())
def as_dict_with_keys(self, keys):
return {key: self.get(key) for key in keys}
@staticmethod
@lru_cache(maxsize=32, typed=False)
def make_key(original_key):
if original_key is None:
return None
return original_key.translate(InsensitiveDict.KEY_TRANSLATION_TABLE).lower()