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 #1847