Skip to content

config

frequenz.sdk.config ¤

Config interface.

Classes¤

frequenz.sdk.config.Config ¤

Stores config variables.

Config variables are read from a file. Only single file can be read. If new file is read, then previous configs will be forgotten.

Source code in frequenz/sdk/config/_config.py
class Config:
    """
    Stores config variables.

    Config variables are read from a file.
    Only single file can be read.
    If new file is read, then previous configs will be forgotten.
    """

    def __init__(self, conf_vars: dict[str, Any]):
        """Instantiate the config store and read config variables from the file.

        Args:
            conf_vars: Dict containing configuration variables
        """
        self._conf_store: dict[str, Any] = conf_vars

    def get(self, key: str, default: Any = None) -> Any:
        """Get the value for the specified key.

        If the key is not in the configs, then return default.

        Args:
            key: Key to be searched.
            default: Value to be returned if the key is not found.  Defaults to
                None.

        Returns:
            value in str format or default.
        """
        return self._conf_store.get(key, default)

    def get_dict(
        self, key_prefix: str, expected_values_type: T | None
    ) -> dict[str, Any]:
        """Get a dictionary based on config key prefixes.

        For example, if key_prefix is "my_dict", then the following config store:
            {
                'some_key': 'some_value',
                'my_dict_key1': 'value1',
                'my_dict_key2': 'value2',
            }
        Will return:
            {
                'key1': 'value1',
                'key2': 'value2',
            }

        Args:
            key_prefix: Only get configuration variables starting with this
                prefix.
            expected_values_type: If provided, the value will be validated against
                this type.

        Returns:
            A dictionary containing the keys prefixed with `key_prefix` as keys
                (but with the prefix removed) and the values as values.
        """
        result: dict[str, Any] = {}
        for key, value in self._conf_store.items():
            if key.startswith(key_prefix):
                new_key = key[len(key_prefix) :]
                if expected_values_type is not None:
                    value = self.get_as(key, expected_values_type)
                result[new_key] = value
        return result

    def get_as(self, key: str, expected_type: Any) -> Any:
        """Get and convert the value to specified type.

        Check if type of the value is as expected.  If type is correct, then
        return converted value.  Otherwise Raise ValueError.

        Type can be:
            * Any typing module type.
            * Any pydantic strict types (e.g. pydantic.StrictInt)

        Args:
            key: Key to be search
            expected_type: type for the value

        Raises:
            ValueError: If can't convert value to the expected type.
            KeyError: If specified key is not in config.

        Returns:
            Value for the specified key, converted to specified type.

        Example:
            For `var1='[1, 2.0, 3.5]'`:
                * `get_as("var1", List[int])` -> `[1,2,3]`
                * `get_as("var1", List[float])` -> `[1.0,2.0,3.5]`
                * `get_as("var1", List[pydantic.StrictInt])` -> [ValueError][]
                * `get_as("var1", List[pydantic.StrictFloat])` -> [ValueError][]

            For `var1='[1,2,3]'`:
                * `get_as("var1", List[pydantic.StrictInt])` -> `[1,2,3]`

        """
        value = self[key]

        if str is expected_type:
            return value

        try:
            obj = json.loads(value)
            metadata = getattr(expected_type, "__metadata__", (None,))[0]
            strict = metadata.strict if isinstance(metadata, Strict) else False
            adapter = TypeAdapter(expected_type)
            parsed_value = adapter.validate_python(obj, strict=strict)
        except (ValidationError, ValueError) as err:
            raise ValueError(
                f"Could not convert config variable: {key} = '{value}' "
                f"to type {str(expected_type)}, err:" + str(err)
            ) from err

        return parsed_value

    def __getitem__(self, key: str) -> Any:
        """Get the value for the specified key.

        If the key is not in the configs, then raise KeyError.

        Args:
            key: key to be searched.

        Raises:
            KeyError: If key is not in found.

        Returns:
            Dictionary if the corresponding value is a subsection in the .toml
                file or a primitive type it is a simple value.
        """
        value = self._conf_store.get(key, None)
        if value is None:
            raise KeyError(f"Unknown config name {key}")

        return value

    def __contains__(self, key: str) -> bool:
        """Return whether the specified key is in the storage.

        Args:
            key: Config variable name.

        Returns:
            True if key is in the storage, otherwise returns False.
        """
        return key in self._conf_store
