cdgriffith / Box

Python dictionaries with advanced dot notation access
https://github.com/cdgriffith/Box/wiki
MIT License
2.61k stars 106 forks source link

Issue with nested Boxes in 5.1.0 #162

Closed TortelliniLeap closed 2 years ago

TortelliniLeap commented 4 years ago
from box import Box

parent_box = Box()

keys = ["a", "b", "c"]

for key in keys:
    sub_box = parent_box[key] = Box()
    sub_box["test"] = "test"
    print(sub_box)

print()
print(parent_box)

Output with version 5.1.0:

{'test': 'test'}
{'test': 'test'}
{'test': 'test'}

{'a': {}, 'b': {}, 'c': {}}

Output with version 4.7.3:

{'test': 'test'}
{'test': 'test'}
{'test': 'test'}

{'a': {'test': 'test'}, 'b': {'test': 'test'}, 'c': {'test': 'test'}}
cdgriffith commented 4 years ago

I will write out a bit more detail about why this happens in a bit and make sure it is better covered in the wiki, just wanted to reply quick that this is happening as designed and won't be able to be changed. However it can be prevented if you pass in box_intact_types=[Box] to parent_box = Box(box_intact_types=[Box])

What happens is every time an object of type dict or list is added to the box, it has to be destructively recreated to ensure everything is linked up properly within the box to use all its special sauce, unless specifically told otherwise.

sub_box = parent_box[key] = Box() is equal to:

temp_var = Box()   # id ...336

# link that pointer to another variable
sub_box = temp_var  # id ...336

# copy object with id ...336 and create new pointer
parent_box[key] = temp_var  # id ...825

The possible workaround are

  1. use box_intact_types
  2. use default_box if applicable
  3. avoid chained assignment when adding objects to box