GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — preparing step to integrate fix_test into lib_updater by youknowone · Pull Request #6698 · RustPython/RustPython

preparing step to integrate fix_test into lib_updater #6698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
youknowone merged 2 commits into RustPython:main from youknowone:quick-import
Jan 11, 2026

Uh oh!

There was an error while loading. Please reload this page.

Merged

preparing step to integrate fix_test into lib_updater #6698

Changes from all commits
Commits
Show all changes
2 commits
Select commit Hold shift + click to select a range
2a1faf4
integrate to lib_updater
youknowone Jan 10, 2026
f2d5594
fix_test --quick-import
youknowone Jan 10, 2026
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

126 changes: 70 additions & 56 deletions 126 scripts/fix_test.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@
It adds @unittest.expectedFailure to the test functions that are failing in RustPython, but not in CPython.
As well as marking the test with a TODO comment.

How to use:
Quick Import (recommended):
python ./scripts/fix_test.py --quick-import cpython/Lib/test/test_foo.py

This will:
1. Copy cpython/Lib/test/test_foo.py to Lib/test/test_foo.py (if not exists)
2. Run the test with RustPython
3. Mark failing tests with @unittest.expectedFailure

Manual workflow:
1. Copy a specific test from the CPython repository to the RustPython repository.
2. Remove all unexpected failures from the test and skip the tests that hang.
3. Build RustPython: cargo build --release
Expand All @@ -15,16 +23,23 @@
"""

import argparse
import ast
import itertools
import platform
import shutil
import sys
from pathlib import Path

from lib_updater import apply_patches, PatchSpec, UtMethod


def parse_args():
parser = argparse.ArgumentParser(description="Fix test.")
parser.add_argument("--path", type=Path, help="Path to test file")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--path", type=Path, help="Path to test file")
group.add_argument(
"--quick-import",
type=Path,
metavar="PATH",
help="Import from path containing /Lib/ (e.g., cpython/Lib/test/foo.py)",
)
parser.add_argument("--force", action="store_true", help="Force modification")
parser.add_argument(
"--platform", action="store_true", help="Platform specific failure"
Expand Down Expand Up @@ -102,39 +117,16 @@ def path_to_test(path) -> list[str]:
return parts[-2:] # Get class name and method name


def find_test_lineno(file: str, test: list[str]) -> tuple[int, int] | None:
"""Find the line number and column offset of a test function.
Returns (lineno, col_offset) or None if not found.
"""
a = ast.parse(file)
for key, node in ast.iter_fields(a):
if key == "body":
for n in node:
match n:
case ast.ClassDef():
if len(test) == 2 and test[0] == n.name:
for fn in n.body:
match fn:
case ast.FunctionDef() | ast.AsyncFunctionDef():
if fn.name == test[-1]:
return (fn.lineno, fn.col_offset)
case ast.FunctionDef() | ast.AsyncFunctionDef():
if n.name == test[0] and len(test) == 1:
return (n.lineno, n.col_offset)
return None


def apply_modifications(file: str, modifications: list[tuple[int, int]]) -> str:
"""Apply all modifications in reverse order to avoid line number offset issues."""
lines = file.splitlines()
fixture = "@unittest.expectedFailure"
# Sort by line number in descending order
modifications.sort(key=lambda x: x[0], reverse=True)
for lineno, col_offset in modifications:
indent = " " * col_offset
lines.insert(lineno - 1, indent + fixture)
lines.insert(lineno - 1, indent + "# TODO: RUSTPYTHON")
return "\n".join(lines)
def build_patches(test_parts_set: set[tuple[str, str]]) -> dict:
"""Convert failing tests to lib_updater patch format."""
patches = {}
for class_name, method_name in test_parts_set:
if class_name not in patches:
patches[class_name] = {}
patches[class_name][method_name] = [
PatchSpec(UtMethod.ExpectedFailure, None, "")
]
return patches


def run_test(test_name):
Expand All @@ -146,7 +138,7 @@ def run_test(test_name):
import subprocess

result = subprocess.run(
[rustpython_location, "-m", "test", "-v", test_name],
[rustpython_location, "-m", "test", "-v", "-u", "all", "--slowest", test_name],
capture_output=True,
text=True,
)
Expand All @@ -155,6 +147,33 @@ def run_test(test_name):

if __name__ == "__main__":
args = parse_args()

# Handle --quick-import: extract Lib/... path and copy if needed
if args.quick_import is not None:
src_str = str(args.quick_import)
lib_marker = "/Lib/"

if lib_marker not in src_str:
print(f"Error: --quick-import path must contain '/Lib/' (got: {src_str})")
sys.exit(1)

idx = src_str.index(lib_marker)
lib_path = Path(src_str[idx + 1 :]) # Lib/test/foo.py
src_path = args.quick_import

if not src_path.exists():
print(f"Error: Source file not found: {src_path}")
sys.exit(1)

if not lib_path.exists():
print(f"Copying: {src_path} -> {lib_path}")
lib_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy(src_path, lib_path)
else:
print(f"File already exists: {lib_path}")

args.path = lib_path

test_path = args.path.resolve()
if not test_path.exists():
print(f"Error: File not found: {test_path}")
Expand All @@ -167,26 +186,21 @@ def run_test(test_name):
tests = run_test(test_name)
f = test_path.read_text(encoding="utf-8")

# Collect all modifications first (with deduplication for subtests)
modifications = []
# Collect failing tests (with deduplication for subtests)
seen_tests = set() # Track (class_name, method_name) to avoid duplicates
for test in tests.tests:
if test.result == "fail" or test.result == "error":
test_parts = path_to_test(test.path)
test_key = tuple(test_parts)
if test_key in seen_tests:
continue # Skip duplicate (same test, different subtest)
seen_tests.add(test_key)
location = find_test_lineno(f, test_parts)
if location:
print(f"Modifying test: {test.name} at line {location[0]}")
modifications.append(location)
else:
print(f"Warning: Could not find test: {test.name} ({test_parts})")

# Apply all modifications in reverse order
if modifications:
f = apply_modifications(f, modifications)
if len(test_parts) == 2:
test_key = tuple(test_parts)
if test_key not in seen_tests:
seen_tests.add(test_key)
print(f"Marking test: {test_parts[0]}.{test_parts[1]}")

# Apply patches using lib_updater
if seen_tests:
patches = build_patches(seen_tests)
f = apply_patches(f, patches)
test_path.write_text(f, encoding="utf-8")

print(f"Modified {len(modifications)} tests")
print(f"Modified {len(seen_tests)} tests")
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.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.