Functions¤
__contains__ ¤
__contains__(key: str) -> bool

Return whether the specified key is in the storage.

PARAMETER DESCRIPTION
key

Config variable name.

TYPE: str

RETURNS DESCRIPTION
bool

True if key is in the storage, otherwise returns False.

Source code in frequenz/sdk/config/_config.py
def __contains__(self, key: str) -> bool:
    """Return whether the specified key is in the storage.

    Args:
        key: Config variable name.

    Returns:
        True if key is in the storage, otherwise returns False.
    """
    return key in self._conf_store
__getitem__ ¤
__getitem__(key: str) -> Any

Get the value for the specified key.

If the key is not in the configs, then raise KeyError.

PARAMETER DESCRIPTION
key

key to be searched.

TYPE: str

RAISES DESCRIPTION
KeyError

If key is not in found.

RETURNS DESCRIPTION
Any

Dictionary if the corresponding value is a subsection in the .toml file or a primitive type it is a simple value.

Source code in frequenz/sdk/config/_config.py
def __getitem__(self, key: str) -> Any:
    """Get the value for the specified key.

    If the key is not in the configs, then raise KeyError.

    Args:
        key: key to be searched.

    Raises:
        KeyError: If key is not in found.

    Returns:
        Dictionary if the corresponding value is a subsection in the .toml
            file or a primitive type it is a simple value.
    """
    value = self._conf_store.get(key, None)
    if value is None:
        raise KeyError(f"Unknown config name {key}")

    return value
__init__ ¤
__init__(conf_vars: dict[str, Any])

Instantiate the config store and read config variables from the file.

PARAMETER DESCRIPTION
conf_vars

Dict containing configuration variables

TYPE: dict[str, Any]

Source code in frequenz/sdk/config/_config.py
def __init__(self, conf_vars: dict[str, Any]):
    """Instantiate the config store and read config variables from the file.

    Args:
        conf_vars: Dict containing configuration variables
    """
    self._conf_store: dict[str, Any] = conf_vars
get ¤
get(key: str, default: Any = None) -> Any

Get the value for the specified key.

If the key is not in the configs, then return default.

PARAMETER DESCRIPTION
key

Key to be searched.

TYPE: str

default

Value to be returned if the key is not found. Defaults to None.

TYPE: Any DEFAULT: None

RETURNS DESCRIPTION
Any

value in str format or default.

Source code in frequenz/sdk/config/_config.py
def get(self, key: str, default: Any = None) -> Any:
    """Get the value for the specified key.

    If the key is not in the configs, then return default.

    Args:
        key: Key to be searched.
        default: Value to be returned if the key is not found.  Defaults to
            None.

    Returns:
        value in str format or default.
    """
    return self._conf_store.get(key, default)
get_as ¤
get_as(key: str, expected_type: Any) -> Any

Get and convert the value to specified type.

Check if type of the value is as expected. If type is correct, then return converted value. Otherwise Raise ValueError.

Type can be
  • Any typing module type.
  • Any pydantic strict types (e.g. pydantic.StrictInt)
PARAMETER DESCRIPTION
key

Key to be search

TYPE: str

expected_type

type for the value

TYPE: Any

RAISES DESCRIPTION
ValueError

If can't convert value to the expected type.

KeyError

If specified key is not in config.

RETURNS DESCRIPTION
Any

Value for the specified key, converted to specified type.

Example

