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

Omit None values in TOML instead of throwing TypeError #85

Closed
jonaslb opened this issue Oct 30, 2022 · 4 comments
Closed

Omit None values in TOML instead of throwing TypeError #85

jonaslb opened this issue Oct 30, 2022 · 4 comments

Comments

@jonaslb
Copy link

jonaslb commented Oct 30, 2022

Is your feature request related to a problem? Please describe.

Example:

@dataclass
class MyExampleConfig(DataClassTOMLMixin):
    username: str | None = None

MyExampleConfig().to_toml()

Gives the following exception:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-68a219996b72> in <module>
----> 1 MyExampleConfig().to_toml()

~/.local/lib/python3.11/site-packages/mashumaro/core/meta/builder.py in to_toml(self, encoder)

~/.local/lib/python3.11/site-packages/tomli_w/_writer.py in dumps(__obj, multiline_strings)
     37 def dumps(__obj: dict[str, Any], *, multiline_strings: bool = False) -> str:
     38     ctx = Context(multiline_strings, {})
---> 39     return "".join(gen_table_chunks(__obj, ctx, name=""))
     40
     41

~/.local/lib/python3.11/site-packages/tomli_w/_writer.py in gen_table_chunks(table, ctx, name, inside_aot)
     71         yielded = True
     72         for k, v in literals:
---> 73             yield f"{format_key_part(k)} = {format_literal(v, ctx)}\n"
     74
     75     for k, v, in_aot in tables:

~/.local/lib/python3.11/site-packages/tomli_w/_writer.py in format_literal(obj, ctx, nest_level)
    100     if isinstance(obj, dict):
    101         return format_inline_table(obj, ctx)
--> 102     raise TypeError(f"Object of type {type(obj)} is not TOML serializable")
    103
    104

TypeError: Object of type <class 'NoneType'> is not TOML serializable

Describe the solution you'd like
It seems that TOML plainly does not represent None values, preferring instead to omit such keys (see toml-lang/toml#30 ). That would be perfectly fine since None in Python is used to indicate missing value. Thus I think the default behavior for TOML should be to just not serialize the None value instead of giving this TypeError.

Describe alternatives you've considered
Currently it seems one needs to use another format e.g. yaml or json if the dataclass has any possibly None values.

@jonaslb
Copy link
Author

jonaslb commented Oct 30, 2022

I'm stupid, there's an omit_none option, ha.

@jonaslb jonaslb closed this as completed Oct 30, 2022
@Fatal1ty
Copy link
Owner

Good spot!

At this moment you can use omit_none code generation option, as you mentioned, but you will need to set omit_none=True each time you call to_toml with it.

I think it’s time to add a new omit_none option to the Config and Dialect classes to change the default behavior. It could be set to True in TOMLDialect that is used to generate to_toml method. With this new feature None values could be skipped out of the box for TOML.

Let me reopen this issue to keep track of it for the next release.

@Fatal1ty
Copy link
Owner

I have made some changes, which I wrote about above. Now using DataClassTOMLMixin will be more convenient:

@dataclass
class InnerDataClassWithOptionalField(DataClassTOMLMixin):
    x: Optional[int] = None


@dataclass
class DataClass(DataClassTOMLMixin):
    x: Optional[InnerDataClassWithOptionalField] = None
    y: Optional[int] = None


obj = DataClass()
assert obj.to_dict() == {"x": None, "y": None}
assert obj.to_toml() == ""

obj = DataClass(InnerDataClassWithOptionalField())
assert obj.to_dict() == {"x": {"x": None}, "y": None}
assert obj.to_toml() == "[x]\n"
assert DataClass.from_toml("[x]\n") == obj

@Fatal1ty
Copy link
Owner

Fatal1ty commented Dec 2, 2022

Starting from 3.2 None values are skipped for TOML.

@Fatal1ty Fatal1ty closed this as completed Dec 2, 2022
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

No branches or pull requests

2 participants