ini2toml package#

Subpackages#

Submodules#

ini2toml.api module#

Public API available for general usage.

In addition to the classes and functions “exported” by this module, the following are also part of the public API:

  • The public members of the types module.

  • The public members of the errors module.

  • The activate function in each submodule of the plugins package

Please notice there might be classes of similar names exported by both api and types. When this happens, the classes in types are not concrete implementations, but instead act as protocols (i.e. abstract descriptions for checking structural polymorphism during static analysis). These should be preferred when writing type hints and signatures.

Plugin authors can also rely on the functions exported by transformations.

class ini2toml.api.BaseTranslator(ini_loads_fn: Callable[[str, Mapping], IntermediateRepr], toml_dumps_fn: Callable[[IntermediateRepr], T], plugins: Sequence[Callable[[Translator], None]] = (), profiles: Sequence[Profile] = (), profile_augmentations: Sequence[ProfileAugmentation] = (), ini_parser_opts: Mapping = mappingproxy({}))[source]#

Bases: Generic[T]

Translator object that follows the public API defined in ini2toml.types.Translator. See dev-guide for a quick explanation of concepts such as plugins, profiles, profile augmentations, etc.

Parameters:
  • ini_loads_fn

    function to convert the .ini/.cfg file into an intermediate representation object. Possible values for this argument include:

  • toml_dumps_fn

    function to convert the intermediate representation object into (ideally) a TOML string. If you don’t exactly need a TOML string (maybe you want your TOML to be represented by bytes or simply the equivalent dict) you can also pass a Callable[[IntermediateRepr], T] function for any desired T.

    Possible values for this argument include:

    • ini2toml.drivers.lite_toml.convert() (when comments can be simply removed)

    • ini2toml.drivers.full_toml.convert() (when you wish to preserve comments in the TOML output)

    • ini2toml.drivers.plain_builtins.convert() (when you wish to retrieve a dict equivalent to the TOML, instead of string with the TOML syntax)

  • plugins (List[Callable[[ini2toml.types.Translator], None]]) – list of plugins activation functions. By default no plugin will be activated.

  • profiles (Dict[str, ini2toml.types.Profile]) – list of profile objects, by default no profile will be pre-loaded (plugins can still add them).

  • profile_augmentations – list of profile augmentations. By default no profile augmentation will be preloaded (plugins can still add them)

  • ini_parser_opts – syntax options for parsing .ini/.cfg files (see ConfigParser and ConfigUpdater). By default it uses the standard configuration of the selected parser (depending on the choice of ini_loads_fn).

Tip

Most of the times the usage of Translator is preferred over BaseTranslator (unless you are vendoring ini2toml and wants to reduce the number of files included in your project).

augment_profiles(fn: Callable[[Profile], None], active_by_default: bool = False, name: str = '', help_text: str = '')[source]#

Register a profile augmentation function to be called after the profile is selected and before the actual translation (see dev-guide).

dumps(irepr: IntermediateRepr) T[source]#
loads(text: str) IntermediateRepr[source]#
plugins: List[Callable[[Translator], None]]#
profiles: Dict[str, Profile]#
translate(ini: str, profile_name: str, active_augmentations: Mapping[str, bool] = mappingproxy({})) T[source]#
class ini2toml.api.Translator(plugins: Sequence[Callable[[Translator], None]] | None = None, profiles: Sequence[Profile] = (), profile_augmentations: Sequence[ProfileAugmentation] = (), ini_parser_opts: Mapping = mappingproxy({}), ini_loads_fn: Callable[[str, Mapping], IntermediateRepr] | None = None, toml_dumps_fn: Callable[[IntermediateRepr], str] | None = None)[source]#

Bases: BaseTranslator[str]

Translator is the main public Python API exposed by the ini2toml, to convert strings representing .ini/.cfg files into the TOML syntax.

It follows the public API defined in ini2toml.types.Translator, and is very similar to BaseTranslator. The main difference is that Translator will try to automatically figure out the values for plugins, ini_loads_fn and toml_dumps_fn when they are not passed, based on the installed Python packages (and available entry-points), while BaseTranslator requires the user to explicitly set these parameters.

