Visitar URL original
Begin the Python 3.15 target and essential-library migration by youknowdot · Pull Request #8950 · RustPython/RustPython · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6c25298
Target Python 3.15 using the final upstream reference
youknowdot Oct 9, 2026
519370b
Adapt essential snippet contracts to Python 3.15 final
youknowdot Oct 9, 2026
0486d6d
Keep final-reference regression paths and remove expired sysconfig ar…
youknowdot Oct 9, 2026
67f79ea
Keep README wording unchanged in Python 3.15 transition
youknowdot Oct 9, 2026
72a6330
Match Python 3.15 repetition specialization and keep universal tests
youknowdot Oct 9, 2026
2002f53
Limit in-place specialization additions to exact sequence repetition
youknowdot Oct 9, 2026
8d6c943
Keep subclass regression scoped to repetition dispatch
youknowdot Oct 9, 2026
ae03487
Provision final CPython 3.15 with pinned uv builds
youknowdot Oct 9, 2026
33198c7
Enforce Python 3.15 AST constructor requirements
youknowdot Oct 9, 2026
8aff205
Keep seeded Python ahead of its Windows DLL directory
youknowdot Oct 9, 2026
934493b
Keep opcode metadata tied to the implemented bytecode format
youknowdot Oct 9, 2026
8573d91
Align CSV, logarithm and decimal formatting with Python 3.15
youknowdot Oct 9, 2026
459395b
Bind the logarithm index result before borrowing its integer
youknowdot Oct 10, 2026
9391879
Align required canonical test expectations with Python 3.15
youknowdot Oct 10, 2026
dcc5619
Track pending frozendict pickle support during the 3.15 transition
youknowdot Oct 10, 2026
54dfc8d
Support final Python 3.15 Windows negative timestamps
youknowdot Oct 10, 2026
d517416
Derive historical Windows timezone offsets from wall time
youknowdot Oct 10, 2026
1003f62
Identify decimal formatting arguments in Python 3.15 errors
youknowdot Oct 10, 2026
b4468ee
Reuse mapping format keys for lookup and error context
youknowdot Oct 10, 2026
4e854bb
Borrow mapping diagnostic keys as Python objects
youknowdot Oct 10, 2026
90d2d12
Avoid empty components in the reference Python library path
youknowdot Oct 10, 2026
1af8926
Isolate RustPython bytecode caches during the 3.15 transition
youknowdot Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .claude/scripts/setup-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if [ "$(printf '%s\n' "3.13" "$CURRENT_PY" | sort -V | head -1)" != "3.13" ]; th
echo "Upgrading python3 default to 3.13..."
# Find best available Python >= 3.13
TARGET=""
for ver in python3.14 python3.13; do
for ver in python3.15 python3.14 python3.13; do
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if command -v "$ver" &>/dev/null; then
TARGET=$(command -v "$ver")
break
Expand All @@ -38,13 +38,17 @@ else
echo "python3 already >= 3.13: $(python3 --version)"
fi

# 2. Clone CPython source if not present (needed for scripts/update_lib)
if [ ! -d "cpython" ]; then
echo "Cloning CPython v3.14.3 (shallow)..."
git clone --depth 1 --branch v3.14.3 https://github.com/python/cpython.git cpython
echo "CPython source ready."
# 2. Ensure the CPython source matches the target (needed for scripts/update_lib)
PYTHON_VERSION="v3.15.0"
if [ ! -e "cpython" ]; then
git clone --depth 1 --branch "$PYTHON_VERSION" https://github.com/python/cpython.git cpython
elif [ ! -d "cpython/.git" ] || [ ! -d "cpython/Lib" ] ||
[ "$(git -C cpython rev-parse HEAD)" != "$(git -C cpython rev-parse --verify "$PYTHON_VERSION^{commit}" 2>/dev/null)" ] ||
[ -n "$(git -C cpython status --porcelain)" ]; then
echo "ERROR: cpython must be a clean checkout of $PYTHON_VERSION. Move the existing directory aside and rerun." >&2
exit 1
else
echo "CPython source already present."
echo "CPython $PYTHON_VERSION source already present."
fi

echo "=== Setup complete ==="
57 changes: 57 additions & 0 deletions .github/actions/setup-python/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Set up reference Python
description: Install CPython from python-build-standalone with pip available.
inputs:
python-version:
description: CPython version to install
default: "3.15.0"
outputs:
python-path:
description: Path to the installed interpreter
value: ${{ steps.python.outputs.python-path }}
python-version:
description: Installed CPython version
value: ${{ steps.python.outputs.python-version }}
runs:
using: composite
steps:
# uv 0.13.0 includes the final 3.15.0 builds, before setup-python's catalog.
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
version: "0.13.0"
python-version: ${{ inputs.python-version }}
activate-environment: true
no-project: true
venv-path: ${{ runner.temp }}/reference-python
enable-cache: false
env:
UV_VENV_SEED: "true"
UV_MANAGED_PYTHON: "true"
- id: python
shell: bash
env:
REQUESTED_PYTHON: ${{ inputs.python-version }}
run: |
python - <<'PY'
import os
import platform
import sys

