Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f34cf70
Update icons.py
jnsebgosselin Jul 31, 2023
804a633
Create updates.py
jnsebgosselin Jul 31, 2023
e341ed7
Setup update manager in mainwindow
jnsebgosselin Aug 2, 2023
b23f01e
Reorder actions in menu
jnsebgosselin Aug 2, 2023
bcda1ce
Add update icons
jnsebgosselin Aug 2, 2023
281bf60
Add a startup_check mode
jnsebgosselin Aug 2, 2023
e02f624
Check for updates on startup
jnsebgosselin Aug 2, 2023
03ed91b
Improve muted update logic
jnsebgosselin Aug 2, 2023
43cd3ca
Remove the 'v' from release tag
jnsebgosselin Aug 3, 2023
adf2827
Complete missing typehints and type checking
jnsebgosselin Aug 10, 2023
9d8aff3
Complete missing typehint
jnsebgosselin Aug 10, 2023
b2384f6
Fix deprecated distutils.version usage
jnsebgosselin Aug 10, 2023
03a64ff
Use custom more meaningfull icons in messagebox
jnsebgosselin Aug 10, 2023
9ece1f5
Update file header
jnsebgosselin Aug 10, 2023
a062d36
SardesPlugin: make sure show_plugin is protected when dockwindow is None
jnsebgosselin Aug 10, 2023
6b7252f
Fix wrong docstring
jnsebgosselin Aug 11, 2023
ff9f0e2
Move updates module to app
jnsebgosselin Aug 11, 2023
dc9f6f6
Rework code to make testing easier
jnsebgosselin Aug 11, 2023
c402d95
Remove not needed WorkerUpdates __init__
jnsebgosselin Aug 11, 2023
b91a7af
Make sure latest release is always returned
jnsebgosselin Aug 11, 2023
f06624f
Simplify some variable names
jnsebgosselin Aug 11, 2023
f3efce8
Update updates.py
jnsebgosselin Aug 11, 2023
b292226
Create test_updates.py
jnsebgosselin Aug 12, 2023
f381cde
Rework test_update_available for modal dialog
jnsebgosselin Aug 12, 2023
75f3dd3
Complete test_no_update_available
jnsebgosselin Aug 12, 2023
1c455b6
Complete test_update_error
jnsebgosselin Aug 12, 2023
fc7ba54
Cleanup code
jnsebgosselin Aug 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions sardes/api/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,11 @@ def show_plugin(self):

This method is called by the mainwindow after it is shown.
"""
is_visible = self.get_option('is_visible', False)
is_docked = self.get_option('is_docked', True)
if is_visible and not is_docked:
self.dockwindow.undock()
if self.dockwindow is not None:
is_visible = self.get_option('is_visible', False)
is_docked = self.get_option('is_docked', True)
if is_visible and not is_docked:
self.dockwindow.undock()

def close_plugin(self):
"""
Expand Down
36 changes: 25 additions & 11 deletions sardes/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ def __init__(self, splash=None, sys_capture_manager=None):
self.db_connection_manager)
print("Table models manager set up succesfully.")

# Setup the update manager.
from sardes.app.updates import UpdatesManager
self.updates_manager = UpdatesManager(parent=self)

self.setup()

def set_splash(self, message):
Expand Down Expand Up @@ -262,6 +266,15 @@ class Separator(object):
triggered=self.confdialog.show
)

# Create show console action.
self.console_action = None
if self.console is not None:
self.console_action = create_action(
self, _('Sardes Console...'), icon='console',
shortcut='Ctrl+Shift+J', context=Qt.ApplicationShortcut,
triggered=self.console.show
)

# Create the panes and toolbars menus and actions
self.panes_menu = QMenu(_("Panes"), self)
self.panes_menu.setIcon(get_icon('panes'))
Expand All @@ -282,13 +295,6 @@ class Separator(object):
triggered=self.reset_window_layout)

# Create help related actions and menus.
self.console_action = None
if self.console is not None:
self.console_action = create_action(
self, _('Sardes Console...'), icon='console',
shortcut='Ctrl+Shift+J', context=Qt.ApplicationShortcut,
triggered=self.console.show
)
report_action = create_action(
self, _('Report an issue...'), icon='bug',
shortcut='Ctrl+Shift+R', context=Qt.ApplicationShortcut,
Expand All @@ -299,18 +305,23 @@ class Separator(object):
shortcut='Ctrl+Shift+I',
context=Qt.ApplicationShortcut
)
update_action = create_action(
self, _('Check for updates...'), icon='update',
triggered=lambda: self.updates_manager.start_updates_check()
)
exit_action = create_action(
self, _('Exit'), icon='exit', triggered=self.close,
shortcut='Ctrl+Shift+Q', context=Qt.ApplicationShortcut
)

# Add the actions and menus to the options menu.
options_menu_items = [
self.lang_menu, preferences_action, Separator(),
self.panes_menu, self.toolbars_menu,
self.lang_menu, preferences_action, self.console_action,
Separator(), self.panes_menu, self.toolbars_menu,
self.lock_dockwidgets_and_toolbars_action,
self.reset_window_layout_action, Separator(),
self.console_action, report_action, about_action, exit_action
report_action, update_action, about_action,
Separator(), exit_action
]
for item in options_menu_items:
if isinstance(item, Separator):
Expand Down Expand Up @@ -602,7 +613,8 @@ def setup_internal_plugins(self):