For most of the users Translator is recommended over BaseTranslator.

See BaseTranslator for a description of the instantiation parameters.

ini2toml.base_translator module#

class ini2toml.base_translator.BaseTranslator(ini_loads_fn: Callable[[str, Mapping], IntermediateRepr], toml_dumps_fn: Callable[[IntermediateRepr], T], plugins: Sequence[Callable[[Translator], None]] = (), profiles: Sequence[Profile] = (), profile_augmentations: Sequence[ProfileAugmentation] = (), ini_parser_opts: Mapping = mappingproxy({}))[source]#

Bases: Generic[T]

Translator object that follows the public API defined in ini2toml.types.Translator. See dev-guide for a quick explanation of concepts such as plugins, profiles, profile augmentations, etc.

Parameters:
  • ini_loads_fn

    function to convert the .ini/.cfg file into an intermediate representation object. Possible values for this argument include:

  • toml_dumps_fn

    function to convert the intermediate representation object into (ideally) a TOML string. If you don’t exactly need a TOML string (maybe you want your TOML to be represented by bytes or simply the equivalent dict) you can also pass a Callable[[IntermediateRepr], T] function for any desired T.

    Possible values for this argument include:

    • ini2toml.drivers.lite_toml.convert() (when comments can be simply removed)

    • ini2toml.drivers.full_toml.convert() (when you wish to preserve comments in the TOML output)

    • ini2toml.drivers.plain_builtins.convert() (when you wish to retrieve a dict equivalent to the TOML, instead of string with the TOML syntax)

  • plugins (List[Callable[[ini2toml.types.Translator], None]]) – list of plugins activation functions. By default no plugin will be activated.

  • profiles (Dict[str, ini2toml.types.Profile]) – list of profile objects, by default no profile will be pre-loaded (plugins can still add them).

  • profile_augmentations – list of profile augmentations. By default no profile augmentation will be preloaded (plugins can still add them)

  • ini_parser_opts – syntax options for parsing .ini/.cfg files (see ConfigParser and ConfigUpdater). By default it uses the standard configuration of the selected parser (depending on the choice of ini_loads_fn).

Tip

Most of the times the usage of Translator is preferred over BaseTranslator (unless you are vendoring ini2toml and wants to reduce the number of files included in your project).

augment_profiles(fn: Callable[[Profile], None], active_by_default: bool = False, name: str = '', help_text: str = '')[source]#

Register a profile augmentation function to be called after the profile is selected and before the actual translation (see dev-guide).

augmentations: Dict[str, ProfileAugmentation]#
dumps(irepr: IntermediateRepr) T[source]#
loads(text: str) IntermediateRepr[source]#
plugins: List[Callable[[Translator], None]]#
profiles: Dict[str, Profile]#
translate(ini: str, profile_name: str, active_augmentations: Mapping[str, bool] = mappingproxy({})) T[source]#

ini2toml.cli module#

class ini2toml.cli.Formatter(prog, indent_increment=2, max_help_position=24, width=None)[source]#

Bases: RawTextHelpFormatter

ini2toml.cli.apply_auto_formatting(text: str) str[source]#
ini2toml.cli.critical_logging()[source]#

Make sure the logging level is set even before parsing the CLI args

ini2toml.cli.exceptions2exit()[source]#
ini2toml.cli.guess_profile(profile: str | None, file_name: str, available: List[str]) str[source]#
ini2toml.cli.parse_args(args: Sequence[str], profiles: Sequence[Profile], augmentations: Sequence[ProfileAugmentation]) Namespace[source]#

Parse command line parameters

Parameters:

args – command line parameters as list of strings (for example ["--help"]).

Returns: command line parameters namespace

ini2toml.cli.run(args: Sequence[str] = ())[source]#

Wrapper allowing Translator to be called in a CLI fashion.

Instead of returning the value from Translator.translate(), it prints the result to the given output_file or stdout.

Parameters:

args (List[str]) – command line parameters as list of strings (for example ["--verbose", "setup.cfg"]).

