3535import re
3636import struct
3737import sys
38+ from importlib .util import MAGIC_NUMBER as MAGIC
3839from typing import Dict , Set
3940
4041from xdis .version_info import IS_GRAAL , IS_PYPY , version_tuple_to_str
@@ -62,12 +63,9 @@ def int2magic(magic_int: int) -> bytes:
6263
6364 if magic_int in (39170 , 39171 ):
6465 return struct .pack ("<H" , magic_int ) + b"\x99 \x00 "
65- if sys .version_info >= (3 , 0 ):
66- return struct .pack (
67- "<Hcc" , magic_int , bytes ("\r " , "utf-8" ), bytes ("\n " , "utf-8" )
68- )
69- else :
70- return struct .pack ("<Hcc" , magic_int , "\r " , "\n " )
66+ return struct .pack (
67+ "<Hcc" , magic_int , bytes ("\r " , "utf-8" ), bytes ("\n " , "utf-8" )
68+ )
7169
7270
7371def magic2int (magic : bytes ) -> int :
@@ -98,8 +96,6 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
9896magicint2version : Dict [int , str ] = {}
9997versions : Dict [bytes , str ] = {}
10098
101- from importlib .util import MAGIC_NUMBER as MAGIC
102-
10399PYTHON_MAGIC_INT = magic2int (MAGIC )
104100
105101# The magic word is used to reject .pyc files generated by other
@@ -154,7 +150,10 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
154150add_magic_from_int (62051 , "2.4a3" )
155151add_magic_from_int (62061 , "2.4b1" )
156152add_magic_from_int (62071 , "2.5a0" )
157- add_magic_from_int (62081 , "2.5a0" ) # ast-branch
153+
154+ # ast-branch
155+ add_magic_from_int (62081 , "2.5a0" )
156+
158157add_magic_from_int (62091 , "2.5a0" ) # with
159158add_magic_from_int (62092 , "2.5a0" ) # changed WITH_CLEANUP opcode
160159add_magic_from_int (62101 , "2.5b3" ) # fix wrong code: for x, in ...
@@ -170,8 +169,11 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
170169# Dropbox-modified Python 2.5 used in versions 1.1x and before of Dropbox
171170add_magic_from_int (62135 , "2.5dropbox" )
172171
173- add_magic_from_int (62151 , "2.6a0" ) # peephole optimizations & STORE_MAP
174- add_magic_from_int (62161 , "2.6a1" ) # WITH_CLEANUP optimization
172+ # peephole optimizations & STORE_MAP
173+ add_magic_from_int (62151 , "2.6a0" )
174+
175+ # WITH_CLEANUP optimization
176+ add_magic_from_int (62161 , "2.6a1" )
175177
176178# Optimize list comprehensions/change LIST_APPEND
177179add_magic_from_int (62171 , "2.7a0" )
@@ -252,14 +254,18 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
252254 3372 , "3.6a1+2"
253255) # MAKE_FUNCTION simplification, remove MAKE_CLOSURE #27095
254256add_magic_from_int (3373 , "3.6b1" ) # add BUILD_STRING opcode #27078
255- add_magic_from_int (
256- 3375 , "3.6b1+1"
257- ) # add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes #27985
258- add_magic_from_int (
259- 3376 , "3.6b1+2"
260- ) # simplify CALL_FUNCTION* & BUILD_MAP_UNPACK_WITH_CALL
261- add_magic_from_int (3377 , "3.6b1+3" ) # set __class__ cell from type.__new__ #23722
262- add_magic_from_int (3378 , "3.6b2" ) # add BUILD_TUPLE_UNPACK_WITH_CALL #28257
257+
258+ # add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes #27985
259+ add_magic_from_int (3375 , "3.6b1+1" )
260+
261+ # simplify CALL_FUNCTION* & BUILD_MAP_UNPACK_WITH_CALL
262+ add_magic_from_int (3376 , "3.6b1+2" )
263+
264+ # set __class__ cell from type.__new__ #23722
265+ add_magic_from_int (3377 , "3.6b1+3" )
266+
267+ # add BUILD_TUPLE_UNPACK_WITH_CALL #28257
268+ add_magic_from_int (3378 , "3.6b2" )
263269
264270# more thorough __class__ validation #23722
265271add_magic_from_int (3379 , "3.6rc1" )
@@ -291,8 +297,7 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
291297# PEP570 Python Positional-Only Parameters #36540
292298add_magic_from_int (3410 , "3.8.0a1+" )
293299
294- # Reverse evaluation order of key: value in dict comprehensions
295- # #35224
300+ # Reverse evaluation order of key: value in dict comprehensions #35224
296301add_magic_from_int (3411 , "3.8.0b2+" )
297302
298303# Swap the position of positional args and positional only args in
@@ -331,27 +336,80 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
331336
332337# RERAISE restores f_lasti if oparg != 0
333338add_magic_from_int (3433 , "3.10a2" )
339+
340+ # PEP 634: Structural Pattern Matching
334341add_magic_from_int (3434 , "3.10a6" )
342+
343+ # Use instruction offsets (as opposed to byte offsets)
335344add_magic_from_int (3435 , "3.10a7" )
336- add_magic_from_int (3438 , "3.10b1" )
337- add_magic_from_int (3439 , "3.10.0rc2" )
338345
346+ # Add GEN_START bytecode #43683
347+ add_magic_from_int (3436 , "3.10b1a" )
348+
349+ # Undo making 'annotations' future by default - We like to dance among core devs!
350+ add_magic_from_int (3437 , "3.10b1b" )
351+
352+ # Safer line number table handling.
353+ add_magic_from_int (3438 , "3.10b1c" )
354+
355+ # Add ROT_N
356+ add_magic_from_int (3439 , "3.10.b1" )
357+
358+ # Use exception table for unwinding ("zero cost" exception handling)
339359add_magic_from_int (3450 , "3.11a1a" )
360+
361+ # Add CALL_METHOD_KW
340362add_magic_from_int (3451 , "3.11a1b" )
363+
364+ # drop nlocals from marshaled code objects
341365add_magic_from_int (3452 , "3.11a1c" )
366+
367+ # add co_fastlocalnames and co_fastlocalkinds
342368add_magic_from_int (3453 , "3.11a1d" )
369+
370+ # compute cell offsets relative to locals bpo-43693
343371add_magic_from_int (3454 , "3.11a1e" )
372+
373+ # add MAKE_CELL bpo-43693
344374add_magic_from_int (3455 , "3.11a1f" )
345- add_magic_from_int (3457 , "3.11a1g" )
346- add_magic_from_int (3458 , "3.11a1h" )
347- add_magic_from_int (3459 , "3.11a1i" )
348- add_magic_from_int (3460 , "3.11a1j" )
349- add_magic_from_int (3461 , "3.11a1k" )
375+
376+ # interleave cell args bpo-43693
377+ add_magic_from_int (3456 , "3.11a1g" )
378+
379+ # Change localsplus to a bytes object bpo-43693
380+ add_magic_from_int (3457 , "3.11a1h" )
381+
382+ # imported objects now don't use LOAD_METHOD/CALL_METHOD
383+ add_magic_from_int (3458 , "3.11a1i" )
384+
385+ # PEP 657: add end line numbers and column offsets for instructions
386+ add_magic_from_int (3459 , "3.11a1j" )
387+
388+ # Add co_qualname field to PyCodeObject bpo-44530
389+ add_magic_from_int (3460 , "3.11a1k" )
390+
391+ # JUMP_ABSOLUTE must jump backwards
392+ add_magic_from_int (3461 , "3.11a1l" )
393+
394+ # bpo-44511: remove COPY_DICT_WITHOUT_KEYS, change
395+ # MATCH_CLASS and MATCH_KEYS, and add COPY
350396add_magic_from_int (3462 , "3.11a2" )
397+
398+ # bpo-45711: JUMP_IF_NOT_EXC_MATCH no longer pops the
399+ # active exception)
351400add_magic_from_int (3463 , "3.11a3a" )
401+
402+ # bpo-45636: Merge numeric BINARY_*/INPLACE_* into
403+ # BINARY_OP
352404add_magic_from_int (3464 , "3.11a3b" )
405+
406+ # Add COPY_FREE_VARS opcode
353407add_magic_from_int (3465 , "3.11a4a" )
408+
409+ # bpo-45292: PEP-654 except*
354410add_magic_from_int (3466 , "3.11a4b" )
411+
412+ # Change CALL_xxx opcodes
355413add_magic_from_int (3466 , "3.11a4c" )
356414add_magic_from_int (3467 , "3.11a4d" )
357415add_magic_from_int (3468 , "3.11a4e" )
@@ -384,15 +442,33 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
384442add_magic_from_int (3495 , "3.11a7e" )
385443
386444# 3.12
445+ # Remove PRECALL opcode)
387446add_magic_from_int (3500 , "3.12a1a" )
447+
448+ # YIELD_VALUE oparg == stack_depth
388449add_magic_from_int (3501 , "3.12a1b" )
450+
451+ # LOAD_FAST_CHECK, no NULL-check in LOAD_FAST
389452add_magic_from_int (3502 , "3.12a1c" )
453+
454+ # Shrink LOAD_METHOD cache
390455add_magic_from_int (3503 , "3.12a1d" )
456+
457+ # Merge LOAD_METHOD back into LOAD_ATTR
391458add_magic_from_int (3504 , "3.12a1e" )
459+
460+ # Specialization/Cache for FOR_ITER
392461add_magic_from_int (3505 , "3.12a1f" )
462+
463+ # Add BINARY_SLICE and STORE_SLICE instructions
393464add_magic_from_int (3506 , "3.12a1g" )
465+
466+ # Set lineno of module's RESUME to 0
394467add_magic_from_int (3507 , "3.12a1h" )
468+
469+ # Add CLEANUP_THROW
395470add_magic_from_int (3508 , "3.12a1i" )
471+
396472add_magic_from_int (3509 , "3.12a1j" )
397473add_magic_from_int (3510 , "3.12a2a" )
398474add_magic_from_int (3511 , "3.12a2b" )
@@ -530,6 +606,10 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict:
530606# Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST
531607add_magic_from_int (3625 , "3.14b3" )
532608
609+ # add_magic_from_int(3655, "3.15.0a0")
610+ # NOTE: this will change on release!
611+ add_magic_from_int (3655 , "3.15.0" )
612+
533613# Weird ones
534614# WTF? Python 3.2.5 and PyPy have weird magic numbers
535615
@@ -657,7 +737,7 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
657737add_canonic_versions (
658738 "3.10 3.10.0 3.10.1 3.10.2 3.10.3 3.10.4 3.10.5 3.10.6 3.10.7 3.10.8 3.10.9 "
659739 "3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.16 3.10.17 3.10.18" ,
660- "3.10.0rc2 " ,
740+ "3.10.b1 " ,
661741)
662742
663743add_canonic_versions ("3.10.13Graal" , "3.10.8Graal" )
@@ -683,6 +763,11 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None:
683763 "3.14b3" ,
684764)
685765
766+ add_canonic_versions (
767+ "3.15 3.15-dev 3.15.0a0" ,
768+ "3.15.0" ,
769+ )
770+
686771# The canonic version for a canonic version is itself
687772for v in versions .values ():
688773 canonic_python_version [v ] = v
@@ -732,7 +817,7 @@ def py_str2tuple(orig_version: str) -> tuple[int, int] | tuple[int, int, int]:
732817 )
733818
734819
735- def sysinfo2magic (version_info = sys .version_info ) -> bytes :
820+ def sysinfo2magic (version_info : tuple = tuple ( sys .version_info ) ) -> bytes :
736821 """Convert a list sys.versions_info compatible list into a 'canonic'
737822 The magic bytes value found at the beginning of a bytecode file.
738823 b'?!\r \n ' is returned if we can't find a version.
0 commit comments