calibrequarry 3.26.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.
- calibrequarry-3.26.0/.github/workflows/ci.yml +21 -0
- calibrequarry-3.26.0/.github/workflows/publish.yml +45 -0
- calibrequarry-3.26.0/.gitignore +31 -0
- calibrequarry-3.26.0/AGENTS.md +1 -0
- calibrequarry-3.26.0/CLAUDE.md +35 -0
- calibrequarry-3.26.0/LICENSE +21 -0
- calibrequarry-3.26.0/PKG-INFO +799 -0
- calibrequarry-3.26.0/README.md +786 -0
- calibrequarry-3.26.0/VERSION +1 -0
- calibrequarry-3.26.0/docs/screenshots/stats.png +0 -0
- calibrequarry-3.26.0/fix_cq_lint.sh +31 -0
- calibrequarry-3.26.0/logo.svg +68 -0
- calibrequarry-3.26.0/patchnotes.md +732 -0
- calibrequarry-3.26.0/pyproject.toml +36 -0
- calibrequarry-3.26.0/roadmap.md +367 -0
- calibrequarry-3.26.0/run_tests.sh +46 -0
- calibrequarry-3.26.0/scripts/audit_conversion_overrides.py +92 -0
- calibrequarry-3.26.0/scripts/audit_drm.py +566 -0
- calibrequarry-3.26.0/scripts/audit_isbns.py +594 -0
- calibrequarry-3.26.0/scripts/compress_pdf.py +581 -0
- calibrequarry-3.26.0/scripts/db_util.py +45 -0
- calibrequarry-3.26.0/scripts/fetch_library_codes.py +667 -0
- calibrequarry-3.26.0/scripts/reconcile_file_metadata.py +869 -0
- calibrequarry-3.26.0/scripts/screen_duplicate.py +338 -0
- calibrequarry-3.26.0/scripts/spot_check.py +769 -0
- calibrequarry-3.26.0/scripts/stamp_pdf.py +291 -0
- calibrequarry-3.26.0/scripts/taxonomy.example.json +117 -0
- calibrequarry-3.26.0/scripts/taxonomy.example.yaml +1146 -0
- calibrequarry-3.26.0/scripts/validate_metadata.py +557 -0
- calibrequarry-3.26.0/spec.md +138 -0
- calibrequarry-3.26.0/src/cquarry_cli/__init__.py +2 -0
- calibrequarry-3.26.0/src/cquarry_cli/__main__.py +11 -0
- calibrequarry-3.26.0/src/cquarry_cli/cli.py +687 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/__init__.py +0 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/analytics.py +108 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/audit.py +172 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/catalog.py +219 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/detail.py +230 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/display.py +170 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/export.py +310 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/info.py +154 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/librarything.py +299 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/stats.py +108 -0
- calibrequarry-3.26.0/src/cquarry_cli/modes/tags.py +25 -0
- calibrequarry-3.26.0/src/cquarry_cli/tui.py +571 -0
- calibrequarry-3.26.0/src/cquarry_cli/writeops.py +912 -0
- calibrequarry-3.26.0/test_queries.sh +39 -0
- calibrequarry-3.26.0/tests/test_audit_drm.py +360 -0
- calibrequarry-3.26.0/tests/test_audit_isbns.py +421 -0
- calibrequarry-3.26.0/tests/test_modes.py +215 -0
- calibrequarry-3.26.0/tests/test_read_modes.py +314 -0
- calibrequarry-3.26.0/tests/test_reconcile.py +285 -0
- calibrequarry-3.26.0/tests/test_scripts.py +1092 -0
- calibrequarry-3.26.0/tests/test_version.py +76 -0
- calibrequarry-3.26.0/tests/test_write_expand.py +262 -0
- calibrequarry-3.26.0/tests/test_write_flow.py +382 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.14"
|
|
16
|
+
- run: pip install "git+https://github.com/VirInvictus/cquarry.git@main"
|
|
17
|
+
- run: pip install .
|
|
18
|
+
- run: pip install ruff==0.15.20
|
|
19
|
+
- run: ruff check src tests scripts
|
|
20
|
+
- run: ruff format --check src tests scripts
|
|
21
|
+
- run: PYTHONPATH=src python -m unittest discover -s tests
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.14"
|
|
16
|
+
|
|
17
|
+
- name: Run test suite
|
|
18
|
+
run: |
|
|
19
|
+
pip install .
|
|
20
|
+
PYTHONPATH=src python -m unittest discover -s tests
|
|
21
|
+
|
|
22
|
+
build-and-publish:
|
|
23
|
+
name: Build distribution and publish to PyPI
|
|
24
|
+
needs: test
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment:
|
|
27
|
+
name: pypi
|
|
28
|
+
url: https://pypi.org/p/calibrequarry
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.14"
|
|
37
|
+
|
|
38
|
+
- name: Install build
|
|
39
|
+
run: python -m pip install --upgrade build
|
|
40
|
+
|
|
41
|
+
- name: Build sdist and wheel
|
|
42
|
+
run: python -m build
|
|
43
|
+
|
|
44
|
+
- name: Publish to PyPI
|
|
45
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.pyo
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.venv/
|
|
9
|
+
|
|
10
|
+
# Editor files
|
|
11
|
+
*.swp
|
|
12
|
+
*.swo
|
|
13
|
+
*~
|
|
14
|
+
.vscode/
|
|
15
|
+
.idea/
|
|
16
|
+
|
|
17
|
+
# uv re-resolves the @main git deps on every sync; a committed lock would
|
|
18
|
+
# freeze cquarry/vir-tui at the moment it was generated, defeating the
|
|
19
|
+
# "latest, always" dependency policy. Keep it local-only.
|
|
20
|
+
uv.lock
|
|
21
|
+
|
|
22
|
+
# Output files
|
|
23
|
+
*.csv
|
|
24
|
+
*.json
|
|
25
|
+
*.txt
|
|
26
|
+
# ...but the shipped taxonomy template is config, not generated output
|
|
27
|
+
!scripts/taxonomy.example.json
|
|
28
|
+
|
|
29
|
+
# OS junk
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CLAUDE.md
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# CLAUDE.md (CalibreQuarry)
|
|
2
|
+
|
|
3
|
+
Per-project guidance. Overrides the global file where they conflict.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
A CLI and TUI toolkit for Calibre users who treat their libraries as curated collections. It provides a purely terminal-driven interface for analyzing and exporting from Calibre databases.
|
|
7
|
+
|
|
8
|
+
## Programmer-facing contract notes (cquarry >= 1.7)
|
|
9
|
+
- `db.get_all_books()` rows expose `authors`, `tags`, `languages`, and `formats` as native `list[str]`. Never `.split(",")` them; comma-containing author/tag names are preserved by the link-table hydration. `normalize_author_display()` accepts both the legacy joined string and the list form.
|
|
10
|
+
- Every book row also carries `size` (total `data.uncompressed_size` bytes, may be None) and, since cquarry >= 1.3/1.4, `pages` (native `books_pages_link`), `author_sorts`, and `author_links`.
|
|
11
|
+
- `search()` raises `ParseException` for unknown virtual libraries or saved searches; only `resolve_vl()` / `resolve_saved_search()` raise `ValueError` (with an available-names message).
|
|
12
|
+
- Raw comments payloads are HTML; run them through `cquarry.helpers.strip_html()` before terminal output.
|
|
13
|
+
- **Write verbs** (`--set-*`, `--add-tag`, `--remove-tag`, `--clear-*`, `--remove-book`) are opt-in and funnel through `run_write()` in `src/cquarry_cli/writeops.py`, dispatched by `cli.py` for flags and called directly by `tui.py` for menu flows; it owns the WritableCalibreDB lifecycle and the error-to-exit-code mapping (argument problems exit 2, lock/write errors exit 1). Read modes never import `cquarry.write` or `writeops`; keep it that way.
|
|
14
|
+
- **Dependency policy.** `cquarry` and `vir-tui` are tracked at `@main` and must never be pinned to a tag or commit, and `uv.lock` stays out of the repo: installs always pull the latest.
|
|
15
|
+
|
|
16
|
+
## Programmer-facing contract notes (3.24.0 onward)
|
|
17
|
+
|
|
18
|
+
- **Detail/audit/analytics modes render; cquarry derives.** `--book` is a renderer over cquarry 1.8's `get_book_dossier()` (batch forms compose it in a loop; `--book --untagged` sources ids from `cquarry.integrity.find_untagged`); `--audit`'s per-book predicates come from `cquarry.integrity`; `--analytics`/`--stats` consume `cquarry.analytics`. Do not re-derive a predicate or a stat inline in this repo: promote it to cquarry (the frontend-only split, now enforced by usage). The one deliberate exception: `--audit`'s duplicate grouping stays inline because the CSV joins ids in scan order and `find_duplicate_books()` sorts numerically.
|
|
19
|
+
|
|
20
|
+
## Hard constraints
|
|
21
|
+
- **Frontend Only.** The core database logic and search evaluation are delegated to the external `cquarry` shared library. Do not add database reads or search parsing logic here; contribute them to `cquarry` instead.
|
|
22
|
+
- **Minimal Dependencies.** Only `cquarry`, `vir-tui`, and `tqdm`. No `calibredb` required.
|
|
23
|
+
- **Immersive Output.** All commands that dump extensive output must be wrapped in `_run_with_capture()` so they display in the curses pager, unless redirected.
|
|
24
|
+
|
|
25
|
+
## Layout
|
|
26
|
+
- `src/cquarry_cli/cli.py` & `tui.py`: Core CLI arguments and the Curses UI menu.
|
|
27
|
+
- `src/cquarry_cli/modes/`: Implementations for each CLI flag (`catalog.py`, `export.py`, `stats.py`, `detail.py`, `info.py`, etc).
|
|
28
|
+
- `src/cquarry_cli/writeops.py`: Shared write-verb plumbing: `run_write()` owns the WritableCalibreDB lifecycle; `dispatch_write()` maps CLI flags onto per-verb executors the TUI also calls.
|
|
29
|
+
- `tests/`: End-to-end integration tests using `cquarry_cli` directly against the database (the unit tests for `cquarry.db` and `cquarry.search` were moved to the `cquarry` library).
|
|
30
|
+
|
|
31
|
+
> **Important:** The core database logic (`db.py`, `search.py`, `helpers.py`, `config.py`) was extracted into the `cquarry` shared library. Additionally, the generic UI formatting and Curses menu primitives have been extracted to the `vir-tui` shared repository. CalibreQuarry relies on both of these external dependencies. (`db.py`, `search.py`, `helpers.py`, `config.py`) was extracted into the `cquarry` shared library package. CalibreQuarry relies on this external dependency.
|
|
32
|
+
|
|
33
|
+
## Conventions
|
|
34
|
+
- Single source of truth for version is `src/cquarry_cli/__init__.py`.
|
|
35
|
+
- Run tests with `./run_tests.sh`. Test the CLI, not just the functions.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vrnvctss
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|