Coverage for python/lsst/dax/apdb/cli/logging_cli.py: 23%

25 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-30 02:54 -0700

1# This file is part of dax_apdb 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ["LoggingCli"] 

25 

26import argparse 

27import logging 

28 

29_log_format = "%(asctime)s %(levelname)s %(name)s - %(message)s" 

30 

31 

32class LoggingCli: 

33 """Class that handles CLI logging options and logging configuration. 

34 

35 Parameters 

36 ---------- 

37 parser : `argparse.ArgumentParser` 

38 Parser for which to define logging options. 

39 """ 

40 

41 def __init__(self, parser: argparse.ArgumentParser): 

42 self._parser = parser 

43 parser.add_argument( 

44 "-l", 

45 "--log-level", 

46 dest="log_level", 

47 action="append", 

48 metavar="LEVEL|LOGGER=LEVEL[,...]", 

49 help="Global or per-logger logging level, comma-separated and can be specified multiple times", 

50 default=[], 

51 ) 

52 

53 def process_args(self, args: argparse.Namespace) -> None: 

54 """Configure Python logging based on command line options.""" 

55 global_level = logging.INFO 

56 logger_levels: dict[str, int] = {} 

57 for level_str in args.log_level: 

58 for spec in level_str.split(","): 

59 logger_name, sep, level_name = spec.rpartition("=") 

60 level = logging.getLevelNamesMapping().get(level_name.upper()) 

61 if level is None: 

62 self._parser.error(f"Unknown logging level {level_name!r} in {level_str!r}") 

63 if logger_name: 

64 logger_levels[logger_name] = level 

65 else: 

66 global_level = level 

67 

68 logging.basicConfig(level=global_level, format=_log_format) 

69 for logger_name, level in logger_levels.items(): 

70 logging.getLogger(logger_name).setLevel(level) 

71 

72 # We want to remove `log_level` so that namespace can be converted to 

73 # a dict and passed as kwargs to scripts. 

74 del args.log_level