Created
November 26, 2024 12:45
-
-
Save SamWolski/ef3b0258ba504a558a87096a370501a0 to your computer and use it in GitHub Desktop.
Python dict with fallback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import UserDict | |
from collections.abc import Mapping | |
from typing import Optional | |
############################################################################### | |
class FallbackDict(UserDict): | |
"""A dict-like which falls back on another mapping for missing keys | |
""" | |
def __init__(self, fallback: Optional[Mapping] = None, **kwargs): | |
self._fallback = fallback if fallback is not None else {} | |
super().__init__(**kwargs) | |
def __getitem__(self, key): | |
return self.data.get(key, self._fallback[key]) | |
def __repr__(self) -> str: | |
rstr = repr(self.data) | |
if self._fallback: | |
rstr += f" with fallback {repr(self._fallback)}" | |
return rstr | |
class NestedFallbackDict(UserDict): | |
"""A dict-like which falls back on another mapping for missing keys, with | |
recursive behaviour for nested mappings | |
If the value to be fetched is a Mapping subclass, a new NestedFallbackDict | |
is constructed out of the fetched Mappings in both the target and fallback | |
dicts. | |
This can be thought of as a deepmerged version of the FallbackDict. | |
""" | |
def __init__(self, fallback: Optional[Mapping] = None, **kwargs): | |
self._fallback = fallback if fallback is not None else {} | |
super().__init__(**kwargs) | |
def __getitem__(self, key): | |
if key in self.data: | |
value = self.data[key] | |
if isinstance(value, Mapping): | |
value_fallback = self._fallback.get(key, {}) | |
value_nfd = NestedFallbackDict(value_fallback) | |
value_nfd.update(value) | |
return value_nfd | |
return value | |
else: | |
return self._fallback[key] | |
def __repr__(self) -> str: | |
rstr = repr(self.data) | |
if self._fallback: | |
rstr += f" with fallback {repr(self._fallback)}" | |
return rstr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment