feat: replace verbosity flag with log-level flag (#1496)

using a string flag is better when using environement variables.
This commit is contained in:
Jonas L 2022-01-08 07:16:08 +01:00 committed by GitHub
parent ba4eeaaff2
commit 40130303dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 45 deletions

View File

@ -5,7 +5,7 @@ from typing import Optional
from loguru import logger from loguru import logger
from .logging import LogLevel, level_from_verbosity, setup_logger from .logging import LogLevel, level_from_name, setup_logger
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
@ -26,13 +26,14 @@ class AbstractApp(ABC):
def __init__( def __init__(
self, self,
*, *,
verbosity: int, log_level: str,
log_filepath: Optional[PathLike] = None, log_filepath: Optional[PathLike] = None,
): ):
self.log_level = level_from_name(log_level)
if log_filepath is not None: if log_filepath is not None:
self.log_filepath = Path(log_filepath) self.log_filepath = Path(log_filepath)
self.log_level = level_from_verbosity(verbosity)
setup_logger(level=self.log_level, filepath=self.log_filepath) setup_logger(level=self.log_level, filepath=self.log_filepath)
logger.info(f"Starting {self.name}...") logger.info(f"Starting {self.name}...")

View File

@ -3,6 +3,7 @@ from typing import Callable
import click import click
from .config import DEFAULT_ENV_PREFIX from .config import DEFAULT_ENV_PREFIX
from .logging import INFO, LOG_LEVEL_MAP
def cli_logging_options(func: Callable) -> Callable: def cli_logging_options(func: Callable) -> Callable:
@ -10,26 +11,16 @@ def cli_logging_options(func: Callable) -> Callable:
Decorator function to add logging options to a click application. Decorator function to add logging options to a click application.
This decorator add the following arguments: This decorator add the following arguments:
- verbosity: int - log_level: str
- log_filepath: Path - log_filepath: Optional[Path]
""" """
func = click.option( func = click.option(
"-v", "--log-level",
"--verbose", "log_level",
"verbosity", envvar=f"{DEFAULT_ENV_PREFIX}_LOG_LEVEL",
envvar=f"{DEFAULT_ENV_PREFIX}_VERBOSITY", type=click.Choice(list(LOG_LEVEL_MAP.keys())),
count=True, default=INFO.name,
default=0, help="Name of the logging level.",
help="Increase logging verbosity (use -vvv to debug).",
)(func)
func = click.option(
"-q",
"--quiet",
"verbosity",
is_flag=True,
flag_value=-1,
help="Decrease logging verbosity.",
)(func) )(func)
func = click.option( func = click.option(

View File

@ -26,23 +26,27 @@ INFO = LogLevel(name="info", no=20)
DEBUG = LogLevel(name="debug", no=10) DEBUG = LogLevel(name="debug", no=10)
TRACE = LogLevel(name="trace", no=5) TRACE = LogLevel(name="trace", no=5)
LOG_LEVEL_MAP = {
ERROR.name: ERROR,
WARNING.name: WARNING,
INFO.name: INFO,
DEBUG.name: DEBUG,
TRACE.name: TRACE,
}
def level_from_verbosity(verbosity: int) -> LogLevel:
def level_from_name(name: str) -> LogLevel:
""" """
Find logging level, depending on the verbosity requested. Find logging level, depending on the name provided.
-q -1 => ERROR :param name: name (one of "error", "warning", "info", "debug", "trace") of the log level
default 0 => WARNING :returns: log level guessed from the name
-v 1 => INFO :raises ValueError: on invalid level name
-vv 2 => DEBUG
-vvv 3 => TRACE
:param verbosity: verbosity (between -1 and 3) of the logger
:returns: log level guessed from the verbosity
""" """
if verbosity < 0: name = name.lower()
return ERROR if name not in LOG_LEVEL_MAP:
return [WARNING, INFO, DEBUG, TRACE][min(3, verbosity)] raise ValueError(f"invalid level name '{name}'")
return LOG_LEVEL_MAP[name]
def setup_logger( def setup_logger(

View File

@ -7,29 +7,32 @@ from libretime_shared.logging import (
DEBUG, DEBUG,
INFO, INFO,
create_task_logger, create_task_logger,
level_from_verbosity, level_from_name,
setup_logger, setup_logger,
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
"verbosity,level_name,level_no", "name,level_name,level_no",
[ [
(-100, "error", 40), ("error", "error", 40),
(-1, "error", 40), ("warning", "warning", 30),
(0, "warning", 30), ("info", "info", 20),
(1, "info", 20), ("debug", "debug", 10),
(2, "debug", 10), ("trace", "trace", 5),
(3, "trace", 5),
(100, "trace", 5),
], ],
) )
def test_level_from_verbosity(verbosity, level_name, level_no): def test_level_from_name(name, level_name, level_no):
level = level_from_verbosity(verbosity) level = level_from_name(name)
assert level.name == level_name assert level.name == level_name
assert level.no == level_no assert level.no == level_no
def test_level_from_name_invalid():
with pytest.raises(ValueError):
level_from_name("invalid")
def test_setup_logger(tmp_path: Path): def test_setup_logger(tmp_path: Path):
log_filepath = tmp_path / "test.log" log_filepath = tmp_path / "test.log"
extra_log_filepath = tmp_path / "extra.log" extra_log_filepath = tmp_path / "extra.log"