From 5df4706a31a5f18116481f3754c13a0a183bfa73 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Sat, 30 Nov 2024 15:06:27 +0100 Subject: [PATCH] map `io::ErrorKind::IsADirectory`/`NotADirectory` to Python on 1.83+ (#4747) --- newsfragments/4747.changed.md | 1 + pyo3-build-config/src/lib.rs | 5 +++++ src/err/impls.rs | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 newsfragments/4747.changed.md diff --git a/newsfragments/4747.changed.md b/newsfragments/4747.changed.md new file mode 100644 index 00000000000..ca04831d064 --- /dev/null +++ b/newsfragments/4747.changed.md @@ -0,0 +1 @@ +Map `io::ErrorKind::IsADirectory`/`NotADirectory` to the corresponding Python exception on Rust 1.83+ \ No newline at end of file diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index 642fdf1659f..554200040e4 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -156,6 +156,10 @@ pub fn print_feature_cfgs() { if rustc_minor_version >= 79 { println!("cargo:rustc-cfg=diagnostic_namespace"); } + + if rustc_minor_version >= 83 { + println!("cargo:rustc-cfg=io_error_more"); + } } /// Registers `pyo3`s config names as reachable cfg expressions @@ -180,6 +184,7 @@ pub fn print_expected_cfgs() { println!("cargo:rustc-check-cfg=cfg(diagnostic_namespace)"); println!("cargo:rustc-check-cfg=cfg(c_str_lit)"); println!("cargo:rustc-check-cfg=cfg(rustc_has_once_lock)"); + println!("cargo:rustc-check-cfg=cfg(io_error_more)"); // allow `Py_3_*` cfgs from the minimum supported version up to the // maximum minor version (+1 for development for the next) diff --git a/src/err/impls.rs b/src/err/impls.rs index b84f46d4306..1af45b7e628 100644 --- a/src/err/impls.rs +++ b/src/err/impls.rs @@ -27,6 +27,15 @@ impl From for io::Error { } else if err.is_instance_of::(py) { io::ErrorKind::TimedOut } else { + #[cfg(io_error_more)] + if err.is_instance_of::(py) { + io::ErrorKind::IsADirectory + } else if err.is_instance_of::(py) { + io::ErrorKind::NotADirectory + } else { + io::ErrorKind::Other + } + #[cfg(not(io_error_more))] io::ErrorKind::Other } }); @@ -54,6 +63,10 @@ impl From for PyErr { io::ErrorKind::AlreadyExists => exceptions::PyFileExistsError::new_err(err), io::ErrorKind::WouldBlock => exceptions::PyBlockingIOError::new_err(err), io::ErrorKind::TimedOut => exceptions::PyTimeoutError::new_err(err), + #[cfg(io_error_more)] + io::ErrorKind::IsADirectory => exceptions::PyIsADirectoryError::new_err(err), + #[cfg(io_error_more)] + io::ErrorKind::NotADirectory => exceptions::PyNotADirectoryError::new_err(err), _ => exceptions::PyOSError::new_err(err), } } @@ -167,5 +180,9 @@ mod tests { check_err(io::ErrorKind::AlreadyExists, "FileExistsError"); check_err(io::ErrorKind::WouldBlock, "BlockingIOError"); check_err(io::ErrorKind::TimedOut, "TimeoutError"); + #[cfg(io_error_more)] + check_err(io::ErrorKind::IsADirectory, "IsADirectoryError"); + #[cfg(io_error_more)] + check_err(io::ErrorKind::NotADirectory, "NotADirectoryError"); } }