ini2toml.cli.setup_logging(loglevel: int)[source]#

Setup basic logging

Parameters:

loglevel – minimum loglevel for emitting messages

ini2toml.errors module#

exception ini2toml.errors.AlreadyRegisteredAugmentation(name: str, new: Callable, existing: Callable)[source]#

Bases: ValueError

The profile augmentation ‘{name}’ is already registered for ‘{existing}’.

Some installed plugins seem to be in conflict with each other, please check ‘{new}’ and ‘{existing}’. If you are the developer behind one of them, please use a different name.

classmethod check(name: str, fn: Callable, registry: Mapping[str, ProfileAugmentation])[source]#
exception ini2toml.errors.InvalidAugmentationName(name: str)[source]#

Bases: ValueError

Profile augmentations should be valid python identifiers

classmethod check(name: str)[source]#
exception ini2toml.errors.InvalidCfgBlock(block)[source]#

Bases: ValueError

Something is wrong with the provided CFG AST, the given block is not valid.

exception ini2toml.errors.InvalidTOMLKey(key)[source]#

Bases: ValueError

{key!r} is not a valid key in the intermediate TOML representation

exception ini2toml.errors.UndefinedProfile(name: str, available: Sequence[str])[source]#

Bases: ValueError

The given profile (‘{name}’) is not registered with ini2toml. Are you sure you have the right plugins installed and loaded?

classmethod check(name: str, available: List[str])[source]#

ini2toml.intermediate_repr module#

Intermediate representations used by ini2toml when transforming between the INI and TOML syntaxes.

class ini2toml.intermediate_repr.CommentKey[source]#

Bases: HiddenKey

class ini2toml.intermediate_repr.Commented(value: T | NotGiven = NotGiven.NOT_GIVEN, comment: str | None = None)[source]#

Bases: Generic[T]

as_commented_list() CommentedList[T][source]#
comment_only()[source]#
has_comment()[source]#
value_or(fallback: S) T | S[source]#
class ini2toml.intermediate_repr.CommentedKV(data: Sequence[Commented[List[Tuple[str, T]]]] = ())[source]#

Bases: Generic[T], UserList

as_dict() dict[source]#
find(key: str) Tuple[int, int] | None[source]#
insert_line(i, values: Iterable[Tuple[str, T]], comment: str | None = None)[source]#
to_ir() IntermediateRepr[source]#

CommentedKV are usually intended to represent INI options, while IntermediateRepr are usually intended to represent INI sections. Therefore this function allows “promoting” an option-equivalent to a section-equivalent representation.

class ini2toml.intermediate_repr.CommentedList(data: Sequence[Commented[List[T]]] = ())[source]#

Bases: Generic[T], UserList

as_list() list[source]#
insert_line(i, values: Iterable[T], comment: str | None = None)[source]#
class ini2toml.intermediate_repr.HiddenKey[source]#

Bases: object

class ini2toml.intermediate_repr.IntermediateRepr(elements: Mapping[str | HiddenKey | Tuple[str | HiddenKey, ...], Any] = mappingproxy({}), order: Sequence[str | HiddenKey | Tuple[str | HiddenKey, ...]] = (), inline_comment: str = '', **kwargs)[source]#

Bases: MutableMapping

