Index: leahi_dialin/utils/enum_updater.py =================================================================== diff -u -r81e359d6c7ced081bd4580ec3e6cc38939781c6a -raf4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1 --- leahi_dialin/utils/enum_updater.py (.../enum_updater.py) (revision 81e359d6c7ced081bd4580ec3e6cc38939781c6a) +++ leahi_dialin/utils/enum_updater.py (.../enum_updater.py) (revision af4e5fe9be4be627d61b4b4f75d0ed56c1ce4fa1) @@ -1,6 +1,25 @@ +########################################################################### +# +# Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file enum_updater.py +# +# @author (last) Zoltan Miskolci +# @date (last) 05-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 05-Aug-2026 +# +############################################################################ + +# Module imports from clang.cindex import Index, CursorKind, Config from datetime import datetime from os import path +import re +import subprocess from typing import List Config.set_library_file("/usr/lib/llvm-18/lib/libclang.so") @@ -13,10 +32,12 @@ """ Read the enums from the C++ file and then update the Python Enum definitions """ - + + cpp_repo_loc = path.abspath(f'{path.dirname(__file__)}/../../leahi-common') files_to_check = [] - files_to_check.append(path.abspath(f'{path.dirname(__file__)}/../../leahi-common/AlarmDefs.h')) - files_to_check.append(path.abspath(f'{path.dirname(__file__)}/../../leahi-common/MsgDefs.h')) + files_to_check.append(f'{cpp_repo_loc}/AlarmDefs.h') + files_to_check.append(f'{cpp_repo_loc}/MsgDefs.h') + _update_cpp_repo(cpp_repo_loc) common_location = path.abspath(f'{path.dirname(__file__)}/../common') file_to_update = {'AlarmList': (f'{common_location}/alarm_defs.py', 'AlarmEnum', False), @@ -26,22 +47,46 @@ } for file in files_to_check: if path.exists(file): - extracted_enums = _extract_enums(file) - for enum_name in extracted_enums: + extracted_cpp_enums = _extract_cpp_enums(file) + for enum_name in extracted_cpp_enums: if enum_name in file_to_update: - _generate_enum_file(file_location = file_to_update[enum_name][0], + + # Extract information from the dictionary + python_file = file_to_update[enum_name][0] + enum_type_name = file_to_update[enum_name][1] + is_enum_hex = file_to_update[enum_name][2] + + # Extract the original Python enums from the file + original_py_enums = _extract_python_enums(python_file) + new_enum = list(extracted_cpp_enums[enum_name]) + + # Get the enum member list + cpp_enum_values = [ item['value'] for item in extracted_cpp_enums[enum_name] ] + + # Add the original Python enum members that are not present in the C++ enum + new_enum.extend( + item + for item in original_py_enums.get(enum_name, []) + if item['value'] not in cpp_enum_values) + + # Sort the new enum list by the value to maintain order + new_enum.sort(key=lambda x: x['value']) + + # Generate the updated Python enum file + _generate_python_enum_file(file_location = python_file, enum_name = enum_name, - enum_member_list = extracted_enums[enum_name], - enum_type = file_to_update[enum_name][1], - is_hex = file_to_update[enum_name][2]) + enum_member_list = new_enum, + enum_type = enum_type_name, + is_hex = is_enum_hex) print(f'Updated enum: {enum_name}') # ============================================================ Private Methods ============================================================ -def _extract_enums(cpp_file): +def _extract_cpp_enums(cpp_file): """ Extract the enums from the provided C++ file + :param cpp_file: (String) The C++ file with full location :return: (Dictionary) The collected enums """ @@ -65,12 +110,55 @@ return enums -def _generate_enum_file(file_location: str, - enum_name: str, - enum_member_list: List[dict], - enum_type: str='Enum', - is_hex: bool=False) -> None: +def _extract_python_enums(py_file): """ + Extract the enums from the provided Python file + + :param py_file: (String) The Python file with full location + :return: (Dictionary) The collected enums + """ + result = {} + inside_enum = False + enum_name = None + + with open(py_file, "r", encoding="utf-8") as f: + for line in f: + # If we are not inside an enum, check if this line declares an enum class + if not inside_enum: + match = re.match(r"class (\w+)\(\w+Enum\):", line) + if match: + enum_name = match.group(1) + result[enum_name] = [] + inside_enum = True + continue + + # If we are inside an enum, process the enum members + else: + # Skip empty lines within the enum definition + if line.strip() == '': + continue + + # If the line is not indented, it means the enum definition has ended + if not line.startswith(' '): + inside_enum = False + continue + + match = re.match(r"\s*(\w+)\s*=\s*([0-9A-Fa-fx]+)\s*#\s*(.*)", line ) + if match: + member, value, comment = match.groups() + result[enum_name].append( { "member": member, + "value": int(value, 0), + "comment": comment, + } ) + return result + + +def _generate_python_enum_file(file_location: str, + enum_name: str, + enum_member_list: List[dict], + enum_type: str='Enum', + is_hex: bool=False) -> None: + """ Generate the enum file content :param file_location: (String) The enum file with full location :param enum_name: (String) The enum's name @@ -145,7 +233,46 @@ return lines +def _update_cpp_repo(cpp_repo: str) -> None: + """ + Update the C++ repository to ensure the latest changes are available for parsing. + :param cpp_repo: (String) The C++ folder with full location + :return: None + """ + try: + # # Switch to the staging branch + # subprocess.run( + # ["git", "-C", cpp_repo, "checkout", "staging"], + # check=True + # ) + + # Get latest refs from remote + subprocess.run( + ["git", "-C", cpp_repo, "fetch", "origin"], + check=True + ) + + # Discard all local changes + subprocess.run( + ["git", "-C", cpp_repo, "reset", "--hard", "HEAD"], + check=True + ) + + subprocess.run( + ["git", "-C", cpp_repo, "pull"], + check=True, + capture_output=True, + text=True + ) + print(f"Successfully updated repository: {cpp_repo}") + + except subprocess.CalledProcessError as e: + print(f"Failed to update repository: {cpp_repo}") + print(e.stderr) + + + # ============================================================ Main ============================================================ if __name__ == '__main__': EnumUpdater.execute()