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

Support for tracking the box "namespace" #226

Closed
JacobHayes opened this issue Aug 10, 2022 · 6 comments
Closed

Support for tracking the box "namespace" #226

JacobHayes opened this issue Aug 10, 2022 · 6 comments

Comments

@JacobHayes
Copy link
Contributor

I have some nested Boxes using an overridden __convert_and_store in a subclass to convert values to an expected type (eg: I want all values to be an int or some other custom class). For that conversion, I would like to know the "namespace" of the Box/value in order to reference it in the conversion and show nicer error messages.

For example, when handling the conversion of 5 in the example below:

box = MyBox({"a": {"b": {"c": 5}}})

I would like to know that I'm assigning to ("a", "b", "c").

This is quite hard to setup only in a subclass because of the recursive value conversion (and copying) during __init__ and conversion doesn't give a good hook to intercept after the box is created, but before sub-boxes are created.

I think the easiest way to support this is by adding a box_path or box_namespace param to __init__ (defaulting to ()) and then into _box_config, which can be passed through (and extended) in __get_default and __convert_and_store when creating sub-boxes.

Is this something you'd be open to? I'd be happy to make a PR for this if so!

@ipcoder
Copy link

ipcoder commented Dec 20, 2022

Actually, I have a similar problem, though formulated a bit differently.
May be this angle could be useful for you as well.

I use Box heavily with box_dots, and find it convenient to think about keys as paths, and operate on them accordingly.

So I have sub-classed Box (to TBox) where box_dots=True by default, and added several enhancement useful for this mode.

First, I re-implemented __setitem__ to allow:

b = Box()
b['z.y.z'] = "Hi" 
# b == {'x': {'y': {'z': 1}}}

Such initializations are possible:

b = TBox({
    'x.y.z': 1,
    'x.y.w': 2,
    'x.m': 100,
    'x.n': {'k.p':200}
})

In general, I believe working with dots should be symmetrical for reading and writing.
Now a = b["x.y"'] reads b.x.y item, but b["x.y"] = a writes to a '"x.y"' key of b.

Implementation is rather straightforward and does not seem to conflict with the rest of Box functionality:

class TBox(Box):

   ...
    def __setitem__(self, key, value):
        if '.' in key:
            node, tail = key.split('.', 1)
            if node not in self:
                super().__setitem__(node, {})
            self[node].__setitem__(tail, value)
        else:
            super().__setitem__(key, value)

What do you think about making that default behavior in box_dots mode?
I saw several issues open on that, except of mine: #170, #214

I am also missing b.x.y.z = a which does not work without default_box=True , which itself is not really useful, due to issues like #236, #192 (also here comment #164 (comment)).

But before some solution for the default_box problem is found, b['x.y.z'] = a does a trick as the difference is mainly syntactic.

@nishikantparmariam
Copy link

I think the easiest way to support this is by adding a box_path or box_namespace param

+1 for this feature.

@JacobHayes
Copy link
Contributor Author

I revived #227 as #240 for the box_namespace config.

@cdgriffith
Copy link
Owner

Adding this feature in Box 7! Please test and give feedback if possible pip install python-box[all]~=7.0.0rc0 (Thanks again @JacobHayes for the PR! )

@JacobHayes
Copy link
Contributor Author

JacobHayes commented Jan 31, 2023

7.0.0rc0 nicely replaced my workarounds, fixing a couple bugs! Though, I did have some issues with some of the wheels.

cdgriffith added a commit that referenced this issue Feb 4, 2023
* Adding #169 default functions with the box_instance and key parameter (thanks to Коптев Роман Викторович)
* Adding #170 Be able to initialize with a flattened dict - by using DDBox (thanks to Ash A.)
* Adding #192 box_dots treats all keys with periods in them as separate keys (thanks to Rexbard)
* Adding #211 support for properties and setters in subclasses (thanks to Serge Lu and David Aronchick)
* Adding #226 namespace to track changes to the box (thanks to Jacob Hayes)
* Adding #236 iPython detection to prevent adding attribute lookup words (thanks to Nishikant Parmar)
* Adding #238 allow ``|`` and ``+`` for frozen boxes (thanks to Peter B)
* Adding new DDBox class (Default Dots Box) that is a subclass of SBox
* Fixing #235 how ``|`` and ``+`` updates were performed for right operations (thanks to aviveh21)
* Fixing #234 typos (thanks to Martin Schorfmann)
* Fixing no implicit optionals with type hinting
@cdgriffith
Copy link
Owner

Added in 7.0.0

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

Successfully merging a pull request may close this issue.

4 participants