diff --git a/README.md b/README.md index 92fd8e5..6ab7ac9 100644 --- a/README.md +++ b/README.md @@ -158,15 +158,11 @@ another_val: [**`main.py`**](https://github.com/bybatkhuu/module.python-config/blob/main/examples/simple/main.py) ```python -import sys import pprint -import logging - -from onion_config import ConfigLoader, BaseConfig +from loguru import logger -logging.basicConfig(stream=sys.stdout, level=logging.INFO) -logger = logging.getLogger(__name__) +from onion_config import ConfigLoader, BaseConfig class ConfigSchema(BaseConfig): @@ -180,8 +176,8 @@ except Exception: exit(2) if __name__ == "__main__": - logger.info(f" App name: {config.app['name']}") - logger.info(f" Config:\n{pprint.pformat(config.model_dump())}\n") + logger.info(f"App name: {config.app['name']}") + logger.info(f"Config:\n{pprint.pformat(config.model_dump())}\n") ``` Run the [**`examples/simple`**](https://github.com/bybatkhuu/module.python-config/tree/main/examples/simple): @@ -195,8 +191,8 @@ python ./main.py **Output**: ```txt -INFO:__main__: App name: New App -INFO:__main__: Config: +2023-09-01 18:23:35.551 | INFO | __main__::22 - App name: New App +2023-09-01 18:23:35.551 | INFO | __main__::23 - Config: {'another_val': {'extra': 1}, 'app': {'description': 'Description of my app.', 'name': 'New App', @@ -277,16 +273,6 @@ extra: } ``` -[**`logger.py`**](https://github.com/bybatkhuu/module.python-config/blob/main/examples/advanced/logger.py): - -```python -import sys -import logging - -logging.basicConfig(stream=sys.stdout, level=logging.INFO) -logger = logging.getLogger(__name__) -``` - [**`schema.py`**](https://github.com/bybatkhuu/module.python-config/blob/main/examples/advanced/schema.py): ```python @@ -328,9 +314,10 @@ class ConfigSchema(BaseConfig): [**`config.py`**](https://github.com/bybatkhuu/module.python-config/blob/main/examples/advanced/config.py): ```python +from loguru import logger + from onion_config import ConfigLoader -from logger import logger from schema import ConfigSchema @@ -348,7 +335,7 @@ try: env_file_paths=[".env", ".env.base", ".env.prod"], pre_load_hook=_pre_load_hook, config_data={"base": "start_value"}, - quiet=False, + warn_mode="LOG", ) # Main config object: config: ConfigSchema = _config_loader.load() @@ -362,24 +349,25 @@ except Exception: ```python import pprint +from loguru import logger + from config import config -from logger import logger if __name__ == "__main__": - logger.info(f" ENV: {config.env}") - logger.info(f" DEBUG: {config.debug}") - logger.info(f" Extra: {config.extra_val}") - logger.info(f" Logger: {config.logger}") - logger.info(f" App: {config.app}") - logger.info(f" Secret: '{config.app.secret.get_secret_value()}'\n") - logger.info(f" Config:\n{pprint.pformat(config.model_dump())}\n") + logger.info(f"ENV: {config.env}") + logger.info(f"DEBUG: {config.debug}") + logger.info(f"Extra: {config.extra_val}") + logger.info(f"Logger: {config.logger}") + logger.info(f"App: {config.app}") + logger.info(f"Secret: '{config.app.secret.get_secret_value()}'\n") + logger.info(f"Config:\n{pprint.pformat(config.model_dump())}\n") try: # This will raise ValidationError config.app.port = 8443 except Exception as e: - logger.error(f" {e}\n") + logger.error(f"{e}\n") ``` Run the [**`examples/advanced`**](https://github.com/bybatkhuu/module.python-config/tree/main/examples/advanced): @@ -393,16 +381,17 @@ python ./app.py **Output**: ```txt -WARNING:onion_config._base:'/home/user/workspaces/projects/onion_config/examples/advanced/.env' file is not exist! -WARNING:onion_config._base:'/not_exists/path/configs_3' directory is not exist! -INFO:logger: ENV: production -INFO:logger: DEBUG: True -INFO:logger: Extra: Something extra! -INFO:logger: Logger: {'output': 'stdout', 'level': 'info'} -INFO:logger: App: name='New App' bind_host='0.0.0.0' port=80 secret=SecretStr('**********') version='0.0.1' description=None -INFO:logger: Secret: 'my_secret' - -INFO:logger: Config: +2023-09-01 18:25:43.744 | INFO | onion_config._base:load:129 - Loading all configs... +2023-09-01 18:25:43.747 | WARNING | onion_config._base:_load_configs_dir:242 - '/not_exists/path/configs_3' directory is not exist! +2023-09-01 18:25:43.748 | SUCCESS | onion_config._base:load:156 - Successfully loaded all configs! +2023-09-01 18:25:43.748 | INFO | __main__::12 - ENV: production +2023-09-01 18:25:43.748 | INFO | __main__::13 - DEBUG: True +2023-09-01 18:25:43.748 | INFO | __main__::14 - Extra: Something extra! +2023-09-01 18:25:43.748 | INFO | __main__::15 - Logger: {'output': 'stdout', 'level': 'info'} +2023-09-01 18:25:43.748 | INFO | __main__::16 - App: name='New App' bind_host='0.0.0.0' port=80 secret=SecretStr('**********') version='0.0.1' description=None +2023-09-01 18:25:43.748 | INFO | __main__::17 - Secret: 'my_secret' + +2023-09-01 18:25:43.748 | INFO | __main__::18 - Config: {'app': {'bind_host': '0.0.0.0', 'description': None, 'name': 'New App', @@ -416,7 +405,7 @@ INFO:logger: Config: 'extra_val': 'Something extra!', 'logger': {'level': 'info', 'output': 'stdout'}} -ERROR:logger: 1 validation error for AppConfig +2023-09-01 18:25:43.748 | ERROR | __main__::24 - 1 validation error for AppConfig port Instance is frozen [type=frozen_instance, input_value=8443, input_type=int] ``` diff --git a/examples/advanced/app.py b/examples/advanced/app.py index 94bc0af..fc3b8c1 100755 --- a/examples/advanced/app.py +++ b/examples/advanced/app.py @@ -3,21 +3,22 @@ import pprint +from loguru import logger + from config import config -from logger import logger if __name__ == "__main__": - logger.info(f" ENV: {config.env}") - logger.info(f" DEBUG: {config.debug}") - logger.info(f" Extra: {config.extra_val}") - logger.info(f" Logger: {config.logger}") - logger.info(f" App: {config.app}") - logger.info(f" Secret: '{config.app.secret.get_secret_value()}'\n") - logger.info(f" Config:\n{pprint.pformat(config.model_dump())}\n") + logger.info(f"ENV: {config.env}") + logger.info(f"DEBUG: {config.debug}") + logger.info(f"Extra: {config.extra_val}") + logger.info(f"Logger: {config.logger}") + logger.info(f"App: {config.app}") + logger.info(f"Secret: '{config.app.secret.get_secret_value()}'\n") + logger.info(f"Config:\n{pprint.pformat(config.model_dump())}\n") try: # This will raise ValidationError config.app.port = 8443 except Exception as e: - logger.error(f" {e}\n") + logger.error(f"{e}\n") diff --git a/examples/advanced/config.py b/examples/advanced/config.py index df5ecc8..59d3619 100644 --- a/examples/advanced/config.py +++ b/examples/advanced/config.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- +from loguru import logger + from onion_config import ConfigLoader -from logger import logger from schema import ConfigSchema @@ -12,6 +13,7 @@ def _pre_load_hook(config_data: dict) -> dict: config_data["extra_val"] = "Something extra!" return config_data + config = None try: _config_loader = ConfigLoader( @@ -20,7 +22,7 @@ def _pre_load_hook(config_data: dict) -> dict: env_file_paths=[".env", ".env.base", ".env.prod"], pre_load_hook=_pre_load_hook, config_data={"base": "start_value"}, - quiet=False, + warn_mode="LOG", ) # Main config object: config: ConfigSchema = _config_loader.load() diff --git a/examples/advanced/logger.py b/examples/advanced/logger.py deleted file mode 100644 index 3856b32..0000000 --- a/examples/advanced/logger.py +++ /dev/null @@ -1,7 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import logging - -logging.basicConfig(stream=sys.stdout, level=logging.INFO) -logger = logging.getLogger(__name__) diff --git a/examples/simple/main.py b/examples/simple/main.py index 86bf3f5..3668b84 100755 --- a/examples/simple/main.py +++ b/examples/simple/main.py @@ -1,15 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import sys import pprint -import logging - -from onion_config import ConfigLoader, BaseConfig +from loguru import logger -logging.basicConfig(stream=sys.stdout, level=logging.INFO) -logger = logging.getLogger(__name__) +from onion_config import ConfigLoader, BaseConfig class ConfigSchema(BaseConfig): @@ -23,5 +19,5 @@ class ConfigSchema(BaseConfig): exit(2) if __name__ == "__main__": - logger.info(f" App name: {config.app['name']}") - logger.info(f" Config:\n{pprint.pformat(config.model_dump())}\n") + logger.info(f"App name: {config.app['name']}") + logger.info(f"Config:\n{pprint.pformat(config.model_dump())}\n") diff --git a/onion_config/__init__.py b/onion_config/__init__.py index 48504f0..f07246a 100644 --- a/onion_config/__init__.py +++ b/onion_config/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from ._base import ConfigLoader, BaseConfig, __version__ +from ._base import ConfigLoader, BaseConfig, WarnEnum, __version__ diff --git a/onion_config/_base.py b/onion_config/_base.py index c01bb89..b4ebc22 100644 --- a/onion_config/_base.py +++ b/onion_config/_base.py @@ -5,24 +5,22 @@ import glob import json import copy -import logging -from typing import Union, List, Callable, Type +from typing import Union, List, Callable, Type, Dict, Any ## Third-party libraries import yaml from dotenv import load_dotenv +from loguru import logger from pydantic import BaseModel, validate_call from pydantic_settings import BaseSettings ## Internal modules +from ._const import WarnEnum from ._utils import deep_merge -from ._schema import BaseConfig +from ._schemas import BaseConfig from .__version__ import __version__ -logger = logging.getLogger(__name__) - - class ConfigLoader: """A core class of `onion_config` module to use as the main config loader. @@ -43,7 +41,7 @@ class ConfigLoader: env_file_paths (str ): Dotenv file paths as to load. Defaults to [ConfigLoader._ENV_FILE_PATH]. required_envs (str ): Required environment variables to check. Defaults to []. pre_load_hook (function ): Custom pre-load method, this method will executed before validating `config`. Defaults to `ConfigLoader._PRE_LOAD_HOOK`. - quiet (bool ): If False, will show warning messages. Defaults to True. + warn_mode (WarnEnum ): Warning mode to handle warnings. Defaults to `WarnEnum.IGNORE`. Methods: load() : Load and validate every configs into `config`. @@ -72,8 +70,8 @@ def __init__( required_envs: List[str] = [], pre_load_hook: Callable = _PRE_LOAD_HOOK, extra_dir: Union[str, None] = None, - config_data: dict = {}, - quiet: bool = True, + config_data: Dict[str, Any] = {}, + warn_mode: WarnEnum = WarnEnum.IGNORE, auto_load: bool = False, ): """ConfigLoader constructor method. @@ -88,7 +86,7 @@ def __init__( pre_load_hook (function , optional): Custom pre-load method, this method will executed before validating `config`. Defaults to `ConfigLoader._PRE_LOAD_HOOK`. extra_dir (Union[str, None] , optional): Extra configs directory to load extra config files. Defaults to None. config_data (dict , optional): Base config data as before everything. Defaults to {}. - quiet (bool , optional): If False, will show warning messages. Defaults to True. + warn_mode (WarnEnum , optional): Warning mode to handle warnings. Defaults to `WarnEnum.IGNORE`. auto_load (bool , optional): Auto load configs on init or not. Defaults to False. """ @@ -100,7 +98,7 @@ def __init__( if extra_dir: self.extra_dir = extra_dir self.config_data = config_data - self.quiet = quiet + self.warn_mode = warn_mode if auto_load: self.load() @@ -127,6 +125,12 @@ def load(self) -> Union[BaseConfig, BaseSettings, BaseModel]: Union[BaseConfig, BaseSettings, BaseModel]: Main config object (based on `config_schema`) for project. """ + _message = "Loading all configs..." + if self.warn_mode == WarnEnum.LOG: + logger.info(_message) + elif self.warn_mode == WarnEnum.DEBUG: + logger.debug(_message) + self._load_dotenv_files() self._check_required_envs() self._load_configs_dirs() @@ -134,7 +138,7 @@ def load(self) -> Union[BaseConfig, BaseSettings, BaseModel]: try: # 5. Execute `pre_load_hook` method to modify `config_data`: - self.config_data: dict = self.pre_load_hook(self.config_data) + self.config_data: Dict[str, Any] = self.pre_load_hook(self.config_data) except Exception: logger.critical("Failed to execute `pre_load_hook` method:") raise @@ -148,6 +152,12 @@ def load(self) -> Union[BaseConfig, BaseSettings, BaseModel]: logger.critical("Failed to init `config_schema`:") raise + _message = "Successfully loaded all configs!" + if self.warn_mode == WarnEnum.LOG: + logger.success(_message) + elif self.warn_mode == WarnEnum.DEBUG: + logger.debug(_message) + return self.config def _load_dotenv_files(self): @@ -170,8 +180,13 @@ def _load_dotenv_file(self, env_file_path: str): if os.path.isfile(env_file_path): load_dotenv(dotenv_path=env_file_path, override=True, encoding="utf-8") else: - if not self.quiet: - logger.warning(f"'{env_file_path}' file is not exist!") + _message = f"'{env_file_path}' file is not exist!" + if self.warn_mode == WarnEnum.RAISE: + raise FileNotFoundError(_message) + # elif self.warn_mode == WarnEnum.LOG: + # logger.warning(_message) + elif self.warn_mode == WarnEnum.DEBUG: + logger.debug(_message) def _check_required_envs(self): """2. Check if required environment variables exist or not. @@ -221,8 +236,13 @@ def _load_configs_dir(self, configs_dir: str): # elif _file_path.lower().endswith(".toml"): # self._load_toml_file(file_path=_file_path) else: - if not self.quiet: - logger.warning(f"'{configs_dir}' directory is not exist!") + _message = f"'{configs_dir}' directory is not exist!" + if self.warn_mode == WarnEnum.RAISE: + raise FileNotFoundError(_message) + elif self.warn_mode == WarnEnum.LOG: + logger.warning(_message) + elif self.warn_mode == WarnEnum.DEBUG: + logger.debug(_message) @validate_call def _load_yaml_file(self, file_path: str): @@ -243,9 +263,6 @@ def _load_yaml_file(self, file_path: str): except Exception: logger.critical(f"Failed to load '{file_path}' YAML config file:") raise - else: - if not self.quiet: - logger.warning(f"'{file_path}' YAML config file is not exist!") @validate_call def _load_json_file(self, file_path: str): @@ -266,9 +283,6 @@ def _load_json_file(self, file_path: str): except Exception: logger.critical(f"Failed to load '{file_path}' JSON config file:") raise - else: - if not self.quiet: - logger.warning(f"'{file_path}' JSON config file is not exist!") # @validate_call # def _load_toml_file(self, file_path: str): @@ -291,9 +305,6 @@ def _load_json_file(self, file_path: str): # except Exception: # logger.critical(f"Failed to load '{file_path}' TOML config file:") # raise - # else: - # if not self.quiet: - # logger.warning(f"'{file_path}' TOML config file is not exist!") def _load_extra_dir(self): """4. Load extra config files from `extra_dir` into `config_data`.""" @@ -373,7 +384,7 @@ def config_schema( ## config_data ## @property - def config_data(self) -> dict: + def config_data(self) -> Dict[str, Any]: try: return self.__config_data except AttributeError: @@ -382,7 +393,7 @@ def config_data(self) -> dict: return self.__config_data @config_data.setter - def config_data(self, config_data: dict): + def config_data(self, config_data: Dict[str, Any]): if not isinstance(config_data, dict): raise TypeError( f"`config_data` attribute type {type(config_data)} is invalid, must be a ." @@ -537,22 +548,30 @@ def pre_load_hook(self, pre_load_hook: Callable): ## pre_load_hook ## - ## quiet ## + ## warn_mode ## @property - def quiet(self) -> bool: + def warn_mode(self) -> WarnEnum: try: - return self.__quiet + return self.__warn_mode except AttributeError: - return True + return WarnEnum.IGNORE - @quiet.setter - def quiet(self, quiet: bool): - if not isinstance(quiet, bool): + @warn_mode.setter + def warn_mode(self, warn_mode: Union[WarnEnum, str]): + if (not isinstance(warn_mode, WarnEnum)) and (not isinstance(warn_mode, str)): raise TypeError( - f"'quiet' attribute type {type(quiet)} is invalid, must be a !" + f"'warn_mode' attribute type {type(warn_mode)} is invalid, must be a or !" ) - self.__quiet = quiet + if isinstance(warn_mode, str): + try: + warn_mode = WarnEnum(warn_mode) + except ValueError: + raise ValueError( + f"'warn_mode' attribute value '{warn_mode}' is invalid, must be a or 'RAISE', 'LOG', 'DEBUG', 'IGNORE'!" + ) + + self.__warn_mode = warn_mode - ## quiet ## + ## warn_mode ## ### ATTRIBUTES ### diff --git a/onion_config/_const.py b/onion_config/_const.py new file mode 100644 index 0000000..f8745e9 --- /dev/null +++ b/onion_config/_const.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +from enum import Enum + + +class WarnEnum(str, Enum): + RAISE = "RAISE" + LOG = "LOG" + DEBUG = "DEBUG" + IGNORE = "IGNORE" diff --git a/onion_config/_schema.py b/onion_config/_schemas.py similarity index 100% rename from onion_config/_schema.py rename to onion_config/_schemas.py diff --git a/requirements.txt b/requirements.txt index 35f941f..fcebf59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ python-dotenv>=1.0.0,<2.0.0 PyYAML>=6.0.1,<7.0 +loguru>=0.7.2,<1.0.0 pydantic[email]>=2.1.1,<3.0.0 pydantic-settings>=2.0.3,<3.0.0 diff --git a/scripts/test.sh b/scripts/test.sh index 7db84b9..ae7fdbd 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -78,12 +78,12 @@ main() fi if [ "${_IS_VERBOSE}" == true ]; then - _verbose_param="-vv" + _verbose_param="-svv" fi echoInfo "Running test..." # shellcheck disable=SC2086 - python -m pytest -sv ${_coverage_param} ${_logging_param} ${_verbose_param} || exit 2 + python -m pytest -v ${_coverage_param} ${_logging_param} ${_verbose_param} || exit 2 echoOk "Done." } diff --git a/setup.py b/setup.py index b6202ff..181d7cc 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ install_requires=[ "python-dotenv>=1.0.0,<2.0.0", "PyYAML>=6.0.1,<7.0", + "loguru>=0.7.2,<1.0.0", "pydantic[email]>=2.1.1,<3.0.0", "pydantic-settings>=2.0.3,<3.0.0", ], diff --git a/tests/test_onion_config.py b/tests/test_onion_config.py index 506ee68..16852ff 100644 --- a/tests/test_onion_config.py +++ b/tests/test_onion_config.py @@ -2,19 +2,20 @@ import os import logging -from typing import Callable +from pathlib import Path +from typing import Callable, Tuple, Dict, Any import pytest from pydantic import Field -from onion_config import ConfigLoader, BaseConfig +from onion_config import ConfigLoader, BaseConfig, WarnEnum logger = logging.getLogger(__name__) @pytest.fixture -def config_loader(): +def config_loader() -> ConfigLoader: _config_loader = ConfigLoader() yield _config_loader @@ -23,7 +24,7 @@ def config_loader(): @pytest.fixture -def configs_dir(tmp_path): +def configs_dir(tmp_path: Path) -> Tuple[str, Dict[str, Any]]: _tmp_configs_dir_pl = tmp_path / "configs" _tmp_configs_dir_pl.mkdir() _tmp_json_file_pl = (_tmp_configs_dir_pl / "test.json").resolve() @@ -49,7 +50,7 @@ def configs_dir(tmp_path): ) -def test_init(config_loader): +def test_init(config_loader: ConfigLoader): logger.info("Testing initialization of 'ConfigLoader'...") assert isinstance(config_loader, ConfigLoader) @@ -66,12 +67,14 @@ def test_init(config_loader): assert config_loader.extra_dir == None assert isinstance(config_loader.config_data, dict) assert config_loader.config_data == {} + assert isinstance(config_loader.warn_mode, WarnEnum) + assert config_loader.warn_mode == WarnEnum.IGNORE assert config_loader.config == None logger.info("Done: Initialization of 'ConfigLoader'.\n") -def test_load(config_loader): +def test_load(config_loader: ConfigLoader): logger.info("Testing 'load' method...") _config: BaseConfig = config_loader.load() @@ -83,7 +86,7 @@ def test_load(config_loader): @pytest.mark.parametrize( - "config_schema, configs_dirs, env_file_paths, required_envs, pre_load_hook, extra_dir, config_data, quiet, expected", + "config_schema, configs_dirs, env_file_paths, required_envs, pre_load_hook, extra_dir, config_data, warn_mode, expected", [ ( BaseConfig, @@ -93,7 +96,7 @@ def test_load(config_loader): lambda config_data: config_data, None, {}, - True, + "IGNORE", {}, ) ], @@ -106,7 +109,7 @@ def test_config_load( pre_load_hook, extra_dir, config_data, - quiet, + warn_mode, expected, ): logger.info("Testing main config cases...") @@ -119,7 +122,7 @@ def test_config_load( pre_load_hook=pre_load_hook, extra_dir=extra_dir, config_data=config_data, - quiet=quiet, + warn_mode=warn_mode, ).load() assert isinstance(_config, config_schema) @@ -136,7 +139,9 @@ def test_config_load( ("TEST_ENV_VAR=123", "123"), ], ) -def test_load_dotenv_files(tmp_path, config_loader, content, expected): +def test_load_dotenv_files( + tmp_path: Path, config_loader: ConfigLoader, content: str, expected: str +): logger.info("Testing '_load_dotenv_files' method...") _tmp_envs_dir_pl = tmp_path / "envs" @@ -155,7 +160,7 @@ def test_load_dotenv_files(tmp_path, config_loader, content, expected): logger.info("Done: '_load_dotenv_files' method.\n") -def test_check_required_envs(config_loader): +def test_check_required_envs(config_loader: ConfigLoader): logger.info("Testing '_check_required_envs' method...") os.environ["REQUIRED_ENV_VAR"] = "required_value" @@ -175,7 +180,9 @@ def test_check_required_envs(config_loader): logger.info("Done: '_check_required_envs' method.\n") -def test_load_configs_dirs(config_loader, configs_dir): +def test_load_configs_dirs( + config_loader: ConfigLoader, configs_dir: Tuple[str, Dict[str, Any]] +): logger.info("Testing '_load_configs_dirs' method...") _configs_dir, _expected = configs_dir @@ -191,7 +198,9 @@ def test_load_configs_dirs(config_loader, configs_dir): logger.info("Done: '_load_configs_dirs' method.\n") -def test_load_extra_dir(tmp_path, config_loader, configs_dir): +def test_load_extra_dir( + tmp_path, config_loader: ConfigLoader, configs_dir: Tuple[str, Dict[str, Any]] +): logger.info("Testing '_load_extra_dir' method...") _configs_dir, _expected = configs_dir @@ -221,7 +230,7 @@ def test_load_extra_dir(tmp_path, config_loader, configs_dir): logger.info("Done: '_load_extra_dir' method.\n") -def test_config(config_loader): +def test_config(config_loader: ConfigLoader): logger.info("Testing 'config' property...") class _ConfigSchema(BaseConfig): @@ -248,7 +257,7 @@ class _ConfigSchema(BaseConfig): logger.info("Done: 'config' property.\n") -def test_config_schema(config_loader): +def test_config_schema(config_loader: ConfigLoader): logger.info("Testing 'config_schema' property...") class _ConfigSchema(BaseConfig): @@ -266,7 +275,7 @@ class _ConfigSchema(BaseConfig): logger.info("Done: 'config_schema' property.\n") -def test_config_data(config_loader): +def test_config_data(config_loader: ConfigLoader): logger.info("Testing 'config_data' property...") _config_data = {"test_var": "test_val"} @@ -287,7 +296,7 @@ def test_config_data(config_loader): logger.info("Done: 'config_data' property.\n") -def test_configs_dirs(config_loader): +def test_configs_dirs(config_loader: ConfigLoader): logger.info("Testing 'configs_dirs' property...") config_loader.configs_dirs = "/tmp/pytest/configs_dir" @@ -304,7 +313,7 @@ def test_configs_dirs(config_loader): logger.info("Done: 'configs_dirs' property.\n") -def test_extra_dir(config_loader): +def test_extra_dir(config_loader: ConfigLoader): logger.info("Testing 'extra_dir' property...") config_loader.extra_dir = "/tmp/pytest/extra_dir" @@ -321,7 +330,7 @@ def test_extra_dir(config_loader): logger.info("Done: 'extra_dir' property.\n") -def test_env_file_paths(config_loader): +def test_env_file_paths(config_loader: ConfigLoader): logger.info("Testing 'env_file_paths' property...") config_loader.env_file_paths = "/tmp/pytest/.env" @@ -338,7 +347,7 @@ def test_env_file_paths(config_loader): logger.info("Done: 'env_file_paths' property.\n") -def test_required_envs(config_loader): +def test_required_envs(config_loader: ConfigLoader): logger.info("Testing 'required_envs' property...") config_loader.required_envs = ["TEST_ENV_VAR"] @@ -359,7 +368,7 @@ def test_required_envs(config_loader): logger.info("Done: 'required_envs' property.\n") -def test_pre_load_hook(config_loader): +def test_pre_load_hook(config_loader: ConfigLoader): logger.info("Testing 'pre_load_hook' property...") def _pre_load_hook(config_data):