diff --git a/src/lbaf/Applications/LBAF_app.py b/src/lbaf/Applications/LBAF_app.py index f94751198..cb411e724 100644 --- a/src/lbaf/Applications/LBAF_app.py +++ b/src/lbaf/Applications/LBAF_app.py @@ -24,6 +24,7 @@ from lbaf.IO.lbsMeshBasedVisualizer import MeshBasedVisualizer import lbaf.IO.lbsStatistics as lbstats from lbaf.Model.lbsPhase import Phase +from lbaf.Utils.exception_handler import exc_handler from lbaf.Utils.logger import logger @@ -79,9 +80,11 @@ def get_configuration_file(self, conf_file: str): except yaml.MarkedYAMLError as err: self.logger.error(f"Invalid YAML file {conf_file} in line {err.problem_mark.line} ({err.problem,} " f"{err.context})") + sys.excepthook = exc_handler raise SystemExit(1) else: self.logger.error(f"Configuration file in {conf_file} not found") + sys.excepthook = exc_handler raise SystemExit(1) def configuration_validation(self): @@ -103,6 +106,7 @@ def parse_conf_file(self): self.grid_size.append(gm.get(key)) if math.prod(self.grid_size) < self.n_ranks: self.logger.error(f"Grid size: {self.grid_size} < {self.n_ranks}") + sys.excepthook = exc_handler raise SystemExit(1) self.object_jitter = gm.get("object_jitter") @@ -268,6 +272,7 @@ def main(self): objects, alpha, beta, gamma, self.params.n_ranks) if n_a != self.params.n_ranks ** len(objects): self.logger.error("Incorrect number of possible arrangements with repetition") + sys.excepthook = exc_handler raise SystemExit(1) self.logger.info(f"Minimax work: {w_min_max:.4g} for {len(a_min_max)} optimal arrangements amongst {n_a}") else: diff --git a/src/lbaf/Applications/MoveCountsViewer.py b/src/lbaf/Applications/MoveCountsViewer.py index df0798114..9b9065b3b 100644 --- a/src/lbaf/Applications/MoveCountsViewer.py +++ b/src/lbaf/Applications/MoveCountsViewer.py @@ -13,6 +13,7 @@ import vtk +from lbaf.Utils.exception_handler import exc_handler from lbaf.Utils.logger import logger @@ -423,6 +424,7 @@ def computeMoveCountsViewer(self): # Instantiate parameters and set values from command line arguments lgr.info("# Parsing command line arguments") if params.parse_command_line(): + sys.excepthook = exc_handler raise SystemExit(1) # Execute viewer diff --git a/src/lbaf/Applications/MoveCountsViewerParameters.py b/src/lbaf/Applications/MoveCountsViewerParameters.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lbaf/Applications/conf.yaml b/src/lbaf/Applications/conf.yaml index ab1ffe7a8..9355e496b 100644 --- a/src/lbaf/Applications/conf.yaml +++ b/src/lbaf/Applications/conf.yaml @@ -72,7 +72,7 @@ algorithm: # Specify output #logging_level: debug -show_traceback: False +show_traceback: True terminal_background: light generate_multimedia: False output_dir: ../../../output diff --git a/src/lbaf/Applications/rank_object_enumerator.py b/src/lbaf/Applications/rank_object_enumerator.py index 28d14879d..26e91be75 100644 --- a/src/lbaf/Applications/rank_object_enumerator.py +++ b/src/lbaf/Applications/rank_object_enumerator.py @@ -14,6 +14,7 @@ raise SystemExit(1) from lbaf.IO.lbsVTDataReader import LoadReader +from lbaf.Utils.exception_handler import exc_handler from lbaf.Utils.logger import logger @@ -114,9 +115,11 @@ def compute_pairwise_reachable_arrangements(objects: tuple, arrangement: tuple, # Sanity checks regarding rank IDs if from_id >= n_ranks: LGR.error(f"Incorrect sender ID: {from_id} >= {n_ranks}") + sys.excepthook = exc_handler raise SystemExit(1) if to_id >= n_ranks: LGR.error(f"Incorrect receiver ID: {to_id} >= {n_ranks}") + sys.excepthook = exc_handler raise SystemExit(1) # Provide upper bounder on transfer size when none provided @@ -210,6 +213,7 @@ def recursively_compute_transitions(stack: list, visited: dict, objects: tuple, w_a = visited.get(arrangement, -1.) if w_a < 0.: LGR.error(f"Arrangement {arrangement} not found in visited map") + sys.excepthook = exc_handler raise SystemExit(1) # Append current arrangement to trajectory stack @@ -289,6 +293,7 @@ def get_conf() -> dict: n_ranks=N_RANKS) if n_a != N_RANKS ** len(objects): LGR.error("Incorrect number of possible arrangements with repetition") + sys.excepthook = exc_handler raise SystemExit(1) LGR.info(f"Number of generated arrangements with repetition: {n_a}") LGR.info(f"\tminimax work: {w_min_max:.4g} for {len(a_min_max)} optimal arrangements") diff --git a/src/lbaf/Execution/lbsAlgorithmBase.py b/src/lbaf/Execution/lbsAlgorithmBase.py index 36e6b88c4..6778ff268 100644 --- a/src/lbaf/Execution/lbsAlgorithmBase.py +++ b/src/lbaf/Execution/lbsAlgorithmBase.py @@ -2,9 +2,10 @@ from logging import Logger import sys +from ..IO.lbsStatistics import compute_function_statistics from ..Model.lbsWorkModelBase import WorkModelBase +from ..Utils.exception_handler import exc_handler from ..Utils.logger import logger -from ..IO.lbsStatistics import compute_function_statistics LGR = logger @@ -23,6 +24,7 @@ def __init__(self, work_model, parameters: dict): # Assert that a work model base instance was passed if not isinstance(work_model, WorkModelBase): LGR().error("Could not create an algorithm without a work model") + sys.excepthook = exc_handler raise SystemExit(1) self.work_model = work_model @@ -49,6 +51,7 @@ def factory(algorithm_name:str, parameters: dict, work_model, lgr: Logger): except: # Otherwise, error out LGR().error(f"Could not create an algorithm with name {algorithm_name}") + sys.excepthook = exc_handler raise SystemExit(1) def update_distributions_and_statistics(self, distributions: dict, statistics: dict): diff --git a/src/lbaf/Execution/lbsBruteForceAlgorithm.py b/src/lbaf/Execution/lbsBruteForceAlgorithm.py index ca56eff35..f2fa7cf38 100644 --- a/src/lbaf/Execution/lbsBruteForceAlgorithm.py +++ b/src/lbaf/Execution/lbsBruteForceAlgorithm.py @@ -4,8 +4,8 @@ from logging import Logger from .lbsAlgorithmBase import AlgorithmBase -from ..Model.lbsObjectCommunicator import ObjectCommunicator from ..Model.lbsPhase import Phase +from ..Utils.exception_handler import exc_handler class BruteForceAlgorithm(AlgorithmBase): @@ -70,6 +70,7 @@ def execute(self, phases: list, distributions: dict, statistics: dict, _): if not phases or not isinstance(phases, list) or not isinstance( (phase := phases[0]), Phase): self.__logger.error(f"Algorithm execution requires a Phase instance") + sys.excepthook = exc_handler raise SystemExit(1) self.phase = phase @@ -124,9 +125,11 @@ def execute(self, phases: list, distributions: dict, statistics: dict, _): # Sanity checks if not len(a_min_max): self.__logger.error("No optimal arrangements were found") + sys.excepthook = exc_handler raise SystemExit(1) if n_arrangements != n_ranks ** len(objects): self.__logger.error("Incorrect number of possible arrangements with repetition") + sys.excepthook = exc_handler raise SystemExit(1) self.__logger.info(f"Minimax work: {w_min_max:.4g} for {len(a_min_max)} optimal arrangements amongst {n_arrangements}") diff --git a/src/lbaf/Execution/lbsCriterionBase.py b/src/lbaf/Execution/lbsCriterionBase.py index 5bdd4bf68..5cee498c8 100644 --- a/src/lbaf/Execution/lbsCriterionBase.py +++ b/src/lbaf/Execution/lbsCriterionBase.py @@ -3,10 +3,11 @@ import sys from ..Model.lbsWorkModelBase import WorkModelBase +from ..Utils.exception_handler import exc_handler from ..Utils.logger import logger -LGR = logger() +LGR = logger class CriterionBase: @@ -21,12 +22,13 @@ def __init__(self, work_model): # Assert that a work model base instance was passed if not isinstance(work_model, WorkModelBase): - LGR.error("Could not create a criterion without a work model") + LGR().error("Could not create a criterion without a work model") + sys.excepthook = exc_handler raise SystemExit(1) self.work_model = work_model # Criterion keeps internal references to ranks and edges - LGR.debug(f"Created base criterion with {str(type(work_model)).split('.')[-1][:-2]} work model") + LGR().debug(f"Created base criterion with {str(type(work_model)).split('.')[-1][:-2]} work model") @staticmethod def factory(criterion_name, work_model, lgr: Logger): @@ -44,7 +46,8 @@ def factory(criterion_name, work_model, lgr: Logger): return criterion(work_model, lgr=lgr) except: # Otherwise, error out - LGR.error(f"Could not create a criterion with name {criterion_name}") + LGR().error(f"Could not create a criterion with name {criterion_name}") + sys.excepthook = exc_handler raise SystemExit(1) @abc.abstractmethod diff --git a/src/lbaf/Execution/lbsInformAndTransferAlgorithm.py b/src/lbaf/Execution/lbsInformAndTransferAlgorithm.py index ed2de2c68..b3b4d97d2 100644 --- a/src/lbaf/Execution/lbsInformAndTransferAlgorithm.py +++ b/src/lbaf/Execution/lbsInformAndTransferAlgorithm.py @@ -12,6 +12,7 @@ from ..Model.lbsPhase import Phase from ..IO.lbsStatistics import compute_function_statistics, print_function_statistics, inverse_transform_sample, \ min_Hamming_distance +from ..Utils.exception_handler import exc_handler class InformAndTransferAlgorithm(AlgorithmBase): @@ -33,15 +34,18 @@ def __init__(self, work_model, parameters: dict, lgr: Logger): if not isinstance(self.__n_iterations, int) or self.__n_iterations < 0: self.__logger.error( f"Incorrect provided number of algorithm iterations: {self.__n_iterations}") + sys.excepthook = exc_handler raise SystemExit(1) self.__n_rounds = parameters.get("n_rounds") if not isinstance(self.__n_rounds, int) or self.__n_rounds < 0: self.__logger.error( f"Incorrect provided number of information rounds: {self.__n_rounds}") + sys.excepthook = exc_handler raise SystemExit(1) self.__fanout = parameters.get("fanout") if not isinstance(self.__fanout, int) or self.__fanout < 0: self.__logger.error(f"Incorrect provided information fanout {self.__fanout}") + sys.excepthook = exc_handler raise SystemExit(1) self.__logger.info( f"Instantiated with {self.__n_iterations} iterations, {self.__n_rounds} rounds, fanout {self.__fanout}") @@ -59,6 +63,7 @@ def __init__(self, work_model, parameters: dict, lgr: Logger): if o_s not in self.__strategy_mapped: self.__logger.error(f"{o_s} does not exist in known ordering strategies: " f"{[x for x in self.__strategy_mapped.keys()]}") + sys.excepthook = exc_handler raise SystemExit(1) self.__order_strategy = self.__strategy_mapped[o_s] self.__logger.info(f"Selected {self.__order_strategy.__name__} object ordering strategy") @@ -70,6 +75,7 @@ def __init__(self, work_model, parameters: dict, lgr: Logger): lgr=self.__logger) if not self.__transfer_criterion: self.__logger.error(f"Could not instantiate a transfer criterion of type {self.__criterion_name}") + sys.excepthook = exc_handler raise SystemExit(1) # Assign optional parameters @@ -264,6 +270,7 @@ def transfer_stage(self): # Sanity check before transfer if p_dst not in p_src.get_known_loads(): self.__logger.error(f"Destination rank {p_dst.get_id()} not in known ranks") + sys.excepthook = exc_handler raise SystemExit(1) # Transfer objects @@ -288,9 +295,9 @@ def transfer_stage(self): def execute(self, phases: list, distributions: dict, statistics: dict, a_min_max): """ Execute 2-phase gossip+transfer algorithm on Phase instance.""" # Ensure that a list with at least one phase was provided - if not phases or not isinstance(phases, list) or not isinstance( - (phase := phases[0]), Phase): + if not phases or not isinstance(phases, list) or not isinstance((phase := phases[0]), Phase): self.__logger.error(f"Algorithm execution requires a Phase instance") + sys.excepthook = exc_handler raise SystemExit(1) self.phase = phase diff --git a/src/lbaf/Execution/lbsPhaseStepperAlgorithm.py b/src/lbaf/Execution/lbsPhaseStepperAlgorithm.py index c0b31a232..1ecae08b0 100644 --- a/src/lbaf/Execution/lbsPhaseStepperAlgorithm.py +++ b/src/lbaf/Execution/lbsPhaseStepperAlgorithm.py @@ -1,8 +1,10 @@ from logging import Logger +import sys from .lbsAlgorithmBase import AlgorithmBase from ..Model.lbsPhase import Phase from ..IO.lbsStatistics import print_function_statistics +from ..Utils.exception_handler import exc_handler class PhaseStepperAlgorithm(AlgorithmBase): @@ -27,6 +29,7 @@ def execute(self, phases: list, distributions: dict, statistics: dict, _): if not phases or not isinstance(phases, list) or not all( [isinstance(p, Phase) for p in phases]): self.__logger.error(f"Algorithm execution requires a Phase instance") + sys.excepthook = exc_handler raise SystemExit(1) # Iterate over all phases diff --git a/src/lbaf/Execution/lbsRuntime.py b/src/lbaf/Execution/lbsRuntime.py index a3405c5b8..12dbf9ff6 100644 --- a/src/lbaf/Execution/lbsRuntime.py +++ b/src/lbaf/Execution/lbsRuntime.py @@ -1,10 +1,10 @@ import sys from logging import Logger -from ..Model.lbsPhase import Phase from ..Model.lbsWorkModelBase import WorkModelBase from ..Execution.lbsAlgorithmBase import AlgorithmBase from ..IO.lbsStatistics import print_function_statistics, compute_function_statistics, min_Hamming_distance +from ..Utils.exception_handler import exc_handler class Runtime: @@ -29,6 +29,7 @@ def __init__(self, phases: list, work_model: dict, algorithm: dict, arrangements # If no LBS phase was provided, do not do anything if not phases or not isinstance(phases, list): self.__logger.error("Could not create a LBS runtime without a list of phases") + sys.excepthook = exc_handler raise SystemExit(1) self.__phases = phases @@ -46,6 +47,7 @@ def __init__(self, phases: list, work_model: dict, algorithm: dict, arrangements lgr=self.__logger) if not self.__algorithm: self.__logger.error(f"Could not instantiate an algorithm of type {self.__algorithm}") + sys.excepthook = exc_handler raise SystemExit(1) # Initialize run distributions and statistics diff --git a/src/lbaf/IO/lbsVTDataReader.py b/src/lbaf/IO/lbsVTDataReader.py index ba8f2a504..bd1c7cf51 100644 --- a/src/lbaf/IO/lbsVTDataReader.py +++ b/src/lbaf/IO/lbsVTDataReader.py @@ -9,6 +9,7 @@ from ..Model.lbsObject import Object from ..Model.lbsObjectCommunicator import ObjectCommunicator from ..Model.lbsRank import Rank +from ..Utils.exception_handler import exc_handler class LoadReader: @@ -51,7 +52,8 @@ def read(self, node_id: int, phase_id: int = -1, comm: bool = False) -> tuple: file_name = self.get_node_trace_file_name(node_id) self.__logger.info(f"Reading {file_name} VT object map") if not os.path.isfile(file_name): - raise FileNotFoundError(f"File {file_name} not found!") + sys.excepthook = exc_handler + raise FileNotFoundError(f"File {file_name} not found") # Retrieve communications from JSON reader iter_map = {} @@ -87,6 +89,7 @@ def read_iteration(self, n_p: int, phase_id: int) -> list: except KeyError as e: msg_err = f"Could not retrieve information for rank {p} at time_step {phase_id}. KeyError {e}" self.__logger.error(msg_err) + sys.excepthook = exc_handler raise KeyError(msg_err) # Merge rank communication with existing ones @@ -136,6 +139,7 @@ def json_reader(self, returned_dict: dict, file_name: str, phase_ids, node_id: i # Extracting type from JSON data schema_type = decompressed_dict.get("type") if schema_type is None: + sys.excepthook = exc_handler raise TypeError("JSON data is missing 'type' key") # Validate schema diff --git a/src/lbaf/IO/schemaValidator.py b/src/lbaf/IO/schemaValidator.py index 6b1734e84..508b5fe97 100644 --- a/src/lbaf/IO/schemaValidator.py +++ b/src/lbaf/IO/schemaValidator.py @@ -2,6 +2,7 @@ import sys from schema import And, Optional, Schema +from ..Utils.exception_handler import exc_handler class SchemaValidator: @@ -257,6 +258,7 @@ def _get_valid_schema(self) -> Schema: elif self.schema_type == "LBStatsfile": return valid_schema_stats + sys.excepthook = exc_handler raise TypeError(f"Unsupported schema type: {self.schema_type} was given") def is_valid(self, schema_to_validate: dict) -> bool: diff --git a/src/lbaf/Model/lbsObject.py b/src/lbaf/Model/lbsObject.py index a7611ad14..b13efbb01 100644 --- a/src/lbaf/Model/lbsObject.py +++ b/src/lbaf/Model/lbsObject.py @@ -1,4 +1,7 @@ +import sys + from .lbsObjectCommunicator import ObjectCommunicator +from ..Utils.exception_handler import exc_handler class Object: @@ -7,12 +10,14 @@ class Object: def __init__(self, i: int, t: float, p: int = None, c: ObjectCommunicator = None, user_defined: dict = None): # Object index if not isinstance(i, int) or isinstance(i, bool): + sys.excepthook = exc_handler raise TypeError(f"i: {i} is type of {type(i)}! Must be !") else: self.__index = i # Time required to perform the work of this object if not isinstance(t, float): + sys.excepthook = exc_handler raise TypeError(f"t: {t} is type of {type(t)}! Must be !") else: self.__time = t @@ -21,18 +26,21 @@ def __init__(self, i: int, t: float, p: int = None, c: ObjectCommunicator = None if bool(isinstance(p, int) or p is None) and not isinstance(p, bool): self.__rank_id = p else: + sys.excepthook = exc_handler raise TypeError(f"p: {p} is type of {type(p)}! Must be !") # Communication graph of this object if defined if isinstance(c, ObjectCommunicator) or c is None: self.__communicator = c else: + sys.excepthook = exc_handler raise TypeError(f"c: {c} is type of {type(c)}! Must be !") # User defined fields if isinstance(user_defined, dict) or user_defined is None: self.__user_defined = user_defined else: + sys.excepthook = exc_handler raise TypeError(f"user_defined: {user_defined} is type of {type(user_defined)}! Must be !") def __repr__(self): diff --git a/src/lbaf/Model/lbsObjectCommunicator.py b/src/lbaf/Model/lbsObjectCommunicator.py index 873459cb5..a247a412a 100644 --- a/src/lbaf/Model/lbsObjectCommunicator.py +++ b/src/lbaf/Model/lbsObjectCommunicator.py @@ -1,4 +1,7 @@ from logging import Logger +import sys + +from ..Utils.exception_handler import exc_handler class ObjectCommunicator: @@ -30,6 +33,7 @@ def _summarize_unidirectional(self, direction): # Sanity check if k.get_id() == self.__object_index: self.__logger.error(f"object {self.__object_index} cannot send communication to itself.") + sys.excepthook = exc_handler raise IndexError(f"object {self.__object_index} cannot send communication to itself.") # Update list of volumes diff --git a/src/lbaf/Model/lbsPhase.py b/src/lbaf/Model/lbsPhase.py index e4b258f80..abfebf320 100644 --- a/src/lbaf/Model/lbsPhase.py +++ b/src/lbaf/Model/lbsPhase.py @@ -7,6 +7,7 @@ from ..IO.lbsStatistics import print_subset_statistics, print_function_statistics, sampler from ..IO.lbsVTDataReader import LoadReader +from ..Utils.exception_handler import exc_handler class Phase: @@ -196,6 +197,7 @@ def populate_from_samplers(self, n_ranks, n_objects, t_sampler, v_sampler, c_deg # Perform sanity checks if len(v_recv) != len(v_sent): self.__logger.error(f"Number of sent and received communications differ: {len(v_sent)} <> {len(v_recv)}") + sys.excepthook = exc_handler raise SystemExit(1) # Compute and report communication volume statistics diff --git a/src/lbaf/Model/lbsWorkModelBase.py b/src/lbaf/Model/lbsWorkModelBase.py index d757040a6..b7f2c7242 100644 --- a/src/lbaf/Model/lbsWorkModelBase.py +++ b/src/lbaf/Model/lbsWorkModelBase.py @@ -2,6 +2,7 @@ from logging import Logger import sys +from ..Utils.exception_handler import exc_handler from ..Utils.logger import logger @@ -36,6 +37,7 @@ def factory(work_name, parameters, lgr: Logger): except: # Otherwise, error out LGR().error(f"Could not create a work with name: {work_name}") + sys.excepthook = exc_handler raise NameError(f"Could not create a work with name: {work_name}") @abc.abstractmethod diff --git a/src/lbaf/Utils/JSON_data_files_validator.py b/src/lbaf/Utils/JSON_data_files_validator.py index 1f2ae25f5..79add6f3a 100644 --- a/src/lbaf/Utils/JSON_data_files_validator.py +++ b/src/lbaf/Utils/JSON_data_files_validator.py @@ -15,6 +15,7 @@ import brotli from lbaf.IO.schemaValidator import SchemaValidator +from lbaf.Utils.exception_handler import exc_handler class JSONDataFilesValidator: @@ -60,10 +61,11 @@ def __get_files_for_validation(dir_path: str, file_prefix: str, file_suffix: str list_of_files = os.listdir(dir_path) if not list_of_files: - raise FileNotFoundError(f"Directory: {dir_path} is EMPTY!") + sys.excepthook = exc_handler + raise FileNotFoundError(f"Directory: {dir_path} is EMPTY") if file_prefix is None and file_suffix is None: - print("File prefix and file suffix not given!") + print("File prefix and file suffix not given") file_prefix = Counter([file.split('.')[0] for file in list_of_files]).most_common()[0][0] print(f"Found most common prefix: {file_prefix}") file_suffix = Counter([file.split('.')[-1] for file in list_of_files]).most_common()[0][0] @@ -107,7 +109,8 @@ def main(self): if self.__check_if_file_exists(file_path=self.__file_path): self.__validate_file(file_path=self.__file_path) else: - raise FileNotFoundError(f"File: {self.__file_path} NOT found!") + sys.excepthook = exc_handler + raise FileNotFoundError(f"File: {self.__file_path} NOT found") elif self.__dir_path is not None: if self.__check_if_dir_exists(dir_path=self.__dir_path): list_of_files_for_validation = self.__get_files_for_validation(dir_path=self.__dir_path, @@ -116,9 +119,11 @@ def main(self): for file in list_of_files_for_validation: self.__validate_file(file_path=file) else: - raise FileNotFoundError(f"Directory: {self.__dir_path} does NOT exist!") + sys.excepthook = exc_handler + raise FileNotFoundError(f"Directory: {self.__dir_path} does NOT exist") else: - raise Exception("FILE path or DIRECTORY path has to be given!") + sys.excepthook = exc_handler + raise Exception("FILE path or DIRECTORY path has to be given") if __name__ == "__main__": diff --git a/src/lbaf/Utils/csv_2_json_data_converter.py b/src/lbaf/Utils/csv_2_json_data_converter.py index 70e361070..9ef5fadd3 100644 --- a/src/lbaf/Utils/csv_2_json_data_converter.py +++ b/src/lbaf/Utils/csv_2_json_data_converter.py @@ -14,6 +14,8 @@ import brotli +from lbaf.Utils.exception_handler import exc_handler + class Csv2JsonConverter: """ A class to convert from previous log structure (CSV) to a current log structure (JSON) @@ -50,7 +52,8 @@ def _get_data_dir(dir_path: str) -> str: elif os.path.isdir(os.path.join(project_path, dir_path)): return os.path.join(project_path, dir_path) else: - print(f"Can not find dir {dir_path}!") + print(f"Can not find dir {dir_path}") + sys.excepthook = exc_handler raise SystemExit(1) def _get_files_for_conversion(self) -> list: diff --git a/src/lbaf/Utils/data_stat_files_updater.py b/src/lbaf/Utils/data_stat_files_updater.py index 0e00889f9..c1b800229 100644 --- a/src/lbaf/Utils/data_stat_files_updater.py +++ b/src/lbaf/Utils/data_stat_files_updater.py @@ -14,6 +14,8 @@ import brotli +from lbaf.Utils.exception_handler import exc_handler + class DataStatFilesUpdater: """ Class validating VT data files according do defined schema. """ @@ -63,6 +65,7 @@ def __get_files_for_validation(dir_path: str, file_prefix: str, file_suffix: str list_of_files = os.listdir(dir_path) if not list_of_files: + sys.excepthook = exc_handler raise FileNotFoundError(f"Directory: {dir_path} is EMPTY!") if file_prefix is None and file_suffix is None: @@ -112,6 +115,7 @@ def main(self): if self.__check_if_file_exists(file_path=self.__file_path): self.__add_type_to_file(file_path=self.__file_path) else: + sys.excepthook = exc_handler raise FileNotFoundError(f"File: {self.__file_path} NOT found!") elif self.__dir_path is not None: if self.__check_if_dir_exists(dir_path=self.__dir_path): @@ -121,9 +125,11 @@ def main(self): for file in list_of_files_for_validation: self.__add_type_to_file(file_path=file) else: - raise FileNotFoundError(f"Directory: {self.__dir_path} does NOT exist!") + sys.excepthook = exc_handler + raise FileNotFoundError(f"Directory: {self.__dir_path} does NOT exist") else: - raise Exception("FILE path or DIRECTORY path has to be given!") + sys.excepthook = exc_handler + raise Exception("FILE path or DIRECTORY path has to be given") if __name__ == "__main__": diff --git a/src/lbaf/Utils/exception_handler.py b/src/lbaf/Utils/exception_handler.py new file mode 100644 index 000000000..9cb3544c4 --- /dev/null +++ b/src/lbaf/Utils/exception_handler.py @@ -0,0 +1,9 @@ +import os + +from .colors import red + + +def exc_handler(exception_type, exception, traceback): + """ Exception handler for hiding traceback. """ + module_name = red(f"[{os.path.splitext(os.path.split(__file__)[-1])[0]}]") + print(f"{module_name} {exception_type.__name__} {exception}") diff --git a/src/lbaf/Utils/vt_data_extractor.py b/src/lbaf/Utils/vt_data_extractor.py index a459b2b64..e497d255a 100644 --- a/src/lbaf/Utils/vt_data_extractor.py +++ b/src/lbaf/Utils/vt_data_extractor.py @@ -13,6 +13,7 @@ import json from lbaf.IO.schemaValidator import SchemaValidator +from lbaf.Utils.exception_handler import exc_handler class VTDataExtractor: @@ -45,6 +46,7 @@ def _initial_checks(self): print(f"Input data directory: {self.input_data_dir}") else: print("Input data directory NOT FOUND!") + sys.excepthook = exc_handler raise SystemExit(1) # Output data if not os.path.exists(self.output_data_dir): @@ -62,6 +64,7 @@ def _process_input_phases(phases_to_extract: list) -> list: phase_list = phase.split('-') if int(phase_list[0]) >= int(phase_list[1]): print('Phase range wrongly declared!') + sys.excepthook = exc_handler raise SystemExit(1) phase_range = list(range(int(phase_list[0]), int(phase_list[1]) + 1)) processed_list.extend(phase_range) @@ -104,6 +107,7 @@ def get_data_from_file(self, file_path: str) -> dict: else: print(f"Invalid JSON schema in {file_path}") SchemaValidator(schema_type=self.schema_type).validate(schema_to_validate=decompressed_dict) + sys.excepthook = exc_handler raise SystemExit(1) return decompressed_dict @@ -148,7 +152,7 @@ def main(self): # It should be declared as list of [int or str] # Int is just a phase number/id # Str is a range of pages in form of "a-b", "a" must be smaller than "b", e.g. "9-11" => [9, 10, 11] will be added - phases = [0,1,2,3,4,5,6,7,8,9,10] + phases = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] vtde = VTDataExtractor(input_data_dir="../data/nolb-8color-16nodes-stats", output_data_dir="../output", phases_to_extract=phases, diff --git a/tests/test_JSON_data_files_validator.py b/tests/test_JSON_data_files_validator.py index 9239b1441..c04e77ec8 100644 --- a/tests/test_JSON_data_files_validator.py +++ b/tests/test_JSON_data_files_validator.py @@ -159,7 +159,7 @@ def test_json_data_files_validator_file_not_found(self): file_suffix=None) with self.assertRaises(FileNotFoundError) as err: JSONDataFilesValidator().main() - self.assertEqual(err.exception.args[0], f"File: {self.wrong_file_path} NOT found!") + self.assertEqual(err.exception.args[0], f"File: {self.wrong_file_path} NOT found") def test_json_data_files_validator_dir_not_found(self): argparse.ArgumentParser.parse_args = Mock() @@ -169,7 +169,7 @@ def test_json_data_files_validator_dir_not_found(self): file_suffix=None) with self.assertRaises(FileNotFoundError) as err: JSONDataFilesValidator().main() - self.assertEqual(err.exception.args[0], f"Directory: {self.wrong_dir_path} does NOT exist!") + self.assertEqual(err.exception.args[0], f"Directory: {self.wrong_dir_path} does NOT exist") def test_json_data_files_validator_no_args(self): argparse.ArgumentParser.parse_args = Mock() @@ -179,7 +179,7 @@ def test_json_data_files_validator_no_args(self): file_suffix=None) with self.assertRaises(Exception) as err: JSONDataFilesValidator().main() - self.assertEqual(err.exception.args[0], "FILE path or DIRECTORY path has to be given!") + self.assertEqual(err.exception.args[0], "FILE path or DIRECTORY path has to be given") def test_json_data_files_validator_wrong_file_schema(self): argparse.ArgumentParser.parse_args = Mock() diff --git a/tests/test_lbs_vt_data_reader.py b/tests/test_lbs_vt_data_reader.py index 81a8a8a2b..dc2b7f0a6 100644 --- a/tests/test_lbs_vt_data_reader.py +++ b/tests/test_lbs_vt_data_reader.py @@ -137,7 +137,7 @@ def test_lbs_vt_data_reader_read_compressed(self): def test_lbs_vt_data_reader_read_file_not_found(self): with self.assertRaises(FileNotFoundError) as err: LoadReader(file_prefix=f"{self.file_prefix}xd", logger=self.logger, file_suffix='json').read(0, 0) - self.assertEqual(err.exception.args[0], f"File {self.file_prefix}xd.0.json not found!") + self.assertEqual(err.exception.args[0], f"File {self.file_prefix}xd.0.json not found") def test_lbs_vt_data_reader_read_wrong_schema(self): file_prefix = os.path.join(self.data_dir, 'synthetic_lb_stats_wrong_schema', 'data')