quacktui 0.1.0__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 (112) hide show
  1. quacktui-0.1.0/.github/dependabot.yml +27 -0
  2. quacktui-0.1.0/.github/workflows/ci.yml +73 -0
  3. quacktui-0.1.0/.github/workflows/homebrew.yml +92 -0
  4. quacktui-0.1.0/.github/workflows/publish.yml +60 -0
  5. quacktui-0.1.0/.gitignore +36 -0
  6. quacktui-0.1.0/.pre-commit-config.yaml +34 -0
  7. quacktui-0.1.0/.sisyphus/boulder.json +49 -0
  8. quacktui-0.1.0/.sisyphus/plans/ducklake-tui.md +2819 -0
  9. quacktui-0.1.0/.sisyphus/run-continuation/ses_12d8b504fffeGwHi8bVV24ENyo.json +10 -0
  10. quacktui-0.1.0/LICENSE +202 -0
  11. quacktui-0.1.0/PKG-INFO +234 -0
  12. quacktui-0.1.0/README.md +200 -0
  13. quacktui-0.1.0/docker-compose.integration.yml +32 -0
  14. quacktui-0.1.0/docs/COMPATIBILITY.md +63 -0
  15. quacktui-0.1.0/docs/CONTRIBUTING.md +60 -0
  16. quacktui-0.1.0/docs/RELEASE.md +114 -0
  17. quacktui-0.1.0/docs/demo/quickstart.tape +16 -0
  18. quacktui-0.1.0/docs/homebrew/quacktui.rb.template +21 -0
  19. quacktui-0.1.0/pyproject.toml +111 -0
  20. quacktui-0.1.0/scripts/regenerate_brew_resources.sh +17 -0
  21. quacktui-0.1.0/scripts/release.sh +113 -0
  22. quacktui-0.1.0/src/quacktui/__init__.py +5 -0
  23. quacktui-0.1.0/src/quacktui/__main__.py +6 -0
  24. quacktui-0.1.0/src/quacktui/app.py +1023 -0
  25. quacktui-0.1.0/src/quacktui/cli.py +96 -0
  26. quacktui-0.1.0/src/quacktui/config/__init__.py +13 -0
  27. quacktui-0.1.0/src/quacktui/config/example.toml +68 -0
  28. quacktui-0.1.0/src/quacktui/config/loader.py +99 -0
  29. quacktui-0.1.0/src/quacktui/config/schema.py +68 -0
  30. quacktui-0.1.0/src/quacktui/export.py +138 -0
  31. quacktui-0.1.0/src/quacktui/history.py +282 -0
  32. quacktui-0.1.0/src/quacktui/lake/__init__.py +21 -0
  33. quacktui-0.1.0/src/quacktui/lake/connection.py +365 -0
  34. quacktui-0.1.0/src/quacktui/lake/errors.py +32 -0
  35. quacktui-0.1.0/src/quacktui/lake/metadata/__init__.py +21 -0
  36. quacktui-0.1.0/src/quacktui/lake/metadata/models.py +80 -0
  37. quacktui-0.1.0/src/quacktui/lake/metadata/repository.py +490 -0
  38. quacktui-0.1.0/src/quacktui/lake/query_worker.py +167 -0
  39. quacktui-0.1.0/src/quacktui/lake/secrets.py +99 -0
  40. quacktui-0.1.0/src/quacktui/logging.py +145 -0
  41. quacktui-0.1.0/src/quacktui/maintenance/__init__.py +51 -0
  42. quacktui-0.1.0/src/quacktui/maintenance/compaction.py +144 -0
  43. quacktui-0.1.0/src/quacktui/maintenance/delete_orphans.py +129 -0
  44. quacktui-0.1.0/src/quacktui/maintenance/expire_snapshots.py +173 -0
  45. quacktui-0.1.0/src/quacktui/maintenance/optimize_manifests.py +222 -0
  46. quacktui-0.1.0/src/quacktui/maintenance/refresh_stats.py +154 -0
  47. quacktui-0.1.0/src/quacktui/screens/__init__.py +5 -0
  48. quacktui-0.1.0/src/quacktui/screens/connection_picker.py +206 -0
  49. quacktui-0.1.0/src/quacktui/screens/help.py +54 -0
  50. quacktui-0.1.0/src/quacktui/screens/main.py +1 -0
  51. quacktui-0.1.0/src/quacktui/screens/theme_picker.py +66 -0
  52. quacktui-0.1.0/src/quacktui/snippets.py +243 -0
  53. quacktui-0.1.0/src/quacktui/views/__init__.py +0 -0
  54. quacktui-0.1.0/src/quacktui/views/catalog_info.py +280 -0
  55. quacktui-0.1.0/src/quacktui/views/file_inventory.py +423 -0
  56. quacktui-0.1.0/src/quacktui/views/health_dashboard.py +265 -0
  57. quacktui-0.1.0/src/quacktui/views/partition_explorer.py +262 -0
  58. quacktui-0.1.0/src/quacktui/views/schema_evolution.py +261 -0
  59. quacktui-0.1.0/src/quacktui/views/snapshot_timeline.py +362 -0
  60. quacktui-0.1.0/src/quacktui/views/table_details.py +253 -0
  61. quacktui-0.1.0/src/quacktui/widgets/__init__.py +0 -0
  62. quacktui-0.1.0/src/quacktui/widgets/autocomplete.py +320 -0
  63. quacktui-0.1.0/src/quacktui/widgets/confirm_dialog.py +135 -0
  64. quacktui-0.1.0/src/quacktui/widgets/result_grid.py +303 -0
  65. quacktui-0.1.0/src/quacktui/widgets/schema_tree.py +263 -0
  66. quacktui-0.1.0/src/quacktui/widgets/sql_editor.py +156 -0
  67. quacktui-0.1.0/tests/__init__.py +0 -0
  68. quacktui-0.1.0/tests/conftest.py +71 -0
  69. quacktui-0.1.0/tests/fixtures/demo-catalog.duckdb +0 -0
  70. quacktui-0.1.0/tests/fixtures/ducklake_setup.sql +49 -0
  71. quacktui-0.1.0/tests/fixtures/test-connections.toml +54 -0
  72. quacktui-0.1.0/tests/lake/__init__.py +0 -0
  73. quacktui-0.1.0/tests/lake/test_connection.py +244 -0
  74. quacktui-0.1.0/tests/lake/test_metadata.py +171 -0
  75. quacktui-0.1.0/tests/lake/test_query_worker.py +135 -0
  76. quacktui-0.1.0/tests/lake/test_secrets.py +102 -0
  77. quacktui-0.1.0/tests/maintenance/__init__.py +0 -0
  78. quacktui-0.1.0/tests/maintenance/test_compaction.py +207 -0
  79. quacktui-0.1.0/tests/maintenance/test_delete_orphans.py +152 -0
  80. quacktui-0.1.0/tests/maintenance/test_expire_snapshots.py +281 -0
  81. quacktui-0.1.0/tests/maintenance/test_optimize_manifests.py +212 -0
  82. quacktui-0.1.0/tests/maintenance/test_refresh_stats.py +222 -0
  83. quacktui-0.1.0/tests/screens/__init__.py +0 -0
  84. quacktui-0.1.0/tests/screens/test_connection_picker.py +219 -0
  85. quacktui-0.1.0/tests/test_app_integration.py +345 -0
  86. quacktui-0.1.0/tests/test_app_skeleton.py +86 -0
  87. quacktui-0.1.0/tests/test_brew_formula.py +19 -0
  88. quacktui-0.1.0/tests/test_cli.py +108 -0
  89. quacktui-0.1.0/tests/test_config.py +153 -0
  90. quacktui-0.1.0/tests/test_export.py +152 -0
  91. quacktui-0.1.0/tests/test_history.py +119 -0
  92. quacktui-0.1.0/tests/test_logging.py +215 -0
  93. quacktui-0.1.0/tests/test_packaging.py +68 -0
  94. quacktui-0.1.0/tests/test_readonly.py +181 -0
  95. quacktui-0.1.0/tests/test_scaffolding.py +25 -0
  96. quacktui-0.1.0/tests/test_snippets.py +220 -0
  97. quacktui-0.1.0/tests/test_tooling.py +22 -0
  98. quacktui-0.1.0/tests/views/__init__.py +0 -0
  99. quacktui-0.1.0/tests/views/test_catalog_info.py +155 -0
  100. quacktui-0.1.0/tests/views/test_file_inventory.py +249 -0
  101. quacktui-0.1.0/tests/views/test_health_dashboard.py +222 -0
  102. quacktui-0.1.0/tests/views/test_partition_explorer.py +176 -0
  103. quacktui-0.1.0/tests/views/test_schema_evolution.py +235 -0
  104. quacktui-0.1.0/tests/views/test_snapshot_timeline.py +231 -0
  105. quacktui-0.1.0/tests/views/test_table_details.py +233 -0
  106. quacktui-0.1.0/tests/widgets/__init__.py +0 -0
  107. quacktui-0.1.0/tests/widgets/test_autocomplete.py +210 -0
  108. quacktui-0.1.0/tests/widgets/test_confirm_dialog.py +125 -0
  109. quacktui-0.1.0/tests/widgets/test_result_grid.py +176 -0
  110. quacktui-0.1.0/tests/widgets/test_schema_tree.py +227 -0
  111. quacktui-0.1.0/tests/widgets/test_sql_editor.py +103 -0
  112. quacktui-0.1.0/uv.lock +1901 -0
@@ -0,0 +1,27 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ time: "09:00"
9
+ open-pull-requests-limit: 5
10
+ reviewers:
11
+ - riazkrm
12
+ labels:
13
+ - dependencies
14
+ - python
15
+
16
+ - package-ecosystem: github-actions
17
+ directory: /
18
+ schedule:
19
+ interval: weekly
20
+ day: monday
21
+ time: "09:00"
22
+ open-pull-requests-limit: 5
23
+ reviewers:
24
+ - riazkrm
25
+ labels:
26
+ - dependencies
27
+ - ci
@@ -0,0 +1,73 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ lint:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: astral-sh/setup-uv@v3
21
+ - run: uv run ruff check .
22
+ - run: uv run ruff format --check .
23
+
24
+ types:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v3
29
+ - run: uv run mypy --strict src/quacktui
30
+
31
+ test-unit:
32
+ runs-on: ubuntu-latest
33
+ strategy:
34
+ matrix:
35
+ python-version: ["3.12", "3.13"]
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - uses: astral-sh/setup-uv@v3
39
+ with:
40
+ python-version: ${{ matrix.python-version }}
41
+ - run: uv run pytest -m "not integration" -v
42
+
43
+ test-integration:
44
+ runs-on: ubuntu-latest
45
+ services:
46
+ minio:
47
+ image: minio/minio:latest
48
+ env:
49
+ MINIO_ROOT_USER: minioadmin
50
+ MINIO_ROOT_PASSWORD: minioadmin
51
+ options: >-
52
+ --health-cmd "curl -f http://localhost:9000/minio/health/live"
53
+ --health-interval 10s
54
+ --health-timeout 5s
55
+ --health-retries 5
56
+ ports:
57
+ - 9000:9000
58
+ - 9001:9001
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ - uses: astral-sh/setup-uv@v3
62
+ - run: uv run pytest -m integration -v
63
+
64
+ build:
65
+ runs-on: ubuntu-latest
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ - uses: astral-sh/setup-uv@v3
69
+ - run: uv build
70
+ - uses: actions/upload-artifact@v4
71
+ with:
72
+ name: dist
73
+ path: dist/
@@ -0,0 +1,92 @@
1
+ name: Homebrew Formula Bump
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: 'Version to bump to (e.g. 0.1.2)'
11
+ required: true
12
+
13
+ jobs:
14
+ bump:
15
+ name: Regenerate + push formula to homebrew-tap
16
+ runs-on: ubuntu-latest
17
+ needs: []
18
+ steps:
19
+ - name: Resolve target version
20
+ id: version
21
+ run: |
22
+ if [ -n "${{ inputs.version }}" ]; then
23
+ VERSION="${{ inputs.version }}"
24
+ else
25
+ VERSION="${GITHUB_REF_NAME#v}"
26
+ fi
27
+ echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
28
+ echo "Target version: ${VERSION}"
29
+
30
+ - name: Wait for PyPI to publish the new version
31
+ run: |
32
+ VERSION="${{ steps.version.outputs.VERSION }}"
33
+ for i in $(seq 1 30); do
34
+ if curl -fsS -o /dev/null "https://pypi.org/pypi/quacktui/${VERSION}/json"; then
35
+ echo "PyPI has quacktui ${VERSION}"
36
+ exit 0
37
+ fi
38
+ echo "Waiting for PyPI to publish quacktui ${VERSION}... (${i}/30)"
39
+ sleep 10
40
+ done
41
+ echo "ERROR: PyPI never published quacktui ${VERSION} within 5 minutes" >&2
42
+ exit 1
43
+
44
+ - uses: actions/setup-python@v5
45
+ with:
46
+ python-version: "3.12"
47
+
48
+ - name: Generate formula via homebrew-pypi-poet
49
+ run: |
50
+ VERSION="${{ steps.version.outputs.VERSION }}"
51
+ python3 -m venv /tmp/poet-venv
52
+ /tmp/poet-venv/bin/pip install --quiet --upgrade pip "setuptools<75"
53
+ /tmp/poet-venv/bin/pip install --quiet "quacktui==${VERSION}" homebrew-pypi-poet
54
+ /tmp/poet-venv/bin/poet -f quacktui > /tmp/quacktui.rb
55
+
56
+ - name: Patch placeholders, add license + test
57
+ run: |
58
+ sed -i 's|desc "Shiny new formula"|desc "TUI for managing DuckLake datalakes"|' /tmp/quacktui.rb
59
+ sed -i 's|homepage "None"|homepage "https://github.com/arksigma/quacktui"|' /tmp/quacktui.rb
60
+ awk '/^ sha256/ && !done {print; print " license \"Apache-2.0\""; done=1; next} 1' /tmp/quacktui.rb > /tmp/quacktui.rb.tmp && mv /tmp/quacktui.rb.tmp /tmp/quacktui.rb
61
+ python3 << 'PYEOF'
62
+ import re
63
+ p = "/tmp/quacktui.rb"
64
+ with open(p) as f:
65
+ content = f.read()
66
+ new_test = ''' test do
67
+ assert_match "TUI for managing DuckLake datalakes", shell_output("#{bin}/quacktui --help")
68
+ end
69
+ end'''
70
+ content = re.sub(r" test do\n.*? end\nend\s*$", new_test + "\n", content, flags=re.DOTALL)
71
+ with open(p, "w") as f:
72
+ f.write(content)
73
+ PYEOF
74
+
75
+ - name: Push to homebrew-tap
76
+ env:
77
+ GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
78
+ VERSION: ${{ steps.version.outputs.VERSION }}
79
+ run: |
80
+ git clone "https://x-access-token:${GH_TOKEN}@github.com/arksigma/homebrew-tap.git" /tmp/tap
81
+ mkdir -p /tmp/tap/Formula
82
+ cp /tmp/quacktui.rb /tmp/tap/Formula/quacktui.rb
83
+ cd /tmp/tap
84
+ git config user.name "github-actions[bot]"
85
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
86
+ git add Formula/quacktui.rb
87
+ if git diff --staged --quiet; then
88
+ echo "No formula changes — already at target version"
89
+ exit 0
90
+ fi
91
+ git commit -m "Formula update for quacktui version ${VERSION}"
92
+ git push origin main
@@ -0,0 +1,60 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+
8
+ jobs:
9
+ verify:
10
+ name: Verify (tests + lint + version match)
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v3
15
+ with:
16
+ python-version: "3.12"
17
+ - name: Verify pyproject.toml version matches tag
18
+ run: |
19
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
20
+ PYPROJECT_VERSION=$(grep -oP '(?<=^version = ")[^"]+' pyproject.toml)
21
+ if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
22
+ echo "Tag version ($TAG_VERSION) does not match pyproject.toml version ($PYPROJECT_VERSION)" >&2
23
+ exit 1
24
+ fi
25
+ echo "Version match: $TAG_VERSION"
26
+ - run: uv run ruff check .
27
+ - run: uv run mypy --strict src/quacktui
28
+ - run: uv run pytest -m "not integration" -v
29
+
30
+ build:
31
+ name: Build wheel + sdist
32
+ needs: verify
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - uses: astral-sh/setup-uv@v3
37
+ with:
38
+ python-version: "3.12"
39
+ - run: uv build
40
+ - run: uv run twine check dist/*
41
+ - uses: actions/upload-artifact@v4
42
+ with:
43
+ name: dist
44
+ path: dist/
45
+
46
+ publish:
47
+ name: Publish to PyPI
48
+ needs: build
49
+ runs-on: ubuntu-latest
50
+ environment:
51
+ name: pypi
52
+ url: https://pypi.org/project/quacktui/
53
+ permissions:
54
+ id-token: write
55
+ steps:
56
+ - uses: actions/download-artifact@v4
57
+ with:
58
+ name: dist
59
+ path: dist/
60
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,36 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+ *.egg/
9
+
10
+ # Virtual environments
11
+ .venv
12
+
13
+ # IDE
14
+ .vscode/
15
+ .idea/
16
+ *.swp
17
+ *.swo
18
+ *~
19
+
20
+ # OS
21
+ .DS_Store
22
+ .DS_Store?
23
+ ._*
24
+ .Spotlight-V100
25
+ .Trashes
26
+ ehthumbs.db
27
+
28
+ # uv
29
+ .python-version
30
+
31
+ # Build artifacts
32
+ sdist/
33
+
34
+ # Sisyphus workflow files
35
+ .sisyphus/evidence/
36
+ .sisyphus/notepads/
@@ -0,0 +1,34 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.17
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/pre-commit/mirrors-mypy
10
+ rev: v2.1.0
11
+ hooks:
12
+ - id: mypy
13
+ args: [--strict, --no-error-summary]
14
+ additional_dependencies:
15
+ - pydantic
16
+ - textual
17
+ - textual-textarea
18
+ - textual-fastdatatable
19
+ - sqlglot
20
+ - tomli_w
21
+ - duckdb>=1.5,<2.0
22
+ - pyarrow>=16.0,<25.0
23
+ files: ^src/quacktui/.*\.py$
24
+ exclude: (__pycache__|\.venv)
25
+
26
+ - repo: local
27
+ hooks:
28
+ - id: pytest
29
+ name: pytest
30
+ entry: uv run pytest
31
+ language: system
32
+ pass_filenames: false
33
+ always_run: true
34
+ args: [tests/, -x, --ff]
@@ -0,0 +1,49 @@
1
+ {
2
+ "active_plan": "/home/ark/dev/quacktui/.sisyphus/plans/ducklake-tui.md",
3
+ "started_at": "2026-06-17T15:15:35.198Z",
4
+ "session_ids": [
5
+ "ses_12d8b504fffeGwHi8bVV24ENyo"
6
+ ],
7
+ "session_origins": {
8
+ "ses_12d8b504fffeGwHi8bVV24ENyo": "direct"
9
+ },
10
+ "plan_name": "ducklake-tui",
11
+ "agent": "atlas",
12
+ "task_sessions": {
13
+ "todo:1": {
14
+ "task_key": "todo:1",
15
+ "task_label": "1",
16
+ "task_title": "**Project scaffolding (uv + src layout + dep pins + integration docker)**",
17
+ "session_id": "ses_129d6f175ffeeQ7X3IbKA7U4XQ",
18
+ "agent": "Sisyphus-Junior",
19
+ "updated_at": "2026-06-17T15:28:55.730Z"
20
+ },
21
+ "todo:2": {
22
+ "task_key": "todo:2",
23
+ "task_label": "2",
24
+ "task_title": "**Tooling baseline (ruff + mypy strict + pre-commit + pytest config)**",
25
+ "session_id": "ses_129cb4fa0ffeW4UARw7zcD06T5",
26
+ "agent": "Sisyphus-Junior",
27
+ "category": "quick",
28
+ "updated_at": "2026-06-17T15:46:06.282Z"
29
+ },
30
+ "todo:5": {
31
+ "task_key": "todo:5",
32
+ "task_label": "5",
33
+ "task_title": "**DuckLake connection layer (one DuckDB instance per connection + SECRET + ATTACH lifecycle)**",
34
+ "session_id": "ses_129b84ffcffe2fwp883uMETB77",
35
+ "agent": "Sisyphus-Junior",
36
+ "category": "unspecified-high",
37
+ "updated_at": "2026-06-17T16:05:06.949Z"
38
+ },
39
+ "todo:6": {
40
+ "task_key": "todo:6",
41
+ "task_label": "6",
42
+ "task_title": "**Metadata repository (typed wrappers over DuckLake system tables)**",
43
+ "session_id": "ses_129aaa325ffeCIc3736jLnKFIB",
44
+ "agent": "Sisyphus-Junior",
45
+ "category": "unspecified-high",
46
+ "updated_at": "2026-06-17T16:21:32.185Z"
47
+ }
48
+ }
49
+ }