From 34d4565d23aec969a93a469ec88fe5dca88846fb Mon Sep 17 00:00:00 2001 From: Nick Moore Date: Thu, 29 Aug 2024 16:26:48 +1000 Subject: [PATCH] more coverage --- countess/core/parameters.py | 7 +- tests/test_parameters.py | 174 ++++++++++++++++++++++++------------ 2 files changed, 125 insertions(+), 56 deletions(-) diff --git a/countess/core/parameters.py b/countess/core/parameters.py index 0dc1b11..eb25998 100644 --- a/countess/core/parameters.py +++ b/countess/core/parameters.py @@ -579,7 +579,12 @@ def get_column_or_value(self, df: pd.DataFrame, numeric: bool): def set_choices(self, choices: Iterable[str]): self.choices = list(choices) - if self._value is not None and type(self._value) is str and self._value.startswith(self.PREFIX) and self._value not in self.choices: + if ( + self._value is not None + and type(self._value) is str + and self._value.startswith(self.PREFIX) + and self._value not in self.choices + ): self._value = self.DEFAULT_VALUE self._choice = None diff --git a/tests/test_parameters.py b/tests/test_parameters.py index 21fac95..241f1fb 100644 --- a/tests/test_parameters.py +++ b/tests/test_parameters.py @@ -1,8 +1,29 @@ -import pytest +import io +from unittest.mock import mock_open, patch import pandas as pd +import pytest -from countess.core.parameters import BooleanParam, FloatParam, MultiParam, StringParam, make_prefix_groups, ScalarParam, StringCharacterSetParam, ChoiceParam, DataTypeOrNoneChoiceParam, ColumnOrNoneChoiceParam, ColumnOrIntegerParam, DataTypeChoiceParam, ColumnChoiceParam, ColumnGroupOrNoneChoiceParam, ColumnOrIndexChoiceParam +from countess.core.parameters import ( + ArrayParam, + BooleanParam, + ChoiceParam, + ColumnChoiceParam, + ColumnGroupOrNoneChoiceParam, + ColumnOrIndexChoiceParam, + ColumnOrIntegerParam, + ColumnOrNoneChoiceParam, + DataTypeChoiceParam, + DataTypeOrNoneChoiceParam, + FileParam, + FloatParam, + IntegerParam, + MultiParam, + ScalarParam, + StringCharacterSetParam, + StringParam, + make_prefix_groups, +) def test_make_prefix_groups(): @@ -10,13 +31,14 @@ def test_make_prefix_groups(): assert x == {"one_": ["two", "three"], "two_": ["one", "two", "three"]} -def test_scalarparm(): +def test_scalarparm(): sp1 = ScalarParam("x") - sp1.value = 'hello' - sp2 = sp1.copy_and_set_value('goodbye') - assert sp1.value == 'hello' - assert sp2.value == 'goodbye' + sp1.value = "hello" + sp2 = sp1.copy_and_set_value("goodbye") + assert sp1.value == "hello" + assert sp2.value == "goodbye" + def test_stringparam(): sp = StringParam("i'm a frayed knot") @@ -90,7 +112,7 @@ def test_multiparam(): mp["foo"] = "hello" assert mp.foo == "hello" assert mp["foo"] == "hello" - assert 'bar' in mp + assert "bar" in mp for key in mp: assert isinstance(mp[key], StringParam) @@ -98,97 +120,95 @@ def test_multiparam(): for key, param in mp.items(): assert isinstance(param, StringParam) - mp.set_parameter('foo._label', 'fnord') - assert mp['foo'].label == 'fnord' + mp.set_parameter("foo._label", "fnord") + assert mp["foo"].label == "fnord" def test_scsp(): - pp = StringCharacterSetParam('x', 'hello', character_set=set('HelO')) - pp.value = 'helicopter' - assert pp.value == 'HelOe' + pp = StringCharacterSetParam("x", "hello", character_set=set("HelO")) + pp.value = "helicopter" + assert pp.value == "HelOe" def test_choiceparam(): - cp = ChoiceParam('x', value='a', choices=['a','b','c','d']) + cp = ChoiceParam("x", value="a", choices=["a", "b", "c", "d"]) cp.value = None - assert cp.value == '' + assert cp.value == "" cp.choice = 2 assert cp.choice == 2 - assert cp.value == 'c' + assert cp.value == "c" cp.choice = 5 assert cp.choice is None - assert cp.value == '' + assert cp.value == "" - cp.value = 'b' - cp.set_choices(['a','b','c']) + cp.value = "b" + cp.set_choices(["a", "b", "c"]) assert cp.choice == 1 - assert cp.value == 'b' + assert cp.value == "b" - cp.set_choices(['x','y']) + cp.set_choices(["x", "y"]) assert cp.choice == 0 - assert cp.value == 'x' + assert cp.value == "x" cp.set_choices([]) assert cp.choice is None - assert cp.value == '' + assert cp.value == "" def test_dtcp1(): - - cp = DataTypeChoiceParam('x') + cp = DataTypeChoiceParam("x") assert cp.get_selected_type() is None def test_dtcp2(): - - cp = DataTypeOrNoneChoiceParam('x') + cp = DataTypeOrNoneChoiceParam("x") assert cp.get_selected_type() is None - assert cp.cast_value('whatever') is None + assert cp.cast_value("whatever") is None assert cp.is_none() - cp.value = 'integer' + cp.value = "integer" assert cp.get_selected_type() == int assert cp.cast_value(7.3) == 7 - assert cp.cast_value('whatever') == 0 + assert cp.cast_value("whatever") == 0 assert not cp.is_none() def test_ccp1(): - - cp = ColumnChoiceParam('x', 'a') + cp = ColumnChoiceParam("x", "a") df = pd.DataFrame([]) with pytest.raises(ValueError): cp.get_column(df) def test_ccp2(): - df = pd.DataFrame([[1,2],[3,4]], columns=['a','b']) - cp = ColumnOrNoneChoiceParam('x') - cp.set_choices(['a','b']) + df = pd.DataFrame([[1, 2], [3, 4]], columns=["a", "b"]) + cp = ColumnOrNoneChoiceParam("x") + cp.set_choices(["a", "b"]) assert cp.is_none() assert cp.get_column(df) is None - cp.value = 'a' + cp.value = "a" assert cp.is_not_none() assert isinstance(cp.get_column(df), pd.Series) - df = df.set_index('a') + df = df.set_index("a") assert isinstance(cp.get_column(df), pd.Series) - df = df.reset_index().set_index(['a','b']) + df = df.reset_index().set_index(["a", "b"]) assert isinstance(cp.get_column(df), pd.Series) - df = pd.DataFrame([], columns=['x','y']) + df = pd.DataFrame([], columns=["x", "y"]) with pytest.raises(ValueError): cp.get_column(df) + def test_coindex(): - cp = ColumnOrIndexChoiceParam('x', choices=['a','b']) - df = pd.DataFrame(columns=['a','b']).set_index('a') + cp = ColumnOrIndexChoiceParam("x", choices=["a", "b"]) + df = pd.DataFrame(columns=["a", "b"]).set_index("a") assert cp.is_index() assert isinstance(cp.get_column(df), pd.Series) @@ -196,40 +216,84 @@ def test_coindex(): assert cp.is_not_index() assert isinstance(cp.get_column(df), pd.Series) + def test_columnorintegerparam(): - df = pd.DataFrame([[1,2],[3,4]], columns=['a','b']) - cp = ColumnOrIntegerParam('x') - cp.set_column_choices(['a','b']) + df = pd.DataFrame([[1, 2], [3, 4]], columns=["a", "b"]) + cp = ColumnOrIntegerParam("x") + cp.set_column_choices(["a", "b"]) assert cp.get_column_name() is None - cp.value = '7' + cp.value = "7" assert cp.choice is None assert cp.get_column_name() is None - assert cp.get_column_or_value(df, False) == '7' + assert cp.get_column_or_value(df, False) == "7" assert cp.get_column_or_value(df, True) == 7 cp.choice = 0 - assert cp.get_column_name() == 'a' + assert cp.get_column_name() == "a" assert isinstance(cp.get_column_or_value(df, False), pd.Series) - cp.set_column_choices(['c','d']) + cp.set_column_choices(["c", "d"]) assert cp.choice is None - cp.value = 'hello' + cp.value = "hello" assert cp.value == 0 + def test_columngroup(): df = pd.DataFrame([], columns=["one_two", "one_three", "two_one", "two_two", "two_three", "three_four_five"]) - cp = ColumnGroupOrNoneChoiceParam('x') + cp = ColumnGroupOrNoneChoiceParam("x") cp.set_column_choices(df.columns) assert cp.is_none() - assert 'one_*' in cp.choices - assert 'two_*' in cp.choices + assert "one_*" in cp.choices + assert "two_*" in cp.choices assert cp.get_column_prefix() is None cp.choice = 2 assert cp.is_not_none() - assert cp.get_column_prefix() == 'two_' - assert cp.get_column_suffixes(df) == ['one', 'two', 'three'] - assert cp.get_column_names(df) == ['two_one', 'two_two', 'two_three'] + assert cp.get_column_prefix() == "two_" + assert cp.get_column_suffixes(df) == ["one", "two", "three"] + assert cp.get_column_names(df) == ["two_one", "two_two", "two_three"] + + +def test_fileparam(): + fp = FileParam("x") + assert fp.get_file_hash() == "0" + + fp.value = "filename" + buf = io.BytesIO(b"hello") + + with patch("builtins.open", lambda *_, **__: buf): + h = fp.get_file_hash() + assert h == "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" + + def dummy(*_, **__): + raise IOError("x") + + with patch("builtins.open", dummy): + assert fp.get_file_hash() == "0" + + fp.value = "/foo/bar/baz" + assert fp.get_parameters("fnord", "/foo") == [("fnord", "bar/baz")] + + +def test_arrayparam_minmax(): + pp = IntegerParam("x") + ap = ArrayParam("y", param=pp, min_size=2, max_size=3) + assert len(ap) == 2 + + assert isinstance(ap.add_row(), IntegerParam) + assert len(ap) == 3 + + assert ap.add_row() is None + assert len(ap) == 3 + + ap.del_row(0) + assert len(ap) == 2 + + ap.del_row(1) + assert len(ap) == 2 + + ap.del_subparam(ap[1]) + assert len(ap) == 2