synodic-client 0.0.1.dev73__tar.gz → 0.0.1.dev74__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/PKG-INFO +1 -1
  2. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/pyproject.toml +1 -1
  3. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/update_controller.py +1 -1
  4. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/updater.py +6 -1
  5. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_updater.py +32 -0
  6. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/LICENSE.md +0 -0
  7. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/README.md +0 -0
  8. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/__init__.py +0 -0
  9. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/__main__.py +0 -0
  10. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/__init__.py +0 -0
  11. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/bootstrap.py +0 -0
  12. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/config_store.py +0 -0
  13. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/data.py +0 -0
  14. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/debug.py +0 -0
  15. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/icon.py +0 -0
  16. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/init.py +0 -0
  17. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/instance.py +0 -0
  18. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/package_state.py +0 -0
  19. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/qt.py +0 -0
  20. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/schema.py +0 -0
  21. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/__init__.py +0 -0
  22. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/action_card.py +0 -0
  23. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/card.py +0 -0
  24. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/install.py +0 -0
  25. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/install_workers.py +0 -0
  26. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/log_panel.py +0 -0
  27. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/plugin_row.py +0 -0
  28. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/projects.py +0 -0
  29. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/schema.py +0 -0
  30. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/screen.py +0 -0
  31. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/settings.py +0 -0
  32. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/sidebar.py +0 -0
  33. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/spinner.py +0 -0
  34. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/tool_update_controller.py +0 -0
  35. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/tray.py +0 -0
  36. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/screen/update_banner.py +0 -0
  37. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/theme.py +0 -0
  38. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/update_model.py +0 -0
  39. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/uri.py +0 -0
  40. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/application/workers.py +0 -0
  41. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/__init__.py +0 -0
  42. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/config.py +0 -0
  43. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/context.py +0 -0
  44. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/debug.py +0 -0
  45. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/output.py +0 -0
  46. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/project.py +0 -0
  47. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/tool.py +0 -0
  48. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/cli/update.py +0 -0
  49. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/client.py +0 -0
  50. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/config.py +0 -0
  51. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/logging.py +0 -0
  52. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/__init__.py +0 -0
  53. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/bootstrap.py +0 -0
  54. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/config.py +0 -0
  55. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/install.py +0 -0
  56. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/project.py +0 -0
  57. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/schema.py +0 -0
  58. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/tool.py +0 -0
  59. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/operations/update.py +0 -0
  60. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/protocol.py +0 -0
  61. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/py.typed +0 -0
  62. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/resolution.py +0 -0
  63. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/schema.py +0 -0
  64. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/startup.py +0 -0
  65. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/synodic_client/subprocess_patch.py +0 -0
  66. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/__init__.py +0 -0
  67. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/conftest.py +0 -0
  68. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/__init__.py +0 -0
  69. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/__init__.py +0 -0
  70. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/test_config.py +0 -0
  71. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/test_install.py +0 -0
  72. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/test_project.py +0 -0
  73. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/test_tool.py +0 -0
  74. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/operations/test_update.py +0 -0
  75. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/__init__.py +0 -0
  76. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/conftest.py +0 -0
  77. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_action_card.py +0 -0
  78. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_gather_packages.py +0 -0
  79. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_install_preview.py +0 -0
  80. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_log_panel.py +0 -0
  81. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_logging.py +0 -0
  82. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_preview_model.py +0 -0
  83. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_settings.py +0 -0
  84. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_sidebar.py +0 -0
  85. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_tray_window_show.py +0 -0
  86. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_update_banner.py +0 -0
  87. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_update_controller.py +0 -0
  88. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/qt/test_update_feedback.py +0 -0
  89. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_cli.py +0 -0
  90. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_client_updater.py +0 -0
  91. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_client_version.py +0 -0
  92. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_config.py +0 -0
  93. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_examples.py +0 -0
  94. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_init.py +0 -0
  95. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_install.py +0 -0
  96. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_resolution.py +0 -0
  97. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_uri.py +0 -0
  98. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/test_workers.py +0 -0
  99. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/windows/__init__.py +0 -0
  100. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/windows/conftest.py +0 -0
  101. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/windows/test_protocol.py +0 -0
  102. {synodic_client-0.0.1.dev73 → synodic_client-0.0.1.dev74}/tests/unit/windows/test_startup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: synodic_client
