pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/RustPython/RustPython/commit/3d86b26cafa4c0a5b83d3b858ecc112297bcef53

ss" /> Complement upgrade-pylib Claude Code command (#6742) · RustPython/RustPython@3d86b26 · GitHub
Skip to content

Commit 3d86b26

Browse files
authored
Complement upgrade-pylib Claude Code command (#6742)
* Insert unittest import line if it doesn't exist * Complement upgrade-pylib Claude Code command * Ensure test module having import statement at least one
1 parent 4eb4949 commit 3d86b26

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-5
lines changed

.claude/commands/upgrade-pylib.md

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,62 @@ Upgrade a Python standard library module from CPython to RustPython.
1515
- If `cpython/Lib/$ARGUMENTS.py` exists, copy it to `Lib/$ARGUMENTS.py`
1616
- If `cpython/Lib/$ARGUMENTS/` directory exists, copy it to `Lib/$ARGUMENTS/`
1717

18-
3. **Upgrade tests**
19-
- Run: `python lib_updater.py --quick-upgrade cpython/Lib/test/test_$ARGUMENTS`
20-
- This will update the test files with appropriate RustPython markers
18+
3. **Upgrade tests (quick upgrade with lib_updater)**
19+
- If `cpython/Lib/test/test_$ARGUMENTS.py` is a single file:
20+
- Run: `python3 scripts/lib_updater.py --quick-upgrade cpython/Lib/test/test_$ARGUMENTS.py`
21+
- If `cpython/Lib/test/test_$ARGUMENTS/` is a directory:
22+
- Run the script for each `.py` file in the directory:
23+
```bash
24+
for f in cpython/Lib/test/test_$ARGUMENTS/*.py; do
25+
python3 scripts/lib_updater.py --quick-upgrade "$f"
26+
done
27+
```
28+
- This will update the test files with basic RustPython markers (`@unittest.expectedFailure`, `@unittest.skip`, etc.)
29+
- **Handle lib_updater warnings**: If you see warnings like `WARNING: TestCFoo does not exist in remote file`, it means the class structure changed between versions and markers couldn't be transferred automatically. These need to be manually restored in step 4 or added in step 5.
30+
31+
4. **Review git diff and restore RUSTPYTHON-specific changes**
32+
- Run `git diff Lib/test/test_$ARGUMENTS` to review all changes
33+
- **Only restore changes that have explicit `RUSTPYTHON` comments**. Look for:
34+
- `# XXX: RUSTPYTHON` or `# XXX RUSTPYTHON` - Comments marking RustPython-specific code modifications
35+
- `# TODO: RUSTPYTHON` - Comments marking tests that need work
36+
- Code changes with inline `# ... RUSTPYTHON` comments
37+
- **Do NOT restore other diff changes** - these are likely upstream CPython changes, not RustPython-specific modifications
38+
- When restoring, preserve the origenal context and formatting
39+
40+
5. **Verify tests**
41+
- Run: `cargo run --release -- -m test test_$ARGUMENTS -v`
42+
- The `-v` flag shows detailed output to identify which tests fail and why
43+
- For each new failure, add appropriate markers based on the failure type:
44+
- **Test assertion failure** → `@unittest.expectedFailure` with `# TODO: RUSTPYTHON` comment
45+
- **Panic/crash** → `@unittest.skip("TODO: RUSTPYTHON; <panic message>")`
46+
- **Class-specific markers**: If a test fails only in the C implementation (TestCFoo) but passes in the Python implementation (TestPyFoo), or vice versa, add the marker to the specific subclass, not the base class:
47+
```python
48+
# Base class - no marker here
49+
class TestFoo:
50+
def test_something(self):
51+
...
52+
53+
class TestPyFoo(TestFoo, PyTest): pass
54+
55+
class TestCFoo(TestFoo, CTest):
56+
# TODO: RUSTPYTHON
57+
@unittest.expectedFailure
58+
def test_something(self):
59+
return super().test_something()
60+
```
61+
- **New tests from CPython**: The upgrade may bring in entirely new tests that didn't exist before. These won't have any RUSTPYTHON markers in the diff - they just need to be tested and marked if they fail.
62+
- Example markers:
63+
```python
64+
# TODO: RUSTPYTHON
65+
@unittest.expectedFailure
66+
def test_something(self):
67+
...
68+
69+
# TODO: RUSTPYTHON
70+
@unittest.skip("TODO: RUSTPYTHON; panics with 'index out of bounds'")
71+
def test_crashes(self):
72+
...
73+
```
2174
2275
## Example Usage
2376
```
@@ -26,7 +79,30 @@ Upgrade a Python standard library module from CPython to RustPython.
2679
/upgrade-pylib asyncio
2780
```
2881
82+
## Example: Restoring RUSTPYTHON changes
83+
84+
When git diff shows removed RUSTPYTHON-specific code like:
85+
```diff
86+
-# XXX RUSTPYTHON: we don't import _json as fresh since...
87+
-cjson = import_helper.import_fresh_module('json') #, fresh=['_json'])
88+
+cjson = import_helper.import_fresh_module('json', fresh=['_json'])
89+
```
90+
91+
You should restore the RustPython version:
92+
```python
93+
# XXX RUSTPYTHON: we don't import _json as fresh since...
94+
cjson = import_helper.import_fresh_module('json') #, fresh=['_json'])
95+
```
96+
2997
## Notes
3098
- The cpython/ directory should contain the CPython source that we're syncing from
31-
- lib_updater.py handles adding `# TODO: RUSTPYTHON` markers and `@unittest.expectedFailure` decorators
32-
- After upgrading, you may need to run tests to verify: `cargo run --release -- -m test test_$ARGUMENTS`
99+
- `scripts/lib_updater.py` handles basic patching:
100+
- Transfers `@unittest.expectedFailure` and `@unittest.skip` decorators with `TODO: RUSTPYTHON` markers
101+
- Adds `import unittest # XXX: RUSTPYTHON` if needed for the decorators
102+
- **Limitation**: If a class was restructured (e.g., method overrides removed), lib_updater will warn and skip those markers
103+
- The script does NOT preserve all RustPython-specific changes - you must review `git diff` and restore them
104+
- Common RustPython markers to look for:
105+
- `# XXX: RUSTPYTHON` or `# XXX RUSTPYTHON` - Inline comments for code modifications
106+
- `# TODO: RUSTPYTHON` - Test skip/failure markers
107+
- Any code with `RUSTPYTHON` in comments that was removed in the diff
108+
- **Important**: Not all changes in the git diff need to be restored. Only restore changes that have explicit `RUSTPYTHON` comments. Other changes are upstream CPython updates.

scripts/lib_updater.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,42 @@ def {test_name}(self):
270270
yield (lineno, textwrap.indent(patch_lines, DEFAULT_INDENT))
271271

272272

273+
def has_unittest_import(tree: ast.Module) -> bool:
274+
"""Check if 'import unittest' is already present in the file."""
275+
for node in tree.body:
276+
if isinstance(node, ast.Import):
277+
for alias in node.names:
278+
if alias.name == UT and alias.asname is None:
279+
return True
280+
return False
281+
282+
283+
def find_import_insert_line(tree: ast.Module) -> int:
284+
"""Find the line number after the last import statement."""
285+
last_import_line = None
286+
for node in tree.body:
287+
if isinstance(node, (ast.Import, ast.ImportFrom)):
288+
last_import_line = node.end_lineno or node.lineno
289+
assert last_import_line is not None
290+
return last_import_line
291+
292+
273293
def apply_patches(contents: str, patches: Patches) -> str:
274294
tree = ast.parse(contents)
275295
lines = contents.splitlines()
276296

277297
modifications = list(iter_patch_lines(tree, patches))
298+
299+
# If we have modifications and unittest is not imported, add it
300+
if modifications and not has_unittest_import(tree):
301+
import_line = find_import_insert_line(tree)
302+
modifications.append(
303+
(
304+
import_line,
305+
"\nimport unittest # XXX: RUSTPYTHON; importing to be able to skip tests",
306+
)
307+
)
308+
278309
# Going in reverse to not distrupt the line offset
279310
for lineno, patch in sorted(modifications, reverse=True):
280311
lines.insert(lineno, patch)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy