From 4b37881132508a925505507c24ef4b01fa5a2695 Mon Sep 17 00:00:00 2001 From: Andrew Schonfeld Date: Tue, 7 Feb 2023 12:53:38 -0500 Subject: [PATCH] https://github.com/man-group/dtale/issues/726: updated set_app_settings to persist updates to instance settings --- dtale/global_state.py | 18 ++++++++++++++++++ dtale/views.py | 14 ++++---------- tests/dtale/test_instance.py | 17 +++++++++++------ tests/dtale/test_views.py | 19 +++++++++++++++++++ 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/dtale/global_state.py b/dtale/global_state.py index d959867e..ca4965db 100644 --- a/dtale/global_state.py +++ b/dtale/global_state.py @@ -4,6 +4,8 @@ from six import PY3 +from dtale.utils import dict_merge + try: from collections.abc import MutableMapping except ImportError: @@ -340,6 +342,12 @@ def get_dtype_info(data_id, col): return next((c for c in dtypes or [] if c["name"] == col), None) +def update_settings(data_id, settings): + curr_settings = _default_store.get_settings(data_id) or {} + updated_settings = dict_merge(curr_settings, settings) + _default_store.set_settings(data_id, updated_settings) + + def get_app_settings(): global APP_SETTINGS return APP_SETTINGS @@ -351,6 +359,16 @@ def set_app_settings(settings): for prop, val in settings.items(): APP_SETTINGS[prop] = val + instance_updates = {} + if settings.get("hide_shutdown") is not None: + instance_updates["hide_shutdown"] = settings.get("hide_shutdown") + if settings.get("hide_header_editor") is not None: + instance_updates["hide_header_editor"] = settings.get("hide_header_editor") + + if _default_store.size() > 0 and len(instance_updates): + for data_id in _default_store.keys(): + update_settings(data_id, instance_updates) + def get_auth_settings(): global AUTH_SETTINGS diff --git a/dtale/views.py b/dtale/views.py index 68de1a81..e361467a 100644 --- a/dtale/views.py +++ b/dtale/views.py @@ -340,7 +340,7 @@ def update_settings(self, **updates): highlight_filter="highlightFilter", ) settings = {name_updates.get(k, k): v for k, v in updates.items()} - _update_settings(self._data_id, settings) + global_state.update_settings(self._data_id, settings) def get_settings(self): """Helper function for retrieving any instance-specific settings.""" @@ -1435,12 +1435,6 @@ def process_keys(): ) -def _update_settings(data_id, settings): - curr_settings = global_state.get_settings(data_id) or {} - updated_settings = dict_merge(curr_settings, settings) - global_state.set_settings(data_id, updated_settings) - - @dtale.route("/update-settings/") @exception_decorator def update_settings(data_id): @@ -1453,7 +1447,7 @@ def update_settings(data_id): :return: JSON """ - _update_settings(data_id, get_json_arg(request, "settings", {})) + global_state.update_settings(data_id, get_json_arg(request, "settings", {})) return jsonify(dict(success=True)) @@ -3879,7 +3873,7 @@ def drop_filtered_rows(data_id): global_state.set_data(data_id, data) global_state.set_dtypes(data_id, build_dtypes_state(data, [])) curr_predefined = curr_settings.get("predefinedFilters", {}) - _update_settings( + global_state.update_settings( data_id, dict( query="", @@ -3899,7 +3893,7 @@ def drop_filtered_rows(data_id): def move_filters_to_custom(data_id): curr_settings = global_state.get_settings(data_id) or {} query = build_query(data_id, curr_settings.get("query")) - _update_settings( + global_state.update_settings( data_id, { "columnFilters": {}, diff --git a/tests/dtale/test_instance.py b/tests/dtale/test_instance.py index f78fd256..c19bca93 100644 --- a/tests/dtale/test_instance.py +++ b/tests/dtale/test_instance.py @@ -208,18 +208,23 @@ def test_started_with_open_browser(): @pytest.mark.unit def test_settings_management(): from dtale.views import DtaleData + import dtale.global_state as global_state with ExitStack() as stack: + mock_default_store = stack.enter_context( + mock.patch("dtale.global_state._default_store", mock.Mock()) + ) + mock_default_store.get_settings.return_value = {} mock_get_settings = stack.enter_context( mock.patch("dtale.global_state.get_settings") ) - mock_set_settings = stack.enter_context( - mock.patch("dtale.global_state.set_settings") - ) + instance = DtaleData(9999, "user/root/proxy/9999") instance.update_settings(range_highlights={}) - mock_get_settings.assert_called_once_with(9999) - mock_set_settings.assert_called_once_with(9999, dict(rangeHighlight={})) - mock_get_settings.reset_mock() + mock_default_store.get_settings.assert_called_once_with(9999) + mock_default_store.set_settings.assert_called_once_with( + 9999, dict(rangeHighlight={}) + ) + mock_default_store.reset_mock() instance.get_settings() mock_get_settings.assert_called_once_with(9999) diff --git a/tests/dtale/test_views.py b/tests/dtale/test_views.py index a769baa6..cb58de79 100644 --- a/tests/dtale/test_views.py +++ b/tests/dtale/test_views.py @@ -86,6 +86,25 @@ def test_startup(unittest): "should lock index columns", ) + global_state.set_app_settings(dict(hide_header_editor=False)) + unittest.assertEqual( + global_state.get_settings(instance._data_id), + dict( + allow_cell_edits=True, + columnFormats={}, + hide_shutdown=True, + hide_header_editor=False, + locked=["date", "security_id"], + precision=2, + sortInfo=[("security_id", "ASC")], + rangeHighlight=None, + backgroundMode=None, + verticalHeaders=False, + highlightFilter=False, + ), + "should lock index columns", + ) + test_data = test_data.reset_index() with pytest.raises(DuplicateDataError): views.startup(URL, data=test_data, ignore_duplicate=False)