diff --git a/noxfile.py b/noxfile.py index 2b4b694dba4..c1d5a090d39 100644 --- a/noxfile.py +++ b/noxfile.py @@ -606,7 +606,11 @@ def _get_coverage_env() -> Dict[str, str]: for line in output.strip().splitlines(): (key, value) = line.split("=", maxsplit=1) - env[key] = value.strip('"') + # Strip single or double quotes from the variable value + # - quote used by llvm-cov differs between Windows and Linux + if value and value[0] in ("'", '"'): + value = value[1:-1] + env[key] = value # Ensure that examples/ and pytests/ all build to the correct target directory to collect # coverage artifacts. diff --git a/src/conversion.rs b/src/conversion.rs index 6fc7a6bf328..5e6211bd68f 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -81,9 +81,8 @@ pub trait ToPyObject { /// Defines a conversion from a Rust type to a Python object. /// -/// It functions similarly to std's [`Into`](std::convert::Into) trait, -/// but requires a [GIL token](Python) as an argument. -/// Many functions and traits internal to PyO3 require this trait as a bound, +/// It functions similarly to std's [`Into`] trait, but requires a [GIL token](Python) +/// as an argument. Many functions and traits internal to PyO3 require this trait as a bound, /// so a lack of this trait can manifest itself in different error messages. /// /// # Examples diff --git a/src/impl_/pyclass.rs b/src/impl_/pyclass.rs index 07fdcc44f2c..892c9c677b5 100644 --- a/src/impl_/pyclass.rs +++ b/src/impl_/pyclass.rs @@ -948,7 +948,7 @@ pub unsafe extern "C" fn free_with_freelist(obj: *mut c_ /// Workaround for Python issue 35810; no longer necessary in Python 3.8 #[inline] #[cfg(not(Py_3_8))] -unsafe fn bpo_35810_workaround(_py: Python<'_>, ty: *mut ffi::PyTypeObject) { +unsafe fn bpo_35810_workaround(py: Python<'_>, ty: *mut ffi::PyTypeObject) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version @@ -956,11 +956,16 @@ unsafe fn bpo_35810_workaround(_py: Python<'_>, ty: *mut ffi::PyTypeObject) { use crate::sync::GILOnceCell; static IS_PYTHON_3_8: GILOnceCell = GILOnceCell::new(); - if *IS_PYTHON_3_8.get_or_init(_py, || _py.version_info() >= (3, 8)) { + if *IS_PYTHON_3_8.get_or_init(py, || py.version_info() >= (3, 8)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } + #[cfg(not(Py_LIMITED_API))] + { + // suppress unused variable warning + let _ = py; + } ffi::Py_INCREF(ty as *mut ffi::PyObject); } diff --git a/src/pyclass/create_type_object.rs b/src/pyclass/create_type_object.rs index a374bfbc39c..ab1e2b07c9c 100644 --- a/src/pyclass/create_type_object.rs +++ b/src/pyclass/create_type_object.rs @@ -413,7 +413,7 @@ fn py_class_qualified_name(module_name: Option<&str>, class_name: &str) -> PyRes /// Workaround for Python issue 45315; no longer necessary in Python 3.11 #[inline] #[cfg(not(Py_3_11))] -fn bpo_45315_workaround(_py: Python<'_>, class_name: CString) { +fn bpo_45315_workaround(py: Python<'_>, class_name: CString) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version @@ -421,11 +421,16 @@ fn bpo_45315_workaround(_py: Python<'_>, class_name: CString) { use crate::sync::GILOnceCell; static IS_PYTHON_3_11: GILOnceCell = GILOnceCell::new(); - if *IS_PYTHON_3_11.get_or_init(_py, || _py.version_info() >= (3, 11)) { + if *IS_PYTHON_3_11.get_or_init(py, || py.version_info() >= (3, 11)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } + #[cfg(not(Py_LIMITED_API))] + { + // suppress unused variable warning + let _ = py; + } std::mem::forget(class_name); } diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index 1ec244a4165..46c31ba4b55 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -52,7 +52,7 @@ impl PyByteArray { ffi::PyByteArray_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t); // Check for an allocation error and return it let pypybytearray: Py = Py::from_owned_ptr_or_err(py, pyptr)?; - let buffer = ffi::PyByteArray_AsString(pyptr) as *mut u8; + let buffer: *mut u8 = ffi::PyByteArray_AsString(pyptr).cast(); debug_assert!(!buffer.is_null()); // Zero-initialise the uninitialised bytearray std::ptr::write_bytes(buffer, 0u8, len); @@ -89,7 +89,7 @@ impl PyByteArray { /// /// See the safety requirements of [`PyByteArray::as_bytes`] and [`PyByteArray::as_bytes_mut`]. pub fn data(&self) -> *mut u8 { - unsafe { ffi::PyByteArray_AsString(self.as_ptr()) as *mut u8 } + unsafe { ffi::PyByteArray_AsString(self.as_ptr()).cast() } } /// Extracts a slice of the `ByteArray`'s entire buffer. diff --git a/src/types/bytes.rs b/src/types/bytes.rs index ef26abf0306..1df82d2bf08 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -58,7 +58,7 @@ impl PyBytes { let pyptr = ffi::PyBytes_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t); // Check for an allocation error and return it let pypybytes: Py = Py::from_owned_ptr_or_err(py, pyptr)?; - let buffer = ffi::PyBytes_AsString(pyptr) as *mut u8; + let buffer: *mut u8 = ffi::PyBytes_AsString(pyptr).cast(); debug_assert!(!buffer.is_null()); // Zero-initialise the uninitialised bytestring std::ptr::write_bytes(buffer, 0u8, len); diff --git a/src/types/string.rs b/src/types/string.rs index 44272101ae3..1a6a717b57b 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -184,11 +184,11 @@ impl PyString { if #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { // PyUnicode_AsUTF8AndSize only available on limited API starting with 3.10. let mut size: ffi::Py_ssize_t = 0; - let data = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) }; + let data: *const u8 = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size).cast() }; if data.is_null() { return Err(crate::PyErr::fetch(self.py())); } else { - unsafe { std::slice::from_raw_parts(data as *const u8, size as usize) } + unsafe { std::slice::from_raw_parts(data, size as usize) } } } else { let bytes = unsafe { diff --git a/tests/test_compile_error.rs b/tests/test_compile_error.rs index 8a22d66cdbf..5f02049e44c 100644 --- a/tests/test_compile_error.rs +++ b/tests/test_compile_error.rs @@ -12,7 +12,7 @@ fn test_compile_errors() { t.compile_fail("tests/ui/invalid_pyclass_enum.rs"); t.compile_fail("tests/ui/invalid_pyclass_item.rs"); t.compile_fail("tests/ui/invalid_pyfunction_signatures.rs"); - #[cfg(not(Py_LIMITED_API))] + #[cfg(any(not(Py_LIMITED_API), Py_3_11))] t.compile_fail("tests/ui/invalid_pymethods_buffer.rs"); t.compile_fail("tests/ui/invalid_pymethod_names.rs"); t.compile_fail("tests/ui/invalid_pymodule_args.rs"); @@ -32,6 +32,8 @@ fn test_compile_errors() { t.compile_fail("tests/ui/invalid_frozen_pyclass_borrow.rs"); t.compile_fail("tests/ui/invalid_pymethod_receiver.rs"); t.compile_fail("tests/ui/missing_intopy.rs"); + // adding extra error conversion impls changes the output + #[cfg(not(any(feature = "eyre", feature = "anyhow")))] t.compile_fail("tests/ui/invalid_result_conversion.rs"); t.compile_fail("tests/ui/not_send.rs"); t.compile_fail("tests/ui/not_send2.rs"); diff --git a/tests/ui/invalid_pymethod_receiver.stderr b/tests/ui/invalid_pymethod_receiver.stderr index 83f29f548a0..b7a7880dbde 100644 --- a/tests/ui/invalid_pymethod_receiver.stderr +++ b/tests/ui/invalid_pymethod_receiver.stderr @@ -5,11 +5,11 @@ error[E0277]: the trait bound `i32: From<&PyCell>` is not satisfied | ^^^ the trait `From<&PyCell>` is not implemented for `i32` | = help: the following other types implement trait `From`: - > > - > > - > + > > + > + > = note: required for `&PyCell` to implement `Into` = note: required for `i32` to implement `TryFrom<&PyCell>` diff --git a/tests/ui/invalid_result_conversion.stderr b/tests/ui/invalid_result_conversion.stderr index eb0f8881fb9..47d945832c0 100644 --- a/tests/ui/invalid_result_conversion.stderr +++ b/tests/ui/invalid_result_conversion.stderr @@ -5,14 +5,14 @@ error[E0277]: the trait bound `PyErr: From` is not satisfied | ^^^^^^^^^^^^^ the trait `From` is not implemented for `PyErr` | = help: the following other types implement trait `From`: - > - > - > - > - > - > - > - > + > + > + > + >> + > + > + > + > and $N others = note: required for `MyError` to implement `Into` = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/missing_intopy.stderr b/tests/ui/missing_intopy.stderr index 69430705b86..26b32b3e742 100644 --- a/tests/ui/missing_intopy.stderr +++ b/tests/ui/missing_intopy.stderr @@ -5,14 +5,14 @@ error[E0277]: the trait bound `Blah: IntoPy>` is not satisfied | ^^^^^^^^^^^^^^^^^^^ the trait `IntoPy>` is not implemented for `Blah` | = help: the following other types implement trait `IntoPy`: - <&'a OsString as IntoPy>> - <&'a Path as IntoPy>> - <&'a PathBuf as IntoPy>> - <&'a PyErr as IntoPy>> - <&'a String as IntoPy>> - <&'a [u8] as IntoPy>> - <&'a str as IntoPy>> - <&'a str as IntoPy>> + >> + >> + >> + >> + >> + >> + >> + >> and $N others = note: required for `Blah` to implement `OkWrap` = note: this error originates in the attribute macro `pyo3::pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)