3
- Version: 0.0.1.dev73
3
+ Version: 0.0.1.dev74
4
4
  Author-Email: Synodic Software <contact@synodic.software>
5
5
  License: LGPL-3.0-or-later
6
6
  Project-URL: homepage, https://github.com/synodic/synodic-client
@@ -15,7 +15,7 @@ dependencies = [
15
15
  "velopack>=0.0.1444.dev49733",
16
16
  "typer>=0.24.1",
17
17
  ]
18
- version = "0.0.1.dev73"
18
+ version = "0.0.1.dev74"
19
19
 
20
20
  [project.license]
21
21
  text = "LGPL-3.0-or-later"
@@ -440,8 +440,8 @@ class UpdateController:
440
440
  # the next launch.
441
441
  sync_startup(sys.executable, auto_start=self._store.config.auto_start)
442
442
 
443
- self._pending_version = None
444
443
  self._client.apply_update_on_exit(restart=True, silent=silent)
444
+ self._pending_version = None
445
445
  logger.info('Update scheduled — restarting application')
446
446
  self._app.quit()
447
447
  except Exception as e:
@@ -184,7 +184,12 @@ class Updater:
184
184
  latest_version=latest,
185
185
  _velopack_info=velopack_info,
186
186
  )
187
- self._state = UpdateState.UPDATE_AVAILABLE
187
+ # Only advance to UPDATE_AVAILABLE if we haven't already
188
+ # moved past it. A periodic re-check that discovers the
189
+ # same release must not regress DOWNLOADED → UPDATE_AVAILABLE,
190
+ # which would cause apply_update_on_exit() to reject the update.
191
+ if self._state not in (UpdateState.DOWNLOADED, UpdateState.APPLYING, UpdateState.APPLIED):
192
+ self._state = UpdateState.UPDATE_AVAILABLE
188
193
  logger.info('Update available: %s -> %s', self._current_version, latest)
189
194
  else:
190
195
  self._update_info = UpdateInfo(
@@ -227,6 +227,38 @@ class TestUpdaterCheckForUpdate:
227
227
  assert info.available is False
228
228
  assert updater.state == UpdateState.FAILED
229
229
 
230
+ @staticmethod
231
+ def test_check_preserves_downloaded_state(updater: Updater) -> None:
232
+ """Re-checking after download must not regress DOWNLOADED → UPDATE_AVAILABLE.
233
+
234
+ Regression test: when the periodic auto-check timer fires between
235
+ download completion and the user clicking "Restart Now", the state
236
+ was incorrectly reset to UPDATE_AVAILABLE, causing apply_update_on_exit
237
+ to reject the update with "No downloaded update to apply".
238
+ """
239
+ mock_target = MagicMock(spec=velopack.VelopackAsset)
240
+ mock_target.Version = '2.0.0'
241
+ mock_velopack_info = MagicMock(spec=velopack.UpdateInfo)
242
+ mock_velopack_info.TargetFullRelease = mock_target
243
+
244
+ mock_manager = MagicMock(spec=velopack.UpdateManager)
245
+ mock_manager.check_for_updates.return_value = mock_velopack_info
246
+
247
+ # Simulate: download already completed
248
+ updater._state = UpdateState.DOWNLOADED
249
+ updater._update_info = UpdateInfo(
250
+ available=True,
251
+ current_version=Version('1.0.0'),
252
+ latest_version=Version('2.0.0'),
253
+ _velopack_info=mock_velopack_info,
254
+ )
255
+
256
+ with patch.object(updater, '_get_velopack_manager', return_value=mock_manager):
257
+ info = updater.check_for_update()
258
+
259
+ assert info.available is True
260
+ assert updater.state == UpdateState.DOWNLOADED
261
+
230
262
 
231
263
  class TestUpdaterDownloadUpdate:
232
264
  """Tests for download_update method."""