sillsdev / sillsdev/python-sil-lift
Media hrefs resolve case-sensitively: Windows-authored folders get false missing-media on Linux
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1
- Forks
- 0
- Avg merge
- 10d 11h
- Merged PRs (30d)
- 6
Description
Lexicon.missing_media() resolves <media> and <illustration> hrefs with a plain is_file(), so a folder authored on Windows reports files as missing when it is read on a case-sensitive filesystem.
Dict.lift <illustration href="pictures\SDD.PNG"/>
pictures/sdd.png
Loads clean on Windows; on Linux sil-lift validate warns missing-media, and --strict fails the run. The image is right there.
The lookup is the two-candidate probe in missing_media() (src/sil_lift/_model.py):
candidates = [base / relative, base / subfolder[ref.kind] / relative]
if not any(candidate.is_file() for candidate in candidates):
This is the same Windows-authored/Linux-read mismatch that #19 fixed for .lift-ranges companions, in the one other place the library touches the filesystem.
Why this is not just "call _existing_file here too"
For a companion, folding the name is unambiguously right: resolve it or silently lose every range it defines. For media the opposite argument has real force. If an illustration href says SDD.PNG and the file is sdd.png, a web export, an APK build, or anything else serving that folder from a case-sensitive host will 404. A validator that silently resolves the mismatch reports a clean bill for a dictionary that is genuinely broken downstream — hiding the defect the check exists to surface.
Options:
- A. Fold silently. ~6 source lines. Consistent with companion resolution, kills the false positives, hides genuine portability defects.
- B. Fold, but report the mismatch as its own finding (
media-case-mismatch, warning).missing-mediagoes back to meaning "no such file under any spelling"; the new code says "found, but only case-insensitively — this will not survive a case-sensitive host." Costs a new problem code, which is a SemVer-covered interface here. - C. Leave it, document it. The status quo is at least honest about the portability problem, just unhelpfully worded and noisy.
B looks right, but it is a real interface decision and wants a deliberate call rather than a drive-by.
Two things to settle either way
- Only the final path component folds.
_existing_filesearches one directory listing for a name; it does not fold directory components. Media hrefs routinely includepictures/andaudio/, soPictures\x.pngagainst an on-diskpictures/would still misreport. Whether to fold directory components is more pressing here than it was for companions, where hrefs are basenames or same-folder relatives. - Cost.
missing_media()iterates every media ref in the document — thousands in a real dictionary — and media folders are large._existing_file'slistingscache has to be threaded across the whole loop so it is one directory read per folder per call, not one per reference.
Rough size
Option A: ~50 lines over 3 files. Option B: ~200-250 lines over ~10 — _model.py, _validate.py, _cli.py, docs/en/guides/{validate,cli,lift-export-interop}.md, a negative corpus fixture plus its PROVENANCE.md entry, test_validate.py, test_cli.py, and CHANGELOG.md.
Split out of review discussion on #19, which deliberately kept its scope to companion resolution.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/sil_lift/_model.py at missing_media() and compare its two-candidate probe with _existing_file and the companion-resolution change in #19. Decide between silent folding, a media-case-mismatch finding, or documentation, then trace the required validation, CLI, documentation, fixture, tests, and changelog updates; done means the chosen behavior is covered and cached directory lookup handles the full media loop.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100