if os.environ["REQUESTED_PYTHON"] == "3.15.0":
assert sys.version_info[:3] == (3, 15, 0), sys.version
assert sys.version_info.releaselevel == "final", sys.version
with open(os.environ["GITHUB_OUTPUT"], "a") as output:
print(f"python-path={sys.executable}", file=output)
print(f"python-version={platform.python_version()}", file=output)
with open(os.environ["GITHUB_ENV"], "a") as env:
print(f"pythonLocation={sys.base_prefix}", file=env)
if sys.platform == "linux":
lib = os.path.join(sys.base_prefix, "lib")
previous = os.environ.get("LD_LIBRARY_PATH")
lib_path = os.pathsep.join([lib, previous] if previous else [lib])
print(f"LD_LIBRARY_PATH={lib_path}", file=env)
if sys.platform == "win32":
with open(os.environ["GITHUB_PATH"], "a") as path:
print(sys.base_prefix, file=path)
print(os.path.dirname(sys.executable), file=path)
print(sys.version)
PY
18 changes: 7 additions & 11 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@
# Windows runners randomly crashes, https://github.com/actions/cache/issues/1754
continue-on-error: true

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- name: Install macOS dependencies
uses: ./.github/actions/install-macos-deps
Expand Down Expand Up @@ -752,7 +752,7 @@
with:
persist-credentials: false

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- uses: dtolnay/rust-toolchain@stable
with:
Expand Down Expand Up @@ -781,18 +781,14 @@
- name: prek run
run: prek run --show-diff-on-failure --color=always --all-files

- name: Get target CPython version
id: cpython-version
run: |
version=$(cat .python-version)
echo "version=${version}" >> "$GITHUB_OUTPUT"

- name: Clone CPython
- name: Clone CPython opcode metadata source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: python/cpython
path: cpython
ref: "v${{ steps.cpython-version.outputs.version }}"
# RustPython still uses the 3.14 bytecode format; this source is only
# for opcode metadata, independent of the 3.15 runtime target.
ref: "v3.14.7"
persist-credentials: false

- name: prek run (manual stage)
Expand Down Expand Up @@ -918,7 +914,7 @@
mkdir geckodriver
tar -xzf geckodriver-v0.36.0-linux64.tar.gz -C geckodriver

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- run: python -m pip install -r requirements.txt
working-directory: ./wasm/tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codspeed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
- uses: dtolnay/rust-toolchain@stable

# The benchmarks are linked against libpython through the pyo3 dev-dependency.
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- name: Restore the machine main last measured on
# A recording that cannot be fetched is read as "none yet", which the step
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/cron-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
with:
tool: cargo-llvm-cov

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- run: sudo apt-get update && sudo apt-get -y install lcov

Expand Down Expand Up @@ -110,7 +110,7 @@

- uses: dtolnay/rust-toolchain@stable

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- name: build rustpython
run: cargo build --release --verbose --features sqlite
Expand Down Expand Up @@ -170,7 +170,7 @@

- uses: dtolnay/rust-toolchain@stable

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python

- run: cargo install cargo-criterion

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lib-deps-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

- name: Setup Python
if: steps.changed-files.outputs.modules != ''
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
uses: ./.github/actions/setup-python

- name: Run deps check
if: steps.changed-files.outputs.modules != ''
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pyperformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@
# Both the third interpreter under test and the host pyperformance
# itself runs on (it only runs under a real CPython; RustPython is just
# the `--python` target it drives).
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python
id: cpython
with:
python-version: "3.14"
python-version: "3.15.0"

- name: Restore cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/update-doc-db.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
python-version:
description: Target python version to generate doc db for
type: string
default: "3.14.7"
default: "3.15.0"
base-ref:
description: Base branch to create the update branch from
type: string
Expand All @@ -35,8 +35,9 @@
persist-credentials: false
sparse-checkout: |
crates/doc
.github/actions/setup-python

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: ./.github/actions/setup-python
with:
python-version: ${{ inputs.python-version }}

Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/upgrade-pylib.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions .github/workflows/upgrade-pylib.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ engine: copilot

runtimes:
python:
version: "3.14"
version: "3.15"

