Skip to content

Commit 9c7d58c

Browse files
authored
Merge pull request #170 from rocky/python-3.14
Python 3.14
2 parents 166cc1e + 6ce6a9e commit 9c7d58c

File tree

11 files changed

+435
-36
lines changed

11 files changed

+435
-36
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
/.pytest_cache
2929
/.python-version
3030
/.tox
31+
.tox
3132
/.venv*/*
3233
/ChangeLog
3334
/ChangeLog-spell-corrected
@@ -51,3 +52,4 @@ com_crashlytics_export_strings.xml
5152
crashlytics-build.properties
5253
crashlytics.properties
5354
fabric.properties
55+
uv.lock

test_crossversion/Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Crossversion xdis test usage:
1111
clean : remove compiled and serialized files
1212
get_sources : symlink all .py files in ./ -> $(SOURCE)
1313
setup_pyenv : setup local pyenv versions to be used by tox
14+
setup_uv : setup tox-uv to run tests with uv
1415
compile : with each tox env, compile all sources in $(SOURCE) to $(COMPILED), then serialize with dis to $(SERIALIZED)
1516
prepare : fully prepare test environment and compile test files
1617
test : prepare and run tests. with each tox env, serialize pyc's in $(COMPILED)<version> with xdis, then check against corresponding serialized pyc in $(SERIALIZED)<version>
@@ -37,12 +38,19 @@ get_sources:
3738
#: setup local pyenv versions to be used by tox
3839
setup_pyenv: .python-version
3940

41+
#: setup tox-uv so tox can use uv
42+
setup_uv:
43+
uv tool install tox --with tox-uv
44+
4045
#: with each tox env, compile all sources in ./templates/source/ to ./templates/compiled/, then serialize with dis to ./templates/serialized/
4146
compile:
4247
tox p -c ./tox_prepare.ini
4348

49+
.prepare_msg:
50+
@echo Ensure you have pyenv or uv installed and ran corresponding target setup_pyenv or setup_uv
51+
4452
#: fully prepare tests
45-
prepare: clean get_sources setup_pyenv compile
53+
prepare: .prepare_msg clean get_sources compile
4654

4755
#: prepare and run tests. with each tox env, serialize pyc's in ./templates/compiled/<version> with xdis, then check against corresponding dis serialized pyc in ./templates/serialized/<version>
4856
test: prepare

test_crossversion/USAGE.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,32 @@ This is done by having a way to identically "serialize" important attributes in
44
We then can check a diff between a serialized xdis and dis bytecode to find if xdis is parsing something incorrectly.
55
Most tests should be ran using the makefile.
66

7+
# Parsing results
8+
When running `make test`, tox will serialize bytecode to be put into text form. Given a bytecode compiled in 3.11 and natively disassembled, we go through each of our test versions, say 3.9 ... 3.14, and disassemble the same 3.11 bytecode.
9+
Given the 3.11 serialized disasembly, disassembled from 3.11, we take the diff between that and a serialized 3.11 disassembled from any of our test versions.
10+
This lets us see if there are any differences in how xdis handles native vs cross version.
11+
12+
This is repeated for every test version.
13+
```
14+
test_vers = (3.9, 3.10, 3.11, 3.12, 3.13)
15+
16+
for native in test_vers:
17+
for v in test_vers:
18+
assert disasm(native) == disasm(v)
19+
```
20+
21+
`make test` will run a series of pytests. If there is a failure, the left hand side is the native dis, and the right hand side is the xdis cross version. You will also see `case = 3.*`, this shows which version of python is being ran for that test.
22+
23+
Pytest will fail early, so not all tests may be ran.
24+
725
# System Requirements
26+
- `uv`
27+
- uv will handle everything on its own
28+
29+
---OR---
30+
831
- `pyenv` and `pyenv-virtualenv`
9-
- Each version needing to be tested should be installed with pyenv.
32+
- Each version needing to be tested should be installed with pyenv
1033
- `tox`
1134

1235
# Usage

test_crossversion/serialize_bytecode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import argparse
4+
import dis
45
import logging
56
import sys
67
from pathlib import Path

test_crossversion/test_xdis.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,17 @@ def get_tests_by_version(v: str) -> Iterable[SerializedTestCase]:
5959
yield SerializedTestCase(compiled_test, serialized_test)
6060

6161

62-
# @pytest.mark.parametrize("version", get_versions())
63-
# def test_version(version):
64-
# """Test each version in compiled template folder."""
65-
# for case in get_tests_by_version(version):
66-
# assert case.serialized_dis.splitlines() == case.serialized_xdis.splitlines()
67-
68-
69-
@pytest.mark.parametrize(
70-
"case", chain.from_iterable(get_tests_by_version(v) for v in get_versions())
71-
)
72-
def test_case(case: SerializedTestCase) -> None:
73-
assert case.serialized_dis.splitlines() == case.serialized_xdis.splitlines()
62+
### MORE VERBOSE ###
63+
@pytest.mark.parametrize("version", get_versions())
64+
def test_version(version):
65+
"""Test each version in compiled template folder."""
66+
for case in get_tests_by_version(version):
67+
assert case.serialized_dis.splitlines() == case.serialized_xdis.splitlines()
68+
69+
70+
### LESS VERBOSE (fail early) ###
71+
#@pytest.mark.parametrize(
72+
# "case", chain.from_iterable(get_tests_by_version(v) for v in get_versions())
73+
#)
74+
#def test_case(case: SerializedTestCase) -> None:
75+
# assert case.serialized_dis.splitlines() == case.serialized_xdis.splitlines()

test_crossversion/tox.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[tox]
22
min_version = 4.0
33
# ENV LIST MUST BE COMMA SEPARATED LIST OF PYTHON VERSIONS
4-
env_list = 3.9, 3.10, 3.11, 3.12, 3.13
4+
env_list = 3.12, 3.13, 3.14
55

66
[testenv]
77
description = Check all permutations of python dis code objects with xdis code objects.
88
deps =
9-
-e=file:///{toxinidir}/../.
9+
-e ../.
1010
pytest
1111
commands =
1212
pytest {tty:--color=yes} {posargs} ./test_xdis.py

test_crossversion/tox_prepare.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[tox]
22
min_version = 4.0
33
# ENV LIST MUST BE COMMA SEPARATED LIST OF PYTHON VERSIONS
4-
env_list = 3.9, 3.10, 3.11, 3.12, 3.13
4+
env_list = 3.12, 3.13, 3.14
55

66
[testenv]
77
description = Compile and serialize source templates with dis
88
deps =
9-
-e=file:///{toxinidir}/../.
9+
-e ../.
1010
pytest # not needed but speeds up env creation
1111
commands =
1212
python ./prepare_templates.py {posargs}

xdis/bytecode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ def get_logical_instruction_at_offset(
363363
elif op in opc.LOCAL_OPS:
364364
if opc.version_tuple >= (3, 13) and opname in (
365365
"LOAD_FAST_LOAD_FAST",
366+
"LOAD_FAST_BORROW_LOAD_FAST_BORROW",
366367
"STORE_FAST_LOAD_FAST",
367368
"STORE_FAST_STORE_FAST",
368369
):

xdis/magics.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,10 +647,11 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
647647
# Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST
648648
add_magic_from_int(3625, "3.14b3")
649649

650-
# Fix miscompilation of some module-level annotations.
650+
# Fix missing exception handlers in logical expression
651651
add_magic_from_int(3626, "3.14rc2")
652652

653-
# Fix miscompilation of some module-level annotations.
653+
# Fix miscompilation of some module-level annotations
654+
654655
add_magic_from_int(3627, "3.14rc3")
655656

656657
# Initial 3.15 version
@@ -844,7 +845,7 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
844845
)
845846

846847
add_canonic_versions(
847-
"3.13 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.13.5 3.13.6 3.13.7 3.13.8 3.13.9",
848+
"3.13 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.13.5 3.13.6 3.13.7 3.13.8 3.13.9 3.13.10",
848849
"3.13.0rc3",
849850
)
850851

0 commit comments

Comments
 (0)