Skip to content

Commit

Permalink
Merge branch '0.8-dev' into issue_2446
Browse files Browse the repository at this point in the history
  • Loading branch information
ptsavol committed Jan 16, 2024
2 parents f061d51 + 6dcfd4f commit f243c85
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 118 deletions.
39 changes: 25 additions & 14 deletions spinetoolbox/spine_db_editor/mvcmodels/compound_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################

"""
Compound models.
These models concatenate several 'single' models and one 'empty' model.
"""
""" Compound models. These models concatenate several 'single' models and one 'empty' model. """
from PySide6.QtCore import Qt, Slot, QTimer, QModelIndex
from PySide6.QtGui import QFont
from spinedb_api.parameter_value import join_value_and_type
Expand All @@ -32,7 +28,7 @@ def __init__(self, parent, db_mngr, *db_maps):
Args:
parent (SpineDBEditor): the parent object
db_mngr (SpineDBManager): the database manager
*db_maps (DiffDatabaseMapping): the database maps included in the model
*db_maps (DatabaseMapping): the database maps included in the model
"""
super().__init__(parent=parent, header=self._make_header())
self._parent = parent
Expand Down Expand Up @@ -272,7 +268,7 @@ def _models_with_db_map(self, db_map):
"""Returns a collection of single models with given db_map.
Args:
db_map (DiffDatabaseMapping)
db_map (DatabaseMapping)
Returns:
list
Expand Down Expand Up @@ -303,7 +299,7 @@ def handle_items_added(self, db_map_data):
Also notifies the empty model so it can remove rows that are already in.
Args:
db_map_data (dict): list of added dict-items keyed by DiffDatabaseMapping
db_map_data (dict): list of added dict-items keyed by DatabaseMapping
"""
for db_map, items in db_map_data.items():
db_map_single_models = [m for m in self.single_models if m.db_map is db_map]
Expand Down Expand Up @@ -340,7 +336,7 @@ def _add_items(self, db_map, entity_class_id, ids, committed):
"""Creates new single model and resets it with the given parameter ids.
Args:
db_map (DiffDatabaseMapping): database map
db_map (DatabaseMapping): database map
entity_class_id (int): parameter's entity class id
ids (list of int): parameter ids
committed (bool): True if the ids have been committed, False otherwise
Expand All @@ -362,7 +358,7 @@ def handle_items_updated(self, db_map_data):
Emits dataChanged so the parameter_name column is refreshed.
Args:
db_map_data (dict): list of updated dict-items keyed by DiffDatabaseMapping
db_map_data (dict): list of updated dict-items keyed by DatabaseMapping
"""
self.dataChanged.emit(
self.index(0, 0), self.index(self.rowCount() - 1, self.columnCount() - 1), [Qt.ItemDataRole.DisplayRole]
Expand All @@ -373,18 +369,33 @@ def handle_items_removed(self, db_map_data):
Removes the affected rows from the corresponding single models.
Args:
db_map_data (dict): list of removed dict-items keyed by DiffDatabaseMapping
db_map_data (dict): list of removed dict-items keyed by DatabaseMapping
"""
self.layoutAboutToBeChanged.emit()
for db_map, items in db_map_data.items():
items_per_class = self._items_per_class(items)
for model in self._models_with_db_map(db_map):
removed_ids = [x["id"] for x in items_per_class.get(model.entity_class_id, {})]
emptied_single_model_indexes = []
for model_index, model in enumerate(self.single_models):
if model.db_map != db_map:
continue
removed_ids = {x["id"] for x in items_per_class.get(model.entity_class_id, {})}
if not removed_ids:
continue
removed_rows = [row for row in range(model.rowCount()) if model._main_data[row] in removed_ids]
removed_rows = []
for row in range(model.rowCount()):
id_ = model._main_data[row]
if id_ in removed_ids:
removed_rows.append(row)
removed_ids.remove(id_)
if not removed_ids:
break
for row, count in sorted(rows_to_row_count_tuples(removed_rows), reverse=True):
del model._main_data[row : row + count]
if model.rowCount() == 0:
emptied_single_model_indexes.append(model_index)
for model_index in reversed(emptied_single_model_indexes):
model = self.sub_models.pop(model_index)
model.deleteLater()
self._do_refresh()
self.layoutChanged.emit()

Expand Down
140 changes: 36 additions & 104 deletions tests/spine_db_editor/mvcmodels/test_compound_parameter_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################

