new Path handling

This commit is contained in:
Robin Müller 2022-06-20 18:02:46 +02:00
parent fc191cc50e
commit 36b44d1e26
4 changed files with 117 additions and 101 deletions

View File

@ -166,9 +166,7 @@ class EventParser(FileParser):
f"Name: {self.mib_table.get(full_id)[0]}| " f"Name: {self.mib_table.get(full_id)[0]}| "
f"Description: {self.mib_table.get(full_id)[2]}" f"Description: {self.mib_table.get(full_id)[2]}"
) )
self.mib_table.update( self.mib_table.update({full_id: (name, severity, description, file_name)})
{full_id: (name, severity, description, file_name.as_posix())}
)
self.count = self.count + 1 self.count = self.count + 1
@staticmethod @staticmethod
@ -277,7 +275,7 @@ class EventParser(FileParser):
def export_to_file( def export_to_file(
filename: str, event_list: List[Tuple[str, List]], file_separator: str filename: Path, event_list: List[Tuple[str, List]], file_separator: str
): ):
file = open(filename, "w") file = open(filename, "w")
fsep = file_separator fsep = file_separator
@ -288,59 +286,57 @@ def export_to_file(
file.write( file.write(
f"{event_id}{fsep}{event_id_as_hex}{fsep}{event_value[EVENT_ENTRY_NAME_IDX]}{fsep}" f"{event_id}{fsep}{event_id_as_hex}{fsep}{event_value[EVENT_ENTRY_NAME_IDX]}{fsep}"
f"{event_value[EVENT_ENTRY_SEVERITY_IDX]}{fsep}{event_value[EVENT_ENTRY_INFO_IDX]}" f"{event_value[EVENT_ENTRY_SEVERITY_IDX]}{fsep}{event_value[EVENT_ENTRY_INFO_IDX]}"
f"{fsep}{event_value[EVENT_SOURCE_FILE_IDX]}\n" f"{fsep}{event_value[EVENT_SOURCE_FILE_IDX].as_posix()}\n"
) )
file.close() file.close()
return
def write_translation_source_file( def write_translation_source_file(
event_list: list, date_string: str, filename: str = "translateEvents.cpp" event_list: list, date_string: str, filename: Path = "translateEvents.cpp"
): ):
outputfile = open(filename, "w") with open(filename, "w") as out:
definitions = "" definitions = ""
# Look up table to avoid duplicate events # Look up table to avoid duplicate events
lut = dict() lut = dict()
function = ( function = (
"const char *translateEvents(Event event) {\n switch ((event & 0xFFFF)) {\n" "const char *translateEvents(Event event) {\n switch ((event & 0xFFFF)) {\n"
) )
for entry in event_list: for entry in event_list:
event_id = entry[0] event_id = entry[0]
event_value = entry[1] event_value = entry[1]
if event_value[EVENT_ENTRY_NAME_IDX] not in lut: if event_value[EVENT_ENTRY_NAME_IDX] not in lut:
definitions += ( definitions += (
f"const char *{event_value[EVENT_ENTRY_NAME_IDX]}_STRING " f"const char *{event_value[EVENT_ENTRY_NAME_IDX]}_STRING "
f'= "{event_value[EVENT_ENTRY_NAME_IDX]}";\n' f'= "{event_value[EVENT_ENTRY_NAME_IDX]}";\n'
) )
function += ( function += (
f" case ({event_id}):\n " f" case ({event_id}):\n "
f"return {event_value[EVENT_ENTRY_NAME_IDX]}_STRING;\n" f"return {event_value[EVENT_ENTRY_NAME_IDX]}_STRING;\n"
) )
lut.update({event_value[EVENT_ENTRY_NAME_IDX]: event_value}) lut.update({event_value[EVENT_ENTRY_NAME_IDX]: event_value})
function += ' default:\n return "UNKNOWN_EVENT";\n' function += ' default:\n return "UNKNOWN_EVENT";\n'
outputfile.write( out.write(
f"/**\n * @brief Auto-generated event translation file. " f"/**\n * @brief Auto-generated event translation file. "
f"Contains {len(event_list)} translations.\n" f"Contains {len(event_list)} translations.\n"
f" * @details\n" f" * @details\n"
f" * Generated on: {date_string}\n */\n" f" * Generated on: {date_string}\n */\n"
) )
outputfile.write('#include "translateEvents.h"\n\n') out.write('#include "translateEvents.h"\n\n')
outputfile.write(definitions + "\n" + function + " }\n return 0;\n}\n") out.write(definitions + "\n" + function + " }\n return 0;\n}\n")
outputfile.close()
def write_translation_header_file(filename: str = "translateEvents.h"): def write_translation_header_file(filename: Path = "translateEvents.h"):
file = open(filename, "w") with open(filename, "w") as out:
file.write( out.write(
f"#ifndef FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_\n" f"#ifndef FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_\n"
f"#define FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_\n\n" f"#define FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_\n\n"
f"{FSFW_EVENT_HEADER_INCLUDE}\n\n" f"{FSFW_EVENT_HEADER_INCLUDE}\n\n"
f"const char *translateEvents(Event event);\n\n" f"const char *translateEvents(Event event);\n\n"
f"#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */\n" f"#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */\n"
) )
def handle_csv_export(file_name: str, event_list: list, file_separator: str): def handle_csv_export(file_name: Path, event_list: list, file_separator: str):
""" """
Generates the CSV in the same directory as the .py file and copes the CSV to another Generates the CSV in the same directory as the .py file and copes the CSV to another
directory if specified. directory if specified.
@ -353,9 +349,9 @@ def handle_csv_export(file_name: str, event_list: list, file_separator: str):
def handle_cpp_export( def handle_cpp_export(
event_list: list, event_list: list,
date_string: str, date_string: str,
file_name: str = "translateEvents.cpp", file_name: Path = "translateEvents.cpp",
generate_header: bool = True, generate_header: bool = True,
header_file_name: str = "translateEvents.h", header_file_name: Path = "translateEvents.h",
): ):
write_translation_source_file( write_translation_source_file(
event_list=event_list, date_string=date_string, filename=file_name event_list=event_list, date_string=date_string, filename=file_name

View File

@ -1,4 +1,6 @@
import re import re
from pathlib import Path
from typing import List
from fsfwgen.parserbase.parser import FileParser from fsfwgen.parserbase.parser import FileParser
from fsfwgen.core import get_console_logger from fsfwgen.core import get_console_logger
@ -9,10 +11,10 @@ LOGGER = get_console_logger()
class ObjectDefinitionParser(FileParser): class ObjectDefinitionParser(FileParser):
def __init__(self, file_list: list): def __init__(self, file_list: List[Path]):
super().__init__(file_list) super().__init__(file_list)
def _handle_file_parsing(self, file_name: str, *args, **kwargs): def _handle_file_parsing(self, file_name: Path, *args, **kwargs):
file = open(file_name, "r", encoding="utf-8") file = open(file_name, "r", encoding="utf-8")
for line in file.readlines(): for line in file.readlines():
match = re.search(r"([\w]*)[\s]*=[\s]*(0[xX][0-9a-fA-F]+)", line) match = re.search(r"([\w]*)[\s]*=[\s]*(0[xX][0-9a-fA-F]+)", line)
@ -21,7 +23,7 @@ class ObjectDefinitionParser(FileParser):
def _handle_file_parsing_moving_window( def _handle_file_parsing_moving_window(
self, self,
file_name: str, file_name: Path,
current_line: int, current_line: int,
moving_window_size: int, moving_window_size: int,
moving_window: list, moving_window: list,

View File

@ -1,7 +1,8 @@
import os.path import os.path
import re import re
import sys import sys
from typing import List, Tuple, Optional from pathlib import Path
from typing import List, Tuple, Optional, Dict
from fsfwgen.parserbase.parser import FileParser, VerbosityLevels from fsfwgen.parserbase.parser import FileParser, VerbosityLevels
from fsfwgen.utility.printer import PrettyPrinter from fsfwgen.utility.printer import PrettyPrinter
@ -160,6 +161,31 @@ class InterfaceParser(FileParser):
self.mib_table.update(dict_to_build) self.mib_table.update(dict_to_build)
class RetvalEntry:
def __init__(
self,
name: str,
description: str,
unique_id: int,
file_name: Path,
subsystem_name: str,
):
self.name = name
self.description = description
self.unique_id = unique_id
self.file_name = file_name
self.subsystem_name = subsystem_name
def __repr__(self):
return (
f"RetvalEntry(name={self.name!r}, description={self.description!r}, unique_id={self.unique_id!r}, "
f"file_name={self.file_name!r}, subsystem_name={self.subsystem_name!r})"
)
RetvalDictT = Dict[int, RetvalEntry]
class ReturnValueParser(FileParser): class ReturnValueParser(FileParser):
""" """
Generic return value parser. Generic return value parser.
@ -173,32 +199,32 @@ class ReturnValueParser(FileParser):
self.count = 0 self.count = 0
# Stores last three lines # Stores last three lines
self.last_lines = ["", "", ""] self.last_lines = ["", "", ""]
self.obsw_root_path: Optional[str] = None self.obsw_root_path: Optional[Path] = None
self.current_interface_id_entries = {"Name": "", "ID": 0, "FullName": ""} self.current_interface_id_entries = {"Name": "", "ID": 0, "FullName": ""}
self.return_value_dict.update( self.return_value_dict.update(
{ {
0: ( 0: RetvalEntry(
"OK", name="OK",
"System-wide code for ok.", description="System-wide code for ok.",
"RETURN_OK", unique_id=0,
"HasReturnvaluesIF.h", file_name=Path("fsfw/returnvalues/HasReturnvaluesIF.h"),
"HasReturnvaluesIF", subsystem_name="HasReturnvaluesIF",
) )
} }
) )
self.return_value_dict.update( self.return_value_dict.update(
{ {
1: ( 1: RetvalEntry(
"Failed", name="Failed",
"Unspecified system-wide code for failed.", description="Unspecified system-wide code for failed.",
"RETURN_FAILED", unique_id=1,
"HasReturnvaluesIF.h", file_name=Path("fsfw/returnvalues/HasReturnvaluesIF.h"),
"HasReturnvaluesIF", subsystem_name="HasReturnvaluesIF",
) )
} }
) )
def _handle_file_parsing(self, file_name: str, *args, **kwargs): def _handle_file_parsing(self, file_name: Path, *args, **kwargs):
"""Former way to parse returnvalues. Not recommended anymore. """Former way to parse returnvalues. Not recommended anymore.
:param file_name: :param file_name:
:param args: :param args:
@ -215,7 +241,7 @@ class ReturnValueParser(FileParser):
def _handle_file_parsing_moving_window( def _handle_file_parsing_moving_window(
self, self,
file_name: str, file_name: Path,
current_line: int, current_line: int,
moving_window_size: int, moving_window_size: int,
moving_window: list, moving_window: list,
@ -263,9 +289,11 @@ class ReturnValueParser(FileParser):
full_returnvalue_string, full_returnvalue_string,
) )
if returnvalue_match: if returnvalue_match:
number_match = returnvalue_match.group(2) number_match = get_number_from_dec_or_hex_str(
returnvalue_match.group(2)
)
else: else:
number_match = returnvalue_match.group(3) number_match = get_number_from_dec_or_hex_str(returnvalue_match.group(3))
if returnvalue_match: if returnvalue_match:
description = self.__search_for_descrip_string(moving_window=moving_window) description = self.__search_for_descrip_string(moving_window=moving_window)
if number_match == INVALID_IF_ID: if number_match == INVALID_IF_ID:
@ -315,12 +343,12 @@ class ReturnValueParser(FileParser):
name_match=returnvalue_match.group(1), name_match=returnvalue_match.group(1),
file_name=file_name, file_name=file_name,
description="", description="",
number_match=returnvalue_match.group(2), number_match=get_number_from_dec_or_hex_str(returnvalue_match.group(2)),
) )
self.last_lines[1] = self.last_lines[0] self.last_lines[1] = self.last_lines[0]
self.last_lines[0] = newline self.last_lines[0] = newline
def __handle_interfaceid_match(self, interface_id_match, file_name: str) -> bool: def __handle_interfaceid_match(self, interface_id_match, file_name: Path) -> bool:
"""Handle a match of an interface ID definition in the code. """Handle a match of an interface ID definition in the code.
Returns whether the interface ID was found successfully in the IF ID header files Returns whether the interface ID was found successfully in the IF ID header files
""" """
@ -338,7 +366,7 @@ class ReturnValueParser(FileParser):
return False return False
self.current_interface_id_entries["Name"] = self.interfaces[ self.current_interface_id_entries["Name"] = self.interfaces[
interface_id_match.group(1) interface_id_match.group(1)
][1] ][1].lstrip()
self.current_interface_id_entries["FullName"] = interface_id_match.group(1) self.current_interface_id_entries["FullName"] = interface_id_match.group(1)
if self.get_verbosity() == VerbosityLevels.DEBUG: if self.get_verbosity() == VerbosityLevels.DEBUG:
current_id = self.current_interface_id_entries["ID"] current_id = self.current_interface_id_entries["ID"]
@ -346,7 +374,7 @@ class ReturnValueParser(FileParser):
return True return True
def __handle_returnvalue_match( def __handle_returnvalue_match(
self, name_match: str, number_match: str, file_name: str, description: str self, name_match: str, number_match: int, file_name: Path, description: str
): ):
string_to_add = self.build_checked_string( string_to_add = self.build_checked_string(
self.current_interface_id_entries["Name"], self.current_interface_id_entries["Name"],
@ -354,23 +382,21 @@ class ReturnValueParser(FileParser):
MAX_STRING_LEN, MAX_STRING_LEN,
PRINT_TRUNCATED_ENTRIES, PRINT_TRUNCATED_ENTRIES,
) )
full_id = ( full_id = (self.current_interface_id_entries["ID"] << 8) | number_match
self.current_interface_id_entries["ID"] << 8
) + return_number_from_string(number_match)
if full_id in self.return_value_dict: if full_id in self.return_value_dict:
# print('Duplicate returncode ' + hex(full_id) + ' from ' + file_name + # print('Duplicate returncode ' + hex(full_id) + ' from ' + file_name +
# ' was already in ' + self.return_value_dict[full_id][3]) # ' was already in ' + self.return_value_dict[full_id][3])
pass pass
if self.obsw_root_path is not None: if self.obsw_root_path is not None:
file_name = os.path.relpath(file_name, self.obsw_root_path) file_name = file_name.relative_to(self.obsw_root_path)
dict_tuple = ( mib_entry = RetvalEntry(
string_to_add, name=string_to_add,
description, description=description,
number_match, unique_id=number_match,
file_name, file_name=file_name,
self.current_interface_id_entries["FullName"], subsystem_name=self.current_interface_id_entries["FullName"],
) )
self.return_value_dict.update({full_id: dict_tuple}) self.return_value_dict.update({full_id: mib_entry})
self.count = self.count + 1 self.count = self.count + 1
def _post_parsing_operation(self): def _post_parsing_operation(self):
@ -379,22 +405,12 @@ class ReturnValueParser(FileParser):
self.mib_table = self.return_value_dict self.mib_table = self.return_value_dict
@staticmethod @staticmethod
def export_to_file(filename: str, list_of_entries: dict, file_separator: str): def export_to_file(filename: str, list_of_entries: RetvalDictT, file_sep: str):
file = open(filename, "w") file = open(filename, "w")
for entry in list_of_entries.items(): for entry in list_of_entries.items():
file.write( file.write(
hex(entry[0]) f"{entry[0]:#06x}{file_sep}{entry[1].name}{file_sep}{entry[1].description}{file_sep}"
+ file_separator f"{entry[1].unique_id}{file_sep}{entry[1].subsystem_name}{file_sep}{entry[1].file_name.as_posix()}\n"
+ entry[1][0]
+ file_separator
+ entry[1][1]
+ file_separator
+ entry[1][2]
+ file_separator
+ entry[1][3]
+ file_separator
+ entry[1][4]
+ "\n"
) )
file.close() file.close()
@ -434,7 +450,7 @@ class ReturnValueParser(FileParser):
return description return description
def return_number_from_string(a_string): def get_number_from_dec_or_hex_str(a_string):
if a_string.startswith("0x"): if a_string.startswith("0x"):
return int(a_string, 16) return int(a_string, 16)
if a_string.isdigit(): if a_string.isdigit():

View File

@ -1,12 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import shutil import shutil
import os import os
from pathlib import Path
from fsfwgen.core import get_console_logger from fsfwgen.core import get_console_logger
LOGGER = get_console_logger() LOGGER = get_console_logger()
def copy_file(filename: str, destination: str = "", delete_existing_file: bool = False): def copy_file(filename: Path, destination: Path = "", delete_existing_file: bool = False):
if not os.path.exists(filename): if not os.path.exists(filename):
LOGGER.warning(f"File {filename} does not exist") LOGGER.warning(f"File {filename} does not exist")
return return
@ -24,7 +26,7 @@ def copy_file(filename: str, destination: str = "", delete_existing_file: bool =
LOGGER.exception("Source and destination are the same!") LOGGER.exception("Source and destination are the same!")
def move_file(file_name: str, destination: str = ""): def move_file(file_name: Path, destination: Path = ""):
if not os.path.exists(file_name): if not os.path.exists(file_name):
print(f"move_file: File {file_name} does not exist") print(f"move_file: File {file_name} does not exist")
return return