Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert integer keys to strings when writing to TOML files #15

Closed
wants to merge 0 commits into from

Conversation

lewiuberg
Copy link
Contributor

Integers as keys are not supported by toml.dumps. I suggest including this capability in PyConfs since it is supported when writing to json, yaml, and ini.

Testing tomldirectly

import toml

int_as_key = {1: {2: "three"}}
str_as_key = {"1": {"2": "three"}}

print(int_as_key)
print(str_as_key)
print()

try:
    with open("with_integer.toml", "w") as f:
        formated_with_dumps = toml.dump(int_as_key, f)
except KeyError:
    print("KeyError")
    with open("with_string.toml", "w") as f:
        formated_with_dumps = toml.dump(str_as_key, f)

print()
print(formated_with_dumps)

Output:

{1: {2: 'three'}}
{'1': {'2': 'three'}}

KeyError

[1]
2 = "three"

@gahjelle
Copy link
Owner

Thanks for adding this PR, @lewiuberg

By experimenting with the current underlying libraries, I see that YAML handles int keys fine, while INI and JSON silently convert int keys to str keys. I guess implementing the latter behavior for TOML should therefore be okay.

I'm currently getting an error when I try to store a Configuration with an int key as TOML:

>>> from pyconfs import Configuration
>>> cfg = Configuration.from_dict({"answer": {42: "Everything"}})
>>> cfg.as_str(format="toml")
Traceback (most recent call last):
  File "<ipython-input-3-5906edeb1c36>", line 1, in <module>
    cfg.as_str(format="toml")
  File "/home/gahjelle/Dropbox/programmering/github/pyconfs/pyconfs/configuration.py", line 392, in as_str
    return writers.as_str(format, config=self.as_dict(), **writer_args)
  File "/home/gahjelle/miniconda3/envs/pyconfs/lib/python3.9/site-packages/pyplugs/_plugins.py", line 210, in call
    return plugin_func(*args, **kwargs)
  File "/home/gahjelle/Dropbox/programmering/github/pyconfs/pyconfs/writers/toml.py", line 39, in as_toml
    formated_config = int_keys_to_str(config)
  File "/home/gahjelle/Dropbox/programmering/github/pyconfs/pyconfs/writers/toml.py", line 23, in int_keys_to_str
    int_keys_to_str(value)
  File "/home/gahjelle/Dropbox/programmering/github/pyconfs/pyconfs/writers/toml.py", line 18, in int_keys_to_str
    for key, value in data.items():
RuntimeError: dictionary keys changed during iteration

>>> cfg.as_str(format="json")
'{"answer": {"42": "Everything"}}'

>>> cfg.as_str(format="yaml")
'answer:\n  42: Everything\n'

>>> cfg.as_str(format="ini")
'[answer]\n42 = Everything\n\n'

I believe this is because we are adding and deleting items in the dictionary while iterating over it. It might be better to create a new dictionary with string keys instead of mutating the existing one.

One possible simplification is that I think we can freely convert all keys to strings and not bother with checking whether a key is an int. Keys are always strings in TOML (https://toml.io/en/v1.0.0#keys).

Thanks for initiating this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants