From 9eb8416422330237b4c8c5b38f485190adc2c846 Mon Sep 17 00:00:00 2001 From: Samuel Jones <samjones714@gmail.com> Date: Tue, 4 Dec 2018 16:05:12 +0000 Subject: [PATCH] Re #24049 Interrim commit --- .../MantidAPI/AnalysisDataServiceObserver.h | 47 +++++++++--- .../API/src/AnalysisDataServiceObserver.cpp | 71 ++++++++++++++++++- .../api/AnalysisDataServiceObserverAdapter.h | 43 +++++++++++ .../PythonInterface/mantid/api/CMakeLists.txt | 2 + .../Exports/AnalysisDataServiceObserver.cpp | 18 ++--- .../AnalysisDataServiceObserverAdapter.cpp | 29 ++++++++ .../workbench/workbench/app/mainwindow.py | 3 +- qt/python/CMakeLists.txt | 5 ++ qt/python/mantidqt/project/project.py | 47 +++++++----- qt/python/mantidqt/project/projectloader.py | 16 +++-- qt/python/mantidqt/project/projectsaver.py | 19 +++-- .../project/test/test_projectloader.py | 15 ++-- .../project/test/test_projectsaver.py | 59 ++++++++------- .../project/test/test_workspaceloader.py | 24 +++---- .../project/test/test_workspacesaver.py | 28 ++++---- qt/python/mantidqt/project/workspaceloader.py | 13 +++- qt/python/mantidqt/project/workspacesaver.py | 4 +- 17 files changed, 317 insertions(+), 126 deletions(-) create mode 100644 Framework/PythonInterface/inc/MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h create mode 100644 Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserverAdapter.cpp diff --git a/Framework/API/inc/MantidAPI/AnalysisDataServiceObserver.h b/Framework/API/inc/MantidAPI/AnalysisDataServiceObserver.h index d7bdfb8bba5..77dc2630bef 100644 --- a/Framework/API/inc/MantidAPI/AnalysisDataServiceObserver.h +++ b/Framework/API/inc/MantidAPI/AnalysisDataServiceObserver.h @@ -25,22 +25,51 @@ public: void observeAll(bool turnOn = true); void observeAdd(bool turnOn = true); - + void observeReplace(bool turnOn = true); + void observeDelete(bool turnOn = true); + virtual void anyChangeHandle() {} protected: - virtual void addHandle(const std::string &wsName, - const Workspace_sptr ws); + virtual void addHandle(const std::string &wsName, const Workspace_sptr ws); + virtual void replaceHandle(const std::string &wsName, + const Workspace_sptr ws); + virtual void deleteHandle(const std::string &wsName, const Workspace_sptr ws); + private: - bool m_observingAdd; + bool m_observingAdd, m_observingReplace, m_observingDelete; + + void _addHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::AddNotification> &pNf); + void _replaceHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::AfterReplaceNotification> + &pNf); + void _deleteHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::PostDeleteNotification> + &pNf); - void _addHandle(const Poco::AutoPtr<AnalysisDataServiceImpl::AddNotification> &pNf){ - this->anyChangeHandle(); - this->addHandle(pNf->objectName(), pNf->object()); - } /// Poco::NObserver for AddNotification. - Poco::NObserver<AnalysisDataServiceObserver, AnalysisDataServiceImpl::AddNotification> + Poco::NObserver<AnalysisDataServiceObserver, + AnalysisDataServiceImpl::AddNotification> m_addObserver; + + /// Poco::NObserver for ReplaceNotification. + Poco::NObserver<AnalysisDataServiceObserver, + AnalysisDataServiceImpl::AfterReplaceNotification> + m_replaceObserver; + + /// Poco::NObserver for DeleteNotification. + Poco::NObserver<AnalysisDataServiceObserver, + AnalysisDataServiceImpl::PostDeleteNotification> + m_deleteObserver; + + /// Poco::NObserver for ClearNotification + + /// Poco::NObserver for RenameNotification + + /// Poco::NObserver for GroupNotification + + /// Poco::NObserver for UnGroupNotification }; } // namespace API diff --git a/Framework/API/src/AnalysisDataServiceObserver.cpp b/Framework/API/src/AnalysisDataServiceObserver.cpp index 78fd69efa3b..b8d77ca181a 100644 --- a/Framework/API/src/AnalysisDataServiceObserver.cpp +++ b/Framework/API/src/AnalysisDataServiceObserver.cpp @@ -10,13 +10,20 @@ AnalysisDataServiceObserver::AnalysisDataServiceObserver() : m_addObserver(*this, &AnalysisDataServiceObserver::_addHandle) {} -AnalysisDataServiceObserver::~AnalysisDataServiceObserver(){ +AnalysisDataServiceObserver::~AnalysisDataServiceObserver() { // Turn off/remove all observers this->observeAll(false); } + +// ------------------------------------------------------------ +// Observe Methods +// ------------------------------------------------------------ + void AnalysisDataServiceObserver::observeAll(bool turnOn) { this->observeAdd(turnOn); + this->observeReplace(turnOn); + this->observeDelete(turnOn); } void AnalysisDataServiceObserver::observeAdd(bool turnOn) { @@ -30,8 +37,68 @@ void AnalysisDataServiceObserver::observeAdd(bool turnOn) { m_observingAdd = turnOn; } +void AnalysisDataServiceObserver::observeReplace(bool turnOn) { + if (turnOn && !m_observingReplace) { + AnalysisDataService::Instance().notificationCenter.addObserver( + m_ReplaceObserver); + } else if (!turnOn && m_observingReplace) { + AnalysisDataService::Instance().notificationCenter.removeObserver( + m_ReplaceObserver); + } + m_observingReplace = turnOn; +} + +void AnalysisDataServiceObserver::observeDelete(bool turnOn) { + if (turnOn && !m_observingDelete) { + AnalysisDataService::Instance().notificationCenter.addObserver( + m_deleteObserver); + } else if (!turnOn && m_observingDelete) { + AnalysisDataService::Instance().notificationCenter.removeObserver( + m_deleteObserver); + } + m_observingDelete = turnOn; +} + +// ------------------------------------------------------------ +// Virtual Methods +// ------------------------------------------------------------ void AnalysisDataServiceObserver::addHandle( const std::string &wsName, const Mantid::API::Workspace_sptr ws) { UNUSED_ARG(wsName) UNUSED_ARG(ws) -} \ No newline at end of file +} + +void AnalysisDataServiceObserver::replaceHandle( + const std::string &wsName, const Mantid::API::Workspace_sptr ws) { + UNUSED_ARG(wsName) + UNUSED_ARG(ws) +} + +void AnalysisDataServiceObserver::deleteHandle( + const std::string &wsName, const Mantid::API::Workspace_sptr ws) { + UNUSED_ARG(wsName) + UNUSED_ARG(ws) +} + +// ------------------------------------------------------------ +// Private Methods +// ------------------------------------------------------------ +void AnalysisDataServiceObserver::_addHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::AddNotification> &pNf) { + this->anyChangeHandle(); + this->addHandle(pNf->objectName(), pNf->object()); +} + +void AnalysisDataServiceObserver::_replaceHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::AfterReplaceNotification> + &pNf) { + this->anyChangeHandle(); + this->replaceHandle(pNf->objectName(), pNf->object()); +} + +void AnalysisDataServiceObserver::_deleteHandle( + const Poco::AutoPtr<AnalysisDataServiceImpl::AfterReplaceNotification> + &pNf) { + this->anyChangeHandle(); + this->deleteHandle(pNf->objectName(), pNf->object()); +} diff --git a/Framework/PythonInterface/inc/MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h b/Framework/PythonInterface/inc/MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h new file mode 100644 index 00000000000..0c478f9fea5 --- /dev/null +++ b/Framework/PythonInterface/inc/MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h @@ -0,0 +1,43 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2013 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#ifndef MANTID_PYTHONINTERFACE_ANALYSISDATASERVICEOBSERVERADAPTER_H_ +#define MANTID_PYTHONINTERFACE_ANALYSISDATASERVICEOBSERVERADAPTER_H_ + +#include "MantidAPI/AnalysisDataServiceObserver.h" +#include <boost/python/wrapper.hpp> + +namespace Mantid { +namespace PythonInterface { + +/** +A wrapper class helping to export AnalysisDataServiceObserver to python. +It provides access from the C++ side to methods defined in python +on subclasses of AnalysisDataServiceObserver. +This allows the virtual methods to be overriden by python subclasses. + */ + +class DLLExport AnalysisDataServiceObserverAdapter + : public API::AnalysisDataServiceObserver { +public: + explicit AnalysisDataServiceObserverAdapter(PyObject *self); + AnalysisDataServiceObserverAdapter( + const AnalysisDataServiceObserverAdapter &) = delete; + AnalysisDataServiceObserverAdapter & + operator=(const AnalysisDataServiceObserverAdapter &) = delete; + void anyChangeHandle() override; + +private: + /// Return the PyObject that owns this wrapper, i.e. self + inline PyObject *getSelf() const { return m_self; } + /// Value of "self" used by python to refer to an instance of this class + PyObject *m_self; +}; + +} // namespace PythonInterface +} // namespace Mantid + +#endif /*MANTID_PYTHONINTERFACE_ANALYSISDATASERVICEOBSERVERADAPTER_H_*/ \ No newline at end of file diff --git a/Framework/PythonInterface/mantid/api/CMakeLists.txt b/Framework/PythonInterface/mantid/api/CMakeLists.txt index a125a7c99d8..fb4911e15d1 100644 --- a/Framework/PythonInterface/mantid/api/CMakeLists.txt +++ b/Framework/PythonInterface/mantid/api/CMakeLists.txt @@ -100,6 +100,7 @@ set ( SRC_FILES src/PythonAlgorithm/DataProcessorAdapter.cpp src/CloneMatrixWorkspace.cpp src/ExtractWorkspace.cpp + src/Exports/AnalysisDataServiceObserverAdapter.cpp ) set ( INC_FILES @@ -110,6 +111,7 @@ set ( INC_FILES ${HEADER_DIR}/api/FitFunctions/IPeakFunctionAdapter.h ${HEADER_DIR}/api/PythonAlgorithm/AlgorithmAdapter.h ${HEADER_DIR}/api/PythonAlgorithm/DataProcessorAdapter.h + ${HEADER_DIR}/api/AnalysisDataServiceObserverAdapter.h ${HEADER_DIR}/api/BinaryOperations.h ${HEADER_DIR}/api/CloneMatrixWorkspace.h ${HEADER_DIR}/api/ExtractWorkspace.h diff --git a/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserver.cpp b/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserver.cpp index b6d61cf3fb9..817040ef5bd 100644 --- a/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserver.cpp +++ b/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserver.cpp @@ -5,26 +5,22 @@ // & Institut Laue - Langevin // SPDX - License - Identifier: GPL - 3.0 + #include "MantidAPI/AnalysisDataServiceObserver.h" +#include "MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h" #include "MantidPythonInterface/kernel/GetPointer.h" -#include <boost/python/class.hpp> #include <boost/python/bases.hpp> -#include <boost/python/register_ptr_to_python.hpp> +#include <boost/python/class.hpp> using namespace Mantid::API; +using namespace Mantid::PythonInterface; using namespace boost::python; void export_AnalysisDataServiceObserver() { - - boost::python::register_ptr_to_python< - boost::shared_ptr<AnalysisDataServiceObserver>>(); - boost::python::class_<AnalysisDataServiceObserver, bases<>, - boost::shared_ptr<AnalysisDataServiceObserver>, boost::noncopyable>( + AnalysisDataServiceObserverAdapter, boost::noncopyable>( "AnalysisDataServiceObserver", "Observes AnalysisDataService notifications: all only") - .def("observeAll", &AnalysisDataServiceObserver::observeAll, (arg("self"), arg("on")), - "Observe AnalysisDataService for any changes") - .def("anyChangeHandle", &AnalysisDataServiceObserver::anyChangeHandle, arg("self"), - "Override this to change the effect of what happens when a change occurs in the ADS"); + .def("observeAll", &AnalysisDataServiceObserverAdapter::observeAll, + (arg("self"), arg("on")), + "Observe AnalysisDataService for any changes"); } \ No newline at end of file diff --git a/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserverAdapter.cpp b/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserverAdapter.cpp new file mode 100644 index 00000000000..b006380e076 --- /dev/null +++ b/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataServiceObserverAdapter.cpp @@ -0,0 +1,29 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidPythonInterface/api/AnalysisDataServiceObserverAdapter.h" +#include "MantidAPI/AnalysisDataServiceObserver.h" +#include "MantidPythonInterface/core/CallMethod.h" + +#include <iostream> + +namespace Mantid { +namespace PythonInterface { + +AnalysisDataServiceObserverAdapter::AnalysisDataServiceObserverAdapter( + PyObject *self) + : API::AnalysisDataServiceObserver(), m_self(self) {} + +void AnalysisDataServiceObserverAdapter::anyChangeHandle() { + try { + return callMethod<void>(getSelf(), "anyChangeHandle"); + } catch (UndefinedAttributeError &) { + return; + } +} + +} // namespace PythonInterface +} // namespace Mantid diff --git a/qt/applications/workbench/workbench/app/mainwindow.py b/qt/applications/workbench/workbench/app/mainwindow.py index fdb92c4fee0..86a876c51c1 100644 --- a/qt/applications/workbench/workbench/app/mainwindow.py +++ b/qt/applications/workbench/workbench/app/mainwindow.py @@ -203,8 +203,7 @@ class MainWindow(QMainWindow): # Set up the project object from mantidqt.project.project import Project - project_save_filename = "mantidsave.project" - self.project = Project(project_save_filename) + self.project = Project() # uses default configuration as necessary self.readSettings(CONF) diff --git a/qt/python/CMakeLists.txt b/qt/python/CMakeLists.txt index 68e6e4ef408..a4ab9bce24d 100644 --- a/qt/python/CMakeLists.txt +++ b/qt/python/CMakeLists.txt @@ -69,6 +69,11 @@ endif () mantidqt/dialogs/test/test_algorithm_dialog.py mantidqt/dialogs/test/test_spectraselectiondialog.py + mantidqt/project/test/test_projectloader.py + mantidqt/project/test/test_projectsaver.py + mantidqt/project/test/test_workspaceloader.py + mantidqt/project/test/test_workspacesaver.py + mantidqt/utils/test/test_async.py mantidqt/utils/test/test_modal_tester.py mantidqt/utils/test/test_qt_utils.py diff --git a/qt/python/mantidqt/project/project.py b/qt/python/mantidqt/project/project.py index 48d4728eaf1..23ba577d251 100644 --- a/qt/python/mantidqt/project/project.py +++ b/qt/python/mantidqt/project/project.py @@ -9,10 +9,9 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) import os -import glob +import re from qtpy.QtWidgets import QFileDialog, QMessageBox -from mantid import logger from mantid.api import AnalysisDataService, AnalysisDataServiceObserver from mantidqt.io import open_a_file_dialog from mantidqt.project.projectloader import ProjectLoader @@ -20,28 +19,24 @@ from mantidqt.project.projectsaver import ProjectSaver class Project(AnalysisDataServiceObserver): - def __init__(self, project_save_name): + def __init__(self): + super(Project, self).__init__() # Has the project been saved self.saved = False # Last save locations self.last_project_location = None - self.project_save_name = project_save_name - self.ads_observer = AnalysisDataServiceObserver() - self.ads_observer.observeAll(True) + self.observeAll(True) + + self.project_file_ext = ".mtdproj" def save(self): if self.last_project_location is None: - self.save_project_as() + self.save_as() else: - # Clear directory before saving to remove old workspaces - files = glob.glob(self.last_project_location + '/.*') - for f in files: - try: - os.remove(f) - except OSError as e: - logger.debug("Whilst cleaning project directory error was thrown: " + e) + # Clear unused workspaces + self._clear_unused_workspaces(self.last_project_location) # Actually save workspaces_to_save = AnalysisDataService.getObjectNames() project_saver = ProjectSaver(self.project_save_name) @@ -53,7 +48,8 @@ class Project(AnalysisDataServiceObserver): directory = None # Check if it exists first_pass = True - while first_pass or (not os.path.exists(directory) and os.path.exists(directory + "mantidsave.project")): + while first_pass or (not os.path.exists(directory) and os.path.exists(directory + (os.path.basename(directory) + + ".mtdproj"))): first_pass = False directory = open_a_file_dialog(accept_mode=QFileDialog.AcceptSave, file_mode=QFileDialog.DirectoryOnly) if directory is None: @@ -63,7 +59,7 @@ class Project(AnalysisDataServiceObserver): # todo: get a list of workspaces but to be implemented on GUI implementation self.last_project_location = directory workspaces_to_save = AnalysisDataService.getObjectNames() - project_saver = ProjectSaver(self.project_save_name) + project_saver = ProjectSaver(self.project_file_ext) project_saver.save_project(directory=directory, workspace_to_save=workspaces_to_save, interfaces_to_save=None) self.saved = True @@ -77,7 +73,7 @@ class Project(AnalysisDataServiceObserver): if directory is None: # Cancel close dialogs return - project_loader = ProjectLoader(self.project_save_name) + project_loader = ProjectLoader(self.project_file_ext) project_loader.load_project(directory) self.last_project_location = directory @@ -103,3 +99,20 @@ class Project(AnalysisDataServiceObserver): def anyChangeHandle(self): self.modified_project() + + @staticmethod + def _clear_unused_workspaces(path): + files_to_remove = [] + list_dir = os.listdir(path) + current_workspaces = AnalysisDataService.getObjectNames() + for item in list_dir: + # Don't count or check files that do not end in .nxs, and check that they are not in current workspaces + # without the .nxs + if bool(re.search('$.nxs', item)): + workspace_name = item.replace(".nxs", "") + if workspace_name not in current_workspaces: + files_to_remove.append(item) + + # Actually remove them + for filename in files_to_remove: + os.remove(path + "/" + filename) diff --git a/qt/python/mantidqt/project/projectloader.py b/qt/python/mantidqt/project/projectloader.py index cde196c214a..d848d92a38b 100644 --- a/qt/python/mantidqt/project/projectloader.py +++ b/qt/python/mantidqt/project/projectloader.py @@ -9,8 +9,9 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) import json +import os -import workspaceloader +from mantidqt.project import workspaceloader from mantid import AnalysisDataService as ADS from mantid import logger @@ -25,28 +26,29 @@ def _confirm_all_workspaces_loaded(workspaces_to_confirm): class ProjectLoader(object): - def __init__(self, project_load_name): - self.project_reader = ProjectReader(project_load_name) + def __init__(self, project_file_ext): + self.project_reader = ProjectReader(project_file_ext) self.workspace_loader = workspaceloader.WorkspaceLoader() + self.project_file_ext = project_file_ext def load_project(self, directory): # Read project self.project_reader.read_project(directory) # Load in the workspaces - self.workspace_loader.load_workspaces(directory=directory) + self.workspace_loader.load_workspaces(directory=directory, project_file_ext=self.project_file_ext) return _confirm_all_workspaces_loaded(workspaces_to_confirm=self.project_reader.workspace_names) class ProjectReader(object): - def __init__(self, project_load_name): + def __init__(self, project_file_ext): self.workspace_names = None self.interfaces_dicts = None self.plot_dicts = None - self.project_load_name = project_load_name + self.project_file_ext = project_file_ext def read_project(self, directory): - f = open(directory + "/" + self.project_load_name) + f = open(directory + "/" + (os.path.basename(directory) + self.project_file_ext)) json_data = json.load(f) self.workspace_names = json_data["workspaces"] self.interfaces_dicts = json_data["interfaces"] diff --git a/qt/python/mantidqt/project/projectsaver.py b/qt/python/mantidqt/project/projectsaver.py index 357ff26499d..619ab148bbb 100644 --- a/qt/python/mantidqt/project/projectsaver.py +++ b/qt/python/mantidqt/project/projectsaver.py @@ -9,16 +9,15 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) from json import dump -from os import makedirs -from os.path import isdir +import os from mantidqt.project import workspacesaver from mantid import logger class ProjectSaver(object): - def __init__(self, project_save_name): - self.project_save_name = project_save_name + def __init__(self, project_file_ext): + self.project_file_ext = project_file_ext def save_project(self, directory, workspace_to_save=None, interfaces_to_save=None): """ @@ -47,12 +46,12 @@ class ProjectSaver(object): # Pass dicts to Project Writer writer = ProjectWriter(dictionaries_to_save, directory, workspace_saver.get_output_list(), - self.project_save_name) + self.project_file_ext) writer.write_out() class ProjectWriter(object): - def __init__(self, dicts, save_location, workspace_names, project_save_name): + def __init__(self, dicts, save_location, workspace_names, project_file_ext): """ :param dicts: @@ -62,7 +61,7 @@ class ProjectWriter(object): self.dicts_to_save = dicts self.workspace_names = workspace_names self.directory = save_location - self.project_save_name = project_save_name + self.project_file_ext = project_file_ext def write_out(self): """ @@ -72,8 +71,8 @@ class ProjectWriter(object): workspace_interface_dict = {"workspaces": self.workspace_names, "interfaces": self.dicts_to_save} # Open file and save the string to it alongside the workspace_names - file_name = self.directory + '/' + self.project_save_name - if not isdir(self.directory): - makedirs(self.directory) + file_name = self.directory + '/' + (os.path.basename(self.directory) + self.project_file_ext) + if not os.path.isdir(self.directory): + os.makedirs(self.directory) f = open(file_name, 'w+') dump(obj=workspace_interface_dict, fp=f) diff --git a/qt/python/mantidqt/project/test/test_projectloader.py b/qt/python/mantidqt/project/test/test_projectloader.py index 852b44875c1..2dff9a20da7 100644 --- a/qt/python/mantidqt/project/test/test_projectloader.py +++ b/qt/python/mantidqt/project/test/test_projectloader.py @@ -9,23 +9,24 @@ import unittest -from os.path import isdir, expanduser +from os.path import isdir from shutil import rmtree +import tempfile from mantid.api import AnalysisDataService as ADS from mantid.simpleapi import CreateSampleWorkspace from mantidqt.project import projectloader, projectsaver -project_file_name = "mantidsave.project" -working_directory = expanduser("~") + "/project_loader_test" +project_file_ext = ".mtdproj" +working_directory = tempfile.mkdtemp() class ProjectLoaderTest(unittest.TestCase): def setUp(self): ws1_name = "ws1" ADS.addOrReplace(ws1_name, CreateSampleWorkspace(OutputWorkspace=ws1_name)) - project_saver = projectsaver.ProjectSaver(project_file_name) + project_saver = projectsaver.ProjectSaver(project_file_ext) project_saver.save_project(workspace_to_save=[ws1_name], directory=working_directory) def tearDown(self): @@ -34,7 +35,7 @@ class ProjectLoaderTest(unittest.TestCase): rmtree(working_directory) def test_project_loading(self): - project_loader = projectloader.ProjectLoader(project_file_name) + project_loader = projectloader.ProjectLoader(project_file_ext) self.assertTrue(project_loader.load_project(working_directory)) @@ -50,7 +51,7 @@ class ProjectReaderTest(unittest.TestCase): def setUp(self): ws1_name = "ws1" ADS.addOrReplace(ws1_name, CreateSampleWorkspace(OutputWorkspace=ws1_name)) - project_saver = projectsaver.ProjectSaver(project_file_name) + project_saver = projectsaver.ProjectSaver(project_file_ext) project_saver.save_project(workspace_to_save=[ws1_name], directory=working_directory) def tearDown(self): @@ -59,7 +60,7 @@ class ProjectReaderTest(unittest.TestCase): rmtree(working_directory) def test_project_reading(self): - project_reader = projectloader.ProjectReader(project_file_name) + project_reader = projectloader.ProjectReader(project_file_ext) project_reader.read_project(working_directory) self.assertEqual(["ws1"], project_reader.workspace_names) self.assertEqual({}, project_reader.interfaces_dicts) diff --git a/qt/python/mantidqt/project/test/test_projectsaver.py b/qt/python/mantidqt/project/test/test_projectsaver.py index d2407beb69d..0fddd3cad46 100644 --- a/qt/python/mantidqt/project/test/test_projectsaver.py +++ b/qt/python/mantidqt/project/test/test_projectsaver.py @@ -9,8 +9,7 @@ import unittest import tempfile -from os import listdir -from os.path import isdir +import os from shutil import rmtree from mantid.api import AnalysisDataService as ADS @@ -18,7 +17,7 @@ from mantid.simpleapi import CreateSampleWorkspace from mantidqt.project import projectsaver -project_file_name = "mantidsave.mtdproj" +project_file_ext = ".mtdproj" working_directory = tempfile.mkdtemp() @@ -28,14 +27,14 @@ class ProjectSaverTest(unittest.TestCase): def setUp(self): # In case it was hard killed and is still present - if isdir(working_directory): + if os.path.isdir(working_directory): rmtree(working_directory) def test_only_one_workspace_saving(self): ws1_name = "ws1" ADS.addOrReplace(ws1_name, CreateSampleWorkspace(OutputWorkspace=ws1_name)) - project_saver = projectsaver.ProjectSaver(project_file_name) - file_name = working_directory + "/" + project_file_name + project_saver = projectsaver.ProjectSaver(project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {}, \"workspaces\": [\"ws1\"]}" project_saver.save_project(workspace_to_save=[ws1_name], directory=working_directory) @@ -45,10 +44,10 @@ class ProjectSaverTest(unittest.TestCase): self.assertEqual(f.read(), saved_file) # Check workspace is saved - list_of_files = listdir(working_directory) + list_of_files = os.listdir(working_directory) self.assertEqual(len(list_of_files), 2) - self.assertTrue(project_file_name in list_of_files) - self.assertTrue(ws1_name in list_of_files) + self.assertTrue(os.path.basename(working_directory) + project_file_ext in list_of_files) + self.assertTrue(ws1_name + ".nxs" in list_of_files) def test_only_multiple_workspaces_saving(self): ws1_name = "ws1" @@ -61,8 +60,8 @@ class ProjectSaverTest(unittest.TestCase): CreateSampleWorkspace(OutputWorkspace=ws3_name) CreateSampleWorkspace(OutputWorkspace=ws4_name) CreateSampleWorkspace(OutputWorkspace=ws5_name) - project_saver = projectsaver.ProjectSaver(project_file_name) - file_name = working_directory + "/" + project_file_name + project_saver = projectsaver.ProjectSaver(project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {}, \"workspaces\": [\"ws1\", \"ws2\", \"ws3\", \"ws4\", \"ws5\"]}" project_saver.save_project(workspace_to_save=[ws1_name, ws2_name, ws3_name, ws4_name, ws5_name], @@ -73,14 +72,14 @@ class ProjectSaverTest(unittest.TestCase): self.assertEqual(f.read(), saved_file) # Check workspace is saved - list_of_files = listdir(working_directory) + list_of_files = os.listdir(working_directory) self.assertEqual(len(list_of_files), 6) - self.assertTrue(project_file_name in list_of_files) - self.assertTrue(ws1_name in list_of_files) - self.assertTrue(ws2_name in list_of_files) - self.assertTrue(ws3_name in list_of_files) - self.assertTrue(ws4_name in list_of_files) - self.assertTrue(ws5_name in list_of_files) + self.assertTrue(os.path.basename(working_directory) + project_file_ext in list_of_files) + self.assertTrue(ws1_name + ".nxs" in list_of_files) + self.assertTrue(ws2_name + ".nxs" in list_of_files) + self.assertTrue(ws3_name + ".nxs" in list_of_files) + self.assertTrue(ws4_name + ".nxs" in list_of_files) + self.assertTrue(ws5_name + ".nxs" in list_of_files) def test_only_saving_one_workspace_when_multiple_are_present_in_the_ADS(self): ws1_name = "ws1" @@ -89,8 +88,8 @@ class ProjectSaverTest(unittest.TestCase): CreateSampleWorkspace(OutputWorkspace=ws1_name) CreateSampleWorkspace(OutputWorkspace=ws2_name) CreateSampleWorkspace(OutputWorkspace=ws3_name) - project_saver = projectsaver.ProjectSaver() - file_name = working_directory + "/" + project_file_name + project_saver = projectsaver.ProjectSaver(project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {}, \"workspaces\": [\"ws1\"]}" project_saver.save_project(workspace_to_save=[ws1_name], directory=working_directory) @@ -100,10 +99,10 @@ class ProjectSaverTest(unittest.TestCase): self.assertEqual(f.read(), saved_file) # Check workspace is saved - list_of_files = listdir(working_directory) + list_of_files = os.listdir(working_directory) self.assertEqual(len(list_of_files), 2) - self.assertTrue(project_file_name in list_of_files) - self.assertTrue(ws1_name in list_of_files) + self.assertTrue(os.path.basename(working_directory) + project_file_ext in list_of_files) + self.assertTrue(ws1_name + ".nxs" in list_of_files) #def test_only_one_interface_saving(self): @@ -126,14 +125,14 @@ class ProjectWriterTest(unittest.TestCase): def setUp(self): # In case it was hard killed and is still present - if isdir(working_directory): + if os.path.isdir(working_directory): rmtree(working_directory) def test_write_out_on_just_dicts(self): workspace_list = [] small_dict = {"interface1": {"value1": 2, "value2": 3}, "interface2": {"value3": 4, "value4": 5}} - project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_name) - file_name = working_directory + "/" + project_file_name + project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {\"interface1\": {\"value2\": 3, \"value1\": 2}, \"interface2\": {\"value4\"" \ ": 5, \"value3\": 4}}, \"workspaces\": []}" @@ -145,8 +144,8 @@ class ProjectWriterTest(unittest.TestCase): def test_write_out_on_just_workspaces(self): workspace_list = ["ws1", "ws2", "ws3", "ws4"] small_dict = {} - project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_name) - file_name = working_directory + "/" + project_file_name + project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {}, \"workspaces\": [\"ws1\", \"ws2\", \"ws3\", \"ws4\"]}" project_writer.write_out() @@ -157,8 +156,8 @@ class ProjectWriterTest(unittest.TestCase): def test_write_out_on_both_workspaces_and_dicts(self): workspace_list = ["ws1", "ws2", "ws3", "ws4"] small_dict = {"interface1": {"value1": 2, "value2": 3}, "interface2": {"value3": 4, "value4": 5}} - project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_name) - file_name = working_directory + "/" + project_file_name + project_writer = projectsaver.ProjectWriter(small_dict, working_directory, workspace_list, project_file_ext) + file_name = working_directory + "/" + os.path.basename(working_directory) + project_file_ext saved_file = "{\"interfaces\": {\"interface1\": {\"value2\": 3, \"value1\": 2}, \"interface2\": {\"value4\":" \ " 5, \"value3\": 4}}, \"workspaces\": [\"ws1\", \"ws2\", \"ws3\", \"ws4\"]}" project_writer.write_out() diff --git a/qt/python/mantidqt/project/test/test_workspaceloader.py b/qt/python/mantidqt/project/test/test_workspaceloader.py index 2900d9cd076..bc45e2cb789 100644 --- a/qt/python/mantidqt/project/test/test_workspaceloader.py +++ b/qt/python/mantidqt/project/test/test_workspaceloader.py @@ -9,30 +9,30 @@ import unittest -from os.path import isdir, expanduser +from os.path import isdir from shutil import rmtree +import tempfile from mantid.api import AnalysisDataService as ADS from mantid.simpleapi import CreateSampleWorkspace from mantidqt.project import projectsaver, workspaceloader -working_directory = expanduser("~") + "/workspace_loader_test" - - class WorkspaceLoaderTest(unittest.TestCase): def setUp(self): - ws1_name = "ws1" - ADS.addOrReplace(ws1_name, CreateSampleWorkspace(OutputWorkspace=ws1_name)) - project_saver = projectsaver.ProjectSaver() - project_saver.save_project(workspace_to_save=[ws1_name], directory=working_directory) + self.working_directory = tempfile.mkdtemp() + self.ws1_name = "ws1" + self.project_ext = ".mtdproj" + ADS.addOrReplace(self.ws1_name, CreateSampleWorkspace(OutputWorkspace=self.ws1_name)) + project_saver = projectsaver.ProjectSaver(self.project_ext) + project_saver.save_project(workspace_to_save=[self.ws1_name], directory=self.working_directory) def tearDown(self): ADS.clear() - if isdir(working_directory): - rmtree(working_directory) + if isdir(self.working_directory): + rmtree(self.working_directory) def test_workspace_loading(self): workspace_loader = workspaceloader.WorkspaceLoader() - workspace_loader.load_workspaces(working_directory) - self.assertEqual(ADS.getObjectNames(), ["ws1"]) + workspace_loader.load_workspaces(self.working_directory, self.project_ext) + self.assertEqual(ADS.getObjectNames(), [self.ws1_name]) diff --git a/qt/python/mantidqt/project/test/test_workspacesaver.py b/qt/python/mantidqt/project/test/test_workspacesaver.py index 66dece07dbc..b77237fb761 100644 --- a/qt/python/mantidqt/project/test/test_workspacesaver.py +++ b/qt/python/mantidqt/project/test/test_workspacesaver.py @@ -9,9 +9,10 @@ import unittest -from os import listdir, mkdir -from os.path import isdir, expanduser +from os import listdir +from os.path import isdir from shutil import rmtree +import tempfile from mantid.api import AnalysisDataService as ADS, IMDEventWorkspace # noqa from mantid.dataobjects import MDHistoWorkspace, MaskWorkspace # noqa @@ -19,33 +20,30 @@ from mantidqt.project import workspacesaver from mantid.simpleapi import (CreateSampleWorkspace, CreateMDHistoWorkspace, LoadMD, LoadMask, MaskDetectors, # noqa ExtractMask) # noqa -working_directory = expanduser("~") + "/workspace_saver_test_directory" - class WorkspaceSaverTest(unittest.TestCase): def setUp(self): - if not isdir(working_directory): - mkdir(working_directory) + self.working_directory = tempfile.mkdtemp() def tearDown(self): ADS.clear() - if isdir(working_directory): - rmtree(working_directory) + if isdir(self.working_directory): + rmtree(self.working_directory) def test_saving_single_workspace(self): - ws_saver = workspacesaver.WorkspaceSaver(working_directory) + ws_saver = workspacesaver.WorkspaceSaver(self.working_directory) ws1 = CreateSampleWorkspace() ws1_name = "ws1" ADS.addOrReplace(ws1_name, ws1) ws_saver.save_workspaces([ws1_name]) - list_of_files = listdir(working_directory) + list_of_files = listdir(self.working_directory) self.assertEqual(len(list_of_files), 1) self.assertEqual(list_of_files[0], ws1_name) def test_saving_multiple_workspaces(self): - ws_saver = workspacesaver.WorkspaceSaver(working_directory) + ws_saver = workspacesaver.WorkspaceSaver(self.working_directory) ws1 = CreateSampleWorkspace() ws1_name = "ws1" ws2 = CreateSampleWorkspace() @@ -55,13 +53,13 @@ class WorkspaceSaverTest(unittest.TestCase): ADS.addOrReplace(ws2_name, ws2) ws_saver.save_workspaces([ws1_name, ws2_name]) - list_of_files = listdir(working_directory) + list_of_files = listdir(self.working_directory) self.assertEqual(len(list_of_files), 2) self.assertEqual(list_of_files[0], ws2_name) self.assertEqual(list_of_files[1], ws1_name) def test_when_MDWorkspace_is_in_ADS(self): - ws_saver = workspacesaver.WorkspaceSaver(working_directory) + ws_saver = workspacesaver.WorkspaceSaver(self.working_directory) ws1 = CreateMDHistoWorkspace(SignalInput='1,2,3,4,5,6,7,8,9', ErrorInput='1,1,1,1,1,1,1,1,1', Dimensionality='2', Extents='-1,1,-1,1', NumberOfBins='3,3', Names='A,B', Units='U,T') @@ -70,13 +68,13 @@ class WorkspaceSaverTest(unittest.TestCase): ADS.addOrReplace(ws1_name, ws1) ws_saver.save_workspaces([ws1_name]) - list_of_files = listdir(working_directory) + list_of_files = listdir(self.working_directory) self.assertEqual(len(list_of_files), 1) self.assertEqual(list_of_files[0], ws1_name) self._load_MDWorkspace_and_test_it(ws1_name) def _load_MDWorkspace_and_test_it(self, save_name): - filename = working_directory + '/' + save_name + filename = self.working_directory + '/' + save_name ws = LoadMD(Filename=filename) ws_is_a_mdworkspace = isinstance(ws, IMDEventWorkspace) or isinstance(ws, MDHistoWorkspace) self.assertEqual(ws_is_a_mdworkspace, True) diff --git a/qt/python/mantidqt/project/workspaceloader.py b/qt/python/mantidqt/project/workspaceloader.py index 6729f875b2c..55f3e38c775 100644 --- a/qt/python/mantidqt/project/workspaceloader.py +++ b/qt/python/mantidqt/project/workspaceloader.py @@ -13,13 +13,22 @@ from os import path, listdir from mantid import logger +# List of extensions to ignore +ignore_exts = [".py"] + + class WorkspaceLoader(object): - def load_workspaces(self, directory): + @staticmethod + def load_workspaces(directory, project_file_ext): + # Include passed project file extension in ignore_exts from projects + ignore_exts.append(project_file_ext) + from mantid.simpleapi import Load # noqa filenames = listdir(directory) for filename in filenames: workspace_name, file_ext = path.splitext(filename) - if file_ext != u'.project': + # if file_ext not in [".mtdproj", ".py"]: + if file_ext not in ignore_exts: try: Load(directory + "/" + filename, OutputWorkspace=workspace_name) except BaseException as exception: diff --git a/qt/python/mantidqt/project/workspacesaver.py b/qt/python/mantidqt/project/workspacesaver.py index 29a37c431fd..b7cc1c4d833 100644 --- a/qt/python/mantidqt/project/workspacesaver.py +++ b/qt/python/mantidqt/project/workspacesaver.py @@ -51,10 +51,10 @@ class WorkspaceSaver(object): if isinstance(workspace, MDHistoWorkspace) or isinstance(workspace, IMDEventWorkspace): # Save normally using SaveMD - SaveMD(InputWorkspace=workspace_name, Filename=place_to_save_workspace) + SaveMD(InputWorkspace=workspace_name, Filename=place_to_save_workspace + ".nxs") else: # Save normally using SaveNexusProcessed - SaveNexusProcessed(InputWorkspace=workspace_name, Filename=place_to_save_workspace) + SaveNexusProcessed(InputWorkspace=workspace_name, Filename=place_to_save_workspace + ".nxs") self.output_list.append(workspace_name) -- GitLab