"""
Unit tests for the models in ``compound_parameter_models`` module.
"""
""" Unit tests for the models in ``compound_parameter_models`` module. """
import unittest
from unittest.mock import MagicMock, patch
from PySide6.QtWidgets import QApplication

from spinedb_api import to_database
from spinetoolbox.spine_db_editor.mvcmodels.compound_models import (
CompoundParameterDefinitionModel,
CompoundParameterValueModel,
Expand All @@ -23,8 +22,8 @@
from tests.mock_helpers import TestSpineDBManager, fetch_model


class TestCompoundObjectParameterDefinitionModel(unittest.TestCase):
db_codename = "compound_object_parameter_definition_model_test_db"
class TestCompoundParameterDefinitionModel(unittest.TestCase):
db_codename = "compound_parameter_definition_model_test_db"

@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -76,49 +75,7 @@ def test_data_for_single_parameter_definition(self):
expected = ["oc", "p", None, "None", None, self.db_codename]
self.assertEqual(row, expected)


class TestCompoundRelationshipParameterDefinitionModel(unittest.TestCase):
@classmethod
def setUpClass(cls):
if not QApplication.instance():
QApplication()

codename = "compound_relationships_parameter_definition_model_test_db"

def setUp(self):
app_settings = MagicMock()
logger = MagicMock()
self._db_mngr = TestSpineDBManager(app_settings, None)
self._db_map = self._db_mngr.get_db_map("sqlite://", logger, codename=self.codename, create=True)
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui"):
self._db_editor = SpineDBEditor(self._db_mngr, {"sqlite://": self.codename})

def tearDown(self):
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state"), patch(
"spinetoolbox.spine_db_editor.widgets.spine_db_editor.QMessageBox"
):
self._db_editor.close()
self._db_mngr.close_all_sessions()
while not self._db_map.closed:
QApplication.processEvents()
self._db_mngr.clean_up()
self._db_editor.deleteLater()

def test_horizontal_header(self):
model = CompoundParameterDefinitionModel(self._db_editor, self._db_mngr, self._db_map)
model.init_model()
expected_header = [
"entity_class_name",
"parameter_name",
"value_list_name",
"default_value",
"description",
"database",
]
header = [model.headerData(i) for i in range(model.columnCount())]
self.assertEqual(header, expected_header)

def test_data_for_single_parameter_definition(self):
def test_data_for_single_parameter_definition_in_multidimensional_entity_class(self):
model = CompoundParameterDefinitionModel(self._db_editor, self._db_mngr, self._db_map)
model.init_model()
fetch_model(model)
Expand All @@ -129,12 +86,28 @@ def test_data_for_single_parameter_definition(self):
self.assertEqual(model.rowCount(), 2)
self.assertEqual(model.columnCount(), 6)
row = [model.index(0, column).data() for column in range(model.columnCount())]
expected = ["rc", "p", None, "None", None, self.codename]
expected = ["rc", "p", None, "None", None, self.db_codename]
self.assertEqual(row, expected)

def test_model_updates_when_entity_class_is_removed(self):
self._db_map.add_entity_class_item(name="oc1")
self._db_map.add_parameter_definition_item(entity_class_name="oc1", name="x")
entity_class_2, error = self._db_map.add_entity_class_item(name="oc2")
self.assertIsNone(error)
self._db_map.add_parameter_definition_item(entity_class_name="oc2", name="x")
self._db_map.add_entity_class_item(name="rc", dimension_name_list=("oc1", "oc2"))
self._db_map.add_parameter_definition_item(entity_class_name="rc", name="x")
model = CompoundParameterDefinitionModel(self._db_editor, self._db_mngr, self._db_map)
model.init_model()
fetch_model(model)
model.set_filter_class_ids({self._db_map: {entity_class_2["id"]}})
self.assertEqual(model.rowCount(), 4)
self._db_mngr.remove_items({self._db_map: {"entity_class": [entity_class_2["id"]]}})
self.assertEqual(model.rowCount(), 1)

class TestCompoundObjectParameterValueModel(unittest.TestCase):
codename = "compound_object_parameter_value_model_test_db"

class TestCompoundParameterValueModel(unittest.TestCase):
db_codename = "compound_parameter_value_model_test_db"

@classmethod
def setUpClass(cls):
Expand All @@ -145,10 +118,10 @@ def setUp(self):
app_settings = MagicMock()
logger = MagicMock()
self._db_mngr = TestSpineDBManager(app_settings, None)
self._db_map = self._db_mngr.get_db_map("sqlite://", logger, codename=self.codename, create=True)
self._db_map = self._db_mngr.get_db_map("sqlite://", logger, codename=self.db_codename, create=True)
self._db_map.fetch_all()
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui"):
self._db_editor = SpineDBEditor(self._db_mngr, {"sqlite://": self.codename})
self._db_editor = SpineDBEditor(self._db_mngr, {"sqlite://": self.db_codename})

def tearDown(self):
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state"), patch(
Expand Down Expand Up @@ -182,13 +155,14 @@ def test_data_for_single_parameter(self):
self._db_mngr.add_entity_classes({self._db_map: [{"name": "oc", "id": 1}]})
self._db_mngr.add_parameter_definitions({self._db_map: [{"name": "p", "entity_class_id": 1, "id": 1}]})
self._db_mngr.add_entities({self._db_map: [{"name": "o", "class_id": 1, "id": 1}]})
value, value_type = to_database(23.0)
self._db_mngr.add_parameter_values(
{
self._db_map: [
{
"parameter_definition_id": 1,
"value": b"23.0",
"type": None,
"value": value,
"type": value_type,
"entity_id": 1,
"entity_class_id": 1,
"alternative_id": 1,
Expand All @@ -200,53 +174,10 @@ def test_data_for_single_parameter(self):
self.assertEqual(model.rowCount(), 2)
self.assertEqual(model.columnCount(), 6)
row = [model.index(0, column).data() for column in range(model.columnCount())]
expected = ["oc", "o", "p", "Base", "23.0", self.codename]
expected = ["oc", "o", "p", "Base", "23.0", self.db_codename]
self.assertEqual(row, expected)


class TestCompoundRelationshipParameterValueModel(unittest.TestCase):
codename = "compound_relationship_parameter_value_model_test_db"

@classmethod
def setUpClass(cls):
if not QApplication.instance():
QApplication()

def setUp(self):
app_settings = MagicMock()
logger = MagicMock()
self._db_mngr = TestSpineDBManager(app_settings, None)
self._db_map = self._db_mngr.get_db_map("sqlite://", logger, codename=self.codename, create=True)
self._db_map.fetch_all()
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.restore_ui"):
self._db_editor = SpineDBEditor(self._db_mngr, {"sqlite://": self.codename})

def tearDown(self):
with patch("spinetoolbox.spine_db_editor.widgets.spine_db_editor.SpineDBEditor.save_window_state"), patch(
"spinetoolbox.spine_db_editor.widgets.spine_db_editor.QMessageBox"
):
self._db_editor.close()
self._db_mngr.close_all_sessions()
while not self._db_map.closed:
QApplication.processEvents()
self._db_mngr.clean_up()
self._db_editor.deleteLater()

def test_horizontal_header(self):
model = CompoundParameterValueModel(self._db_editor, self._db_mngr, self._db_map)
model.init_model()
expected_header = [
"entity_class_name",
"entity_byname",
"parameter_name",
"alternative_name",
"value",
"database",
]
header = [model.headerData(i) for i in range(model.columnCount())]
self.assertEqual(header, expected_header)

def test_data_for_single_parameter(self):
def test_data_for_single_parameter_in_multidimensional_entity(self):
model = CompoundParameterValueModel(self._db_editor, self._db_mngr, self._db_map)
model.init_model()
fetch_model(model)
Expand All @@ -255,13 +186,14 @@ def test_data_for_single_parameter(self):
self._db_mngr.add_entity_classes({self._db_map: [{"name": "rc", "dimension_id_list": [1], "id": 2}]})
self._db_mngr.add_parameter_definitions({self._db_map: [{"name": "p", "entity_class_id": 2, "id": 1}]})
self._db_mngr.add_entities({self._db_map: [{"name": "r", "class_id": 2, "element_id_list": [1], "id": 2}]})
value, value_type = to_database(23.0)
self._db_mngr.add_parameter_values(
{
self._db_map: [
{
"parameter_definition_id": 1,
"value": b"23.0",
"type": None,
"value": value,
"type": value_type,
"entity_id": 2,
"entity_class_id": 2,
"alternative_id": 1,
Expand All @@ -273,7 +205,7 @@ def test_data_for_single_parameter(self):
self.assertEqual(model.rowCount(), 2)
self.assertEqual(model.columnCount(), 6)
row = [model.index(0, column).data() for column in range(model.columnCount())]
expected = ["rc", "o", "p", "Base", "23.0", self.codename]
expected = ["rc", "o", "p", "Base", "23.0", self.db_codename]
self.assertEqual(row, expected)


Expand Down

0 comments on commit f243c85

Please sign in to comment.