No longer remove failed add-ons installs and warn when add-on installs, removals and updates cannot complete#15937
Conversation
This reverts commit 81e17be.
… no longer existing pending installation entries.
|
See test results for failed build of commit 01bb1c5b70 |
|
Thanks for your review @seanbudd @CyrilleB79 ! I believe all your points are now addressed. |
CyrilleB79
left a comment
There was a problem hiding this comment.
LGTM globally. Many thanks for this!
I have made various failing tests for the 3 cases (keep folder open in Explorer, create a file with the same name as the folder to be created, etc.). The UX is as expected.
I have just added suggestions about GUI phrasing or variable names.
| "Some operations on add-ons failed. See the log file for more details.\n{}" | ||
| ).format("\n".join(addonFailureMessages)), | ||
| # Translators: Title of message shown when requested action on add-ons failed. | ||
| _("Add-on failures"), |
There was a problem hiding this comment.
It's not the add-on is failing, it's its install/removal process.
A simpler title would be enough IMO.
| _("Add-on failures"), | |
| _("Error"), |
| _shuttingDownFlagLock = threading.Lock() | ||
|
|
||
|
|
||
| def _showAddonsWarnings() -> None: |
There was a problem hiding this comment.
Since we are displaying an error message:
| def _showAddonsWarnings() -> None: | |
| def _showAddonsUpdateErrors() -> None: |
or only:
| def _showAddonsWarnings() -> None: | |
| def _showAddonsErrors() -> None: |
| addonFailureMessages.append( | ||
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to update. | ||
| "The following add-on failed to update: {}", |
There was a problem hiding this comment.
Add end of sentence period. It's better when reading the whole dialog (NVDA+B) and various such messages are concatenated.
| "The following add-on failed to update: {}", | |
| "The following add-on failed to update: {}.", |
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to update. | ||
| "The following add-on failed to update: {}", | ||
| "The following add-ons failed to update: {}", |
| addonFailureMessages.append( | ||
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to be uninstalled. | ||
| "The following add-on failed to uninstall: {}", |
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to be uninstalled. | ||
| "The following add-on failed to uninstall: {}", | ||
| "The following add-ons failed to uninstall: {}", |
| addonFailureMessages.append( | ||
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to be installed. | ||
| "The following add-on failed to be installed: {}", |
| ngettext( | ||
| # Translators: Shown when one or more add-ons failed to be installed. | ||
| "The following add-on failed to be installed: {}", | ||
| "The following add-ons failed to be installed: {}", |
…tween add-ons (#15967) Fixes regression from PR #14481. Discovered due to intermittent failures occurring when installing add-ons, when working on #15852 and #15937 Summary of the issue: When installing and uninstalling add-ons bundling install tasks, installation either fails or behaves unexpectedly in the following scenarios: 1: User installs an add-on User removes it and restarts NVDA User tries to install the same add-on In this scenario when installing the install tasks included in the version of add-on which was just removed are used, which is unexpected. Note that this worked well before #14481, not sure why pkgutil.ImpImporter behaves better (I haven't investigated, as it is deprecated). 2: User installs an add-on, which imports its sub module in install tasks using loadModule and also imports a sub module in the same way inside global plugin / app module during normal operation User upgrades the add-on to a different version In this scenario after upgrade the add-on module from the uninstalled version is used during normal operation of NVDA. 3: User installs an add-on which imports one of its modules in install tasks by manipulating sys.path, for real life examples see Instant Translate and Mouse Wheel Scrolling User uninstalls this add-on, restarts NVDA, and tries to install the new version In this scenario installation fails since the imported module from the old version is used. A slight variation of this scenario is to try to install both Instant Translate and Mouse Wheel Scrolling the add-on installed last would fail to be installed, since they both bundle module named donate_dialog but with different functions Description of user facing changes Add-ons are successfully installed in all scenarios described above. Description of development approach All these problems exist because when importing modules in Python if module with the same name exists in sys.modules it is just used without importing it again. To ensure modules are always re-imported when needed, the following has been done: When importing modules we no longer use add-on name to create a name space package in which the module would be imported, the last segment of the add-on path is used instead. This ensures that the package for add-on which is installed would just be its name, and for add-on which is pending install it would end with the pending install suffix. This fixes issue 1. loadModule memorizes all modules it imported for a given add-on. After installation / removal is done they're removed from sys.modules. This fixes issue 2. To remove cached modules imported with the standard import command, we store names of all modules imported before installation / removal, perform it, create list of newly imported modules and remove all newly added modules which belong to the add-on from the cache. This fixes issue 3.
…tween add-ons (nvaccess#15967) Fixes regression from PR nvaccess#14481. Discovered due to intermittent failures occurring when installing add-ons, when working on nvaccess#15852 and nvaccess#15937 Summary of the issue: When installing and uninstalling add-ons bundling install tasks, installation either fails or behaves unexpectedly in the following scenarios: 1: User installs an add-on User removes it and restarts NVDA User tries to install the same add-on In this scenario when installing the install tasks included in the version of add-on which was just removed are used, which is unexpected. Note that this worked well before nvaccess#14481, not sure why pkgutil.ImpImporter behaves better (I haven't investigated, as it is deprecated). 2: User installs an add-on, which imports its sub module in install tasks using loadModule and also imports a sub module in the same way inside global plugin / app module during normal operation User upgrades the add-on to a different version In this scenario after upgrade the add-on module from the uninstalled version is used during normal operation of NVDA. 3: User installs an add-on which imports one of its modules in install tasks by manipulating sys.path, for real life examples see Instant Translate and Mouse Wheel Scrolling User uninstalls this add-on, restarts NVDA, and tries to install the new version In this scenario installation fails since the imported module from the old version is used. A slight variation of this scenario is to try to install both Instant Translate and Mouse Wheel Scrolling the add-on installed last would fail to be installed, since they both bundle module named donate_dialog but with different functions Description of user facing changes Add-ons are successfully installed in all scenarios described above. Description of development approach All these problems exist because when importing modules in Python if module with the same name exists in sys.modules it is just used without importing it again. To ensure modules are always re-imported when needed, the following has been done: When importing modules we no longer use add-on name to create a name space package in which the module would be imported, the last segment of the add-on path is used instead. This ensures that the package for add-on which is installed would just be its name, and for add-on which is pending install it would end with the pending install suffix. This fixes issue 1. loadModule memorizes all modules it imported for a given add-on. After installation / removal is done they're removed from sys.modules. This fixes issue 2. To remove cached modules imported with the standard import command, we store names of all modules imported before installation / removal, perform it, create list of newly imported modules and remove all newly added modules which belong to the add-on from the cache. This fixes issue 3.
…tween add-ons (nvaccess#15967) Fixes regression from PR nvaccess#14481. Discovered due to intermittent failures occurring when installing add-ons, when working on nvaccess#15852 and nvaccess#15937 Summary of the issue: When installing and uninstalling add-ons bundling install tasks, installation either fails or behaves unexpectedly in the following scenarios: 1: User installs an add-on User removes it and restarts NVDA User tries to install the same add-on In this scenario when installing the install tasks included in the version of add-on which was just removed are used, which is unexpected. Note that this worked well before nvaccess#14481, not sure why pkgutil.ImpImporter behaves better (I haven't investigated, as it is deprecated). 2: User installs an add-on, which imports its sub module in install tasks using loadModule and also imports a sub module in the same way inside global plugin / app module during normal operation User upgrades the add-on to a different version In this scenario after upgrade the add-on module from the uninstalled version is used during normal operation of NVDA. 3: User installs an add-on which imports one of its modules in install tasks by manipulating sys.path, for real life examples see Instant Translate and Mouse Wheel Scrolling User uninstalls this add-on, restarts NVDA, and tries to install the new version In this scenario installation fails since the imported module from the old version is used. A slight variation of this scenario is to try to install both Instant Translate and Mouse Wheel Scrolling the add-on installed last would fail to be installed, since they both bundle module named donate_dialog but with different functions Description of user facing changes Add-ons are successfully installed in all scenarios described above. Description of development approach All these problems exist because when importing modules in Python if module with the same name exists in sys.modules it is just used without importing it again. To ensure modules are always re-imported when needed, the following has been done: When importing modules we no longer use add-on name to create a name space package in which the module would be imported, the last segment of the add-on path is used instead. This ensures that the package for add-on which is installed would just be its name, and for add-on which is pending install it would end with the pending install suffix. This fixes issue 1. loadModule memorizes all modules it imported for a given add-on. After installation / removal is done they're removed from sys.modules. This fixes issue 2. To remove cached modules imported with the standard import command, we store names of all modules imported before installation / removal, perform it, create list of newly imported modules and remove all newly added modules which belong to the add-on from the cache. This fixes issue 3.
…s, removals and updates cannot complete (nvaccess#15937) Reverts nvaccess#15921 Closes nvaccess#12823 Addresses the most likely cause of nvaccess#15719 Hopefully fixes nvaccess#15927 Summary of the issue: PR nvaccess#15921 started removing all add-ons which failed to be installed without showing warnings to the user. Users generally expect NVDA to attempt installation / removal of add-ons on the next restart if they failed, to have a warning when one of these operations didn't succeed and not to be able to install add-on which is not fully removed from Add-ons Store. Description of user facing changes When one or more add-ons fails to be updated, uninstalled or installed, NVDA shows an appropriate warning on startup. Installation / removal is attempted on the next restart. When add-on is pending remove it is shown in the Add-ons Store along with the 'pending remove' status. All add-ons which are no longer present on disk are removed from the list of pending installs to hopefully improve nvaccess#15719. Description of development approach NVDA stores add-ons whose installation / removal failed in a list. All these add-ons are not loaded ,but shown in the Add-ons Store. These lists are used to determine what warnings should be shown to the user. List of pending installs is cleaned-up from add-ons which are no longer present on disk, excluding these which failed to be installed, as their install is going to be attempted on the next restart.
…tween add-ons (nvaccess#15967) Fixes regression from PR nvaccess#14481. Discovered due to intermittent failures occurring when installing add-ons, when working on nvaccess#15852 and nvaccess#15937 Summary of the issue: When installing and uninstalling add-ons bundling install tasks, installation either fails or behaves unexpectedly in the following scenarios: 1: User installs an add-on User removes it and restarts NVDA User tries to install the same add-on In this scenario when installing the install tasks included in the version of add-on which was just removed are used, which is unexpected. Note that this worked well before nvaccess#14481, not sure why pkgutil.ImpImporter behaves better (I haven't investigated, as it is deprecated). 2: User installs an add-on, which imports its sub module in install tasks using loadModule and also imports a sub module in the same way inside global plugin / app module during normal operation User upgrades the add-on to a different version In this scenario after upgrade the add-on module from the uninstalled version is used during normal operation of NVDA. 3: User installs an add-on which imports one of its modules in install tasks by manipulating sys.path, for real life examples see Instant Translate and Mouse Wheel Scrolling User uninstalls this add-on, restarts NVDA, and tries to install the new version In this scenario installation fails since the imported module from the old version is used. A slight variation of this scenario is to try to install both Instant Translate and Mouse Wheel Scrolling the add-on installed last would fail to be installed, since they both bundle module named donate_dialog but with different functions Description of user facing changes Add-ons are successfully installed in all scenarios described above. Description of development approach All these problems exist because when importing modules in Python if module with the same name exists in sys.modules it is just used without importing it again. To ensure modules are always re-imported when needed, the following has been done: When importing modules we no longer use add-on name to create a name space package in which the module would be imported, the last segment of the add-on path is used instead. This ensures that the package for add-on which is installed would just be its name, and for add-on which is pending install it would end with the pending install suffix. This fixes issue 1. loadModule memorizes all modules it imported for a given add-on. After installation / removal is done they're removed from sys.modules. This fixes issue 2. To remove cached modules imported with the standard import command, we store names of all modules imported before installation / removal, perform it, create list of newly imported modules and remove all newly added modules which belong to the add-on from the cache. This fixes issue 3.
Link to issue number:
Reverts #15921
Closes #12823
Addresses the most likely cause of #15719
Hopefully fixes #15927
Summary of the issue:
PR #15921 started removing all add-ons which failed to be installed without showing warnings to the user. Users generally expect NVDA to attempt installation / removal of add-ons on the next restart if they failed, to have a warning when one of these operations didn't succeed and not to be able to install add-on which is not fully removed from Add-ons Store.
Description of user facing changes
When one or more add-ons fails to be updated, uninstalled or installed, NVDA shows an appropriate warning on startup. Installation / removal is attempted on the next restart. When add-on is pending remove it is shown in the Add-ons Store along with the 'pending remove' status. All add-ons which are no longer present on disk are removed from the list of pending installs to hopefully improve #15719.
Description of development approach
NVDA stores add-ons whose installation / removal failed in a list. All these add-ons are not loaded ,but shown in the Add-ons Store. These lists are used to determine what warnings should be shown to the user. List of pending installs is cleaned-up from add-ons which are no longer present on disk, excluding these which failed to be installed, as their install is going to be attempted on the next restart.
Testing strategy:
Known issues with pull request:
None known
Code Review Checklist: