extradict icon indicating copy to clipboard operation
extradict copied to clipboard

Issue with index 0 of deep sequence within NestedData

Open netgirard opened this issue 1 year ago • 3 comments

Having an issue with index 0 of a NestedList inside a NestedDict when I create it from flattened keys. I would expect this behavior:

Python 3.9.5 (default, Nov 23 2021, 15:27:38) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from extradict import NestedData
>>> flat ={'list.0' : 'list0', 'list.1': 'list1', 'list.2': 'list2'}
>>> test = NestedData(flat)
>>> 
>>> test2 = NestedData()
>>> test2['list'] = []
>>> test2['list'].append('list0')
>>> test2['list'].append('list1')
>>> test2['list'].append('list2')
>>> 
>>> test['list.1']
'list1'
>>> test2['list.1']
'list1'
>>> test['list.2']
'list2'
>>> test2['list.2']
'list2'
>>> test['list.0']
'list0'
>>> test2['list.0']
'list0'

Instead, I get a KeyError only on test['list.0'] of below:

>>> test['list.0']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/e5589509/IT3-PaaS/.direnv/python-3.9.5/lib/python3.9/site-packages/extradict/nested_data.py", line 96, in __getitem__
    return self[key][subpath]
  File "/home/e5589509/IT3-PaaS/.direnv/python-3.9.5/lib/python3.9/site-packages/extradict/nested_data.py", line 229, in __getitem__
    wrapped = self.wrap(self.data[int(index)])
KeyError: 0

Hopefully I'm not missing something obvious.

Also tried on Python 3.12.2, both using extradict 0.6.0

netgirard avatar Mar 28 '24 18:03 netgirard

Sorry for the delay. No really - I had not thought on importing dictionaries with keys containing "." when I made the data structure - it is almost chance that it works for the list.1 and list.2 indices in your example.

Do you have the need to import data already in this format? I suppose the safe way to go is to check for the separator when updating data, and have a special code path to break the keys as it go.

For non-separator containing keys, the normal behavior is to preserve the original data structure as the .data attribute in the NestedData instance - but it would be very tricky to support embedded separators in the keys in this way - as I said, I am surprised it even worked for the other 2 indices.

jsbueno avatar May 15 '24 01:05 jsbueno

OTOH, here is what goes internally - maybe it is "fixable" without many changes from the point the code is now:

In [18]: bb = NestedData({'list.0' : 'list0', 'list.1': 'list1', 'list.2':
    ...:  'list2'})

In [19]: bb.data
Out[19]: {'list': {'0': 'list0', 1: 'list1', 2: 'list2'}}

For some reason, the index "0" is kept as a string, while the others are converted to ints. The way to go here is to check if the indices form a numeric sequence and convert that inner data structure to a list instead of a dict.

jsbueno avatar May 15 '24 01:05 jsbueno

I think I came across this Stack Overflow answer from you, and was not looking for nested lists originally, but then the potential to need them came up, so I gave it a try.

netgirard avatar May 15 '24 18:05 netgirard

Fixed by https://github.com/jsbueno/extradict/commit/51fd98195176e65edd37b44a1be9a1dfe7eba87f

jsbueno avatar Sep 18 '24 03:09 jsbueno