diff --git a/.gitignore b/.gitignore index 43ae0e2..dfcf8d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,31 @@ +# Python __pycache__/ -*.py[cod] +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +.venv/ + +# Build artifacts +dist/ +build/ +*.egg-info/ +*.egg + +# Other +.DS_Store +*.log +*.pot +*.pytx +*.swp +.idea/ +.vscode/ +*.db +*.sqlite +*.sqlite3 +/downloads +/node_modules +*.deb +*.rpm \ No newline at end of file diff --git a/src/sqliteviewer.egg-info/PKG-INFO b/src/sqliteviewer.egg-info/PKG-INFO index 2c29e15..186fa9d 100644 --- a/src/sqliteviewer.egg-info/PKG-INFO +++ b/src/sqliteviewer.egg-info/PKG-INFO @@ -47,6 +47,8 @@ Requires-Dist: build>=1.0.3; extra == "dev" Dynamic: license-file # SQLite Viewer for Ubuntu +⚠️ This repository is an experimental project using AI tools such as Codex. +It is shared for educational purposes only. Please note that it is provided *as is*, without warranty or official support. A lightweight PyQt6 desktop SQLite database viewer targeting Ubuntu desktops. The app lets you inspect tables, run ad-hoc queries, and export results—packaged for distribution via Python wheels or Debian packages. @@ -78,6 +80,9 @@ source .venv/bin/activate pip install --upgrade pip pip install -e ".[dev]" ``` +Keep the extras in quotes (the `".[dev]"` part) so shells like `zsh` don't treat it as a glob pattern. + +If you prefer `uv`, install it beforehand (for example `pip install uv`) and then run `uv pip install -e ".[dev]"` inside the virtual environment. Launch the viewer: diff --git a/src/sqliteviewer.egg-info/SOURCES.txt b/src/sqliteviewer.egg-info/SOURCES.txt index 92c1852..72e2614 100644 --- a/src/sqliteviewer.egg-info/SOURCES.txt +++ b/src/sqliteviewer.egg-info/SOURCES.txt @@ -20,4 +20,5 @@ src/sqliteviewer.egg-info/top_level.txt src/sqliteviewer/resources/__init__.py src/sqliteviewer/resources/icon.png src/sqliteviewer/resources/sqliteviewer.desktop -tests/test_database.py \ No newline at end of file +tests/test_database.py +tests/test_mainwindow.py \ No newline at end of file diff --git a/src/sqliteviewer/mainwindow.py b/src/sqliteviewer/mainwindow.py index 9487fb8..0aaa73a 100644 --- a/src/sqliteviewer/mainwindow.py +++ b/src/sqliteviewer/mainwindow.py @@ -296,6 +296,8 @@ def _show_about_dialog(self) -> None: def _load_recent_files(self) -> None: files = self.settings.value("recent_files", [], type=list) self._recent_files = [f for f in files if Path(f).exists()] + if len(self._recent_files) != len(files): + self.settings.setValue("recent_files", self._recent_files) self._update_recent_menu() def _remember_recent_file(self, path: str) -> None: diff --git a/tests/test_mainwindow.py b/tests/test_mainwindow.py new file mode 100644 index 0000000..5fa1944 --- /dev/null +++ b/tests/test_mainwindow.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import tempfile +from pathlib import Path + +import pytest +from PyQt6.QtCore import QSettings + +from sqliteviewer.mainwindow import MainWindow + + +@pytest.fixture +def test_settings(qtbot) -> QSettings: + """Override QSettings to use a temporary, clean .ini file for tests.""" + QSettings.setDefaultFormat(QSettings.Format.IniFormat) + settings = QSettings("test-org", "test-app") + settings.clear() + yield settings + settings.clear() + + +def test_recent_files_are_purged_on_load(qtbot, test_settings, monkeypatch): + """Verify that non-existent recent files are removed from settings on load.""" + # Arrange: Use monkeypatch to ensure the MainWindow uses our test_settings instance. + monkeypatch.setattr( + "sqliteviewer.mainwindow.QSettings", lambda *args, **kwargs: test_settings + ) + + with tempfile.NamedTemporaryFile() as tmpfile: + real_path = Path(tmpfile.name).as_posix() + fake_path = "/tmp/this-file-definitely-does-not-exist.db" + initial_files = [real_path, fake_path] + test_settings.setValue("recent_files", initial_files) + + # Act: create the main window, which should trigger the load + window = MainWindow() + qtbot.addWidget(window) + + # Assert: the settings should now only contain the real path + stored_files = test_settings.value("recent_files", [], type=list) + assert stored_files == [real_path] \ No newline at end of file