append(key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Simulate the position-aware collections.abc.MutableMapping.append() method, but also require a key to be specified.

copy() R[source]#
index(key: str | HiddenKey | Tuple[str | HiddenKey, ...]) int[source]#

Find the position of key

insert(position: int, key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Simulate the position-aware collections.abc.MutableMapping.insert() method, but also require a key to be specified.

rename(old_key: str | HiddenKey | Tuple[str | HiddenKey, ...], new_key: str | HiddenKey | Tuple[str | HiddenKey, ...], ignore_missing=False)[source]#

This method renames an existing key, without changing its position. Notice that new_key cannot be already present, and that trying to rename a non-pre-existing key will also result in error (unless ignore_missing=True).

replace_first_remove_others(existing_keys: Sequence[str | HiddenKey | Tuple[str | HiddenKey, ...]], new_key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Find the first key in existing_keys that existing in the intermediate representation, and replaces it with new_key (similar to replace()). All the other keys in existing_keys are removed and the value of new_key is set to value.

class ini2toml.intermediate_repr.NotGiven(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)#

Bases: Enum

NOT_GIVEN = 1#
class ini2toml.intermediate_repr.WhitespaceKey[source]#

Bases: HiddenKey

ini2toml.profile module#

class ini2toml.profile.Profile(name: str, help_text: str = '', pre_processors: Sequence[Callable[[str], str]] = (), intermediate_processors: Sequence[Callable[[R], R]] = (), post_processors: Sequence[Callable[[str], str]] = (), ini_parser_opts: dict | None = None)[source]#

Bases: object

Profile object that follows the public API defined in ini2toml.types.Profile.

replace(**changes) P#

Works similarly to dataclasses.replace()

class ini2toml.profile.ProfileAugmentation(fn: Callable[[Profile], None], active_by_default: bool = False, name: str = '', help_text: str = '')[source]#

Bases: object

is_active(explicitly_active: bool | None = None) bool[source]#

explicitly_active is a tree-state variable: True if the user explicitly asked for the augmentation, False if the user explicitly denied the augmentation, or None otherwise.

ini2toml.profile.replace(self: P, **changes) P[source]#

Works similarly to dataclasses.replace()

ini2toml.transformations module#

Reusable value and type casting transformations

ini2toml.transformations.CP = ('#', ';')#

Default Comment Prefixes

ini2toml.transformations.CoerceFn#

Functions that know how to parser/coerce string values into different types

alias of Callable[[str], T]

ini2toml.transformations.Scalar#

Simple data types with TOML correspondence

alias of Union[int, float, bool, str]

ini2toml.transformations.Transformation#

There are 2 main types of transformation:

  • The first one is a simple transformation that processes a string value (coming from an option in the original CFG/INI file) into a value with an equivalent TOML data type. For example: transforming "2" (string) into 2 (integer).

  • The second one tries to preserve metadata (such as comments) from the original CFG/INI file. This kind of transformation processes a string value into an intermediary representation (e.g. Commented, CommentedList, obj:CommentedKV) that needs to be properly handled before adding to the TOML document.

In a higher level we can also consider an ensemble of transformations that transform an entire table of the TOML document.

alias of Union[Callable[[str], Any], Callable[[M], M]]

ini2toml.transformations.apply(x, fn)[source]#

Useful to reduce over a list of functions

ini2toml.transformations.coerce_bool(value: str) bool[source]#
ini2toml.transformations.coerce_scalar(value: str) int | float | bool | str[source]#

Try to convert the given string to a proper “scalar” type (e.g. integer, float, bool, …) with an direct TOML equivalent. If the conversion is unknown or not possible, it will return the same input value (as string).

Note

This function “guesses” the value type based in heuristics and/or regular expressions, therefore there is no guarantee the output has the same type as intended by the original author.

Note

Currently date/time-related types are not supported.

ini2toml.transformations.deprecated(name: str, fn: ~ini2toml.transformations.TF = <function noop>, instead: str = '') TF[source]#

Wrapper around the fn transformation to warn user about deprecation.

ini2toml.transformations.is_false(value: str) bool[source]#
ini2toml.transformations.is_float(value: str) bool[source]#
ini2toml.transformations.is_true(value: str) bool[source]#
ini2toml.transformations.kebab_case(field: str) str[source]#
ini2toml.transformations.noop(x: T) T[source]#
ini2toml.transformations.pipe(fn1: Callable[[S], T], fn2: Callable[[T], U]) Callable[[S], U][source]#
ini2toml.transformations.pipe(fn1: Callable[[S], T], fn2: Callable[[T], U], fn3: Callable[[U], V]) Callable[[S], V]
ini2toml.transformations.pipe(fn1: Callable[[S], T], fn2: Callable[[T], U], fn3: Callable[[U], V], fn4: Callable[[V], X]) Callable[[S], X]
ini2toml.transformations.pipe(fn1: Callable[[S], T], fn2: Callable[[T], U], fn3: Callable[[U], V], fn4: Callable[[V], X], fn5: Callable[[X], Y]) Callable[[S], Y]
ini2toml.transformations.pipe(fn1: Callable[[S], T], fn2: Callable[[T], U], fn3: Callable[[U], V], fn4: Callable[[V], X], fn5: Callable[[X], Y], *fn: Callable[[Y], Y]) Callable[[S], Y]

Compose 1-argument functions respecting the sequence they should be applied:

pipe(fn1, fn2, fn3, ..., fnN)(x) == fnN(...(fn3(fn2(fn1(x)))))
ini2toml.transformations.remove_prefixes(text: str, prefixes: Sequence[str])[source]#
ini2toml.transformations.split_comment(value: str, *, comment_prefixes=CP) Commented[str][source]#
ini2toml.transformations.split_comment(value: str, coerce_fn: Callable[[str], T], comment_prefixes=CP) Commented[T]
ini2toml.transformations.split_kv_pairs(value: str, key_sep: str = '=', *, pair_sep=',', subsplit_dangling=True, comment_prefixes=CP) CommentedKV[str][source]#
ini2toml.transformations.split_kv_pairs(value: str, key_sep: str = '=', *, coerce_fn: Callable[[str], T], pair_sep=',', subsplit_dangling=True, comment_prefixes=CP) CommentedKV[T]
ini2toml.transformations.split_kv_pairs(value: str, key_sep: str, coerce_fn: Callable[[str], T], pair_sep=',', subsplit_dangling=True, comment_prefixes=CP) CommentedKV[T]

Value encoded as a (potentially) dangling list of key-value pairs.

This function will first try to split the value by lines (dangling list) using str.splitlines(). Then, if subsplit_dangling=True, it will split each line using pair_sep. As a result a list of key-value pairs is obtained. For each item in this list, the key is separated from the value by key_sep. coerce_fn is used to convert the value in each pair.

ini2toml.transformations.split_list(value: str, sep: str = ',', *, subsplit_dangling=True, comment_prefixes=CP, force_multiline=False) CommentedList[str][source]#
ini2toml.transformations.split_list(value: str, sep: str = ',', *, coerce_fn: Callable[[str], T], subsplit_dangling=True, comment_prefixes=CP, force_multiline=False) CommentedList[T]
ini2toml.transformations.split_list(value: str, sep: str, coerce_fn: Callable[[str], T], subsplit_dangling=True, comment_prefixes=CP, force_multiline=False) CommentedList[T]

Value encoded as a (potentially) dangling list values separated by sep.

This function will first try to split the value by lines (dangling list) using str.splitlines(). Then, if subsplit_dangling=True, it will split each line using sep. As a result a list of items is obtained. For each item in this list coerce_fn is applied.

ini2toml.transformations.split_scalar(value: str, *, comment_prefixes=('#', ';')) Commented[int | float | bool | str][source]#

ini2toml.translator module#

class ini2toml.translator.Translator(plugins: Sequence[Callable[[Translator], None]] | None = None, profiles: Sequence[Profile] = (), profile_augmentations: Sequence[ProfileAugmentation] = (), ini_parser_opts: Mapping = mappingproxy({}), ini_loads_fn: Callable[[str, Mapping], IntermediateRepr] | None = None, toml_dumps_fn: Callable[[IntermediateRepr], str] | None = None)[source]#

Bases: BaseTranslator[str]

Translator is the main public Python API exposed by the ini2toml, to convert strings representing .ini/.cfg files into the TOML syntax.

It follows the public API defined in ini2toml.types.Translator, and is very similar to BaseTranslator. The main difference is that Translator will try to automatically figure out the values for plugins, ini_loads_fn and toml_dumps_fn when they are not passed, based on the installed Python packages (and available entry-points), while BaseTranslator requires the user to explicitly set these parameters.

For most of the users Translator is recommended over BaseTranslator.

See BaseTranslator for a description of the instantiation parameters.

ini2toml.types module#

class ini2toml.types.CLIChoice(*args, **kwargs)[source]#

Bases: Protocol

help_text: str#
name: str#
class ini2toml.types.CommentKey[source]#

Bases: HiddenKey

class ini2toml.types.Commented(value: T | NotGiven = NotGiven.NOT_GIVEN, comment: str | None = None)[source]#

Bases: Generic[T]

as_commented_list() CommentedList[T][source]#
comment_only()[source]#
has_comment()[source]#
value_or(fallback: S) T | S[source]#
class ini2toml.types.CommentedKV(data: Sequence[Commented[List[Tuple[str, T]]]] = ())[source]#

Bases: Generic[T], UserList

as_dict() dict[source]#
find(key: str) Tuple[int, int] | None[source]#
insert_line(i, values: Iterable[Tuple[str, T]], comment: str | None = None)[source]#
to_ir() IntermediateRepr[source]#

CommentedKV are usually intended to represent INI options, while IntermediateRepr are usually intended to represent INI sections. Therefore this function allows “promoting” an option-equivalent to a section-equivalent representation.

class ini2toml.types.CommentedList(data: Sequence[Commented[List[T]]] = ())[source]#

Bases: Generic[T], UserList

as_list() list[source]#
insert_line(i, values: Iterable[T], comment: str | None = None)[source]#
class ini2toml.types.HiddenKey[source]#

Bases: object

class ini2toml.types.IntermediateRepr(elements: Mapping[str | HiddenKey | Tuple[str | HiddenKey, ...], Any] = mappingproxy({}), order: Sequence[str | HiddenKey | Tuple[str | HiddenKey, ...]] = (), inline_comment: str = '', **kwargs)[source]#

Bases: MutableMapping

append(key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Simulate the position-aware collections.abc.MutableMapping.append() method, but also require a key to be specified.

copy() R[source]#
index(key: str | HiddenKey | Tuple[str | HiddenKey, ...]) int[source]#

Find the position of key

insert(position: int, key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Simulate the position-aware collections.abc.MutableMapping.insert() method, but also require a key to be specified.

rename(old_key: str | HiddenKey | Tuple[str | HiddenKey, ...], new_key: str | HiddenKey | Tuple[str | HiddenKey, ...], ignore_missing=False)[source]#

This method renames an existing key, without changing its position. Notice that new_key cannot be already present, and that trying to rename a non-pre-existing key will also result in error (unless ignore_missing=True).

replace_first_remove_others(existing_keys: Sequence[str | HiddenKey | Tuple[str | HiddenKey, ...]], new_key: str | HiddenKey | Tuple[str | HiddenKey, ...], value: Any)[source]#

Find the first key in existing_keys that existing in the intermediate representation, and replaces it with new_key (similar to replace()). All the other keys in existing_keys are removed and the value of new_key is set to value.

class ini2toml.types.Profile(*args, **kwargs)[source]#

Bases: Protocol

help_text: str#
intermediate_processors: List[Callable[[R], R]]#
name: str#
post_processors: List[Callable[[str], str]]#
pre_processors: List[Callable[[str], str]]#
class ini2toml.types.ProfileAugmentation(*args, **kwargs)[source]#

Bases: Protocol

active_by_default: bool#
fn(profile: Profile)[source]#
help_text: str#
is_active(explicitly_active: bool | None = None) bool[source]#

explicitly_active is a tree-state variable: True if the user explicitly asked for the augmentation, False if the user explicitly denied the augmentation, or None otherwise.

name: str#
class ini2toml.types.Translator(*args, **kwargs)[source]#

Bases: Protocol

augment_profiles(fn: Callable[[Profile], None], active_by_default: bool = False, name: str = '', help_text: str = '')[source]#

Register a profile augmentation function (see Core Concepts). The keyword name and help_text can be used to customise the description featured in ini2toml’s CLI, but when these arguments are not given (or empty strings), name is taken from fn.__name__ and help_text is taken from fn.__doc__ (docstring).

class ini2toml.types.WhitespaceKey[source]#

Bases: HiddenKey

Module contents#