Coverage for src/efts_io/cli.py: 47.62%

21 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-07-24 10:14 +1000

1"""Module that contains the command line application.""" 

2 

3# Why does this file exist, and why not put this in `__main__`? 

4# 

5# You might be tempted to import things from `__main__` later, 

6# but that will cause problems: the code will get executed twice: 

7# 

8# - When you run `python -m efts_io` python will execute 

9# `__main__.py` as a script. That means there won't be any 

10# `efts_io.__main__` in `sys.modules`. 

11# - When you import `__main__` it will get executed again (as a module) because 

12# there's no `efts_io.__main__` in `sys.modules`. 

13 

14from __future__ import annotations 

15 

16import argparse 

17import sys 

18from typing import Any 

19 

20from efts_io import debug 

21 

22 

23class _DebugInfo(argparse.Action): 

24 def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None: 

25 super().__init__(nargs=nargs, **kwargs) 

26 

27 def __call__(self, *args: Any, **kwargs: Any) -> None: # noqa: ARG002 

28 debug.print_debug_info() 

29 sys.exit(0) 

30 

31 

32def get_parser() -> argparse.ArgumentParser: 

33 """Return the CLI argument parser. 

34 

35 Returns: 

36 An argparse parser. 

37 """ 

38 parser = argparse.ArgumentParser(prog="efts") 

39 parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {debug.get_version()}") 

40 parser.add_argument("--debug-info", action=_DebugInfo, help="Print debug information.") 

41 return parser 

42 

43 

44def main(args: list[str] | None = None) -> int: 

45 """Run the main program. 

46 

47 This function is executed when you type `efts` or `python -m efts_io`. 

48 

49 Parameters: 

50 args: Arguments passed from the command line. 

51 

52 Returns: 

53 An exit code. 

54 """ 

55 parser = get_parser() 

56 opts = parser.parse_args(args=args) 

57 print(opts) 

58 return 0