"""Utils for accessing process environment variables""" import os from typing import ( Any, Callable, List, Optional, ) from django.core.exceptions import ImproperlyConfigured NOT_SET = object() def get_environment(name: str, mapper: Optional[Callable[[str], Any]] = None, default=NOT_SET) -> Any: """Return a value with the given name from the process environment variables""" possible_environ_names = [name] for environ_name in possible_environ_names: try: value = os.environ[environ_name] except KeyError: continue else: break else: if default is NOT_SET: raise ImproperlyConfigured('The {} environment variable is not present under names: {}'.format(name, ', '.join(possible_environ_names))) else: return default mapper = mapper or str return mapper(value) def boolean_mapper(value: str) -> bool: """Map a string representation on a boolean value to Python bool""" if value.lower() in {'true', '1', 'yes'}: return True if value.lower() in {'false', '0', 'no'}: return False raise ImproperlyConfigured('Boolean mapper cannot map the {} value to bool'.format(value)) def list_mapper_factory(delimiter: Optional[str] = None, item_mapper: Optional[Callable[[str], Any]] = None) -> Callable[[str], List[Any]]: """Return a function that maps lists serialized to a string with a specified delimiter to a Python list :param delimiter: the item delimiter in the serialized list :param item_mapper: the mapper for list elements :return: the mapper function """ delimiter = delimiter or ',' item_mapper = item_mapper or str def list_mapper(value: str) -> List[Any]: """Map a list serialized to a string to a Python list Assumes an empty string represents an empty list, not a list containing an empty string. :param value: the list serialized to string :return: the parsed list """ if value == '': return [] return [item_mapper(item) for item in value.split(delimiter)] return list_mapper