@@ -1206,7 +1206,7 @@ fn ends_with(entry: &DirEntry, pat: &str) -> bool {
1206
1206
/// Returns `None` if the library directory is not available, and a runtime error
1207
1207
/// when no or multiple sysconfigdata files are found.
1208
1208
fn find_sysconfigdata ( cross : & CrossCompileConfig ) -> Result < Option < PathBuf > > {
1209
- let mut sysconfig_paths = find_all_sysconfigdata ( cross) ;
1209
+ let mut sysconfig_paths = find_all_sysconfigdata ( cross) ? ;
1210
1210
if sysconfig_paths. is_empty ( ) {
1211
1211
if let Some ( lib_dir) = cross. lib_dir . as_ref ( ) {
1212
1212
bail ! ( "Could not find _sysconfigdata*.py in {}" , lib_dir. display( ) ) ;
@@ -1269,11 +1269,16 @@ fn find_sysconfigdata(cross: &CrossCompileConfig) -> Result<Option<PathBuf>> {
1269
1269
///
1270
1270
/// Returns an empty vector when the target Python library directory
1271
1271
/// is not set via `PYO3_CROSS_LIB_DIR`.
1272
- pub fn find_all_sysconfigdata ( cross : & CrossCompileConfig ) -> Vec < PathBuf > {
1272
+ pub fn find_all_sysconfigdata ( cross : & CrossCompileConfig ) -> Result < Vec < PathBuf > > {
1273
1273
let sysconfig_paths = if let Some ( lib_dir) = cross. lib_dir . as_ref ( ) {
1274
- search_lib_dir ( lib_dir, cross)
1274
+ search_lib_dir ( lib_dir, cross) . with_context ( || {
1275
+ format ! (
1276
+ "failed to search the lib dir at 'PYO3_CROSS_LIB_DIR={}'" ,
1277
+ lib_dir. display( )
1278
+ )
1279
+ } ) ?
1275
1280
} else {
1276
- return Vec :: new ( ) ;
1281
+ return Ok ( Vec :: new ( ) ) ;
1277
1282
} ;
1278
1283
1279
1284
let sysconfig_name = env_var ( "_PYTHON_SYSCONFIGDATA_NAME" ) ;
@@ -1291,7 +1296,7 @@ pub fn find_all_sysconfigdata(cross: &CrossCompileConfig) -> Vec<PathBuf> {
1291
1296
sysconfig_paths. sort ( ) ;
1292
1297
sysconfig_paths. dedup ( ) ;
1293
1298
1294
- sysconfig_paths
1299
+ Ok ( sysconfig_paths)
1295
1300
}
1296
1301
1297
1302
fn is_pypy_lib_dir ( path : & str , v : & Option < PythonVersion > ) -> bool {
@@ -1322,17 +1327,22 @@ fn is_cpython_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
1322
1327
}
1323
1328
1324
1329
/// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths
1325
- fn search_lib_dir ( path : impl AsRef < Path > , cross : & CrossCompileConfig ) -> Vec < PathBuf > {
1330
+ fn search_lib_dir ( path : impl AsRef < Path > , cross : & CrossCompileConfig ) -> Result < Vec < PathBuf > > {
1326
1331
let mut sysconfig_paths = vec ! [ ] ;
1327
- for f in fs:: read_dir ( path) . expect ( "Path does not exist" ) {
1332
+ for f in fs:: read_dir ( path. as_ref ( ) ) . with_context ( || {
1333
+ format ! (
1334
+ "failed to list the entries in '{}'" ,
1335
+ path. as_ref( ) . display( )
1336
+ )
1337
+ } ) ? {
1328
1338
sysconfig_paths. extend ( match & f {
1329
1339
// Python 3.7+ sysconfigdata with platform specifics
1330
1340
Ok ( f) if starts_with ( f, "_sysconfigdata_" ) && ends_with ( f, "py" ) => vec ! [ f. path( ) ] ,
1331
1341
Ok ( f) if f. metadata ( ) . map_or ( false , |metadata| metadata. is_dir ( ) ) => {
1332
1342
let file_name = f. file_name ( ) ;
1333
1343
let file_name = file_name. to_string_lossy ( ) ;
1334
1344
if file_name == "build" || file_name == "lib" {
1335
- search_lib_dir ( f. path ( ) , cross)
1345
+ search_lib_dir ( f. path ( ) , cross) ?
1336
1346
} else if file_name. starts_with ( "lib." ) {
1337
1347
// check if right target os
1338
1348
if !file_name. contains ( & cross. target . operating_system . to_string ( ) ) {
@@ -1342,12 +1352,12 @@ fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<Pat
1342
1352
if !file_name. contains ( & cross. target . architecture . to_string ( ) ) {
1343
1353
continue ;
1344
1354
}
1345
- search_lib_dir ( f. path ( ) , cross)
1355
+ search_lib_dir ( f. path ( ) , cross) ?
1346
1356
} else if is_cpython_lib_dir ( & file_name, & cross. version )
1347
1357
|| is_pypy_lib_dir ( & file_name, & cross. version )
1348
1358
|| is_graalpy_lib_dir ( & file_name, & cross. version )
1349
1359
{
1350
- search_lib_dir ( f. path ( ) , cross)
1360
+ search_lib_dir ( f. path ( ) , cross) ?
1351
1361
} else {
1352
1362
continue ;
1353
1363
}
@@ -1376,7 +1386,7 @@ fn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Vec<Pat
1376
1386
}
1377
1387
}
1378
1388
1379
- sysconfig_paths
1389
+ Ok ( sysconfig_paths)
1380
1390
}
1381
1391
1382
1392
/// Find cross compilation information from sysconfigdata file
@@ -2747,4 +2757,24 @@ mod tests {
2747
2757
]
2748
2758
) ;
2749
2759
}
2760
+
2761
+ #[ test]
2762
+ fn test_find_sysconfigdata_in_invalid_lib_dir ( ) {
2763
+ let e = find_all_sysconfigdata ( & CrossCompileConfig {
2764
+ lib_dir : Some ( PathBuf :: from ( "/abc/123/not/a/real/path" ) ) ,
2765
+ version : None ,
2766
+ implementation : None ,
2767
+ target : triple ! ( "x86_64-unknown-linux-gnu" ) ,
2768
+ } )
2769
+ . unwrap_err ( ) ;
2770
+
2771
+ // actual error message is platform-dependent, so just check the context we add
2772
+ assert ! ( e. report( ) . to_string( ) . starts_with(
2773
+ "failed to search the lib dir at 'PYO3_CROSS_LIB_DIR=/abc/123/not/a/real/path'\n \
2774
+ caused by:\n \
2775
+ - 0: failed to list the entries in '/abc/123/not/a/real/path'\n \
2776
+ - 1: \
2777
+ "
2778
+ ) ) ;
2779
+ }
2750
2780
}
0 commit comments