Skip to content

Commit

Permalink
Improve upgrade (robotframework#2898)
Browse files Browse the repository at this point in the history
* Fix unit tests for upgrade

* Improve restart dialogs
  • Loading branch information
HelioGuilherme66 authored Oct 9, 2024
1 parent f824649 commit 29929a6
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Likewise, the current version of wxPython, is 4.2.2, but RIDE is known to work w

`pip install -U robotframework-ride`

(3.8 <= python <= 3.12) Install current development version (**2.1dev87**) with:
(3.8 <= python <= 3.12) Install current development version (**2.1dev88**) with:

`pip install -U https://github.com/robotframework/RIDE/archive/master.zip`

Expand Down
27 changes: 15 additions & 12 deletions src/robotide/application/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import builtins
import os
from csv import excel

import wx
from contextlib import contextmanager
from pathlib import Path
Expand Down Expand Up @@ -332,24 +334,25 @@ def change_locale(self, message):
self._locale.AddCatalog('RIDE')
if len(message.keys) > 1: # Avoid initial setting
from multiprocessing import shared_memory
from .restartutil import restart_dialog
from .restartutil import do_restart
new_locale = self._locale.GetName()
# print(f"DEBUG: application.py RIDE change_locale from {initial_locale} to {new_locale}")
if initial_locale != new_locale:
if restart_dialog(): # DEBUG: See the in implementation why we don't restart
# print("DEBUG: application.py RIDE change_locale Restart accepted.")
# Shared memory to store language definition
#if restart_dialog(): # DEBUG: See the in implementation why we don't restart
# print("DEBUG: application.py RIDE change_locale Restart accepted.")
# Shared memory to store language definition
try:
sharemem = shared_memory.ShareableList(['en'], name="language")
except FileExistsError: # Other instance created file
sharemem = shared_memory.ShareableList(name="language")
result = do_restart()
if result:
try:
sharemem = shared_memory.ShareableList(['en'], name="language")
except FileExistsError: # Other instance created file
sharemem = shared_memory.ShareableList(name="language")
finally:
sharemem.shm.close()
sharemem.shm.unlink()
# wx.CallAfter(self.ExitMainLoop)
# wx.CallLater(1000, self.Destroy)
wx.CallLater(1000, self.ExitMainLoop)
# self.DeletePendingEvents()
except FileNotFoundError:
pass


@staticmethod
def update_excludes(message):
Expand Down
24 changes: 11 additions & 13 deletions src/robotide/application/restartutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@


def restart_dialog():
if not _askyesno(
_("Re-open RIDE for Language Change"),
if not _askyesno(_("Re-open RIDE for Language Change"),
f"{SPC}{_('Language change will only be correct after re-opening RIDE.')}"
f"{SPC}\n{SPC}{_('Do you want to CLOSE RIDE now?')}\n{SPC}"
# f"{_('After restarting RIDE you will see another dialog informing to close this RIDE instance.')}"
Expand All @@ -41,16 +40,15 @@ def restart_dialog():

def do_restart():
my_pid = psutil.Process()
command = sys.executable + " -m robotide.__init__ --noupdatecheck"
# DEBUG: The starting of new RIDE instance with subsequent closing of this instance,
# makes problems in editing the current file, and even opening new file. Because of
# this, the restarting is disabled, until someone finds a good way to clean-up memory.
# wx.CallLater(100, subprocess.Popen, command.split(' '), start_new_session=True)
# Wait 10 seconds before trying to kill this process
""" Not working well:
wx.CallLater(10000, psutil.Process.kill, my_pid.pid)
"""
wx.CallLater(5000, _askyesno, _("Completed Language Change"),
f"\n{SPC}{_('You should close this RIDE (Process ID = ')}{my_pid.pid}){SPC}",
wx.GetActiveWindow())

# this, the restarting was disabled, until someone finds a good way to clean-up memory.
command = sys.executable + " -m robotide.__init__ --noupdatecheck"
wx.CallLater(500, subprocess.Popen, command.split(' '), start_new_session=True)
result = _askyesno(_("Completed Language Change"),
f"\n{SPC}{_('You should close this RIDE (Process ID = ')}{my_pid.pid}){SPC}"
f"\n{SPC}{_('Do you want to CLOSE RIDE now?')}\n{SPC}",
wx.GetActiveWindow())
if result:
wx.CallLater(1000, wx.App.Get().GetTopWindow().Close)
return True
15 changes: 8 additions & 7 deletions src/robotide/application/updatenotifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ..utils.versioncomparator import cmp_versions, parse_version
from ..widgets import ButtonWithHandler, HtmlWindow, RIDEDialog
from ..postinstall import MessageDialog
from ..publish import PUBLISHER, RideRunnerStarted, RideRunnerStopped
from ..publish import PUBLISHER, RideRunnerStopped

_ = wx.GetTranslation # To keep linter/code analyser happy
builtins.__dict__['_'] = wx.GetTranslation
Expand Down Expand Up @@ -164,7 +164,6 @@ def do_upgrade(command, notebook):
config = RunnerCommand('Upgrade RIDE', command, 'Uses pip to upgrade RIDE.')
PUBLISHER.subscribe(start_upgraded, RideRunnerStopped)
result = ui.Runner(config, notebook).run()
# result = 0
time.sleep(10)
if result == -1:
_askyesno(_("Failed to Upgrade"), f"{SPC}{_('An error occurred when installing new version')}",
Expand All @@ -173,15 +172,17 @@ def do_upgrade(command, notebook):


def start_upgraded(message):
__ = message
command = sys.executable + " -m robotide.__init__ --noupdatecheck"
wx.CallLater(500, subprocess.Popen, command.split(' '), start_new_session=True)
pid = psutil.Process.pid
result = _askyesno(_("Completed Upgrade"), f"\n{SPC}{_('You should close this RIDE (Process ID = ')}{pid}){SPC}",
p = psutil.Process()
result = _askyesno(_("Completed Upgrade"), f"\n{SPC}{_('You should close this RIDE (Process ID = ')}{p.pid}){SPC}"
f"\n{SPC}{_('Do you want to CLOSE RIDE now?')}\n{SPC}",
wx.GetActiveWindow())
PUBLISHER.unsubscribe(start_upgraded, RideRunnerStopped)
if result:
time.sleep(10)
wx.App.Get().OnExit()
wx.CallAfter(wx.App.Get().GetTopWindow().Close)
# wx.CallAfter(p.terminate)


class LocalHtmlWindow(HtmlWindow):
Expand Down Expand Up @@ -258,5 +259,5 @@ def on_checkbox_change(self, event):
def on_upgrade_now(self, event):
__ = event
_add_content_to_clipboard(self._command)
self.Hide()
self.Close()
do_upgrade(self._command, self._notebook)
2 changes: 1 addition & 1 deletion src/robotide/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
#
# Automatically generated by `tasks.py`.

VERSION = 'v2.1dev87'
VERSION = 'v2.1dev88'
51 changes: 29 additions & 22 deletions utest/application/test_updatenotifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class UpdateNotifierTestCase(unittest.TestCase):

def setUp(self):
self._callback_called = False
self._version = None
self._newest_version = None
self._url = None
self.app = MyApp()
settings = self.app.settings
Expand Down Expand Up @@ -141,18 +141,25 @@ def _callback(self, version, url, settings, notebook):
__ = notebook
self.assertFalse(self._callback_called)
self._callback_called = True
self.assertNotEqual(None, version)
self._version = version
self.assertNotEqual(None, url)
self.assertIsNotNone(version)
self._newest_version = version
self.assertIsNotNone(url)
self._url = url
self.assertEqual(dict, type(settings))

@staticmethod
def _update_notifier_controller(settings, notebook, current, new, url='some url'):
ctrl = UpdateNotifierController(settings, notebook)
ctrl.VERSION = current
ctrl._get_newest_version = lambda: new
ctrl._get_download_url = lambda v: url if v == new else None
def _new():
return new
ctrl._get_newest_version = _new
def _url():
return url
ctrl._get_download_url = _url
def _null():
return None
ctrl._get_rf_pypi_data = _null
return ctrl

@staticmethod
Expand All @@ -165,11 +172,11 @@ def test_normal_update(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0', '1', 'http://xyz.abc.efg.di')
ctrl.notify_update_if_needed(self._callback)
self.assertEqual('1', self._version)
self.assertEqual('http://xyz.abc.efg.di', self._url)
self.assertTrue(self._callback_called)
self.assertEqual('1', self._newest_version)
self.assertEqual('http://xyz.abc.efg.di', self._url)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
# Uncomment next lines if you want to see the app
# wx.CallLater(5000, self.app.ExitMainLoop)
# self.app.MainLoop()
Expand All @@ -179,9 +186,9 @@ def test_update_when_trunk_version(self):
ctrl = self._update_notifier_controller(settings, self.notebook, '2.0', '2.0.1')
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(self._callback_called)
self.assertEqual('2.0.1', self._version)
self.assertEqual('2.0.1', self._newest_version)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)

def test_last_update_done_less_than_a_week_ago(self):
original_time = time.time() - 60 * 60 * 24 * 3
Expand All @@ -205,14 +212,14 @@ def test_no_update_found(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.55', '0.55')
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertFalse(self._callback_called)

def test_no_update_found_dev(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.56', '0.56')
ctrl.notify_update_if_needed(self._callback, ignore_check_condition=False, show_no_update=False)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertFalse(self._callback_called)

def test_no_update_found_dev_notify(self):
Expand All @@ -225,15 +232,15 @@ def test_first_run_sets_settings_correctly_and_checks_for_updates(self):
settings = self.internal_settings(check_for_updates=None, last_update_check=None)
ctrl = self._update_notifier_controller(settings, self.notebook,'1.0.2', '1.0.2')
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertFalse(self._callback_called)

def test_first_run_sets_settings_correctly_and_finds_an_update(self):
settings = self.internal_settings(check_for_updates=None, last_update_check=None)
ctrl = self._update_notifier_controller(settings, self.notebook, '1.2', '2.0')
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertTrue(self._callback_called)

Expand All @@ -246,7 +253,7 @@ def throw_timeout_error():

ctrl._get_newest_version = throw_timeout_error
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 10) # The dialog timeout in 10 seconds
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 10) # The dialog timeout in 10 seconds
self.assertFalse(self._callback_called)

def test_download_url_checking_timeouts(self):
Expand All @@ -261,46 +268,46 @@ def throw_timeout_error(*args):

ctrl._get_download_url = throw_timeout_error
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertFalse(self._callback_called)

def test_server_returns_no_versions(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '1.2.2', None)
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertFalse(self._callback_called)

def test_server_returns_older_version(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.44', '0.43.1')
ctrl.notify_update_if_needed(self._callback)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 1)
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 1)
self.assertTrue(settings[CHECKFORUPDATES])
self.assertFalse(self._callback_called)

def test_forced_check_released(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.43.0', '0.43.1')
ctrl.notify_update_if_needed(self._callback, ignore_check_condition=True)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 19) # The dialog timeout in 20 seconds
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 19) # The dialog timeout in 20 seconds
self.assertTrue(settings[CHECKFORUPDATES])
self.assertTrue(self._callback_called)

def test_forced_check_development(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.44dev12', '0.44.dev14')
ctrl.notify_update_if_needed(self._callback, ignore_check_condition=True)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 20) # The dialog timeout in 20 seconds
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 20) # The dialog timeout in 20 seconds
self.assertTrue(settings[CHECKFORUPDATES])
self.assertTrue(self._callback_called)

def test_forced_check_development_ok(self):
settings = self.internal_settings()
ctrl = self._update_notifier_controller(settings, self.notebook, '0.44dev12', '0.44.dev12')
ctrl.notify_update_if_needed(self._callback, ignore_check_condition=False)
self.assertTrue(settings[LASTUPDATECHECK] > time.time() - 20) # The dialog timeout in 20 seconds
self.assertGreater(settings[LASTUPDATECHECK], time.time() - 20) # The dialog timeout in 20 seconds
self.assertTrue(settings[CHECKFORUPDATES])
self.assertFalse(self._callback_called)

Expand Down

0 comments on commit 29929a6

Please sign in to comment.