At work I massage a lot of JSON and YAML data. One of the annoyances of
this is that all imported data is handled as `dict`s, so you end up with
things horrible to type like:

```python
virt_data['cluster']['ssh-authorized-keys'] = data['cluster'].get('ssh-authorized-keys', [])
```

Lots of strings and dict indexing. Wouldn't if be nicer to write it as:

```python
virt_data.cluster.ssh_authorized_keys = data.cluster.get('ssh-authorized-keys', [])
```

After a while, it feels better.

So, like any Python developer who likes to play with these things, I
tried to write a class that would implement object attribute access and
dict indexing at the same time. The latter should allow for using as
input for `yaml.dump()` and `json.dump()` transparently.

I wrote 110 lines of heavily tested code. All went fine until I found a
bug in `__deepcopy__()` that meant to, once more, do recursion in case of
`list`s or other `dict`s. To be honest, I have a lot of work load
right now, and I didn't have the energy to factor out this recursing code
from other methods.

Meanwhile, a few weeks ago I saw a new package in Debian called
[`python-box`](https://github.com/cdgriffith/Box), which promised implementing exactly that. I wrote a note
about testing it and moved on. This looked like the right moment to do
exactly that.

Long story short, it worked perfectly. I replaced most of my class with
`box.Box` by inheriting from it, I kept the only method I had that didn't
come from `dict`, and it worked almost as expected. The only difference
was that `Box` tries to keep attribute access and dict indexing completely
separated. Let me explain.

In the example above, you'll see that `['ssh-authorized-keys']` was
replaced by `.ssh_authorized_keys`. The change from `-` to `_` is needed
because identifiers (including attribute names) can't have `-`s. The
`dict`/`object` duality also means that you can access elements with the
`getattr()` function and the `.get()` method. What `python-box` does, which
I wasn't in my original class, is
to only allow the `_` variant with `getattr()`, and only the `-` variant
with `get()`. I think I changed two lines of code, including one test,
and all was fine.
´
So, in conclusion, if you ever want and/or need `object`/`dict` duality,
go for `python-box`. It has a decent release cadence, not many open
issues, `cdgriffith` seems to answer promptly. Be sure of checking out
[its limitations](https://github.com/cdgriffith/Box#limitations) before
using it.


