@@ -648,7 +648,6 @@ const GLOBAL_EXTENSIONS: &[&str] = &[
648
648
"_weakref" ,
649
649
"array" ,
650
650
"atexit" ,
651
- "audioop" ,
652
651
"binascii" ,
653
652
"builtins" ,
654
653
"cmath" ,
@@ -675,13 +674,17 @@ const GLOBAL_EXTENSIONS: &[&str] = &[
675
674
// _testsinglephase added in 3.12.
676
675
// _sha256 and _sha512 merged into _sha2 in 3.12.
677
676
// _xxinterpchannels added in 3.12.
677
+ // audioop removed in 3.13
678
+ // _crypt removed in 3.13
679
+ // spwd removed in Python 3.13
678
680
679
681
// We didn't build ctypes_test until 3.9.
680
682
// We didn't build some test extensions until 3.9.
681
683
682
684
const GLOBAL_EXTENSIONS_PYTHON_3_8 : & [ & str ] = & [ "_sha256" , "_sha512" , "parser" ] ;
683
685
684
686
const GLOBAL_EXTENSIONS_PYTHON_3_9 : & [ & str ] = & [
687
+ "audioop" ,
685
688
"_peg_parser" ,
686
689
"_sha256" ,
687
690
"_sha512" ,
@@ -692,6 +695,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_9: &[&str] = &[
692
695
] ;
693
696
694
697
const GLOBAL_EXTENSIONS_PYTHON_3_10 : & [ & str ] = & [
698
+ "audioop" ,
695
699
"_sha256" ,
696
700
"_sha512" ,
697
701
"_uuid" ,
@@ -700,6 +704,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_10: &[&str] = &[
700
704
] ;
701
705
702
706
const GLOBAL_EXTENSIONS_PYTHON_3_11 : & [ & str ] = & [
707
+ "audioop" ,
703
708
"_sha256" ,
704
709
"_sha512" ,
705
710
"_tokenize" ,
@@ -710,6 +715,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_11: &[&str] = &[
710
715
] ;
711
716
712
717
const GLOBAL_EXTENSIONS_PYTHON_3_12 : & [ & str ] = & [
718
+ "audioop" ,
713
719
"_sha2" ,
714
720
"_tokenize" ,
715
721
"_typing" ,
@@ -722,14 +728,19 @@ const GLOBAL_EXTENSIONS_PYTHON_3_13: &[&str] = &[
722
728
"_sha2" ,
723
729
"_tokenize" ,
724
730
"_typing" ,
725
- "_xxinterpchannels " ,
726
- "_xxsubinterpreters " ,
731
+ "_interpchannels " ,
732
+ "_subinterpreters " ,
727
733
"_zoneinfo" ,
734
+ "_interpreters" ,
735
+ "_suggestions" ,
736
+ "_sysconfig" ,
737
+ "_testexternalinspection" ,
728
738
] ;
729
739
730
740
const GLOBAL_EXTENSIONS_MACOS : & [ & str ] = & [ "_scproxy" ] ;
731
741
732
- const GLOBAL_EXTENSIONS_POSIX : & [ & str ] = & [
742
+ // TODO(zanieb): Consider replicating this explicitly for each Python version.
743
+ const GLOBAL_EXTENSIONS_POSIX_PRE_313 : & [ & str ] = & [
733
744
"_crypt" ,
734
745
"_ctypes_test" ,
735
746
"_curses" ,
@@ -748,7 +759,26 @@ const GLOBAL_EXTENSIONS_POSIX: &[&str] = &[
748
759
"termios" ,
749
760
] ;
750
761
751
- const GLOBAL_EXTENSIONS_LINUX : & [ & str ] = & [ "spwd" ] ;
762
+ const GLOBAL_EXTENSIONS_POSIX_POST_313 : & [ & str ] = & [
763
+ "_ctypes_test" ,
764
+ "_curses" ,
765
+ "_curses_panel" ,
766
+ "_dbm" ,
767
+ "_posixshmem" ,
768
+ "_posixsubprocess" ,
769
+ "_testinternalcapi" ,
770
+ "fcntl" ,
771
+ "grp" ,
772
+ "posix" ,
773
+ "pwd" ,
774
+ "readline" ,
775
+ "resource" ,
776
+ "syslog" ,
777
+ "termios" ,
778
+ ] ;
779
+
780
+ const GLOBAL_EXTENSIONS_LINUX_PRE_313 : & [ & str ] = & [ "spwd" ] ;
781
+ const GLOBAL_EXTENSIONS_LINUX_POST_313 : & [ & str ] = & [ ] ;
752
782
753
783
const GLOBAL_EXTENSIONS_WINDOWS : & [ & str ] = & [
754
784
"_msi" ,
@@ -1004,20 +1034,18 @@ fn validate_elf<'data, Elf: FileHeader<Endian = Endianness>>(
1004
1034
if let Some ( version) = version_version {
1005
1035
let parts: Vec < & str > = version. splitn ( 2 , '_' ) . collect ( ) ;
1006
1036
1007
- if parts. len ( ) == 2 {
1008
- if parts[ 0 ] == "GLIBC" {
1009
- let v = version_compare:: Version :: from ( parts[ 1 ] )
1010
- . expect ( "unable to parse version" ) ;
1037
+ if parts. len ( ) == 2 && parts[ 0 ] == "GLIBC" {
1038
+ let v = version_compare:: Version :: from ( parts[ 1 ] )
1039
+ . expect ( "unable to parse version" ) ;
1011
1040
1012
- if & v > wanted_glibc_max_version {
1013
- context. errors . push ( format ! (
1014
- "{} references too new glibc symbol {:?} ({} > {})" ,
1015
- path. display( ) ,
1016
- name,
1017
- v,
1018
- wanted_glibc_max_version,
1019
- ) ) ;
1020
- }
1041
+ if & v > wanted_glibc_max_version {
1042
+ context. errors . push ( format ! (
1043
+ "{} references too new glibc symbol {:?} ({} > {})" ,
1044
+ path. display( ) ,
1045
+ name,
1046
+ v,
1047
+ wanted_glibc_max_version,
1048
+ ) ) ;
1021
1049
}
1022
1050
}
1023
1051
}
@@ -1045,12 +1073,8 @@ fn validate_elf<'data, Elf: FileHeader<Endian = Endianness>>(
1045
1073
if let Some ( filename) = path. file_name ( ) {
1046
1074
let filename = filename. to_string_lossy ( ) ;
1047
1075
1048
- if filename. starts_with ( "libpython" ) && filename. ends_with ( ".so.1.0" ) {
1049
- if matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK )
1050
- && symbol. st_visibility ( ) == STV_DEFAULT
1051
- {
1052
- context. libpython_exported_symbols . insert ( name. to_string ( ) ) ;
1053
- }
1076
+ if filename. starts_with ( "libpython" ) && filename. ends_with ( ".so.1.0" ) && matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK ) && symbol. st_visibility ( ) == STV_DEFAULT {
1077
+ context. libpython_exported_symbols . insert ( name. to_string ( ) ) ;
1054
1078
}
1055
1079
}
1056
1080
}
@@ -1144,7 +1168,7 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1144
1168
target_version = Some ( parse_version_nibbles ( v. version . get ( endian) ) ) ;
1145
1169
}
1146
1170
LoadCommandVariant :: Dylib ( command) => {
1147
- let raw_string = load_command. string ( endian, command. dylib . name . clone ( ) ) ?;
1171
+ let raw_string = load_command. string ( endian, command. dylib . name ) ?;
1148
1172
let lib = String :: from_utf8 ( raw_string. to_vec ( ) ) ?;
1149
1173
1150
1174
dylib_names. push ( lib. clone ( ) ) ;
@@ -1355,9 +1379,9 @@ fn validate_possible_object_file(
1355
1379
json,
1356
1380
triple,
1357
1381
python_major_minor,
1358
- path. as_ref ( ) ,
1382
+ path,
1359
1383
header,
1360
- & data,
1384
+ data,
1361
1385
) ?;
1362
1386
}
1363
1387
FileKind :: Elf64 => {
@@ -1368,9 +1392,9 @@ fn validate_possible_object_file(
1368
1392
json,
1369
1393
triple,
1370
1394
python_major_minor,
1371
- path. as_ref ( ) ,
1395
+ path,
1372
1396
header,
1373
- & data,
1397
+ data,
1374
1398
) ?;
1375
1399
}
1376
1400
FileKind :: MachO32 => {
@@ -1386,9 +1410,9 @@ fn validate_possible_object_file(
1386
1410
json. apple_sdk_version
1387
1411
. as_ref ( )
1388
1412
. expect ( "apple_sdk_version should be set" ) ,
1389
- path. as_ref ( ) ,
1413
+ path,
1390
1414
header,
1391
- & data,
1415
+ data,
1392
1416
) ?;
1393
1417
}
1394
1418
FileKind :: MachO64 => {
@@ -1404,9 +1428,9 @@ fn validate_possible_object_file(
1404
1428
json. apple_sdk_version
1405
1429
. as_ref ( )
1406
1430
. expect ( "apple_sdk_version should be set" ) ,
1407
- path. as_ref ( ) ,
1431
+ path,
1408
1432
header,
1409
- & data,
1433
+ data,
1410
1434
) ?;
1411
1435
}
1412
1436
FileKind :: MachOFat32 | FileKind :: MachOFat64 => {
@@ -1418,11 +1442,11 @@ fn validate_possible_object_file(
1418
1442
}
1419
1443
FileKind :: Pe32 => {
1420
1444
let file = PeFile32 :: parse ( data) ?;
1421
- validate_pe ( & mut context, path. as_ref ( ) , & file) ?;
1445
+ validate_pe ( & mut context, path, & file) ?;
1422
1446
}
1423
1447
FileKind :: Pe64 => {
1424
1448
let file = PeFile64 :: parse ( data) ?;
1425
- validate_pe ( & mut context, path. as_ref ( ) , & file) ?;
1449
+ validate_pe ( & mut context, path, & file) ?;
1426
1450
}
1427
1451
_ => { }
1428
1452
}
@@ -1450,7 +1474,7 @@ fn validate_extension_modules(
1450
1474
return Ok ( errors) ;
1451
1475
}
1452
1476
1453
- let mut wanted = BTreeSet :: from_iter ( GLOBAL_EXTENSIONS . iter ( ) . map ( |x| * x ) ) ;
1477
+ let mut wanted = BTreeSet :: from_iter ( GLOBAL_EXTENSIONS . iter ( ) . copied ( ) ) ;
1454
1478
1455
1479
match python_major_minor {
1456
1480
"3.8" => {
@@ -1477,7 +1501,17 @@ fn validate_extension_modules(
1477
1501
}
1478
1502
1479
1503
if is_macos {
1480
- wanted. extend ( GLOBAL_EXTENSIONS_POSIX ) ;
1504
+ match python_major_minor {
1505
+ "3.8" | "3.9" | "3.10" | "3.11" | "3.12" => {
1506
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX_PRE_313 ) ;
1507
+ }
1508
+ "3.13" => {
1509
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX_POST_313 ) ;
1510
+ }
1511
+ _ => {
1512
+ panic ! ( "unhandled Python version: {}" , python_major_minor) ;
1513
+ }
1514
+ }
1481
1515
wanted. extend ( GLOBAL_EXTENSIONS_MACOS ) ;
1482
1516
}
1483
1517
@@ -1492,15 +1526,42 @@ fn validate_extension_modules(
1492
1526
}
1493
1527
1494
1528
if is_linux {
1495
- wanted. extend ( GLOBAL_EXTENSIONS_POSIX ) ;
1496
- wanted. extend ( GLOBAL_EXTENSIONS_LINUX ) ;
1529
+ match python_major_minor {
1530
+ "3.8" | "3.9" | "3.10" | "3.11" | "3.12" => {
1531
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX_PRE_313 ) ;
1532
+ }
1533
+ "3.13" => {
1534
+ wanted. extend ( GLOBAL_EXTENSIONS_POSIX_POST_313 ) ;
1535
+ }
1536
+ _ => {
1537
+ panic ! ( "unhandled Python version: {}" , python_major_minor) ;
1538
+ }
1539
+ }
1540
+ match python_major_minor {
1541
+ "3.8" | "3.9" | "3.10" | "3.11" | "3.12" => {
1542
+ wanted. extend ( GLOBAL_EXTENSIONS_LINUX_PRE_313 ) ;
1543
+ }
1544
+ "3.13" => {
1545
+ wanted. extend ( GLOBAL_EXTENSIONS_LINUX_POST_313 ) ;
1546
+ }
1547
+ _ => {
1548
+ panic ! ( "unhandled Python version: {}" , python_major_minor) ;
1549
+ }
1550
+ }
1497
1551
1498
- if !is_linux_musl {
1552
+ // Removed in Python 3.13
1553
+ if !is_linux_musl && matches ! ( python_major_minor, "3.8" | "3.9" | "3.10" | "3.11" | "3.12" )
1554
+ {
1499
1555
wanted. insert ( "ossaudiodev" ) ;
1500
1556
}
1501
1557
}
1502
1558
1503
- if ( is_linux || is_macos) && matches ! ( python_major_minor, "3.9" | "3.10" | "3.11" | "3.12" | "3.13" ) {
1559
+ if ( is_linux || is_macos)
1560
+ && matches ! (
1561
+ python_major_minor,
1562
+ "3.9" | "3.10" | "3.11" | "3.12" | "3.13"
1563
+ )
1564
+ {
1504
1565
wanted. extend ( [
1505
1566
"_testbuffer" ,
1506
1567
"_testimportmultiple" ,
@@ -1604,8 +1665,7 @@ fn validate_json(json: &PythonJsonMain, triple: &str, is_debug: bool) -> Result<
1604
1665
triple,
1605
1666
json. crt_features . contains ( & "static" . to_string ( ) ) ,
1606
1667
& have_extensions,
1607
- ) ?
1608
- . into_iter ( ) ,
1668
+ ) ?,
1609
1669
) ;
1610
1670
1611
1671
Ok ( errors)
@@ -1659,7 +1719,7 @@ fn validate_distribution(
1659
1719
1660
1720
let is_static = triple. contains ( "unknown-linux-musl" ) ;
1661
1721
1662
- let mut tf = crate :: open_distribution_archive ( & dist_path) ?;
1722
+ let mut tf = crate :: open_distribution_archive ( dist_path) ?;
1663
1723
1664
1724
// First entry in archive should be python/PYTHON.json.
1665
1725
let mut entries = tf. entries ( ) ?;
@@ -1725,7 +1785,7 @@ fn validate_distribution(
1725
1785
context. merge ( validate_possible_object_file (
1726
1786
json. as_ref ( ) . unwrap ( ) ,
1727
1787
python_major_minor,
1728
- & triple,
1788
+ triple,
1729
1789
& path,
1730
1790
& data,
1731
1791
) ?) ;
@@ -1750,9 +1810,9 @@ fn validate_distribution(
1750
1810
context. merge ( validate_possible_object_file (
1751
1811
json. as_ref ( ) . unwrap ( ) ,
1752
1812
python_major_minor,
1753
- & triple,
1813
+ triple,
1754
1814
& member_path,
1755
- & member_data,
1815
+ member_data,
1756
1816
) ?) ;
1757
1817
}
1758
1818
}
@@ -1938,11 +1998,7 @@ fn validate_distribution(
1938
1998
} else if triple. contains ( "-windows-" ) {
1939
1999
false
1940
2000
// Presence of a shared library extension implies no export.
1941
- } else if ext. shared_lib . is_some ( ) {
1942
- false
1943
- } else {
1944
- true
1945
- } ;
2001
+ } else { ext. shared_lib . is_none ( ) } ;
1946
2002
1947
2003
if exported != wanted {
1948
2004
context. errors . push ( format ! (
@@ -2020,7 +2076,7 @@ fn verify_distribution_behavior(dist_path: &Path) -> Result<Vec<String>> {
2020
2076
tf. unpack ( temp_dir. path ( ) ) ?;
2021
2077
2022
2078
let python_json_path = temp_dir. path ( ) . join ( "python" ) . join ( "PYTHON.json" ) ;
2023
- let python_json_data = std:: fs:: read ( & python_json_path) ?;
2079
+ let python_json_data = std:: fs:: read ( python_json_path) ?;
2024
2080
let python_json = parse_python_json ( & python_json_data) ?;
2025
2081
2026
2082
let python_exe = temp_dir. path ( ) . join ( "python" ) . join ( python_json. python_exe ) ;
@@ -2029,7 +2085,7 @@ fn verify_distribution_behavior(dist_path: &Path) -> Result<Vec<String>> {
2029
2085
std:: fs:: write ( & test_file, PYTHON_VERIFICATIONS . as_bytes ( ) ) ?;
2030
2086
2031
2087
eprintln ! ( " running interpreter tests (output should follow)" ) ;
2032
- let output = duct:: cmd ( & python_exe, & [ test_file. display ( ) . to_string ( ) ] )
2088
+ let output = duct:: cmd ( python_exe, [ test_file. display ( ) . to_string ( ) ] )
2033
2089
. stdout_to_stderr ( )
2034
2090
. unchecked ( )
2035
2091
. env ( "TARGET_TRIPLE" , & python_json. target_triple )
0 commit comments