Repository navigation
Closed
Description
While a statement like 4=5 is a little strange mabye it is technically valid TOML if I'm not mistaken. The parse function handles this correctly, but the add and setdefault function seem to stumble on this, as demonstrated below.
I stumbled across this bug while I was trying to reproduce another, so I'll admit it's a bit of an edge case, but it should probably work properly. I can open a PR for this if maintainer would be open to it and agrees that this is the correct way to go.
In [1]: import tomlkit
In [2]: parse("4=5")
Out [2]: {'4': 5}
In [3]: tomlkit.TOMLDocument().setdefault(4,5)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 1
----> 1 tomlkit.TOMLDocument().setdefault(4,5)
File[redacted]/tomlkit/container.py:639, in Container.setdefault(self, key, default)
638 def setdefault(self, key: Key | str, default: Any) -> Any:
--> 639 super().setdefault(key, default=default)
640 return self[key]
File [redacted]/_collections_abc.py:1012, in MutableMapping.setdefault(self, key, default)
1010 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D'
1011 try:
-> 1012 return self[key]
1013 except KeyError:
1014 self[key] = default
File [redacted]/tomlkit/container.py:622, in Container.__getitem__(self, key)
621 def __getitem__(self, key: Key | str) -> Item | Container:
--> 622 item = self.item(key)
623 if isinstance(item, Item) and item.is_boolean():
624 return item.value
Fiile [redacted]/tomlkit/container.py:460, in Container.item(self, key)
458 """Get an item for the given key."""
459 if not isinstance(key, Key):
--> 460 key = SingleKey(key)
462 idx = self._map.get(key)
463 if idx is None:
File [redacted]/tomlkit/items.py:384, in SingleKey.__init__(self, k, t, sep, original)
376 def __init__(
377 self,
378 k: str,
(...)
381 original: str | None = None,
382 ) -> None:
383 if t is None:
--> 384 if not k or any(
385 c not in string.ascii_letters + string.digits + "-" + "_" for c in k
386 ):
387 t = KeyType.Basic
388 else:
TypeError: 'int' object is not iterableFrom the last code in the stack frame it seems that the code assumes the key is iterable which it may not be, but this should be not too hard to fix with an additional check along the lines of
if not k or (isinstance(k, collections.abc.Iterable) and c not in ...) :Metadata
Metadata
Assignees
Labels
No labels
Activity
frostming commentedon May 6, 2025
Thanks for catching, PR welcome
aslowwriter commentedon May 6, 2025
cool, I'll try and open a PR sometime this week
DimmaDont commentedon May 31, 2025
Shouldn't the
4be wrapped in quotes? e.g..setdefault("4", 5)From the TOML spec:
setdefault()already expectskeyto beKey | straslowwriter commentedon Jun 2, 2025
Well you're correct that according to the type hints (which I didn't pay attention to at the time apparently) the submitted code is incorrect, but the spec you quoted does explicitly allow for this, so I think the library should accept it. It can should just be cast to a string
frostming commentedon Jun 3, 2025
I don't think you interpret it correctly, the specs treats digits as string, not convert it to strings. From the perspective of a table, the keys are always strings.
This is the result of the recommended writer
tomli-w:However, compared to it, the error message of tomlkit is confusing, can you help to improve it, rejecting all types other than string
aslowwriter commentedon Jun 3, 2025
hmmm, yeah I guess you're right. In that case I guess I'll also just throw a Type Error like
tomli_wdoes. I've updated the PRfix(deps): update dependency tomlkit to v0.13.3 (#343)