sqlbench 0.1.55__tar.gz → 0.1.57__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 (43) hide show
  1. {sqlbench-0.1.55 → sqlbench-0.1.57}/PKG-INFO +1 -1
  2. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/connection_dialog.py +18 -6
  3. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/main_window.py +23 -11
  4. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/version.py +1 -1
  5. {sqlbench-0.1.55 → sqlbench-0.1.57}/.github/workflows/pypi-publish.yml +0 -0
  6. {sqlbench-0.1.55 → sqlbench-0.1.57}/.gitignore +0 -0
  7. {sqlbench-0.1.55 → sqlbench-0.1.57}/CLAUDE.md +0 -0
  8. {sqlbench-0.1.55 → sqlbench-0.1.57}/Makefile +0 -0
  9. {sqlbench-0.1.55 → sqlbench-0.1.57}/PYQT_MIGRATION_FEATURES.md +0 -0
  10. {sqlbench-0.1.55 → sqlbench-0.1.57}/README.md +0 -0
  11. {sqlbench-0.1.55 → sqlbench-0.1.57}/pyproject.toml +0 -0
  12. {sqlbench-0.1.55 → sqlbench-0.1.57}/requirements.txt +0 -0
  13. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/__init__.py +0 -0
  14. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/__main__.py +0 -0
  15. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/adapters.py +0 -0
  16. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/app.py +0 -0
  17. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/database.py +0 -0
  18. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/dialogs/__init__.py +0 -0
  19. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/dialogs/connection_dialog.py +0 -0
  20. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/dialogs/regex_builder_dialog.py +0 -0
  21. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/launcher.py +0 -0
  22. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/__init__.py +0 -0
  23. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/connection_tree.py +0 -0
  24. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/__init__.py +0 -0
  25. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/query_manager_dialog.py +0 -0
  26. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/record_viewer_dialog.py +0 -0
  27. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/regex_builder_dialog.py +0 -0
  28. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/dialogs/settings_dialog.py +0 -0
  29. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/icons.py +0 -0
  30. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/syntax.py +0 -0
  31. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/tab_widget.py +0 -0
  32. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/tabs/__init__.py +0 -0
  33. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/tabs/spool_tab.py +0 -0
  34. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/tabs/sql_tab.py +0 -0
  35. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/qt/theme.py +0 -0
  36. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/resources/db_ibmi.png +0 -0
  37. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/resources/db_mysql.png +0 -0
  38. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/resources/db_postgresql.png +0 -0
  39. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/resources/db_unknown.png +0 -0
  40. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/resources/sqlbench.png +0 -0
  41. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/tabs/__init__.py +0 -0
  42. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/tabs/spool_tab.py +0 -0
  43. {sqlbench-0.1.55 → sqlbench-0.1.57}/sqlbench/tabs/sql_tab.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlbench
3
- Version: 0.1.55
3
+ Version: 0.1.57
4
4
  Summary: A multi-database SQL workbench with support for IBM i, MySQL, and PostgreSQL
5
5
  Project-URL: Homepage, https://github.com/jpsteil/sqlbench
6
6
  Project-URL: Repository, https://github.com/jpsteil/sqlbench
@@ -303,6 +303,7 @@ class ConnectionDialog(QDialog):
303
303
  import subprocess
304
304
  import sys
305
305
  import threading
306
+ from PyQt6.QtCore import QTimer
306
307
 
307
308
  db_type = self.cmb_type.currentData()
308
309
  adapter_cls = ADAPTERS.get(db_type)
@@ -317,23 +318,34 @@ class ConnectionDialog(QDialog):
317
318
 
318
319
  self.btn_install_driver.setEnabled(False)
319
320
  self.btn_install_driver.setText("Installing...")
321
+ self._install_result = None # (success: bool, error: str or None)
320
322
 
321
323
  def do_install():
322
324
  try:
323
325
  result = subprocess.run(
324
326
  [sys.executable, "-m", "pip", "install", pkg],
325
- capture_output=True, text=True)
326
- from PyQt6.QtCore import QTimer
327
+ capture_output=True, text=True,
328
+ stdin=subprocess.DEVNULL, timeout=120)
327
329
  if result.returncode == 0:
328
- QTimer.singleShot(0, self._on_driver_installed)
330
+ self._install_result = (True, None)
329
331
  else:
