Coverage for packages/dqm-ml/src/dqm_ml/__main__.py: 92%

40 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-07-21 08:27 +0000

1"""Main CLI entry point for DQM-ML v2. 

2 

3This module provides the command-line interface for running DQM-ML 

4commands including version display, listing available plugins, and 

5processing data quality assessment jobs. 

6""" 

7 

8import argparse 

9from collections.abc import Iterable 

10import logging 

11from typing import Any 

12 

13from typing_extensions import override 

14 

15from dqm_ml.cli_tools import CustomFormatter 

16from dqm_ml.dependency import get_available_command 

17 

18logger = logging.getLogger(__name__) 

19 

20 

21class _HelpAction(argparse._HelpAction): 

22 """Custom help action to support command-specific help.""" 

23 

24 @override 

25 def __call__( 

26 self, 

27 parser: argparse.ArgumentParser, 

28 namespace: argparse.Namespace, 

29 values: str | Iterable[Any] | None, 

30 option_string: str | None = None, 

31 ) -> None: 

32 """Handle help action for command-specific or global help. 

33 

34 Args: 

35 parser: The argument parser instance. 

36 namespace: Parsed namespace containing the command. 

37 values: Optional values passed to the help action. 

38 option_string: The option string that triggered this action. 

39 

40 Raises: 

41 ValueError: If the specified command is unknown. 

42 """ 

43 if namespace.command: 

44 # print help for the specific command 

45 command_list = get_available_command() 

46 if namespace.command in command_list and command_list[namespace.command] is not None: 

47 command_list[namespace.command](["-h"]) 

48 else: 

49 raise ValueError(f"Unknown command {namespace.command}") 

50 else: 

51 parser.print_help() 

52 parser.exit() 

53 

54 

55def parse_args(arg_list: list[str] | None, command_list: Iterable[str]) -> Any: 

56 """Parse command-line arguments for the DQM-ML CLI. 

57 

58 Args: 

59 arg_list: Raw argument list (or None for sys.argv). 

60 command_list: Iterable of available command names. 

61 

62 Returns: 

63 Tuple of (parsed_args, remaining_args). 

64 """ 

65 parser = argparse.ArgumentParser( 

66 prog="dqm-ml", 

67 description="DQM-ML Job client", 

68 epilog="for more informations see README", 

69 add_help=False, 

70 ) 

71 

72 parser.add_argument("-h", "--help", action=_HelpAction, help="help for help if you need some help") 

73 

74 parser.add_argument("command", choices=command_list, help="Available command for your dqm-ml installation") 

75 

76 parser.add_argument("-v", "--verbose", action="store_true") 

77 parser.add_argument("-q", "--quiet", action="store_true") 

78 

79 cli_args, remaining = parser.parse_known_args(arg_list) 

80 

81 return cli_args, remaining 

82 

83 

84# TODO get parameters, logs, ... 

85def execute(arg_list: list[str] | None = None) -> None: 

86 """Execute the DQM-ML CLI command based on parsed arguments. 

87 

88 Discovers available commands, parses arguments, configures logging, 

89 and dispatches to the appropriate command handler. 

90 

91 Args: 

92 arg_list: Raw argument list (or None for sys.argv). 

93 """ 

94 # Exemple of other optional dependencies command 

95 # with optional_dependencies(optional_dep_mode): 

96 # import dqm_ml_dummy_command.cli 

97 # command_list["dqm_ml_dummy_command"] = dqm_ml_dummy_command.cli 

98 command_list = get_available_command() 

99 

100 args, remaining = parse_args(arg_list, command_list) 

101 

102 if args.verbose: 

103 CustomFormatter.init_log(format="%(name)s - %(message)s (%(filename)s:%(lineno)d)", level=logging.DEBUG) # noqa: E501 

104 elif args.quiet: 104 ↛ 105line 104 didn't jump to line 105 because the condition on line 104 was never true

105 CustomFormatter.init_log(format="%(message)s", level=logging.ERROR) 

106 else: 

107 CustomFormatter.init_log(format="%(message)s", level=logging.INFO) 

108 

109 logger.debug(f"Execution dqm-ml with {arg_list}") 

110 

111 if args.command in command_list and command_list[args.command] is not None: 

112 command_list[args.command](remaining) 

113 else: 

114 raise ValueError(f"Unknown command {args.command}") 

115 

116 

117if __name__ == "__main__": 117 ↛ 118line 117 didn't jump to line 118 because the condition on line 117 was never true

118 execute()