tools:
bash:
Expand All @@ -48,11 +48,9 @@ safe-outputs:
cache:
key: cpython-lib-${{ env.PYTHON_VERSION }}
path: cpython
restore-keys:
- cpython-lib-

env:
PYTHON_VERSION: "v3.14.7"
PYTHON_VERSION: "v3.15.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject stale CPython caches before library upgrades

When the Upgrade Python Library workflow is dispatched while a cpython-lib-v3.14.* cache exists, this version bump makes the primary key miss, the frontmatter's restore-keys: cpython-lib- restores that old cpython/ tree, and Step 1 later skips cloning whenever cpython/Lib exists. scripts/update_lib quick then copies 3.14 library files even though the workflow and PR template target v3.15.0; validate or check out $PYTHON_VERSION after restoring, or remove the cross-version fallback.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8d6c943. The workflow source and regenerated lock file no longer restore cross-version CPython caches. Both the workflow setup and .claude/scripts/setup-env.sh reject an existing checkout unless HEAD matches v3.15.0 and the working tree is clean; they leave stale or dirty files untouched. The cache validation fixtures and workflow security scan pass. Hosted CI is still pending.

ISSUE_ID: "6839"
---

Expand All @@ -65,10 +63,15 @@ You are an automated maintenance agent for RustPython, a Python 3 interpreter wr
The CPython source may already be cached. Check if the `cpython` directory exists and has the correct version:

```bash
if [ -d "cpython/Lib" ]; then
echo "CPython cache hit, skipping clone"
else
if [ ! -e "cpython" ]; then
git clone --depth 1 --branch "$PYTHON_VERSION" https://github.com/python/cpython.git cpython
elif [ ! -d "cpython/.git" ] || [ ! -d "cpython/Lib" ] ||
[ "$(git -C cpython rev-parse HEAD)" != "$(git -C cpython rev-parse --verify "$PYTHON_VERSION^{commit}" 2>/dev/null)" ] ||
[ -n "$(git -C cpython status --porcelain)" ]; then
echo "ERROR: cpython must be a clean checkout of $PYTHON_VERSION. Move the existing directory aside and rerun." >&2
exit 1
else
echo "CPython $PYTHON_VERSION source already present."
fi
```

Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.14.7
3.15.0
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This document provides guidelines for AI coding agents (GitHub Copilot, Claude C

## Project Overview

RustPython is a Python 3 interpreter written in Rust, implementing Python 3.14.0+ compatibility. The project aims to provide:
RustPython is a Python 3 interpreter written in Rust, targeting Python 3.15 with compatibility work in progress. The project aims to provide:

- A complete Python-3 environment entirely in Rust (not CPython bindings)
- A clean implementation without compatibility hacks
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ RustPython requires the following:
stable version: `rustup update stable`
- If you do not have Rust installed, use [rustup](https://rustup.rs/) to
do so.
- CPython version 3.14 or higher
- CPython version 3.15 or higher
- CPython can be installed by your operating system's package manager,
from the [Python website](https://www.python.org/downloads/), or
using a third-party distribution, such as
Expand Down
13 changes: 1 addition & 12 deletions Lib/sysconfig/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,7 @@ def _safe_realpath(path):
if "_PYTHON_PROJECT_BASE" in os.environ:
_PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])

def is_python_build(check_home=None):
if check_home is not None:
import warnings
warnings.warn(
(
'The check_home argument of sysconfig.is_python_build is '
'deprecated and its value is ignored. '
'It will be removed in Python 3.15.'
),
DeprecationWarning,
stacklevel=2,
)
def is_python_build():
for fn in ("Setup", "Setup.local"):
if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
return True
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/pickletester.py
Original file line number Diff line number Diff line change
Expand Up @@ -4394,6 +4394,8 @@ def test_fast_save_enter_frozenset(self):
def test_fast_save_enter_set(self):
self.fast_save_enter(lambda i: set([i]))

# TODO: RUSTPYTHON; frozendict support: https://github.com/RustPython/RustPython/pull/8951
@unittest.expectedFailure
def test_fast_save_enter_frozendict(self):
if self.py_version < (3, 15):
self.skipTest('need frozendict')
Expand Down Expand Up @@ -4441,6 +4443,8 @@ def test_deep_nested_struct_set(self):
depth=FAST_NESTING_LIMIT+1,
compare_equal=False)

# TODO: RUSTPYTHON; frozendict support: https://github.com/RustPython/RustPython/pull/8951
@unittest.expectedFailure
def test_deep_nested_struct_frozendict(self):
if self.py_version < (3, 15):
self.skipTest('need frozendict')
Expand Down
Loading
Loading