diff --git a/ixmp4/core/optimization/indexset.py b/ixmp4/core/optimization/indexset.py index 163e82ee..9e768a7a 100644 --- a/ixmp4/core/optimization/indexset.py +++ b/ixmp4/core/optimization/indexset.py @@ -94,7 +94,9 @@ def get(self, name: str) -> IndexSet: return IndexSet(_backend=self.backend, _model=indexset) def list(self, name: str | None = None) -> list[IndexSet]: - indexsets = self.backend.optimization.indexsets.list(name=name) + indexsets = self.backend.optimization.indexsets.list( + run_id=self._run.id, name=name + ) return [ IndexSet( _backend=self.backend, @@ -104,4 +106,6 @@ def list(self, name: str | None = None) -> list[IndexSet]: ] def tabulate(self, name: str | None = None) -> pd.DataFrame: - return self.backend.optimization.indexsets.tabulate(name=name) + return self.backend.optimization.indexsets.tabulate( + run_id=self._run.id, name=name + ) diff --git a/ixmp4/core/optimization/scalar.py b/ixmp4/core/optimization/scalar.py index 6c8b36d7..b4262d80 100644 --- a/ixmp4/core/optimization/scalar.py +++ b/ixmp4/core/optimization/scalar.py @@ -137,4 +137,6 @@ def list(self, name: str | None = None) -> Iterable[Scalar]: ] def tabulate(self, name: str | None = None) -> pd.DataFrame: - return self.backend.optimization.scalars.tabulate(name=name) + return self.backend.optimization.scalars.tabulate( + run_id=self._run.id, name=name + ) diff --git a/ixmp4/core/optimization/table.py b/ixmp4/core/optimization/table.py index 065d6793..dad74e6d 100644 --- a/ixmp4/core/optimization/table.py +++ b/ixmp4/core/optimization/table.py @@ -116,4 +116,4 @@ def list(self, name: str | None = None) -> Iterable[Table]: ] def tabulate(self, name: str | None = None) -> pd.DataFrame: - return self.backend.optimization.tables.tabulate(name=name) + return self.backend.optimization.tables.tabulate(run_id=self._run.id, name=name) diff --git a/tests/core/test_indexset.py b/tests/core/test_indexset.py index 0260f191..a887730b 100644 --- a/tests/core/test_indexset.py +++ b/tests/core/test_indexset.py @@ -2,9 +2,9 @@ import pandas.testing as pdt import pytest -from ixmp4 import IndexSet +from ixmp4.core import IndexSet, Platform -from ..utils import all_platforms +from ..utils import all_platforms, create_indexsets_for_run def df_from_list(indexsets: list[IndexSet]): @@ -36,37 +36,38 @@ def df_from_list(indexsets: list[IndexSet]): @all_platforms class TestCoreIndexSet: def test_create_indexset(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - indexset_1 = run.optimization.indexsets.create("IndexSet 1") + indexset_1 = run.optimization.indexsets.create("Indexset 1") assert indexset_1.id == 1 - assert indexset_1.name == "IndexSet 1" + assert indexset_1.name == "Indexset 1" - indexset_2 = run.optimization.indexsets.create("IndexSet 2") + indexset_2 = run.optimization.indexsets.create("Indexset 2") assert indexset_1.id != indexset_2.id with pytest.raises(IndexSet.NotUnique): - _ = run.optimization.indexsets.create("IndexSet 1") + _ = run.optimization.indexsets.create("Indexset 1") def test_get_indexset(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - _ = run.optimization.indexsets.create("IndexSet 1") - indexset = run.optimization.indexsets.get("IndexSet 1") + run.set_as_default() + create_indexsets_for_run(platform=test_mp, run_id=run.id, amount=1) + indexset = run.optimization.indexsets.get("Indexset 1") assert indexset.id == 1 - assert indexset.name == "IndexSet 1" + assert indexset.name == "Indexset 1" with pytest.raises(IndexSet.NotFound): _ = run.optimization.indexsets.get("Foo") def test_add_elements(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") test_elements = ["foo", "bar"] - indexset_1 = run.optimization.indexsets.create("IndexSet 1") + indexset_1 = run.optimization.indexsets.create("Indexset 1") indexset_1.add(test_elements) - run.optimization.indexsets.create("IndexSet 2").add(test_elements) - indexset_2 = run.optimization.indexsets.get("IndexSet 2") + run.optimization.indexsets.create("Indexset 2").add(test_elements) + indexset_2 = run.optimization.indexsets.get("Indexset 2") assert indexset_1.elements == indexset_2.elements with pytest.raises(ValueError): @@ -76,24 +77,28 @@ def test_add_elements(self, test_mp, request): indexset_2.add(["baz", "baz"]) indexset_1.add(1) - indexset_3 = run.optimization.indexsets.get("IndexSet 1") + indexset_3 = run.optimization.indexsets.get("Indexset 1") indexset_2.add("1") - indexset_4 = run.optimization.indexsets.get("IndexSet 2") + indexset_4 = run.optimization.indexsets.get("Indexset 2") assert indexset_3.elements != indexset_4.elements assert len(indexset_3.elements) == len(indexset_4.elements) test_elements_2 = ["One", 2, 3.141] - indexset_5 = run.optimization.indexsets.create("IndexSet 5") + indexset_5 = run.optimization.indexsets.create("Indexset 5") indexset_5.add(test_elements_2) assert indexset_5.elements == test_elements_2 def test_list_indexsets(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, list() lists only `default` version runs: - run.set_as_default() - indexset_1 = run.optimization.indexsets.create("Indexset 1") - indexset_2 = run.optimization.indexsets.create("Indexset 2") + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id + ) + # Create indexset in another run to test listing indexsets for specific run + test_mp.runs.create("Model", "Scenario").optimization.indexsets.create( + "Indexset 1" + ) + expected_ids = [indexset_1.id, indexset_2.id] list_ids = [indexset.id for indexset in run.optimization.indexsets.list()] assert not (set(expected_ids) ^ set(list_ids)) @@ -107,12 +112,18 @@ def test_list_indexsets(self, test_mp, request): assert not (set(expected_id) ^ set(list_id)) def test_tabulate_indexsets(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, tabulate() lists only `default` version runs: - run.set_as_default() - indexset_1 = run.optimization.indexsets.create("Indexset 1") - indexset_2 = run.optimization.indexsets.create("Indexset 2") + # Convert to core.indexset; util uses db.indexset for efficiency + indexset_1, indexset_2 = tuple( + IndexSet(_backend=test_mp.backend, _model=model) + for model in create_indexsets_for_run(platform=test_mp, run_id=run.id) + ) + # Create indexset in another run to test tabulating indexsets for specific run + test_mp.runs.create("Model", "Scenario").optimization.indexsets.create( + "Indexset 1" + ) + expected = df_from_list(indexsets=[indexset_1, indexset_2]) result = run.optimization.indexsets.tabulate() # utils.assert_unordered_equality doesn't like lists, so make sure the order in @@ -124,10 +135,15 @@ def test_tabulate_indexsets(self, test_mp, request): pdt.assert_frame_equal(expected, result) def test_indexset_docs(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - indexset_1 = run.optimization.indexsets.create("IndexSet 1") - docs = "Documentation of IndexSet 1" + (indexset_1,) = tuple( + IndexSet(_backend=test_mp.backend, _model=model) + for model in create_indexsets_for_run( + platform=test_mp, run_id=run.id, amount=1 + ) + ) + docs = "Documentation of Indexset 1" indexset_1.docs = docs assert indexset_1.docs == docs diff --git a/tests/core/test_scalar.py b/tests/core/test_scalar.py index a964ccf5..58cee876 100644 --- a/tests/core/test_scalar.py +++ b/tests/core/test_scalar.py @@ -1,7 +1,7 @@ import pandas as pd import pytest -from ixmp4 import Scalar +from ixmp4.core import Platform, Scalar from ..utils import all_platforms, assert_unordered_equality @@ -35,7 +35,7 @@ def df_from_list(scalars: list[Scalar]): @all_platforms class TestCoreScalar: def test_create_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") unit = test_mp.units.create("Test Unit") scalar_1 = run.optimization.scalars.create( @@ -63,7 +63,7 @@ def test_create_scalar(self, test_mp, request): assert scalar_3.unit.name == "" def test_get_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") unit = test_mp.units.create("Test Unit") scalar = run.optimization.scalars.create("Scalar", value=10, unit=unit.name) @@ -77,7 +77,7 @@ def test_get_scalar(self, test_mp, request): _ = run.optimization.scalars.get("Foo") def test_update_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") unit = test_mp.units.create("Test Unit") unit2 = test_mp.units.create("Test Unit 2") @@ -100,15 +100,18 @@ def test_update_scalar(self, test_mp, request): assert scalar.unit.id == result.unit.id == 1 def test_list_scalars(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, list() lists only `default` version runs: - run.set_as_default() unit = test_mp.units.create("Test Unit") scalar_1 = run.optimization.scalars.create( "Scalar 1", value=1, unit="Test Unit" ) scalar_2 = run.optimization.scalars.create("Scalar 2", value=2, unit=unit.name) + # Create scalar in another run to test listing scalars for specific run + test_mp.runs.create("Model", "Scenario").optimization.scalars.create( + "Scalar 1", value=1, unit=unit + ) + expected_ids = [scalar_1.id, scalar_2.id] list_ids = [scalar.id for scalar in run.optimization.scalars.list()] assert not (set(expected_ids) ^ set(list_ids)) @@ -121,13 +124,16 @@ def test_list_scalars(self, test_mp, request): assert not (set(expected_id) ^ set(list_id)) def test_tabulate_scalars(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, tabulate() lists only `default` version runs: - run.set_as_default() unit = test_mp.units.create("Test Unit") scalar_1 = run.optimization.scalars.create("Scalar 1", value=1, unit=unit.name) scalar_2 = run.optimization.scalars.create("Scalar 2", value=2, unit=unit.name) + # Create scalar in another run to test tabulating scalars for specific run + test_mp.runs.create("Model", "Scenario").optimization.scalars.create( + "Scalar 1", value=1, unit=unit + ) + expected = df_from_list(scalars=[scalar_1, scalar_2]) result = run.optimization.scalars.tabulate() assert_unordered_equality(expected, result, check_dtype=False) @@ -137,7 +143,7 @@ def test_tabulate_scalars(self, test_mp, request): assert_unordered_equality(expected, result, check_dtype=False) def test_scalar_docs(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") unit = test_mp.units.create("Test Unit") scalar = run.optimization.scalars.create("Scalar 1", value=4, unit=unit.name) diff --git a/tests/core/test_table.py b/tests/core/test_table.py index ac923f4d..6d9b54f7 100644 --- a/tests/core/test_table.py +++ b/tests/core/test_table.py @@ -1,9 +1,9 @@ import pandas as pd import pytest -from ixmp4 import Platform, Table +from ixmp4.core import IndexSet, Platform, Table -from ..utils import all_platforms +from ..utils import all_platforms, create_indexsets_for_run def df_from_list(tables: list[Table]): @@ -39,7 +39,10 @@ def test_create_table(self, test_mp, request): run = test_mp.runs.create("Model", "Scenario") # Test normal creation - indexset = run.optimization.indexsets.create("Indexset") + indexset, indexset_2 = tuple( + IndexSet(_backend=test_mp.backend, _model=model) + for model in create_indexsets_for_run(platform=test_mp, run_id=run.id) + ) table = run.optimization.tables.create( "Table 1", constrained_to_indexsets=[indexset.name], @@ -48,20 +51,20 @@ def test_create_table(self, test_mp, request): assert table.id == 1 assert table.name == "Table 1" assert table.data == {} - assert table.columns[0].name == "Indexset" + assert table.columns[0].name == indexset.name assert table.constrained_to_indexsets == [indexset.name] # Test duplicate name raises with pytest.raises(Table.NotUnique): _ = run.optimization.tables.create( - "Table 1", constrained_to_indexsets=["Indexset"] + "Table 1", constrained_to_indexsets=[indexset.name] ) # Test mismatch in constrained_to_indexsets and column_names raises with pytest.raises(ValueError, match="not equal in length"): _ = run.optimization.tables.create( name="Table 2", - constrained_to_indexsets=["Indexset"], + constrained_to_indexsets=[indexset.name], column_names=["Dimension 1", "Dimension 2"], ) @@ -82,11 +85,10 @@ def test_create_table(self, test_mp, request): ) # Test column.dtype is registered correctly - indexset_2 = run.optimization.indexsets.create("Indexset 2") indexset_2.add(elements=2024) table_3 = run.optimization.tables.create( "Table 5", - constrained_to_indexsets=["Indexset", indexset_2.name], + constrained_to_indexsets=[indexset.name, indexset_2.name], ) # If indexset doesn't have elements, a generic dtype is registered assert table_3.columns[0].dtype == "object" @@ -95,9 +97,11 @@ def test_create_table(self, test_mp, request): def test_get_table(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - indexset = run.optimization.indexsets.create(name="Indexset") + (indexset,) = create_indexsets_for_run( + platform=test_mp, run_id=run.id, amount=1 + ) _ = run.optimization.tables.create( - name="Table", constrained_to_indexsets=["Indexset"] + name="Table", constrained_to_indexsets=[indexset.name] ) table = run.optimization.tables.get("Table") assert table.run_id == run.id @@ -113,16 +117,18 @@ def test_get_table(self, test_mp, request): def test_table_add_data(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - indexset = run.optimization.indexsets.create("Indexset") + indexset, indexset_2 = tuple( + IndexSet(_backend=test_mp.backend, _model=model) + for model in create_indexsets_for_run(platform=test_mp, run_id=run.id) + ) indexset.add(elements=["foo", "bar", ""]) - indexset_2 = run.optimization.indexsets.create("Indexset 2") indexset_2.add([1, 2, 3]) # pandas can only convert dicts to dataframes if the values are lists # or if index is given. But maybe using read_json instead of from_dict # can remedy this. Or maybe we want to catch the resulting # "ValueError: If using all scalar values, you must pass an index" and # reraise a custom informative error? - test_data_1 = {"Indexset": ["foo"], "Indexset 2": [1]} + test_data_1 = {indexset.name: ["foo"], indexset_2.name: [1]} table = run.optimization.tables.create( "Table", constrained_to_indexsets=[indexset.name, indexset_2.name], @@ -137,22 +143,22 @@ def test_table_add_data(self, test_mp, request): with pytest.raises(ValueError, match="missing values"): table_2.add( - pd.DataFrame({"Indexset": [None], "Indexset 2": [2]}), + pd.DataFrame({indexset.name: [None], indexset_2.name: [2]}), # empty string is allowed for now, but None or NaN raise ) with pytest.raises(ValueError, match="contains duplicate rows"): table_2.add( - data={"Indexset": ["foo", "foo"], "Indexset 2": [2, 2]}, + data={indexset.name: ["foo", "foo"], indexset_2.name: [2, 2]}, ) # Test raising on unrecognised data.values() with pytest.raises(ValueError, match="contains values that are not allowed"): table_2.add( - data={"Indexset": ["foo"], "Indexset 2": [0]}, + data={indexset.name: ["foo"], indexset_2.name: [0]}, ) - test_data_2 = {"Indexset": [""], "Indexset 2": [3]} + test_data_2 = {indexset.name: [""], indexset_2.name: [3]} table_2.add(data=test_data_2) assert table_2.data == test_data_2 @@ -195,12 +201,15 @@ def test_table_add_data(self, test_mp, request): # This doesn't seem to test a distinct case compared to the above with pytest.raises(ValueError, match="Trying to add data to unknown Columns!"): table_4.add( - data={"Column 1": ["bar"], "Column 2": [3], "Indexset": ["foo"]}, + data={"Column 1": ["bar"], "Column 2": [3], indexset.name: ["foo"]}, ) # Test various data types - test_data_5 = {"Indexset": ["foo", "foo", "bar"], "Indexset 3": [1, "2", 3.14]} indexset_3 = run.optimization.indexsets.create(name="Indexset 3") + test_data_5 = { + indexset.name: ["foo", "foo", "bar"], + indexset_3.name: [1, "2", 3.14], + } indexset_3.add(elements=[1, "2", 3.14]) table_5 = run.optimization.tables.create( name="Table 5", @@ -216,16 +225,20 @@ def test_table_add_data(self, test_mp, request): def test_list_tables(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, list() lists scalars for `default` version runs: - run.set_as_default() - _ = run.optimization.indexsets.create("Indexset") - _ = run.optimization.indexsets.create("Indexset 2") + create_indexsets_for_run(platform=test_mp, run_id=run.id) table = run.optimization.tables.create( - "Table", constrained_to_indexsets=["Indexset"] + "Table", constrained_to_indexsets=["Indexset 1"] ) table_2 = run.optimization.tables.create( "Table 2", constrained_to_indexsets=["Indexset 2"] ) + # Create table in another run to test listing tables for specific run + run_2 = test_mp.runs.create("Model", "Scenario") + indexset_3 = run_2.optimization.indexsets.create("Indexset 3") + run_2.optimization.tables.create( + "Table 1", constrained_to_indexsets=[indexset_3.name] + ) + expected_ids = [table.id, table_2.id] list_ids = [table.id for table in run.optimization.tables.list()] assert not (set(expected_ids) ^ set(list_ids)) @@ -238,18 +251,25 @@ def test_list_tables(self, test_mp, request): def test_tabulate_table(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - # Per default, tabulate() lists scalars for `default` version runs: - run.set_as_default() - indexset = run.optimization.indexsets.create("Indexset") - indexset_2 = run.optimization.indexsets.create("Indexset 2") + indexset, indexset_2 = tuple( + IndexSet(_backend=test_mp.backend, _model=model) + for model in create_indexsets_for_run(platform=test_mp, run_id=run.id) + ) table = run.optimization.tables.create( name="Table", - constrained_to_indexsets=["Indexset", "Indexset 2"], + constrained_to_indexsets=[indexset.name, indexset_2.name], ) table_2 = run.optimization.tables.create( name="Table 2", - constrained_to_indexsets=["Indexset", "Indexset 2"], + constrained_to_indexsets=[indexset.name, indexset_2.name], ) + # Create table in another run to test listing tables for specific run + run_2 = test_mp.runs.create("Model", "Scenario") + indexset_3 = run_2.optimization.indexsets.create("Indexset 3") + run_2.optimization.tables.create( + "Table 1", constrained_to_indexsets=[indexset_3.name] + ) + pd.testing.assert_frame_equal( df_from_list([table_2]), run.optimization.tables.tabulate(name="Table 2"), @@ -257,9 +277,9 @@ def test_tabulate_table(self, test_mp, request): indexset.add(["foo", "bar"]) indexset_2.add([1, 2, 3]) - test_data_1 = {"Indexset": ["foo"], "Indexset 2": [1]} + test_data_1 = {indexset.name: ["foo"], indexset_2.name: [1]} table.add(test_data_1) - test_data_2 = {"Indexset 2": [2, 3], "Indexset": ["foo", "bar"]} + test_data_2 = {indexset_2.name: [2, 3], indexset.name: ["foo", "bar"]} table_2.add(test_data_2) pd.testing.assert_frame_equal( df_from_list([table, table_2]), @@ -269,7 +289,9 @@ def test_tabulate_table(self, test_mp, request): def test_table_docs(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.runs.create("Model", "Scenario") - indexset = run.optimization.indexsets.create("Indexset") + (indexset,) = create_indexsets_for_run( + platform=test_mp, run_id=run.id, amount=1 + ) table_1 = run.optimization.tables.create( "Table 1", constrained_to_indexsets=[indexset.name] ) diff --git a/tests/data/test_optimization_indexset.py b/tests/data/test_optimization_indexset.py index 5c99a2d9..78bc2441 100644 --- a/tests/data/test_optimization_indexset.py +++ b/tests/data/test_optimization_indexset.py @@ -2,9 +2,10 @@ import pandas.testing as pdt import pytest -from ixmp4 import IndexSet +from ixmp4.core import Platform +from ixmp4.data.abstract import IndexSet -from ..utils import all_platforms +from ..utils import all_platforms, create_indexsets_for_run def df_from_list(indexsets: list): @@ -36,7 +37,7 @@ def df_from_list(indexsets: list): @all_platforms class TestDataOptimizationIndexSet: def test_create_indexset(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") indexset_1 = test_mp.backend.optimization.indexsets.create( run_id=run.id, name="Indexset" @@ -51,17 +52,15 @@ def test_create_indexset(self, test_mp, request): ) def test_get_indexset(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - _ = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset" - ) + create_indexsets_for_run(platform=test_mp, run_id=run.id, amount=1) indexset = test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="Indexset" + run_id=run.id, name="Indexset 1" ) assert indexset.id == 1 assert indexset.run__id == 1 - assert indexset.name == "Indexset" + assert indexset.name == "Indexset 1" with pytest.raises(IndexSet.NotFound): _ = test_mp.backend.optimization.indexsets.get( @@ -69,31 +68,30 @@ def test_get_indexset(self, test_mp, request): ) def test_list_indexsets(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, list() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) - indexset_1 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 1" - ) - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id ) assert [indexset_1] == test_mp.backend.optimization.indexsets.list( - name="Indexset 1" + name=indexset_1.name ) assert [indexset_1, indexset_2] == test_mp.backend.optimization.indexsets.list() + # Test only indexsets belonging to this Run are listed when run_id is provided + run_2 = test_mp.backend.runs.create("Model", "Scenario") + indexset_3, indexset_4 = create_indexsets_for_run( + platform=test_mp, run_id=run_2.id, offset=2 + ) + assert [indexset_3, indexset_4] == test_mp.backend.optimization.indexsets.list( + run_id=run_2.id + ) + def test_tabulate_indexsets(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, tabulate() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) - indexset_1 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 1" - ) - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_1.id, elements="foo" @@ -118,23 +116,31 @@ def test_tabulate_indexsets(self, test_mp, request): expected, test_mp.backend.optimization.indexsets.tabulate(name="Indexset 1") ) + # Test only indexsets belonging to this Run are tabulated if run_id is provided + run_2 = test_mp.backend.runs.create("Model", "Scenario") + indexset_3, indexset_4 = create_indexsets_for_run( + platform=test_mp, run_id=run_2.id, offset=2 + ) + expected = df_from_list(indexsets=[indexset_3, indexset_4]) + pdt.assert_frame_equal( + expected, test_mp.backend.optimization.indexsets.tabulate(run_id=run_2.id) + ) + def test_add_elements(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore test_elements = ["foo", "bar"] run = test_mp.backend.runs.create("Model", "Scenario") - indexset_1 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="IndexSet 1" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id ) + test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_1.id, elements=test_elements ) indexset_1 = test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="IndexSet 1" + run_id=run.id, name=indexset_1.name ) - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="IndexSet 2" - ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_2.id, elements=test_elements ) @@ -142,7 +148,7 @@ def test_add_elements(self, test_mp, request): assert ( indexset_1.elements == test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="IndexSet 2" + run_id=run.id, name=indexset_2.name ).elements ) @@ -160,25 +166,25 @@ def test_add_elements(self, test_mp, request): indexset_id=indexset_1.id, elements=1 ) indexset_3 = test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="IndexSet 1" + run_id=run.id, name=indexset_1.name ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_2.id, elements="1" ) indexset_4 = test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="IndexSet 2" + run_id=run.id, name=indexset_2.name ) assert indexset_3.elements != indexset_4.elements assert len(indexset_3.elements) == len(indexset_4.elements) test_elements_2 = [1, "2", 3.14] indexset_5 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="IndexSet 5" + run_id=run.id, name="Indexset 5" ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_5.id, elements=test_elements_2 ) indexset_5 = test_mp.backend.optimization.indexsets.get( - run_id=run.id, name="IndexSet 5" + run_id=run.id, name="Indexset 5" ) assert indexset_5.elements == test_elements_2 diff --git a/tests/data/test_optimization_scalar.py b/tests/data/test_optimization_scalar.py index 1f9491f1..bb8c827a 100644 --- a/tests/data/test_optimization_scalar.py +++ b/tests/data/test_optimization_scalar.py @@ -2,7 +2,8 @@ import pandas.testing as pdt import pytest -from ixmp4 import Scalar +from ixmp4.core import Platform +from ixmp4.data.abstract import Scalar from ..utils import all_platforms @@ -36,7 +37,7 @@ def df_from_list(scalars: list): @all_platforms class TestDataOptimizationScalar: def test_create_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") unit = test_mp.backend.units.create("Unit") unit2 = test_mp.backend.units.create("Unit 2") @@ -54,7 +55,7 @@ def test_create_scalar(self, test_mp, request): ) def test_get_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") unit = test_mp.backend.units.create("Unit") scalar = test_mp.backend.optimization.scalars.create( @@ -68,7 +69,7 @@ def test_get_scalar(self, test_mp, request): _ = test_mp.backend.optimization.scalars.get(run_id=run.id, name="Scalar 2") def test_update_scalar(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") unit = test_mp.backend.units.create("Unit") unit2 = test_mp.backend.units.create("Unit 2") @@ -87,10 +88,8 @@ def test_update_scalar(self, test_mp, request): assert ret.value == 20 def test_list_scalars(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, list() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) unit = test_mp.backend.units.create("Unit") unit2 = test_mp.backend.units.create("Unit 2") scalar_1 = test_mp.backend.optimization.scalars.create( @@ -102,11 +101,21 @@ def test_list_scalars(self, test_mp, request): assert [scalar_1] == test_mp.backend.optimization.scalars.list(name="Scalar") assert [scalar_1, scalar_2] == test_mp.backend.optimization.scalars.list() + # Test listing of scalars of particular run only + run_2 = test_mp.backend.runs.create("Model", "Scenario") + scalar_3 = test_mp.backend.optimization.scalars.create( + run_id=run_2.id, name="Scalar", value=1, unit_name=unit.name + ) + scalar_4 = test_mp.backend.optimization.scalars.create( + run_id=run_2.id, name="Scalar 2", value=2, unit_name=unit2.name + ) + assert [scalar_3, scalar_4] == test_mp.backend.optimization.scalars.list( + run_id=run_2.id + ) + def test_tabulate_scalars(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, tabulate() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) unit = test_mp.backend.units.create("Unit") unit2 = test_mp.backend.units.create("Unit 2") scalar_1 = test_mp.backend.optimization.scalars.create( @@ -124,3 +133,16 @@ def test_tabulate_scalars(self, test_mp, request): pdt.assert_frame_equal( expected, test_mp.backend.optimization.scalars.tabulate(name="Scalar") ) + + # Test tabulation of scalars of particular run only + run_2 = test_mp.backend.runs.create("Model", "Scenario") + scalar_3 = test_mp.backend.optimization.scalars.create( + run_id=run_2.id, name="Scalar", value=1, unit_name=unit.name + ) + scalar_4 = test_mp.backend.optimization.scalars.create( + run_id=run_2.id, name="Scalar 2", value=2, unit_name=unit2.name + ) + expected = df_from_list(scalars=[scalar_3, scalar_4]) + pdt.assert_frame_equal( + expected, test_mp.backend.optimization.scalars.tabulate(run_id=run_2.id) + ) diff --git a/tests/data/test_optimization_table.py b/tests/data/test_optimization_table.py index d2b3c49c..fc26e2d7 100644 --- a/tests/data/test_optimization_table.py +++ b/tests/data/test_optimization_table.py @@ -1,9 +1,10 @@ import pandas as pd import pytest -from ixmp4 import Platform, Table +from ixmp4.core import Platform +from ixmp4.data.abstract import Table -from ..utils import all_platforms +from ..utils import all_platforms, create_indexsets_for_run def df_from_list(tables: list): @@ -37,23 +38,23 @@ def test_create_table(self, test_mp, request): run = test_mp.backend.runs.create("Model", "Scenario") # Test normal creation - indexset_1 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id ) table = test_mp.backend.optimization.tables.create( - run_id=run.id, name="Table", constrained_to_indexsets=["Indexset"] + run_id=run.id, name="Table", constrained_to_indexsets=[indexset_1.name] ) assert table.run__id == run.id assert table.name == "Table" assert table.data == {} # JsonDict type currently requires a dict, not None - assert table.columns[0].name == "Indexset" + assert table.columns[0].name == indexset_1.name assert table.columns[0].constrained_to_indexset == indexset_1.id # Test duplicate name raises with pytest.raises(Table.NotUnique): _ = test_mp.backend.optimization.tables.create( - run_id=run.id, name="Table", constrained_to_indexsets=["Indexset"] + run_id=run.id, name="Table", constrained_to_indexsets=[indexset_1.name] ) # Test mismatch in constrained_to_indexsets and column_names raises @@ -61,7 +62,7 @@ def test_create_table(self, test_mp, request): _ = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table 2", - constrained_to_indexsets=["Indexset"], + constrained_to_indexsets=[indexset_1.name], column_names=["Dimension 1", "Dimension 2"], ) @@ -84,9 +85,6 @@ def test_create_table(self, test_mp, request): ) # Test column.dtype is registered correctly - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" - ) test_mp.backend.optimization.indexsets.add_elements( indexset_2.id, elements=2024 ) @@ -94,14 +92,14 @@ def test_create_table(self, test_mp, request): table_3 = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table 5", - constrained_to_indexsets=["Indexset", indexset_2.name], + constrained_to_indexsets=[indexset_1.name, indexset_2.name], ) # If indexset doesn't have elements, a generic dtype is registered assert table_3.columns[0].dtype == "object" assert table_3.columns[1].dtype == "int64" def test_get_table(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") _ = test_mp.backend.optimization.indexsets.create( run_id=run.id, name="Indexset" @@ -119,15 +117,12 @@ def test_get_table(self, test_mp, request): def test_table_add_data(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - indexset_1 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_1.id, elements=["foo", "bar", ""] ) - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" - ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_2.id, elements=[1, 2, 3] ) @@ -136,7 +131,7 @@ def test_table_add_data(self, test_mp, request): # can remedy this. Or maybe we want to catch the resulting # "ValueError: If using all scalar values, you must pass an index" and # reraise a custom informative error? - test_data_1 = {"Indexset": ["foo"], "Indexset 2": [1]} + test_data_1 = {indexset_1.name: ["foo"], indexset_2.name: [1]} table = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table", @@ -158,24 +153,24 @@ def test_table_add_data(self, test_mp, request): with pytest.raises(ValueError, match="missing values"): test_mp.backend.optimization.tables.add_data( table_id=table_2.id, - data=pd.DataFrame({"Indexset": [None], "Indexset 2": [2]}), + data=pd.DataFrame({indexset_1.name: [None], indexset_2.name: [2]}), # empty string is allowed for now (see below), but None or NaN raise ) with pytest.raises(ValueError, match="contains duplicate rows"): test_mp.backend.optimization.tables.add_data( table_id=table_2.id, - data={"Indexset": ["foo", "foo"], "Indexset 2": [2, 2]}, + data={indexset_1.name: ["foo", "foo"], indexset_2.name: [2, 2]}, ) # Test raising on unrecognised data.values() with pytest.raises(ValueError, match="contains values that are not allowed"): test_mp.backend.optimization.tables.add_data( table_id=table_2.id, - data={"Indexset": ["foo"], "Indexset 2": [0]}, + data={indexset_1.name: ["foo"], indexset_2.name: [0]}, ) - test_data_2 = {"Indexset": [""], "Indexset 2": [3]} + test_data_2 = {indexset_1.name: [""], indexset_2.name: [3]} test_mp.backend.optimization.tables.add_data( table_id=table_2.id, data=test_data_2 ) @@ -243,10 +238,13 @@ def test_table_add_data(self, test_mp, request): ) # Test various data types - test_data_5 = {"Indexset": ["foo", "foo", "bar"], "Indexset 3": [1, "2", 3.14]} indexset_3 = test_mp.backend.optimization.indexsets.create( run_id=run.id, name="Indexset 3" ) + test_data_5 = { + indexset_1.name: ["foo", "foo", "bar"], + indexset_3.name: [1, "2", 3.14], + } test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_3.id, elements=[1, "2", 3.14] ) @@ -267,18 +265,11 @@ def test_table_add_data(self, test_mp, request): assert table_5.data == test_data_5 def test_list_table(self, test_mp, request): - test_mp = request.getfixturevalue(test_mp) + test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, list() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) - _ = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset" - ) - _ = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" - ) + create_indexsets_for_run(platform=test_mp, run_id=run.id) table = test_mp.backend.optimization.tables.create( - run_id=run.id, name="Table", constrained_to_indexsets=["Indexset"] + run_id=run.id, name="Table", constrained_to_indexsets=["Indexset 1"] ) table_2 = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table 2", constrained_to_indexsets=["Indexset 2"] @@ -287,26 +278,36 @@ def test_list_table(self, test_mp, request): assert [table] == test_mp.backend.optimization.tables.list(name="Table") + # Test listing of Tables when specifying a Run + run_2 = test_mp.backend.runs.create("Model", "Scenario") + indexset_3, indexset_4 = create_indexsets_for_run( + platform=test_mp, run_id=run_2.id, offset=2 + ) + table_3 = test_mp.backend.optimization.tables.create( + run_id=run_2.id, name="Table", constrained_to_indexsets=[indexset_3.name] + ) + table_4 = test_mp.backend.optimization.tables.create( + run_id=run_2.id, name="Table 2", constrained_to_indexsets=[indexset_4.name] + ) + assert [table_3, table_4] == test_mp.backend.optimization.tables.list( + run_id=run_2.id + ) + def test_tabulate_table(self, test_mp, request): test_mp: Platform = request.getfixturevalue(test_mp) # type: ignore run = test_mp.backend.runs.create("Model", "Scenario") - # Per default, tabulate() lists scalars for `default` version runs: - test_mp.backend.runs.set_as_default_version(run.id) - indexset = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset" - ) - indexset_2 = test_mp.backend.optimization.indexsets.create( - run_id=run.id, name="Indexset 2" + indexset_1, indexset_2 = create_indexsets_for_run( + platform=test_mp, run_id=run.id, offset=2 ) table = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table", - constrained_to_indexsets=["Indexset", "Indexset 2"], + constrained_to_indexsets=[indexset_1.name, indexset_2.name], ) table_2 = test_mp.backend.optimization.tables.create( run_id=run.id, name="Table 2", - constrained_to_indexsets=["Indexset", "Indexset 2"], + constrained_to_indexsets=[indexset_1.name, indexset_2.name], ) pd.testing.assert_frame_equal( df_from_list([table_2]), @@ -314,18 +315,18 @@ def test_tabulate_table(self, test_mp, request): ) test_mp.backend.optimization.indexsets.add_elements( - indexset_id=indexset.id, elements=["foo", "bar"] + indexset_id=indexset_1.id, elements=["foo", "bar"] ) test_mp.backend.optimization.indexsets.add_elements( indexset_id=indexset_2.id, elements=[1, 2, 3] ) - test_data_1 = {"Indexset": ["foo"], "Indexset 2": [1]} + test_data_1 = {indexset_1.name: ["foo"], indexset_2.name: [1]} test_mp.backend.optimization.tables.add_data( table_id=table.id, data=test_data_1 ) table = test_mp.backend.optimization.tables.get(run_id=run.id, name="Table") - test_data_2 = {"Indexset 2": [2, 3], "Indexset": ["foo", "bar"]} + test_data_2 = {indexset_2.name: [2, 3], indexset_1.name: ["foo", "bar"]} test_mp.backend.optimization.tables.add_data( table_id=table_2.id, data=test_data_2 ) @@ -334,3 +335,19 @@ def test_tabulate_table(self, test_mp, request): df_from_list([table, table_2]), test_mp.backend.optimization.tables.tabulate(), ) + + # Test tabulation of Tables when specifying a Run + run_2 = test_mp.backend.runs.create("Model", "Scenario") + indexset_3, indexset_4 = create_indexsets_for_run( + platform=test_mp, run_id=run_2.id, offset=2 + ) + table_3 = test_mp.backend.optimization.tables.create( + run_id=run_2.id, name="Table", constrained_to_indexsets=[indexset_3.name] + ) + table_4 = test_mp.backend.optimization.tables.create( + run_id=run_2.id, name="Table 2", constrained_to_indexsets=[indexset_4.name] + ) + pd.testing.assert_frame_equal( + df_from_list([table_3, table_4]), + test_mp.backend.optimization.tables.tabulate(run_id=run_2.id), + ) diff --git a/tests/utils.py b/tests/utils.py index 1dc74f8c..79c8d826 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -3,6 +3,8 @@ import pytest from ixmp4 import DataPoint +from ixmp4.core import Platform +from ixmp4.data.abstract import IndexSet from .conftest import SKIP_PGSQL_TESTS @@ -198,3 +200,15 @@ def create_iamc_query_test_data(test_mp): run2.meta = {"run": 2, "test": "string", "bool": False} return [r1, r2, r3], units + + +def create_indexsets_for_run( + platform: Platform, run_id: int, amount: int = 2, offset: int = 1 +) -> tuple[IndexSet, ...]: + """Create `amount` indexsets called `Indexset n` for `run`.""" + return tuple( + platform.backend.optimization.indexsets.create( + run_id=run_id, name=f"Indexset {i}" + ) + for i in range(offset, offset + amount) + )