Skip to content

Commit

Permalink
Simplify AttrDict and create a separated Settings class
Browse files Browse the repository at this point in the history
  • Loading branch information
leogama committed Jun 10, 2022
1 parent ab1e5e7 commit 2ea720a
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 34 deletions.
34 changes: 4 additions & 30 deletions dill/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,8 @@
import logging
logger = logging.getLogger('dill._utils')

import inspect
from functools import partialmethod

class AttrDict(dict):
"""syntactic sugar for accessing dictionary items"""
_CAST = object() # singleton
def __init__(self, *args, **kwargs):
data = args[0] if len(args) == 2 and args[1] is self._CAST else dict(*args, **kwargs)
for key, val in tuple(data.items()):
if isinstance(val, dict) and not isinstance(val, AttrDict):
data[key] = AttrDict(val, self._CAST)
super().__setattr__('_data', data)
def _check_attr(self, name):
try:
super().__getattribute__(name)
Expand All @@ -33,33 +23,17 @@ def _check_attr(self, name):
def __getattr__(self, key):
# This is called only if dict.__getattribute__(key) fails.
try:
return self._data[key]
return self[key]
except KeyError:
raise AttributeError("'AttrDict' object has no attribute %r" % key)
def __setattr__(self, key, value):
self._check_attr(key)
if isinstance(value, dict):
self._data[key] = AttrDict(value, self._CAST)
else:
self._data[key] = value
self[key] = value
def __delattr__(self, key):
self._check_attr(key)
del self._data[key]
def __proxy__(self, method, *args, **kwargs):
return getattr(self._data, method)(*args, **kwargs)
del self[key]
def __reduce__(self):
return AttrDict, (self._data,)
def copy(self):
# Deep copy.
copy = AttrDict(self._data)
for key, val in tuple(copy.items()):
if isinstance(val, AttrDict):
copy[key] = val.copy()
return copy

for method, _ in inspect.getmembers(dict, inspect.ismethoddescriptor):
if method not in vars(AttrDict) and method not in {'__getattribute__', '__reduce_ex__'}:
setattr(AttrDict, method, partialmethod(AttrDict.__proxy__, method))
return type(self), (dict(self),)


### Namespace filtering
Expand Down
3 changes: 0 additions & 3 deletions dill/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,6 @@ def dump_session(filename: Union[PathLike, BytesIO] = '/tmp/session.pkl',
#NOTE: *must* run before _filter_objects()
main = _stash_modules(main)
main = _filter_objects(main, exclude, include, obj=original_main)

print(list(vars(main)))

if hasattr(filename, 'write'):
f = filename
else:
Expand Down
29 changes: 28 additions & 1 deletion dill/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,34 @@
from pickle import DEFAULT_PROTOCOL
except ImportError:
from pickle import HIGHEST_PROTOCOL as DEFAULT_PROTOCOL
from ._utils import AttrDict as Settings, ExcludeRules
from collections.abc import MutableMapping
from ._utils import AttrDict, ExcludeRules

class Settings(AttrDict):
"""allow multiple level attribute access"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for key, value in tuple(self.items()):
if isinstance(value, MutableMapping):
self[key] = Settings(value)
@staticmethod
def _cast_dict(obj):
return Settings(obj) if isinstance(obj, MutableMapping) else obj
def __setitem__(self, key, value):
super().__setitem__(key, self._cast_dict(value))
def setdefault(self, key, default=None):
super().setdefault(key, self._cast_dict(default))
def update(self, *args, **kwargs):
super().update(Settings(*args, **kwargs))
def __setattr__(self, key, value):
super().__setattr__(key, _cast_dict(value))
def copy(self):
# Deep copy.
copy = Settings(self)
for key, value in self.items():
if isinstance(value, Settings):
copy[key] = value.copy()
return copy

settings = Settings({
#'main' : None,
Expand Down

0 comments on commit 2ea720a

Please sign in to comment.