330
332
  error = result.stderr or result.stdout or "Unknown error"
331
- QTimer.singleShot(0, lambda: self._on_driver_install_failed(error))
333
+ self._install_result = (False, error)
332
334
  except Exception as e:
333
- from PyQt6.QtCore import QTimer
334
- QTimer.singleShot(0, lambda: self._on_driver_install_failed(str(e)))
335
+ self._install_result = (False, str(e))
336
+
337
+ def poll_result():
338
+ if self._install_result is None:
339
+ QTimer.singleShot(500, poll_result)
340
+ return
341
+ success, error = self._install_result
342
+ if success:
343
+ self._on_driver_installed()
344
+ else:
345
+ self._on_driver_install_failed(error)
335
346
 
336
347
  threading.Thread(target=do_install, daemon=True).start()
348
+ QTimer.singleShot(2000, poll_result)
337
349
 
338
350
  def _on_driver_installed(self) -> None:
339
351
  """Handle successful driver installation."""
@@ -599,30 +599,42 @@ class MainWindow(QMainWindow):
599
599
 
600
600
  def _run_upgrade(self) -> None:
601
601
  """Run pipx upgrade in background."""
602
+ self._upgrade_result = None # (success: bool, message: str)
603
+
602
604
  def do_upgrade():
603
605
  try:
604
606
  result = subprocess.run(
605
607
  ["pipx", "upgrade", "sqlbench"],
606
- capture_output=True, text=True)
608
+ capture_output=True, text=True,
609
+ stdin=subprocess.DEVNULL, timeout=120)
607
610
  if result.returncode == 0:
608
- QTimer.singleShot(0, lambda: QMessageBox.information(
609
- self, "Upgrade Complete",
610
- "SQLBench has been upgraded.\nPlease restart to use the new version."))
611
+ self._upgrade_result = (True, "SQLBench has been upgraded.\nPlease restart to use the new version.")
611
612
  else:
612
613
  error = result.stderr or result.stdout or "Unknown error"
613
- QTimer.singleShot(0, lambda: QMessageBox.warning(
614
- self, "Upgrade Failed", f"Failed to upgrade:\n{error}"))
614
+ self._upgrade_result = (False, f"Failed to upgrade:\n{error}")
615
+ except subprocess.TimeoutExpired:
616
+ self._upgrade_result = (False, "Upgrade timed out. Please upgrade manually:\n\npipx upgrade sqlbench")
615
617
  except FileNotFoundError:
616
- QTimer.singleShot(0, lambda: QMessageBox.warning(
617
- self, "Upgrade Failed",
618
- "pipx not found. Please upgrade manually:\n\npipx upgrade sqlbench"))
618
+ self._upgrade_result = (False, "pipx not found. Please upgrade manually:\n\npipx upgrade sqlbench")
619
619
  except Exception as e:
620
- QTimer.singleShot(0, lambda: QMessageBox.warning(
621
- self, "Upgrade Failed", f"Failed to upgrade:\n{e}"))
620
+ self._upgrade_result = (False, f"Failed to upgrade:\n{e}")
621
+
622
+ def poll_result():
623
+ result = self._upgrade_result
624
+ if result is None:
625
+ QTimer.singleShot(500, poll_result)
626
+ return
627
+ success, message = result
628
+ self.status_bar.showMessage("Upgrade complete" if success else "Upgrade failed", 3000)
629
+ if success:
630
+ QMessageBox.information(self, "Upgrade Complete", message)
631
+ else:
632
+ QMessageBox.warning(self, "Upgrade Failed", message)
622
633
 
623
634
  self.status_bar.showMessage("Upgrading SQLBench...")
624
635
  thread = threading.Thread(target=do_upgrade, daemon=True)
625
636
  thread.start()
637
+ QTimer.singleShot(2000, poll_result)
626
638
 
627
639
  def set_status(self, message: str, timeout: int = 0) -> None:
628
640
  """Set status bar message."""
@@ -4,7 +4,7 @@ import threading
4
4
  import urllib.request
5
5
  import json
6
6
 
7
- __version__ = "0.1.55"
7
+ __version__ = "0.1.57"
8
8
 
9
9
 
10
10
  def get_installed_version():
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes