From 7e95536b4b721e0faf0e6724da92f5e8d623994b Mon Sep 17 00:00:00 2001 From: dtrai2 <95028228+dtrai2@users.noreply.github.com> Date: Fri, 8 Nov 2024 11:39:08 +0100 Subject: [PATCH] standardize exception inheritance to `Exception` (#695) --- CHANGELOG.md | 1 + logprep/abc/processor.py | 2 +- logprep/connector/dummy/input.py | 6 +++--- logprep/connector/file/input.py | 2 +- logprep/connector/json/input.py | 2 +- logprep/connector/jsonl/input.py | 2 +- .../filter/expression/filter_expression.py | 2 +- logprep/filter/lucene_filter.py | 2 +- logprep/processor/amides/detection.py | 4 ++-- logprep/processor/dissector/processor.py | 4 +--- logprep/processor/field_manager/processor.py | 3 +-- logprep/processor/labeler/labeling_schema.py | 2 +- .../processor/list_comparison/processor.py | 2 +- .../processor/template_replacer/processor.py | 2 +- .../util/auto_rule_tester/auto_rule_tester.py | 2 +- logprep/util/grok_pattern_loader.py | 2 +- .../util/pre_detector_rule_matching_tester.py | 2 +- .../connector/test_confluent_kafka_common.py | 2 +- .../connector/test_confluent_kafka_input.py | 2 +- tests/unit/connector/test_dummy_input.py | 6 +++--- tests/unit/connector/test_dummy_output.py | 2 +- tests/unit/connector/test_json_input.py | 2 +- .../test_clusterer_signature_phase.py | 6 +++--- .../generic_adder/test_generic_adder.py | 20 +++++++++---------- 24 files changed, 40 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6620e4e..537507eb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Breaking ### Features ### Improvements +* replace `BaseException` with `Exception` for custom errors ### Bugfix - fix `confluent_kafka.store_offsets` if `last_valid_record` is `None`, can happen if a rebalancing happens diff --git a/logprep/abc/processor.py b/logprep/abc/processor.py index 1bdd6ac60..c7c4510cc 100644 --- a/logprep/abc/processor.py +++ b/logprep/abc/processor.py @@ -375,7 +375,7 @@ def _has_missing_values(self, event, rule, source_field_dict): if missing_fields: if rule.ignore_missing_fields: return True - error = BaseException(f"{self.name}: no value for fields: {missing_fields}") + error = Exception(f"{self.name}: no value for fields: {missing_fields}") self._handle_warning_error(event, rule, error) return True return False diff --git a/logprep/connector/dummy/input.py b/logprep/connector/dummy/input.py index 292b351b2..4ae58188f 100644 --- a/logprep/connector/dummy/input.py +++ b/logprep/connector/dummy/input.py @@ -4,7 +4,7 @@ A dummy input that returns the documents it was initialized with. -If a "document" is derived from BaseException, that exception will be thrown instead of +If a "document" is derived from Exception, that exception will be thrown instead of returning a document. The exception will be removed and subsequent calls may return documents or throw other exceptions in the given order. @@ -36,7 +36,7 @@ class DummyInput(Input): class Config(Input.Config): """DummyInput specific configuration""" - documents: List[Union[dict, type, BaseException]] + documents: List[Union[dict, type, Exception]] """A list of documents that should be returned.""" repeat_documents: Optional[str] = field( validator=validators.instance_of(bool), default=False @@ -57,6 +57,6 @@ def _get_event(self, timeout: float) -> tuple: document = self._documents.pop(0) - if (document.__class__ == type) and issubclass(document, BaseException): + if (document.__class__ == type) and issubclass(document, Exception): raise document return document, None diff --git a/logprep/connector/file/input.py b/logprep/connector/file/input.py index 6e9d89477..3c5a74897 100644 --- a/logprep/connector/file/input.py +++ b/logprep/connector/file/input.py @@ -2,7 +2,7 @@ FileInput ========== A generic line input that returns the documents it was initialized with. -If a "document" is derived from BaseException, that exception will be thrown instead of +If a "document" is derived from Exception, that exception will be thrown instead of returning a document. The exception will be removed and subsequent calls may return documents or throw other exceptions in the given order. diff --git a/logprep/connector/json/input.py b/logprep/connector/json/input.py index 7269bd042..c05a6e30b 100644 --- a/logprep/connector/json/input.py +++ b/logprep/connector/json/input.py @@ -4,7 +4,7 @@ A json input that returns the documents it was initialized with. -If a "document" is derived from BaseException, that exception will be thrown instead of +If a "document" is derived from Exception, that exception will be thrown instead of returning a document. The exception will be removed and subsequent calls may return documents or throw other exceptions in the given order. diff --git a/logprep/connector/jsonl/input.py b/logprep/connector/jsonl/input.py index 426fd23dc..a580db904 100644 --- a/logprep/connector/jsonl/input.py +++ b/logprep/connector/jsonl/input.py @@ -4,7 +4,7 @@ A json line input that returns the documents it was initialized with. -If a "document" is derived from BaseException, that exception will be thrown instead of +If a "document" is derived from Exception, that exception will be thrown instead of returning a document. The exception will be removed and subsequent calls may return documents or throw other exceptions in the given order. diff --git a/logprep/filter/expression/filter_expression.py b/logprep/filter/expression/filter_expression.py index 9ef840494..701d2f657 100644 --- a/logprep/filter/expression/filter_expression.py +++ b/logprep/filter/expression/filter_expression.py @@ -6,7 +6,7 @@ from typing import Any, List -class FilterExpressionError(BaseException): +class FilterExpressionError(Exception): """Base class for FilterExpression related exceptions.""" diff --git a/logprep/filter/lucene_filter.py b/logprep/filter/lucene_filter.py index 18a5187ee..31f16c7ed 100644 --- a/logprep/filter/lucene_filter.py +++ b/logprep/filter/lucene_filter.py @@ -130,7 +130,7 @@ logger = logging.getLogger("LuceneFilter") -class LuceneFilterError(BaseException): +class LuceneFilterError(Exception): """Base class for LuceneFilter related exceptions.""" diff --git a/logprep/processor/amides/detection.py b/logprep/processor/amides/detection.py index a38c7532b..93f948bb0 100644 --- a/logprep/processor/amides/detection.py +++ b/logprep/processor/amides/detection.py @@ -10,7 +10,7 @@ from logprep.processor.amides.features import CommaSeparation -class DetectionModelError(BaseException): +class DetectionModelError(Exception): """Base exception class for all RuleModel-related errors.""" @@ -98,7 +98,7 @@ def detect(self, sample: str) -> Tuple[bool, float]: return False, round(confidence_value, 3) -class RuleAttributorError(BaseException): +class RuleAttributorError(Exception): """Base class for all RuleAttributor-related Errors.""" diff --git a/logprep/processor/dissector/processor.py b/logprep/processor/dissector/processor.py index 8d1444e5e..1da24a239 100644 --- a/logprep/processor/dissector/processor.py +++ b/logprep/processor/dissector/processor.py @@ -70,9 +70,7 @@ def _get_mappings(self, event, rule) -> List[Tuple[Callable, dict, str, str, str if loop_content is None: if rule.ignore_missing_fields: continue - error = BaseException( - f"dissector: mapping field '{source_field}' does not exist" - ) + error = Exception(f"dissector: mapping field '{source_field}' does not exist") self._handle_warning_error(event, rule, error) if delimiter is not None and loop_content is not None: content, _, loop_content = loop_content.partition(delimiter) diff --git a/logprep/processor/field_manager/processor.py b/logprep/processor/field_manager/processor.py index 98280d4b6..09eeeab6f 100644 --- a/logprep/processor/field_manager/processor.py +++ b/logprep/processor/field_manager/processor.py @@ -197,8 +197,7 @@ def _get_field_values(event, source): def _get_missing_fields_error(self, source_fields, field_values): missing_fields = [key for key, value in zip(source_fields, field_values) if value is None] - error = BaseException(f"{self.name}: missing source_fields: {missing_fields}") - return error + return Exception(f"{self.name}: missing source_fields: {missing_fields}") @staticmethod def _get_flatten_source_fields(source_fields_values): diff --git a/logprep/processor/labeler/labeling_schema.py b/logprep/processor/labeler/labeling_schema.py index e5826d3d4..e589717b6 100644 --- a/logprep/processor/labeler/labeling_schema.py +++ b/logprep/processor/labeler/labeling_schema.py @@ -12,7 +12,7 @@ from logprep.util.getter import GetterFactory -class LabelingSchemaError(BaseException): +class LabelingSchemaError(Exception): """Base class for LabelingSchema related exceptions.""" diff --git a/logprep/processor/list_comparison/processor.py b/logprep/processor/list_comparison/processor.py index b8bdbae1d..e3166ec2e 100644 --- a/logprep/processor/list_comparison/processor.py +++ b/logprep/processor/list_comparison/processor.py @@ -36,7 +36,7 @@ from logprep.util.helper import add_field_to, get_dotted_field_value -class ListComparisonError(BaseException): +class ListComparisonError(Exception): """Base class for ListComparison related exceptions.""" def __init__(self, name: str, message: str): diff --git a/logprep/processor/template_replacer/processor.py b/logprep/processor/template_replacer/processor.py index 653e1e0cd..7a0502809 100644 --- a/logprep/processor/template_replacer/processor.py +++ b/logprep/processor/template_replacer/processor.py @@ -45,7 +45,7 @@ from logprep.util.helper import add_field_to, get_dotted_field_value -class TemplateReplacerError(BaseException): +class TemplateReplacerError(Exception): """Base class for TemplateReplacer related exceptions.""" def __init__(self, name: str, message: str): diff --git a/logprep/util/auto_rule_tester/auto_rule_tester.py b/logprep/util/auto_rule_tester/auto_rule_tester.py index c1837ae3b..2083a4d5a 100644 --- a/logprep/util/auto_rule_tester/auto_rule_tester.py +++ b/logprep/util/auto_rule_tester/auto_rule_tester.py @@ -77,7 +77,7 @@ # pylint: disable=protected-access -class AutoRuleTesterException(BaseException): +class AutoRuleTesterException(Exception): """Base class for AutoRuleTester related exceptions.""" def __init__(self, message: str): diff --git a/logprep/util/grok_pattern_loader.py b/logprep/util/grok_pattern_loader.py index 6536edc52..7f2437a02 100644 --- a/logprep/util/grok_pattern_loader.py +++ b/logprep/util/grok_pattern_loader.py @@ -6,7 +6,7 @@ PATTERN_CONVERSION = [("[[:alnum:]]", r"\w")] -class GrokPatternLoaderError(BaseException): +class GrokPatternLoaderError(Exception): """Base class for GrokPatternLoader related exceptions.""" def __init__(self, message: str): diff --git a/logprep/util/pre_detector_rule_matching_tester.py b/logprep/util/pre_detector_rule_matching_tester.py index 8d41f28ef..e6b4eb72c 100644 --- a/logprep/util/pre_detector_rule_matching_tester.py +++ b/logprep/util/pre_detector_rule_matching_tester.py @@ -23,7 +23,7 @@ # pylint: disable=protected-access -class MatchingRuleTesterException(BaseException): +class MatchingRuleTesterException(Exception): """Base class for MatchingRuleTester related exceptions.""" def __init__(self, message: str): diff --git a/tests/unit/connector/test_confluent_kafka_common.py b/tests/unit/connector/test_confluent_kafka_common.py index 25ef76dcb..5e16dd978 100644 --- a/tests/unit/connector/test_confluent_kafka_common.py +++ b/tests/unit/connector/test_confluent_kafka_common.py @@ -31,7 +31,7 @@ def test_create_fails_for_unknown_option(self): def test_error_callback_logs_error(self): self.object.metrics.number_of_errors = 0 with mock.patch("logging.Logger.error") as mock_error: - test_error = BaseException("test error") + test_error = Exception("test error") self.object._error_callback(test_error) mock_error.assert_called() mock_error.assert_called_with(f"{self.object.describe()}: {test_error}") diff --git a/tests/unit/connector/test_confluent_kafka_input.py b/tests/unit/connector/test_confluent_kafka_input.py index fc284e4f8..d2cf0344d 100644 --- a/tests/unit/connector/test_confluent_kafka_input.py +++ b/tests/unit/connector/test_confluent_kafka_input.py @@ -234,7 +234,7 @@ def test_get_next_raises_critical_input_parsing_error(self): def test_commit_callback_raises_warning_error_and_counts_failures(self): with pytest.raises(InputWarning, match="Could not commit offsets"): - self.object._commit_callback(BaseException, ["topic_partition"]) + self.object._commit_callback(Exception, ["topic_partition"]) assert self.object._commit_failures == 1 def test_commit_callback_counts_commit_success(self): diff --git a/tests/unit/connector/test_dummy_input.py b/tests/unit/connector/test_dummy_input.py index 8580bd68f..df496ded9 100644 --- a/tests/unit/connector/test_dummy_input.py +++ b/tests/unit/connector/test_dummy_input.py @@ -10,7 +10,7 @@ from tests.unit.connector.base import BaseInputTestCase -class DummyError(BaseException): +class DummyError(Exception): pass @@ -44,9 +44,9 @@ def test_raises_exceptions_instead_of_returning_them_in_document(self): def test_raises_exceptions_instead_of_returning_them(self): config = copy.deepcopy(self.CONFIG) - config["documents"] = [BaseException] + config["documents"] = [Exception] self.object = Factory.create({"Test Instance Name": config}) - with raises(BaseException): + with raises(Exception): self.object.get_next(self.timeout) def test_repeat_documents_repeats_documents(self): diff --git a/tests/unit/connector/test_dummy_output.py b/tests/unit/connector/test_dummy_output.py index 7136111d0..082498d93 100644 --- a/tests/unit/connector/test_dummy_output.py +++ b/tests/unit/connector/test_dummy_output.py @@ -45,7 +45,7 @@ def test_raises_exception_on_call_to_store(self): config.update({"exceptions": ["FatalOutputError"]}) dummy_output = Factory.create({"test connector": config}) - with raises(BaseException, match="FatalOutputError"): + with raises(Exception, match="FatalOutputError"): dummy_output.store({"order": 0}) def test_raises_exception_on_call_to_store_custom(self): diff --git a/tests/unit/connector/test_json_input.py b/tests/unit/connector/test_json_input.py index 93095fad5..6e7db2b15 100644 --- a/tests/unit/connector/test_json_input.py +++ b/tests/unit/connector/test_json_input.py @@ -11,7 +11,7 @@ from tests.unit.connector.base import BaseInputTestCase -class DummyError(BaseException): +class DummyError(Exception): pass diff --git a/tests/unit/processor/clusterer/test_clusterer_signature_phase.py b/tests/unit/processor/clusterer/test_clusterer_signature_phase.py index faf0fdd8b..512163d77 100644 --- a/tests/unit/processor/clusterer/test_clusterer_signature_phase.py +++ b/tests/unit/processor/clusterer/test_clusterer_signature_phase.py @@ -48,14 +48,14 @@ def test_apply_signature_engine(self): def test_exception_if_raw_text_with_start_tag(): log_record = LogRecord(raw_text="Test log with start tag <+> must raise an exception") sign_engine = SignatureEngine() - with pytest.raises(BaseException, match=r"Start-tag <\+> in raw log message"): + with pytest.raises(Exception, match=r"Start-tag <\+> in raw log message"): sign_engine.run(log_record, LogSaltModeTestComposition.rules[0]) @staticmethod def test_exception_if_raw_text_with_end_tag(): log_record = LogRecord(raw_text="Test log with end tag must raise an exception") sign_engine = SignatureEngine() - with pytest.raises(BaseException, match=r"End-tag in raw log message"): + with pytest.raises(Exception, match=r"End-tag in raw log message"): sign_engine.run(log_record, LogSaltModeTestComposition.rules[0]) @staticmethod @@ -64,7 +64,7 @@ def test_missing_end_tag_in_sig_text(): "Test log with a start tag <+>, but a missing end tag, " "must raise an exception" ) stp = SignatureTagParser() - with pytest.raises(BaseException): + with pytest.raises(Exception): stp.calculate_signature(sig_text) diff --git a/tests/unit/processor/generic_adder/test_generic_adder.py b/tests/unit/processor/generic_adder/test_generic_adder.py index 5fe29930b..f792741ed 100644 --- a/tests/unit/processor/generic_adder/test_generic_adder.py +++ b/tests/unit/processor/generic_adder/test_generic_adder.py @@ -489,11 +489,11 @@ def test_check_if_file_not_stale_after_initialization_of_the_generic_adder(self) assert not self.object._check_if_file_not_exists_or_stale(time.time()) def test_check_if_file_stale_after_enough_time_has_passed(self): - time.sleep(0.2) # nosemgrep + time.sleep(0.2) assert self.object._check_if_file_not_exists_or_stale(time.time()) def test_check_if_file_not_stale_after_enough_time_has_passed_but_file_has_been_changed(self): - time.sleep(0.2) # nosemgrep + time.sleep(0.2) with open(self.object._db_file_path, "r", encoding="utf-8") as db_file: file_temp = db_file.read() now = time.time() @@ -561,7 +561,7 @@ def test_sql_database_reloads_table_on_change_after_wait(self): document_2 = {"add_from_sql_db_table": "Test", "source": "TEST_0.test.123"} self.object.process(document_1) - time.sleep(0.2) # nosemgrep + time.sleep(0.2) mock_simulate_table_change() self.object.process(document_2) @@ -579,7 +579,7 @@ def test_sql_database_with_empty_table_load_after_change(self): self.object._db_table = {} self.object._initialize_sql(self.CONFIG["sql_config"]) mock_simulate_table_change() - time.sleep(0.2) # nosemgrep + time.sleep(0.2) self.object.process(document) assert document == expected @@ -621,14 +621,14 @@ def test_time_to_check_for_change_not_read_for_change(self): assert self.object._db_connector.time_to_check_for_change() is False def test_time_to_check_for_change_read_for_change(self): - time.sleep(self.object._file_check_interval) # nosemgrep + time.sleep(self.object._file_check_interval) assert self.object._db_connector.time_to_check_for_change() is True def test_update_from_db_and_write_to_file_change_and_stale(self): assert os.path.isfile(self.object._db_file_path) last_file_change = os.path.getmtime(self.object._db_file_path) mock_simulate_table_change() - time.sleep(self.object._file_check_interval) # nosemgrep + time.sleep(self.object._file_check_interval) self.object._update_from_db_and_write_to_file() assert self.object._db_table == { "TEST_0": (["b", "fi"], ["c", "fo"]), @@ -640,7 +640,7 @@ def test_update_from_db_and_write_to_file_change_and_stale(self): def test_update_from_db_and_write_to_file_no_change_and_stale(self): assert os.path.isfile(self.object._db_file_path) last_file_change = os.path.getmtime(self.object._db_file_path) - time.sleep(self.object._file_check_interval) # nosemgrep + time.sleep(self.object._file_check_interval) self.object._update_from_db_and_write_to_file() assert self.object._db_table == { "TEST_0": (["b", "foo"], ["c", "bar"]), @@ -654,7 +654,7 @@ def test_update_from_db_and_write_to_file_change_and_not_stale(self): last_file_change = os.path.getmtime(self.object._db_file_path) self.object._file_check_interval = 9999999 mock_simulate_table_change() - time.sleep(0.01) # nosemgrep + time.sleep(0.01) self.object._update_from_db_and_write_to_file() assert self.object._db_table == { "TEST_0": (["b", "fi"], ["c", "fo"]), @@ -667,7 +667,7 @@ def test_update_from_db_and_write_to_file_no_change_and_not_stale(self): assert os.path.isfile(self.object._db_file_path) last_file_change = os.path.getmtime(self.object._db_file_path) self.object._file_check_interval = 9999999 - time.sleep(0.01) # nosemgrep + time.sleep(0.01) self.object._update_from_db_and_write_to_file() assert self.object._db_table == { "TEST_0": (["b", "foo"], ["c", "bar"]), @@ -679,7 +679,7 @@ def test_update_from_db_and_write_to_file_no_change_and_not_stale(self): def test_update_from_db_and_write_to_file_no_existing_file_stale(self): assert os.path.isfile(self.object._db_file_path) os.remove(self.object._db_file_path) - time.sleep(self.object._file_check_interval) # nosemgrep + time.sleep(self.object._file_check_interval) self.object._db_connector._last_table_checksum = None self.object._update_from_db_and_write_to_file() assert self.object._db_table == {