Skip to content

Commit

Permalink
Backup only at replacement, warn user on replacement
Browse files Browse the repository at this point in the history
  • Loading branch information
Marilyth committed May 31, 2021
1 parent 7727b6b commit 4e200a4
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 125 deletions.
124 changes: 36 additions & 88 deletions mslib/msui/_tests/test_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,27 @@
from mslib import __version__


class SubprocessVersionMock:
def __init__(self):
self.stdout = "*mss 999.999.999\n"
class SubprocessDifferentVersionMock:
def __init__(self, args=None, **named_args):
self.returncode = 0
self.args = args
if args and "list" in args and "mss" in args:
self.stdout = "*mss 0.0.0\n"
else:
self.stdout = "*mss 999.999.999\n"


class SubprocessSameMock:
def __init__(self):
self.stdout = f"*mss {__version__}\n"
def __init__(self, args=None, **named_args):
self.stdout = f"*mss 999.999.999\n"
self.returncode = 0
self.args = args


class SubprocessGitMock:
def __init__(self):
def __init__(self, args=None, **named_args):
self.stdout = "true"
self.args = args


def create_mock(function, on_success=None, on_failure=None, start=True):
Expand All @@ -70,110 +76,54 @@ def teardown(self):
self.application.quit()
QtWidgets.QApplication.processEvents()

@mock.patch("subprocess.run", return_value=SubprocessVersionMock())
@mock.patch("subprocess.Popen", new=SubprocessDifferentVersionMock)
@mock.patch("subprocess.run", new=SubprocessDifferentVersionMock)
@mock.patch("mslib.utils.Worker.create", create_mock)
def test_update_recognised(self, mock):
def test_update_recognised(self):
update_available = False
status = ""
progress = 0
finished = False

def status_changed(s):
nonlocal status
status = s

def progress_changed(value):
nonlocal progress
progress = value

def update_signal():
nonlocal update_available
update_available = True

def finished_signal():
nonlocal finished
finished = True

self.updater.on_status_update.connect(status_changed)
self.updater.on_update_finished.connect(finished_signal)
self.updater.on_progress_update.connect(progress_changed)
self.updater.on_update_available.connect(update_signal)
self.updater.run()

assert self.updater.new_version == "999.999.999"
assert update_available
self.updater.new_version = "0.0.0"

self.updater.update_mss()
assert self.updater.base_path == "999.999.999"
assert self.updater.current_path == "999.999.999"
assert progress == 100
assert finished
assert status == "Update finished. Please restart MSS."
assert self.updater.progressBar.value() == 100
assert self.updater.statusLabel.text() == "Update successful. Please restart MSS."

@mock.patch("subprocess.run", return_value=SubprocessSameMock())
@mock.patch("subprocess.Popen", new=SubprocessSameMock)
@mock.patch("subprocess.run", new=SubprocessSameMock)
@mock.patch("mslib.utils.Worker.create", create_mock)
def test_no_update(self, mock):
update_available = False
status = ""

def update_signal():
nonlocal update_available
update_available = True

def status_changed(s):
nonlocal status
status = s

self.updater.on_update_available.connect(update_signal)
self.updater.on_status_update.connect(status_changed)
def test_no_update(self):
self.updater.run()
assert self.updater.statusLabel.text() == "Your MSS is up to date."

assert self.updater.new_version == __version__
assert not update_available
assert status == "Your MSS is up to date."

@mock.patch("subprocess.run", return_value=SubprocessGitMock())
@mock.patch("subprocess.Popen", new=SubprocessGitMock)
@mock.patch("subprocess.run", new=SubprocessGitMock)
@mock.patch("mslib.utils.Worker.create", create_mock)
def test_no_update_on_git(self, mock):
update_available = False

def update_signal():
nonlocal update_available
update_available = True

self.updater.on_update_available.connect(update_signal)
def test_no_update_on_git(self):
self.updater.run()

assert self.updater.new_version is None
assert not update_available
assert self.updater.statusLabel.text() == "Nothing to do"

