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
« 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.
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 typing import Any
27from trlc.ast import Symbol_Table
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
34# Variables ********************************************************************
36# Classes **********************************************************************
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.
45 Attributes:
46 _converter (AbstractConverter): The converter used for processing items.
47 _exclude_files (list): List of file paths to exclude from processing.
48 """
50 def __init__(self, args: Any, converter: AbstractConverter) -> None:
51 """
52 Initializes the TrlcWalker with the given arguments and converter.
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
61 def walk_symbols(self, symbol_table: Symbol_Table) -> Ret:
62 """
63 Walks through the items in the given symbol table and processes them.
65 Args:
66 symbol_table (Symbol_Table): The symbol table containing items to be walked through.
68 Returns:
69 Ret: Status of the walk operation.
70 """
71 result = self._converter.begin()
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
78 # Normalize the file name to make it comparable.
79 file_name = os.path.normpath(file_name)
81 if self._exclude_files is not None:
82 for excluded_path in self._exclude_files:
84 # Normalize the excluded path to make it comparable.
85 excluded_path = os.path.normpath(excluded_path)
87 if os.path.commonpath([excluded_path, file_name]) == excluded_path:
88 skip_it = True
89 break
91 if skip_it is True:
92 log_verbose(f"Skipping file {file_name}.")
94 else:
95 log_verbose(f"Processing file {file_name}.")
96 result = self._walk_file(file_name, item_list)
98 if result != Ret.OK:
99 break
101 if result == Ret.OK:
102 result = self._converter.finish()
104 return result
106 def _walk_file(self, file_name: str, item_list: Any) -> Ret:
107 """
108 Walks through the items in the given file.
110 Args:
111 file_name (str): The name of the file.
112 item_list (Any): The list of trlc items in the file.
114 Returns:
115 Ret: The result of the walk operation.
116 """
117 result = Ret.ERROR
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
125 except Exception as e: # pylint: disable=broad-except
126 log_error(f"Error processing file {file_name}: {e}")
128 return result
130 def _walk_items(self, item_list: list) -> Ret:
131 """
132 Walks through the given list of items.
134 Args:
135 item_list (list): The list of items to walk through.
137 Returns:
138 Ret: The result of the walk operation.
139 """
141 result = Ret.OK
143 try:
144 for item in item_list:
145 result = self._visit_item(item)
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
154 return result
156 def _visit_item(self, item: Any) -> Ret:
157 """
158 Visits the given item and processes it based on its type.
160 Args:
161 item (Any): The item to visit.
163 Returns:
164 Ret: The result of the visit.
165 """
166 result = Ret.OK
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
176 return result
178# Functions ********************************************************************
181# Main *************************************************************************