Source code for certdeploy.errors

"""Exceptions to use with both CertDeploy servers and CertDeploy clients."""

from typing import Any


def _double_quote(value: str) -> str:
    """Return a string with added surrounding double quotes."""
    return f'"{value}"'


[docs] class CertDeployError(Exception): """CertDeploy specific error."""
[docs] class ConfigError(CertDeployError): """Configuration error."""
[docs] class ConfigInvalid(ConfigError): """Invalid configuration exception. Arguments: key: The config key. value: The value given in the config. must: If the value must have been something set this to be that thing. Defaults to `None`. config_desc: The description of the config if needed. Defaults to an empty string. Example: An example of formatting using `must`. ConfigInvalid( 'renew_unit', None, must='not be a weekday if `renew_every` is set and not' ' 1' ) -> ('Invalid value "None" for `renew_unit`. `renew_unit` ' 'must not be a weekday if `renew_every` is set and ' 'not 1.') """ def __init__( self, key: str, value: Any, must: str = None, # noqa: D107 config_desc: str = '', ): # Add a space to the description if it is set if config_desc: config_desc = f'{config_desc} ' if must: super().__init__( f'Invalid value "{value}" for {config_desc}' f'`{key}`. `{key}` must {must}.', ) else: super().__init__( f'Invalid value "{value}" for {config_desc}`{key}`.', )
[docs] class ConfigInvalidNumber(ConfigInvalid): """Invalid numeric configuration exception. Arguments: key: The config key. value: The value given in the config. is_type: The name of the required number type. Defaults to `'number'`. optional: If `True` `'if set'` is added to the end of the message. Defaults to `False`. gt: Changes the phrasing to reflect the config must be 'greater than' the value of `gt`. Defaults to `None`. lt: Changes the phrasing to reflect the config must be 'less than' the value of `lt`. Defaults to `None`. ge: Changes the phrasing to reflect the config must be 'greater than or equal to' the value of `ge`. Defaults to `None`. le: Changes the phrasing to reflect the config must be 'less than or equal to' the value of `le`. Defaults to `None`. config_desc: The description of the config if needed. Defaults to an empty string. """ def __init__( self, key: str, value: Any, is_type: str = 'number', optional: bool = False, gt: str = None, lt: str = None, ge: str = None, le: str = None, config_desc: str = '', ): if is_type == int: is_type = 'integer' elif is_type == float: is_type = 'float' if not isinstance(is_type, str): is_type = str(is_type) bounds = [] bounds_str = '' if gt is not None: bounds.append(f'greater than {gt}') if lt is not None: bounds.append(f'less than {lt}') if ge is not None: bounds.append(f'greater than or equal to {ge}') if le is not None: bounds.append(f'less than or equal to {le}') if bounds: bounds_str = f' {" and ".join(bounds)}' if_set = '' if optional: if_set = ' if set' a_or_an = 'a' if is_type[0] in ('a', 'e', 'i', 'o', 'u'): a_or_an = 'an' super().__init__( key, value, must=f'be {a_or_an} {is_type}{bounds_str}{if_set}', config_desc=config_desc, )
[docs] class ConfigInvalidChoice(ConfigInvalid): """Invalid configuration from selection. Note: `choices` is a list of two or more choices. An exception is raised from this exception if a list of length one is given. The universe may impload if that happens. Arguments: key: The config key. value: The value given in the config. must: If the value must have been something set this to be that thing. Defaults to `None`. See `ConfigInvalid` for an example. choices: A list of two or more valid values for the config. If there are only two choices they will be listed as `'either A or B'`. If there are three or more choices they will be listed as a comma separated list with and oxford comma and an or for the last choice. quote: If `True` add double quotes to the choices. Defaults to `True`. config_desc: The description of the config if needed. Defaults to an empty string. Raises: ValueError: When the number of choices is invalid. """ def __init__( self, key: str, value: Any, choices: list[Any], quote: bool = True, config_desc: str = '', ): if quote: choices = [_double_quote(c) for c in choices] if len(choices) == 2: must = f'be either {" or ".join(choices)}' elif len(choices) >= 3: must = f'be {", ".join(choices[:-1])}, or {choices[-1]}' else: raise ValueError('Invalid number of choices') super().__init__(key, value, must=must, config_desc=config_desc)
[docs] class ConfigInvalidPath(ConfigInvalid): """Invalid file system path configuation exception. Note: One or more of `bad_format`, `exist`, or `writable` must be `True` or an exception is raised from this exception . The universe may impload if that happens. Arguments: key: The config key. value: The value given in the config. exist: If `True` the path must exist. Defaults to `True`. writable: If `True` the path must be writable. Defaults to `False`. bad_format: If `True` the format of `value` is invalid. Defaults to `False`. is_type: If set the message will be phrased as needing to be the value of `is_type`. Defaults to an empty string. config_desc: The description of the config if needed. Defaults to an empty string. Raises: ValueError: When one or more of `bad_format`, `exist`, or `writable` must be True. """ def __init__( self, key: str, value: str, exist: bool = True, writable: bool = False, bad_format: bool = False, is_type: str = '', config_desc: str = '', ): if bad_format: super().__init__( key, value, must='be a file system path', config_desc=config_desc, ) return if writable and is_type: must = f'exist and be a {is_type} writable by CertDeploy' elif writable: must = 'exist and be writable by CertDeploy' elif exist and is_type: must = f'be a {is_type} that exists' elif exist: must = 'exist' else: raise ValueError( 'One or more of `bad_format`, `exist`, or `writable` must be ' '`True`.', ) super().__init__(key, value, must=must, config_desc=config_desc)