Coverage for lobster/tools/trlc/trlc_tool.py: 0%
64 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-01-09 10:06 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-01-09 10:06 +0000
1#!/usr/bin/env python3
2#
3# LOBSTER - Lightweight Open BMW Software Traceability Evidence Report
4# Copyright (C) 2023-2025 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as
8# published by the Free Software Foundation, either version 3 of the
9# License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public
17# License along with this program. If not, see
18# <https://www.gnu.org/licenses/>.
20import argparse
21import os
22import sys
23from typing import Iterable, Optional, Sequence
25from yamale import YamaleError
27from trlc.errors import Message_Handler, TRLC_Error
28from trlc.trlc import Source_Manager
30from lobster.common.errors import PathError
31from lobster.common.items import Requirement
32from lobster.common.multi_file_input_tool import create_worklist, MultiFileInputTool
34from lobster.tools.trlc.converter import Converter
35from lobster.tools.trlc.errors import (
36 InvalidConversionRuleError,
37 RecordObjectComponentError,
38 TrlcFailure,
39 TupleToStringFailedError,
40 TupleToStringMissingError,
41)
42from lobster.tools.trlc.lobster_trlc_config import LobsterTrlcConfig
45class LOBSTER_Trlc(MultiFileInputTool):
46 def __init__(self):
47 super().__init__(
48 name = "trlc",
49 description = "Extract tracing data from TRLC files.",
50 extensions = ["rsl", "trlc"],
51 official = True,
52 )
54 def _run_impl(self, options: argparse.Namespace):
55 try:
56 self._execute(options)
57 return 0
58 except YamaleError as e:
59 print(
60 f"{self.name}: The configuration file does not "
61 f"conform to the YAML schema. {e}",
62 file=sys.stderr,
63 )
64 except TRLC_Error as e:
65 print(
66 f"{self.name}: An error occurred during processing: {e}",
67 file=sys.stderr,
68 )
69 except FileNotFoundError as e:
70 print(
71 f"{self.name}: File or directory not found: {e}",
72 file=sys.stderr,
73 )
74 except PathError as e:
75 print(
76 f"{self.name}: {e}",
77 file=sys.stderr,
78 )
79 except TrlcFailure as e:
80 print(
81 f"{self.name}: TRLC processing failed: {e}",
82 file=sys.stderr,
83 )
84 except (InvalidConversionRuleError, RecordObjectComponentError) as e:
85 print(
86 f"{self.name}: Invalid conversion rule defined in {options.config}: "
87 f"{e}",
88 file=sys.stderr,
89 )
90 except (TupleToStringMissingError, TupleToStringFailedError) as e:
91 print(
92 f"{self.name}: error in 'to-string-rules' in {options.config}: "
93 f"{e}",
94 file=sys.stderr,
95 )
97 return 1
99 @staticmethod
100 def _register_trlc_files(sm: Source_Manager, work_list: Iterable[str]):
101 for item in work_list:
102 ok = True
103 if os.path.isfile(item):
104 ok = sm.register_file(item)
105 elif os.path.isdir(item):
106 ok = sm.register_directory(item)
107 else:
108 raise FileNotFoundError(item)
109 if not ok:
110 raise PathError(f"Failed to register file or directory '{item}'")
112 def _execute(self, options: argparse.Namespace) -> None:
113 config = LobsterTrlcConfig.from_file(options.config)
114 work_list = create_worklist(config, options.dir_or_files)
115 trlc_mh = Message_Handler()
116 sm = Source_Manager(trlc_mh)
117 self._register_trlc_files(sm, work_list)
118 symbol_table = sm.process()
119 if not symbol_table:
120 raise TrlcFailure("aborting due to TRLC error")
122 items = []
123 converter = Converter(
124 conversion_rules=config.conversion_rules,
125 to_string_rules=config.to_string_rules,
126 symbol_table=symbol_table,
127 )
128 for n_obj in symbol_table.iter_record_objects():
129 item = converter.generate_lobster_object(n_obj)
130 if item:
131 items.append(item)
133 # lobster-trace: trlc_req.Output_File
134 self._write_output(Requirement, options.out, items)
137def main(args: Optional[Sequence[str]] = None) -> int:
138 return LOBSTER_Trlc().run(args)