Python: Pin openrewrite Python package version in RPC bootstrap#6813
Merged
knutwannheden merged 4 commits intomainfrom Feb 25, 2026
Merged
Python: Pin openrewrite Python package version in RPC bootstrap#6813knutwannheden merged 4 commits intomainfrom
openrewrite Python package version in RPC bootstrap#6813knutwannheden merged 4 commits intomainfrom
Conversation
PythonRewriteRpc.bootstrapOpenrewrite() was running bare `pip install openrewrite` without a version specifier, unlike the JavaScript side which reads /META-INF/version.txt and pins `@openrewrite/rewrite@<version>`. This meant the Python RPC could end up with a mismatched openrewrite package version, and the existence-only check meant users could get stuck on a stale version indefinitely. Changes: - Generate META-INF/version.txt in the build (PEP 440 format) so the Java code can read the expected Python package version at runtime - Pin `openrewrite==<version>` in bootstrapOpenrewrite() for release and CI builds; skip pinning for local .dev0 builds - Track installed version via a marker file to detect and upgrade stale installs - Add license exclude for version.txt and .gitignore entry
Without --upgrade, pip install --target may skip the install when it sees the package already exists, even if the version differs.
openrewrite Python package version in RPC bootstrap
For SNAPSHOT/dev builds, probe whether the Python interpreter can already import rewrite (e.g., from a venv with an editable install). If so, skip both the bootstrap and the PYTHONPATH prepend so the interpreter's own package takes precedence. For release/CI builds, always bootstrap and prepend to ensure the correct pinned version is used. This mirrors the JS pattern where SNAPSHOT trusts the local dev environment (npm link) while release pins the exact version.
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.
Summary
PythonRewriteRpc.bootstrapOpenrewrite()was running barepip install openrewritewithout a version specifier, unlike the JavaScript side which reads/META-INF/version.txtand pins@openrewrite/rewrite@<version>via npx. This could result in a mismatched Python openrewrite package, and the existence-only check meant users could get stuck on a stale version indefinitely.Changes
META-INF/version.txtat build time (PEP 440 format), matching therewrite-javascriptpattern. Wired intosourcesJar,processResources,licenseMain,assembletasks. License exclude and.gitignoreentry added.bootstrapOpenrewrite()reads the version from the resource and runspip install --upgrade openrewrite==<version>for release/CI builds. For local.dev0builds, the version is not pinned..openrewrite-versionmarker file tracks the installed version inpipPackagesPath. On startup, if the marker doesn't match the JAR's version, the package is reinstalled with--upgrade.import rewrite(e.g., from a venv with an editable install). If so, skips both bootstrap andPYTHONPATHprepend so the interpreter's own package takes precedence. This mirrors the JS pattern where SNAPSHOT trusts the local dev environment (npm link).Behavior matrix
version.txt8.75.08.75.0openrewrite==8.75.0, prepend to PYTHONPATH8.75.0.dev2026...8.75.0.dev08.75.0.dev0openrewrite, prepend to PYTHONPATHCompanion CLI PR: https://github.com/moderneinc/moderne-cli/pull/3350
Test plan
./gradlew :rewrite-python:assemblesucceeds,version.txtpresent in JAR with correct content./gradlew :rewrite-python:licenseFormatdoes not inject headers intoversion.txt8.75.0inversion.txtpipPackagesPathset installs the pinned version