toml-cli
toml-cli copied to clipboard
toml set added a duplicated table when parent table is defined after child table
$ cat test.toml
[root.d1]
f1="f1"
[root]
f2="f2"
# It seems like the toml-cli can't deal with the tables which parent table is defined after child table?
$ toml set --toml-path test.toml root.f3 "f3"
$ cat test.toml
[root]
f3 = "f3"
[root.d1]
f1="f1"
[root]
f2="f2"
$ toml set --toml-path test.toml root.f3 "f3"
╭──────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /opt/homebrew/lib/python3.10/site-packages/tomlkit/parser.py:161 in parse │
│ │
│ 158 │ │ │ │ value = self._parse_aot(value, key) ╭─────────────────────── locals ────────────────────────╮ │
│ 159 │ │ │ │ body = {'root': {'f3': 'f3', 'd1': {'f1': 'f1'}}} │ │
│ 160 │ │ │ try: │ key = <Key root> │ │
│ ❱ 161 │ │ │ │ body.append(key, value) │ self = <tomlkit.parser.Parser object at 0x10209d6c0> │ │
│ 162 │ │ │ except Exception as e: │ value = {'f2': 'f2'} │ │
│ 163 │ │ │ │ raise self.parse_error(ParseError, str(e)) from e ╰───────────────────────────────────────────────────────╯ │
│ 164 │
│ │
│ /opt/homebrew/lib/python3.10/site-packages/tomlkit/container.py:265 in append │
│ │
│ 262 │ │ │ │ │ elif current_body_element[0].is_dotted(): ╭─────────────────────────────── locals ────────────────────────────────╮ │
│ 263 │ │ │ │ │ │ raise TOMLKitError("Redefinition of an existing table") │ current = {'f3': 'f3', 'd1': {'f1': 'f1'}} │ │
│ 264 │ │ │ │ elif not item.is_super_table(): │ current_body_element = (<Key root>, {'f3': 'f3', 'd1': {'f1': 'f1'}}) │ │
│ ❱ 265 │ │ │ │ │ raise KeyAlreadyPresent(key) │ current_idx = 0 │ │
│ 266 │ │ │ elif isinstance(item, AoT): │ item = {'f2': 'f2'} │ │
│ 267 │ │ │ │ if not isinstance(current, AoT): │ key = <Key root> │ │
│ 268 │ │ │ │ │ # Tried to define an AoT after a table with the same name. │ prev = {'f3': 'f3', 'd1': {'f1': 'f1'}} │ │
│ │ prev_ws = False │ │
│ │ self = {'root': {'f3': 'f3', 'd1': {'f1': 'f1'}}} │ │
│ │ validate = True │ │
│ ╰───────────────────────────────────────────────────────────────────────╯ │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
KeyAlreadyPresent: Key "root" already exists.
The above exception was the direct cause of the following exception:
╭──────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /opt/homebrew/lib/python3.10/site-packages/toml_cli/__init__.py:73 in set_ │
│ │
│ 70 │ ), ╭────────────── locals ──────────────╮ │
│ 71 ): │ key = 'root.f3' │ │
│ 72 │ """Set a value to a toml file""" │ to_array = False │ │
│ ❱ 73 │ toml_part = toml_file = tomlkit.parse(toml_path.read_text()) │ to_bool = False │ │
│ 74 │ │ to_float = False │ │
│ 75 │ for key_part in key.split(".")[:-1]: │ to_int = False │ │
│ 76 │ │ try: │ toml_path = PosixPath('test.toml') │ │
│ │ value = 'f3' │ │
│ ╰────────────────────────────────────╯ │
│ │
│ /opt/homebrew/lib/python3.10/site-packages/tomlkit/api.py:91 in parse │
│ │
│ 88 │ """ ╭────────────────────────────── locals ───────────────────────────────╮ │
│ 89 │ Parses a string or bytes into a TOMLDocument. │ string = '[root]\nf3 = "f3"\n[root.d1]\nf1="f1"\n[root]\nf2="f2"\n' │ │
│ 90 │ """ ╰─────────────────────────────────────────────────────────────────────╯ │
│ ❱ 91 │ return Parser(string).parse() │
│ 92 │
│ 93 │
│ 94 def document() -> TOMLDocument: │
│ │
│ /opt/homebrew/lib/python3.10/site-packages/tomlkit/parser.py:163 in parse │
│ │
│ 160 │ │ │ try: ╭─────────────────────── locals ────────────────────────╮ │
│ 161 │ │ │ │ body.append(key, value) │ body = {'root': {'f3': 'f3', 'd1': {'f1': 'f1'}}} │ │
│ 162 │ │ │ except Exception as e: │ key = <Key root> │ │
│ ❱ 163 │ │ │ │ raise self.parse_error(ParseError, str(e)) from e │ self = <tomlkit.parser.Parser object at 0x10209d6c0> │ │
│ 164 │ │ │ value = {'f2': 'f2'} │ │
│ 165 │ │ body.parsing(False) ╰───────────────────────────────────────────────────────╯ │
│ 166 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
ParseError: Key "root" already exists. at line 6 col 0
Thanks for the isssue. Too bad, the issue is caused by the underlying toml document library. So it is not an easy fix. I will check if I can make a PR for that library or use another one.
It's OK. I also found it should be a tomlkit bug.