Coverage for src/pyTRLCConverter/item_walker.py: 84%
64 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 10:59 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 10:59 +0000
1"""
2This module implements a TRLC items walker over the loaded model.
4Author: Norbert Schulz (norbert.schulz@newtec.de)
5"""
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/>.
23# Imports **********************************************************************
24import os
25import traceback
26from trlc.ast import Symbol_Table
28from pyTRLCConverter.abstract_converter import AbstractConverter
29from pyTRLCConverter.logger import log_verbose, log_error
30from pyTRLCConverter.trlc_helper import get_file_dict_from_symbols, is_item_record, is_item_section
31from pyTRLCConverter.ret import Ret
33# Variables ********************************************************************
35# Classes **********************************************************************
38class ItemWalker: # pylint: disable=too-few-public-methods
39 # lobster-trace: SwRequirements.sw_req_process_trlc_symbols
40 """
41 A walker that traverses through the TRLC items in the given symbol table.
43 Attributes:
44 _converter (AbstractConverter): The converter used for processing items.
45 _exclude_files (list): List of file paths to exclude from processing.
46 """
48 def __init__(self, args: any, converter: AbstractConverter) -> None:
49 """
50 Initializes the TrlcWalker with the given arguments and converter.
52 Args:
53 args (any): Arguments containing the exclude file paths.
54 converter (AbstractConverter): The converter used for processing items.
55 """
56 self._converter = converter
57 self._exclude_files = args.exclude
59 def walk_symbols(self, symbol_table: Symbol_Table) -> Ret:
60 """
61 Walks through the items in the given symbol table and processes them.
63 Args:
64 symbol_table (Symbol_Table): The symbol table containing items to be walked through.
66 Returns:
67 Ret: Status of the walk operation.
68 """
69 result = self._converter.begin()
71 if result == Ret.OK:
72 files_dict = get_file_dict_from_symbols(symbol_table)
73 for file_name, item_list in files_dict.items():
74 skip_it = False
76 # Normalize the file name to make it comparable.
77 file_name = os.path.normpath(file_name)
79 if self._exclude_files is not None:
80 for excluded_path in self._exclude_files:
82 # Normalize the excluded path to make it comparable.
83 excluded_path = os.path.normpath(excluded_path)
85 if os.path.commonpath([excluded_path, file_name]) == excluded_path:
86 skip_it = True
87 break
89 if skip_it is True:
90 log_verbose(f"Skipping file {file_name}.")
92 else:
93 log_verbose(f"Processing file {file_name}.")
94 result = self._walk_file(file_name, item_list)
96 if result != Ret.OK:
97 break
99 if result == Ret.OK:
100 result = self._converter.finish()
102 return result
104 def _walk_file(self, file_name: str, item_list: any) -> Ret:
105 """
106 Walks through the items in the given file.
108 Args:
109 file_name (str): The name of the file.
110 item_list (any): The list of trlc items in the file.
112 Returns:
113 Ret: The result of the walk operation.
114 """
115 result = Ret.ERROR
117 try:
118 if Ret.OK == self._converter.enter_file(file_name):
119 if Ret.OK == self._walk_items(item_list):
120 if Ret.OK == self._converter.leave_file(file_name):
121 result = Ret.OK
123 except Exception as e: # pylint: disable=broad-except
124 log_error(f"Error processing file {file_name}: {e}")
126 return result
128 def _walk_items(self, item_list: list) -> Ret:
129 """
130 Walks through the given list of items.
132 Args:
133 item_list (list): The list of items to walk through.
135 Returns:
136 Ret: The result of the walk operation.
137 """
139 result = Ret.OK
141 try:
142 for item in item_list:
143 result = self._visit_item(item)
145 if result != Ret.OK:
146 break
147 except Exception as e: # pylint: disable=broad-except
148 log_error(f"Error processing item {item}: {e}")
149 traceback.print_exc()
150 result = Ret.ERROR
152 return result
154 def _visit_item(self, item: any) -> Ret:
155 """
156 Visits the given item and processes it based on its type.
158 Args:
159 item (any): The item to visit.
161 Returns:
162 Ret: The result of the visit.
163 """
164 result = Ret.OK
166 if is_item_section(item):
167 result = self._converter.convert_section(item[0], item[1])
168 elif is_item_record(item):
169 result = self._converter.convert_record_object(item[0], item[1])
170 else:
171 log_error(f"Unrecognized item type {item}")
172 result = Ret.ERROR
174 return result
176# Functions ********************************************************************
179# Main *************************************************************************