Skip to content

Commit

Permalink
Project level setting to disable execute project button (#2238)
Browse files Browse the repository at this point in the history
  • Loading branch information
soininen authored Aug 10, 2023
2 parents 79ce54c + 5aec09b commit af55312
Show file tree
Hide file tree
Showing 21 changed files with 704 additions and 205 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
## [Unreleased]

### Added
- Support for version 11 Spine Toolbox projects.
- Executable Tool Specifications can be used to run any (shell) command. This enhancement
duplicates the functionality of Gimlet project items and makes them obsolete.
- There is now an option to select if new scenarios or tools are automatically used
Expand All @@ -30,6 +31,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
- "Make Julia Kernel" and "Make Python Kernel" buttons in Settings->Tools page. Clicking them creates a new
Julia or Python kernel based on selected Julia/Python executable on the same page if the kernel does not exist.
If the kernel already exists, it is selected automatically.
- ``project.json`` now has an experimental option ["project"]["settings"]["enable_execute_all"] which disables the
Execute Project button when set to ``false``. The option is currently not settable in the UI.

### Changed
- The console settings of Python tools as well as the command and shell settings of executable tools
Expand All @@ -54,6 +57,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
Duplicating a previously duplicated item now has the number `xx` incremented instead of having a new number appended.
- "Open kernel spec editor" buttons in Settings->Tools page have been changed "Make Julia kernel" and
"Make Python Kernel" buttons
-

### Deprecated

Expand Down
4 changes: 2 additions & 2 deletions bin/build_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def fix_resources_imports(path):
lines = list()
with open(path, 'r') as in_file:
for line in in_file:
if line == "from . import resources_icons_rc\n":
if line == "from . import resources_icons_rc\n":
lines.append("from spinetoolbox import resources_icons_rc\n")
elif line == "from . import resources_logos_rc\n":
elif line == "from . import resources_logos_rc\n":
lines.append("from spinetoolbox import resources_logos_rc\n")
else:
lines.append(line)
Expand Down
7 changes: 5 additions & 2 deletions execution_tests/import_file_packs/.spinetoolbox/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {
"Tool": [
Expand Down Expand Up @@ -42,7 +42,10 @@
]
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Create file pack": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {
"Tool": [
Expand Down Expand Up @@ -106,7 +106,10 @@
}
]
}
]
],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Write data": {
Expand Down
7 changes: 5 additions & 2 deletions execution_tests/merger_write_order/.spinetoolbox/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {},
"connections": [
Expand Down Expand Up @@ -52,7 +52,10 @@
}
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"First source": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {
"Exporter": [
Expand Down Expand Up @@ -34,7 +34,10 @@
}
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Data": {
Expand Down
7 changes: 5 additions & 2 deletions execution_tests/parallel_importer/.spinetoolbox/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {
"Tool": [
Expand Down Expand Up @@ -53,7 +53,10 @@
]
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Source": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "",
"specifications": {
"Tool": [
Expand Down Expand Up @@ -56,7 +56,10 @@
]
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Source": {
Expand Down
7 changes: 5 additions & 2 deletions execution_tests/scenario_filters/.spinetoolbox/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"version": 10,
"version": 11,
"description": "Test project to test scenario filtering in a Tool project item.",
"specifications": {
"Importer": [
Expand Down Expand Up @@ -58,7 +58,10 @@
}
}
],
"jumps": []
"jumps": [],
"settings": {
"enable_execute_all": true
}
},
"items": {
"Data store": {
Expand Down
2 changes: 1 addition & 1 deletion spinetoolbox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from pathlib import Path

# NOTE: All required Python package versions are in setup.cfg
LATEST_PROJECT_VERSION = 10
LATEST_PROJECT_VERSION = 11

# For the Add/Update SpineOpt wizard
REQUIRED_SPINE_OPT_VERSION = "0.6.9"
Expand Down
25 changes: 17 additions & 8 deletions spinetoolbox/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
)
from spine_engine.utils.serialization import deserialize_path, serialize_path
from spine_engine.server.util.zip_handler import ZipHandler
from .project_settings import ProjectSettings
from .server.engine_client import EngineClient
from .metaobject import MetaObject
from .helpers import (
Expand Down Expand Up @@ -107,13 +108,14 @@ class SpineToolboxProject(MetaObject):
specification_saved = Signal(str, str)
"""Emitted after a specification has been saved."""

def __init__(self, toolbox, p_dir, plugin_specs, settings, logger):
def __init__(self, toolbox, p_dir, plugin_specs, app_settings, settings, logger):
"""
Args:
toolbox (ToolboxUI): toolbox of this project
p_dir (str): Project directory
plugin_specs (Iterable of ProjectItemSpecification): specifications available as plugins
settings (QSettings): Toolbox settings
app_settings (QSettings): Toolbox settings
settings (ProjectSettings): project settings
logger (LoggerInterface): a logger instance
"""
_, name = os.path.split(p_dir)
Expand All @@ -124,6 +126,7 @@ def __init__(self, toolbox, p_dir, plugin_specs, settings, logger):
self._connections = list()
self._jumps = list()
self._logger = logger
self._app_settings = app_settings
self._settings = settings
self._engine_workers = []
self._execution_in_progress = False
Expand All @@ -148,6 +151,10 @@ def toolbox(self):
def all_item_names(self):
return list(self._project_items)

@property
def settings(self):
return self._settings

def _create_project_structure(self, directory):
"""Makes the given directory a Spine Toolbox project directory.
Creates directories and files that are common to all projects.
Expand Down Expand Up @@ -193,6 +200,7 @@ def save(self):
project_dict = {
"version": LATEST_PROJECT_VERSION,
"description": self.description,
"settings": self._settings.to_dict(),
"specifications": serialized_spec_paths,
"connections": [connection.to_dict() for connection in self._connections],
"jumps": [jump.to_dict() for jump in self._jumps],
Expand Down Expand Up @@ -288,6 +296,7 @@ def load(self, spec_factories, item_factories):
self._merge_local_data_to_project_info(local_data_dict, project_info)
# Parse project info
self.set_description(project_info["project"]["description"])
self._settings = ProjectSettings.from_dict(project_info["project"]["settings"])
spec_paths_per_type = project_info["project"]["specifications"]
deserialized_paths = [
deserialize_path(path, self.project_dir) for paths in spec_paths_per_type.values() for path in paths
Expand All @@ -296,7 +305,7 @@ def load(self, spec_factories, item_factories):
specification_local_data = load_specification_local_data(self.config_dir)
for path in deserialized_paths:
spec = load_specification_from_file(
path, specification_local_data, spec_factories, self._settings, self._logger
path, specification_local_data, spec_factories, self._app_settings, self._logger
)
if spec is not None:
self.add_specification(spec, save_to_disk=False)
Expand Down Expand Up @@ -973,7 +982,7 @@ def _execute_dags(self, dags, execution_permits_list):
if not self.job_id:
self.project_execution_finished.emit()
return
settings = make_settings_dict_for_engine(self._settings)
settings = make_settings_dict_for_engine(self._app_settings)
darker_fg_color = QColor(FG_COLOR).darker().name()
darker = lambda x: f'<span style="color: {darker_fg_color}">{x}</span>'
for k, (dag, execution_permits) in enumerate(zip(dags, execution_permits_list)):
Expand Down Expand Up @@ -1401,8 +1410,8 @@ def _update_ranks(self, dag):
item.set_rank(ranks[item_name])

@property
def settings(self):
return self._settings
def app_settings(self):
return self._app_settings

@busy_effect
def prepare_remote_execution(self):
Expand All @@ -1412,7 +1421,7 @@ def prepare_remote_execution(self):
str: Job Id if server is ready for remote execution, empty string if something went wrong or "1" if
local execution is enabled.
"""
if not self._settings.value("engineSettings/remoteExecutionEnabled", defaultValue="false") == "true":
if not self._app_settings.value("engineSettings/remoteExecutionEnabled", defaultValue="false") == "true":
return "1" # Something that isn't False
host, port, sec_model, sec_folder = self._toolbox.engine_server_settings()
if not host:
Expand Down Expand Up @@ -1462,7 +1471,7 @@ def prepare_remote_execution(self):

def finalize_remote_execution(self):
"""Sends a request to server to remove the project directory and removes the project ZIP file from client."""
if not self._settings.value("engineSettings/remoteExecutionEnabled", defaultValue="false") == "true":
if not self._app_settings.value("engineSettings/remoteExecutionEnabled", defaultValue="false") == "true":
return
host, port, sec_model, sec_folder = self._toolbox.engine_server_settings()
try:
Expand Down
40 changes: 40 additions & 0 deletions spinetoolbox/project_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
######################################################################################################################
# Copyright (C) 2017-2022 Spine project consortium
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
# any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# 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/>.
######################################################################################################################
"""Contains project-specific settings."""

import dataclasses


@dataclasses.dataclass
class ProjectSettings:
"""Spine Toolbox project settings."""

enable_execute_all: bool = True

def to_dict(self):
"""Serializes the settings into a dictionary.
Returns:
dict: serialized settings
"""
return dataclasses.asdict(self)

@staticmethod
def from_dict(settings_dict):
"""Deserializes settings from dictionary.
Args:
settings_dict (dict): serialized settings
Returns:
ProjectSettings: deserialized settings
"""
return ProjectSettings(**settings_dict)
Loading

0 comments on commit af55312

Please sign in to comment.