Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve upgrade #2898

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading