[](https://pypi.org/project/dictat/)
[](https://gitlab.com/janoskut/dictat/-/releases)
[](https://gitlab.com/janoskut/dictat/-/commits/main)
[](https://gitlab.com/janoskut/dictat/-/commits/main)
[](https://unlicense.org/)
[]()
`Adict` is an attribute-accessible dynamic dict wrapper, which allows to access dict items in
attribute notation (".") and allows friendly checks for non-existing items.
`Adict` is not an _extension_ of Python's `dict` (as for example
[adict](https://test.pypi.org/project/adict/) and [dict](https://test.pypi.org/project/dict/)),
but a _wrapper_ around `dict` objects. This allows to use attribute syntax not only for objects
created using the `Adict()` constructor, but also for child dictionaries, which are automatically
wrapped into an `Adict` when they're returned.
# Features
- Default `dict` behavior
- Full wrapping of nested `dict`s
- Fail-safe attribute notation (`adict.key`) doesn't raise `KeyError`
- Save traversing using parenthesis syntax (`('key')`)
- Supports nested dicts
- Supports JSON encoding
# Installation
```sh
pip install dictat
```
# Examples
```py
from dictat import Adict
dict1 = Adict()
print('noob' in dict1) # False
print(dict1.noob) # None - doesn't fail
# print(dict1['noob']) # raises KeyError - default dict behavior
dict1.noob = 'me'
print(dict1['noob']) # "me" - dict notation
print(dict1.noob) # "me" -, attribute notation
dict1.sub = {}
dict1.sub.dict = {'noobs': ['me', 'you']}
print(dict1.sub.dict.noobs[1]) # "you"
dict2 = {'noob': 'me', 'sub': {'you': 'noob'}}
dict3 = Adict(dict2) # construct around existing dict
print('noob' in dict3) # True
print(dict3['noob']) # "me", dict notation
print(dict3.noob) # "me", attribute notation
print(dict3.sub.you) # "noob', nested attribute notation
```
## Safe traversing using paranthesis syntax
At the cost of not having `None` values, the `()` operator allows key access, which always returns
a valid (empty) `Adict` instance when the key doesn't exist. This allowes to traverse `dict`s
into depper levels, without intermediate `None` checks. This syntax is basically an abbreviation
of the `dict.get(key, default)` function, but has the additional feature to again wrap default
`dict` values into `Adict(dict)` results.
```py
dd = Adict({'noob': 'me', 'sub': {'you': 'noob'}})
print(dd('sub')('you')) # "noob"
# is equivalent to
print(dd('sub', {})('you', {}))
# is equiivalent to
print(dd.get('sub', {}).get('you', {}))
print(dd('nokey')) # {} (isinstance Adict)
print(dd('nokey', {})) # {} (isinstance Adict)
print(dd('nokey', None) # None
```
## JSON encoding
```py
from dictat import Adict, JsonEncoder
import json
import pathlib
adict = Adict()
adict.key = 'string'
adict.sub = dict(subkey='subvalue', obj=object())
adict.path = pathlib.Path('somepath') # normally not JSON serializable
dump = json.dumps(adict, cls=JsonEncoder)
print(dump)
# {"key": "string", "sub": {"subkey": "subvalue"}, "path": "somepath"}
```