Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create subkeys with dots as needed #214

Open
csm10495 opened this issue Nov 3, 2021 · 3 comments
Open

Create subkeys with dots as needed #214

csm10495 opened this issue Nov 3, 2021 · 3 comments

Comments

@csm10495
Copy link

csm10495 commented Nov 3, 2021

Hey,

I noticed this line in the docs:

Be aware, if those sub boxes didn't exist as planned, a new key with that value would be created instead

So if i do:

In [1]: from box import Box

In [2]: b = Box(box_dots=True)

In [3]: b['a.c'] = 123

In [4]: b
Out[4]: <Box: {'a.c': 123}>

In [5]: b.a.c
---------------------------------------------------------------------------
BoxKeyError                               Traceback (most recent call last)
<ipython-input-5-746fa1d52262> in <module>
----> 1 b.a.c

~/python3.7/site-packages/box/box.py in __getattr__(self, item)
    488             if self._box_config["default_box"]:
    489                 return self.__get_default(item, attr=True)
--> 490             raise BoxKeyError(str(err)) from None
    491         return value
    492

BoxKeyError: "'Box' object has no attribute 'a'"

Is there a way to make it so that it recursively makes boxes as needed to make it to the final key?

@cdgriffith
Copy link
Owner

Currently no, but I am not opposed to that as a feature.

@csm10495
Copy link
Author

csm10495 commented Nov 4, 2021

Found a 'cheap' way to do this:


In [1]: from box import Box

In [2]: box_data = Box(box_dots=True, default_box=True)

In [3]: box_data.a.b.c = 1

In [4]: box_data.a.b.c
Out[4]: 1

In [5]: v = 1234

In [6]: exec('box_data.c.a.b = v', locals())

In [7]: box_data.c.a.b
Out[7]: 1234

The exec mechanism can be used if you have a key as a string too:

In [8]: key = 'z.y.x'

In [9]: exec(f'box_data.{key} = v', locals())

In [10]: box_data.z.y.x
Out[10]: 1234

Optimally a better way wouldn't require something like an exec call.

@cdgriffith
Copy link
Owner

With Box 7 going to have it so you can combine default_box and box_dots as you described and have it work with dots in strings as well. So:

a = Box(box_dots=True, default_box=True)
a['b.c'] = 3 
# Box({'b': {'c': 3}})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants