Document dist-cache gotcha for python_depends changes, Settings label bug
CLAUDE.md was out of date after this session's two on-device fixes
(commit d276f88): still described the kivy recipe as python_depends=[]
(filetype is back), and didn't mention the p4a dist-caching trap that
made the filetype fix silently ineffective until the stale dist
directory was deleted, or the Settings popup label wrapping bug.
Cross-referenced with android-app-template's CLAUDE.md, which hit the
same label bug in more places.
This commit is contained in:
parent
d276f8842f
commit
4a617469b8
1 changed files with 73 additions and 17 deletions
90
CLAUDE.md
90
CLAUDE.md
|
|
@ -9,11 +9,13 @@ Context for future Claude sessions working on this repo.
|
|||
relocatable data path, taskbar icon, "Time Since" column.
|
||||
- Repo is pushed to `repo.tas-tech.net/tas-tech.net/event-tracker`
|
||||
(private — will go public once there's a tagged release).
|
||||
- **Android build (`android/`) works end-to-end** — `./build.sh android
|
||||
debug` produces `android/bin/eventtracker-0.1-arm64-v8a-debug.apk`.
|
||||
Confirmed via a full `BUILD SUCCESSFUL` Gradle run, not just "recipes
|
||||
compiled." Three real, distinct bugs had to be fixed to get here (all
|
||||
now baked into `build.sh`/`buildozer.spec`, nothing left to redo):
|
||||
- **Android build (`android/`) works end-to-end AND is confirmed running
|
||||
on-device** — `./build.sh android debug` produces
|
||||
`android/bin/eventtracker-0.1-arm64-v8a-debug.apk`, installs, and
|
||||
launches clean (`adb logcat` shows `Start application main loop`, no
|
||||
crash). Five real, distinct bugs had to be fixed to get here (all now
|
||||
baked into `build.sh`/`buildozer.spec`/`main.py`, nothing left to
|
||||
redo):
|
||||
1. p4a's `kivy` recipe pulling in unused `requests`/`charset-normalizer`
|
||||
that couldn't actually install — `android/p4a-recipes/kivy`.
|
||||
2. p4a's own internal pymodules venv corrupting itself on every
|
||||
|
|
@ -21,9 +23,19 @@ Context for future Claude sessions working on this repo.
|
|||
3. Gradle's build-script compiler rejecting this machine's default JDK
|
||||
(java-26) — `build.sh` pins `JAVA_HOME` to `java-17-openjdk` for
|
||||
just this build.
|
||||
4. Fix #1 above was applied too aggressively and dropped `filetype`
|
||||
too, which `kivy/core/image` genuinely needs — on-device startup
|
||||
crash (`ModuleNotFoundError: No module named 'filetype'`). Restored
|
||||
just `filetype`.
|
||||
5. p4a caches a built dist by recipe-name match and never re-derives
|
||||
a recipe's `python_depends` for an existing dist, so fix #4 above
|
||||
silently had zero effect until the stale dist directory
|
||||
(`.buildozer/android/platform/build-<arch>/dists/eventtracker`) was
|
||||
deleted to force a re-derive. Traced end-to-end through
|
||||
`pythonforandroid/distribution.py`/`graph.py`, not guessed — see
|
||||
the dedicated entry below.
|
||||
See "Android companion — design decisions" below for the full
|
||||
root-cause writeup on each. Not yet installed/tested on an actual
|
||||
phone — that's the next real checkpoint, not another build fix.
|
||||
root-cause writeup on each.
|
||||
- **Outstanding, agreed but not implemented**: split `config.json` into
|
||||
two files — event list (safe to sync between machines) vs. data file
|
||||
path (must stay local per-device, same principle as the Android app's
|
||||
|
|
@ -158,6 +170,18 @@ android/
|
|||
- **No matplotlib on Android** — unreliable through Kivy's garden
|
||||
packaging. `BarRow` in `main.py` hand-draws a proportional bar with
|
||||
Kivy's own `Color`/`Rectangle` canvas primitives instead.
|
||||
- **Wrapping `Label`s bind `text_size` to their own `width`, never set
|
||||
it once from `self.width` in a `Popup.__init__`** — `SettingsPopup`'s
|
||||
info label originally did `text_size=(self.width, None)` at
|
||||
construction time, but the Popup hasn't been laid out yet at that
|
||||
point, so `self.width` is Kivy's ~100px pre-layout default rather
|
||||
than the popup's real size. That locked the label into wrapping at
|
||||
~100px forever — rendered on-device as a 1-character-wide vertical
|
||||
column of text. Fixed by binding instead:
|
||||
`label.bind(width=lambda inst, w: setattr(inst, "text_size", (w, None)))`
|
||||
after construction. Same bug, same fix, also applied to
|
||||
`android-app-template`'s `SettingsPopup`/`LegalPopup` (that repo had
|
||||
it in four places) — see that repo's `CLAUDE.md`.
|
||||
- **Config path is local-only, same principle as desktop's `CONFIG_PATH`**
|
||||
— each device's app-private storage holds only that device's CSV
|
||||
path; it is never itself synced. Only the CSV — the actual data — goes
|
||||
|
|
@ -192,11 +216,11 @@ android/
|
|||
- **`p4a-recipes/kivy` — local override, not a workaround** — p4a's own
|
||||
built-in `kivy` recipe declares
|
||||
`python_depends = ['certifi', 'chardet', 'idna', 'requests', 'urllib3', 'filetype']`
|
||||
(for `kivy.network.UrlRequest`, which this app never calls).
|
||||
`requests` transitively needs `charset-normalizer`, whose newest
|
||||
release is the first to ship a prebuilt Android-tagged wheel (new,
|
||||
tied to CPython 3.14's official Android build target). p4a's own
|
||||
dependency resolver (`process_python_modules` in
|
||||
(most of that list only for `kivy.network.UrlRequest`, which this app
|
||||
never calls). `requests` transitively needs `charset-normalizer`,
|
||||
whose newest release is the first to ship a prebuilt Android-tagged
|
||||
wheel (new, tied to CPython 3.14's official Android build target).
|
||||
p4a's own dependency resolver (`process_python_modules` in
|
||||
`pythonforandroid/build.py`) finds that wheel correctly during its
|
||||
`pip --dry-run --platform=android_24_arm64_v8a` pass and pins the
|
||||
exact URL into a generated `requirements.txt` — but the *next* stage
|
||||
|
|
@ -206,11 +230,43 @@ android/
|
|||
p4a bug, confirmed by reading `pythonforandroid/build.py` directly
|
||||
(not guessed) — and `python_depends` isn't something `buildozer.spec`
|
||||
can override, so `p4a-recipes/kivy/__init__.py` is a full copy of the
|
||||
upstream recipe (patches included) with just `python_depends = []`.
|
||||
`buildozer.spec` points at it via `p4a.local_recipes = p4a-recipes`.
|
||||
If a future Kivy release actually needs one of those network extras,
|
||||
re-diff against p4a's current `pythonforandroid/recipes/kivy/__init__.py`
|
||||
before blindly re-adding them.
|
||||
upstream recipe (patches included) keeping only `filetype` —
|
||||
`kivy/core/image/__init__.py` imports it directly for image format
|
||||
sniffing, confirmed by an on-device startup crash
|
||||
(`ModuleNotFoundError: No module named 'filetype'`) the one time it
|
||||
got dropped along with the rest. `filetype` is pure Python with zero
|
||||
dependencies of its own, so it doesn't reintroduce the
|
||||
requests/charset-normalizer chain. `buildozer.spec` points at the
|
||||
override via `p4a.local_recipes = p4a-recipes`. If a future Kivy
|
||||
release actually needs one of the other four back, re-diff against
|
||||
p4a's current `pythonforandroid/recipes/kivy/__init__.py` before
|
||||
blindly re-adding them.
|
||||
- **Editing `p4a-recipes/kivy/__init__.py` alone is not enough — p4a
|
||||
caches the built dist and may never re-read it.** `Distribution.get_
|
||||
distribution()` (`pythonforandroid/distribution.py`) matches an
|
||||
existing dist purely by name (`eventtracker`) and recipe-name list
|
||||
(`python3`, `kivy`, etc. — from `buildozer.spec`'s `requirements =`
|
||||
line). `python_depends` isn't a recipe name, so it's never consulted
|
||||
during that match; if a dist with the same name+recipes already
|
||||
exists, it's reused wholesale with `needs_build = False`, and
|
||||
`build_dist_from_args()` — the only function that reads
|
||||
`recipe.python_depends` and pip-installs pymodules
|
||||
(`graph.py:334` → `run_pymodules_install`) — never runs at all. This
|
||||
is exactly what happened restoring `filetype`: the recipe file was
|
||||
correct on disk, but the next build reused the stale dist and the
|
||||
APK still crashed identically. Confirmed two ways: unpacked the built
|
||||
APK's `libpybundle.so` and found no `filetype` anywhere in it, then
|
||||
traced the caching logic in `distribution.py`/`graph.py` line by
|
||||
line. Fix: delete the stale dist directory so
|
||||
`Distribution.get_distributions()`'s glob finds nothing and
|
||||
`needs_build` falls back to `True` —
|
||||
`rm -rf android/.buildozer/android/platform/build-<arch>/dists/<package.name>`
|
||||
— then rebuild. This only redoes packaging (pymodule install +
|
||||
Gradle assembly), not the expensive native recipe compilation, so
|
||||
it's fast (single-digit seconds of Gradle work in practice). Anytime
|
||||
a *recipe's* `python_depends` changes (not `buildozer.spec`'s
|
||||
`requirements =` line, which p4a does check), delete the dist before
|
||||
the next build or the change silently won't take effect.
|
||||
- **Previously-tried and reverted**: `--system-site-packages` on the
|
||||
build venv. It fixed the `--user`/pip-in-venv error above, but leaked
|
||||
the real system Python's installed packages into what p4a decided the
|
||||
|
|
|
|||
Loading…
Reference in a new issue