3535import re
3636import struct
3737import sys
38+ from collections import defaultdict
3839from importlib .util import MAGIC_NUMBER as MAGIC
3940from typing import Dict , Set , Tuple
4041
5455 24881 , # RustPython 3.13
5556)
5657
58+ # A list of interim Python version magic numbers used, but were not
59+ # the *final* major/minor for that release. For example, number 3430
60+ # to 3435 (3.10a1 to 3.10a7) are in this list, but 3438 (the *last* of
61+ # the 3.10b magic number changes), is not. Magic number 3438 used in
62+ # 3.10b was the final release before major/minor release 3.10; it
63+ # is the magic number used in 3.10 releases 3.10.0 to 3.10.19.
64+
65+ # FIXME: complete the below table.
66+ # fmt: off
67+
68+ # The following should be interim and this list.
69+ # The they all seems to be used in Python up to 3.6.15!
70+ # 3378 3.6b Used up to 3.6.15
71+ # 3372 is also 3.6?
72+ # 3379 is 3.7?
73+ # 3230 3.3a4
74+ # 3131 3.0a5 is 3.0.1?
75+ # 3393 3.7?
76+ # 3401 3.8.0a3+?
77+ INTERIM_MAGIC_INTS = frozenset ([
78+ 3010 , 3020 , 3030 , 3040 , 3050 , 3060 , 3061 , 3071 , 3081 , 3091 ,
79+ 3101 , 3103 , 3111 , 3141 , 3160 , 3170 , 3190 , 3200 , 3210 , 3220 ,
80+ 3250 , 3260 , 3270 , 3280 , 3290 , 3300 , 3320 , 3340 ,
81+ 3361 , 3371 , 3373 , 3375 , 3376 , 3377 , 3390 , 3391 ,
82+ 3392 , 3400 , 3410 , 3411 , 3412 , 3420 , 3421 , 3422 , 3423 ,
83+ 3424 , 3430 , 3431 , 3432 , 3433 , 3435 , 3436 , 3437 , 3438 , 3450 , 3451 ,
84+ # ...
85+ 62041 , 62051 , 62071 , 62081 , 62071 , 62091 , 62081 , 62091 , 62092 , 62111 ,
86+ 62121 , 62121 , 62151 , 62171 , 62181 , 62191 , 62201 ,
87+ ])
88+ # fmt: ofn
5789
5890def add_magic_from_int (magic_int : int , version : str ) -> None :
5991 magicint2version [magic_int ] = version
6092 versions [int2magic (magic_int )] = version
93+ version2magicint [version ].append (magic_int )
6194
95+ version2magicint = defaultdict (list )
6296
6397def int2magic (magic_int : int ) -> bytes :
6498 """Given a magic int like 62211, compute the corresponding magic byte string
@@ -154,11 +188,9 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
154188add_magic_from_int (62041 , "2.4a0" )
155189add_magic_from_int (62051 , "2.4a3" )
156190add_magic_from_int (62061 , "2.4b1" )
157- add_magic_from_int (62071 , "2.5a0" )
158-
159- # ast-branch
160- add_magic_from_int (62081 , "2.5a0" )
161191
192+ add_magic_from_int (62071 , "2.5a0" )
193+ add_magic_from_int (62081 , "2.5a0" ) # ast-branch
162194add_magic_from_int (62091 , "2.5a0" ) # with
163195add_magic_from_int (62092 , "2.5a0" ) # changed WITH_CLEANUP opcode
164196add_magic_from_int (62101 , "2.5b3" ) # fix wrong code: for x, in ...
@@ -416,7 +448,11 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
416448
417449# Change CALL_xxx opcodes
418450add_magic_from_int (3466 , "3.11a4c" )
451+
452+ # Add SEND opcode
419453add_magic_from_int (3467 , "3.11a4d" )
454+
455+ # bpo-45711: remove type, traceback from exc_info
420456add_magic_from_int (3468 , "3.11a4e" )
421457add_magic_from_int (3469 , "3.11a4f" )
422458add_magic_from_int (3470 , "3.11a4g" )
@@ -591,19 +627,19 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
591627# Add oparg to END_ASYNC_FOR
592628add_magic_from_int (3618 , "3.14a6b" )
593629
594- # Renumber RESUME opcode from 149 to 128
630+ # Renumber RESUME opcode from 149 to 128.
595631add_magic_from_int (3619 , "3.14a6c" )
596632
597- # Optimize bytecode for all/any/tuple called on a genexp
633+ # Optimize bytecode for all/any/tuple called on a genexp.
598634add_magic_from_int (3620 , "3.14a7a" )
599635
600- # Optimize LOAD_FAST opcodes into LOAD_FAST_BORROW
636+ # Optimize LOAD_FAST opcodes into LOAD_FAST_BORROW.
601637add_magic_from_int (3621 , "3.14a7b" )
602638
603- # Store annotations in different class dict keys
639+ # Store annotations in different class dict keys.
604640add_magic_from_int (3622 , "3.14a7c" )
605641
606- # Add BUILD_INTERPOLATION & BUILD_TEMPLATE opcodes
642+ # Add BUILD_INTERPOLATION & BUILD_TEMPLATE opcodes.
607643add_magic_from_int (3623 , "3.14a7d" )
608644
609645# Don't optimize LOAD_FAST when local is killed by DELETE_FAST
@@ -612,11 +648,34 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
612648# Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST
613649add_magic_from_int (3625 , "3.14b3" )
614650
651+ # Fix miscompilation of some module-level annotations.
652+ add_magic_from_int (3626 , "3.14rc2" )
653+
654+ # Fix miscompilation of some module-level annotations.
615655add_magic_from_int (3627 , "3.14rc3" )
616656
617- # add_magic_from_int(3655, "3.15.0a0")
657+ # Initial 3.15 version
658+ add_magic_from_int (3650 , "3.15a0" )
659+
660+ # Simplify LOAD_CONST.
661+ add_magic_from_int (3651 , "3.15a1a" )
662+
663+ # Add Virtual iterators.
664+ add_magic_from_int (3652 , "3.15a1b" )
665+
666+ # Fix handling of opcodes that may leave operands on the stack when
667+ # optimizing LOAD_FAST.
668+ add_magic_from_int (3653 , "3.15a1c" )
669+
670+ # Fix missing exception handlers in logical expression.
671+ add_magic_from_int (3654 , "3.15a1d" )
672+
673+ # Fix miscompilation of some module-level annotations.
674+ # add_magic_from_int(3655, "3.15a1e")
618675# NOTE: this will change on release!
619- add_magic_from_int (3655 , "3.15.0" )
676+ add_magic_from_int (3655 , "3.15-dev" )
677+
678+ # Python 3.16 will start with 3700
620679
621680# Weird ones
622681# WTF? Python 3.2.5 and PyPy have weird magic numbers
@@ -703,7 +762,7 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
703762add_canonic_versions (
704763 "3.6b2 3.6 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 "
705764 "3.6.9 3.6.10 3.6.11 3.6.12 3.6.13 3.6.14 3.6.15" ,
706- "3.6rc1" ,
765+ "3.6rc1" , # ?? 3.6b2 is not 3.6rc1!
707766)
708767
709768add_canonic_versions ("3.7b1" , "3.7.0beta3" )
@@ -774,8 +833,8 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
774833add_canonic_versions ("3.14 3.14.0" , "3.14rc3" )
775834
776835add_canonic_versions (
777- "3.15 3.15.0a1 3.15-dev 3.15.0a0" ,
778- "3.15.0 " ,
836+ "3.15 3.15.0 3.15.0a1 3.15.0a0" ,
837+ "3.15-dev " ,
779838)
780839
781840# The canonic version for a canonic version is itself
@@ -784,6 +843,12 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
784843# A set of all Python versions we know about
785844python_versions = set (canonic_python_version .keys ())
786845
846+ # Python major, minor version names, e.g. 3.6, 3.11pypy, etc.
847+ # These are not considered interim version number.
848+ minor_release_names = {
849+ python_version for python_version in python_versions if re .match ("^[1-3][.][0-9]+(?:pypy|Graal)?$" , python_version )
850+ }
851+
787852
788853def __show (text , magic ) -> None :
789854 print (text , struct .unpack ("BBBB" , magic ), struct .unpack ("<HBB" , magic ))
@@ -869,6 +934,12 @@ def test() -> None:
869934 print (type (magic_20 ), len (magic_20 ), repr (magic_20 ))
870935 assert sysinfo2magic () == MAGIC , (sysinfo2magic (), MAGIC )
871936
937+ # Check that our interim version numbers are not used as release numbers.
938+ interim_version_names = {magicint2version [magic_int ] for magic_int in INTERIM_MAGIC_INTS }
939+ incorrect_interim_names = interim_version_names .intersection (minor_release_names )
940+ if interim_version_names :
941+ for incorrect_name in incorrect_interim_names :
942+ print (f"Remove { incorrect_name } { version2magicint [incorrect_name ]} " )
872943
873944if __name__ == "__main__" :
874945 test ()
0 commit comments