Last active
November 25, 2022 17:37
-
-
Save juftin/77205837df489e957705976fce25da3d to your computer and use it in GitHub Desktop.
Recursive SimpleNamespace Extension
This file contains 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
""" | |
Extending the SimpleNamespace Class | |
""" | |
import datetime | |
from functools import singledispatch | |
from types import SimpleNamespace | |
from typing import Any | |
class CustomNameSpace(SimpleNamespace): | |
""" | |
Extension of the SimpleNamespace Class that allows subscription | |
""" | |
def __getitem__(self, item): | |
return self.__getattribute__(item) | |
def __setitem__(self, key, value): | |
self.__setattr__(key, value) | |
@staticmethod | |
def data_to_namespace(data: Any) -> Any: | |
""" | |
Recursively Convert Dictionaries (or a list of dicts) into SimpleNamespace objects | |
Non dictionary objects are returned as they are | |
""" | |
@singledispatch | |
def wrap_namespace(ob): | |
return ob | |
@wrap_namespace.register(dict) | |
def _wrap_dict(ob): | |
return CustomNameSpace(**{k: wrap_namespace(v) for k, v in ob.items()}) | |
@wrap_namespace.register(list) | |
@wrap_namespace.register(set) | |
@wrap_namespace.register(tuple) | |
def _wrap_list(ob): | |
return [wrap_namespace(v) for v in ob] | |
return wrap_namespace(data) | |
# Convert our classmethod to an importable, standalone function | |
data_to_namespace = CustomNameSpace.data_to_namespace | |
if __name__ == "__main__": | |
# Try it out on some nested data | |
now = datetime.datetime.now() | |
data = [ | |
{ | |
"Nested": { | |
"Dictionaries": { | |
"Are": { | |
"Tricky": now | |
} | |
} | |
} | |
} | |
] | |
namespace = data_to_namespace(data=data) | |
# Here's how we would access a dictionary | |
assert data[0]["Nested"]["Dictionaries"]["Are"]["Tricky"] == now | |
# Here's how we can now access the dictionary items as attributes | |
assert namespace[0].Nested.Dictionaries.Are.Tricky == now | |
# We can also access them like a dictionary too | |
assert namespace[0]["Nested"]["Dictionaries"]["Are"]["Tricky"] == now |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment