Python box: dict/object duality
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:
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:
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
, 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 before
using it.