3802 lines
129 KiB
Diff
3802 lines
129 KiB
Diff
From 180f5886407e7c1dda34afa6fc7298b34d2925da Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 15:02:33 +0200
|
|
Subject: [PATCH 1/6] Update pyo3 to 0.25.0
|
|
|
|
---
|
|
Cargo.lock | 4 +-
|
|
include/pyo3/pyo3-build-config/Cargo.toml | 6 +-
|
|
include/pyo3/pyo3-build-config/src/errors.rs | 2 +-
|
|
include/pyo3/pyo3-build-config/src/impl_.rs | 41 +-
|
|
include/pyo3/pyo3-build-config/src/lib.rs | 63 +--
|
|
include/pyo3/pyo3-ffi/ACKNOWLEDGEMENTS | 2 +-
|
|
include/pyo3/pyo3-ffi/Cargo.toml | 10 +-
|
|
include/pyo3/pyo3-ffi/build.rs | 74 ++-
|
|
include/pyo3/pyo3-ffi/src/abstract_.rs | 41 +-
|
|
include/pyo3/pyo3-ffi/src/bytearrayobject.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/code.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/compat/mod.rs | 2 +
|
|
include/pyo3/pyo3-ffi/src/compat/py_3_10.rs | 26 ++
|
|
include/pyo3/pyo3-ffi/src/compat/py_3_13.rs | 15 +
|
|
include/pyo3/pyo3-ffi/src/compat/py_3_14.rs | 26 ++
|
|
.../pyo3/pyo3-ffi/src/cpython/abstract_.rs | 32 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/bytesobject.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/code.rs | 232 ++--------
|
|
include/pyo3/pyo3-ffi/src/cpython/compile.rs | 63 ++-
|
|
.../pyo3-ffi/src/cpython/critical_section.rs | 14 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/descrobject.rs | 5 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/dictobject.rs | 16 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/frameobject.rs | 5 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/funcobject.rs | 2 +
|
|
.../pyo3/pyo3-ffi/src/cpython/genobject.rs | 14 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/import.rs | 10 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/initconfig.rs | 10 +
|
|
include/pyo3/pyo3-ffi/src/cpython/lock.rs | 9 -
|
|
.../pyo3/pyo3-ffi/src/cpython/longobject.rs | 12 -
|
|
include/pyo3/pyo3-ffi/src/cpython/mod.rs | 5 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/object.rs | 8 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/objimpl.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/pyerrors.rs | 2 +
|
|
include/pyo3/pyo3-ffi/src/cpython/pyframe.rs | 5 +-
|
|
include/pyo3/pyo3-ffi/src/cpython/pyhash.rs | 38 ++
|
|
include/pyo3/pyo3-ffi/src/cpython/pystate.rs | 16 +-
|
|
.../pyo3/pyo3-ffi/src/cpython/tupleobject.rs | 4 +-
|
|
.../pyo3-ffi/src/cpython/unicodeobject.rs | 117 ++++-
|
|
.../pyo3-ffi/src/cpython/weakrefobject.rs | 1 +
|
|
include/pyo3/pyo3-ffi/src/datetime.rs | 10 +-
|
|
include/pyo3/pyo3-ffi/src/dictobject.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/floatobject.rs | 2 +-
|
|
.../pyo3/pyo3-ffi/src/genericaliasobject.rs | 12 +
|
|
include/pyo3/pyo3-ffi/src/lib.rs | 23 +-
|
|
include/pyo3/pyo3-ffi/src/longobject.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/memoryobject.rs | 5 +-
|
|
include/pyo3/pyo3-ffi/src/methodobject.rs | 8 +-
|
|
include/pyo3/pyo3-ffi/src/modsupport.rs | 7 +-
|
|
include/pyo3/pyo3-ffi/src/object.rs | 422 ++++--------------
|
|
include/pyo3/pyo3-ffi/src/pyarena.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/pybuffer.rs | 6 +-
|
|
include/pyo3/pyo3-ffi/src/pyerrors.rs | 1 +
|
|
include/pyo3/pyo3-ffi/src/pyframe.rs | 2 +-
|
|
include/pyo3/pyo3-ffi/src/pyhash.rs | 30 +-
|
|
include/pyo3/pyo3-ffi/src/pyport.rs | 9 +-
|
|
include/pyo3/pyo3-ffi/src/pystate.rs | 78 +++-
|
|
include/pyo3/pyo3-ffi/src/pythonrun.rs | 6 +-
|
|
include/pyo3/pyo3-ffi/src/refcount.rs | 369 +++++++++++++++
|
|
include/pyo3/pyo3-ffi/src/setobject.rs | 6 +-
|
|
include/pyo3/pyo3-ffi/src/weakrefobject.rs | 8 +-
|
|
60 files changed, 1065 insertions(+), 885 deletions(-)
|
|
create mode 100644 include/pyo3/pyo3-ffi/src/compat/py_3_14.rs
|
|
create mode 100644 include/pyo3/pyo3-ffi/src/cpython/pyhash.rs
|
|
create mode 100644 include/pyo3/pyo3-ffi/src/genericaliasobject.rs
|
|
create mode 100644 include/pyo3/pyo3-ffi/src/refcount.rs
|
|
|
|
diff --git a/Cargo.lock b/Cargo.lock
|
|
index 03fdf346..c4b1eb1c 100644
|
|
--- a/Cargo.lock
|
|
+++ b/Cargo.lock
|
|
@@ -190,7 +190,7 @@ dependencies = [
|
|
|
|
[[package]]
|
|
name = "pyo3-build-config"
|
|
-version = "0.23.3"
|
|
+version = "0.25.0"
|
|
dependencies = [
|
|
"once_cell",
|
|
"target-lexicon",
|
|
@@ -198,7 +198,7 @@ dependencies = [
|
|
|
|
[[package]]
|
|
name = "pyo3-ffi"
|
|
-version = "0.23.3"
|
|
+version = "0.25.0"
|
|
dependencies = [
|
|
"libc",
|
|
"pyo3-build-config",
|
|
diff --git a/include/pyo3/pyo3-build-config/Cargo.toml b/include/pyo3/pyo3-build-config/Cargo.toml
|
|
index 0facef81..54d5cb49 100644
|
|
--- a/include/pyo3/pyo3-build-config/Cargo.toml
|
|
+++ b/include/pyo3/pyo3-build-config/Cargo.toml
|
|
@@ -1,6 +1,6 @@
|
|
[package]
|
|
name = "pyo3-build-config"
|
|
-version = "0.23.3"
|
|
+version = "0.25.0"
|
|
description = "Build configuration for the PyO3 ecosystem"
|
|
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
|
keywords = ["pyo3", "python", "cpython", "ffi"]
|
|
@@ -36,7 +36,9 @@ abi3-py38 = ["abi3-py39"]
|
|
abi3-py39 = ["abi3-py310"]
|
|
abi3-py310 = ["abi3-py311"]
|
|
abi3-py311 = ["abi3-py312"]
|
|
-abi3-py312 = ["abi3"]
|
|
+abi3-py312 = ["abi3-py313"]
|
|
+abi3-py313 = ["abi3-py314"]
|
|
+abi3-py314 = ["abi3"]
|
|
|
|
[package.metadata.docs.rs]
|
|
features = ["resolve-config"]
|
|
diff --git a/include/pyo3/pyo3-build-config/src/errors.rs b/include/pyo3/pyo3-build-config/src/errors.rs
|
|
index 87c59a99..b11d02fd 100644
|
|
--- a/include/pyo3/pyo3-build-config/src/errors.rs
|
|
+++ b/include/pyo3/pyo3-build-config/src/errors.rs
|
|
@@ -68,7 +68,7 @@ impl std::fmt::Display for ErrorReport<'_> {
|
|
writeln!(f, "\ncaused by:")?;
|
|
let mut index = 0;
|
|
while let Some(some_source) = source {
|
|
- writeln!(f, " - {}: {}", index, some_source)?;
|
|
+ writeln!(f, " - {index}: {some_source}")?;
|
|
source = some_source.source();
|
|
index += 1;
|
|
}
|
|
diff --git a/include/pyo3/pyo3-build-config/src/impl_.rs b/include/pyo3/pyo3-build-config/src/impl_.rs
|
|
index 0f90d573..9485b8a0 100644
|
|
--- a/include/pyo3/pyo3-build-config/src/impl_.rs
|
|
+++ b/include/pyo3/pyo3-build-config/src/impl_.rs
|
|
@@ -40,7 +40,7 @@ const MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion {
|
|
};
|
|
|
|
/// Maximum Python version that can be used as minimum required Python version with abi3.
|
|
-pub(crate) const ABI3_MAX_MINOR: u8 = 12;
|
|
+pub(crate) const ABI3_MAX_MINOR: u8 = 13;
|
|
|
|
#[cfg(test)]
|
|
thread_local! {
|
|
@@ -58,7 +58,7 @@ pub fn cargo_env_var(var: &str) -> Option<String> {
|
|
/// the variable changes.
|
|
pub fn env_var(var: &str) -> Option<OsString> {
|
|
if cfg!(feature = "resolve-config") {
|
|
- println!("cargo:rerun-if-env-changed={}", var);
|
|
+ println!("cargo:rerun-if-env-changed={var}");
|
|
}
|
|
#[cfg(test)]
|
|
{
|
|
@@ -180,9 +180,8 @@ impl InterpreterConfig {
|
|
let mut out = vec![];
|
|
|
|
for i in MINIMUM_SUPPORTED_VERSION.minor..=self.version.minor {
|
|
- out.push(format!("cargo:rustc-cfg=Py_3_{}", i));
|
|
+ out.push(format!("cargo:rustc-cfg=Py_3_{i}"));
|
|
}
|
|
- println!("cargo::rustc-check-cfg=cfg(Py_3_14)");
|
|
|
|
match self.implementation {
|
|
PythonImplementation::CPython => {}
|
|
@@ -200,7 +199,7 @@ impl InterpreterConfig {
|
|
BuildFlag::Py_GIL_DISABLED => {
|
|
out.push("cargo:rustc-cfg=Py_GIL_DISABLED".to_owned())
|
|
}
|
|
- flag => out.push(format!("cargo:rustc-cfg=py_sys_config=\"{}\"", flag)),
|
|
+ flag => out.push(format!("cargo:rustc-cfg=py_sys_config=\"{flag}\"")),
|
|
}
|
|
}
|
|
|
|
@@ -339,7 +338,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
|
|
|
|
let lib_dir = if cfg!(windows) {
|
|
map.get("base_prefix")
|
|
- .map(|base_prefix| format!("{}\\libs", base_prefix))
|
|
+ .map(|base_prefix| format!("{base_prefix}\\libs"))
|
|
} else {
|
|
map.get("libdir").cloned()
|
|
};
|
|
@@ -667,7 +666,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
|
|
write_option_line!(python_framework_prefix)?;
|
|
write_line!(suppress_build_script_link_lines)?;
|
|
for line in &self.extra_build_script_lines {
|
|
- writeln!(writer, "extra_build_script_line={}", line)
|
|
+ writeln!(writer, "extra_build_script_line={line}")
|
|
.context("failed to write extra_build_script_line")?;
|
|
}
|
|
Ok(())
|
|
@@ -854,7 +853,7 @@ fn is_abi3() -> bool {
|
|
/// Must be called from a PyO3 crate build script.
|
|
pub fn get_abi3_version() -> Option<PythonVersion> {
|
|
let minor_version = (MINIMUM_SUPPORTED_VERSION.minor..=ABI3_MAX_MINOR)
|
|
- .find(|i| cargo_env_var(&format!("CARGO_FEATURE_ABI3_PY3{}", i)).is_some());
|
|
+ .find(|i| cargo_env_var(&format!("CARGO_FEATURE_ABI3_PY3{i}")).is_some());
|
|
minor_version.map(|minor| PythonVersion { major: 3, minor })
|
|
}
|
|
|
|
@@ -1122,8 +1121,8 @@ pub enum BuildFlag {
|
|
impl Display for BuildFlag {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
- BuildFlag::Other(flag) => write!(f, "{}", flag),
|
|
- _ => write!(f, "{:?}", self),
|
|
+ BuildFlag::Other(flag) => write!(f, "{flag}"),
|
|
+ _ => write!(f, "{self:?}"),
|
|
}
|
|
}
|
|
}
|
|
@@ -1147,7 +1146,7 @@ impl FromStr for BuildFlag {
|
|
/// PyO3 will pick these up and pass to rustc via `--cfg=py_sys_config={varname}`;
|
|
/// this allows using them conditional cfg attributes in the .rs files, so
|
|
///
|
|
-/// ```rust
|
|
+/// ```rust,no_run
|
|
/// #[cfg(py_sys_config="{varname}")]
|
|
/// # struct Foo;
|
|
/// ```
|
|
@@ -1203,7 +1202,7 @@ impl BuildFlags {
|
|
|
|
for k in &BuildFlags::ALL {
|
|
use std::fmt::Write;
|
|
- writeln!(&mut script, "print(config.get('{}', '0'))", k).unwrap();
|
|
+ writeln!(&mut script, "print(config.get('{k}', '0'))").unwrap();
|
|
}
|
|
|
|
let stdout = run_python_script(interpreter.as_ref(), &script)?;
|
|
@@ -1241,7 +1240,7 @@ impl Display for BuildFlags {
|
|
} else {
|
|
write!(f, ",")?;
|
|
}
|
|
- write!(f, "{}", flag)?;
|
|
+ write!(f, "{flag}")?;
|
|
}
|
|
Ok(())
|
|
}
|
|
@@ -1307,6 +1306,10 @@ pub fn parse_sysconfigdata(sysconfigdata_path: impl AsRef<Path>) -> Result<Sysco
|
|
})?;
|
|
script += r#"
|
|
for key, val in build_time_vars.items():
|
|
+ # (ana)conda(-forge) built Pythons are statically linked but ship the shared library with them.
|
|
+ # We detect them based on the magic prefix directory they have encoded in their builds.
|
|
+ if key == "Py_ENABLE_SHARED" and "_h_env_placehold" in build_time_vars.get("prefix"):
|
|
+ val = 1
|
|
print(key, val)
|
|
"#;
|
|
|
|
@@ -1424,7 +1427,7 @@ pub fn find_all_sysconfigdata(cross: &CrossCompileConfig) -> Result<Vec<PathBuf>
|
|
|
|
fn is_pypy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
|
|
let pypy_version_pat = if let Some(v) = v {
|
|
- format!("pypy{}", v)
|
|
+ format!("pypy{v}")
|
|
} else {
|
|
"pypy3.".into()
|
|
};
|
|
@@ -1433,7 +1436,7 @@ fn is_pypy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
|
|
|
|
fn is_graalpy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
|
|
let graalpy_version_pat = if let Some(v) = v {
|
|
- format!("graalpy{}", v)
|
|
+ format!("graalpy{v}")
|
|
} else {
|
|
"graalpy2".into()
|
|
};
|
|
@@ -1442,7 +1445,7 @@ fn is_graalpy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
|
|
|
|
fn is_cpython_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {
|
|
let cpython_version_pat = if let Some(v) = v {
|
|
- format!("python{}", v)
|
|
+ format!("python{v}")
|
|
} else {
|
|
"python3.".into()
|
|
};
|
|
@@ -1756,7 +1759,7 @@ fn default_lib_name_unix(
|
|
) -> Result<String> {
|
|
match implementation {
|
|
PythonImplementation::CPython => match ld_version {
|
|
- Some(ld_version) => Ok(format!("python{}", ld_version)),
|
|
+ Some(ld_version) => Ok(format!("python{ld_version}")),
|
|
None => {
|
|
if version > PythonVersion::PY37 {
|
|
// PEP 3149 ABI version tags are finally gone
|
|
@@ -1773,7 +1776,7 @@ fn default_lib_name_unix(
|
|
}
|
|
},
|
|
PythonImplementation::PyPy => match ld_version {
|
|
- Some(ld_version) => Ok(format!("pypy{}-c", ld_version)),
|
|
+ Some(ld_version) => Ok(format!("pypy{ld_version}-c")),
|
|
None => Ok(format!("pypy{}.{}-c", version.major, version.minor)),
|
|
},
|
|
|
|
@@ -2002,7 +2005,7 @@ fn unescape(escaped: &str) -> Vec<u8> {
|
|
}
|
|
}
|
|
|
|
- bytes.push(unhex(chunk[0]) << 4 | unhex(chunk[1]));
|
|
+ bytes.push((unhex(chunk[0]) << 4) | unhex(chunk[1]));
|
|
}
|
|
|
|
bytes
|
|
diff --git a/include/pyo3/pyo3-build-config/src/lib.rs b/include/pyo3/pyo3-build-config/src/lib.rs
|
|
index 9070f6d7..f47c16f4 100644
|
|
--- a/include/pyo3/pyo3-build-config/src/lib.rs
|
|
+++ b/include/pyo3/pyo3-build-config/src/lib.rs
|
|
@@ -46,7 +46,7 @@ use target_lexicon::OperatingSystem;
|
|
pub fn use_pyo3_cfgs() {
|
|
print_expected_cfgs();
|
|
for cargo_command in get().build_script_outputs() {
|
|
- println!("{}", cargo_command)
|
|
+ println!("{cargo_command}")
|
|
}
|
|
}
|
|
|
|
@@ -102,12 +102,7 @@ fn _add_python_framework_link_args(
|
|
) {
|
|
if matches!(triple.operating_system, OperatingSystem::Darwin(_)) && link_libpython {
|
|
if let Some(framework_prefix) = interpreter_config.python_framework_prefix.as_ref() {
|
|
- writeln!(
|
|
- writer,
|
|
- "cargo:rustc-link-arg=-Wl,-rpath,{}",
|
|
- framework_prefix
|
|
- )
|
|
- .unwrap();
|
|
+ writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{framework_prefix}").unwrap();
|
|
}
|
|
}
|
|
}
|
|
@@ -168,40 +163,36 @@ fn resolve_cross_compile_config_path() -> Option<PathBuf> {
|
|
})
|
|
}
|
|
|
|
+/// Helper to print a feature cfg with a minimum rust version required.
|
|
+fn print_feature_cfg(minor_version_required: u32, cfg: &str) {
|
|
+ let minor_version = rustc_minor_version().unwrap_or(0);
|
|
+
|
|
+ if minor_version >= minor_version_required {
|
|
+ println!("cargo:rustc-cfg={cfg}");
|
|
+ }
|
|
+
|
|
+ // rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before
|
|
+ if minor_version >= 80 {
|
|
+ println!("cargo:rustc-check-cfg=cfg({cfg})");
|
|
+ }
|
|
+}
|
|
+
|
|
/// Use certain features if we detect the compiler being used supports them.
|
|
///
|
|
/// Features may be removed or added as MSRV gets bumped or new features become available,
|
|
/// so this function is unstable.
|
|
#[doc(hidden)]
|
|
pub fn print_feature_cfgs() {
|
|
- let rustc_minor_version = rustc_minor_version().unwrap_or(0);
|
|
-
|
|
- if rustc_minor_version >= 70 {
|
|
- println!("cargo:rustc-cfg=rustc_has_once_lock");
|
|
- }
|
|
-
|
|
- // invalid_from_utf8 lint was added in Rust 1.74
|
|
- if rustc_minor_version >= 74 {
|
|
- println!("cargo:rustc-cfg=invalid_from_utf8_lint");
|
|
- }
|
|
-
|
|
- if rustc_minor_version >= 79 {
|
|
- println!("cargo:rustc-cfg=c_str_lit");
|
|
- }
|
|
-
|
|
+ print_feature_cfg(70, "rustc_has_once_lock");
|
|
+ print_feature_cfg(70, "cargo_toml_lints");
|
|
+ print_feature_cfg(71, "rustc_has_extern_c_unwind");
|
|
+ print_feature_cfg(74, "invalid_from_utf8_lint");
|
|
+ print_feature_cfg(79, "c_str_lit");
|
|
// Actually this is available on 1.78, but we should avoid
|
|
// https://github.com/rust-lang/rust/issues/124651 just in case
|
|
- if rustc_minor_version >= 79 {
|
|
- println!("cargo:rustc-cfg=diagnostic_namespace");
|
|
- }
|
|
-
|
|
- if rustc_minor_version >= 83 {
|
|
- println!("cargo:rustc-cfg=io_error_more");
|
|
- }
|
|
-
|
|
- if rustc_minor_version >= 85 {
|
|
- println!("cargo:rustc-cfg=fn_ptr_eq");
|
|
- }
|
|
+ print_feature_cfg(79, "diagnostic_namespace");
|
|
+ print_feature_cfg(83, "io_error_more");
|
|
+ print_feature_cfg(85, "fn_ptr_eq");
|
|
}
|
|
|
|
/// Registers `pyo3`s config names as reachable cfg expressions
|
|
@@ -220,14 +211,8 @@ pub fn print_expected_cfgs() {
|
|
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)");
|
|
println!("cargo:rustc-check-cfg=cfg(pyo3_disable_reference_pool)");
|
|
println!("cargo:rustc-check-cfg=cfg(pyo3_leak_on_drop_without_reference_pool)");
|
|
- 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)");
|
|
- println!("cargo:rustc-check-cfg=cfg(fn_ptr_eq)");
|
|
|
|
// allow `Py_3_*` cfgs from the minimum supported version up to the
|
|
// maximum minor version (+1 for development for the next)
|
|
diff --git a/include/pyo3/pyo3-ffi/ACKNOWLEDGEMENTS b/include/pyo3/pyo3-ffi/ACKNOWLEDGEMENTS
|
|
index 4502d777..8b20727d 100644
|
|
--- a/include/pyo3/pyo3-ffi/ACKNOWLEDGEMENTS
|
|
+++ b/include/pyo3/pyo3-ffi/ACKNOWLEDGEMENTS
|
|
@@ -3,4 +3,4 @@ for binary compatibility, with additional metadata to support PyPy.
|
|
|
|
For original implementations please see:
|
|
- https://github.com/python/cpython
|
|
- - https://foss.heptapod.net/pypy/pypy
|
|
+ - https://github.com/pypy/pypy
|
|
diff --git a/include/pyo3/pyo3-ffi/Cargo.toml b/include/pyo3/pyo3-ffi/Cargo.toml
|
|
index 14a4f958..73ea84ab 100644
|
|
--- a/include/pyo3/pyo3-ffi/Cargo.toml
|
|
+++ b/include/pyo3/pyo3-ffi/Cargo.toml
|
|
@@ -1,6 +1,6 @@
|
|
[package]
|
|
name = "pyo3-ffi"
|
|
-version = "0.23.3"
|
|
+version = "0.25.0"
|
|
description = "Python-API bindings for the PyO3 ecosystem"
|
|
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
|
keywords = ["pyo3", "python", "cpython", "ffi"]
|
|
@@ -12,7 +12,7 @@ edition = "2021"
|
|
links = "python"
|
|
|
|
[dependencies]
|
|
-libc = "0.2"
|
|
+libc = "0.2.62"
|
|
|
|
[features]
|
|
|
|
@@ -32,7 +32,9 @@ abi3-py38 = ["abi3-py39", "pyo3-build-config/abi3-py38"]
|
|
abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39"]
|
|
abi3-py310 = ["abi3-py311", "pyo3-build-config/abi3-py310"]
|
|
abi3-py311 = ["abi3-py312", "pyo3-build-config/abi3-py311"]
|
|
-abi3-py312 = ["abi3", "pyo3-build-config/abi3-py312"]
|
|
+abi3-py312 = ["abi3-py313", "pyo3-build-config/abi3-py312"]
|
|
+abi3-py313 = ["abi3-py314", "pyo3-build-config/abi3-py313"]
|
|
+abi3-py314 = ["abi3", "pyo3-build-config/abi3-py314"]
|
|
|
|
# Automatically generates `python3.dll` import libraries for Windows targets.
|
|
generate-import-lib = ["pyo3-build-config/python3-dll-a"]
|
|
@@ -41,4 +43,4 @@ generate-import-lib = ["pyo3-build-config/python3-dll-a"]
|
|
paste = "1"
|
|
|
|
[build-dependencies]
|
|
-pyo3-build-config = { path = "../pyo3-build-config", features = ["resolve-config"] }
|
|
+pyo3-build-config = { path = "../pyo3-build-config", version = "=0.25.0", features = ["resolve-config"] }
|
|
diff --git a/include/pyo3/pyo3-ffi/build.rs b/include/pyo3/pyo3-ffi/build.rs
|
|
index b0f1c28d..6776cd80 100644
|
|
--- a/include/pyo3/pyo3-ffi/build.rs
|
|
+++ b/include/pyo3/pyo3-ffi/build.rs
|
|
@@ -4,9 +4,8 @@ use pyo3_build_config::{
|
|
cargo_env_var, env_var, errors::Result, is_linking_libpython, resolve_interpreter_config,
|
|
InterpreterConfig, PythonVersion,
|
|
},
|
|
- warn, BuildFlag, PythonImplementation,
|
|
+ warn, PythonImplementation,
|
|
};
|
|
-use std::ops::Not;
|
|
|
|
/// Minimum Python version PyO3 supports.
|
|
struct SupportedVersions {
|
|
@@ -18,15 +17,15 @@ const SUPPORTED_VERSIONS_CPYTHON: SupportedVersions = SupportedVersions {
|
|
min: PythonVersion { major: 3, minor: 7 },
|
|
max: PythonVersion {
|
|
major: 3,
|
|
- minor: 13,
|
|
+ minor: 14,
|
|
},
|
|
};
|
|
|
|
const SUPPORTED_VERSIONS_PYPY: SupportedVersions = SupportedVersions {
|
|
- min: PythonVersion { major: 3, minor: 7 },
|
|
+ min: PythonVersion { major: 3, minor: 9 },
|
|
max: PythonVersion {
|
|
major: 3,
|
|
- minor: 10,
|
|
+ minor: 11,
|
|
},
|
|
};
|
|
|
|
@@ -57,15 +56,22 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
interpreter_config.version,
|
|
versions.min,
|
|
);
|
|
- ensure!(
|
|
- interpreter_config.version <= versions.max || env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1"),
|
|
- "the configured Python interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\
|
|
- = help: please check if an updated version of PyO3 is available. Current version: {}\n\
|
|
- = help: set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 to suppress this check and build anyway using the stable ABI",
|
|
- interpreter_config.version,
|
|
- versions.max,
|
|
- std::env::var("CARGO_PKG_VERSION").unwrap(),
|
|
- );
|
|
+ if interpreter_config.version > versions.max {
|
|
+ ensure!(!interpreter_config.is_free_threaded(),
|
|
+ "The configured Python interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\
|
|
+ = help: please check if an updated version of PyO3 is available. Current version: {}\n\
|
|
+ = help: The free-threaded build of CPython does not support the limited API so this check cannot be suppressed.",
|
|
+ interpreter_config.version, versions.max, std::env::var("CARGO_PKG_VERSION").unwrap()
|
|
+ );
|
|
+ ensure!(env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1"),
|
|
+ "the configured Python interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\
|
|
+ = help: please check if an updated version of PyO3 is available. Current version: {}\n\
|
|
+ = help: set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 to suppress this check and build anyway using the stable ABI",
|
|
+ interpreter_config.version,
|
|
+ versions.max,
|
|
+ std::env::var("CARGO_PKG_VERSION").unwrap(),
|
|
+ );
|
|
+ }
|
|
}
|
|
PythonImplementation::PyPy => {
|
|
let versions = SUPPORTED_VERSIONS_PYPY;
|
|
@@ -107,10 +113,16 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
|
|
if interpreter_config.abi3 {
|
|
match interpreter_config.implementation {
|
|
- PythonImplementation::CPython => {}
|
|
+ PythonImplementation::CPython => {
|
|
+ if interpreter_config.is_free_threaded() {
|
|
+ warn!(
|
|
+ "The free-threaded build of CPython does not yet support abi3 so the build artifacts will be version-specific."
|
|
+ )
|
|
+ }
|
|
+ }
|
|
PythonImplementation::PyPy => warn!(
|
|
"PyPy does not yet support abi3 so the build artifacts will be version-specific. \
|
|
- See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information."
|
|
+ See https://github.com/pypy/pypy/issues/3397 for more information."
|
|
),
|
|
PythonImplementation::GraalPy => warn!(
|
|
"GraalPy does not support abi3 so the build artifacts will be version-specific."
|
|
@@ -121,29 +133,6 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
-fn ensure_gil_enabled(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
- let gil_enabled = interpreter_config
|
|
- .build_flags
|
|
- .0
|
|
- .contains(&BuildFlag::Py_GIL_DISABLED)
|
|
- .not();
|
|
- ensure!(
|
|
- gil_enabled || std::env::var("UNSAFE_PYO3_BUILD_FREE_THREADED").map_or(false, |os_str| os_str == "1"),
|
|
- "the Python interpreter was built with the GIL disabled, which is not yet supported by PyO3\n\
|
|
- = help: see https://github.com/PyO3/pyo3/issues/4265 for more information\n\
|
|
- = help: please check if an updated version of PyO3 is available. Current version: {}\n\
|
|
- = help: set UNSAFE_PYO3_BUILD_FREE_THREADED=1 to suppress this check and build anyway for free-threaded Python",
|
|
- std::env::var("CARGO_PKG_VERSION").unwrap()
|
|
- );
|
|
- if !gil_enabled && interpreter_config.abi3 {
|
|
- warn!(
|
|
- "The free-threaded build of CPython does not yet support abi3 so the build artifacts will be version-specific."
|
|
- )
|
|
- }
|
|
-
|
|
- Ok(())
|
|
-}
|
|
-
|
|
fn ensure_target_pointer_width(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
if let Some(pointer_width) = interpreter_config.pointer_width {
|
|
// Try to check whether the target architecture matches the python library
|
|
@@ -187,7 +176,7 @@ fn emit_link_config(interpreter_config: &InterpreterConfig) -> Result<()> {
|
|
);
|
|
|
|
if let Some(lib_dir) = &interpreter_config.lib_dir {
|
|
- println!("cargo:rustc-link-search=native={}", lib_dir);
|
|
+ println!("cargo:rustc-link-search=native={lib_dir}");
|
|
}
|
|
|
|
Ok(())
|
|
@@ -209,7 +198,6 @@ fn configure_pyo3() -> Result<()> {
|
|
|
|
ensure_python_version(&interpreter_config)?;
|
|
ensure_target_pointer_width(&interpreter_config)?;
|
|
- ensure_gil_enabled(&interpreter_config)?;
|
|
|
|
// Serialize the whole interpreter config into DEP_PYTHON_PYO3_CONFIG env var.
|
|
interpreter_config.to_cargo_dep_env()?;
|
|
@@ -219,12 +207,12 @@ fn configure_pyo3() -> Result<()> {
|
|
}
|
|
|
|
for cfg in interpreter_config.build_script_outputs() {
|
|
- println!("{}", cfg)
|
|
+ println!("{cfg}")
|
|
}
|
|
|
|
// Extra lines come last, to support last write wins.
|
|
for line in &interpreter_config.extra_build_script_lines {
|
|
- println!("{}", line);
|
|
+ println!("{line}");
|
|
}
|
|
|
|
// Emit cfgs like `invalid_from_utf8_lint`
|
|
diff --git a/include/pyo3/pyo3-ffi/src/abstract_.rs b/include/pyo3/pyo3-ffi/src/abstract_.rs
|
|
index ce6c9b94..84fb98a1 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/abstract_.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/abstract_.rs
|
|
@@ -1,15 +1,23 @@
|
|
use crate::object::*;
|
|
use crate::pyport::Py_ssize_t;
|
|
+#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]
|
|
+use libc::size_t;
|
|
use std::os::raw::{c_char, c_int};
|
|
|
|
#[inline]
|
|
-#[cfg(all(not(Py_3_13), not(PyPy)))] // CPython exposed as a function in 3.13, in object.h
|
|
+#[cfg(all(
|
|
+ not(Py_3_13), // CPython exposed as a function in 3.13, in object.h
|
|
+ not(all(PyPy, not(Py_3_11))) // PyPy exposed as a function until PyPy 3.10, macro in 3.11+
|
|
+))]
|
|
pub unsafe fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int {
|
|
PyObject_SetAttrString(o, attr_name, std::ptr::null_mut())
|
|
}
|
|
|
|
#[inline]
|
|
-#[cfg(all(not(Py_3_13), not(PyPy)))] // CPython exposed as a function in 3.13, in object.h
|
|
+#[cfg(all(
|
|
+ not(Py_3_13), // CPython exposed as a function in 3.13, in object.h
|
|
+ not(all(PyPy, not(Py_3_11))) // PyPy exposed as a function until PyPy 3.10, macro in 3.11+
|
|
+))]
|
|
pub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_int {
|
|
PyObject_SetAttr(o, attr_name, std::ptr::null_mut())
|
|
}
|
|
@@ -17,6 +25,7 @@ pub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_
|
|
extern "C" {
|
|
#[cfg(all(
|
|
not(PyPy),
|
|
+ not(GraalPy),
|
|
any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10
|
|
))]
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_CallNoArgs")]
|
|
@@ -70,6 +79,28 @@ extern "C" {
|
|
method: *mut PyObject,
|
|
...
|
|
) -> *mut PyObject;
|
|
+}
|
|
+#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]
|
|
+pub const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
|
|
+ 1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);
|
|
+
|
|
+extern "C" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyObject_Vectorcall")]
|
|
+ #[cfg(any(Py_3_12, all(Py_3_11, not(Py_LIMITED_API))))]
|
|
+ pub fn PyObject_Vectorcall(
|
|
+ callable: *mut PyObject,
|
|
+ args: *const *mut PyObject,
|
|
+ nargsf: size_t,
|
|
+ kwnames: *mut PyObject,
|
|
+ ) -> *mut PyObject;
|
|
+
|
|
+ #[cfg(any(Py_3_12, all(Py_3_9, not(any(Py_LIMITED_API, PyPy, GraalPy)))))]
|
|
+ pub fn PyObject_VectorcallMethod(
|
|
+ name: *mut PyObject,
|
|
+ args: *const *mut PyObject,
|
|
+ nargsf: size_t,
|
|
+ kwnames: *mut PyObject,
|
|
+ ) -> *mut PyObject;
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_Type")]
|
|
pub fn PyObject_Type(o: *mut PyObject) -> *mut PyObject;
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_Size")]
|
|
@@ -119,7 +150,11 @@ extern "C" {
|
|
pub fn PyIter_Next(arg1: *mut PyObject) -> *mut PyObject;
|
|
#[cfg(all(not(PyPy), Py_3_10))]
|
|
#[cfg_attr(PyPy, link_name = "PyPyIter_Send")]
|
|
- pub fn PyIter_Send(iter: *mut PyObject, arg: *mut PyObject, presult: *mut *mut PyObject);
|
|
+ pub fn PyIter_Send(
|
|
+ iter: *mut PyObject,
|
|
+ arg: *mut PyObject,
|
|
+ presult: *mut *mut PyObject,
|
|
+ ) -> PySendResult;
|
|
|
|
#[cfg_attr(PyPy, link_name = "PyPyNumber_Check")]
|
|
pub fn PyNumber_Check(o: *mut PyObject) -> c_int;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/bytearrayobject.rs b/include/pyo3/pyo3-ffi/src/bytearrayobject.rs
|
|
index 24a97bcc..d27dfa8b 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/bytearrayobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/bytearrayobject.rs
|
|
@@ -17,7 +17,7 @@ pub struct PyByteArrayObject {
|
|
}
|
|
|
|
#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]
|
|
-opaque_struct!(PyByteArrayObject);
|
|
+opaque_struct!(pub PyByteArrayObject);
|
|
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
diff --git a/include/pyo3/pyo3-ffi/src/code.rs b/include/pyo3/pyo3-ffi/src/code.rs
|
|
index d28f68cd..296b17f6 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/code.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/code.rs
|
|
@@ -1,4 +1,4 @@
|
|
// This header doesn't exist in CPython, but Include/cpython/code.h does. We add
|
|
// this here so that PyCodeObject has a definition under the limited API.
|
|
|
|
-opaque_struct!(PyCodeObject);
|
|
+opaque_struct!(pub PyCodeObject);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/compat/mod.rs b/include/pyo3/pyo3-ffi/src/compat/mod.rs
|
|
index 11f29128..044ea467 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/compat/mod.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/compat/mod.rs
|
|
@@ -52,8 +52,10 @@ macro_rules! compat_function {
|
|
|
|
mod py_3_10;
|
|
mod py_3_13;
|
|
+mod py_3_14;
|
|
mod py_3_9;
|
|
|
|
pub use self::py_3_10::*;
|
|
pub use self::py_3_13::*;
|
|
+pub use self::py_3_14::*;
|
|
pub use self::py_3_9::*;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/compat/py_3_10.rs b/include/pyo3/pyo3-ffi/src/compat/py_3_10.rs
|
|
index c6e8c2cb..d962fb3b 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/compat/py_3_10.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/compat/py_3_10.rs
|
|
@@ -17,3 +17,29 @@ compat_function!(
|
|
obj
|
|
}
|
|
);
|
|
+
|
|
+compat_function!(
|
|
+ originally_defined_for(Py_3_10);
|
|
+
|
|
+ #[inline]
|
|
+ pub unsafe fn PyModule_AddObjectRef(
|
|
+ module: *mut crate::PyObject,
|
|
+ name: *const std::os::raw::c_char,
|
|
+ value: *mut crate::PyObject,
|
|
+ ) -> std::os::raw::c_int {
|
|
+ if value.is_null() && crate::PyErr_Occurred().is_null() {
|
|
+ crate::PyErr_SetString(
|
|
+ crate::PyExc_SystemError,
|
|
+ c_str!("PyModule_AddObjectRef() must be called with an exception raised if value is NULL").as_ptr(),
|
|
+ );
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ crate::Py_XINCREF(value);
|
|
+ let result = crate::PyModule_AddObject(module, name, value);
|
|
+ if result < 0 {
|
|
+ crate::Py_XDECREF(value);
|
|
+ }
|
|
+ result
|
|
+ }
|
|
+);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/compat/py_3_13.rs b/include/pyo3/pyo3-ffi/src/compat/py_3_13.rs
|
|
index 59289cb7..96c90e7e 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/compat/py_3_13.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/compat/py_3_13.rs
|
|
@@ -104,3 +104,18 @@ compat_function!(
|
|
crate::PyList_SetSlice(list, 0, crate::PY_SSIZE_T_MAX, std::ptr::null_mut())
|
|
}
|
|
);
|
|
+
|
|
+compat_function!(
|
|
+ originally_defined_for(Py_3_13);
|
|
+
|
|
+ #[inline]
|
|
+ pub unsafe fn PyModule_Add(
|
|
+ module: *mut crate::PyObject,
|
|
+ name: *const std::os::raw::c_char,
|
|
+ value: *mut crate::PyObject,
|
|
+ ) -> std::os::raw::c_int {
|
|
+ let result = crate::compat::PyModule_AddObjectRef(module, name, value);
|
|
+ crate::Py_XDECREF(value);
|
|
+ result
|
|
+ }
|
|
+);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/compat/py_3_14.rs b/include/pyo3/pyo3-ffi/src/compat/py_3_14.rs
|
|
new file mode 100644
|
|
index 00000000..6fdaef17
|
|
--- /dev/null
|
|
+++ b/include/pyo3/pyo3-ffi/src/compat/py_3_14.rs
|
|
@@ -0,0 +1,26 @@
|
|
+compat_function!(
|
|
+ originally_defined_for(all(Py_3_14, not(Py_LIMITED_API)));
|
|
+
|
|
+ #[inline]
|
|
+ pub unsafe fn Py_HashBuffer(
|
|
+ ptr: *const std::ffi::c_void,
|
|
+ len: crate::Py_ssize_t,
|
|
+ ) -> crate::Py_hash_t {
|
|
+ #[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
|
+ {
|
|
+ crate::_Py_HashBytes(ptr, len)
|
|
+ }
|
|
+
|
|
+ #[cfg(any(Py_LIMITED_API, PyPy))]
|
|
+ {
|
|
+ let bytes = crate::PyBytes_FromStringAndSize(ptr as *const std::os::raw::c_char, len);
|
|
+ if bytes.is_null() {
|
|
+ -1
|
|
+ } else {
|
|
+ let result = crate::PyObject_Hash(bytes);
|
|
+ crate::Py_DECREF(bytes);
|
|
+ result
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/abstract_.rs b/include/pyo3/pyo3-ffi/src/cpython/abstract_.rs
|
|
index 477ad02b..6ada1a75 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/abstract_.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/abstract_.rs
|
|
@@ -1,5 +1,5 @@
|
|
use crate::{PyObject, Py_ssize_t};
|
|
-#[cfg(not(all(Py_3_11, GraalPy)))]
|
|
+#[cfg(any(all(Py_3_8, not(any(PyPy, GraalPy))), not(Py_3_11)))]
|
|
use std::os::raw::c_char;
|
|
use std::os::raw::c_int;
|
|
|
|
@@ -41,8 +41,8 @@ extern "C" {
|
|
) -> *mut PyObject;
|
|
}
|
|
|
|
-#[cfg(Py_3_8)]
|
|
-pub const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
|
|
+#[cfg(Py_3_8)] // NB exported as public in abstract.rs from 3.12
|
|
+const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
|
|
1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);
|
|
|
|
#[cfg(Py_3_8)]
|
|
@@ -91,7 +91,7 @@ pub unsafe fn _PyObject_VectorcallTstate(
|
|
}
|
|
}
|
|
|
|
-#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
|
|
+#[cfg(all(Py_3_8, not(any(PyPy, GraalPy, Py_3_11))))] // exported as a function from 3.11, see abstract.rs
|
|
#[inline(always)]
|
|
pub unsafe fn PyObject_Vectorcall(
|
|
callable: *mut PyObject,
|
|
@@ -103,16 +103,6 @@ pub unsafe fn PyObject_Vectorcall(
|
|
}
|
|
|
|
extern "C" {
|
|
- #[cfg(all(PyPy, Py_3_8))]
|
|
- #[cfg_attr(not(Py_3_9), link_name = "_PyPyObject_Vectorcall")]
|
|
- #[cfg_attr(Py_3_9, link_name = "PyPyObject_Vectorcall")]
|
|
- pub fn PyObject_Vectorcall(
|
|
- callable: *mut PyObject,
|
|
- args: *const *mut PyObject,
|
|
- nargsf: size_t,
|
|
- kwnames: *mut PyObject,
|
|
- ) -> *mut PyObject;
|
|
-
|
|
#[cfg(Py_3_8)]
|
|
#[cfg_attr(
|
|
all(not(any(PyPy, GraalPy)), not(Py_3_9)),
|
|
@@ -187,23 +177,13 @@ pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *m
|
|
_PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())
|
|
}
|
|
|
|
-extern "C" {
|
|
- #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
|
|
- pub fn PyObject_VectorcallMethod(
|
|
- name: *mut PyObject,
|
|
- args: *const *mut PyObject,
|
|
- nargsf: size_t,
|
|
- kwnames: *mut PyObject,
|
|
- ) -> *mut PyObject;
|
|
-}
|
|
-
|
|
#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
|
|
#[inline(always)]
|
|
pub unsafe fn PyObject_CallMethodNoArgs(
|
|
self_: *mut PyObject,
|
|
name: *mut PyObject,
|
|
) -> *mut PyObject {
|
|
- PyObject_VectorcallMethod(
|
|
+ crate::PyObject_VectorcallMethod(
|
|
name,
|
|
&self_,
|
|
1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
|
|
@@ -220,7 +200,7 @@ pub unsafe fn PyObject_CallMethodOneArg(
|
|
) -> *mut PyObject {
|
|
let args = [self_, arg];
|
|
assert!(!arg.is_null());
|
|
- PyObject_VectorcallMethod(
|
|
+ crate::PyObject_VectorcallMethod(
|
|
name,
|
|
args.as_ptr(),
|
|
2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/bytesobject.rs b/include/pyo3/pyo3-ffi/src/cpython/bytesobject.rs
|
|
index 306702de..dd78e646 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/bytesobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/bytesobject.rs
|
|
@@ -17,7 +17,7 @@ pub struct PyBytesObject {
|
|
}
|
|
|
|
#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]
|
|
-opaque_struct!(PyBytesObject);
|
|
+opaque_struct!(pub PyBytesObject);
|
|
|
|
extern "C" {
|
|
#[cfg_attr(PyPy, link_name = "_PyPyBytes_Resize")]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/code.rs b/include/pyo3/pyo3-ffi/src/cpython/code.rs
|
|
index 230096ca..3d47a1bc 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/code.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/code.rs
|
|
@@ -1,207 +1,43 @@
|
|
use crate::object::*;
|
|
use crate::pyport::Py_ssize_t;
|
|
|
|
-#[allow(unused_imports)]
|
|
-use std::os::raw::{c_char, c_int, c_short, c_uchar, c_void};
|
|
+#[cfg(not(GraalPy))]
|
|
+use std::os::raw::c_char;
|
|
+use std::os::raw::{c_int, c_void};
|
|
#[cfg(not(any(PyPy, GraalPy)))]
|
|
use std::ptr::addr_of_mut;
|
|
|
|
-#[cfg(all(Py_3_8, not(any(PyPy, GraalPy)), not(Py_3_11)))]
|
|
-opaque_struct!(_PyOpcache);
|
|
+// skipped private _PY_MONITORING_LOCAL_EVENTS
|
|
+// skipped private _PY_MONITORING_UNGROUPED_EVENTS
|
|
+// skipped private _PY_MONITORING_EVENTS
|
|
|
|
-#[cfg(Py_3_12)]
|
|
-pub const _PY_MONITORING_LOCAL_EVENTS: usize = 10;
|
|
-#[cfg(Py_3_12)]
|
|
-pub const _PY_MONITORING_UNGROUPED_EVENTS: usize = 15;
|
|
-#[cfg(Py_3_12)]
|
|
-pub const _PY_MONITORING_EVENTS: usize = 17;
|
|
+// skipped private _PyLocalMonitors
|
|
+// skipped private _Py_GlobalMonitors
|
|
|
|
-#[cfg(Py_3_12)]
|
|
-#[repr(C)]
|
|
-#[derive(Clone, Copy)]
|
|
-pub struct _Py_LocalMonitors {
|
|
- pub tools: [u8; if cfg!(Py_3_13) {
|
|
- _PY_MONITORING_LOCAL_EVENTS
|
|
- } else {
|
|
- _PY_MONITORING_UNGROUPED_EVENTS
|
|
- }],
|
|
-}
|
|
-
|
|
-#[cfg(Py_3_12)]
|
|
-#[repr(C)]
|
|
-#[derive(Clone, Copy)]
|
|
-pub struct _Py_GlobalMonitors {
|
|
- pub tools: [u8; _PY_MONITORING_UNGROUPED_EVENTS],
|
|
-}
|
|
-
|
|
-// skipped _Py_CODEUNIT
|
|
+// skipped private _Py_CODEUNIT
|
|
|
|
-// skipped _Py_OPCODE
|
|
-// skipped _Py_OPARG
|
|
+// skipped private _Py_OPCODE
|
|
+// skipped private _Py_OPARG
|
|
|
|
-// skipped _py_make_codeunit
|
|
+// skipped private _py_make_codeunit
|
|
|
|
-// skipped _py_set_opcode
|
|
+// skipped private _py_set_opcode
|
|
|
|
-// skipped _Py_MAKE_CODEUNIT
|
|
-// skipped _Py_SET_OPCODE
|
|
-
|
|
-#[cfg(Py_3_12)]
|
|
-#[repr(C)]
|
|
-#[derive(Copy, Clone)]
|
|
-pub struct _PyCoCached {
|
|
- pub _co_code: *mut PyObject,
|
|
- pub _co_varnames: *mut PyObject,
|
|
- pub _co_cellvars: *mut PyObject,
|
|
- pub _co_freevars: *mut PyObject,
|
|
-}
|
|
-
|
|
-#[cfg(Py_3_12)]
|
|
-#[repr(C)]
|
|
-#[derive(Copy, Clone)]
|
|
-pub struct _PyCoLineInstrumentationData {
|
|
- pub original_opcode: u8,
|
|
- pub line_delta: i8,
|
|
-}
|
|
+// skipped private _Py_MAKE_CODEUNIT
|
|
+// skipped private _Py_SET_OPCODE
|
|
|
|
-#[cfg(Py_3_12)]
|
|
-#[repr(C)]
|
|
-#[derive(Copy, Clone)]
|
|
-pub struct _PyCoMonitoringData {
|
|
- pub local_monitors: _Py_LocalMonitors,
|
|
- pub active_monitors: _Py_LocalMonitors,
|
|
- pub tools: *mut u8,
|
|
- pub lines: *mut _PyCoLineInstrumentationData,
|
|
- pub line_tools: *mut u8,
|
|
- pub per_instruction_opcodes: *mut u8,
|
|
- pub per_instruction_tools: *mut u8,
|
|
-}
|
|
-
|
|
-#[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_7)))]
|
|
-opaque_struct!(PyCodeObject);
|
|
-
|
|
-#[cfg(all(not(any(PyPy, GraalPy)), Py_3_7, not(Py_3_8)))]
|
|
-#[repr(C)]
|
|
-pub struct PyCodeObject {
|
|
- pub ob_base: PyObject,
|
|
- pub co_argcount: c_int,
|
|
- pub co_kwonlyargcount: c_int,
|
|
- pub co_nlocals: c_int,
|
|
- pub co_stacksize: c_int,
|
|
- pub co_flags: c_int,
|
|
- pub co_firstlineno: c_int,
|
|
- pub co_code: *mut PyObject,
|
|
- pub co_consts: *mut PyObject,
|
|
- pub co_names: *mut PyObject,
|
|
- pub co_varnames: *mut PyObject,
|
|
- pub co_freevars: *mut PyObject,
|
|
- pub co_cellvars: *mut PyObject,
|
|
- pub co_cell2arg: *mut Py_ssize_t,
|
|
- pub co_filename: *mut PyObject,
|
|
- pub co_name: *mut PyObject,
|
|
- pub co_lnotab: *mut PyObject,
|
|
- pub co_zombieframe: *mut c_void,
|
|
- pub co_weakreflist: *mut PyObject,
|
|
- pub co_extra: *mut c_void,
|
|
-}
|
|
-
|
|
-#[cfg(Py_3_13)]
|
|
-opaque_struct!(_PyExecutorArray);
|
|
-
|
|
-#[cfg(all(not(any(PyPy, GraalPy)), Py_3_8, not(Py_3_11)))]
|
|
-#[repr(C)]
|
|
-pub struct PyCodeObject {
|
|
- pub ob_base: PyObject,
|
|
- pub co_argcount: c_int,
|
|
- pub co_posonlyargcount: c_int,
|
|
- pub co_kwonlyargcount: c_int,
|
|
- pub co_nlocals: c_int,
|
|
- pub co_stacksize: c_int,
|
|
- pub co_flags: c_int,
|
|
- pub co_firstlineno: c_int,
|
|
- pub co_code: *mut PyObject,
|
|
- pub co_consts: *mut PyObject,
|
|
- pub co_names: *mut PyObject,
|
|
- pub co_varnames: *mut PyObject,
|
|
- pub co_freevars: *mut PyObject,
|
|
- pub co_cellvars: *mut PyObject,
|
|
- pub co_cell2arg: *mut Py_ssize_t,
|
|
- pub co_filename: *mut PyObject,
|
|
- pub co_name: *mut PyObject,
|
|
- #[cfg(not(Py_3_10))]
|
|
- pub co_lnotab: *mut PyObject,
|
|
- #[cfg(Py_3_10)]
|
|
- pub co_linetable: *mut PyObject,
|
|
- pub co_zombieframe: *mut c_void,
|
|
- pub co_weakreflist: *mut PyObject,
|
|
- pub co_extra: *mut c_void,
|
|
- pub co_opcache_map: *mut c_uchar,
|
|
- pub co_opcache: *mut _PyOpcache,
|
|
- pub co_opcache_flag: c_int,
|
|
- pub co_opcache_size: c_uchar,
|
|
-}
|
|
+// skipped private _PyCoCached
|
|
+// skipped private _PyCoLineInstrumentationData
|
|
+// skipped private _PyCoMontoringData
|
|
|
|
-#[cfg(all(not(any(PyPy, GraalPy)), Py_3_11))]
|
|
-#[repr(C)]
|
|
-pub struct PyCodeObject {
|
|
- pub ob_base: PyVarObject,
|
|
- pub co_consts: *mut PyObject,
|
|
- pub co_names: *mut PyObject,
|
|
- pub co_exceptiontable: *mut PyObject,
|
|
- pub co_flags: c_int,
|
|
- #[cfg(not(Py_3_12))]
|
|
- pub co_warmup: c_int,
|
|
+// skipped private _PyExecutorArray
|
|
|
|
- pub co_argcount: c_int,
|
|
- pub co_posonlyargcount: c_int,
|
|
- pub co_kwonlyargcount: c_int,
|
|
- pub co_stacksize: c_int,
|
|
- pub co_firstlineno: c_int,
|
|
-
|
|
- pub co_nlocalsplus: c_int,
|
|
- #[cfg(Py_3_12)]
|
|
- pub co_framesize: c_int,
|
|
- pub co_nlocals: c_int,
|
|
- #[cfg(not(Py_3_12))]
|
|
- pub co_nplaincellvars: c_int,
|
|
- pub co_ncellvars: c_int,
|
|
- pub co_nfreevars: c_int,
|
|
- #[cfg(Py_3_12)]
|
|
- pub co_version: u32,
|
|
-
|
|
- pub co_localsplusnames: *mut PyObject,
|
|
- pub co_localspluskinds: *mut PyObject,
|
|
- pub co_filename: *mut PyObject,
|
|
- pub co_name: *mut PyObject,
|
|
- pub co_qualname: *mut PyObject,
|
|
- pub co_linetable: *mut PyObject,
|
|
- pub co_weakreflist: *mut PyObject,
|
|
- #[cfg(not(Py_3_12))]
|
|
- pub _co_code: *mut PyObject,
|
|
- #[cfg(not(Py_3_12))]
|
|
- pub _co_linearray: *mut c_char,
|
|
- #[cfg(Py_3_13)]
|
|
- pub co_executors: *mut _PyExecutorArray,
|
|
- #[cfg(Py_3_12)]
|
|
- pub _co_cached: *mut _PyCoCached,
|
|
- #[cfg(Py_3_12)]
|
|
- pub _co_instrumentation_version: u64,
|
|
- #[cfg(Py_3_12)]
|
|
- pub _co_monitoring: *mut _PyCoMonitoringData,
|
|
- pub _co_firsttraceable: c_int,
|
|
- pub co_extra: *mut c_void,
|
|
- pub co_code_adaptive: [c_char; 1],
|
|
-}
|
|
-
|
|
-#[cfg(PyPy)]
|
|
-#[repr(C)]
|
|
-pub struct PyCodeObject {
|
|
- pub ob_base: PyObject,
|
|
- pub co_name: *mut PyObject,
|
|
- pub co_filename: *mut PyObject,
|
|
- pub co_argcount: c_int,
|
|
- pub co_flags: c_int,
|
|
-}
|
|
+opaque_struct!(
|
|
+ #[doc = "A Python code object.\n"]
|
|
+ #[doc = "\n"]
|
|
+ #[doc = "`pyo3-ffi` does not expose the contents of this struct, as it has no stability guarantees."]
|
|
+ pub PyCodeObject
|
|
+);
|
|
|
|
/* Masks for co_flags */
|
|
pub const CO_OPTIMIZED: c_int = 0x0001;
|
|
@@ -247,28 +83,14 @@ pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {
|
|
(Py_TYPE(op) == addr_of_mut!(PyCode_Type)) as c_int
|
|
}
|
|
|
|
-#[inline]
|
|
-#[cfg(all(not(any(PyPy, GraalPy)), Py_3_10, not(Py_3_11)))]
|
|
-pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t {
|
|
- crate::PyTuple_GET_SIZE((*op).co_freevars)
|
|
-}
|
|
-
|
|
-#[inline]
|
|
-#[cfg(all(not(Py_3_10), Py_3_11, not(any(PyPy, GraalPy))))]
|
|
-pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> c_int {
|
|
- (*op).co_nfreevars
|
|
-}
|
|
-
|
|
extern "C" {
|
|
#[cfg(PyPy)]
|
|
#[link_name = "PyPyCode_Check"]
|
|
pub fn PyCode_Check(op: *mut PyObject) -> c_int;
|
|
-
|
|
- #[cfg(PyPy)]
|
|
- #[link_name = "PyPyCode_GetNumFree"]
|
|
- pub fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t;
|
|
}
|
|
|
|
+// skipped PyCode_GetNumFree (requires knowledge of code object layout)
|
|
+
|
|
extern "C" {
|
|
#[cfg(not(GraalPy))]
|
|
#[cfg_attr(PyPy, link_name = "PyPyCode_New")]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/compile.rs b/include/pyo3/pyo3-ffi/src/cpython/compile.rs
|
|
index 79f06c92..078b5e0d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/compile.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/compile.rs
|
|
@@ -6,19 +6,21 @@ use crate::pyarena::*;
|
|
use crate::pythonrun::*;
|
|
#[cfg(not(any(PyPy, Py_3_10)))]
|
|
use crate::PyCodeObject;
|
|
+use crate::INT_MAX;
|
|
#[cfg(not(any(PyPy, Py_3_10)))]
|
|
use std::os::raw::c_char;
|
|
use std::os::raw::c_int;
|
|
|
|
-// skipped non-limited PyCF_MASK
|
|
-// skipped non-limited PyCF_MASK_OBSOLETE
|
|
-// skipped non-limited PyCF_SOURCE_IS_UTF8
|
|
-// skipped non-limited PyCF_DONT_IMPLY_DEDENT
|
|
-// skipped non-limited PyCF_ONLY_AST
|
|
-// skipped non-limited PyCF_IGNORE_COOKIE
|
|
-// skipped non-limited PyCF_TYPE_COMMENTS
|
|
-// skipped non-limited PyCF_ALLOW_TOP_LEVEL_AWAIT
|
|
-// skipped non-limited PyCF_COMPILE_MASK
|
|
+// skipped PyCF_MASK
|
|
+// skipped PyCF_MASK_OBSOLETE
|
|
+// skipped PyCF_SOURCE_IS_UTF8
|
|
+// skipped PyCF_DONT_IMPLY_DEDENT
|
|
+// skipped PyCF_ONLY_AST
|
|
+// skipped PyCF_IGNORE_COOKIE
|
|
+// skipped PyCF_TYPE_COMMENTS
|
|
+// skipped PyCF_ALLOW_TOP_LEVEL_AWAIT
|
|
+// skipped PyCF_OPTIMIZED_AST
|
|
+// skipped PyCF_COMPILE_MASK
|
|
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
@@ -28,31 +30,23 @@ pub struct PyCompilerFlags {
|
|
pub cf_feature_version: c_int,
|
|
}
|
|
|
|
-// skipped non-limited _PyCompilerFlags_INIT
|
|
+// skipped _PyCompilerFlags_INIT
|
|
|
|
-#[cfg(all(Py_3_12, not(any(Py_3_13, PyPy, GraalPy))))]
|
|
-#[repr(C)]
|
|
-#[derive(Copy, Clone)]
|
|
-pub struct _PyCompilerSrcLocation {
|
|
- pub lineno: c_int,
|
|
- pub end_lineno: c_int,
|
|
- pub col_offset: c_int,
|
|
- pub end_col_offset: c_int,
|
|
-}
|
|
-
|
|
-// skipped SRC_LOCATION_FROM_AST
|
|
-
|
|
-#[cfg(not(any(PyPy, GraalPy, Py_3_13)))]
|
|
+// NB this type technically existed in the header until 3.13, when it was
|
|
+// moved to the internal CPython headers.
|
|
+//
|
|
+// We choose not to expose it in the public API past 3.10, as it is
|
|
+// not used in the public API past that point.
|
|
+#[cfg(not(any(PyPy, GraalPy, Py_3_10)))]
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
pub struct PyFutureFeatures {
|
|
pub ff_features: c_int,
|
|
- #[cfg(not(Py_3_12))]
|
|
pub ff_lineno: c_int,
|
|
- #[cfg(Py_3_12)]
|
|
- pub ff_location: _PyCompilerSrcLocation,
|
|
}
|
|
|
|
+// FIXME: these constants should probably be &CStr, if they are used at all
|
|
+
|
|
pub const FUTURE_NESTED_SCOPES: &str = "nested_scopes";
|
|
pub const FUTURE_GENERATORS: &str = "generators";
|
|
pub const FUTURE_DIVISION: &str = "division";
|
|
@@ -62,13 +56,12 @@ pub const FUTURE_PRINT_FUNCTION: &str = "print_function";
|
|
pub const FUTURE_UNICODE_LITERALS: &str = "unicode_literals";
|
|
pub const FUTURE_BARRY_AS_BDFL: &str = "barry_as_FLUFL";
|
|
pub const FUTURE_GENERATOR_STOP: &str = "generator_stop";
|
|
-// skipped non-limited FUTURE_ANNOTATIONS
|
|
+pub const FUTURE_ANNOTATIONS: &str = "annotations";
|
|
|
|
+#[cfg(not(any(PyPy, GraalPy, Py_3_10)))]
|
|
extern "C" {
|
|
- #[cfg(not(any(PyPy, Py_3_10)))]
|
|
pub fn PyNode_Compile(arg1: *mut _node, arg2: *const c_char) -> *mut PyCodeObject;
|
|
|
|
- #[cfg(not(any(PyPy, Py_3_10)))]
|
|
pub fn PyAST_CompileEx(
|
|
_mod: *mut _mod,
|
|
filename: *const c_char,
|
|
@@ -77,7 +70,6 @@ extern "C" {
|
|
arena: *mut PyArena,
|
|
) -> *mut PyCodeObject;
|
|
|
|
- #[cfg(not(any(PyPy, Py_3_10)))]
|
|
pub fn PyAST_CompileObject(
|
|
_mod: *mut _mod,
|
|
filename: *mut PyObject,
|
|
@@ -86,23 +78,20 @@ extern "C" {
|
|
arena: *mut PyArena,
|
|
) -> *mut PyCodeObject;
|
|
|
|
- #[cfg(not(any(PyPy, Py_3_10)))]
|
|
pub fn PyFuture_FromAST(_mod: *mut _mod, filename: *const c_char) -> *mut PyFutureFeatures;
|
|
|
|
- #[cfg(not(any(PyPy, Py_3_10)))]
|
|
pub fn PyFuture_FromASTObject(
|
|
_mod: *mut _mod,
|
|
filename: *mut PyObject,
|
|
) -> *mut PyFutureFeatures;
|
|
+}
|
|
|
|
- // skipped non-limited _Py_Mangle
|
|
- // skipped non-limited PY_INVALID_STACK_EFFECT
|
|
+pub const PY_INVALID_STACK_EFFECT: c_int = INT_MAX;
|
|
+
|
|
+extern "C" {
|
|
|
|
pub fn PyCompile_OpcodeStackEffect(opcode: c_int, oparg: c_int) -> c_int;
|
|
|
|
#[cfg(Py_3_8)]
|
|
pub fn PyCompile_OpcodeStackEffectWithJump(opcode: c_int, oparg: c_int, jump: c_int) -> c_int;
|
|
-
|
|
- // skipped non-limited _PyASTOptimizeState
|
|
- // skipped non-limited _PyAST_Optimize
|
|
}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/critical_section.rs b/include/pyo3/pyo3-ffi/src/cpython/critical_section.rs
|
|
index 1fc6591c..808dba87 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/critical_section.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/critical_section.rs
|
|
@@ -9,16 +9,6 @@ pub struct PyCriticalSection {
|
|
_cs_mutex: *mut PyMutex,
|
|
}
|
|
|
|
-#[cfg(Py_GIL_DISABLED)]
|
|
-impl Default for PyCriticalSection {
|
|
- fn default() -> Self {
|
|
- PyCriticalSection {
|
|
- _cs_prev: 0,
|
|
- _cs_mutex: core::ptr::null_mut(),
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
#[repr(C)]
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
pub struct PyCriticalSection2 {
|
|
@@ -27,10 +17,10 @@ pub struct PyCriticalSection2 {
|
|
}
|
|
|
|
#[cfg(not(Py_GIL_DISABLED))]
|
|
-opaque_struct!(PyCriticalSection);
|
|
+opaque_struct!(pub PyCriticalSection);
|
|
|
|
#[cfg(not(Py_GIL_DISABLED))]
|
|
-opaque_struct!(PyCriticalSection2);
|
|
+opaque_struct!(pub PyCriticalSection2);
|
|
|
|
extern "C" {
|
|
pub fn PyCriticalSection_Begin(c: *mut PyCriticalSection, op: *mut PyObject);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/descrobject.rs b/include/pyo3/pyo3-ffi/src/cpython/descrobject.rs
|
|
index 1b5ee466..7cef9bdb 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/descrobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/descrobject.rs
|
|
@@ -69,10 +69,7 @@ pub struct PyWrapperDescrObject {
|
|
pub d_wrapped: *mut c_void,
|
|
}
|
|
|
|
-#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
-extern "C" {
|
|
- pub static mut _PyMethodWrapper_Type: PyTypeObject;
|
|
-}
|
|
+// skipped _PyMethodWrapper_Type
|
|
|
|
// skipped non-limited PyDescr_NewWrapper
|
|
// skipped non-limited PyDescr_IsData
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/dictobject.rs b/include/pyo3/pyo3-ffi/src/cpython/dictobject.rs
|
|
index f67a7725..34b66a96 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/dictobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/dictobject.rs
|
|
@@ -2,10 +2,10 @@ use crate::object::*;
|
|
use crate::pyport::Py_ssize_t;
|
|
use std::os::raw::c_int;
|
|
|
|
-opaque_struct!(PyDictKeysObject);
|
|
+opaque_struct!(pub PyDictKeysObject);
|
|
|
|
#[cfg(Py_3_11)]
|
|
-opaque_struct!(PyDictValues);
|
|
+opaque_struct!(pub PyDictValues);
|
|
|
|
#[cfg(not(GraalPy))]
|
|
#[repr(C)]
|
|
@@ -17,7 +17,10 @@ pub struct PyDictObject {
|
|
Py_3_12,
|
|
deprecated(note = "Deprecated in Python 3.12 and will be removed in the future.")
|
|
)]
|
|
+ #[cfg(not(Py_3_14))]
|
|
pub ma_version_tag: u64,
|
|
+ #[cfg(Py_3_14)]
|
|
+ _ma_watcher_tag: u64,
|
|
pub ma_keys: *mut PyDictKeysObject,
|
|
#[cfg(not(Py_3_11))]
|
|
pub ma_values: *mut *mut PyObject,
|
|
@@ -36,15 +39,6 @@ extern "C" {
|
|
item: *mut PyObject,
|
|
hash: crate::Py_hash_t,
|
|
) -> c_int;
|
|
-
|
|
- #[cfg(Py_3_13)]
|
|
- pub fn _PyDict_SetItem_KnownHash_LockHeld(
|
|
- mp: *mut PyDictObject,
|
|
- name: *mut PyObject,
|
|
- value: *mut PyObject,
|
|
- hash: crate::Py_hash_t,
|
|
- ) -> c_int;
|
|
-
|
|
// skipped _PyDict_DelItem_KnownHash
|
|
// skipped _PyDict_DelItemIf
|
|
// skipped _PyDict_NewKeysForClass
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/frameobject.rs b/include/pyo3/pyo3-ffi/src/cpython/frameobject.rs
|
|
index 6d2346f9..993e93c8 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/frameobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/frameobject.rs
|
|
@@ -53,7 +53,7 @@ pub struct PyFrameObject {
|
|
}
|
|
|
|
#[cfg(any(PyPy, GraalPy, Py_3_11))]
|
|
-opaque_struct!(PyFrameObject);
|
|
+opaque_struct!(pub PyFrameObject);
|
|
|
|
// skipped _PyFrame_IsRunnable
|
|
// skipped _PyFrame_IsExecuting
|
|
@@ -89,7 +89,8 @@ extern "C" {
|
|
pub fn PyFrame_FastToLocals(f: *mut PyFrameObject);
|
|
|
|
// skipped _PyFrame_DebugMallocStats
|
|
- // skipped PyFrame_GetBack
|
|
+ #[cfg(all(Py_3_9, not(PyPy)))]
|
|
+ pub fn PyFrame_GetBack(f: *mut PyFrameObject) -> *mut PyFrameObject;
|
|
|
|
#[cfg(not(Py_3_9))]
|
|
pub fn PyFrame_ClearFreeList() -> c_int;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/funcobject.rs b/include/pyo3/pyo3-ffi/src/cpython/funcobject.rs
|
|
index 25de30d5..cd2052de 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/funcobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/funcobject.rs
|
|
@@ -41,6 +41,8 @@ pub struct PyFunctionObject {
|
|
pub func_weakreflist: *mut PyObject,
|
|
pub func_module: *mut PyObject,
|
|
pub func_annotations: *mut PyObject,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub func_annotate: *mut PyObject,
|
|
#[cfg(Py_3_12)]
|
|
pub func_typeparams: *mut PyObject,
|
|
pub vectorcall: Option<crate::vectorcallfunc>,
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/genobject.rs b/include/pyo3/pyo3-ffi/src/cpython/genobject.rs
|
|
index 4be310a8..92f14d59 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/genobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/genobject.rs
|
|
@@ -1,13 +1,11 @@
|
|
use crate::object::*;
|
|
use crate::PyFrameObject;
|
|
-#[cfg(not(any(PyPy, GraalPy)))]
|
|
-use crate::_PyErr_StackItem;
|
|
-#[cfg(all(Py_3_11, not(GraalPy)))]
|
|
+#[cfg(all(Py_3_11, not(any(PyPy, GraalPy, Py_3_14))))]
|
|
use std::os::raw::c_char;
|
|
use std::os::raw::c_int;
|
|
use std::ptr::addr_of_mut;
|
|
|
|
-#[cfg(not(any(PyPy, GraalPy)))]
|
|
+#[cfg(not(any(PyPy, GraalPy, Py_3_14)))]
|
|
#[repr(C)]
|
|
pub struct PyGenObject {
|
|
pub ob_base: PyObject,
|
|
@@ -20,7 +18,7 @@ pub struct PyGenObject {
|
|
pub gi_weakreflist: *mut PyObject,
|
|
pub gi_name: *mut PyObject,
|
|
pub gi_qualname: *mut PyObject,
|
|
- pub gi_exc_state: _PyErr_StackItem,
|
|
+ pub gi_exc_state: crate::cpython::pystate::_PyErr_StackItem,
|
|
#[cfg(Py_3_11)]
|
|
pub gi_origin_or_finalizer: *mut PyObject,
|
|
#[cfg(Py_3_11)]
|
|
@@ -35,6 +33,9 @@ pub struct PyGenObject {
|
|
pub gi_iframe: [*mut PyObject; 1],
|
|
}
|
|
|
|
+#[cfg(all(Py_3_14, not(any(PyPy, GraalPy))))]
|
|
+opaque_struct!(pub PyGenObject);
|
|
+
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
pub static mut PyGen_Type: PyTypeObject;
|
|
@@ -67,9 +68,10 @@ extern "C" {
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
pub static mut PyCoro_Type: PyTypeObject;
|
|
- pub static mut _PyCoroWrapper_Type: PyTypeObject;
|
|
}
|
|
|
|
+// skipped _PyCoroWrapper_Type
|
|
+
|
|
#[inline]
|
|
pub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int {
|
|
PyObject_TypeCheck(op, addr_of_mut!(PyCoro_Type))
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/import.rs b/include/pyo3/pyo3-ffi/src/cpython/import.rs
|
|
index 697d68a4..c8ef5ab4 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/import.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/import.rs
|
|
@@ -65,10 +65,8 @@ pub struct _frozen {
|
|
extern "C" {
|
|
#[cfg(not(PyPy))]
|
|
pub static mut PyImport_FrozenModules: *const _frozen;
|
|
- #[cfg(all(not(PyPy), Py_3_11))]
|
|
- pub static mut _PyImport_FrozenBootstrap: *const _frozen;
|
|
- #[cfg(all(not(PyPy), Py_3_11))]
|
|
- pub static mut _PyImport_FrozenStdlib: *const _frozen;
|
|
- #[cfg(all(not(PyPy), Py_3_11))]
|
|
- pub static mut _PyImport_FrozenTest: *const _frozen;
|
|
}
|
|
+
|
|
+// skipped _PyImport_FrozenBootstrap
|
|
+// skipped _PyImport_FrozenStdlib
|
|
+// skipped _PyImport_FrozenTest
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/initconfig.rs b/include/pyo3/pyo3-ffi/src/cpython/initconfig.rs
|
|
index 321d200e..076981f1 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/initconfig.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/initconfig.rs
|
|
@@ -93,6 +93,8 @@ pub struct PyConfig {
|
|
pub tracemalloc: c_int,
|
|
#[cfg(Py_3_12)]
|
|
pub perf_profiling: c_int,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub remote_debug: c_int,
|
|
pub import_time: c_int,
|
|
#[cfg(Py_3_11)]
|
|
pub code_debug_ranges: c_int,
|
|
@@ -141,10 +143,18 @@ pub struct PyConfig {
|
|
pub safe_path: c_int,
|
|
#[cfg(Py_3_12)]
|
|
pub int_max_str_digits: c_int,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub thread_inherit_context: c_int,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub context_aware_warnings: c_int,
|
|
+ #[cfg(all(Py_3_14, target_os = "macos"))]
|
|
+ pub use_system_logger: c_int,
|
|
#[cfg(Py_3_13)]
|
|
pub cpu_count: c_int,
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
pub enable_gil: c_int,
|
|
+ #[cfg(all(Py_3_14, Py_GIL_DISABLED))]
|
|
+ pub tlbc_enabled: c_int,
|
|
pub pathconfig_warnings: c_int,
|
|
#[cfg(Py_3_10)]
|
|
pub program_name: *mut wchar_t,
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/lock.rs b/include/pyo3/pyo3-ffi/src/cpython/lock.rs
|
|
index c451666e..6c80b00d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/lock.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/lock.rs
|
|
@@ -8,15 +8,6 @@ pub struct PyMutex {
|
|
pub(crate) _pin: PhantomPinned,
|
|
}
|
|
|
|
-impl PyMutex {
|
|
- pub const fn new() -> PyMutex {
|
|
- PyMutex {
|
|
- _bits: AtomicU8::new(0),
|
|
- _pin: PhantomPinned,
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
extern "C" {
|
|
pub fn PyMutex_Lock(m: *mut PyMutex);
|
|
pub fn PyMutex_Unlock(m: *mut PyMutex);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
index 6063575e..45acaae5 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
@@ -61,18 +61,6 @@ extern "C" {
|
|
is_signed: c_int,
|
|
) -> *mut PyObject;
|
|
|
|
- #[cfg(Py_3_13)]
|
|
- #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
- pub fn _PyLong_AsByteArray(
|
|
- v: *mut PyLongObject,
|
|
- bytes: *mut c_uchar,
|
|
- n: size_t,
|
|
- little_endian: c_int,
|
|
- is_signed: c_int,
|
|
- with_exceptions: c_int,
|
|
- ) -> c_int;
|
|
-
|
|
- #[cfg(not(Py_3_13))]
|
|
#[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
pub fn _PyLong_AsByteArray(
|
|
v: *mut PyLongObject,
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/mod.rs b/include/pyo3/pyo3-ffi/src/cpython/mod.rs
|
|
index fe909f0c..adaf8bc8 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/mod.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/mod.rs
|
|
@@ -38,6 +38,7 @@ pub(crate) mod pythonrun;
|
|
// skipped sysmodule.h
|
|
pub(crate) mod floatobject;
|
|
pub(crate) mod pyframe;
|
|
+pub(crate) mod pyhash;
|
|
pub(crate) mod tupleobject;
|
|
pub(crate) mod unicodeobject;
|
|
pub(crate) mod weakrefobject;
|
|
@@ -71,8 +72,10 @@ pub use self::object::*;
|
|
pub use self::objimpl::*;
|
|
pub use self::pydebug::*;
|
|
pub use self::pyerrors::*;
|
|
-#[cfg(Py_3_11)]
|
|
+#[cfg(all(Py_3_11, not(PyPy)))]
|
|
pub use self::pyframe::*;
|
|
+#[cfg(any(not(PyPy), Py_3_13))]
|
|
+pub use self::pyhash::*;
|
|
#[cfg(all(Py_3_8, not(PyPy)))]
|
|
pub use self::pylifecycle::*;
|
|
pub use self::pymem::*;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/object.rs b/include/pyo3/pyo3-ffi/src/cpython/object.rs
|
|
index 75eef11a..26ef784d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/object.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/object.rs
|
|
@@ -310,10 +310,14 @@ pub struct PyHeapTypeObject {
|
|
pub ht_cached_keys: *mut c_void,
|
|
#[cfg(Py_3_9)]
|
|
pub ht_module: *mut object::PyObject,
|
|
- #[cfg(Py_3_11)]
|
|
+ #[cfg(all(Py_3_11, not(PyPy)))]
|
|
_ht_tpname: *mut c_char,
|
|
- #[cfg(Py_3_11)]
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub ht_token: *mut c_void,
|
|
+ #[cfg(all(Py_3_11, not(PyPy)))]
|
|
_spec_cache: _specialization_cache,
|
|
+ #[cfg(all(Py_GIL_DISABLED, Py_3_14))]
|
|
+ pub unique_id: Py_ssize_t,
|
|
}
|
|
|
|
impl Default for PyHeapTypeObject {
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/objimpl.rs b/include/pyo3/pyo3-ffi/src/cpython/objimpl.rs
|
|
index 98a19abe..14f7121a 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/objimpl.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/objimpl.rs
|
|
@@ -1,4 +1,4 @@
|
|
-#[cfg(not(all(Py_3_11, GraalPy)))]
|
|
+#[cfg(not(all(Py_3_11, any(PyPy, GraalPy))))]
|
|
use libc::size_t;
|
|
use std::os::raw::c_int;
|
|
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/pyerrors.rs b/include/pyo3/pyo3-ffi/src/cpython/pyerrors.rs
|
|
index c6e10e5f..c9831669 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/pyerrors.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/pyerrors.rs
|
|
@@ -46,6 +46,8 @@ pub struct PySyntaxErrorObject {
|
|
pub end_offset: *mut PyObject,
|
|
pub text: *mut PyObject,
|
|
pub print_file_and_line: *mut PyObject,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub metadata: *mut PyObject,
|
|
}
|
|
|
|
#[cfg(not(any(PyPy, GraalPy)))]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/pyframe.rs b/include/pyo3/pyo3-ffi/src/cpython/pyframe.rs
|
|
index d0cfa0a2..f0c38be4 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/pyframe.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/pyframe.rs
|
|
@@ -1,2 +1,3 @@
|
|
-#[cfg(Py_3_11)]
|
|
-opaque_struct!(_PyInterpreterFrame);
|
|
+// NB used in `_PyEval_EvalFrameDefault`, maybe we remove this too.
|
|
+#[cfg(all(Py_3_11, not(PyPy)))]
|
|
+opaque_struct!(pub _PyInterpreterFrame);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/pyhash.rs b/include/pyo3/pyo3-ffi/src/cpython/pyhash.rs
|
|
new file mode 100644
|
|
index 00000000..b746018a
|
|
--- /dev/null
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/pyhash.rs
|
|
@@ -0,0 +1,38 @@
|
|
+#[cfg(Py_3_14)]
|
|
+use crate::Py_ssize_t;
|
|
+#[cfg(Py_3_13)]
|
|
+use crate::{PyObject, Py_hash_t};
|
|
+#[cfg(any(Py_3_13, not(PyPy)))]
|
|
+use std::os::raw::c_void;
|
|
+#[cfg(not(PyPy))]
|
|
+use std::os::raw::{c_char, c_int};
|
|
+
|
|
+#[cfg(not(PyPy))]
|
|
+#[repr(C)]
|
|
+#[derive(Copy, Clone)]
|
|
+pub struct PyHash_FuncDef {
|
|
+ pub hash:
|
|
+ Option<extern "C" fn(arg1: *const c_void, arg2: crate::Py_ssize_t) -> crate::Py_hash_t>,
|
|
+ pub name: *const c_char,
|
|
+ pub hash_bits: c_int,
|
|
+ pub seed_bits: c_int,
|
|
+}
|
|
+
|
|
+#[cfg(not(PyPy))]
|
|
+impl Default for PyHash_FuncDef {
|
|
+ #[inline]
|
|
+ fn default() -> Self {
|
|
+ unsafe { std::mem::zeroed() }
|
|
+ }
|
|
+}
|
|
+
|
|
+extern "C" {
|
|
+ #[cfg(not(PyPy))]
|
|
+ pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef;
|
|
+ #[cfg(Py_3_13)]
|
|
+ pub fn Py_HashPointer(ptr: *const c_void) -> Py_hash_t;
|
|
+ #[cfg(Py_3_13)]
|
|
+ pub fn PyObject_GenericHash(obj: *mut PyObject) -> Py_hash_t;
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t;
|
|
+}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/pystate.rs b/include/pyo3/pyo3-ffi/src/cpython/pystate.rs
|
|
index 5481265b..b8f6fd66 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/pystate.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/pystate.rs
|
|
@@ -27,16 +27,18 @@ pub const PyTrace_OPCODE: c_int = 7;
|
|
// skipped PyTraceInfo
|
|
// skipped CFrame
|
|
|
|
+/// Private structure used inline in `PyGenObject`
|
|
#[cfg(not(PyPy))]
|
|
#[repr(C)]
|
|
#[derive(Clone, Copy)]
|
|
+#[doc(hidden)] // TODO should be able to make pub(crate) after MSRV 1.74
|
|
pub struct _PyErr_StackItem {
|
|
#[cfg(not(Py_3_11))]
|
|
- pub exc_type: *mut PyObject,
|
|
- pub exc_value: *mut PyObject,
|
|
+ exc_type: *mut PyObject,
|
|
+ exc_value: *mut PyObject,
|
|
#[cfg(not(Py_3_11))]
|
|
- pub exc_traceback: *mut PyObject,
|
|
- pub previous_item: *mut _PyErr_StackItem,
|
|
+ exc_traceback: *mut PyObject,
|
|
+ previous_item: *mut _PyErr_StackItem,
|
|
}
|
|
|
|
// skipped _PyStackChunk
|
|
@@ -69,21 +71,21 @@ extern "C" {
|
|
pub fn PyThreadState_DeleteCurrent();
|
|
}
|
|
|
|
-#[cfg(all(Py_3_9, not(Py_3_11)))]
|
|
+#[cfg(all(Py_3_9, not(any(Py_3_11, PyPy))))]
|
|
pub type _PyFrameEvalFunction = extern "C" fn(
|
|
*mut crate::PyThreadState,
|
|
*mut crate::PyFrameObject,
|
|
c_int,
|
|
) -> *mut crate::object::PyObject;
|
|
|
|
-#[cfg(Py_3_11)]
|
|
+#[cfg(all(Py_3_11, not(PyPy)))]
|
|
pub type _PyFrameEvalFunction = extern "C" fn(
|
|
*mut crate::PyThreadState,
|
|
*mut crate::_PyInterpreterFrame,
|
|
c_int,
|
|
) -> *mut crate::object::PyObject;
|
|
|
|
-#[cfg(Py_3_9)]
|
|
+#[cfg(all(Py_3_9, not(PyPy)))]
|
|
extern "C" {
|
|
/// Get the frame evaluation function.
|
|
pub fn _PyInterpreterState_GetEvalFrameFunc(
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/tupleobject.rs b/include/pyo3/pyo3-ffi/src/cpython/tupleobject.rs
|
|
index c06609fb..dc1bf8e4 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/tupleobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/tupleobject.rs
|
|
@@ -1,4 +1,6 @@
|
|
use crate::object::*;
|
|
+#[cfg(Py_3_14)]
|
|
+use crate::pyport::Py_hash_t;
|
|
#[cfg(not(PyPy))]
|
|
use crate::pyport::Py_ssize_t;
|
|
|
|
@@ -6,7 +8,7 @@ use crate::pyport::Py_ssize_t;
|
|
pub struct PyTupleObject {
|
|
pub ob_base: PyVarObject,
|
|
#[cfg(Py_3_14)]
|
|
- pub ob_hash: crate::Py_hash_t,
|
|
+ pub ob_hash: Py_hash_t,
|
|
pub ob_item: [*mut PyObject; 1],
|
|
}
|
|
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/unicodeobject.rs b/include/pyo3/pyo3-ffi/src/cpython/unicodeobject.rs
|
|
index 72da46c1..452c82e4 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/unicodeobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/unicodeobject.rs
|
|
@@ -1,4 +1,4 @@
|
|
-#[cfg(not(PyPy))]
|
|
+#[cfg(any(Py_3_11, not(PyPy)))]
|
|
use crate::Py_hash_t;
|
|
use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_ssize_t};
|
|
use libc::wchar_t;
|
|
@@ -31,11 +31,13 @@ use std::os::raw::{c_char, c_int, c_uint, c_void};
|
|
// skipped Py_UNICODE_LOW_SURROGATE
|
|
|
|
// generated by bindgen v0.63.0 (with small adaptations)
|
|
+#[cfg(not(Py_3_14))]
|
|
#[repr(C)]
|
|
struct BitfieldUnit<Storage> {
|
|
storage: Storage,
|
|
}
|
|
|
|
+#[cfg(not(Py_3_14))]
|
|
impl<Storage> BitfieldUnit<Storage> {
|
|
#[inline]
|
|
pub const fn new(storage: Storage) -> Self {
|
|
@@ -43,7 +45,7 @@ impl<Storage> BitfieldUnit<Storage> {
|
|
}
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
impl<Storage> BitfieldUnit<Storage>
|
|
where
|
|
Storage: AsRef<[u8]> + AsMut<[u8]>,
|
|
@@ -117,30 +119,33 @@ where
|
|
}
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_INTERNED_INDEX: usize = 0;
|
|
-#[cfg(all(not(GraalPy), not(Py_3_14)))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_INTERNED_WIDTH: u8 = 2;
|
|
|
|
-#[cfg(all(not(GraalPy), Py_3_14))]
|
|
-const STATE_INTERNED_WIDTH: u8 = 16;
|
|
-
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize;
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_KIND_WIDTH: u8 = 3;
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize;
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_COMPACT_WIDTH: u8 = 1;
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_ASCII_INDEX: usize =
|
|
(STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize;
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
const STATE_ASCII_WIDTH: u8 = 1;
|
|
|
|
+#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]
|
|
+const STATE_STATICALLY_ALLOCATED_INDEX: usize =
|
|
+ (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;
|
|
+#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]
|
|
+const STATE_STATICALLY_ALLOCATED_WIDTH: u8 = 1;
|
|
+
|
|
#[cfg(not(any(Py_3_12, GraalPy)))]
|
|
const STATE_READY_INDEX: usize =
|
|
(STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;
|
|
@@ -156,15 +161,15 @@ const STATE_READY_WIDTH: u8 = 1;
|
|
///
|
|
/// Memory layout of C bitfields is implementation defined, so these functions are still
|
|
/// unsafe. Users must verify that they work as expected on the architectures they target.
|
|
+#[cfg(not(Py_3_14))]
|
|
#[repr(C)]
|
|
-#[repr(align(4))]
|
|
struct PyASCIIObjectState {
|
|
bitfield_align: [u8; 0],
|
|
bitfield: BitfieldUnit<[u8; 4usize]>,
|
|
}
|
|
|
|
// c_uint and u32 are not necessarily the same type on all targets / architectures
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
#[allow(clippy::useless_transmute)]
|
|
impl PyASCIIObjectState {
|
|
#[inline]
|
|
@@ -218,6 +223,26 @@ impl PyASCIIObjectState {
|
|
.set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64)
|
|
}
|
|
|
|
+ #[cfg(Py_3_12)]
|
|
+ #[inline]
|
|
+ unsafe fn statically_allocated(&self) -> c_uint {
|
|
+ std::mem::transmute(self.bitfield.get(
|
|
+ STATE_STATICALLY_ALLOCATED_INDEX,
|
|
+ STATE_STATICALLY_ALLOCATED_WIDTH,
|
|
+ ) as u32)
|
|
+ }
|
|
+
|
|
+ #[cfg(Py_3_12)]
|
|
+ #[inline]
|
|
+ unsafe fn set_statically_allocated(&mut self, val: c_uint) {
|
|
+ let val: u32 = std::mem::transmute(val);
|
|
+ self.bitfield.set(
|
|
+ STATE_STATICALLY_ALLOCATED_INDEX,
|
|
+ STATE_STATICALLY_ALLOCATED_WIDTH,
|
|
+ val as u64,
|
|
+ )
|
|
+ }
|
|
+
|
|
#[cfg(not(Py_3_12))]
|
|
#[inline]
|
|
unsafe fn ready(&self) -> c_uint {
|
|
@@ -233,6 +258,7 @@ impl PyASCIIObjectState {
|
|
}
|
|
}
|
|
|
|
+#[cfg(not(Py_3_14))]
|
|
impl From<u32> for PyASCIIObjectState {
|
|
#[inline]
|
|
fn from(value: u32) -> Self {
|
|
@@ -243,6 +269,7 @@ impl From<u32> for PyASCIIObjectState {
|
|
}
|
|
}
|
|
|
|
+#[cfg(not(Py_3_14))]
|
|
impl From<PyASCIIObjectState> for u32 {
|
|
#[inline]
|
|
fn from(value: PyASCIIObjectState) -> Self {
|
|
@@ -254,26 +281,36 @@ impl From<PyASCIIObjectState> for u32 {
|
|
pub struct PyASCIIObject {
|
|
pub ob_base: PyObject,
|
|
pub length: Py_ssize_t,
|
|
- #[cfg(not(PyPy))]
|
|
+ #[cfg(any(Py_3_11, not(PyPy)))]
|
|
pub hash: Py_hash_t,
|
|
/// A bit field with various properties.
|
|
///
|
|
/// Rust doesn't expose bitfields. So we have accessor functions for
|
|
/// retrieving values.
|
|
///
|
|
+ /// Before 3.12:
|
|
/// unsigned int interned:2; // SSTATE_* constants.
|
|
/// unsigned int kind:3; // PyUnicode_*_KIND constants.
|
|
/// unsigned int compact:1;
|
|
/// unsigned int ascii:1;
|
|
/// unsigned int ready:1;
|
|
/// unsigned int :24;
|
|
+ ///
|
|
+ /// 3.12, and 3.13
|
|
+ /// unsigned int interned:2; // SSTATE_* constants.
|
|
+ /// unsigned int kind:3; // PyUnicode_*_KIND constants.
|
|
+ /// unsigned int compact:1;
|
|
+ /// unsigned int ascii:1;
|
|
+ /// unsigned int statically_allocated:1;
|
|
+ /// unsigned int :24;
|
|
+ /// on 3.14 and higher PyO3 doesn't access the internal state
|
|
pub state: u32,
|
|
#[cfg(not(Py_3_12))]
|
|
pub wstr: *mut wchar_t,
|
|
}
|
|
|
|
/// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe.
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
impl PyASCIIObject {
|
|
#[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12
|
|
/// Get the `interned` field of the [`PyASCIIObject`] state bitfield.
|
|
@@ -350,6 +387,7 @@ impl PyASCIIObject {
|
|
///
|
|
/// Calling this function with an argument that is neither `0` nor `1` is invalid.
|
|
#[inline]
|
|
+ #[cfg(not(all(Py_3_14, Py_GIL_DISABLED)))]
|
|
pub unsafe fn set_ascii(&mut self, val: c_uint) {
|
|
let mut state = PyASCIIObjectState::from(self.state);
|
|
state.set_ascii(val);
|
|
@@ -375,6 +413,26 @@ impl PyASCIIObject {
|
|
state.set_ready(val);
|
|
self.state = u32::from(state);
|
|
}
|
|
+
|
|
+ /// Get the `statically_allocated` field of the [`PyASCIIObject`] state bitfield.
|
|
+ ///
|
|
+ /// Returns either `0` or `1`.
|
|
+ #[inline]
|
|
+ #[cfg(Py_3_12)]
|
|
+ pub unsafe fn statically_allocated(&self) -> c_uint {
|
|
+ PyASCIIObjectState::from(self.state).statically_allocated()
|
|
+ }
|
|
+
|
|
+ /// Set the `statically_allocated` flag of the [`PyASCIIObject`] state bitfield.
|
|
+ ///
|
|
+ /// Calling this function with an argument that is neither `0` nor `1` is invalid.
|
|
+ #[inline]
|
|
+ #[cfg(Py_3_12)]
|
|
+ pub unsafe fn set_statically_allocated(&mut self, val: c_uint) {
|
|
+ let mut state = PyASCIIObjectState::from(self.state);
|
|
+ state.set_statically_allocated(val);
|
|
+ self.state = u32::from(state);
|
|
+ }
|
|
}
|
|
|
|
#[repr(C)]
|
|
@@ -416,7 +474,7 @@ pub const SSTATE_INTERNED_IMMORTAL: c_uint = 2;
|
|
#[cfg(Py_3_12)]
|
|
pub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3;
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint {
|
|
debug_assert!(crate::PyUnicode_Check(op) != 0);
|
|
@@ -426,13 +484,13 @@ pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint {
|
|
(*(op as *mut PyASCIIObject)).ascii()
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint {
|
|
(*(op as *mut PyASCIIObject)).compact()
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint {
|
|
((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into()
|
|
@@ -464,7 +522,13 @@ pub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 {
|
|
PyUnicode_DATA(op) as *mut Py_UCS4
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(all(not(GraalPy), Py_3_14))]
|
|
+extern "C" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyUnicode_KIND")]
|
|
+ pub fn PyUnicode_KIND(op: *mut PyObject) -> c_uint;
|
|
+}
|
|
+
|
|
+#[cfg(all(not(GraalPy), not(Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint {
|
|
debug_assert!(crate::PyUnicode_Check(op) != 0);
|
|
@@ -474,7 +538,7 @@ pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint {
|
|
(*(op as *mut PyASCIIObject)).kind()
|
|
}
|
|
|
|
-#[cfg(not(GraalPy))]
|
|
+#[cfg(not(any(GraalPy, Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void {
|
|
if PyUnicode_IS_ASCII(op) != 0 {
|
|
@@ -492,7 +556,7 @@ pub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void {
|
|
(*(op as *mut PyUnicodeObject)).data.any
|
|
}
|
|
|
|
-#[cfg(not(any(GraalPy, PyPy)))]
|
|
+#[cfg(not(any(GraalPy, PyPy, Py_3_14)))]
|
|
#[inline]
|
|
pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void {
|
|
debug_assert!(crate::PyUnicode_Check(op) != 0);
|
|
@@ -504,6 +568,13 @@ pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void {
|
|
}
|
|
}
|
|
|
|
+#[cfg(Py_3_14)]
|
|
+#[cfg(all(not(GraalPy), Py_3_14))]
|
|
+extern "C" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyUnicode_DATA")]
|
|
+ pub fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void;
|
|
+}
|
|
+
|
|
// skipped PyUnicode_WRITE
|
|
// skipped PyUnicode_READ
|
|
// skipped PyUnicode_READ_CHAR
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/weakrefobject.rs b/include/pyo3/pyo3-ffi/src/cpython/weakrefobject.rs
|
|
index 88bb501b..1c50c7a7 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/weakrefobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/weakrefobject.rs
|
|
@@ -1,3 +1,4 @@
|
|
+// NB publicly re-exported in `src/weakrefobject.rs`
|
|
#[cfg(not(any(PyPy, GraalPy)))]
|
|
pub struct _PyWeakReference {
|
|
pub ob_base: crate::PyObject,
|
|
diff --git a/include/pyo3/pyo3-ffi/src/datetime.rs b/include/pyo3/pyo3-ffi/src/datetime.rs
|
|
index e529e0fc..4db1bdd1 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/datetime.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/datetime.rs
|
|
@@ -119,7 +119,7 @@ pub struct PyDateTime_DateTime {
|
|
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
|
|
// This should work for Date or DateTime
|
|
let data = (*(o as *mut PyDateTime_Date)).data;
|
|
- c_int::from(data[0]) << 8 | c_int::from(data[1])
|
|
+ (c_int::from(data[0]) << 8) | c_int::from(data[1])
|
|
}
|
|
|
|
#[inline]
|
|
@@ -487,7 +487,9 @@ extern "C" {
|
|
pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int;
|
|
#[link_name = "PyPyDateTime_GET_FOLD"]
|
|
pub fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int;
|
|
- // skipped PyDateTime_DATE_GET_TZINFO (not in PyPy)
|
|
+ #[link_name = "PyPyDateTime_DATE_GET_TZINFO"]
|
|
+ #[cfg(Py_3_10)]
|
|
+ pub fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject;
|
|
|
|
#[link_name = "PyPyDateTime_TIME_GET_HOUR"]
|
|
pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int;
|
|
@@ -499,7 +501,9 @@ extern "C" {
|
|
pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int;
|
|
#[link_name = "PyPyDateTime_TIME_GET_FOLD"]
|
|
pub fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int;
|
|
- // skipped PyDateTime_TIME_GET_TZINFO (not in PyPy)
|
|
+ #[link_name = "PyPyDateTime_TIME_GET_TZINFO"]
|
|
+ #[cfg(Py_3_10)]
|
|
+ pub fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject;
|
|
|
|
#[link_name = "PyPyDateTime_DELTA_GET_DAYS"]
|
|
pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/dictobject.rs b/include/pyo3/pyo3-ffi/src/dictobject.rs
|
|
index 710be802..e609352a 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/dictobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/dictobject.rs
|
|
@@ -118,4 +118,4 @@ extern "C" {
|
|
|
|
#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]
|
|
// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)
|
|
-opaque_struct!(PyDictObject);
|
|
+opaque_struct!(pub PyDictObject);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/floatobject.rs b/include/pyo3/pyo3-ffi/src/floatobject.rs
|
|
index 65fc1d4c..4e1d6476 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/floatobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/floatobject.rs
|
|
@@ -4,7 +4,7 @@ use std::ptr::addr_of_mut;
|
|
|
|
#[cfg(Py_LIMITED_API)]
|
|
// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)
|
|
-opaque_struct!(PyFloatObject);
|
|
+opaque_struct!(pub PyFloatObject);
|
|
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
diff --git a/include/pyo3/pyo3-ffi/src/genericaliasobject.rs b/include/pyo3/pyo3-ffi/src/genericaliasobject.rs
|
|
new file mode 100644
|
|
index 00000000..7979d7d8
|
|
--- /dev/null
|
|
+++ b/include/pyo3/pyo3-ffi/src/genericaliasobject.rs
|
|
@@ -0,0 +1,12 @@
|
|
+#[cfg(Py_3_9)]
|
|
+use crate::object::{PyObject, PyTypeObject};
|
|
+
|
|
+#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
+extern "C" {
|
|
+ #[cfg(Py_3_9)]
|
|
+ #[cfg_attr(PyPy, link_name = "PyPy_GenericAlias")]
|
|
+ pub fn Py_GenericAlias(origin: *mut PyObject, args: *mut PyObject) -> *mut PyObject;
|
|
+
|
|
+ #[cfg(Py_3_9)]
|
|
+ pub static mut Py_GenericAliasType: PyTypeObject;
|
|
+}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/lib.rs b/include/pyo3/pyo3-ffi/src/lib.rs
|
|
index 7bdba117..f78c918a 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/lib.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/lib.rs
|
|
@@ -129,7 +129,7 @@
|
|
//! ```
|
|
//!
|
|
//! **`src/lib.rs`**
|
|
-//! ```rust
|
|
+//! ```rust,no_run
|
|
//! use std::os::raw::{c_char, c_long};
|
|
//! use std::ptr;
|
|
//!
|
|
@@ -327,17 +327,24 @@
|
|
non_snake_case,
|
|
non_upper_case_globals,
|
|
clippy::upper_case_acronyms,
|
|
- clippy::missing_safety_doc
|
|
+ clippy::missing_safety_doc,
|
|
+ clippy::ptr_eq
|
|
)]
|
|
#![warn(elided_lifetimes_in_paths, unused_lifetimes)]
|
|
+// This crate is a hand-maintained translation of CPython's headers, so requiring "unsafe"
|
|
+// blocks within those translations increases maintenance burden without providing any
|
|
+// additional safety. The safety of the functions in this crate is determined by the
|
|
+// original CPython headers
|
|
+#![allow(unsafe_op_in_unsafe_fn)]
|
|
|
|
// Until `extern type` is stabilized, use the recommended approach to
|
|
// model opaque types:
|
|
// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
|
|
macro_rules! opaque_struct {
|
|
- ($name:ident) => {
|
|
+ ($(#[$attrs:meta])* $pub:vis $name:ident) => {
|
|
+ $(#[$attrs])*
|
|
#[repr(C)]
|
|
- pub struct $name([u8; 0]);
|
|
+ $pub struct $name([u8; 0]);
|
|
};
|
|
}
|
|
|
|
@@ -351,7 +358,7 @@ macro_rules! opaque_struct {
|
|
///
|
|
/// Examples:
|
|
///
|
|
-/// ```rust
|
|
+/// ```rust,no_run
|
|
/// use std::ffi::CStr;
|
|
///
|
|
/// const HELLO: &CStr = pyo3_ffi::c_str!("hello");
|
|
@@ -410,6 +417,8 @@ pub use self::enumobject::*;
|
|
pub use self::fileobject::*;
|
|
pub use self::fileutils::*;
|
|
pub use self::floatobject::*;
|
|
+#[cfg(Py_3_9)]
|
|
+pub use self::genericaliasobject::*;
|
|
pub use self::import::*;
|
|
pub use self::intrcheck::*;
|
|
pub use self::iterobject::*;
|
|
@@ -439,6 +448,7 @@ pub use self::pystate::*;
|
|
pub use self::pystrtod::*;
|
|
pub use self::pythonrun::*;
|
|
pub use self::rangeobject::*;
|
|
+pub use self::refcount::*;
|
|
pub use self::setobject::*;
|
|
pub use self::sliceobject::*;
|
|
pub use self::structseq::*;
|
|
@@ -479,7 +489,7 @@ mod fileobject;
|
|
mod fileutils;
|
|
mod floatobject;
|
|
// skipped empty frameobject.h
|
|
-// skipped genericaliasobject.h
|
|
+mod genericaliasobject;
|
|
mod import;
|
|
// skipped interpreteridobject.h
|
|
mod intrcheck;
|
|
@@ -531,6 +541,7 @@ mod pystrtod;
|
|
// skipped pythread.h
|
|
// skipped pytime.h
|
|
mod rangeobject;
|
|
+mod refcount;
|
|
mod setobject;
|
|
mod sliceobject;
|
|
mod structseq;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/longobject.rs b/include/pyo3/pyo3-ffi/src/longobject.rs
|
|
index 68b4ecba..eca0af3d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/longobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/longobject.rs
|
|
@@ -4,7 +4,7 @@ use libc::size_t;
|
|
use std::os::raw::{c_char, c_double, c_int, c_long, c_longlong, c_ulong, c_ulonglong, c_void};
|
|
use std::ptr::addr_of_mut;
|
|
|
|
-opaque_struct!(PyLongObject);
|
|
+opaque_struct!(pub PyLongObject);
|
|
|
|
#[inline]
|
|
pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {
|
|
diff --git a/include/pyo3/pyo3-ffi/src/memoryobject.rs b/include/pyo3/pyo3-ffi/src/memoryobject.rs
|
|
index b7ef9e2e..4e1e50c6 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/memoryobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/memoryobject.rs
|
|
@@ -3,11 +3,10 @@ use crate::pyport::Py_ssize_t;
|
|
use std::os::raw::{c_char, c_int};
|
|
use std::ptr::addr_of_mut;
|
|
|
|
+// skipped _PyManagedBuffer_Type
|
|
+
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
- #[cfg(not(Py_LIMITED_API))]
|
|
- pub static mut _PyManagedBuffer_Type: PyTypeObject;
|
|
-
|
|
#[cfg_attr(PyPy, link_name = "PyPyMemoryView_Type")]
|
|
pub static mut PyMemoryView_Type: PyTypeObject;
|
|
}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/methodobject.rs b/include/pyo3/pyo3-ffi/src/methodobject.rs
|
|
index 37e1e206..3dfbbb5a 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/methodobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/methodobject.rs
|
|
@@ -50,7 +50,7 @@ pub type PyCFunctionFast = unsafe extern "C" fn(
|
|
) -> *mut PyObject;
|
|
|
|
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
|
-#[cfg_attr(Py_3_10, deprecated(note = "renamed to `PyCFunctionFast`"))]
|
|
+#[deprecated(note = "renamed to `PyCFunctionFast`")]
|
|
pub type _PyCFunctionFast = PyCFunctionFast;
|
|
|
|
pub type PyCFunctionWithKeywords = unsafe extern "C" fn(
|
|
@@ -68,7 +68,7 @@ pub type PyCFunctionFastWithKeywords = unsafe extern "C" fn(
|
|
) -> *mut PyObject;
|
|
|
|
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
|
-#[cfg_attr(Py_3_10, deprecated(note = "renamed to `PyCFunctionFastWithKeywords`"))]
|
|
+#[deprecated(note = "renamed to `PyCFunctionFastWithKeywords`")]
|
|
pub type _PyCFunctionFastWithKeywords = PyCFunctionFastWithKeywords;
|
|
|
|
#[cfg(all(Py_3_9, not(Py_LIMITED_API)))]
|
|
@@ -153,7 +153,7 @@ pub union PyMethodDefPointer {
|
|
|
|
/// This variant corresponds with [`METH_FASTCALL`].
|
|
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
|
- #[cfg_attr(Py_3_10, deprecated(note = "renamed to `PyCFunctionFast`"))]
|
|
+ #[deprecated(note = "renamed to `PyCFunctionFast`")]
|
|
pub _PyCFunctionFast: PyCFunctionFast,
|
|
|
|
/// This variant corresponds with [`METH_FASTCALL`].
|
|
@@ -162,7 +162,7 @@ pub union PyMethodDefPointer {
|
|
|
|
/// This variant corresponds with [`METH_FASTCALL`] | [`METH_KEYWORDS`].
|
|
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
|
- #[cfg_attr(Py_3_10, deprecated(note = "renamed to `PyCFunctionFastWithKeywords`"))]
|
|
+ #[deprecated(note = "renamed to `PyCFunctionFastWithKeywords`")]
|
|
pub _PyCFunctionFastWithKeywords: PyCFunctionFastWithKeywords,
|
|
|
|
/// This variant corresponds with [`METH_FASTCALL`] | [`METH_KEYWORDS`].
|
|
diff --git a/include/pyo3/pyo3-ffi/src/modsupport.rs b/include/pyo3/pyo3-ffi/src/modsupport.rs
|
|
index 6da2795b..56a68fe2 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/modsupport.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/modsupport.rs
|
|
@@ -37,12 +37,7 @@ extern "C" {
|
|
// skipped Py_VaBuildValue
|
|
|
|
#[cfg(Py_3_13)]
|
|
- pub fn PyModule_Add(
|
|
- module: *mut PyObject,
|
|
- name: *const c_char,
|
|
- value: *mut PyObject,
|
|
- ) -> core::ffi::c_int;
|
|
-
|
|
+ pub fn PyModule_Add(module: *mut PyObject, name: *const c_char, value: *mut PyObject) -> c_int;
|
|
#[cfg(Py_3_10)]
|
|
#[cfg_attr(PyPy, link_name = "PyPyModule_AddObjectRef")]
|
|
pub fn PyModule_AddObjectRef(
|
|
diff --git a/include/pyo3/pyo3-ffi/src/object.rs b/include/pyo3/pyo3-ffi/src/object.rs
|
|
index 51083a8e..5fbf45db 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/object.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/object.rs
|
|
@@ -1,5 +1,7 @@
|
|
use crate::pyport::{Py_hash_t, Py_ssize_t};
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
+use crate::refcount;
|
|
+#[cfg(Py_GIL_DISABLED)]
|
|
use crate::PyMutex;
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
use std::marker::PhantomPinned;
|
|
@@ -7,81 +9,50 @@ use std::mem;
|
|
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void};
|
|
use std::ptr;
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
-use std::sync::atomic::{AtomicIsize, AtomicU32, AtomicU8, Ordering::Relaxed};
|
|
+use std::sync::atomic::{AtomicIsize, AtomicU32, AtomicU8};
|
|
|
|
#[cfg(Py_LIMITED_API)]
|
|
-opaque_struct!(PyTypeObject);
|
|
+opaque_struct!(pub PyTypeObject);
|
|
|
|
#[cfg(not(Py_LIMITED_API))]
|
|
pub use crate::cpython::object::PyTypeObject;
|
|
|
|
-#[cfg(Py_3_12)]
|
|
-const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
|
|
- if cfg!(target_pointer_width = "64") {
|
|
- c_uint::MAX as Py_ssize_t
|
|
- } else {
|
|
- // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h)
|
|
- (c_uint::MAX >> 2) as Py_ssize_t
|
|
- }
|
|
-};
|
|
-
|
|
-#[cfg(Py_GIL_DISABLED)]
|
|
-const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
|
|
-
|
|
-#[allow(clippy::declare_interior_mutable_const)]
|
|
-pub const PyObject_HEAD_INIT: PyObject = PyObject {
|
|
- #[cfg(py_sys_config = "Py_TRACE_REFS")]
|
|
- _ob_next: std::ptr::null_mut(),
|
|
- #[cfg(py_sys_config = "Py_TRACE_REFS")]
|
|
- _ob_prev: std::ptr::null_mut(),
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- ob_tid: 0,
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- _padding: 0,
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- ob_mutex: PyMutex {
|
|
- _bits: AtomicU8::new(0),
|
|
- _pin: PhantomPinned,
|
|
- },
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- ob_gc_bits: 0,
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- ob_ref_local: AtomicU32::new(_Py_IMMORTAL_REFCNT_LOCAL),
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- ob_ref_shared: AtomicIsize::new(0),
|
|
- #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
|
|
- ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },
|
|
- #[cfg(not(Py_3_12))]
|
|
- ob_refcnt: 1,
|
|
- #[cfg(PyPy)]
|
|
- ob_pypy_link: 0,
|
|
- ob_type: std::ptr::null_mut(),
|
|
-};
|
|
-
|
|
-// skipped PyObject_VAR_HEAD
|
|
-// skipped Py_INVALID_SIZE
|
|
-
|
|
-// skipped private _Py_UNOWNED_TID
|
|
+// skip PyObject_HEAD
|
|
|
|
-#[cfg(Py_GIL_DISABLED)]
|
|
-const _Py_REF_SHARED_SHIFT: isize = 2;
|
|
-// skipped private _Py_REF_SHARED_FLAG_MASK
|
|
-
|
|
-// skipped private _Py_REF_SHARED_INIT
|
|
-// skipped private _Py_REF_MAYBE_WEAKREF
|
|
-// skipped private _Py_REF_QUEUED
|
|
-// skipped private _Py_REF_MERGED
|
|
+#[repr(C)]
|
|
+#[derive(Copy, Clone)]
|
|
+#[cfg(all(Py_3_14, not(Py_GIL_DISABLED), target_endian = "big"))]
|
|
+/// This struct is anonymous in CPython, so the name was given by PyO3 because
|
|
+/// Rust structs need a name.
|
|
+pub struct PyObjectObFlagsAndRefcnt {
|
|
+ pub ob_flags: u16,
|
|
+ pub ob_overflow: u16,
|
|
+ pub ob_refcnt: u32,
|
|
+}
|
|
|
|
-// skipped private _Py_REF_SHARED
|
|
+#[repr(C)]
|
|
+#[derive(Copy, Clone)]
|
|
+#[cfg(all(Py_3_14, not(Py_GIL_DISABLED), target_endian = "little"))]
|
|
+/// This struct is anonymous in CPython, so the name was given by PyO3 because
|
|
+/// Rust structs need a name.
|
|
+pub struct PyObjectObFlagsAndRefcnt {
|
|
+ pub ob_refcnt: u32,
|
|
+ pub ob_overflow: u16,
|
|
+ pub ob_flags: u16,
|
|
+}
|
|
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
|
|
/// This union is anonymous in CPython, so the name was given by PyO3 because
|
|
-/// Rust unions need a name.
|
|
+/// Rust union need a name.
|
|
pub union PyObjectObRefcnt {
|
|
+ #[cfg(all(target_pointer_width = "64", Py_3_14))]
|
|
+ pub ob_refcnt_full: crate::PY_INT64_T,
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub refcnt_and_flags: PyObjectObFlagsAndRefcnt,
|
|
pub ob_refcnt: Py_ssize_t,
|
|
- #[cfg(target_pointer_width = "64")]
|
|
+ #[cfg(all(target_pointer_width = "64", not(Py_3_14)))]
|
|
pub ob_refcnt_split: [crate::PY_UINT32_T; 2],
|
|
}
|
|
|
|
@@ -95,6 +66,9 @@ impl std::fmt::Debug for PyObjectObRefcnt {
|
|
#[cfg(all(not(Py_3_12), not(Py_GIL_DISABLED)))]
|
|
pub type PyObjectObRefcnt = Py_ssize_t;
|
|
|
|
+// PyObject_HEAD_INIT comes before the PyObject definition in object.h
|
|
+// but we put it after PyObject because HEAD_INIT uses PyObject
|
|
+
|
|
#[repr(C)]
|
|
#[derive(Debug)]
|
|
pub struct PyObject {
|
|
@@ -104,8 +78,10 @@ pub struct PyObject {
|
|
pub _ob_prev: *mut PyObject,
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
pub ob_tid: libc::uintptr_t,
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
+ #[cfg(all(Py_GIL_DISABLED, not(Py_3_14)))]
|
|
pub _padding: u16,
|
|
+ #[cfg(all(Py_GIL_DISABLED, Py_3_14))]
|
|
+ pub ob_flags: u16,
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
pub ob_mutex: PyMutex, // per-object lock
|
|
#[cfg(Py_GIL_DISABLED)]
|
|
@@ -121,7 +97,41 @@ pub struct PyObject {
|
|
pub ob_type: *mut PyTypeObject,
|
|
}
|
|
|
|
-// skipped private _PyObject_CAST
|
|
+#[allow(clippy::declare_interior_mutable_const)]
|
|
+pub const PyObject_HEAD_INIT: PyObject = PyObject {
|
|
+ #[cfg(py_sys_config = "Py_TRACE_REFS")]
|
|
+ _ob_next: std::ptr::null_mut(),
|
|
+ #[cfg(py_sys_config = "Py_TRACE_REFS")]
|
|
+ _ob_prev: std::ptr::null_mut(),
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ ob_tid: 0,
|
|
+ #[cfg(all(Py_GIL_DISABLED, Py_3_14))]
|
|
+ ob_flags: 0,
|
|
+ #[cfg(all(Py_GIL_DISABLED, not(Py_3_14)))]
|
|
+ _padding: 0,
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ ob_mutex: PyMutex {
|
|
+ _bits: AtomicU8::new(0),
|
|
+ _pin: PhantomPinned,
|
|
+ },
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ ob_gc_bits: 0,
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ ob_ref_local: AtomicU32::new(refcount::_Py_IMMORTAL_REFCNT_LOCAL),
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ ob_ref_shared: AtomicIsize::new(0),
|
|
+ #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
|
|
+ ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },
|
|
+ #[cfg(not(Py_3_12))]
|
|
+ ob_refcnt: 1,
|
|
+ #[cfg(PyPy)]
|
|
+ ob_pypy_link: 0,
|
|
+ ob_type: std::ptr::null_mut(),
|
|
+};
|
|
+
|
|
+// skipped _Py_UNOWNED_TID
|
|
+
|
|
+// skipped _PyObject_CAST
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug)]
|
|
@@ -150,41 +160,23 @@ extern "C" {
|
|
pub fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int;
|
|
}
|
|
|
|
-// skipped private _Py_GetThreadLocal_Addr
|
|
+// skipped _Py_GetThreadLocal_Addr
|
|
|
|
-// skipped private _Py_ThreadId
|
|
+// skipped _Py_ThreadID
|
|
|
|
-// skipped private _Py_IsOwnedByCurrentThread
|
|
+// skipped _Py_IsOwnedByCurrentThread
|
|
|
|
-#[inline]
|
|
-pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
|
|
- #[cfg(Py_GIL_DISABLED)]
|
|
- {
|
|
- let local = (*ob).ob_ref_local.load(Relaxed);
|
|
- if local == _Py_IMMORTAL_REFCNT_LOCAL {
|
|
- return _Py_IMMORTAL_REFCNT;
|
|
- }
|
|
- let shared = (*ob).ob_ref_shared.load(Relaxed);
|
|
- local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
|
|
- }
|
|
-
|
|
- #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
|
|
- {
|
|
- (*ob).ob_refcnt.ob_refcnt
|
|
- }
|
|
-
|
|
- #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
|
|
- {
|
|
- (*ob).ob_refcnt
|
|
- }
|
|
+#[cfg(GraalPy)]
|
|
+extern "C" {
|
|
+ #[cfg(GraalPy)]
|
|
+ fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;
|
|
|
|
- #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
|
|
- {
|
|
- _Py_REFCNT(ob)
|
|
- }
|
|
+ #[cfg(GraalPy)]
|
|
+ fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;
|
|
}
|
|
|
|
#[inline]
|
|
+#[cfg(not(Py_3_14))]
|
|
pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
|
|
#[cfg(not(GraalPy))]
|
|
return (*ob).ob_type;
|
|
@@ -192,6 +184,15 @@ pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
|
|
return _Py_TYPE(ob);
|
|
}
|
|
|
|
+#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
+#[cfg(Py_3_14)]
|
|
+extern "C" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPy_TYPE")]
|
|
+ pub fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject;
|
|
+}
|
|
+
|
|
+// skip _Py_TYPE compat shim
|
|
+
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
#[cfg_attr(PyPy, link_name = "PyPyLong_Type")]
|
|
@@ -212,29 +213,11 @@ pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
|
|
_Py_SIZE(ob)
|
|
}
|
|
|
|
-#[inline(always)]
|
|
-#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
|
|
-pub unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
|
|
- #[cfg(target_pointer_width = "64")]
|
|
- {
|
|
- (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
|
|
- }
|
|
-
|
|
- #[cfg(target_pointer_width = "32")]
|
|
- {
|
|
- ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
|
|
- }
|
|
-}
|
|
-
|
|
#[inline]
|
|
pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
|
|
(Py_TYPE(ob) == tp) as c_int
|
|
}
|
|
|
|
-// skipped _Py_SetRefCnt
|
|
-
|
|
-// skipped Py_SET_REFCNT
|
|
-
|
|
// skipped Py_SET_TYPE
|
|
|
|
// skipped Py_SET_SIZE
|
|
@@ -436,7 +419,7 @@ extern "C" {
|
|
arg2: *const c_char,
|
|
arg3: *mut PyObject,
|
|
) -> c_int;
|
|
- #[cfg(any(Py_3_13, PyPy))] // CPython defined in 3.12 as an inline function in abstract.h
|
|
+ #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_DelAttrString")]
|
|
pub fn PyObject_DelAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrString")]
|
|
@@ -460,7 +443,7 @@ extern "C" {
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_SetAttr")]
|
|
pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject)
|
|
-> c_int;
|
|
- #[cfg(any(Py_3_13, PyPy))] // CPython defined in 3.12 as an inline function in abstract.h
|
|
+ #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_DelAttr")]
|
|
pub fn PyObject_DelAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
|
|
#[cfg_attr(PyPy, link_name = "PyPyObject_HasAttr")]
|
|
@@ -586,222 +569,6 @@ pub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) {
|
|
pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;
|
|
pub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18;
|
|
|
|
-extern "C" {
|
|
- #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
- fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
|
|
- #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
- fn _Py_INCREF_IncRefTotal();
|
|
- #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
- fn _Py_DECREF_DecRefTotal();
|
|
-
|
|
- #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
|
|
- fn _Py_Dealloc(arg1: *mut PyObject);
|
|
-
|
|
- #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
|
|
- #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
|
|
- pub fn Py_IncRef(o: *mut PyObject);
|
|
- #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
|
|
- #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
|
|
- pub fn Py_DecRef(o: *mut PyObject);
|
|
-
|
|
- #[cfg(all(Py_3_10, not(PyPy)))]
|
|
- fn _Py_IncRef(o: *mut PyObject);
|
|
- #[cfg(all(Py_3_10, not(PyPy)))]
|
|
- fn _Py_DecRef(o: *mut PyObject);
|
|
-
|
|
- #[cfg(GraalPy)]
|
|
- fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
|
|
-
|
|
- #[cfg(GraalPy)]
|
|
- fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;
|
|
-
|
|
- #[cfg(GraalPy)]
|
|
- fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;
|
|
-}
|
|
-
|
|
-#[inline(always)]
|
|
-pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
|
- // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
|
|
- // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
|
|
- #[cfg(any(
|
|
- Py_GIL_DISABLED,
|
|
- Py_LIMITED_API,
|
|
- py_sys_config = "Py_REF_DEBUG",
|
|
- GraalPy
|
|
- ))]
|
|
- {
|
|
- // _Py_IncRef was added to the ABI in 3.10; skips null checks
|
|
- #[cfg(all(Py_3_10, not(PyPy)))]
|
|
- {
|
|
- _Py_IncRef(op);
|
|
- }
|
|
-
|
|
- #[cfg(any(not(Py_3_10), PyPy))]
|
|
- {
|
|
- Py_IncRef(op);
|
|
- }
|
|
- }
|
|
-
|
|
- // version-specific builds are allowed to directly manipulate the reference count
|
|
- #[cfg(not(any(
|
|
- Py_GIL_DISABLED,
|
|
- Py_LIMITED_API,
|
|
- py_sys_config = "Py_REF_DEBUG",
|
|
- GraalPy
|
|
- )))]
|
|
- {
|
|
- #[cfg(all(Py_3_12, target_pointer_width = "64"))]
|
|
- {
|
|
- let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
|
|
- let new_refcnt = cur_refcnt.wrapping_add(1);
|
|
- if new_refcnt == 0 {
|
|
- return;
|
|
- }
|
|
- (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
|
|
- }
|
|
-
|
|
- #[cfg(all(Py_3_12, target_pointer_width = "32"))]
|
|
- {
|
|
- if _Py_IsImmortal(op) != 0 {
|
|
- return;
|
|
- }
|
|
- (*op).ob_refcnt.ob_refcnt += 1
|
|
- }
|
|
-
|
|
- #[cfg(not(Py_3_12))]
|
|
- {
|
|
- (*op).ob_refcnt += 1
|
|
- }
|
|
-
|
|
- // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue
|
|
- // or submit a PR supporting Py_STATS build option and pystats.h
|
|
- }
|
|
-}
|
|
-
|
|
-#[inline(always)]
|
|
-#[cfg_attr(
|
|
- all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
|
|
- track_caller
|
|
-)]
|
|
-pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
|
- // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
|
|
- // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts
|
|
- // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
|
|
- #[cfg(any(
|
|
- Py_GIL_DISABLED,
|
|
- Py_LIMITED_API,
|
|
- all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
|
|
- GraalPy
|
|
- ))]
|
|
- {
|
|
- // _Py_DecRef was added to the ABI in 3.10; skips null checks
|
|
- #[cfg(all(Py_3_10, not(PyPy)))]
|
|
- {
|
|
- _Py_DecRef(op);
|
|
- }
|
|
-
|
|
- #[cfg(any(not(Py_3_10), PyPy))]
|
|
- {
|
|
- Py_DecRef(op);
|
|
- }
|
|
- }
|
|
-
|
|
- #[cfg(not(any(
|
|
- Py_GIL_DISABLED,
|
|
- Py_LIMITED_API,
|
|
- all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
|
|
- GraalPy
|
|
- )))]
|
|
- {
|
|
- #[cfg(Py_3_12)]
|
|
- if _Py_IsImmortal(op) != 0 {
|
|
- return;
|
|
- }
|
|
-
|
|
- // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue
|
|
- // or submit a PR supporting Py_STATS build option and pystats.h
|
|
-
|
|
- #[cfg(py_sys_config = "Py_REF_DEBUG")]
|
|
- _Py_DECREF_DecRefTotal();
|
|
-
|
|
- #[cfg(Py_3_12)]
|
|
- {
|
|
- (*op).ob_refcnt.ob_refcnt -= 1;
|
|
-
|
|
- #[cfg(py_sys_config = "Py_REF_DEBUG")]
|
|
- if (*op).ob_refcnt.ob_refcnt < 0 {
|
|
- let location = std::panic::Location::caller();
|
|
- let filename = std::ffi::CString::new(location.file()).unwrap();
|
|
- _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
|
|
- }
|
|
-
|
|
- if (*op).ob_refcnt.ob_refcnt == 0 {
|
|
- _Py_Dealloc(op);
|
|
- }
|
|
- }
|
|
-
|
|
- #[cfg(not(Py_3_12))]
|
|
- {
|
|
- (*op).ob_refcnt -= 1;
|
|
-
|
|
- if (*op).ob_refcnt == 0 {
|
|
- _Py_Dealloc(op);
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#[inline]
|
|
-pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
|
|
- let tmp = *op;
|
|
- if !tmp.is_null() {
|
|
- *op = ptr::null_mut();
|
|
- Py_DECREF(tmp);
|
|
- }
|
|
-}
|
|
-
|
|
-#[inline]
|
|
-pub unsafe fn Py_XINCREF(op: *mut PyObject) {
|
|
- if !op.is_null() {
|
|
- Py_INCREF(op)
|
|
- }
|
|
-}
|
|
-
|
|
-#[inline]
|
|
-pub unsafe fn Py_XDECREF(op: *mut PyObject) {
|
|
- if !op.is_null() {
|
|
- Py_DECREF(op)
|
|
- }
|
|
-}
|
|
-
|
|
-extern "C" {
|
|
- #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
|
|
- #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
- pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
|
|
- #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
|
|
- #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
- pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
|
|
-}
|
|
-
|
|
-// macro _Py_NewRef not public; reimplemented directly inside Py_NewRef here
|
|
-// macro _Py_XNewRef not public; reimplemented directly inside Py_XNewRef here
|
|
-
|
|
-#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
|
|
-#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
-#[inline]
|
|
-pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
|
|
- Py_INCREF(obj);
|
|
- obj
|
|
-}
|
|
-
|
|
-#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
|
|
-#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
-#[inline]
|
|
-pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
|
|
- Py_XINCREF(obj);
|
|
- obj
|
|
-}
|
|
-
|
|
#[cfg(Py_3_13)]
|
|
pub const Py_CONSTANT_NONE: c_uint = 0;
|
|
#[cfg(Py_3_13)]
|
|
@@ -942,4 +709,7 @@ extern "C" {
|
|
arg1: *mut crate::PyTypeObject,
|
|
arg2: *mut crate::PyModuleDef,
|
|
) -> *mut PyObject;
|
|
+
|
|
+ #[cfg(Py_3_14)]
|
|
+ pub fn PyType_Freeze(tp: *mut crate::PyTypeObject) -> c_int;
|
|
}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pyarena.rs b/include/pyo3/pyo3-ffi/src/pyarena.rs
|
|
index 87d5f28a..1200de3d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pyarena.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pyarena.rs
|
|
@@ -1 +1 @@
|
|
-opaque_struct!(PyArena);
|
|
+opaque_struct!(pub PyArena);
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pybuffer.rs b/include/pyo3/pyo3-ffi/src/pybuffer.rs
|
|
index 50bf4e61..de706759 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pybuffer.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pybuffer.rs
|
|
@@ -103,7 +103,11 @@ extern "C" {
|
|
}
|
|
|
|
/// Maximum number of dimensions
|
|
-pub const PyBUF_MAX_NDIM: c_int = if cfg!(PyPy) { 36 } else { 64 };
|
|
+pub const PyBUF_MAX_NDIM: usize = if cfg!(all(PyPy, not(Py_3_11))) {
|
|
+ 36
|
|
+} else {
|
|
+ 64
|
|
+};
|
|
|
|
/* Flags for getting buffers */
|
|
pub const PyBUF_SIMPLE: c_int = 0;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pyerrors.rs b/include/pyo3/pyo3-ffi/src/pyerrors.rs
|
|
index 6c9313c4..d341239a 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pyerrors.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pyerrors.rs
|
|
@@ -116,6 +116,7 @@ extern "C" {
|
|
#[cfg_attr(PyPy, link_name = "PyPyExc_BaseException")]
|
|
pub static mut PyExc_BaseException: *mut PyObject;
|
|
#[cfg(Py_3_11)]
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyExc_BaseExceptionGroup")]
|
|
pub static mut PyExc_BaseExceptionGroup: *mut PyObject;
|
|
#[cfg_attr(PyPy, link_name = "PyPyExc_Exception")]
|
|
pub static mut PyExc_Exception: *mut PyObject;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pyframe.rs b/include/pyo3/pyo3-ffi/src/pyframe.rs
|
|
index 4dd3d2b3..1693b20b 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pyframe.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pyframe.rs
|
|
@@ -6,7 +6,7 @@ use crate::PyFrameObject;
|
|
use std::os::raw::c_int;
|
|
|
|
#[cfg(Py_LIMITED_API)]
|
|
-opaque_struct!(PyFrameObject);
|
|
+opaque_struct!(pub PyFrameObject);
|
|
|
|
extern "C" {
|
|
pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pyhash.rs b/include/pyo3/pyo3-ffi/src/pyhash.rs
|
|
index 8b0b6771..074278dd 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pyhash.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pyhash.rs
|
|
@@ -1,7 +1,5 @@
|
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
|
use crate::pyport::{Py_hash_t, Py_ssize_t};
|
|
-#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
|
|
-use std::os::raw::c_char;
|
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
|
use std::os::raw::c_void;
|
|
|
|
@@ -12,11 +10,8 @@ extern "C" {
|
|
// skipped non-limited _Py_HashPointer
|
|
// skipped non-limited _Py_HashPointerRaw
|
|
|
|
- #[cfg(not(all(Py_3_14, any(Py_LIMITED_API, PyPy))))]
|
|
+ #[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
|
pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t;
|
|
-
|
|
- #[cfg(Py_3_14)]
|
|
- pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t;
|
|
}
|
|
|
|
pub const _PyHASH_MULTIPLIER: c_ulong = 1000003;
|
|
@@ -25,29 +20,6 @@ pub const _PyHASH_MULTIPLIER: c_ulong = 1000003;
|
|
|
|
// skipped non-limited _Py_HashSecret_t
|
|
|
|
-#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
|
|
-#[repr(C)]
|
|
-#[derive(Copy, Clone)]
|
|
-pub struct PyHash_FuncDef {
|
|
- pub hash: Option<extern "C" fn(arg1: *const c_void, arg2: Py_ssize_t) -> Py_hash_t>,
|
|
- pub name: *const c_char,
|
|
- pub hash_bits: c_int,
|
|
- pub seed_bits: c_int,
|
|
-}
|
|
-
|
|
-#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
|
|
-impl Default for PyHash_FuncDef {
|
|
- #[inline]
|
|
- fn default() -> Self {
|
|
- unsafe { std::mem::zeroed() }
|
|
- }
|
|
-}
|
|
-
|
|
-extern "C" {
|
|
- #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
|
|
- pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef;
|
|
-}
|
|
-
|
|
// skipped Py_HASH_CUTOFF
|
|
|
|
pub const Py_HASH_EXTERNAL: c_int = 0;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pyport.rs b/include/pyo3/pyo3-ffi/src/pyport.rs
|
|
index a144c67f..e524831d 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pyport.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pyport.rs
|
|
@@ -1,3 +1,8 @@
|
|
+// NB libc does not define this constant on all platforms, so we hard code it
|
|
+// like CPython does.
|
|
+// https://github.com/python/cpython/blob/d8b9011702443bb57579f8834f3effe58e290dfc/Include/pyport.h#L372
|
|
+pub const INT_MAX: std::os::raw::c_int = 2147483647;
|
|
+
|
|
pub type PY_UINT32_T = u32;
|
|
pub type PY_UINT64_T = u64;
|
|
|
|
@@ -11,8 +16,8 @@ pub type Py_ssize_t = ::libc::ssize_t;
|
|
pub type Py_hash_t = Py_ssize_t;
|
|
pub type Py_uhash_t = ::libc::size_t;
|
|
|
|
-pub const PY_SSIZE_T_MIN: Py_ssize_t = isize::MIN as Py_ssize_t;
|
|
-pub const PY_SSIZE_T_MAX: Py_ssize_t = isize::MAX as Py_ssize_t;
|
|
+pub const PY_SSIZE_T_MIN: Py_ssize_t = Py_ssize_t::MIN;
|
|
+pub const PY_SSIZE_T_MAX: Py_ssize_t = Py_ssize_t::MAX;
|
|
|
|
#[cfg(target_endian = "big")]
|
|
pub const PY_BIG_ENDIAN: usize = 1;
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pystate.rs b/include/pyo3/pyo3-ffi/src/pystate.rs
|
|
index 23aeea3a..cc16e554 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pystate.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pystate.rs
|
|
@@ -1,3 +1,5 @@
|
|
+#[cfg(all(Py_3_10, not(PyPy), not(Py_LIMITED_API)))]
|
|
+use crate::frameobject::PyFrameObject;
|
|
use crate::moduleobject::PyModuleDef;
|
|
use crate::object::PyObject;
|
|
use std::os::raw::c_int;
|
|
@@ -7,8 +9,8 @@ use std::os::raw::c_long;
|
|
|
|
pub const MAX_CO_EXTRA_USERS: c_int = 255;
|
|
|
|
-opaque_struct!(PyThreadState);
|
|
-opaque_struct!(PyInterpreterState);
|
|
+opaque_struct!(pub PyThreadState);
|
|
+opaque_struct!(pub PyInterpreterState);
|
|
|
|
extern "C" {
|
|
#[cfg(not(PyPy))]
|
|
@@ -63,9 +65,14 @@ extern "C" {
|
|
}
|
|
|
|
// skipped non-limited / 3.9 PyThreadState_GetInterpreter
|
|
-// skipped non-limited / 3.9 PyThreadState_GetFrame
|
|
// skipped non-limited / 3.9 PyThreadState_GetID
|
|
|
|
+extern "C" {
|
|
+ // PyThreadState_GetFrame
|
|
+ #[cfg(all(Py_3_10, not(PyPy), not(Py_LIMITED_API)))]
|
|
+ pub fn PyThreadState_GetFrame(arg1: *mut PyThreadState) -> *mut PyFrameObject;
|
|
+}
|
|
+
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
pub enum PyGILState_STATE {
|
|
@@ -73,9 +80,70 @@ pub enum PyGILState_STATE {
|
|
PyGILState_UNLOCKED,
|
|
}
|
|
|
|
+#[cfg(not(Py_3_14))]
|
|
+struct HangThread;
|
|
+
|
|
+#[cfg(not(Py_3_14))]
|
|
+impl Drop for HangThread {
|
|
+ fn drop(&mut self) {
|
|
+ loop {
|
|
+ std::thread::park(); // Block forever.
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+// The PyGILState_Ensure function will call pthread_exit during interpreter shutdown,
|
|
+// which causes undefined behavior. Redirect to the "safe" version that hangs instead,
|
|
+// as Python 3.14 does.
|
|
+//
|
|
+// See https://github.com/rust-lang/rust/issues/135929
|
|
+
|
|
+// C-unwind only supported (and necessary) since 1.71. Python 3.14+ does not do
|
|
+// pthread_exit from PyGILState_Ensure (https://github.com/python/cpython/issues/87135).
|
|
+mod raw {
|
|
+ #[cfg(all(not(Py_3_14), rustc_has_extern_c_unwind))]
|
|
+ extern "C-unwind" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
|
|
+ pub fn PyGILState_Ensure() -> super::PyGILState_STATE;
|
|
+ }
|
|
+
|
|
+ #[cfg(not(all(not(Py_3_14), rustc_has_extern_c_unwind)))]
|
|
+ extern "C" {
|
|
+ #[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
|
|
+ pub fn PyGILState_Ensure() -> super::PyGILState_STATE;
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg(not(Py_3_14))]
|
|
+pub unsafe extern "C" fn PyGILState_Ensure() -> PyGILState_STATE {
|
|
+ let guard = HangThread;
|
|
+ // If `PyGILState_Ensure` calls `pthread_exit`, which it does on Python < 3.14
|
|
+ // when the interpreter is shutting down, this will cause a forced unwind.
|
|
+ // doing a forced unwind through a function with a Rust destructor is unspecified
|
|
+ // behavior.
|
|
+ //
|
|
+ // However, currently it runs the destructor, which will cause the thread to
|
|
+ // hang as it should.
|
|
+ //
|
|
+ // And if we don't catch the unwinding here, then one of our callers probably has a destructor,
|
|
+ // so it's unspecified behavior anyway, and on many configurations causes the process to abort.
|
|
+ //
|
|
+ // The alternative is for pyo3 to contain custom C or C++ code that catches the `pthread_exit`,
|
|
+ // but that's also annoying from a portability point of view.
|
|
+ //
|
|
+ // On Windows, `PyGILState_Ensure` calls `_endthreadex` instead, which AFAICT can't be caught
|
|
+ // and therefore will cause unsafety if there are pinned objects on the stack. AFAICT there's
|
|
+ // nothing we can do it other than waiting for Python 3.14 or not using Windows. At least,
|
|
+ // if there is nothing pinned on the stack, it won't cause the process to crash.
|
|
+ let ret: PyGILState_STATE = raw::PyGILState_Ensure();
|
|
+ std::mem::forget(guard);
|
|
+ ret
|
|
+}
|
|
+
|
|
+#[cfg(Py_3_14)]
|
|
+pub use self::raw::PyGILState_Ensure;
|
|
+
|
|
extern "C" {
|
|
- #[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
|
|
- pub fn PyGILState_Ensure() -> PyGILState_STATE;
|
|
#[cfg_attr(PyPy, link_name = "PyPyGILState_Release")]
|
|
pub fn PyGILState_Release(arg1: PyGILState_STATE);
|
|
#[cfg(not(PyPy))]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/pythonrun.rs b/include/pyo3/pyo3-ffi/src/pythonrun.rs
|
|
index e7ea2d2e..80209b58 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/pythonrun.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/pythonrun.rs
|
|
@@ -49,12 +49,12 @@ pub const PYOS_STACK_MARGIN: c_int = 2048;
|
|
// skipped PyOS_CheckStack under Microsoft C
|
|
|
|
#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]
|
|
-opaque_struct!(_mod);
|
|
+opaque_struct!(pub _mod);
|
|
|
|
#[cfg(not(any(PyPy, Py_3_10)))]
|
|
-opaque_struct!(symtable);
|
|
+opaque_struct!(pub symtable);
|
|
#[cfg(not(any(PyPy, Py_3_10)))]
|
|
-opaque_struct!(_node);
|
|
+opaque_struct!(pub _node);
|
|
|
|
#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]
|
|
#[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/refcount.rs b/include/pyo3/pyo3-ffi/src/refcount.rs
|
|
new file mode 100644
|
|
index 00000000..fcb5f45b
|
|
--- /dev/null
|
|
+++ b/include/pyo3/pyo3-ffi/src/refcount.rs
|
|
@@ -0,0 +1,369 @@
|
|
+use crate::pyport::Py_ssize_t;
|
|
+use crate::PyObject;
|
|
+#[cfg(py_sys_config = "Py_REF_DEBUG")]
|
|
+use std::os::raw::c_char;
|
|
+#[cfg(Py_3_12)]
|
|
+use std::os::raw::c_int;
|
|
+#[cfg(all(Py_3_14, any(not(Py_GIL_DISABLED), target_pointer_width = "32")))]
|
|
+use std::os::raw::c_long;
|
|
+#[cfg(any(Py_GIL_DISABLED, all(Py_3_12, not(Py_3_14))))]
|
|
+use std::os::raw::c_uint;
|
|
+#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
|
|
+use std::os::raw::c_ulong;
|
|
+use std::ptr;
|
|
+#[cfg(Py_GIL_DISABLED)]
|
|
+use std::sync::atomic::Ordering::Relaxed;
|
|
+
|
|
+#[cfg(Py_3_14)]
|
|
+const _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 7;
|
|
+
|
|
+#[cfg(all(Py_3_12, not(Py_3_14)))]
|
|
+const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
|
|
+ if cfg!(target_pointer_width = "64") {
|
|
+ c_uint::MAX as Py_ssize_t
|
|
+ } else {
|
|
+ // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h)
|
|
+ (c_uint::MAX >> 2) as Py_ssize_t
|
|
+ }
|
|
+};
|
|
+
|
|
+// comments in Python.h about the choices for these constants
|
|
+
|
|
+#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
|
|
+const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
|
|
+ if cfg!(target_pointer_width = "64") {
|
|
+ ((3 as c_ulong) << (30 as c_ulong)) as Py_ssize_t
|
|
+ } else {
|
|
+ ((5 as c_long) << (28 as c_long)) as Py_ssize_t
|
|
+ }
|
|
+};
|
|
+
|
|
+#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
|
|
+const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
|
|
+ if cfg!(target_pointer_width = "64") {
|
|
+ _Py_IMMORTAL_INITIAL_REFCNT
|
|
+ | ((_Py_STATICALLY_ALLOCATED_FLAG as Py_ssize_t) << (32 as Py_ssize_t))
|
|
+ } else {
|
|
+ ((7 as c_long) << (28 as c_long)) as Py_ssize_t
|
|
+ }
|
|
+};
|
|
+
|
|
+#[cfg(all(Py_3_14, target_pointer_width = "32"))]
|
|
+const _Py_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t = ((1 as c_long) << (30 as c_long)) as Py_ssize_t;
|
|
+
|
|
+#[cfg(all(Py_3_14, target_pointer_width = "32"))]
|
|
+const _Py_STATIC_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t =
|
|
+ ((6 as c_long) << (28 as c_long)) as Py_ssize_t;
|
|
+
|
|
+#[cfg(all(Py_3_14, Py_GIL_DISABLED))]
|
|
+const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = c_uint::MAX as Py_ssize_t;
|
|
+
|
|
+#[cfg(Py_GIL_DISABLED)]
|
|
+pub(crate) const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
|
|
+
|
|
+#[cfg(Py_GIL_DISABLED)]
|
|
+const _Py_REF_SHARED_SHIFT: isize = 2;
|
|
+// skipped private _Py_REF_SHARED_FLAG_MASK
|
|
+
|
|
+// skipped private _Py_REF_SHARED_INIT
|
|
+// skipped private _Py_REF_MAYBE_WEAKREF
|
|
+// skipped private _Py_REF_QUEUED
|
|
+// skipped private _Py_REF_MERGED
|
|
+
|
|
+// skipped private _Py_REF_SHARED
|
|
+
|
|
+extern "C" {
|
|
+ #[cfg(all(Py_3_14, Py_LIMITED_API))]
|
|
+ pub fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t;
|
|
+}
|
|
+
|
|
+#[cfg(not(all(Py_3_14, Py_LIMITED_API)))]
|
|
+#[inline]
|
|
+pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ {
|
|
+ let local = (*ob).ob_ref_local.load(Relaxed);
|
|
+ if local == _Py_IMMORTAL_REFCNT_LOCAL {
|
|
+ #[cfg(not(Py_3_14))]
|
|
+ return _Py_IMMORTAL_REFCNT;
|
|
+ #[cfg(Py_3_14)]
|
|
+ return _Py_IMMORTAL_INITIAL_REFCNT;
|
|
+ }
|
|
+ let shared = (*ob).ob_ref_shared.load(Relaxed);
|
|
+ local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
|
|
+ }
|
|
+
|
|
+ #[cfg(all(Py_LIMITED_API, Py_3_14))]
|
|
+ {
|
|
+ Py_REFCNT(ob)
|
|
+ }
|
|
+
|
|
+ #[cfg(all(not(Py_GIL_DISABLED), not(all(Py_LIMITED_API, Py_3_14)), Py_3_12))]
|
|
+ {
|
|
+ (*ob).ob_refcnt.ob_refcnt
|
|
+ }
|
|
+
|
|
+ #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
|
|
+ {
|
|
+ (*ob).ob_refcnt
|
|
+ }
|
|
+
|
|
+ #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
|
|
+ {
|
|
+ _Py_REFCNT(ob)
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg(Py_3_12)]
|
|
+#[inline(always)]
|
|
+unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
|
|
+ #[cfg(all(target_pointer_width = "64", not(Py_GIL_DISABLED)))]
|
|
+ {
|
|
+ (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
|
|
+ }
|
|
+
|
|
+ #[cfg(all(target_pointer_width = "32", not(Py_GIL_DISABLED)))]
|
|
+ {
|
|
+ #[cfg(not(Py_3_14))]
|
|
+ {
|
|
+ ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
|
|
+ }
|
|
+
|
|
+ #[cfg(Py_3_14)]
|
|
+ {
|
|
+ ((*op).ob_refcnt.ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT) as c_int
|
|
+ }
|
|
+ }
|
|
+
|
|
+ #[cfg(Py_GIL_DISABLED)]
|
|
+ {
|
|
+ ((*op).ob_ref_local.load(Relaxed) == _Py_IMMORTAL_REFCNT_LOCAL) as c_int
|
|
+ }
|
|
+}
|
|
+
|
|
+// skipped _Py_IsStaticImmortal
|
|
+
|
|
+// TODO: Py_SET_REFCNT
|
|
+
|
|
+extern "C" {
|
|
+ #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
+ fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
|
|
+ #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
+ fn _Py_INCREF_IncRefTotal();
|
|
+ #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
|
|
+ fn _Py_DECREF_DecRefTotal();
|
|
+
|
|
+ #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
|
|
+ fn _Py_Dealloc(arg1: *mut PyObject);
|
|
+
|
|
+ #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
|
|
+ #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
|
|
+ pub fn Py_IncRef(o: *mut PyObject);
|
|
+ #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
|
|
+ #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
|
|
+ pub fn Py_DecRef(o: *mut PyObject);
|
|
+
|
|
+ #[cfg(all(Py_3_10, not(PyPy)))]
|
|
+ fn _Py_IncRef(o: *mut PyObject);
|
|
+ #[cfg(all(Py_3_10, not(PyPy)))]
|
|
+ fn _Py_DecRef(o: *mut PyObject);
|
|
+
|
|
+ #[cfg(GraalPy)]
|
|
+ fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
|
|
+}
|
|
+
|
|
+#[inline(always)]
|
|
+pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
|
+ // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
|
|
+ // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
|
|
+ #[cfg(any(
|
|
+ Py_GIL_DISABLED,
|
|
+ Py_LIMITED_API,
|
|
+ py_sys_config = "Py_REF_DEBUG",
|
|
+ GraalPy
|
|
+ ))]
|
|
+ {
|
|
+ // _Py_IncRef was added to the ABI in 3.10; skips null checks
|
|
+ #[cfg(all(Py_3_10, not(PyPy)))]
|
|
+ {
|
|
+ _Py_IncRef(op);
|
|
+ }
|
|
+
|
|
+ #[cfg(any(not(Py_3_10), PyPy))]
|
|
+ {
|
|
+ Py_IncRef(op);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // version-specific builds are allowed to directly manipulate the reference count
|
|
+ #[cfg(not(any(
|
|
+ Py_GIL_DISABLED,
|
|
+ Py_LIMITED_API,
|
|
+ py_sys_config = "Py_REF_DEBUG",
|
|
+ GraalPy
|
|
+ )))]
|
|
+ {
|
|
+ #[cfg(all(Py_3_14, target_pointer_width = "64"))]
|
|
+ {
|
|
+ let cur_refcnt = (*op).ob_refcnt.ob_refcnt;
|
|
+ if (cur_refcnt as i32) < 0 {
|
|
+ return;
|
|
+ }
|
|
+ (*op).ob_refcnt.ob_refcnt = cur_refcnt.wrapping_add(1);
|
|
+ }
|
|
+
|
|
+ #[cfg(all(Py_3_12, not(Py_3_14), target_pointer_width = "64"))]
|
|
+ {
|
|
+ let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
|
|
+ let new_refcnt = cur_refcnt.wrapping_add(1);
|
|
+ if new_refcnt == 0 {
|
|
+ return;
|
|
+ }
|
|
+ (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
|
|
+ }
|
|
+
|
|
+ #[cfg(all(Py_3_12, target_pointer_width = "32"))]
|
|
+ {
|
|
+ if _Py_IsImmortal(op) != 0 {
|
|
+ return;
|
|
+ }
|
|
+ (*op).ob_refcnt.ob_refcnt += 1
|
|
+ }
|
|
+
|
|
+ #[cfg(not(Py_3_12))]
|
|
+ {
|
|
+ (*op).ob_refcnt += 1
|
|
+ }
|
|
+
|
|
+ // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue
|
|
+ // or submit a PR supporting Py_STATS build option and pystats.h
|
|
+ }
|
|
+}
|
|
+
|
|
+// skipped _Py_DecRefShared
|
|
+// skipped _Py_DecRefSharedDebug
|
|
+// skipped _Py_MergeZeroLocalRefcount
|
|
+
|
|
+#[inline(always)]
|
|
+#[cfg_attr(
|
|
+ all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
|
|
+ track_caller
|
|
+)]
|
|
+pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
|
+ // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
|
|
+ // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts
|
|
+ // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
|
|
+ #[cfg(any(
|
|
+ Py_GIL_DISABLED,
|
|
+ Py_LIMITED_API,
|
|
+ all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
|
|
+ GraalPy
|
|
+ ))]
|
|
+ {
|
|
+ // _Py_DecRef was added to the ABI in 3.10; skips null checks
|
|
+ #[cfg(all(Py_3_10, not(PyPy)))]
|
|
+ {
|
|
+ _Py_DecRef(op);
|
|
+ }
|
|
+
|
|
+ #[cfg(any(not(Py_3_10), PyPy))]
|
|
+ {
|
|
+ Py_DecRef(op);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ #[cfg(not(any(
|
|
+ Py_GIL_DISABLED,
|
|
+ Py_LIMITED_API,
|
|
+ all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
|
|
+ GraalPy
|
|
+ )))]
|
|
+ {
|
|
+ #[cfg(Py_3_12)]
|
|
+ if _Py_IsImmortal(op) != 0 {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue
|
|
+ // or submit a PR supporting Py_STATS build option and pystats.h
|
|
+
|
|
+ #[cfg(py_sys_config = "Py_REF_DEBUG")]
|
|
+ _Py_DECREF_DecRefTotal();
|
|
+
|
|
+ #[cfg(Py_3_12)]
|
|
+ {
|
|
+ (*op).ob_refcnt.ob_refcnt -= 1;
|
|
+
|
|
+ #[cfg(py_sys_config = "Py_REF_DEBUG")]
|
|
+ if (*op).ob_refcnt.ob_refcnt < 0 {
|
|
+ let location = std::panic::Location::caller();
|
|
+ let filename = std::ffi::CString::new(location.file()).unwrap();
|
|
+ _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
|
|
+ }
|
|
+
|
|
+ if (*op).ob_refcnt.ob_refcnt == 0 {
|
|
+ _Py_Dealloc(op);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ #[cfg(not(Py_3_12))]
|
|
+ {
|
|
+ (*op).ob_refcnt -= 1;
|
|
+
|
|
+ if (*op).ob_refcnt == 0 {
|
|
+ _Py_Dealloc(op);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#[inline]
|
|
+pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
|
|
+ let tmp = *op;
|
|
+ if !tmp.is_null() {
|
|
+ *op = ptr::null_mut();
|
|
+ Py_DECREF(tmp);
|
|
+ }
|
|
+}
|
|
+
|
|
+#[inline]
|
|
+pub unsafe fn Py_XINCREF(op: *mut PyObject) {
|
|
+ if !op.is_null() {
|
|
+ Py_INCREF(op)
|
|
+ }
|
|
+}
|
|
+
|
|
+#[inline]
|
|
+pub unsafe fn Py_XDECREF(op: *mut PyObject) {
|
|
+ if !op.is_null() {
|
|
+ Py_DECREF(op)
|
|
+ }
|
|
+}
|
|
+
|
|
+extern "C" {
|
|
+ #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
|
|
+ #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
+ pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
|
|
+ #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
|
|
+ #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
+ pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
|
|
+}
|
|
+
|
|
+// macro _Py_NewRef not public; reimplemented directly inside Py_NewRef here
|
|
+// macro _Py_XNewRef not public; reimplemented directly inside Py_XNewRef here
|
|
+
|
|
+#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
|
|
+#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
+#[inline]
|
|
+pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
|
|
+ Py_INCREF(obj);
|
|
+ obj
|
|
+}
|
|
+
|
|
+#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
|
|
+#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
|
|
+#[inline]
|
|
+pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
|
|
+ Py_XINCREF(obj);
|
|
+ obj
|
|
+}
|
|
diff --git a/include/pyo3/pyo3-ffi/src/setobject.rs b/include/pyo3/pyo3-ffi/src/setobject.rs
|
|
index 9d5351fc..87e33e80 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/setobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/setobject.rs
|
|
@@ -39,11 +39,7 @@ pub unsafe fn PySet_GET_SIZE(so: *mut PyObject) -> Py_ssize_t {
|
|
(*so).used
|
|
}
|
|
|
|
-#[cfg(not(Py_LIMITED_API))]
|
|
-#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
-extern "C" {
|
|
- pub static mut _PySet_Dummy: *mut PyObject;
|
|
-}
|
|
+// skipped _PySet_Dummy
|
|
|
|
extern "C" {
|
|
#[cfg(not(Py_LIMITED_API))]
|
|
diff --git a/include/pyo3/pyo3-ffi/src/weakrefobject.rs b/include/pyo3/pyo3-ffi/src/weakrefobject.rs
|
|
index 305dc290..88a1bf90 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/weakrefobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/weakrefobject.rs
|
|
@@ -4,16 +4,18 @@ use std::os::raw::c_int;
|
|
use std::ptr::addr_of_mut;
|
|
|
|
#[cfg(all(not(PyPy), Py_LIMITED_API, not(GraalPy)))]
|
|
-opaque_struct!(PyWeakReference);
|
|
+opaque_struct!(pub PyWeakReference);
|
|
|
|
#[cfg(all(not(PyPy), not(Py_LIMITED_API), not(GraalPy)))]
|
|
pub use crate::_PyWeakReference as PyWeakReference;
|
|
|
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
|
extern "C" {
|
|
+ // TODO: PyO3 is depending on this symbol in `reference.rs`, we should change this and
|
|
+ // remove the export as this is a private symbol.
|
|
pub static mut _PyWeakref_RefType: PyTypeObject;
|
|
- pub static mut _PyWeakref_ProxyType: PyTypeObject;
|
|
- pub static mut _PyWeakref_CallableProxyType: PyTypeObject;
|
|
+ static mut _PyWeakref_ProxyType: PyTypeObject;
|
|
+ static mut _PyWeakref_CallableProxyType: PyTypeObject;
|
|
|
|
#[cfg(PyPy)]
|
|
#[link_name = "PyPyWeakref_CheckRef"]
|
|
|
|
From d2570d2f25eba771468f41020a2ad69e0cbdbbc7 Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 17:00:34 +0200
|
|
Subject: [PATCH 2/6] Add pyo3-ffi patch for _PyLong_AsByteArray with
|
|
exceptions
|
|
|
|
Co-authored-by: ijl <ijl@mailbox.org>
|
|
---
|
|
...i-pylong-asbytearray-with-exceptions.patch | 23 +++++++++++++++++++
|
|
1 file changed, 23 insertions(+)
|
|
create mode 100644 include/pyo3-ffi-pylong-asbytearray-with-exceptions.patch
|
|
|
|
diff --git a/include/pyo3-ffi-pylong-asbytearray-with-exceptions.patch b/include/pyo3-ffi-pylong-asbytearray-with-exceptions.patch
|
|
new file mode 100644
|
|
index 00000000..20e5d7a3
|
|
--- /dev/null
|
|
+++ b/include/pyo3-ffi-pylong-asbytearray-with-exceptions.patch
|
|
@@ -0,0 +1,23 @@
|
|
+diff --git a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
+index 45acaae..6063575 100644
|
|
+--- a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
++++ b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
+@@ -61,6 +61,18 @@ extern "C" {
|
|
+ is_signed: c_int,
|
|
+ ) -> *mut PyObject;
|
|
+
|
|
++ #[cfg(Py_3_13)]
|
|
++ #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
++ pub fn _PyLong_AsByteArray(
|
|
++ v: *mut PyLongObject,
|
|
++ bytes: *mut c_uchar,
|
|
++ n: size_t,
|
|
++ little_endian: c_int,
|
|
++ is_signed: c_int,
|
|
++ with_exceptions: c_int,
|
|
++ ) -> c_int;
|
|
++
|
|
++ #[cfg(not(Py_3_13))]
|
|
+ #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
+ pub fn _PyLong_AsByteArray(
|
|
+ v: *mut PyLongObject,
|
|
|
|
From d01aea4541800dca412e3f4c3068e974f18c3218 Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 18:26:19 +0200
|
|
Subject: [PATCH 3/6] Apply pyo3-ffi patch
|
|
|
|
---
|
|
include/pyo3/pyo3-ffi/src/cpython/longobject.rs | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
diff --git a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
index 45acaae5..6063575e 100644
|
|
--- a/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
+++ b/include/pyo3/pyo3-ffi/src/cpython/longobject.rs
|
|
@@ -61,6 +61,18 @@ extern "C" {
|
|
is_signed: c_int,
|
|
) -> *mut PyObject;
|
|
|
|
+ #[cfg(Py_3_13)]
|
|
+ #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
+ pub fn _PyLong_AsByteArray(
|
|
+ v: *mut PyLongObject,
|
|
+ bytes: *mut c_uchar,
|
|
+ n: size_t,
|
|
+ little_endian: c_int,
|
|
+ is_signed: c_int,
|
|
+ with_exceptions: c_int,
|
|
+ ) -> c_int;
|
|
+
|
|
+ #[cfg(not(Py_3_13))]
|
|
#[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")]
|
|
pub fn _PyLong_AsByteArray(
|
|
v: *mut PyLongObject,
|
|
|
|
From 6427dba13406b499bc2edc033c0eeeaafdfa4ad4 Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 15:16:24 +0200
|
|
Subject: [PATCH 4/6] Fix _PyDict_SetItem_KnownHash_LockHeld
|
|
|
|
---
|
|
src/util.rs | 10 ----------
|
|
1 file changed, 10 deletions(-)
|
|
|
|
diff --git a/src/util.rs b/src/util.rs
|
|
index ccf425ce..0a255c3f 100644
|
|
--- a/src/util.rs
|
|
+++ b/src/util.rs
|
|
@@ -258,19 +258,9 @@ macro_rules! pydict_setitem {
|
|
($dict:expr, $pykey:expr, $pyval:expr) => {
|
|
debug_assert!(ffi!(Py_REFCNT($dict)) == 1);
|
|
debug_assert!(str_hash!($pykey) != -1);
|
|
- #[cfg(not(Py_3_13))]
|
|
unsafe {
|
|
let _ = pyo3_ffi::_PyDict_SetItem_KnownHash($dict, $pykey, $pyval, str_hash!($pykey));
|
|
}
|
|
- #[cfg(Py_3_13)]
|
|
- unsafe {
|
|
- let _ = pyo3_ffi::_PyDict_SetItem_KnownHash_LockHeld(
|
|
- $dict.cast::<pyo3_ffi::PyDictObject>(),
|
|
- $pykey,
|
|
- $pyval,
|
|
- str_hash!($pykey),
|
|
- );
|
|
- }
|
|
reverse_pydict_incref!($pykey);
|
|
reverse_pydict_incref!($pyval);
|
|
};
|
|
|
|
From 80779519c9363a81884e77358e62fb443a584039 Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 15:16:40 +0200
|
|
Subject: [PATCH 5/6] Fix _Py_IsImmortal
|
|
|
|
---
|
|
src/util.rs | 6 ++----
|
|
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/util.rs b/src/util.rs
|
|
index 0a255c3f..bbfb72ed 100644
|
|
--- a/src/util.rs
|
|
+++ b/src/util.rs
|
|
@@ -120,10 +120,8 @@ macro_rules! str_from_slice {
|
|
macro_rules! reverse_pydict_incref {
|
|
($op:expr) => {
|
|
unsafe {
|
|
- if pyo3_ffi::_Py_IsImmortal($op) == 0 {
|
|
- debug_assert!(ffi!(Py_REFCNT($op)) >= 2);
|
|
- (*$op).ob_refcnt.ob_refcnt -= 1;
|
|
- }
|
|
+ debug_assert!(ffi!(Py_REFCNT($op)) >= 2);
|
|
+ (*$op).ob_refcnt.ob_refcnt -= 1;
|
|
}
|
|
};
|
|
}
|
|
|
|
From b90995f44f80176d403b720d706dfe5a027855ff Mon Sep 17 00:00:00 2001
|
|
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
|
Date: Fri, 23 May 2025 17:12:44 +0200
|
|
Subject: [PATCH 6/6] Use PyUnicode API
|
|
|
|
---
|
|
src/serialize/per_type/dict.rs | 4 ++--
|
|
src/serialize/per_type/unicode.rs | 4 ++--
|
|
src/str/ffi.rs | 29 +++++++++++++++--------------
|
|
src/str/pyunicode_new.rs | 3 +++
|
|
4 files changed, 22 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/src/serialize/per_type/dict.rs b/src/serialize/per_type/dict.rs
|
|
index e2e04f62..cf2c3a4b 100644
|
|
--- a/src/serialize/per_type/dict.rs
|
|
+++ b/src/serialize/per_type/dict.rs
|
|
@@ -13,7 +13,7 @@ use crate::serialize::per_type::{
|
|
};
|
|
use crate::serialize::serializer::PyObjectSerializer;
|
|
use crate::serialize::state::SerializerState;
|
|
-use crate::str::{unicode_to_str, unicode_to_str_via_ffi};
|
|
+use crate::str::unicode_to_str;
|
|
use crate::typeref::{STR_TYPE, TRUE, VALUE_STR};
|
|
use crate::util::isize_to_usize;
|
|
use compact_str::CompactString;
|
|
@@ -321,7 +321,7 @@ fn non_str_str(key: *mut pyo3_ffi::PyObject) -> Result<CompactString, SerializeE
|
|
#[cold]
|
|
#[inline(never)]
|
|
fn non_str_str_subclass(key: *mut pyo3_ffi::PyObject) -> Result<CompactString, SerializeError> {
|
|
- let uni = unicode_to_str_via_ffi(key);
|
|
+ let uni = unicode_to_str(key);
|
|
if unlikely!(uni.is_none()) {
|
|
Err(SerializeError::InvalidStr)
|
|
} else {
|
|
diff --git a/src/serialize/per_type/unicode.rs b/src/serialize/per_type/unicode.rs
|
|
index 23270916..7267b454 100644
|
|
--- a/src/serialize/per_type/unicode.rs
|
|
+++ b/src/serialize/per_type/unicode.rs
|
|
@@ -1,7 +1,7 @@
|
|
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
use crate::serialize::error::SerializeError;
|
|
-use crate::str::{unicode_to_str, unicode_to_str_via_ffi};
|
|
+use crate::str::unicode_to_str;
|
|
|
|
use serde::ser::{Serialize, Serializer};
|
|
|
|
@@ -50,7 +50,7 @@ impl Serialize for StrSubclassSerializer {
|
|
where
|
|
S: Serializer,
|
|
{
|
|
- let uni = unicode_to_str_via_ffi(self.ptr);
|
|
+ let uni = unicode_to_str(self.ptr);
|
|
if unlikely!(uni.is_none()) {
|
|
err!(SerializeError::InvalidStr)
|
|
}
|
|
diff --git a/src/str/ffi.rs b/src/str/ffi.rs
|
|
index 4f1c76bd..6b57e7ae 100644
|
|
--- a/src/str/ffi.rs
|
|
+++ b/src/str/ffi.rs
|
|
@@ -1,25 +1,19 @@
|
|
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
use crate::util::isize_to_usize;
|
|
-use core::ffi::c_void;
|
|
-use pyo3_ffi::{PyASCIIObject, PyCompactUnicodeObject, PyObject, Py_hash_t};
|
|
+#[cfg(not(Py_3_14))]
|
|
+use pyo3_ffi::PyCompactUnicodeObject;
|
|
+use pyo3_ffi::{
|
|
+ PyASCIIObject, PyObject, PyUnicode_DATA, PyUnicode_GET_LENGTH, PyUnicode_KIND, Py_hash_t,
|
|
+};
|
|
|
|
// see unicodeobject.h for documentation
|
|
|
|
#[inline]
|
|
pub fn hash_str(op: *mut PyObject) -> Py_hash_t {
|
|
unsafe {
|
|
- let data_ptr: *mut c_void = if (*op.cast::<PyASCIIObject>()).compact() == 1
|
|
- && (*op.cast::<PyASCIIObject>()).ascii() == 1
|
|
- {
|
|
- op.cast::<PyASCIIObject>().offset(1).cast::<c_void>()
|
|
- } else {
|
|
- op.cast::<PyCompactUnicodeObject>()
|
|
- .offset(1)
|
|
- .cast::<c_void>()
|
|
- };
|
|
- let num_bytes =
|
|
- (*op.cast::<PyASCIIObject>()).length * ((*op.cast::<PyASCIIObject>()).kind()) as isize;
|
|
+ let data_ptr = PyUnicode_DATA(op);
|
|
+ let num_bytes = PyUnicode_GET_LENGTH(op) * PyUnicode_KIND(op) as isize;
|
|
#[cfg(Py_3_14)]
|
|
let hash = pyo3_ffi::Py_HashBuffer(data_ptr, num_bytes);
|
|
#[cfg(not(Py_3_14))]
|
|
@@ -30,7 +24,7 @@ pub fn hash_str(op: *mut PyObject) -> Py_hash_t {
|
|
}
|
|
|
|
#[inline(never)]
|
|
-pub fn unicode_to_str_via_ffi(op: *mut PyObject) -> Option<&'static str> {
|
|
+fn unicode_to_str_via_ffi(op: *mut PyObject) -> Option<&'static str> {
|
|
let mut str_size: pyo3_ffi::Py_ssize_t = 0;
|
|
let ptr = ffi!(PyUnicode_AsUTF8AndSize(op, &mut str_size)).cast::<u8>();
|
|
if unlikely!(ptr.is_null()) {
|
|
@@ -40,6 +34,7 @@ pub fn unicode_to_str_via_ffi(op: *mut PyObject) -> Option<&'static str> {
|
|
}
|
|
}
|
|
|
|
+#[cfg(not(Py_3_14))]
|
|
#[inline]
|
|
pub fn unicode_to_str(op: *mut PyObject) -> Option<&'static str> {
|
|
unsafe {
|
|
@@ -58,3 +53,9 @@ pub fn unicode_to_str(op: *mut PyObject) -> Option<&'static str> {
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+#[cfg(Py_3_14)]
|
|
+#[inline]
|
|
+pub fn unicode_to_str(op: *mut PyObject) -> Option<&'static str> {
|
|
+ unicode_to_str_via_ffi(op)
|
|
+}
|
|
diff --git a/src/str/pyunicode_new.rs b/src/str/pyunicode_new.rs
|
|
index 7b1c2df2..738b8489 100644
|
|
--- a/src/str/pyunicode_new.rs
|
|
+++ b/src/str/pyunicode_new.rs
|
|
@@ -8,7 +8,9 @@ macro_rules! validate_str {
|
|
#[cfg(not(Py_3_12))]
|
|
debug_assert!((*($ptr.cast::<PyASCIIObject>())).ready() == 1);
|
|
|
|
+ #[cfg(not(Py_3_14))]
|
|
debug_assert!((*($ptr.cast::<PyASCIIObject>())).compact() == 1);
|
|
+ #[cfg(not(Py_3_14))]
|
|
debug_assert!((*($ptr.cast::<PyASCIIObject>())).interned() == 0);
|
|
|
|
debug_assert!(ffi!(_PyUnicode_CheckConsistency($ptr.cast::<PyObject>(), 1)) == 1);
|
|
@@ -22,6 +24,7 @@ pub fn pyunicode_ascii(buf: *const u8, num_chars: usize) -> *mut pyo3_ffi::PyObj
|
|
let data_ptr = ptr.cast::<PyASCIIObject>().offset(1).cast::<u8>();
|
|
core::ptr::copy_nonoverlapping(buf, data_ptr, num_chars);
|
|
core::ptr::write(data_ptr.add(num_chars), 0);
|
|
+ #[cfg(not(Py_3_14))]
|
|
debug_assert!((*(ptr.cast::<PyASCIIObject>())).ascii() == 1);
|
|
validate_str!(ptr);
|
|
ptr.cast::<PyObject>()
|