docs: add maintenance guide; fix AppImage version selection; bump to 1.1.0
- Add MAINTENANCE.md (dependency updates, EOL watch, build/smoke-test workflows, orientation-fix invariants) - Remove AGENTS.md; fold its unique context into MAINTENANCE.md - Add .venv/.posit/appimage to .dockerignore to shrink build context - Fix build-appimage.sh to select the wheel matching pyproject.toml version instead of alphabetically-first (bundled stale 1.0.0 code) - Bump version 1.0.0 -> 1.1.0 in pyproject.toml, uv.lock, AppImage recipe
This commit is contained in:
parent
5f71b61596
commit
c8194742d1
7 changed files with 289 additions and 158 deletions
|
|
@ -11,3 +11,6 @@ out
|
|||
.env
|
||||
.scanslicer
|
||||
.uv-cache
|
||||
.venv
|
||||
.posit
|
||||
appimage
|
||||
|
|
|
|||
152
AGENTS.md
152
AGENTS.md
|
|
@ -1,152 +0,0 @@
|
|||
# ScanSlicer (fork) — Project Guide
|
||||
|
||||
Purpose of this file: give any LLM working in this repo enough context to be
|
||||
effective without re-reading everything. Keep it current as the code changes.
|
||||
|
||||
## What this project is
|
||||
|
||||
ScanSlicer is a desktop Qt application (Python/PySide6) that detects multiple
|
||||
photos in a flatbed scan image, lets the user correct each box manually, then
|
||||
exports perspective-corrected crops. Inspired by
|
||||
[PhotoSlicer](https://github.com/francescovannini/photoslicer) (Francesco
|
||||
Vannini). Runs on Linux over Wayland or X11.
|
||||
|
||||
This repo is a **local fork** of
|
||||
[macrodev8/ScanSlicer](https://github.com/macrodev8/ScanSlicer) (upstream owner
|
||||
inactive). License: GNU GPL v3 (must be preserved). Attribution: keep upstream
|
||||
credit and the "inspired by PhotoSlicer" note; `pyproject.toml` lists both the
|
||||
fork maintainer and the upstream author, and `README.md` states the fork
|
||||
relationship and the changes made.
|
||||
|
||||
## Goals of this fork
|
||||
|
||||
1. Fix the mirrored-export orientation bug and add an explicit left/right
|
||||
orientation workflow. Implemented, tested in the GUI, and committed — see
|
||||
"The orientation fix" below. This was the primary patch.
|
||||
2. Keep the app usable on the maintainer's own photo scans; afterwards only
|
||||
minimal maintenance is expected.
|
||||
3. Push to the maintainer's Forgejo instance at `code.dgerdesmann.de` (no
|
||||
GitHub fork). Keep licensing, attribution, and repository description proper.
|
||||
|
||||
The maintainer is primarily an R user and new to Python/Git. Changes should be
|
||||
small, self-checked, clean, and secure; do not assume the maintainer can vet
|
||||
Python code.
|
||||
|
||||
## The orientation fix (implemented)
|
||||
|
||||
The bug: exported slices could come out mirrored (left/right swapped). Root
|
||||
cause is `PhotoSlice.normalize_top_left()` (in `slices.py`), which re-derives
|
||||
"top" from geometry — it picks a top-left corner and resolves winding so edge
|
||||
0→1 is the "most horizontal" top edge. That inference is ambiguous, and because
|
||||
`squarize()` and `reset_rotation()` both re-run `normalize_top_left()` at the
|
||||
end, any manual correction was silently overwritten.
|
||||
|
||||
The fix adds an explicit left/right orientation workflow:
|
||||
|
||||
- `PhotoSlice.swapped` — persistent flag (default `False`): "user has explicitly
|
||||
mirrored left/right".
|
||||
- `PhotoSlice.swap_left_right()` — toggles `swapped` and reindexes the corners
|
||||
`[TL,TR,BR,BL] -> [TR,TL,BL,BR]` (i.e. `bbox[[1,0,3,2]]`), a pure left/right
|
||||
mirror that keeps the top (edge 0→1) and bottom edges in place. NOTE: the
|
||||
earlier `[0,3,2,1]` reindex was wrong — it rotated the quad 90°.
|
||||
- `normalize_top_left()` applies the same `[1,0,3,2]` reindex when `swapped` is
|
||||
true (after its geometric inference), so manual orientation survives
|
||||
`squarize()` / `reset_rotation()`.
|
||||
- "Swap L/R" toolbar button (`ui_builders_preview.py`) ->
|
||||
`CanvasStateMixin.swap_active_slice_left_right()` ->
|
||||
`ScanSlicerCanvasActionsMixin.swap_active_box_left_right()`.
|
||||
- Visual indication in `CanvasRenderMixin.paintEvent()` (`canvas_render.py`):
|
||||
corners color-coded left = orange, right = cyan; edges colored red = top
|
||||
(0→1), green = right (1→2), orange = bottom (2→3), and the left edge (3→0)
|
||||
follows lock state (blue locked / lightgreen unlocked).
|
||||
|
||||
## Key implementation facts
|
||||
|
||||
- `PhotoSlice.bbox` is a 4×2 numpy array in the order
|
||||
`[top-left, top-right, bottom-right, bottom-left]`.
|
||||
- `Autoslicer.save_slice()` (in `autoslicer.py`) builds the perspective
|
||||
transform assuming the `[TL,TR,BR,BL]` order. Do NOT change that contract
|
||||
without updating every consumer.
|
||||
- `PhotoSlice.squarize()` and `reset_rotation()` call `normalize_top_left()` at
|
||||
the end; the `swapped` flag makes that safe for manual orientation.
|
||||
|
||||
## Repository structure
|
||||
|
||||
```
|
||||
scanslicer/ application source (package)
|
||||
entry.py CLI parsing, Wayland/X11 backend selection
|
||||
main.py QtScanSlicer main window, theme, app bootstrap
|
||||
controller*.py UI action handlers (status, canvas, detection,
|
||||
image I/O, params)
|
||||
ui_builders*.py widget construction (controls, preview, shared)
|
||||
canvas*.py interactive canvas (interaction/render/state mixins)
|
||||
slices.py PhotoSlice geometry model + polys_iou
|
||||
autoslicer.py detection/export engine wrapper (save_slice)
|
||||
autoslicer_detection.py detection pipelines, contour→box extraction
|
||||
autoslicer_feedback.py auto-tune profiles, scoring, feedback persistence
|
||||
params.py parameter model, defaults, presets
|
||||
packaging/appimage/ AppImage recipe + build scripts (preferred deploy)
|
||||
Dockerfile container runtime image
|
||||
docker-compose.yml GUI container wiring
|
||||
pyproject.toml package metadata + dependencies (uv.lock pinned)
|
||||
docs/ user-guide, architecture, parameters, autotune,
|
||||
runtime-config, appimage, development
|
||||
```
|
||||
|
||||
## Architecture in brief
|
||||
|
||||
- `QtScanSlicer` (`main.py`) is a `QMainWindow` composed from UI builder mixins
|
||||
and controller mixins.
|
||||
- `QtSlicingCanvas` (`canvas.py`) = interaction + render + state mixins; holds
|
||||
the image, zoom/pan state, and the list of `PhotoSlice` objects.
|
||||
- Background work (detection, auto-tune) runs on a single-worker `QThreadPool`;
|
||||
results are delivered back to the UI via Qt signals.
|
||||
- Export flow: `save_all()` (`controller_image_io.py`) loops over locked slices
|
||||
and calls `Autoslicer.save_slice(bbox, path, params)` for each.
|
||||
|
||||
## Run / build
|
||||
|
||||
```bash
|
||||
uv sync --frozen
|
||||
uv run scanslicer /path/to/scans # or: python -m scanslicer
|
||||
```
|
||||
|
||||
- AppImage (preferred): `bash packaging/appimage/build-appimage.sh`
|
||||
- AppImage via Docker: `bash packaging/appimage/build-appimage-docker.sh`
|
||||
- Docker runtime: `docker compose up --build`
|
||||
- Dependencies (from `pyproject.toml`): PySide6, opencv-python-headless, numpy.
|
||||
- Python >= 3.10; dev env is Python 3.12 in `.venv`.
|
||||
|
||||
Dependency / supply-chain decisions (deliberate — keep them):
|
||||
- `opencv-python-headless` is intentional: the app uses no OpenCV GUI/highgui.
|
||||
- Pillow was removed (it was unused). Don't re-add without a concrete need.
|
||||
- The AppImage build exports hashes from `uv.lock` and installs with
|
||||
`pip install --require-hashes`.
|
||||
|
||||
### AppImage build: Docker context gotcha
|
||||
|
||||
The maintainer's Docker points at Docker Desktop (`desktop-linux` context). Its
|
||||
bind-mount filesystem forbids `chown`, but `appimage-builder` needs root
|
||||
ownership while extracting `.deb` packages, so the build fails with
|
||||
`dpkg-deb ... Cannot change ownership to uid 0, gid 0: Operation not permitted`.
|
||||
|
||||
Workaround: run the Dockerized build against the native daemon (or switch
|
||||
context with `docker context use default`):
|
||||
|
||||
```bash
|
||||
DOCKER_HOST=unix:///var/run/docker.sock bash packaging/appimage/build-appimage-docker.sh
|
||||
```
|
||||
|
||||
Output lands in `appimage/dist/ScanSlicer-<version>-x86_64.AppImage` (the
|
||||
`appimage/` dir is git-ignored).
|
||||
|
||||
## Config / persistence
|
||||
|
||||
Runtime files live in `~/.config/scanslicer/` (or `$XDG_CONFIG_HOME/scanslicer/`)
|
||||
by default: `defaults.json`, `presets.json`, `autotune-feedback.json`,
|
||||
`status.log`. Paths are overridable via `SCANSLICER_*_PATH` env vars. In the
|
||||
Docker setup these land in `./.scanslicer/` on the host.
|
||||
|
||||
## Notes
|
||||
|
||||
- No automated test suite exists; validate changes by running the app on sample scans (startup, detection, save, auto-tune).
|
||||
266
MAINTENANCE.md
Normal file
266
MAINTENANCE.md
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
# Maintaining ScanSlicer
|
||||
|
||||
This file is a how-to for keeping the fork alive over time. The goals are
|
||||
narrow and deliberate:
|
||||
|
||||
1. **Keep the app functional** for its one real job (detect photos in a flatbed
|
||||
scan, correct the boxes, export straightened crops).
|
||||
2. **Avoid security issues and breakage from end-of-life (EOL) components.**
|
||||
|
||||
There is **no ambition to develop new features**. Maintenance is manual: when
|
||||
something drifts out of date, you bump a version, re-verify the app, and commit.
|
||||
Do not add features, refactor, or "improve" things while doing maintenance —
|
||||
small, focused changes only.
|
||||
|
||||
> Scope guard: this repo is a local fork of `macrodev8/ScanSlicer`, published at
|
||||
> `https://code.dgerdesmann.de/dan/ScanSlicer.git`. License is GPL v3. Keep the
|
||||
> upstream credit and the "inspired by PhotoSlicer" note intact. See `README.md`
|
||||
> and `docs/` for project context.
|
||||
|
||||
---
|
||||
|
||||
## Where things live
|
||||
|
||||
| Component | File(s) |
|
||||
|---|---|
|
||||
| Package metadata + dependency constraints | `pyproject.toml` |
|
||||
| **Pinned** dependency versions (source of truth) | `uv.lock` |
|
||||
| Runtime container image | `Dockerfile` (ubuntu:24.04 + uv) |
|
||||
| AppImage recipe + build scripts | `packaging/appimage/` |
|
||||
| Bundled third-party license notice | `THIRD_PARTY_NOTICES` |
|
||||
| Dev env (Python 3.12) | `.venv/` (managed by uv) |
|
||||
|
||||
Dependency management is done with **uv**. `pyproject.toml` declares the
|
||||
requirements (mostly loose), and `uv.lock` pins the *exact* versions that get
|
||||
installed and shipped. `uv.lock` is committed — do not edit it by hand; let uv
|
||||
rewrite it.
|
||||
|
||||
---
|
||||
|
||||
## Code invariants (orientation fix + bbox order)
|
||||
|
||||
This fork's one real code change is the mirrored-export orientation fix. Keep
|
||||
these invariants in mind when touching geometry code.
|
||||
|
||||
- **`PhotoSlice.bbox` is a 4×2 numpy array in the order
|
||||
`[top-left, top-right, bottom-right, bottom-left]`.** `Autoslicer.save_slice()`
|
||||
(`autoslicer.py`) builds the perspective transform assuming that order. Do NOT
|
||||
change this contract without updating every consumer.
|
||||
- **`PhotoSlice.swapped`** (default `False`) is the persistent "user explicitly
|
||||
mirrored left/right" flag. `swap_left_right()` toggles it and reindexes
|
||||
corners `[TL,TR,BR,BL] -> [TR,TL,BL,BR]` (`bbox[[1,0,3,2]]`) — a pure
|
||||
left/right mirror that keeps the top and bottom edges in place.
|
||||
- **Root cause of the original bug:** `normalize_top_left()` (`slices.py`)
|
||||
re-derives "top" from geometry, which is ambiguous, and `squarize()` /
|
||||
`reset_rotation()` both re-run it at the end, silently overwriting manual
|
||||
corrections. The fix makes `normalize_top_left()` apply the same `[1,0,3,2]`
|
||||
reindex when `swapped` is true, so manual orientation survives. (Historical:
|
||||
an earlier `[0,3,2,1]` reindex was wrong — it rotated the quad 90°.)
|
||||
- **UI wiring:** "Swap L/R" button (`ui_builders_preview.py`) →
|
||||
`CanvasStateMixin.swap_active_slice_left_right()` (`canvas_state.py`) →
|
||||
`ScanSlicerCanvasActionsMixin.swap_active_box_left_right()`
|
||||
(`controller_canvas_actions.py`) → `PhotoSlice.swap_left_right()`.
|
||||
- **Visual color coding** (`canvas_render.py`): corners — left = orange, right
|
||||
= cyan; edges — red = top (0→1), green = right (1→2), orange = bottom (2→3),
|
||||
left edge (3→0) follows lock state (blue locked / lightgreen unlocked).
|
||||
|
||||
---
|
||||
|
||||
## Current pinned versions (snapshot)
|
||||
|
||||
Update this table whenever you bump something, so the next session has a
|
||||
starting point.
|
||||
|
||||
| Component | Pinned version | Where |
|
||||
|---|---|---|
|
||||
| PySide6 / PySide6-Addons / -Essentials / shiboken6 | 6.10.2 | `uv.lock` |
|
||||
| opencv-python-headless | 4.13.0.92 | `uv.lock` (constraint `~=4.13.0` in `pyproject.toml`) |
|
||||
| numpy | 2.2.6 (Py<3.11) / 2.4.2 (Py≥3.11) | `uv.lock` |
|
||||
| Python (dev env) | 3.12 | `.venv` |
|
||||
| Python floor | `>=3.10` | `pyproject.toml` |
|
||||
| uv (both Dockerfiles) | 0.10.2 | `Dockerfile`, `packaging/appimage/Dockerfile` |
|
||||
| appimage-builder | 1.1.0 | `packaging/appimage/Dockerfile` |
|
||||
| AppImage base OS | Ubuntu **noble** (24.04) | `packaging/appimage/AppImageBuilder.yml` |
|
||||
| Runtime image base | Ubuntu 24.04 | `Dockerfile` |
|
||||
|
||||
---
|
||||
|
||||
## What can go stale, and the priority order
|
||||
|
||||
Review these roughly in this order — the first items are the real security/EOL
|
||||
surface; the last ones are packaging plumbing that only matters at build time.
|
||||
|
||||
1. **PySide6 / Qt** — the largest attack surface and the component with the
|
||||
most aggressive EOL cadence. Qt 6.x minor releases stop receiving updates
|
||||
quickly; PySide6 tracks Qt. Keep this on a recent 6.x.
|
||||
2. **opencv-python-headless** — image processing; bump to the latest 4.x.
|
||||
3. **numpy** — bump to the latest 2.x.
|
||||
4. **Python** — the *shipped* runtime is what matters. The AppImage bundles its
|
||||
own Python (from Ubuntu noble, currently 3.12), so the app does not run on
|
||||
the host's Python. The `requires-python = ">=3.10"` floor only affects
|
||||
development resolution. Watch Python 3.10's EOL: when it goes EOL, raise the
|
||||
floor (e.g. to `>=3.11`) so no EOL interpreter is ever considered valid.
|
||||
5. **Packaging toolchain** — `uv` and `appimage-builder` versions pinned in the
|
||||
two Dockerfiles. Only bump these when you have a reason (build breaks, or a
|
||||
notable security fix in the tool itself).
|
||||
6. **Ubuntu base images** — `noble` is an LTS (supported to ~2029). Revisit
|
||||
the apt source and GPG key in `AppImageBuilder.yml` and the `FROM` line in
|
||||
both Dockerfiles when noble approaches EOL.
|
||||
|
||||
Suggested cadence: check PyPI/upstream releases every ~3–6 months, or promptly
|
||||
when a security advisory is published for any of the above.
|
||||
|
||||
---
|
||||
|
||||
## Updating Python dependencies
|
||||
|
||||
All commands run from the repo root. The dev env is `.venv` (Python 3.12).
|
||||
|
||||
### 1. Bring the environment up to the committed lock (baseline)
|
||||
|
||||
```bash
|
||||
uv sync --frozen
|
||||
```
|
||||
|
||||
### 2. Bump a single dependency to its latest
|
||||
|
||||
```bash
|
||||
uv lock --upgrade-package PySide6
|
||||
uv lock --upgrade-package opencv-python-headless
|
||||
uv lock --upgrade-package numpy
|
||||
```
|
||||
|
||||
`--dry-run` previews the change without touching anything:
|
||||
|
||||
```bash
|
||||
uv lock --upgrade-package PySide6 --dry-run
|
||||
```
|
||||
|
||||
To bump *everything* at once (use sparingly — harder to bisect if something
|
||||
breaks):
|
||||
|
||||
```bash
|
||||
uv lock --upgrade
|
||||
```
|
||||
|
||||
### 3. Install the updated set and verify
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
uv run scanslicer /path/to/test/scans
|
||||
```
|
||||
|
||||
Then run the smoke-test checklist below.
|
||||
|
||||
### Special case: opencv major/minor bump
|
||||
|
||||
`opencv-python-headless` is the **only** dependency with a constraint in
|
||||
`pyproject.toml` (`~=4.13.0`), which pins it to the 4.13.x line. To move to
|
||||
4.14+, edit that constraint in `pyproject.toml` first, then run
|
||||
`uv lock --upgrade-package opencv-python-headless`. PySide6 and numpy are
|
||||
unpinned in `pyproject.toml`, so uv can move them freely.
|
||||
|
||||
### After any version change
|
||||
|
||||
- Commit `pyproject.toml` (if edited) **and** `uv.lock` together.
|
||||
- Update the version table above.
|
||||
- Update `THIRD_PARTY_NOTICES` — it lists concrete PySide6/Qt, numpy, and
|
||||
opencv versions, and it ships inside every AppImage. Keep it aligned with
|
||||
`uv.lock`.
|
||||
- Rebuild and smoke-test the AppImage if the runtime stack (PySide6/Qt) changed.
|
||||
|
||||
---
|
||||
|
||||
## Updating the AppImage packaging toolchain
|
||||
|
||||
The AppImage build pins its own tool versions in `packaging/appimage/Dockerfile`:
|
||||
|
||||
- `uv` (`COPY --from=ghcr.io/astral-sh/uv:0.10.2 ...`)
|
||||
- `appimage-builder==1.1.0` (an `ARG` near the top)
|
||||
|
||||
Bump either by editing that file. If you change `appimage-builder`, the
|
||||
`AppImageBuilder.yml` recipe may need adjusting for new versions (rare). The
|
||||
Ubuntu apt source and GPG key live in `AppImageBuilder.yml` — update those when
|
||||
noble goes EOL or the key rotates.
|
||||
|
||||
> **Hardcoded Python paths:** `AppImageBuilder.yml` hardcodes `python3.12` in
|
||||
> `QT_PLUGIN_PATH` and `LD_LIBRARY_PATH`. If the AppImage base OS ever moves to
|
||||
> a different Python minor, those two lines must be updated to match.
|
||||
|
||||
---
|
||||
|
||||
## Updating the runtime Docker image
|
||||
|
||||
`Dockerfile` (repo root) pins the base (`ubuntu:24.04`) and `uv 0.10.2`.
|
||||
Bump these when needed, then rebuild and run the container smoke test:
|
||||
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verifying a change (smoke-test checklist)
|
||||
|
||||
There is **no automated test suite**. After any dependency or packaging change,
|
||||
manually confirm the app still works:
|
||||
|
||||
1. **Startup** on both Wayland and X11:
|
||||
```bash
|
||||
uv run scanslicer --backend wayland
|
||||
uv run scanslicer --backend x11
|
||||
```
|
||||
2. **Detection** on a representative sample scan (boxes appear on load/Detect).
|
||||
3. **Save flow** — lock a box, export, confirm the output is straight and not
|
||||
mirrored (this fork's orientation fix is the thing most likely to regress).
|
||||
4. **Auto-tune** — run a profile and confirm feedback is written/read without
|
||||
error.
|
||||
5. If the runtime stack changed: rebuild the AppImage and confirm it launches
|
||||
and saves.
|
||||
6. If the Docker image changed: `docker compose up --build` and confirm the app
|
||||
opens.
|
||||
|
||||
---
|
||||
|
||||
## The Docker gotcha (recap — keep this in mind)
|
||||
|
||||
The maintainer's Docker points at **Docker Desktop** (`desktop-linux` context).
|
||||
Its bind-mount filesystem forbids `chown`, but `appimage-builder` needs root
|
||||
ownership while extracting `.deb` packages, so the Dockerized AppImage build
|
||||
fails with:
|
||||
|
||||
```
|
||||
dpkg-deb ... Cannot change ownership to uid 0, gid 0: Operation not permitted
|
||||
```
|
||||
|
||||
Workaround: run the build against the **native** daemon instead:
|
||||
|
||||
```bash
|
||||
DOCKER_HOST=unix:///var/run/docker.sock bash packaging/appimage/build-appimage-docker.sh
|
||||
```
|
||||
|
||||
(or `docker context use default` first). Output lands in
|
||||
`appimage/dist/ScanSlicer-<version>-x86_64.AppImage` (the `appimage/` dir is
|
||||
git-ignored).
|
||||
|
||||
---
|
||||
|
||||
## Commit / release hygiene
|
||||
|
||||
- Commit `uv.lock` and `pyproject.toml` (and `THIRD_PARTY_NOTICES` when
|
||||
applicable) together as a single change.
|
||||
- Write a short, factual commit message, e.g. `Bump PySide6 to 6.10.x`.
|
||||
- Push to the Forgejo remote: `git push origin`.
|
||||
- The AppImage build verifies package hashes (`--require-hashes`) from
|
||||
`uv.lock`; publishing the AppImage alongside the matching committed source is
|
||||
already handled by committing before building.
|
||||
|
||||
---
|
||||
|
||||
## One-line summary
|
||||
|
||||
Bump PySide6/Qt first and most often; bump opencv and numpy when convenient;
|
||||
treat uv/appimage-builder/Ubuntu as build plumbing you only touch when
|
||||
necessary. After every change, run the smoke-test checklist, rebuild the
|
||||
AppImage if the runtime stack moved, and commit `uv.lock` + `pyproject.toml`
|
||||
together.
|
||||
|
|
@ -6,7 +6,7 @@ AppDir:
|
|||
id: scanslicer
|
||||
name: ScanSlicer
|
||||
icon: scanslicer
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
exec: usr/bin/python3
|
||||
exec_args: "-m scanslicer $@"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,25 @@ uv export \
|
|||
--no-emit-project \
|
||||
--format requirements-txt \
|
||||
--output-file "${BUILD_DIR}/requirements.txt"
|
||||
# Remove stale wheels from previous versions so a version-specific lookup
|
||||
# below cannot accidentally pick up an outdated build artifact.
|
||||
rm -f "${BUILD_DIR}"/scanslicer-*.whl
|
||||
uv build --wheel --out-dir "${BUILD_DIR}"
|
||||
|
||||
WHEEL_PATH="$(ls -1 "${BUILD_DIR}"/scanslicer-*.whl | head -n 1)"
|
||||
if [[ -z "${WHEEL_PATH}" ]]; then
|
||||
echo "Could not find built wheel in ${BUILD_DIR}" >&2
|
||||
# Select the wheel matching the project version from pyproject.toml. Listing
|
||||
# with `ls` and taking the first result breaks once an older wheel for a
|
||||
# previous version is left in the build dir, because `ls` sorts
|
||||
# alphabetically and would pick the stale artifact.
|
||||
PROJECT_VERSION="$(sed -n 's/^version *= *"\([^"]*\)".*/\1/p' "${ROOT_DIR}/pyproject.toml" | head -n 1)"
|
||||
if [[ -z "${PROJECT_VERSION}" ]]; then
|
||||
echo "Could not determine project version from pyproject.toml" >&2
|
||||
exit 1
|
||||
fi
|
||||
WHEEL_PATH="${BUILD_DIR}/scanslicer-${PROJECT_VERSION}-py3-none-any.whl"
|
||||
if [[ ! -f "${WHEEL_PATH}" ]]; then
|
||||
echo "Could not find built wheel for version ${PROJECT_VERSION} in ${BUILD_DIR}" >&2
|
||||
echo "Found wheels:" >&2
|
||||
ls -1 "${BUILD_DIR}"/scanslicer-*.whl >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "scanslicer"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
description = "Detect, straighten and save photos from a flatbed scanner source image"
|
||||
readme = { file = "README.md", content-type = "text/markdown" }
|
||||
requires-python = ">=3.10"
|
||||
|
|
|
|||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -222,7 +222,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "scanslicer"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue