diff --git a/configurations/errors.py b/configurations/errors.py index 102badf..9804896 100644 --- a/configurations/errors.py +++ b/configurations/errors.py @@ -13,10 +13,24 @@ class TermStyles: END = "\033[0m" if os.isatty(sys.stderr.fileno()) else "" +def extract_explanation_lines_from_value(value_instance: 'Value') -> List[str]: + result = [] + + if value_instance.help_text is not None: + result.append(f"Help: {value_instance.help_text}") + + if value_instance.destination_name is not None: + result.append(f"{value_instance.destination_name} is taken from the environment variable " + f"{value_instance.full_environ_name} as a {type(value_instance).__name__}") + + return result + + class SetupError(Exception): """ Exception that gets raised when a configuration class cannot be set up by the importer """ + def __init__(self, msg: str, child_errors: List['ConfigurationError'] = None) -> None: """ :param step_verb: Which step the importer tried to perform (e.g. import, setup) @@ -60,14 +74,9 @@ class ValueRetrievalError(ConfigurationError): :param extra_explanation_lines: Extra lines that will be appended to `ConfigurationError.explanation_lines` in addition the ones automatically generated from the provided *value_instance*. """ - explanation_lines = list(extra_explanation_lines) - if value_instance.destination_name is not None: - explanation_lines.append(f"{value_instance.destination_name} is taken from the environment variable " - f"{value_instance.full_environ_name} as a {type(value_instance).__name__}") - super().__init__( f"Value of {value_instance.destination_name} could not be retrieved from environment", - explanation_lines + list(extra_explanation_lines) + extract_explanation_lines_from_value(value_instance) ) @@ -89,11 +98,7 @@ class ValueProcessingError(ConfigurationError): if hasattr(value_instance, "message"): error += ": " + value_instance.message.format(raw_value) - explanation_lines = list(extra_explanation_lines) - if value_instance.destination_name is not None: - explanation_lines.append(f"{value_instance.destination_name} is taken from the environment variable " - f"{value_instance.full_environ_name} as a {type(value_instance).__name__}") - + explanation_lines = list(extra_explanation_lines) + extract_explanation_lines_from_value(value_instance) explanation_lines.append(f"'{raw_value}' was received but that is invalid") super().__init__(error, explanation_lines) diff --git a/configurations/values.py b/configurations/values.py index 8829d43..a0ddce6 100644 --- a/configurations/values.py +++ b/configurations/values.py @@ -58,7 +58,7 @@ class Value: return instance def __init__(self, default=None, environ=True, environ_name=None, - environ_prefix='DJANGO', environ_required=False, + environ_prefix='DJANGO', environ_required=False, help_text=None, *args, **kwargs): if isinstance(default, Value) and default.default is not None: self.default = copy.copy(default.default) @@ -71,6 +71,7 @@ class Value: self.environ_name = environ_name self.environ_required = environ_required self.destination_name = None + self.help_text = help_text def __str__(self): return str(self.value) diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 879a3b8..0cf7a74 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -4,7 +4,7 @@ from configurations import Configuration, values class Base(Configuration): # Django settings for test_project project. - DEBUG = values.BooleanValue(True, environ=True) + DEBUG = values.BooleanValue(True, environ=True, help_text="Enables or disables django debug mode") ADMINS = ( # ('Your Name', 'your_email@example.com'),