@mock.patch("subprocess.run", return_value=SubprocessVersionMock())
@mock.patch("subprocess.Popen", new=SubprocessDifferentVersionMock)
@mock.patch("subprocess.run", new=SubprocessDifferentVersionMock)
@mock.patch("mslib.utils.Worker.create", create_mock)
def test_update_failed(self, mock):
def test_update_failed(self):
update_available = False
status = ""
progress = 0
finished = False

def status_changed(s):
nonlocal status
status = s

def progress_changed(value):
nonlocal progress
progress = value

def update_signal():
nonlocal update_available
update_available = True

def finished_signal():
nonlocal finished
finished = True

self.updater.on_status_update.connect(status_changed)
self.updater.on_update_finished.connect(finished_signal)
self.updater.on_progress_update.connect(progress_changed)
self.updater.on_update_available.connect(update_signal)
self.updater.run()

Expand All @@ -182,14 +132,12 @@ def finished_signal():
self.updater.new_version = "1000.1000.1000"

self.updater.update_mss()
assert progress == 45
assert not finished
assert status == "Update failed, please do it manually."

@mock.patch("subprocess.run", return_value=SubprocessVersionMock())
@mock.patch("shutil.copytree", return_value=None)
@mock.patch("shutil.rmtree", return_value=None)
def test_environment_replace(self, subprocess_mock, shutil1, shutil2):
self.updater.new_version = "999.999.999"
assert self.updater.statusLabel.text() == "Update failed. Please try it manually or " \
"try replacing the environment!"

@mock.patch("subprocess.Popen", new=SubprocessDifferentVersionMock)
@mock.patch("subprocess.run", new=SubprocessDifferentVersionMock)
def test_environment_replace(self):
self.updater.new_version = "0.0.0"
self.updater._set_base_env_path()
assert self.updater._try_environment_replace()
3 changes: 2 additions & 1 deletion mslib/msui/mss_pyui.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ def __init__(self, *args):
self.updater = Updater(self)
self.updater.on_update_available.connect(self.notify_on_update)
self.updater.run()
self.actionUpdater.triggered.connect(self.updater.show)

@staticmethod
def preload_wms(urls):
Expand Down Expand Up @@ -769,7 +770,7 @@ def notify_on_update(self, old, new):
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
QtWidgets.QMessageBox.No)
if ret == QtWidgets.QMessageBox.Yes:
self.updater.update_mss()
self.updater.show()


