Coverage for src / pyTRLCConverter / item_walker.py: 85%

65 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-21 12:06 +0000

1""" 

2This module implements a TRLC items walker over the loaded model. 

3 

4Author: Norbert Schulz (norbert.schulz@newtec.de) 

5""" 

6 

7# pyTRLCConverter - A tool to convert TRLC files to specific formats. 

8# Copyright (c) 2024 - 2025 NewTec GmbH 

9# 

10# This file is part of pyTRLCConverter program. 

11# 

12# The pyTRLCConverter program is free software: you can redistribute it and/or modify it under 

13# the terms of the GNU General Public License as published by the Free Software Foundation, 

14# either version 3 of the License, or (at your option) any later version. 

15# 

16# The pyTRLCConverter program is distributed in the hope that it will be useful, but 

17# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

18# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 

19# 

20# You should have received a copy of the GNU General Public License along with pyTRLCConverter. 

21# If not, see <https://www.gnu.org/licenses/>. 

22 

23# Imports ********************************************************************** 

24import os 

25import traceback 

26from typing import Any 

27from trlc.ast import Symbol_Table 

28 

29from pyTRLCConverter.abstract_converter import AbstractConverter 

30from pyTRLCConverter.logger import log_verbose, log_error 

31from pyTRLCConverter.trlc_helper import get_file_dict_from_symbols, is_item_record, is_item_section 

32from pyTRLCConverter.ret import Ret 

33 

34# Variables ******************************************************************** 

35 

36# Classes ********************************************************************** 

37 

38 

39# pylint: disable-next=too-few-public-methods 

40class ItemWalker: 

41 # lobster-trace: SwRequirements.sw_req_process_trlc_symbols 

42 """ 

43 A walker that traverses through the TRLC items in the given symbol table. 

44 

45 Attributes: 

46 _converter (AbstractConverter): The converter used for processing items. 

47 _exclude_files (list): List of file paths to exclude from processing. 

48 """ 

49 

50 def __init__(self, args: Any, converter: AbstractConverter) -> None: 

51 """ 

52 Initializes the TrlcWalker with the given arguments and converter. 

53 

54 Args: 

55 args (Any): Arguments containing the exclude file paths. 

56 converter (AbstractConverter): The converter used for processing items. 

57 """ 

58 self._converter = converter 

59 self._exclude_files = args.exclude 

60 

61 def walk_symbols(self, symbol_table: Symbol_Table) -> Ret: 

62 """ 

63 Walks through the items in the given symbol table and processes them. 

64 

65 Args: 

66 symbol_table (Symbol_Table): The symbol table containing items to be walked through. 

67 

68 Returns: 

69 Ret: Status of the walk operation. 

70 """ 

71 result = self._converter.begin() 

72 

73 if result == Ret.OK: 

74 files_dict = get_file_dict_from_symbols(symbol_table) 

75 for file_name, item_list in files_dict.items(): 

76 skip_it = False 

77 

78 # Normalize the file name to make it comparable. 

79 file_name = os.path.normpath(file_name) 

80 

81 if self._exclude_files is not None: 

82 for excluded_path in self._exclude_files: 

83 

84 # Normalize the excluded path to make it comparable. 

85 excluded_path = os.path.normpath(excluded_path) 

86 

87 if os.path.commonpath([excluded_path, file_name]) == excluded_path: 

88 skip_it = True 

89 break 

90 

91 if skip_it is True: 

92 log_verbose(f"Skipping file {file_name}.") 

93 

94 else: 

95 log_verbose(f"Processing file {file_name}.") 

96 result = self._walk_file(file_name, item_list) 

97 

98 if result != Ret.OK: 

99 break 

100 

101 if result == Ret.OK: 

102 result = self._converter.finish() 

103 

104 return result 

105 

106 def _walk_file(self, file_name: str, item_list: Any) -> Ret: 

107 """ 

108 Walks through the items in the given file. 

109 

110 Args: 

111 file_name (str): The name of the file. 

112 item_list (Any): The list of trlc items in the file. 

113 

114 Returns: 

115 Ret: The result of the walk operation. 

116 """ 

117 result = Ret.ERROR 

118 

119 try: 

120 if Ret.OK == self._converter.enter_file(file_name): 

121 if Ret.OK == self._walk_items(item_list): 

122 if Ret.OK == self._converter.leave_file(file_name): 

123 result = Ret.OK 

124 

125 except Exception as e: # pylint: disable=broad-except 

126 log_error(f"Error processing file {file_name}: {e}") 

127 

128 return result 

129 

130 def _walk_items(self, item_list: list) -> Ret: 

131 """ 

132 Walks through the given list of items. 

133 

134 Args: 

135 item_list (list): The list of items to walk through. 

136 

137 Returns: 

138 Ret: The result of the walk operation. 

139 """ 

140 

141 result = Ret.OK 

142 

143 try: 

144 for item in item_list: 

145 result = self._visit_item(item) 

146 

147 if result != Ret.OK: 

148 break 

149 except Exception as e: # pylint: disable=broad-except 

150 log_error(f"Error processing item {item}: {e}") 

151 traceback.print_exc() 

152 result = Ret.ERROR 

153 

154 return result 

155 

156 def _visit_item(self, item: Any) -> Ret: 

157 """ 

158 Visits the given item and processes it based on its type. 

159 

160 Args: 

161 item (Any): The item to visit. 

162 

163 Returns: 

164 Ret: The result of the visit. 

165 """ 

166 result = Ret.OK 

167 

168 if is_item_section(item): 

169 result = self._converter.convert_section(item[0], item[1]) 

170 elif is_item_record(item): 

171 result = self._converter.convert_record_object(item[0], item[1]) 

172 else: 

173 log_error(f"Unrecognized item type {item}") 

174 result = Ret.ERROR 

175 

176 return result 

177 

178# Functions ******************************************************************** 

179 

180 

181# Main *************************************************************************