diff --git a/CHANGELOG.md b/CHANGELOG.md index e8e4b015..3ef7c55c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Added `rmsd` and `rmsd_kabsch` to calculate RMSD without and with rotational alignment to `Structure` class (#230). - Added `calc_rotational_constants` to calculate molecular rotational constants to `Structure` class (#230). - Added `calc_rotor_type` to classify a molecule's rotor type to `Structure` class (#230). +- Add type checks for ncores and memory setters in `Input` and checks for invalid negative values (#261). ### Changed - Refactored methods from Runner into BaseRunner (#193) diff --git a/src/opi/input/core.py b/src/opi/input/core.py index 188519c3..fa238c80 100644 --- a/src/opi/input/core.py +++ b/src/opi/input/core.py @@ -114,12 +114,25 @@ def ncores(self) -> int | None: @ncores.setter def ncores(self, value: int | None) -> None: """ + Setter for the ncores property. Value given must be a non-negative integer. + Parameters ---------- value : int | None + + Raises + ------ + TypeError + If the given value is not an integer. + + ValueError + If the given value is negative. """ - if value is not None and value < 0: - raise ValueError(f"{self.__class__.__name__}.ncores must be a positive integer.") + if value is not None: + if not isinstance(value, int): + raise TypeError(f"{self.__class__.__name__}.ncores must be an integer.") + elif value < 0: + raise ValueError(f"{self.__class__.__name__}.ncores must be a positive integer.") # << END OF IF self._ncores = value @@ -130,12 +143,25 @@ def memory(self) -> int | None: @memory.setter def memory(self, value: int | None) -> None: """ + Setter for the memory property. Value given must be a non-negative integer. + Parameters ---------- value : int | None + + Raises + ------ + TypeError + If the given value is not an integer. + + ValueError + If the given value is negative. """ - if value is not None and value < 0: - raise ValueError(f"{self.__class__.__name__}.memory must be a positive integer.") + if value is not None: + if not isinstance(value, int): + raise TypeError(f"{self.__class__.__name__}.memory must be an integer.") + elif value < 0: + raise ValueError(f"{self.__class__.__name__}.memory must be a positive integer.") # << END OF IF self._memory = value diff --git a/tests/unit/test_input_core.py b/tests/unit/test_input_core.py new file mode 100644 index 00000000..a97734ef --- /dev/null +++ b/tests/unit/test_input_core.py @@ -0,0 +1,66 @@ +import pytest + +from opi.core import Calculator + +""" +This module contains tests for the `ncores` and `memory` properties of the `Input` class. +""" + + +@pytest.fixture +def empty_calc(): + """An empty instance of `Calculator`.""" + empty_calc = Calculator("test", version_check=False) + return empty_calc + + +@pytest.mark.unit +@pytest.mark.input +@pytest.mark.parametrize("ncores", [0, 4, None]) +def test_ncores_valid(empty_calc: Calculator, ncores: int | None): + """Test for `Input.ncores` setter with valid values.""" + empty_calc.input.ncores = ncores + assert empty_calc.input.ncores == ncores + + +@pytest.mark.unit +@pytest.mark.input +@pytest.mark.parametrize("ncores", ["4", 4.0, [4]]) +def test_ncores_wrong_type(empty_calc: Calculator, ncores: object): + """Test for `Input.ncores` setter with values of the wrong type.""" + with pytest.raises(TypeError): + empty_calc.input.ncores = ncores + + +@pytest.mark.unit +@pytest.mark.input +def test_ncores_negative(empty_calc: Calculator): + """Test for `Input.ncores` setter with an invalid negative value.""" + with pytest.raises(ValueError): + empty_calc.input.ncores = -1 + + +@pytest.mark.unit +@pytest.mark.input +@pytest.mark.parametrize("memory", [0, 4000, None]) +def test_memory_valid(empty_calc: Calculator, memory: int | None): + """Test for `Input.memory` setter with valid values.""" + empty_calc.input.memory = memory + assert empty_calc.input.memory == memory + + +@pytest.mark.unit +@pytest.mark.input +@pytest.mark.parametrize("memory", ["4000", 4000.0, [4000]]) +def test_memory_wrong_type(empty_calc: Calculator, memory: object): + """Test for `Input.memory` setter with values of the wrong type.""" + with pytest.raises(TypeError): + empty_calc.input.memory = memory + + +@pytest.mark.unit +@pytest.mark.input +def test_memory_negative(empty_calc: Calculator): + """Test for `Input.memory` setter with an invalid negative value.""" + with pytest.raises(ValueError): + empty_calc.input.memory = -1