Coverage for lobster/common/meta_data_tool_base.py: 74%

19 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-09-22 04:43 +0000

1# LOBSTER - Lightweight Open BMW Software Traceability Evidence Report 

2# Copyright (C) 2025 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) 

3# 

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

5# it under the terms of the GNU Affero General Public License as 

6# published by the Free Software Foundation, either version 3 of the 

7# License, or (at your option) any later version. 

8# 

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

10# WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

12# Affero General Public License for more details. 

13# 

14# You should have received a copy of the GNU Affero General Public 

15# License along with this program. If not, see 

16# <https://www.gnu.org/licenses/>. 

17 

18from abc import abstractmethod, ABCMeta 

19from argparse import ArgumentParser, Namespace, RawTextHelpFormatter 

20from typing import Optional, Sequence 

21from lobster.common.version import FULL_NAME 

22 

23 

24BUG_URL = "https://github.com/bmw-software-engineering/lobster/issues" 

25 

26 

27class MetaDataToolBase(metaclass=ABCMeta): 

28 def __init__( 

29 self, 

30 name: str, 

31 description: str, 

32 official: bool, 

33 ) -> None: 

34 """Base class for LOBSTER tools. 

35 

36 It provides an ArgumentParser and implements the --version and --help 

37 features. 

38 

39 params: 

40 name (str): The name of the tool, without the 'lobster-' prefix. 

41 description (str): A brief description of the tool. 

42 It will be used in the help message. 

43 official (bool): Whether the tool is an official LOBSTER tool. 

44 This flag determines the URL for the bug ticker.""" 

45 

46 self._name = f"lobster-{name}" 

47 self._argument_parser = ArgumentParser( 

48 prog = self._name, 

49 description = description, 

50 epilog = (f"Part of {FULL_NAME}, licensed under the AGPLv3." 

51 f" Please report bugs to {BUG_URL}." 

52 if official else None), 

53 allow_abbrev = False, 

54 formatter_class=RawTextHelpFormatter, 

55 fromfile_prefix_chars="@", # lobster-trace: req.Args_From_File 

56 ) 

57 self._argument_parser.add_argument( 

58 "-v", 

59 "--version", 

60 action="version", 

61 default=None, 

62 help="print version and exit", 

63 version=FULL_NAME, 

64 ) 

65 

66 @property 

67 def name(self) -> str: 

68 """The name of the tool, prefixed with 'lobster-'.""" 

69 return self._name 

70 

71 def run(self, args: Optional[Sequence[str]] = None) -> int: 

72 """ 

73 Parse the command line arguments and run the tool implementation. 

74 

75 If the --version or --help flag is set, it prints those messages. 

76 Otherwise it calls the _run_impl method with the parsed arguments. 

77 """ 

78 

79 # parse_args calls sys.exit if 'args' contains --help or --version 

80 # so we wrap the call in a try-catch block 

81 try: 

82 parsed_arguments = self._argument_parser.parse_args(args) 

83 return self._run_impl(parsed_arguments) 

84 except SystemExit as e: 

85 return e.code 

86 

87 @abstractmethod 

88 def _run_impl(self, options: Namespace) -> int: 

89 """This method should be implemented by subclasses to run the tool. 

90 

91 The return value shall be an exit code. 

92 """