diff --git a/gemd/entity/bounds_validation.py b/gemd/entity/bounds_validation.py index 3b8c039..9a58412 100644 --- a/gemd/entity/bounds_validation.py +++ b/gemd/entity/bounds_validation.py @@ -1,7 +1,11 @@ from enum import IntEnum from contextlib import contextmanager +from logging import getLogger -__all__ = ["WarningLevel", "get_validation_level", "set_validation_level", "validation_level"] +__all__ = ["WarningLevel", "get_validation_level", "set_validation_level", + "validation_level", "raise_or_warn"] + +logger = getLogger(__name__) class WarningLevel(IntEnum): @@ -43,3 +47,25 @@ def validation_level(level: WarningLevel): # Restore previous value BOUNDS_VALIDATION = old_value + + +def raise_or_warn(message, *, exc_class=ValueError, **kwargs): + """Raise, warn, or ignore based on the current validation level. + + Parameters + ---------- + message: str + The error/warning message. + exc_class: type + Exception class to raise when level is FATAL. + **kwargs: + Additional keyword arguments passed to the exception constructor. + + """ + level = get_validation_level() + if level == WarningLevel.IGNORE: + return + if level == WarningLevel.WARNING: + logger.warning(message) + else: + raise exc_class(message, **kwargs) diff --git a/tests/entity/test_bounds_validation.py b/tests/entity/test_bounds_validation.py index 28f2665..fdf515e 100644 --- a/tests/entity/test_bounds_validation.py +++ b/tests/entity/test_bounds_validation.py @@ -1,5 +1,9 @@ +import logging + +import pytest + from gemd.entity.bounds_validation import WarningLevel, set_validation_level, \ - get_validation_level, validation_level + get_validation_level, validation_level, raise_or_warn def test_bounds_validation(): @@ -9,3 +13,24 @@ def test_bounds_validation(): set_validation_level(WarningLevel.WARNING) assert get_validation_level() == WarningLevel.WARNING, "Setter worked." assert get_validation_level() == old_level, "Original level restored." + + +def test_raise_or_warn_ignore(): + """Verify raise_or_warn does nothing at IGNORE level.""" + with validation_level(WarningLevel.IGNORE): + raise_or_warn("should be ignored") # no exception, no warning + + +def test_raise_or_warn_warning(caplog): + """Verify raise_or_warn logs at WARNING level.""" + with validation_level(WarningLevel.WARNING): + with caplog.at_level(logging.WARNING): + raise_or_warn("check this") + assert "check this" in caplog.text + + +def test_raise_or_warn_fatal(): + """Verify raise_or_warn raises at FATAL level.""" + with validation_level(WarningLevel.FATAL): + with pytest.raises(ValueError, match="boom"): + raise_or_warn("boom")