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

Add toml utility module that wraps every toml Python module ever created #1851

Merged
merged 10 commits into from
Aug 21, 2024

Conversation

achilleas-k
Copy link
Member

@achilleas-k achilleas-k commented Aug 15, 2024

The toml module story in osbuild is difficult. Different distro versions have different modules packaged or built-in, sometimes with different capabilities (no writing). Since we need to support reading and writing toml files both on the host (osbuild internals, sources, inputs) and in the build root (stages), this PR centralises the import decision making in an internal utility module that covers all cases.

The wrapper is quite ugly and there's a few reasons for that. Two of the modules we might import (tomli and tomllib) don't support writing, so we need to either import a separate module (tomli_w) or raise an exception when dump() is called without a write-capable module. The tomli and tomllib modules require files be opened in binary mode (not text) while the others require text mode. So we can't wrap the toml.load() and toml.dump() functions directly; the caller doesn't know which module it will be using. We keep track of the mode based on which import succeeded and have our functions open the files as needed.

The wrapper functions are named load_from_file() and dump_to_file() to avoid confusion with the load() and dump() functions that take a file object.

The PR also adds simple read/write tests and tox configs for testing every supported toml module.

Feel free to suggest anything that might make the module less of a mess.

Fixes #1847

alexlarsson
alexlarsson previously approved these changes Aug 16, 2024
Copy link
Collaborator

@alexlarsson alexlarsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for untangling this! A quick question about the support status inline

osbuild/util/toml.py Outdated Show resolved Hide resolved
osbuild/util/toml.py Show resolved Hide resolved
osbuild/util/toml.py Show resolved Hide resolved
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for digging into this and solving it. Abstracting it away is the right choice, I like it. Some comments/ramblings inline but all optional

osbuild/util/toml.py Outdated Show resolved Hide resolved
osbuild/util/toml.py Show resolved Hide resolved
test/mod/test_util_toml.py Show resolved Hide resolved
osbuild/util/toml.py Show resolved Hide resolved
osbuild/util/toml.py Show resolved Hide resolved
tox.ini Show resolved Hide resolved
tox.ini Show resolved Hide resolved
Copy link
Contributor

@kingsleyzissou kingsleyzissou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tomlunacy :chefs-kiss: great stuff, thanks for figuring this out, lgtm

@mvo5 mvo5 enabled auto-merge (rebase) August 16, 2024 15:16
mvo5 added a commit to mvo5/images that referenced this pull request Aug 16, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
Copy link
Contributor

@bcl bcl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great Job! Not sure why schutzbot is unhappy, I restarted the failed tests.

@achilleas-k
Copy link
Member Author

FWIW, all test configs built successfully with this PR in osbuild/images: osbuild/images#863

@achilleas-k
Copy link
Member Author

Great Job! Not sure why schutzbot is unhappy, I restarted the failed tests.

I'm looking into the rpm build failures now.

mvo5 added a commit to mvo5/images that referenced this pull request Aug 20, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
mvo5 added a commit to mvo5/images that referenced this pull request Aug 20, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
The toml module situation in Python is a bit of a mess.  Different
distro versions have different modules packaged or built-in, sometimes
with different capabilities (no writing).  Since we need to support
reading and writing toml files both on the host (osbuild internals,
sources, inputs) and in the build root (stages), let's centralise the
import decision making in an internal utility module that covers all
cases.

Two of the modules we might import (tomli and tomllib) don't support
writing, so we need to either import a separate module (tomli_w) or
raise an exception when dump() is called without a write-capable module.

The tomli and tomllib modules require files be opened in binary mode
(not text) while the others require text mode.  So we can't wrap the
toml.load() and toml.dump() functions directly; the caller doesn't know
which module it will be using.  Let's keep track of the mode based on
which import succeeded and have our functions open the files as needed.

The wrapper functions are named load_from_file() and dump_to_file() to
avoid confusion with the load() and dump() functions that take a file
object.

See also osbuild#1847
The containers.storage.conf stage writes a header explaining what the
configuration is doing and its origin.  It also supports adding extra
comments via stage options, which we need to support.  Add support for
writing comments at the top of the file in the toml.dump_to_file()
function.
Add a new util module called host which is used for functions that are
meant for interactions with the host.  These functions should not be
used in stages.

The containers.get_host_storage() function is renamed to
host.get_container_storage() for clarity, since it is no longer
namespaced under containers.
Different toml libraries write arrays differently, so we can't know
exactly what the file contents will look like.  Some will write an array
in a single line (toml) while others will break it into one element per
line (tomli_w).  Parse the file that's written by the stage so we can
compare the objects instead of the text contents directly.
- Specify utf-8 encoding when opening files in text mode.
- Add type hints.
- Prefix all the top-level names with _.
Add two unit tests for our toml util module.
- Write an object with util.toml, read it with util.toml, and compare
  written and read objects.
- Write an object directly as a string, read it with util.toml,
  comparing with an expected object.

A test that writes with util.toml, reads as string, and verifies the
read string is difficult to do in a general way, because each toml
module we support writes files in a slightly different way.
Add four toml test environments, testing that osbuild.util.toml works
for reading and writing with all our supported toml module combinations.
@elkoniu
Copy link
Contributor

elkoniu commented Aug 20, 2024

Branch rebased on top of rpm build failure fix

@mvo5 mvo5 merged commit af913d9 into osbuild:main Aug 21, 2024
47 checks passed
@achilleas-k achilleas-k deleted the tomlunacy branch August 21, 2024 17:26
mvo5 added a commit to mvo5/images that referenced this pull request Sep 19, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
bcl pushed a commit to mvo5/images that referenced this pull request Sep 23, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
github-merge-queue bot pushed a commit to osbuild/images that referenced this pull request Oct 8, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
github-merge-queue bot pushed a commit to osbuild/images that referenced this pull request Oct 8, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
github-merge-queue bot pushed a commit to osbuild/images that referenced this pull request Oct 9, 2024
The current code will install python3-toml on fedora and also
on rhel11 (once it comes out) because that is the default for
unhandled distros.

This commit makes the various toml libs for each distro more
explicit, see also osbuild/osbuild#1851
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.

Ensure every supported distribution can use stages with toml
6 participants