def main():
Expand Down
5 changes: 5 additions & 0 deletions mslib/msui/qt5/ui_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ def setupUi(self, MSSMainWindow):
self.actionLoadConfigurationFile.setObjectName("actionLoadConfigurationFile")
self.actionShortcuts = QtWidgets.QAction(MSSMainWindow)
self.actionShortcuts.setObjectName("actionShortcuts")
self.actionUpdater = QtWidgets.QAction(MSSMainWindow)
self.actionUpdater.setObjectName("actionUpdater")
self.menu_File.addAction(self.actionNewFlightTrack)
self.menu_File.addAction(self.actionOpenFlightTrack)
self.menu_File.addSeparator()
Expand All @@ -118,6 +120,7 @@ def setupUi(self, MSSMainWindow):
self.menu_Help.addAction(self.actionOnlineHelp)
self.menu_Help.addAction(self.actionAboutMSUI)
self.menu_Help.addAction(self.actionShortcuts)
self.menu_Help.addAction(self.actionUpdater)
self.menu_Mscolab.addAction(self.actionMscolabProjects)
self.menubar.addAction(self.menu_File.menuAction())
self.menubar.addAction(self.menu_View.menuAction())
Expand Down Expand Up @@ -171,3 +174,5 @@ def retranslateUi(self, MSSMainWindow):
self.actionShortcuts.setText(_translate("MSSMainWindow", "Shortcuts"))
self.actionShortcuts.setToolTip(_translate("MSSMainWindow", "Show Current Shortcuts"))
self.actionShortcuts.setShortcut(_translate("MSSMainWindow", "Alt+S"))
self.actionUpdater.setText(_translate("MSSMainWindow", "Updater"))
self.actionUpdater.setToolTip(_translate("MSSMainWindow", "Open the Updater Dialog"))
50 changes: 48 additions & 2 deletions mslib/msui/qt5/ui_updater_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,70 @@
class Ui_Updater(object):
def setupUi(self, Updater):
Updater.setObjectName("Updater")
Updater.setWindowModality(QtCore.Qt.ApplicationModal)
Updater.setWindowModality(QtCore.Qt.NonModal)
Updater.resize(854, 353)
self.verticalLayout = QtWidgets.QVBoxLayout(Updater)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.labelVersion = QtWidgets.QLabel(Updater)
self.labelVersion.setObjectName("labelVersion")
self.horizontalLayout.addWidget(self.labelVersion)
self.btUpdate = QtWidgets.QPushButton(Updater)
self.btUpdate.setEnabled(False)
self.btUpdate.setObjectName("btUpdate")
self.horizontalLayout.addWidget(self.btUpdate)
self.btReplace = QtWidgets.QPushButton(Updater)
self.btReplace.setEnabled(False)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
brush = QtGui.QBrush(QtGui.QColor(190, 190, 190))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
self.btReplace.setPalette(palette)
self.btReplace.setObjectName("btReplace")
self.horizontalLayout.addWidget(self.btReplace)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.label = QtWidgets.QLabel(Updater)
self.label.setOpenExternalLinks(True)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.verticalLayout.addLayout(self.horizontalLayout)
self.statusLabel = QtWidgets.QLabel(Updater)
self.statusLabel.setObjectName("statusLabel")
self.verticalLayout.addWidget(self.statusLabel)
self.output = QtWidgets.QPlainTextEdit(Updater)
font = QtGui.QFont()
font.setFamily("Sans Serif")
font.setStyleStrategy(QtGui.QFont.PreferDefault)
self.output.setFont(font)
self.output.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap)
self.output.setReadOnly(True)
self.output.setPlainText("")
self.output.setCenterOnScroll(False)
self.output.setObjectName("output")
self.verticalLayout.addWidget(self.output)
self.progressBar = QtWidgets.QProgressBar(Updater)
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.verticalLayout.addWidget(self.progressBar)

self.retranslateUi(Updater)
QtCore.QMetaObject.connectSlotsByName(Updater)

def retranslateUi(self, Updater):
_translate = QtCore.QCoreApplication.translate
Updater.setWindowTitle(_translate("Updater", "Updater"))
self.statusLabel.setText(_translate("Updater", "Status"))
self.labelVersion.setText(_translate("Updater", "Newest Version: x.x.x"))
self.btUpdate.setText(_translate("Updater", "Update Current Environment"))
self.btReplace.setToolTip(_translate("Updater", "Closing MSS during this operation may break your environment!"))
self.btReplace.setText(_translate("Updater", "Replace Current Environment"))
self.label.setText(_translate("Updater", "<html><head/><body><p><a href=\"https://mss.readthedocs.io/en/stable/installation.html#install\"><span style=\" text-decoration: underline; color:#0000ff;\">Manual update instructions</span></a></p></body></html>"))
self.statusLabel.setText(_translate("Updater", "Nothing to do"))
self.progressBar.setFormat(_translate("Updater", "Installation Progress: %p%"))
9 changes: 9 additions & 0 deletions mslib/msui/ui/ui_mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Save a flight track to name it.</string>
<addaction name="actionOnlineHelp"/>
<addaction name="actionAboutMSUI"/>
<addaction name="actionShortcuts"/>
<addaction name="actionUpdater"/>
</widget>
<widget class="QMenu" name="menu_Mscolab">
<property name="title">
Expand Down Expand Up @@ -266,6 +267,14 @@ Save a flight track to name it.</string>
<string>Alt+S</string>
</property>
</action>
<action name="actionUpdater">
<property name="text">
<string>Updater</string>
</property>
<property name="toolTip">
<string>Open the Updater Dialog</string>
</property>
</action>
</widget>
<resources/>
<connections>
Expand Down
Loading

0 comments on commit 4e200a4

Please sign in to comment.