Skip to content

Commit afd9fce

Browse files
authored
Merge pull request #19 from stonebig/duckdb
Duckdb
2 parents 9f611cf + 7b38283 commit afd9fce

10 files changed

Lines changed: 734 additions & 75 deletions

File tree

.github/workflows/tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ jobs:
2828
run: |
2929
python -m pip install --upgrade pip
3030
python -m pip install flake8 pytest nose
31+
# optional DuckDB engine (no wheel on PyPy : tests will auto-skip)
32+
python -m pip install duckdb numpy || echo "duckdb not available"
3133
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
3234
- name: Lint with flake8
3335
run: |

CLAUDE.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project overview
6+
7+
sqlite_bro is a graphic SQLite browser/client implemented as a **single Python source file**:
8+
`sqlite_bro/sqlite_bro.py` (~2300 lines). Keeping the tool in one file is a deliberate design goal
9+
(see README.rst: "Easy to distribute : 1 Python source file") — it's meant to be copied to any
10+
machine and run directly with `python sqlite_bro.py`, or loaded remotely via
11+
`%load https://raw.githubusercontent.com/stonebig/sqlite_bro/master/sqlite_bro/sqlite_bro.py`.
12+
Avoid splitting it into multiple modules.
13+
14+
Supports Python >= 3.3 and PyPy3. Uses Tkinter/ttk for the GUI (`from tkinter import *`, with a
15+
Python 2.7 fallback import path still present via `from __future__ import ...`).
16+
17+
## Common commands
18+
19+
Install in editable mode and run:
20+
```
21+
pip install -e .
22+
sqlite_bro # launch the GUI
23+
sqlite_bro -h # see CLI options (-q/--quiet, -w/--wait, -db/--database, -sc/--scripts)
24+
python -m sqlite_bro.sqlite_bro # run directly without install
25+
```
26+
27+
Run tests (from repo root):
28+
```
29+
pytest -v
30+
pytest -v sqlite_bro/tests/test_general.py::test_Basics # single test
31+
```
32+
33+
- `test_general.py` drives the real Tkinter GUI app (`App()`); on Linux CI this needs a virtual
34+
display (Xvfb) since there's no `DISPLAY` otherwise.
35+
- `test_general_no_gui.py` is the same test suite against `App(use_gui=False)`, exercising the
36+
command/query engine without Tkinter widgets.
37+
38+
Lint (as run in CI, see `.github/workflows/tests.yml`):
39+
```
40+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
41+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
42+
```
43+
44+
CI matrix: Python 3.8, 3.12, and pypy-3.10 (`.github/workflows/tests.yml`). `appveyor.yml` is legacy
45+
(Python 2.7/3.4, nosetests) and not the active CI.
46+
47+
Build/publish uses `flit_core` (see `pyproject.toml`), not setuptools — version is read from
48+
`sqlite_bro/__init__.py`'s `__version__`.
49+
50+
## Architecture
51+
52+
Everything lives in `sqlite_bro/sqlite_bro.py`. The major pieces, in order of appearance:
53+
54+
- **`App`** — the Tkinter application. Can run with or without a GUI (`use_gui` flag), which is
55+
what lets the query/script engine be tested headlessly. Owns the DB connection lifecycle
56+
(`new_db`, `open_db`, `backup_db`, `restore_db`, `attach_db`, `close_db`), the menu/toolbar, the
57+
font/tab UI (drag-reorder tabs via `btn_press`/`btn_Move`/`btn_release`), CSV import/export
58+
dialogs, and the DB-tree view (`feed_dbtree`).
59+
- **`App.create_and_add_results`** — the core script execution engine (the largest method, ~1000
60+
lines). It splits a multi-statement script into individual instructions via
61+
`Baresql.get_sqlsplit`, then for each instruction dispatches on its shape:
62+
- `pydef ...` blocks → registers an embedded Python function as a SQLite function
63+
(`Baresql.createpydef`), so SQL can call user-defined Python (see the `.` command doc block in
64+
`_main()`'s `welcome_text` and the `py_hello`/`py_fib` examples).
65+
- `.` prefixed lines → **dot-commands** (sqlite3-CLI-style), parsed with `shlex.split`. Supported:
66+
`.backup`, `.cd`, `.dump`, `.excel`, `.headers`, `.import`, `.once`, `.open`, `.output`,
67+
`.print`, `.read`, `.restore`, `.separator`, `.shell`. This is what gives sqlite_bro its
68+
command-line scripting story independent of the GUI.
69+
- everything else → run as SQL against `Baresql.conn`, with results rendered into the tab's
70+
treeview (`NotebookForQueries.add_treeview`).
71+
- **`NotebookForQueries`** — manages the query-tab notebook: creating tabs (`new_query_tab`),
72+
attaching result treeviews to a tab, and sortable columns (`sortby`).
73+
- **`Baresql`** — thin wrapper around `sqlite3.Connection`. Handles: dump export tweaks
74+
(`iterdump`, forces a UTF-8 marker, toggles `PRAGMA foreign_keys` around dumps), SQL tokenizing
75+
and statement splitting (`get_tokens`, `get_sqlsplit` — this is what makes multi-statement
76+
scripts and dot-commands work inside one text blob), and CSV import/export row streaming
77+
(`insert_reader`, `export_writer`).
78+
- **`guess_csv`** / **`guess_encoding`** / **`guess_sql_creation`** — CSV format and file-encoding
79+
auto-detection used by import/export, independent of `Baresql`.
80+
- **`create_dialog`** — generic Tkinter modal-dialog builder reused by several features (rename
81+
tab, import CSV, export CSV, etc.) rather than each having bespoke dialog code.
82+
- **`_main()`** — CLI entry point (`sqlite_bro = "sqlite_bro.sqlite_bro:_main"` in
83+
`pyproject.toml`). Builds the built-in "Welcome" demo script (which doubles as living
84+
documentation of SQL features and dot-commands), parses argv with `argparse` (falls back to no
85+
CLI args pre-3.2), and boots `App`.
86+
87+
When editing, keep in mind the GUI/no-GUI duality: any change to script/command execution
88+
(`create_and_add_results`, `Baresql`) must keep working under `use_gui=False`, since that's the
89+
path exercised by `test_general_no_gui.py` and by headless/CLI usage (`-q/--quiet`).

HISTORY.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
Changelog
22
=========
33

4+
2026-07-13a : v0.14.0 'Quack me up !'
5+
-------------------------------------
6+
7+
* optional DuckDB engine : create or open a '.duckdb' database (needs 'pip install duckdb'), with its own DuckDB-flavored welcome demo
8+
9+
* pydef embedded Python functions work on the DuckDB engine (type-annotated ones are registered natively)
10+
11+
* script runs now feed a single 'Logs' result tab (N°, Time, Result, Status, Instruction) : DDL/DML/pydef/dot-commands no longer spawn one result tab each, and silent statements become visible
12+
13+
* data grids keep their own result tabs, titled 'Qry_<n>' where <n> matches the record N° in the 'Logs' tab
14+
15+
* 'Logs' and 'Dump' result tabs are pinned on the left of the results notebook
16+
17+
* window title and database tree indicate the engine in use (SQLite or DuckDB)
18+
19+
* fix : refreshing the database tree no longer crashes on views repeating a column name (e.g. 'select *' over a join)
20+
21+
422
2024-05-11b : v0.13.1 'Setup me down !'
523
---------------------------------------
624

README.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
sqlite_bro : a graphic SQLite browser in 1 Python file
2-
======================================================
1+
sqlite_bro : a graphic SQLite and DuckDB browser in 1 Python file
2+
=================================================================
33

4-
sqlite_bro is a tool to browse SQLite databases with
5-
any basic python installation.
4+
sqlite_bro is a tool to browse SQLite (and optionally DuckDB)
5+
databases with any basic python installation.
66

77

88
Features
99
--------
1010

11-
* Tabular browsing of a SQLite database
11+
* Tabular browsing of a SQLite or DuckDB database
12+
13+
* Optional DuckDB engine : open or create a '.duckdb' file (needs 'pip install duckdb')
1214

1315
* Import/Export of .csv files with auto-detection
1416

docs/sqlite_bro.GIF

98.5 KB
Loading

docs/sqlite_bro_command_line.GIF

-44.4 KB
Loading

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ classifiers=[
2525
'Topic :: Software Development :: Widget Sets',
2626
]
2727
dynamic = ["version",]
28-
description="a graphic SQLite Client in 1 Python file"
29-
keywords = ["sqlite", "gui", "ttk", "sql"]
28+
description="a graphic SQLite and DuckDB Client in 1 Python file"
29+
keywords = ["sqlite", "duckdb", "gui", "ttk", "sql"]
3030

3131
[project.urls]
3232
Documentation = "https://github.com/stonebig/sqlite_bro/README.rst"

sqlite_bro/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.13.1'
1+
__version__ = '0.14.0'

0 commit comments

Comments
 (0)