Skip to content

Commit

Permalink
Merge pull request #80 from valentingol/logging
Browse files Browse the repository at this point in the history
✨ Improve cliconfig logging
  • Loading branch information
valentingol committed Jan 12, 2024
2 parents 8c4d480 + 8392d34 commit b9de646
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 17 deletions.
7 changes: 6 additions & 1 deletion cliconfig/__init__.py
Expand Up @@ -12,8 +12,8 @@
.. include:: ../DOCUMENTATION.md
"""

from cliconfig import (
_logger,
base,
cli_parser,
config_routines,
Expand All @@ -22,6 +22,7 @@
processing,
tag_routines,
)
from cliconfig._logger import create_logger
from cliconfig._version import __version__, __version_tuple__
from cliconfig.base import Config
from cliconfig.config_routines import (
Expand All @@ -46,9 +47,13 @@
create_processing_value,
)

_CLICONFIG_LOGGER = create_logger()

__all__ = [
"__version__",
"__version_tuple__",
"_CLICONFIG_LOGGER",
"_logger",
"Config",
"DefaultProcessings",
"Processing",
Expand Down
16 changes: 16 additions & 0 deletions cliconfig/_logger.py
@@ -0,0 +1,16 @@
# Copyright (c) 2023 Valentin Goldite. All Rights Reserved.
"""Logging functions for cliconfig."""
import logging
import sys
from logging import Logger


def create_logger() -> Logger:
"""Create cliconfig logger."""
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("%(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
13 changes: 6 additions & 7 deletions cliconfig/config_routines.py
@@ -1,10 +1,10 @@
# Copyright (c) 2023 Valentin Goldite. All Rights Reserved.
"""Low-level and high-level functions to manipulate config."""
import logging
import sys
from copy import deepcopy
from typing import Any, Dict, List, Optional, Union

import cliconfig
from cliconfig.base import Config
from cliconfig.cli_parser import parse_cli
from cliconfig.dict_routines import flatten, show_dict, unflatten
Expand Down Expand Up @@ -84,6 +84,7 @@ def make_config(
does NOT raise an error but only a warning. This ensures the compatibility
with other CLI usage (e.g notebook, argparse, etc.)
"""
logger = cliconfig._CLICONFIG_LOGGER # pylint: disable=W0212
# Create the processing list
process_list_: List[Processing] = [] if process_list is None else process_list
if add_default_processing:
Expand Down Expand Up @@ -124,23 +125,21 @@ def make_config(
if new_keys:
new_keys_message = " - " + "\n - ".join(new_keys)
message = (
"[CONFIG] Warning: New keys found in CLI parameters "
"[CONFIG] New keys found in CLI parameters "
f"that will not be merged:\n{new_keys_message}"
)
logging.warning(message)
print(message)
logger.warning(message)
# Merge CLI parameters
cli_params_config = Config(cli_params_dict, [])
config = merge_flat_processing(
config, cli_params_config, allow_new_keys=False, preprocess_first=False
)
message = (
f"[CONFIG] Info: Merged {len(default_config_paths)} default config(s), "
f"[CONFIG] Merged {len(default_config_paths)} default config(s), "
f"{len(additional_config_paths)} additional config(s) and "
f"{len(cli_params_dict)} CLI parameter(s)."
)
logging.info(message)
print(message)
logger.info(message)
config = end_build_processing(config)
config.dict = unflatten(config.dict)
return config
Expand Down
22 changes: 13 additions & 9 deletions tests/unit/test_config_routines.py
Expand Up @@ -22,7 +22,10 @@
from cliconfig.processing.builtin import ProcessCopy


def test_make_config(capsys: pytest.CaptureFixture, process_add1: Processing) -> None:
def test_make_config(
caplog: pytest.LogCaptureFixture,
process_add1: Processing,
) -> None:
"""Test make_config."""
sys_argv = sys.argv.copy()
sys.argv = [
Expand All @@ -33,15 +36,13 @@ def test_make_config(capsys: pytest.CaptureFixture, process_add1: Processing) ->
"--param2@add1=6",
"--unknown2=8", # check that not error but a warning in console
]
capsys.readouterr() # Clear stdout and stderr
caplog.clear()
config = make_config(
"tests/configs/default1.yaml",
"tests/configs/default2.yaml",
process_list=[process_add1],
fallback="tests/configs/fallback.yaml",
)
captured = capsys.readouterr()
out = captured.out
expected_config = {
"param1": 4,
"param2": 7,
Expand All @@ -54,15 +55,18 @@ def test_make_config(capsys: pytest.CaptureFixture, process_add1: Processing) ->
},
"processing name": "ProcessAdd1",
}
expected_out = (
"[CONFIG] Warning: New keys found in CLI parameters that will not be merged:\n"
expected_out1 = (
"[CONFIG] New keys found in CLI parameters that will not be merged:\n"
" - unknown\n"
" - unknown2\n"
"[CONFIG] Info: Merged 2 default config(s), "
"2 additional config(s) and 1 CLI parameter(s).\n"
)
expected_out2 = (
"[CONFIG] Merged 2 default config(s), 2 additional config(s) "
"and 1 CLI parameter(s)."
)
check.equal(config.dict, expected_config)
check.equal(out, expected_out)
check.is_in(expected_out1, caplog.text)
check.is_in(expected_out2, caplog.text)

# No additional configs and fallback
sys.argv = [
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/test_logger.py
@@ -0,0 +1,22 @@
# Copyright (c) 2023 Valentin Goldite. All Rights Reserved.
"""Tests for dict routines."""
import pytest
import pytest_check as check

from cliconfig._logger import create_logger


def test_create_logger(
caplog: pytest.CaptureFixture,
capsys: pytest.CaptureFixture,
) -> None:
"""Test create_logger."""
logger = create_logger()
logger.info("This is an info message.")
check.is_true("INFO cliconfig._logger:test_logger.py:" in caplog.text)
check.is_true(" This is an info message." in caplog.text)
check.is_true("INFO - This is an info message." in capsys.readouterr().out)
logger.warning("This is a warning message.")
check.is_true("WARNING cliconfig._logger:test_logger.py:" in caplog.text)
check.is_true(" This is a warning message." in caplog.text)
check.is_true("WARNING - This is a warning message." in capsys.readouterr().out)

0 comments on commit b9de646

Please sign in to comment.