Coverage for src/xlbudget/configure.py: 40.74%

25 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2024-01-05 07:44 +0000

1"""The setup and configuration for xlbudget. 

2 

3Warning: Logger usage in this file 

4 

5 The logger can only be used after `_configure_logger` is called in `setup`. 

6""" 

7 

8import logging 

9from argparse import ArgumentParser, Namespace 

10 

11from .commands import Command, get_command_classes 

12 

13 

14def setup() -> Namespace: 

15 """Package-level setup and configuration. 

16 

17 Returns: 

18 A[n] `Namespace` containing the parsed CLI arguments. 

19 """ 

20 parser = _configure_argument_parser() 

21 args = parser.parse_args() 

22 _configure_logger(args.log_level) 

23 

24 # log args after call to _configure_logger 

25 logger = logging.getLogger(__name__) 

26 logger.debug(f"parsed CLI arguments: {args}") 

27 

28 return args 

29 

30 

31def _configure_argument_parser() -> ArgumentParser: 

32 """Configures the argument parser for all arguments. 

33 

34 Returns: 

35 A[n] `ArgumentParser` configured for this package. 

36 """ 

37 parser = ArgumentParser() 

38 

39 Command.configure_common_args(parser) 

40 _configure_logger_args(parser) 

41 

42 cmd_subparsers = parser.add_subparsers( 

43 title="command", 

44 required=True, 

45 description="The xlbudget command to run.", 

46 ) 

47 for cmd_cls in get_command_classes(): 

48 cmd_cls.configure_args(cmd_subparsers) 

49 

50 return parser 

51 

52 

53def _configure_logger_args(parser: ArgumentParser) -> None: 

54 """Configures the argument parser for logger arguments. 

55 The log level configuration was adapted from 

56 [this Stack Overflow answer](https://stackoverflow.com/a/20663028). 

57 

58 Args: 

59 parser (ArgumentParser): The argument parser to update. 

60 """ 

61 group_log = parser.add_argument_group( 

62 "logger configuration", 

63 description="Arguments that override the default logger configuration.", 

64 ) 

65 group_log_lvl = group_log.add_mutually_exclusive_group() 

66 group_log_lvl.add_argument( 

67 "-d", 

68 "--debug", 

69 help="print lots of debugging statements; can't use with -v/--verbose", 

70 action="store_const", 

71 dest="log_level", 

72 const=logging.DEBUG, 

73 default=logging.WARNING, 

74 ) 

75 group_log_lvl.add_argument( 

76 "-v", 

77 "--verbose", 

78 help="be verbose; can't use with -d/--debug", 

79 action="store_const", 

80 dest="log_level", 

81 const=logging.INFO, 

82 ) 

83 

84 

85def _configure_logger(level: int) -> None: 

86 """Configures the logger. 

87 

88 Since this configuration is global, there is no need to return the logger. 

89 To use the logger in a file, add `logger = logging.getLogger(__name__)` at the top. 

90 

91 Args: 

92 level (int): The [logging level](https://docs.python.org/3/library/logging.html#logging-levels). 

93 """ # noqa 

94 logging.basicConfig( 

95 level=level, 

96 format="%(levelname)s - %(name)s:%(lineno)s - %(message)s", 

97 )