uiri / toml

Python lib for TOML
MIT License
1.1k stars 190 forks source link

mixed types in array don't work #270

Open vanyakosmos opened 4 years ago

vanyakosmos commented 4 years ago
[config]
list = [
  { key = "value"},
  "foo",
]

this way file will be parsed but "foo" will be ignored: {config: {list: [{key: value}]}}


[config]
list = [
  "foo",
  { key = "value"},
]

After parsing toml file above parser will throw an error: IndexError: list index out of range. Traceback:

  File "/path/to/lib/python3.7/site-packages/toml/decoder.py", line 456, in loads
    multibackslash)
  File "/path/to/lib/python3.7/site-packages/toml/decoder.py", line 725, in load_line
    value, vtype = self.load_value(pair[1], strictly_valid)
  File "/path/to/lib/python3.7/site-packages/toml/decoder.py", line 802, in load_value
    return (self.load_array(v), "array")
  File "/path/to/lib/python3.7/site-packages/toml/decoder.py", line 914, in load_array
    a[b] = a[b] + ',' + a[b + 1]
IndexError: list index out of range
flokno commented 4 years ago

This was only recently added to toml itself: https://github.com/toml-lang/toml/pull/676/

Edit: Wait, I think 2 different issues are going on here. The first is that indeed

[config]
list = [
  { key = "value"},
  "foo",
]

is parsed to 'config': {'list': [{'key': 'value'}]}} dropping the foo.

[config]
list = [
  "foo",
  { key = "value"},
]

throws the IndexError, but that is to be expected I think because of the trailing comma. The question is: Why is the unmatched trailing comma not detected in the first example?

Finally,

[config]
list = [
  "foo",
  { key = "value"}
]

i.e., without the trailing comma, raises toml.decoder.TomlDecodeError: Not a homogeneous array, which is not necessary anymore according to https://github.com/toml-lang/toml/pull/676/. I guess that is what the issue was relating to in the first place.

dalonsoa commented 4 years ago

I can still reproduce this error and, indeed, the result is rather inconsisten: it can dump arrays with mixed types, but it fails when loading that same output.

To reproduce:

import toml
data = {"a": [1, "cat"]}
data_encoded = toml.dumps(data)

The above works and results in data_encoded equal to 'a = [ 1, "cat",]\n' . Then:

data_back = toml.loads(data_encoded)

results in:

Traceback (most recent call last):
  File "XXXXXXX/python3.8/site-packages/toml/decoder.py", line 510, in loads
    ret = decoder.load_line(line, currentlevel, multikey,
  File "XXXXXXX/python3.8/site-packages/toml/decoder.py", line 777, in load_line
    value, vtype = self.load_value(pair[1], strictly_valid)
  File "XXXXXXX/python3.8/site-packages/toml/decoder.py", line 875, in load_value
    return (self.load_array(v), "array")
  File "XXXXXXX/python3.8/site-packages/toml/decoder.py", line 1024, in load_array
    raise ValueError("Not a homogeneous array")
ValueError: Not a homogeneous array
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "XXXXXXX/python3.8/site-packages/IPython/core/interactiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-7-8f12f46e5bec>", line 1, in <module>
    data_back = toml.loads(data_encoded)
  File "XXXXXXX/python3.8/site-packages/toml/decoder.py", line 513, in loads
    raise TomlDecodeError(str(err), original, pos)
toml.decoder.TomlDecodeError: Not a homogeneous array (line 1 column 1 char 0)

The same applies when loading/dumping to a file rather than a string.

arnauddevie commented 4 years ago

Reproduced this error with mixed integer/float array

Python: 3.7.5 toml: 0.10.0, 0.10.1

Dump

import toml

mixed_types = [0, 1.1, 2.2, 3.3] # mixed integer and floats

toml.dumps({'array': mixed_types})

'array = [ 0, 1.1, 2.2, 3.3,]\n'

Load

toml.loads(toml.dumps({'array': mixed_types}))

ValueError Traceback (most recent call last) ~\Anaconda3\envs\modeling\lib\site-packages\toml\decoder.py in loads(s, _dict, decoder) 455 ret = decoder.load_line(line, currentlevel, multikey, --> 456 multibackslash) 457 except ValueError as err:

~\Anaconda3\envs\modeling\lib\site-packages\toml\decoder.py in load_line(self, line, currentlevel, multikey, multibackslash) 724 else: --> 725 value, vtype = self.load_value(pair[1], strictly_valid) 726 try:

~\Anaconda3\envs\modeling\lib\site-packages\toml\decoder.py in load_value(self, v, strictly_valid) 801 elif v[0] == '[': --> 802 return (self.load_array(v), "array") 803 elif v[0] == '{':

~\Anaconda3\envs\modeling\lib\site-packages\toml\decoder.py in load_array(self, a) 940 if ntype != atype: --> 941 raise ValueError("Not a homogeneous array") 942 else:

ValueError: Not a homogeneous array

During handling of the above exception, another exception occurred:

TomlDecodeError Traceback (most recent call last)

in ----> 1 toml.loads(toml.dumps({'array': mixed_types})) ~\Anaconda3\envs\modeling\lib\site-packages\toml\decoder.py in loads(s, _dict, decoder) 456 multibackslash) 457 except ValueError as err: --> 458 raise TomlDecodeError(str(err), original, pos) 459 if ret is not None: 460 multikey, multilinestr, multibackslash = ret TomlDecodeError: Not a homogeneous array (line 1 column 1 char 0)

Spec v1.0.0-rc.2 says:

Array

Arrays are square brackets with values inside. Whitespace is ignored. Elements are separated by commas. Arrays can contain values of the same data types as allowed in key/value pairs. Values of different types may be mixed.

# Mixed-type arrays are allowed
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
  "Foo Bar <foo@example.com>",
  { name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]
cykerway commented 2 years ago

Still a problem on Python 3.9.9 with toml 0.10.2:

arr = [ 'a', 0 ]

Error:

toml.decoder.TomlDecodeError: Not a homogeneous array ...

Doc (https://toml.io/en/v1.0.0#array):

Values of different types may be mixed.

RichardBruskiewich commented 1 year ago

Still a problem 3 years later... See https://github.com/python-poetry/poetry/issues/7094