def show(self):
"""
Extend Qt method to call show_plugin on each installed plugin.
Extend base class method to perform specific actions of certain
plugins after the mainwindow has been shown.
"""
super().show()

Expand All @@ -613,6 +625,8 @@ def show(self):
if self.databases_plugin.get_option('auto_connect_to_database'):
self.databases_plugin.connect_to_database()

self.updates_manager.start_updates_check(startup_check=True)


class ExceptHook(QObject):
"""
Expand Down
134 changes: 134 additions & 0 deletions sardes/app/tests/test_updates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright © GWHAT Project Contributors
# https://github.com/jnsebgosselin/gwhat
#
# This file is part of GWHAT (Ground-Water Hydrograph Analysis Toolbox).
# Licensed under the terms of the GNU General Public License.
# -----------------------------------------------------------------------------

# ---- Standard imports
import os
os.environ['SARDES_PYTEST'] = 'True'

# ---- Third parties imports
import pytest
from qtpy.QtCore import QTimer

# ---- Local imports
from sardes.app.updates import UpdatesManager
from sardes.config.main import CONF


# =============================================================================
# ---- Fixtures
# =============================================================================
@pytest.fixture
def updates_manager(qtbot):
CONF.reset_to_defaults()
updates_manager = UpdatesManager()
assert updates_manager.dialog.isVisible() is False
yield updates_manager

# To avoid: Thread: Destroyed while thread is still running.
qtbot.wait(300)


# =============================================================================
# ---- Tests
# =============================================================================
def test_update_available(updates_manager, qtbot, mocker):
"""
Assert that the worker to check for updates on the GitHub API is
working as expected when an update is available.

Note that since we are forcing the current version to a not stable version,
the '1.1.0rc2 update should be proposed to the user.
"""
mocker.patch('sardes.app.updates.__version__', '1.1.0rc1')
mocker.patch(
'sardes.app.updates.fetch_available_releases',
return_value=(['0.9.0', '1.1.0rc2', '1.0.0'], None)
)

def handle_dialog(on_startup: bool):
assert updates_manager.dialog.isVisible() is True
assert updates_manager.dialog.chkbox.isVisible() == on_startup
assert 'Sardes 1.1.0rc2 is available!' in updates_manager.dialog.text()
updates_manager.dialog.close()

with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
QTimer.singleShot(300, lambda: handle_dialog(on_startup=False))
updates_manager.start_updates_check()

# Test that this is working also as expected during STARTUP and mute
# the message on next startups.
with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
updates_manager.dialog.chkbox.setChecked(True)
QTimer.singleShot(300, lambda: handle_dialog(on_startup=True))
updates_manager.start_updates_check(startup_check=True)

# Assert the update is muted as expected.
with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
updates_manager.start_updates_check(startup_check=True)
assert updates_manager.dialog.isVisible() is False


def test_no_update_available(updates_manager, qtbot, mocker):
"""
Assert that the worker to check for updates on the GitHub API is
working as expected when no update is available.

Note that since we are forcing the current version to a stable version,
the '1.1.0rc2 update should be proposed to the user.
"""
mocker.patch('sardes.app.updates.__version__', '1.1.0')
mocker.patch(
'sardes.app.updates.fetch_available_releases',
return_value=(['0.9.0', '1.1.0rc2', '1.0.0'], None)
)

def handle_dialog(on_startup: bool):
assert updates_manager.dialog.isVisible() is True
assert updates_manager.dialog.chkbox.isVisible() == on_startup
assert 'is up to date' in updates_manager.dialog.text()
updates_manager.dialog.close()

with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
QTimer.singleShot(300, lambda: handle_dialog(on_startup=False))
updates_manager.start_updates_check()

# Test that the 'up-to-date' message is not shown during STARTUP.
with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
updates_manager.start_updates_check(startup_check=True)
assert updates_manager.dialog.isVisible() is False


def test_update_error(updates_manager, qtbot, mocker):
"""
Assert that the worker to check for updates on the GitHub API is
working as expected when there is an error.
"""
mocker.patch(
'sardes.app.updates.fetch_available_releases',
return_value=(['0.9.0', '1.1.0rc2', '1.0.0'], 'some error')
)

def handle_dialog(on_startup: bool):
assert updates_manager.dialog.isVisible() is True
assert updates_manager.dialog.chkbox.isVisible() == on_startup
assert 'some error' in updates_manager.dialog.text()
updates_manager.dialog.close()

with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
QTimer.singleShot(300, lambda: handle_dialog(on_startup=False))
updates_manager.start_updates_check()

# Test that the error message is not shown during STARTUP.
with qtbot.waitSignal(updates_manager.worker.sig_releases_fetched):
updates_manager.start_updates_check(startup_check=True)
assert updates_manager.dialog.isVisible() is False


if __name__ == "__main__":
pytest.main(['-x', __file__, '-v', '-rw'])
Loading