From 035e5ca95b60bd5c07447d03a4f664f7c3e021e5 Mon Sep 17 00:00:00 2001 From: Luca Atella Date: Wed, 20 Nov 2024 18:59:31 +0100 Subject: [PATCH] refactor(errors): centralize validation error messages for better maintainability - Added specific error messages for filename, version, environment variables, and class/attribute mismatches. - Enhanced clarity and reusability of validation errors in SpyModel. - Organized errors for SpyModel validation, including environment and variable mismatches --- src/importspy/errors.py | 17 +++++++++- src/importspy/utils/spy_model_utils.py | 47 ++++++++++++-------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/importspy/errors.py b/src/importspy/errors.py index f9250f6..1731414 100644 --- a/src/importspy/errors.py +++ b/src/importspy/errors.py @@ -1,5 +1,20 @@ class Errors: + ANALYSIS_RECURSION_WARNING = ("Warning: You cannot analyze the code that itself handles analysis, as this may result " "in uncontrolled deep recursion. To avoid potential performance issues or stack overflow " - "errors, ensure that the analysis process does not recursively attempt to evaluate itself.") \ No newline at end of file + "errors, ensure that the analysis process does not recursively attempt to evaluate itself.") + + ### Spy model validation + FILENAME_MISMATCH = "Filename mismatch: {0} != {1}" + VERSION_MISMATCH = "Version mismatch: {0} != {1}" + ENV_VAR_MISMATCH = "Value mismatch for environment variable '{0}': expected '{1}', found '{2}'." + ENV_VAR_MISSING = "Missing environment variable: '{0}'. Ensure it is defined in the system." + VAR_MISMATCH = "Value mismatch for variable '{0}': expected '{1}', found '{2}'" + VAR_MISSING = "Missing variable: '{0}'. Ensure it is defined." + GENERIC_FUNCTIONS_MISMATCH = "Functions mismatch: Some functions are not defined." + CLASS_MISSING = "Missing class: {0} Ensure it is defined." + GENERIC_CLASS_ATTRIBUTES_MISMATCH = "Class attributes mismatch in Class {0}: some attributes are not defined in the class {0}." + GENERIC_INSTANCE_ATTRIBUTES_MISMATCH = "Instance attributes mismatch in Class {0}: some attributes are not defined in the __init__ method of the class {0}." + GENERIC_CLASS_METHODS_MISMATCH = "Methods mismatch in Class {0}: some attributes are not defined in the class {0}." + GENERIC_CLASS_SUPERCLASSES_MISMATCH = "Superclass mismatch in Class: {0} some superclasses are not defined in the class {0}." \ No newline at end of file diff --git a/src/importspy/utils/spy_model_utils.py b/src/importspy/utils/spy_model_utils.py index e29922a..2a88179 100644 --- a/src/importspy/utils/spy_model_utils.py +++ b/src/importspy/utils/spy_model_utils.py @@ -1,11 +1,12 @@ from importspy.models import SpyModel +from ..errors import Errors def is_subset(spy_model_1: SpyModel, spy_model_2: SpyModel) -> bool: """ Determine if the first SpyModel is a subset of the second SpyModel. This function checks whether all relevant attributes (such as functions, classes, methods, - superclasses, filename, and version) specified in `spy_model_1` are present in `spy_model_2`. + superclassesf"Superclass mismatch in {}", filename, and version) specified in `spy_model_1` are present in `spy_model_2`. It throws a ValueError with a specific message indicating the type of mismatch. Parameters: @@ -32,37 +33,33 @@ def is_subset(spy_model_1: SpyModel, spy_model_2: SpyModel) -> bool: ``` """ if spy_model_1.filename and spy_model_1.filename != spy_model_2.filename: - raise ValueError(f"Filename mismatch: {spy_model_1.filename} != {spy_model_2.filename}") + raise ValueError(Errors.FILENAME_MISMATCH.format(spy_model_1.filename, spy_model_2.filename)) if spy_model_1.version and spy_model_1.version != spy_model_2.version: - raise ValueError(f"Version mismatch: {spy_model_1.version} != {spy_model_2.version}") - spy_model_2_env_vars = spy_model_2.env_vars - for expected_key, expected_value in spy_model_1.env_vars.items(): - if expected_key in spy_model_2_env_vars: - if expected_value != spy_model_2_env_vars[expected_key]: - raise ValueError(f"Value mismatch for environment variable '{expected_key}': expected '{expected_value}', found '{spy_model_2_env_vars[expected_key]}'." - ) - else: - raise ValueError(f"Missing environment variable: '{expected_key}'. Ensure it is defined in the system.") - spy_model_2_variables = spy_model_2.variables - for expected_key, expected_value in spy_model_1.variables.items(): - if expected_key in spy_model_2_variables: - if expected_value != spy_model_2_variables[expected_key]: - raise ValueError(f"Value mismatch for variable '{expected_key}': expected '{expected_value}', found '{spy_model_2_variables[expected_key]}'." - ) - else: - raise ValueError(f"Missing variable: '{expected_key}'. Ensure it is defined.") + raise ValueError(Errors.VERSION_MISMATCH.format(spy_model_1.version, spy_model_2.version)) + #Env vars validation + dict_compare(spy_model_1.env_vars, spy_model_2.env_vars, Errors.ENV_VAR_MISSING, Errors.ENV_VAR_MISMATCH) + #Variables validation + dict_compare(spy_model_1.variables, spy_model_2.variables, Errors.VAR_MISSING, Errors.VAR_MISMATCH) if spy_model_1.functions and not set(spy_model_1.functions).issubset(spy_model_2.functions): - raise ValueError("Functions mismatch: Some functions are not present in the second model.") + raise ValueError(Errors.GENERIC_FUNCTIONS_MISMATCH) for class_1 in spy_model_1.classes: class_2 = next((cls for cls in spy_model_2.classes if cls.name == class_1.name), None) if not class_2: - raise ValueError(f"Class not found: {class_1.name}") + raise ValueError(Errors.CLASS_MISSING.format(class_1.name)) if class_1.class_attr and not set(class_1.class_attr).issubset(class_2.class_attr): - raise ValueError(f"Class attributes mismatch in {class_1.name}") + raise ValueError(Errors.GENERIC_CLASS_ATTRIBUTES_MISMATCH.format(class_1.name)) if class_1.instance_attr and not set(class_1.instance_attr).issubset(class_2.instance_attr): - raise ValueError(f"Instance attributes mismatch in {class_1.name}") + raise ValueError(Errors.GENERIC_INSTANCE_ATTRIBUTES_MISMATCH.format(class_1.name)) if class_1.methods and not set(class_1.methods).issubset(class_2.methods): - raise ValueError(f"Methods mismatch in {class_1.name}") + raise ValueError(Errors.GENERIC_CLASS_METHODS_MISMATCH.format(class_1.name)) if class_1.superclasses and not set(class_1.superclasses).issubset(class_2.superclasses): - raise ValueError(f"Superclass mismatch in {class_1.name}") + raise ValueError(Errors.GENERIC_CLASS_SUPERCLASSES_MISMATCH.format(class_1.name)) return True + +def dict_compare(dict1:dict, dict2:dict, missing_error:str, mismatch_error:str): + for expected_key, expected_value in dict1.items(): + if expected_key in dict2: + if expected_value != dict2[expected_key]: + raise ValueError(mismatch_error.format(expected_key, expected_value, dict2[expected_key])) + else: + raise ValueError(missing_error.format(expected_key)) \ No newline at end of file