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

65 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-06-26 12:41 +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 - 2026 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 """A walker that traverses through the TRLC items in the given symbol table.""" 

43 

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

45 """ 

46 Initializes the TrlcWalker with the given arguments and converter. 

47 

48 Args: 

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

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

51 """ 

52 self._converter = converter 

53 self._exclude_files = args.exclude 

54 

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

56 """ 

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

58 

59 Args: 

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

61 

62 Returns: 

63 Ret: Status of the walk operation. 

64 """ 

65 result = self._converter.begin() 

66 

67 if result == Ret.OK: 

68 files_dict = get_file_dict_from_symbols(symbol_table) 

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

70 skip_it = False 

71 

72 # Normalize the file name to make it comparable. 

73 file_name = os.path.normpath(file_name) 

74 

75 if self._exclude_files is not None: 

76 for excluded_path in self._exclude_files: 

77 

78 # Normalize the excluded path to make it comparable. 

79 excluded_path = os.path.normpath(excluded_path) 

80 

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

82 skip_it = True 

83 break 

84 

85 if skip_it is True: 

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

87 

88 else: 

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

90 result = self._walk_file(file_name, item_list) 

91 

92 if result != Ret.OK: 

93 break 

94 

95 if result == Ret.OK: 

96 result = self._converter.finish() 

97 

98 return result 

99 

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

101 """ 

102 Walks through the items in the given file. 

103 

104 Args: 

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

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

107 

108 Returns: 

109 Ret: The result of the walk operation. 

110 """ 

111 result = Ret.ERROR 

112 

113 try: 

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

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

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

117 result = Ret.OK 

118 

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

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

121 

122 return result 

123 

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

125 """ 

126 Walks through the given list of items. 

127 

128 Args: 

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

130 

131 Returns: 

132 Ret: The result of the walk operation. 

133 """ 

134 

135 result = Ret.OK 

136 

137 try: 

138 for item in item_list: 

139 result = self._visit_item(item) 

140 

141 if result != Ret.OK: 

142 break 

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

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

145 traceback.print_exc() 

146 result = Ret.ERROR 

147 

148 return result 

149 

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

151 """ 

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

153 

154 Args: 

155 item (Any): The item to visit. 

156 

157 Returns: 

158 Ret: The result of the visit. 

159 """ 

160 result = Ret.OK 

161 

162 if is_item_section(item): 

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

164 elif is_item_record(item): 

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

166 else: 

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

168 result = Ret.ERROR 

169 

170 return result 

171 

172# Functions ******************************************************************** 

173 

174 

175# Main *************************************************************************