For var1='[1, 2.0, 3.5]': * get_as("var1", List[int]) -> [1,2,3] * get_as("var1", List[float]) -> [1.0,2.0,3.5] * get_as("var1", List[pydantic.StrictInt]) -> ValueError * get_as("var1", List[pydantic.StrictFloat]) -> ValueError

For var1='[1,2,3]': * get_as("var1", List[pydantic.StrictInt]) -> [1,2,3]

Source code in frequenz/sdk/config/_config.py
def get_as(self, key: str, expected_type: Any) -> Any:
    """Get and convert the value to specified type.

    Check if type of the value is as expected.  If type is correct, then
    return converted value.  Otherwise Raise ValueError.

    Type can be:
        * Any typing module type.
        * Any pydantic strict types (e.g. pydantic.StrictInt)

    Args:
        key: Key to be search
        expected_type: type for the value

    Raises:
        ValueError: If can't convert value to the expected type.
        KeyError: If specified key is not in config.

    Returns:
        Value for the specified key, converted to specified type.

    Example:
        For `var1='[1, 2.0, 3.5]'`:
            * `get_as("var1", List[int])` -> `[1,2,3]`
            * `get_as("var1", List[float])` -> `[1.0,2.0,3.5]`
            * `get_as("var1", List[pydantic.StrictInt])` -> [ValueError][]
            * `get_as("var1", List[pydantic.StrictFloat])` -> [ValueError][]

        For `var1='[1,2,3]'`:
            * `get_as("var1", List[pydantic.StrictInt])` -> `[1,2,3]`

    """
    value = self[key]

    if str is expected_type:
        return value

    try:
        obj = json.loads(value)
        metadata = getattr(expected_type, "__metadata__", (None,))[0]
        strict = metadata.strict if isinstance(metadata, Strict) else False
        adapter = TypeAdapter(expected_type)
        parsed_value = adapter.validate_python(obj, strict=strict)
    except (ValidationError, ValueError) as err:
        raise ValueError(
            f"Could not convert config variable: {key} = '{value}' "
            f"to type {str(expected_type)}, err:" + str(err)
        ) from err

    return parsed_value
get_dict ¤
get_dict(
    key_prefix: str, expected_values_type: T | None
) -> dict[str, Any]

Get a dictionary based on config key prefixes.

For example, if key_prefix is "my_dict", then the following config store: { 'some_key': 'some_value', 'my_dict_key1': 'value1', 'my_dict_key2': 'value2', } Will return: { 'key1': 'value1', 'key2': 'value2', }

PARAMETER DESCRIPTION
key_prefix

Only get configuration variables starting with this prefix.

TYPE: str

expected_values_type

If provided, the value will be validated against this type.

TYPE: T | None

RETURNS DESCRIPTION
dict[str, Any]

A dictionary containing the keys prefixed with key_prefix as keys (but with the prefix removed) and the values as values.

Source code in frequenz/sdk/config/_config.py
def get_dict(
    self, key_prefix: str, expected_values_type: T | None
) -> dict[str, Any]:
    """Get a dictionary based on config key prefixes.

    For example, if key_prefix is "my_dict", then the following config store:
        {
            'some_key': 'some_value',
            'my_dict_key1': 'value1',
            'my_dict_key2': 'value2',
        }
    Will return:
        {
            'key1': 'value1',
            'key2': 'value2',
        }

    Args:
        key_prefix: Only get configuration variables starting with this
            prefix.
        expected_values_type: If provided, the value will be validated against
            this type.

    Returns:
        A dictionary containing the keys prefixed with `key_prefix` as keys
            (but with the prefix removed) and the values as values.
    """
    result: dict[str, Any] = {}
    for key, value in self._conf_store.items():
        if key.startswith(key_prefix):
            new_key = key[len(key_prefix) :]
            if expected_values_type is not None:
                value = self.get_as(key, expected_values_type)
            result[new_key] = value
    return result