Proposal: SimpleNamespace "recursive" parameter

Marco Sulla Marco.Sulla.Python at gmail.com
Fri Aug 14 00:39:58 EDT 2020


This seems to work:

from types import SimpleNamespace
from collections.abc import Iterable

def isIterableNotStr(arg):
    return isinstance(arg, Iterable) and not isinstance(arg, str)

class DeepNamespace(SimpleNamespace):
    def namespacesFromIterable(self, arg):
        vals = []
        changed = False

        for x in arg:
            not_iterable = True

            try:
                x.items
                value = type(self)(**x)
                changed = True
                not_iterable = False
            except AttributeError:
                if isIterableNotStr(x):
                    value = self.namespacesFromIterable(x)
                    changed = True
                    not_iterable = False

            if not_iterable:
                value = x

            vals.append(value)

        if changed:
            return tuple(vals)

        return arg


    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        for k, v in kwargs.items():
            try:
                v.items
            except AttributeError:
                if isIterableNotStr(v):
                    self.__setattr__(k, self.namespacesFromIterable(v))
            else:
                self.__setattr__(k, type(self)(**v))

Notice that if the dict contains at any level an iterable that is not
a string or a dict-like object, this is converted to a tuple. Probably
there's a smarter way to maintain the original iterable type.


More information about the Python-list mailing list