Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emit cargo:rustc-check-cfg=CHECK_CFG for pyo3s config names #4163

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ fn configure_pyo3() -> Result<()> {
}

fn main() {
pyo3_build_config::print_expected_cfgs();
if let Err(e) = configure_pyo3() {
eprintln!("error: {}", e.report());
std::process::exit(1)
Expand Down
4 changes: 2 additions & 2 deletions guide/src/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,12 @@ To make PyO3's core functionality continue to work while the GIL Refs API is in

PyO3 0.21 has introduced the [`PyBackedStr`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedStr.html) and [`PyBackedBytes`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedBytes.html) types to help with this case. The easiest way to avoid lifetime challenges from extracting `&str` is to use these. For more complex types like `Vec<&str>`, is now impossible to extract directly from a Python object and `Vec<PyBackedStr>` is the recommended upgrade path.

A key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines. For example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs-migration` feature.
A key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines. For example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs` feature.

Before:

```rust
# #[cfg(feature = "gil-refs-migration")] {
# #[cfg(feature = "gil-refs")] {
# use pyo3::prelude::*;
# use pyo3::types::{PyList, PyType};
# fn example<'py>(py: Python<'py>) -> PyResult<()> {
Expand Down
4 changes: 2 additions & 2 deletions pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
};

/// Minimum Python version PyO3 supports.
const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 };
pub(crate) const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 };

/// GraalPy may implement the same CPython version over multiple releases.
const MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion {
Expand All @@ -39,7 +39,7 @@ const MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion {
};

/// Maximum Python version that can be used as minimum required Python version with abi3.
const ABI3_MAX_MINOR: u8 = 12;
pub(crate) const ABI3_MAX_MINOR: u8 = 12;

/// Gets an environment variable owned by cargo.
///
Expand Down
20 changes: 20 additions & 0 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use target_lexicon::OperatingSystem;
/// For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building-and-distribution/multiple_python_versions.html).
#[cfg(feature = "resolve-config")]
pub fn use_pyo3_cfgs() {
print_expected_cfgs();
for cargo_command in get().build_script_outputs() {
println!("{}", cargo_command)
}
Expand Down Expand Up @@ -153,6 +154,25 @@ pub fn print_feature_cfgs() {
}
}

/// Registers `pyo3`s config names as reachable cfg expressions
///
/// - <https://github.com/rust-lang/cargo/pull/13571>
/// - <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg>
#[doc(hidden)]
pub fn print_expected_cfgs() {
println!("cargo:rustc-check-cfg=cfg(Py_LIMITED_API)");
println!("cargo:rustc-check-cfg=cfg(PyPy)");
println!("cargo:rustc-check-cfg=cfg(GraalPy)");
println!("cargo:rustc-check-cfg=cfg(py_sys_config, values(\"Py_DEBUG\", \"Py_REF_DEBUG\", \"Py_TRACE_REFS\", \"COUNT_ALLOCS\"))");
println!("cargo:rustc-check-cfg=cfg(invalid_from_utf8_lint)");

// allow `Py_3_*` cfgs from the minimum supported version up to the
// maximum minor version (+1 for development for the next)
for i in impl_::MINIMUM_SUPPORTED_VERSION.minor..=impl_::ABI3_MAX_MINOR + 1 {
println!("cargo:rustc-check-cfg=cfg(Py_3_{i})");
}
}

/// Private exports used in PyO3's build.rs
///
/// Please don't use these - they could change at any time.
Expand Down
1 change: 1 addition & 0 deletions pyo3-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ fn print_config_and_exit(config: &InterpreterConfig) {
}

fn main() {
pyo3_build_config::print_expected_cfgs();
if let Err(e) = configure_pyo3() {
eprintln!("error: {}", e.report());
std::process::exit(1)
Expand Down
2 changes: 1 addition & 1 deletion src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
//! enabled, `Ungil` is defined as the following:
//!
//! ```rust
//! # #[cfg(FALSE)]
//! # #[cfg(any())]
//! # {
//! #![feature(auto_traits, negative_impls)]
//!
Expand Down
10 changes: 5 additions & 5 deletions src/tests/hygiene/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,23 @@ pub enum Enum {
#[pyo3(crate = "crate")]
pub struct Foo3 {
#[pyo3(get, set)]
#[cfg(FALSE)]
#[cfg(any())]
field: i32,

#[pyo3(get, set)]
#[cfg(not(FALSE))]
#[cfg(not(any()))]
field: u32,
}

#[crate::pyclass]
#[pyo3(crate = "crate")]
pub struct Foo4 {
#[pyo3(get, set)]
#[cfg(FALSE)]
#[cfg(not(FALSE))]
#[cfg(any())]
#[cfg(not(any()))]
field: i32,

#[pyo3(get, set)]
#[cfg(not(FALSE))]
#[cfg(not(any()))]
field: u32,
}
Loading