fix: percent-encode books.json URLs (99.6% were malformed) - #70
Merged
Conversation
`generate_books_json.py` interpolated GCS object names into public URLs without encoding them. Object names contain spaces, non-ASCII (Hebrew, Portuguese), and characters like " and ?, so 19,667 of 19,754 entries (99.6%) carried malformed URLs. Only 87 were clean ASCII. This went unnoticed because Python `requests` silently auto-encodes, and our own example script uses requests. But `curl "<url>"` cannot parse a URL containing raw spaces and fails outright — so the curl command in our README's Quick Start was broken for 99.6% of texts, as it was for wget and any strict client (Go, Java). Fixed with urllib.parse.quote(name, safe="/"), which preserves path separators and encodes everything else. Encoded URLs are equivalent to raw ones for anyone already working around this, so the change is backward-safe. books.json is regenerated here rather than left to the next monthly run, so the URLs are correct now instead of in three weeks. Verified after regeneration: - total_texts 19754 and special_files 6623, both unchanged - the set of (title, language, versionTitle, categories) keys is identical - zero entries retain a raw space or non-ASCII character in any URL - every URL decodes back to exactly its previous value - curl returns 200 on encoded URLs that previously returned no response Note this only fixes the URL symptom. Titles containing " and ? are also invalid in Windows path names, so recursive bucket downloads still fail for those works on Windows — see #20, #33 and #42. That needs sanitising at the export layer and is tracked separately. Also dropped two pieces of cruft while here: - .DS_Store was tracked despite being listed in .gitignore (listing a file never untracks it), so macOS noise was shipping in a public repo. Untracked, still ignored. - .gitattributes contained a single Git LFS rule for links/links.csv, a file removed from the working tree in 2017. It has governed nothing for nine years, and after the history reset it governs nothing at all. The LFS object itself is preserved in Sefaria-Export-Archive. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019pxsazh62eqpiroSrY5rij
📊 Code Quality Score: 28/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
📊 Code Quality Score: 27/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
generate_books_json.pybuilt public GCS URLs by plain string interpolation, without percent-encoding the object name:GCS object names contain spaces, Hebrew, Portuguese accents, and characters like
"and?. 19,667 of 19,754 entries (99.6%) carried malformed URLs. Only 87 were clean ASCII.Why nobody noticed
Python
requestssilently auto-encodes, andexamples/download_from_books_json.pyusesrequests— so the documented Python path always worked.But
curlcannot parse a URL containing raw spaces and fails with no response at all. Thecurlcommand in our own README Quick Start was broken for 99.6% of texts, as it was forwgetand any strict client (Go, Java).curlrequestsThe fix
urllib.parse.quote(name, safe="/")— preserves path separators, encodes everything else. Encoded URLs are equivalent to raw ones for anyone already working around this, so it is backward-safe.books.jsonis regenerated here rather than waiting for the next monthly run, so URLs are correct now rather than in three weeks.Verification
After regenerating against the live bucket:
total_texts19754 andspecial_files6623 — both unchanged(title, language, versionTitle, categories)keys is identicalcurlreturns 200 on encoded URLs that previously returned no response30 tests pass, including new coverage for
%20, Hebrew, accented characters,%22/%3F, slash preservation, and clean-ASCII-unchanged.Scope note
This fixes only the URL symptom. Titles containing
"and?are also invalid in Windows path names, so recursive bucket downloads still fail for those works on Windows — see #20, #33 and #42. That needs sanitising at the export layer and is tracked separately. Both symptoms share one root cause: export paths are neither sanitised nor encoded.Also included
.DS_Storewas tracked despite being in.gitignore— listing a file never untracks it, so macOS noise was shipping in a public repo. Untracked, still ignored..gitattributesremoved. Its sole contents were a Git LFS rule forlinks/links.csv, a file deleted from the working tree in 2017. It has governed nothing for nine years. The LFS object itself is preserved in Sefaria-Export-Archive.🤖 Generated with Claude Code
https://claude.ai/code/session_019pxsazh62eqpiroSrY5rij