Repository navigation
fix(mirror): replace embeddable Windows Python with full builds - #294
Merged
Merged
Conversation
… zips For Python versions python-build-standalone has no Windows build for, the mirror served python.org's embeddable zips. Those are a trimmed runtime for embedding in an application: a ._pth file puts them in isolated mode (a script's own directory is not on sys.path and PYTHONPATH is ignored), and they have no venv, ensurepip, headers or tkinter. The mirror now assembles a full build of the same release instead, on the existing Linux runner: - windows-amd64: python.org's per-component MSIs (core, exe, lib, dev, tcltk), each verified against its .asc signature from the Windows release signing key (pinned in keys/, fingerprint checked) and unpacked with msiextract from msitools. - windows-arm64: python.org's pythonarm64 NuGet packages, verified against the SHA-512 in nuget.org's catalog, keeping only tools/. x64 NuGet packages are not used: some (3.5.2, 3.5.3, 3.6.0) lack venv and ensurepip. Both are packed reproducibly as a .tar.gz with everything under python/, the layout of python-build-standalone's Windows archives, so dtvem installs them unchanged. Each is checked to be a full install (no ._pth, venv, ensurepip, headers, import library, and tkinter for MSI builds); an upstream build that is not is skipped rather than published, without failing the run. MirrorJob gains an optional Build step used in place of a download. The new sources run after python-build-standalone, so it still wins where it has a build. Archives go to new .tar.gz keys rather than overwriting the old .zip objects, which are cached as immutable and still referenced by released dtvem binaries. A sync-only run now also treats an assembled job as pending until its archive exists, since its metadata already exists from the old zip. mirror-sync installs msitools for the Python job, and a new mirror-tool workflow vets and tests this module, which Build & Test does not cover.
python.org's embeddable Windows package ships a pythonXY._pth file that runs Python in isolated mode: a script cannot import modules sitting next to it, PYTHONPATH is ignored, and site-packages is off. The installer used to uncomment "import site" in that file, which brought back site-packages but left the isolation. The installer now renames the file to pythonXY._pth.disabled instead. Python only looks for the exact name, so the install behaves like a regular one, and the rename can be undone. The mirror serves full builds for every affected version except 3.5.2 (its MSIs are unsigned and its NuGet package incomplete), so this is the fallback for that version and any embeddable build still served. A new dtvem doctor check (python-isolated-mode) flags installed Python versions that still have a ._pth file, such as ones installed by older releases. --fix applies the same rename in place; the resolution also recommends reinstalling to get a full build with venv, headers and tkinter. The shared logic lives in a small internal/pth package. getPipURL now uses the version-specific get-pip.py for Python 3.9 as well: the main script requires 3.10+, so pip setup failed for 3.9 installs that rely on the get-pip.py fallback (embeddable builds).
5 tasks
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.
Description
For Python versions python-build-standalone has no Windows build for (72
windows-amd64, 19windows-arm64), dtvem served python.org's embeddable zips. Those run in isolated mode because of apythonXY._pthfile: a script can't import modules next to it andPYTHONPATHis ignored. They also lackvenv,ensurepip, C headers and tkinter.This PR makes the mirror assemble a full build of the same release instead, on the existing Linux runner. It also makes the installer and
dtvem doctordeal with the embeddable builds that remain.Type of Change
Related Issues
Resolves #293
Relates to #113
Changes Made
Mirror (
scripts/mirror-binaries), commit 1windows-amd64: python.org's per-component MSIs (core,exe,lib,dev,tcltk):.ascsignature using python.org's Windows signing key. The key is committed inkeys/, its fingerprint is pinned in code, and verification happens in Go withProtonMail/go-crypto, a dependency of the mirror module only.msiextractfrom msitools.amd64/folder has all five MSIs with signatures. 3.14+ uses Sigstore only.windows-arm64: python.org'spythonarm64NuGet packages. Each is verified against the SHA-512 in nuget.org's catalog, and onlytools/is kept.venvandensurepip, while 3.5.4 and 3.6.8 are full, so there's no clean cutoff..tar.gzwith everything underpython/. That's python-build-standalone's Windows layout, so the client installs them unchanged.._pth, plusvenv,ensurepip, headers, the import library, and tkinter for MSI builds.errNotFullBuild).MirrorJobgains an optionalBuildstep that's used in place of a download..tar.gzkeys. The old.zipobjects aren't overwritten, because they're cached as immutable and released dtvem binaries reference them.--sync-onlyused to skip any job whose.meta.jsonexisted, and the old zips' metadata already exists. An assembled job now also stays pending until its archive exists. This applies toBuildjobs only, so other runtimes keep today's behaviour.mirror-sync.ymlinstalls msitools for the Python job.mirror-tool.ymlvets and race-tests this module on PRs. It's a separate Go module, so Build & Test doesn't cover it.Client (
src/), commit 2pythonXY._pthtopythonXY._pth.disabledinstead of uncommentingimport site. This turns isolated mode off for any embeddable build still installed. The only one left after the mirror runs is 3.5.2: its MSIs are unsigned and its NuGet package is incomplete.dtvem doctorcheckpython-isolated-mode: flags installed versions that still have a._pthfile.--fixapplies the rename in place, and the resolution text recommends reinstalling for a full build. The shared logic is in a newinternal/pthpackage.getPipURL: now uses the version-specificget-pip.pyfor 3.9 too. The main script requires 3.10+, so pip setup failed today for any 3.9 install relying on theget-pip.pyfallback; released dtvem 0.6.5 fails the same way.Testing
Test Environment
ubuntu:24.04/golang:1.25containers (mirror)Test Steps
go test ./src/...all 27 packages pass. The new tests coverinternal/pth, the doctor check (flag, fix, re-run OK, registered) and thegetPipURL3.9 case.go vetpasses on Windows and on Linux (GOOS=linux).go test -racepasses in a Linux container.httptestservers and a fake extractor. They cover signature checks (good, tampered, wrong signer, wrong pinned fingerprint), discovery for both sources, MSI and NuGet assembly (including URI-escaped names and dropped packaging files), reproducibility, rejection of embeddable or incomplete trees,pendingJobs,recordResult,fetchBinaryand source order.MIRROR_NETWORK_TESTS=1, Linux container with msitools):dtvem install, with no client changes, of the Linux-built 3.5.0, 3.9.11 and 3.12.2 archives on Windows 11. They were served locally through a seeded manifest cache in an isolatedDTVEM_ROOT.dtvem doctor: ran against the 0.6.5 install.Test Results
Converted archives installed with
dtvem install:PYTHONPATHScripts\pip.exe/ pippython -m venvThe embeddable 3.9.9 from today's mirror:
sys.flags.isolatedpython39._pth.disabled)PYTHONPATHvenv, tkinterdtvem doctoron the 0.6.5 install reported⚠ Python versions run in isolated mode (embeddable builds) [fixable], listingPython 3.9.9: python39._pth, and its fix renamed the file.Checklist
golangci-lint runand fixed all issues (includes gofmt, govet, and 40+ linters)go mod tidyto clean up dependencies (mirror module: addsgithub.com/ProtonMail/go-crypto; main module unchanged)go test ./...)Breaking Changes
None.
Rollout
The mirror change takes effect on the next Mirror Sync run (daily, or dispatch it for
python).Additional Notes
._pth.disabled.stale-shims-pathWindows fix rewritesHKCU\Environment\PathwithSetStringValue(REG_SZ). AREG_EXPAND_SZuser PATH is converted, so entries like%USERPROFILE%\…stop expanding. It should preserve the value kind. Worth its own ticket.