rwskit.config

Attributes

log

T

E

I

TypeParser

Classes

YamlConfig

A base class for serializable configuration objects.

EnvironmentConfig

A mixin clas for configuration objects to help constructing them from environment variables.

Module Contents

rwskit.config.log[source]
rwskit.config.T[source]
rwskit.config.E[source]
rwskit.config.I[source]
rwskit.config.TypeParser[source]
class rwskit.config.YamlConfig[source]

Bases: yamlable.YamlAble

A base class for serializable configuration objects.

Classes that inherit from this class can easily be serialized to and from YAML files. Given a YAML file, the class can be reconstructed as long as the YAML attributes can be uniquely mapped to a subclass of YamlConfig.

Additionally, the configuration can be split across multiple files for better modularity using the !include directive.

Examples

>>> class ChildConfig(YamlConfig):
...     id: int
...     name: str
...     timestamp: datetime.datetime
>>> class ParentConfig(YamlConfig):
...     parent_attr: str = "parent_attr_value"
...     child_attr:
>>> expected_config = ParentConfig(
...     id=1,
...     child_config=ChildConfig(
...         id=2,
...         name="child_config",
...         timestamp=datetime.datetime.now()
... )
>>> plain_yaml = '''
... child_config:
...     id: 2
...     name: child_config
...     timestamp: 2024-11-19 13:55:34.064388
...  id: 1
... '''
>>> from_plain_yaml = YamlConfig.loads_yaml(plain_yaml)
>>> assert from_plain_yaml == expected_config

The !yamlable tag can be used to explicitly tell the YAML parser which class to construct. The syntax is !yamlable/<fully_qualified_class_name>.

>>> tagged_yaml = '''
... !yamlable/my_package.my_module.ParentConfig
... child_config: !yamlable/my_package.my_module.ChildConfig
...     id: 2
...     name: child_config
...     timestamp: 2024-11-19 13:55:34.064388
... id: 1
... '''
>>> assert YamlConfig.loads_yaml(tagged_yaml) == expected_config

You can use the !include directive to include other YAML files. For example, assume you have the following two YAML files:

# child_config.yaml

id: 2
name: "child_config"
timestamp: 2024-11-19 13:55:34.064388
# parent_config.yaml

id: 1
child_config: !include child_config.yaml

You can load the parent config using YamlConfig.load_yaml as follows:

>>> YamlConfig.load_yaml("parent_config.yaml")
default_type_parsers[source]
classmethod __init_subclass__(**kwargs: Any)[source]

Initialize subclasses to make them suitable configuration objects.

  • Automatically assign the __yaml_tag_suffix__ using the fully qualified class name.

  • Convert the class to a pydantic.dataclasses.dataclass that has frozen=True and kw_only=True.

Parameters:

kwargs (Any)

classmethod get_registered_classes() set[Type[YamlConfig]][source]

Get the set of classes currently registered as configuration objects.

Returns:

The set of registered yaml config classes.

Return type:

set[Type[YamlConfig]]

dumps_plain_yaml() str[source]

Represent the class as plain YAML without any tags.

Note

It may not be possible to reconstruct the python object from this string.

Returns:

The object as plain YAML without any tags.

Return type:

str

classmethod load_yaml(file_path_or_stream: str | pathlib.Path | io.IOBase | io.StringIO, safe: bool = True) T[source]

Parses the given file path or stream as a yaml document. This methods only returns successfully if the result is an instance of cls.

Parameters:
  • file_path_or_stream

  • safe – True (default) uses yaml.safe_load. False uses yaml.load

Returns:

class rwskit.config.EnvironmentConfig(*args, **kwargs)[source]

Bases: abc.ABC

A mixin clas for configuration objects to help constructing them from environment variables.

This mixin adds a method from_environment() that will try to parse environment variables into the correct type for the dataclass. All you have to do is implement the environment_mapping() method to provide a mapping between environment variable names and the dataclass field names.

classmethod get_default_type_parsers() dict[Type[I], TypeParser][source]

Get the default type parsers for this class.

classmethod environment_mapping() Mapping[str, str][source]
Abstractmethod:

Returns a mapping from environment variable names to their corresponding field name.

Return type:

Mapping[str, str]

Raises:

ViolationError – If any of the returned values are not a field name of this class. Note, not all fields need to be included in the mapping, but any entry that is included must correspond to a field name.

classmethod from_environment(type_parsers: dict[Type[I], TypeParser] | None = None, **kwargs) E[source]

Create an instance from environment variables.

Environment variables can represent python primitive values, date objects, datetime objects. They can also be lists, sets, tuples, or dicts of these types. Collections are space separated string. Multiword strings should be enclosed in double quotes. Dictionary key value pairs are delimited by ‘=’. Spaces are not allowed in keys or values.

Parameters:
  • type_parsers (dict[Type[I], TypeParser]) – A mapping from python types to functions that parse a string into that type. These will be combined and override the default parsing rules described above.

  • kwargs – Additional keyword arguments to override the values from the environment or composite fields (e.g., other dataclasses), which are constructed externally.

classmethod get_environment_kwargs(type_parsers: dict[Type[I], TypeParser]) dict[str, I][source]

Get the keyword arguments for this dataclass that are available from the environment.

Parameters:

type_parsers (dict[Type, TypeParser]) – The type parsers to use when parsing environment variables.

Returns:

The keyword arguments as a dictionary.

Return type:

dict[str, Any]

classmethod get_dataclass_field_map() dict[str, dataclasses.Field][source]

Get a mapping from field names to their dataclass fields.

classmethod get_field_from_name(field_name: str) dataclasses.Field[source]

Get the dataclass field from its name.

classmethod parse_value_from_string(input_string: str, target_type: Type[I], type_parsers: dict[Type[I], TypeParser] | None = None)[source]

Try to parse an input string into the given python target_type.

The input string can be a single value that can be parsed by the default parsing rules or any of the rules implemented by the given type_parsers. By default, the parseable values are: str, int, float, bool, datetime.datetime, datetime.date, re.Pattern, and any class that can be constructed from a single string argument (e.g., pathlib.Path.

To handle more complex target_types, the input string can also be a JSON string. The string will be parsed as JSON and the resulting object will be traversed to try to convert the leaf values using the all the available parsing rules.

Parameters:
  • input_string (str) – The string to parse.

  • target_type (Type) – The python type to parse the value into.

  • type_parsers (dict[Type, TypeParser], optional) – An optional dictionary that maps a type to a function that parses a string to that type. These rules will augment the default parsing rules given by get_default_type_parsers() and will take precedent over the default rules if there is a conflict.

Return type:

An instance of the target type parsed from the environment value.