remove all functionality deprecated in 0.20 (#4322)

* remove all functionality deprecated in 0.20

* bump version to 0.23.0-dev

* undo unintended revert

* fixup UI test
This commit is contained in:
David Hewitt 2024-07-09 17:44:27 +01:00 committed by GitHub
parent e73112f3f6
commit 8652ac8e1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 62 additions and 257 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3" name = "pyo3"
version = "0.22.1" version = "0.23.0-dev"
description = "Bindings to Python interpreter" description = "Bindings to Python interpreter"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
readme = "README.md" readme = "README.md"
@ -21,10 +21,10 @@ memoffset = "0.9"
once_cell = "1.13.0" once_cell = "1.13.0"
# ffi bindings to the python interpreter, split into a separate crate so they can be used independently # ffi bindings to the python interpreter, split into a separate crate so they can be used independently
pyo3-ffi = { path = "pyo3-ffi", version = "=0.22.1" } pyo3-ffi = { path = "pyo3-ffi", version = "=0.23.0-dev" }
# support crates for macros feature # support crates for macros feature
pyo3-macros = { path = "pyo3-macros", version = "=0.22.1", optional = true } pyo3-macros = { path = "pyo3-macros", version = "=0.23.0-dev", optional = true }
indoc = { version = "2.0.1", optional = true } indoc = { version = "2.0.1", optional = true }
unindent = { version = "0.2.1", optional = true } unindent = { version = "0.2.1", optional = true }
@ -63,7 +63,7 @@ rayon = "1.6.1"
futures = "0.3.28" futures = "0.3.28"
[build-dependencies] [build-dependencies]
pyo3-build-config = { path = "pyo3-build-config", version = "=0.22.1", features = ["resolve-config"] } pyo3-build-config = { path = "pyo3-build-config", version = "=0.23.0-dev", features = ["resolve-config"] }
[features] [features]
default = ["macros"] default = ["macros"]

View File

@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.22.1"); variable::set("PYO3_VERSION", "0.23.0-dev");
file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/pyproject.toml", "pyproject.toml"); file::rename(".template/pyproject.toml", "pyproject.toml");
file::delete(".template"); file::delete(".template");

View File

@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.22.1"); variable::set("PYO3_VERSION", "0.23.0-dev");
file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/pyproject.toml", "pyproject.toml"); file::rename(".template/pyproject.toml", "pyproject.toml");
file::delete(".template"); file::delete(".template");

View File

@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.22.1"); variable::set("PYO3_VERSION", "0.23.0-dev");
file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/plugin_api/Cargo.toml", "plugin_api/Cargo.toml"); file::rename(".template/plugin_api/Cargo.toml", "plugin_api/Cargo.toml");
file::delete(".template"); file::delete(".template");

View File

@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.22.1"); variable::set("PYO3_VERSION", "0.23.0-dev");
file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/setup.cfg", "setup.cfg"); file::rename(".template/setup.cfg", "setup.cfg");
file::delete(".template"); file::delete(".template");

View File

@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.22.1"); variable::set("PYO3_VERSION", "0.23.0-dev");
file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/pyproject.toml", "pyproject.toml"); file::rename(".template/pyproject.toml", "pyproject.toml");
file::delete(".template"); file::delete(".template");

View File

@ -0,0 +1 @@
Deprecate `PyAnyMethods::is_ellipsis` (`Py::is_ellpsis` was deprecated in PyO3 0.20).

View File

@ -0,0 +1 @@
Remove all functionality deprecated in PyO3 0.20.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3-build-config" name = "pyo3-build-config"
version = "0.22.1" version = "0.23.0-dev"
description = "Build configuration for the PyO3 ecosystem" description = "Build configuration for the PyO3 ecosystem"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3-ffi" name = "pyo3-ffi"
version = "0.22.1" version = "0.23.0-dev"
description = "Python-API bindings for the PyO3 ecosystem" description = "Python-API bindings for the PyO3 ecosystem"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]
@ -38,7 +38,7 @@ abi3-py312 = ["abi3", "pyo3-build-config/abi3-py312"]
generate-import-lib = ["pyo3-build-config/python3-dll-a"] generate-import-lib = ["pyo3-build-config/python3-dll-a"]
[build-dependencies] [build-dependencies]
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.22.1", features = ["resolve-config"] } pyo3-build-config = { path = "../pyo3-build-config", version = "=0.23.0-dev", features = ["resolve-config"] }
[lints] [lints]
workspace = true workspace = true

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3-macros-backend" name = "pyo3-macros-backend"
version = "0.22.1" version = "0.23.0-dev"
description = "Code generation for PyO3 package" description = "Code generation for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]
@ -16,7 +16,7 @@ edition = "2021"
[dependencies] [dependencies]
heck = "0.5" heck = "0.5"
proc-macro2 = { version = "1.0.60", default-features = false } proc-macro2 = { version = "1.0.60", default-features = false }
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.22.1", features = ["resolve-config"] } pyo3-build-config = { path = "../pyo3-build-config", version = "=0.23.0-dev", features = ["resolve-config"] }
quote = { version = "1", default-features = false } quote = { version = "1", default-features = false }
[dependencies.syn] [dependencies.syn]
@ -25,7 +25,7 @@ default-features = false
features = ["derive", "parsing", "printing", "clone-impls", "full", "extra-traits"] features = ["derive", "parsing", "printing", "clone-impls", "full", "extra-traits"]
[build-dependencies] [build-dependencies]
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.22.1" } pyo3-build-config = { path = "../pyo3-build-config", version = "=0.23.0-dev" }
[lints] [lints]
workspace = true workspace = true

View File

@ -1,53 +1,6 @@
use crate::{ use crate::method::{FnArg, FnSpec};
method::{FnArg, FnSpec}, use proc_macro2::TokenStream;
utils::Ctx, use quote::quote_spanned;
};
use proc_macro2::{Span, TokenStream};
use quote::{quote_spanned, ToTokens};
pub enum Deprecation {
PyMethodsNewDeprecatedForm,
}
impl Deprecation {
fn ident(&self, span: Span) -> syn::Ident {
let string = match self {
Deprecation::PyMethodsNewDeprecatedForm => "PYMETHODS_NEW_DEPRECATED_FORM",
};
syn::Ident::new(string, span)
}
}
pub struct Deprecations<'ctx>(Vec<(Deprecation, Span)>, &'ctx Ctx);
impl<'ctx> Deprecations<'ctx> {
pub fn new(ctx: &'ctx Ctx) -> Self {
Deprecations(Vec::new(), ctx)
}
pub fn push(&mut self, deprecation: Deprecation, span: Span) {
self.0.push((deprecation, span))
}
}
impl<'ctx> ToTokens for Deprecations<'ctx> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self(deprecations, Ctx { pyo3_path, .. }) = self;
for (deprecation, span) in deprecations {
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
let ident = deprecation.ident(*span);
quote_spanned!(
*span =>
#[allow(clippy::let_unit_value)]
{
let _ = #pyo3_path::impl_::deprecations::#ident;
}
)
.to_tokens(tokens)
}
}
}
pub(crate) fn deprecate_trailing_option_default(spec: &FnSpec<'_>) -> TokenStream { pub(crate) fn deprecate_trailing_option_default(spec: &FnSpec<'_>) -> TokenStream {
if spec.signature.attribute.is_none() if spec.signature.attribute.is_none()

View File

@ -1,11 +1,8 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::ffi::CString; use std::ffi::CString;
use crate::attributes::{self, get_pyo3_options, take_attributes, NameAttribute};
use crate::utils::{Ctx, LitCStr}; use crate::utils::{Ctx, LitCStr};
use crate::{
attributes::{self, get_pyo3_options, take_attributes, NameAttribute},
deprecations::Deprecations,
};
use proc_macro2::{Ident, Span}; use proc_macro2::{Ident, Span};
use syn::{ use syn::{
ext::IdentExt, ext::IdentExt,
@ -14,12 +11,12 @@ use syn::{
Result, Result,
}; };
pub struct ConstSpec<'ctx> { pub struct ConstSpec {
pub rust_ident: syn::Ident, pub rust_ident: syn::Ident,
pub attributes: ConstAttributes<'ctx>, pub attributes: ConstAttributes,
} }
impl ConstSpec<'_> { impl ConstSpec {
pub fn python_name(&self) -> Cow<'_, Ident> { pub fn python_name(&self) -> Cow<'_, Ident> {
if let Some(name) = &self.attributes.name { if let Some(name) = &self.attributes.name {
Cow::Borrowed(&name.value.0) Cow::Borrowed(&name.value.0)
@ -35,10 +32,9 @@ impl ConstSpec<'_> {
} }
} }
pub struct ConstAttributes<'ctx> { pub struct ConstAttributes {
pub is_class_attr: bool, pub is_class_attr: bool,
pub name: Option<NameAttribute>, pub name: Option<NameAttribute>,
pub deprecations: Deprecations<'ctx>,
} }
pub enum PyO3ConstAttribute { pub enum PyO3ConstAttribute {
@ -56,12 +52,11 @@ impl Parse for PyO3ConstAttribute {
} }
} }
impl<'ctx> ConstAttributes<'ctx> { impl ConstAttributes {
pub fn from_attrs(attrs: &mut Vec<syn::Attribute>, ctx: &'ctx Ctx) -> syn::Result<Self> { pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Self> {
let mut attributes = ConstAttributes { let mut attributes = ConstAttributes {
is_class_attr: false, is_class_attr: false,
name: None, name: None,
deprecations: Deprecations::new(ctx),
}; };
take_attributes(attrs, |attr| { take_attributes(attrs, |attr| {

View File

@ -10,7 +10,6 @@ use crate::deprecations::deprecate_trailing_option_default;
use crate::utils::{Ctx, LitCStr}; use crate::utils::{Ctx, LitCStr};
use crate::{ use crate::{
attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue}, attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue},
deprecations::{Deprecation, Deprecations},
params::{impl_arg_params, Holders}, params::{impl_arg_params, Holders},
pyfunction::{ pyfunction::{
FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute, FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute,
@ -411,7 +410,6 @@ pub struct FnSpec<'a> {
pub text_signature: Option<TextSignatureAttribute>, pub text_signature: Option<TextSignatureAttribute>,
pub asyncness: Option<syn::Token![async]>, pub asyncness: Option<syn::Token![async]>,
pub unsafety: Option<syn::Token![unsafe]>, pub unsafety: Option<syn::Token![unsafe]>,
pub deprecations: Deprecations<'a>,
} }
pub fn parse_method_receiver(arg: &syn::FnArg) -> Result<SelfType> { pub fn parse_method_receiver(arg: &syn::FnArg) -> Result<SelfType> {
@ -443,7 +441,6 @@ impl<'a> FnSpec<'a> {
sig: &'a mut syn::Signature, sig: &'a mut syn::Signature,
meth_attrs: &mut Vec<syn::Attribute>, meth_attrs: &mut Vec<syn::Attribute>,
options: PyFunctionOptions, options: PyFunctionOptions,
ctx: &'a Ctx,
) -> Result<FnSpec<'a>> { ) -> Result<FnSpec<'a>> {
let PyFunctionOptions { let PyFunctionOptions {
text_signature, text_signature,
@ -453,9 +450,8 @@ impl<'a> FnSpec<'a> {
} = options; } = options;
let mut python_name = name.map(|name| name.value.0); let mut python_name = name.map(|name| name.value.0);
let mut deprecations = Deprecations::new(ctx);
let fn_type = Self::parse_fn_type(sig, meth_attrs, &mut python_name, &mut deprecations)?; let fn_type = Self::parse_fn_type(sig, meth_attrs, &mut python_name)?;
ensure_signatures_on_valid_method(&fn_type, signature.as_ref(), text_signature.as_ref())?; ensure_signatures_on_valid_method(&fn_type, signature.as_ref(), text_signature.as_ref())?;
let name = &sig.ident; let name = &sig.ident;
@ -493,7 +489,6 @@ impl<'a> FnSpec<'a> {
text_signature, text_signature,
asyncness: sig.asyncness, asyncness: sig.asyncness,
unsafety: sig.unsafety, unsafety: sig.unsafety,
deprecations,
}) })
} }
@ -507,9 +502,8 @@ impl<'a> FnSpec<'a> {
sig: &syn::Signature, sig: &syn::Signature,
meth_attrs: &mut Vec<syn::Attribute>, meth_attrs: &mut Vec<syn::Attribute>,
python_name: &mut Option<syn::Ident>, python_name: &mut Option<syn::Ident>,
deprecations: &mut Deprecations<'_>,
) -> Result<FnType> { ) -> Result<FnType> {
let mut method_attributes = parse_method_attributes(meth_attrs, deprecations)?; let mut method_attributes = parse_method_attributes(meth_attrs)?;
let name = &sig.ident; let name = &sig.ident;
let parse_receiver = |msg: &'static str| { let parse_receiver = |msg: &'static str| {
@ -982,10 +976,7 @@ impl MethodTypeAttribute {
/// If the attribute does not match one of the attribute names, returns `Ok(None)`. /// If the attribute does not match one of the attribute names, returns `Ok(None)`.
/// ///
/// Otherwise will either return a parse error or the attribute. /// Otherwise will either return a parse error or the attribute.
fn parse_if_matching_attribute( fn parse_if_matching_attribute(attr: &syn::Attribute) -> Result<Option<Self>> {
attr: &syn::Attribute,
deprecations: &mut Deprecations<'_>,
) -> Result<Option<Self>> {
fn ensure_no_arguments(meta: &syn::Meta, ident: &str) -> syn::Result<()> { fn ensure_no_arguments(meta: &syn::Meta, ident: &str) -> syn::Result<()> {
match meta { match meta {
syn::Meta::Path(_) => Ok(()), syn::Meta::Path(_) => Ok(()),
@ -1029,11 +1020,6 @@ impl MethodTypeAttribute {
if path.is_ident("new") { if path.is_ident("new") {
ensure_no_arguments(meta, "new")?; ensure_no_arguments(meta, "new")?;
Ok(Some(MethodTypeAttribute::New(path.span()))) Ok(Some(MethodTypeAttribute::New(path.span())))
} else if path.is_ident("__new__") {
let span = path.span();
deprecations.push(Deprecation::PyMethodsNewDeprecatedForm, span);
ensure_no_arguments(meta, "__new__")?;
Ok(Some(MethodTypeAttribute::New(span)))
} else if path.is_ident("classmethod") { } else if path.is_ident("classmethod") {
ensure_no_arguments(meta, "classmethod")?; ensure_no_arguments(meta, "classmethod")?;
Ok(Some(MethodTypeAttribute::ClassMethod(path.span()))) Ok(Some(MethodTypeAttribute::ClassMethod(path.span())))
@ -1068,15 +1054,12 @@ impl Display for MethodTypeAttribute {
} }
} }
fn parse_method_attributes( fn parse_method_attributes(attrs: &mut Vec<syn::Attribute>) -> Result<Vec<MethodTypeAttribute>> {
attrs: &mut Vec<syn::Attribute>,
deprecations: &mut Deprecations<'_>,
) -> Result<Vec<MethodTypeAttribute>> {
let mut new_attrs = Vec::new(); let mut new_attrs = Vec::new();
let mut found_attrs = Vec::new(); let mut found_attrs = Vec::new();
for attr in attrs.drain(..) { for attr in attrs.drain(..) {
match MethodTypeAttribute::parse_if_matching_attribute(&attr, deprecations)? { match MethodTypeAttribute::parse_if_matching_attribute(&attr)? {
Some(attr) => found_attrs.push(attr), Some(attr) => found_attrs.push(attr),
None => new_attrs.push(attr), None => new_attrs.push(attr),
} }

View File

@ -12,7 +12,6 @@ use crate::attributes::{
self, kw, take_pyo3_options, CrateAttribute, ExtendsAttribute, FreelistAttribute, self, kw, take_pyo3_options, CrateAttribute, ExtendsAttribute, FreelistAttribute,
ModuleAttribute, NameAttribute, NameLitStr, RenameAllAttribute, ModuleAttribute, NameAttribute, NameLitStr, RenameAllAttribute,
}; };
use crate::deprecations::Deprecations;
use crate::konst::{ConstAttributes, ConstSpec}; use crate::konst::{ConstAttributes, ConstSpec};
use crate::method::{FnArg, FnSpec, PyArg, RegularArg}; use crate::method::{FnArg, FnSpec, PyArg, RegularArg};
use crate::pyfunction::ConstructorAttribute; use crate::pyfunction::ConstructorAttribute;
@ -384,7 +383,7 @@ fn impl_class(
ctx: &Ctx, ctx: &Ctx,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
let pytypeinfo_impl = impl_pytypeinfo(cls, args, None, ctx); let pytypeinfo_impl = impl_pytypeinfo(cls, args, ctx);
let (default_richcmp, default_richcmp_slot) = let (default_richcmp, default_richcmp_slot) =
pyclass_richcmp(&args.options, &syn::parse_quote!(#cls), ctx)?; pyclass_richcmp(&args.options, &syn::parse_quote!(#cls), ctx)?;
@ -779,7 +778,7 @@ fn impl_simple_enum(
let cls = simple_enum.ident; let cls = simple_enum.ident;
let ty: syn::Type = syn::parse_quote!(#cls); let ty: syn::Type = syn::parse_quote!(#cls);
let variants = simple_enum.variants; let variants = simple_enum.variants;
let pytypeinfo = impl_pytypeinfo(cls, args, None, ctx); let pytypeinfo = impl_pytypeinfo(cls, args, ctx);
for variant in &variants { for variant in &variants {
ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => "`constructor` can't be used on a simple enum variant"); ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => "`constructor` can't be used on a simple enum variant");
@ -889,7 +888,7 @@ fn impl_complex_enum(
let ctx = &Ctx::new(&args.options.krate, None); let ctx = &Ctx::new(&args.options.krate, None);
let cls = complex_enum.ident; let cls = complex_enum.ident;
let variants = complex_enum.variants; let variants = complex_enum.variants;
let pytypeinfo = impl_pytypeinfo(cls, &args, None, ctx); let pytypeinfo = impl_pytypeinfo(cls, &args, ctx);
let (default_richcmp, default_richcmp_slot) = pyclass_richcmp(&args.options, &ty, ctx)?; let (default_richcmp, default_richcmp_slot) = pyclass_richcmp(&args.options, &ty, ctx)?;
let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?; let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?;
@ -977,7 +976,7 @@ fn impl_complex_enum(
}, },
}; };
let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, None, ctx); let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, ctx);
variant_cls_pytypeinfos.push(variant_cls_pytypeinfo); variant_cls_pytypeinfos.push(variant_cls_pytypeinfo);
let (variant_cls_impl, field_getters, mut slots) = let (variant_cls_impl, field_getters, mut slots) =
@ -1057,7 +1056,6 @@ fn impl_complex_enum_variant_match_args(
attributes: ConstAttributes { attributes: ConstAttributes {
is_class_attr: true, is_class_attr: true,
name: None, name: None,
deprecations: Deprecations::new(ctx),
}, },
}; };
@ -1318,7 +1316,6 @@ fn generate_protocol_slot(
&mut method.sig, &mut method.sig,
&mut Vec::new(), &mut Vec::new(),
PyFunctionOptions::default(), PyFunctionOptions::default(),
ctx,
) )
.unwrap(); .unwrap();
slot.generate_type_slot(&syn::parse_quote!(#cls), &spec, name, ctx) slot.generate_type_slot(&syn::parse_quote!(#cls), &spec, name, ctx)
@ -1334,7 +1331,6 @@ fn generate_default_protocol_slot(
&mut method.sig, &mut method.sig,
&mut Vec::new(), &mut Vec::new(),
PyFunctionOptions::default(), PyFunctionOptions::default(),
ctx,
) )
.unwrap(); .unwrap();
let name = spec.name.to_string(); let name = spec.name.to_string();
@ -1360,7 +1356,6 @@ fn simple_enum_default_methods<'a>(
kw: syn::parse_quote! { name }, kw: syn::parse_quote! { name },
value: NameLitStr(py_ident.clone()), value: NameLitStr(py_ident.clone()),
}), }),
deprecations: Deprecations::new(ctx),
}, },
}; };
unit_variant_names unit_variant_names
@ -1383,7 +1378,6 @@ fn complex_enum_default_methods<'a>(
kw: syn::parse_quote! { name }, kw: syn::parse_quote! { name },
value: NameLitStr(py_ident.clone()), value: NameLitStr(py_ident.clone()),
}), }),
deprecations: Deprecations::new(ctx),
}, },
}; };
variant_names variant_names
@ -1397,19 +1391,17 @@ fn complex_enum_default_methods<'a>(
pub fn gen_complex_enum_variant_attr( pub fn gen_complex_enum_variant_attr(
cls: &syn::Ident, cls: &syn::Ident,
cls_type: &syn::Type, cls_type: &syn::Type,
spec: &ConstSpec<'_>, spec: &ConstSpec,
ctx: &Ctx, ctx: &Ctx,
) -> MethodAndMethodDef { ) -> MethodAndMethodDef {
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
let member = &spec.rust_ident; let member = &spec.rust_ident;
let wrapper_ident = format_ident!("__pymethod_variant_cls_{}__", member); let wrapper_ident = format_ident!("__pymethod_variant_cls_{}__", member);
let deprecations = &spec.attributes.deprecations;
let python_name = spec.null_terminated_python_name(ctx); let python_name = spec.null_terminated_python_name(ctx);
let variant_cls = format_ident!("{}_{}", cls, member); let variant_cls = format_ident!("{}_{}", cls, member);
let associated_method = quote! { let associated_method = quote! {
fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
#deprecations
::std::result::Result::Ok(py.get_type_bound::<#variant_cls>().into_any().unbind()) ::std::result::Result::Ok(py.get_type_bound::<#variant_cls>().into_any().unbind())
} }
}; };
@ -1497,7 +1489,6 @@ fn complex_enum_struct_variant_new<'a>(
text_signature: None, text_signature: None,
asyncness: None, asyncness: None,
unsafety: None, unsafety: None,
deprecations: Deprecations::new(ctx),
}; };
crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx) crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx)
@ -1552,7 +1543,6 @@ fn complex_enum_tuple_variant_new<'a>(
text_signature: None, text_signature: None,
asyncness: None, asyncness: None,
unsafety: None, unsafety: None,
deprecations: Deprecations::new(ctx),
}; };
crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx) crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx)
@ -1577,7 +1567,6 @@ fn complex_enum_variant_field_getter<'a>(
text_signature: None, text_signature: None,
asyncness: None, asyncness: None,
unsafety: None, unsafety: None,
deprecations: Deprecations::new(ctx),
}; };
let property_type = crate::pymethod::PropertyType::Function { let property_type = crate::pymethod::PropertyType::Function {
@ -1641,12 +1630,7 @@ fn descriptors_to_items(
Ok(items) Ok(items)
} }
fn impl_pytypeinfo( fn impl_pytypeinfo(cls: &syn::Ident, attr: &PyClassArgs, ctx: &Ctx) -> TokenStream {
cls: &syn::Ident,
attr: &PyClassArgs,
deprecations: Option<&Deprecations<'_>>,
ctx: &Ctx,
) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
let cls_name = get_class_python_name(cls, attr).to_string(); let cls_name = get_class_python_name(cls, attr).to_string();
@ -1677,8 +1661,6 @@ fn impl_pytypeinfo(
#[inline] #[inline]
fn type_object_raw(py: #pyo3_path::Python<'_>) -> *mut #pyo3_path::ffi::PyTypeObject { fn type_object_raw(py: #pyo3_path::Python<'_>) -> *mut #pyo3_path::ffi::PyTypeObject {
use #pyo3_path::prelude::PyTypeMethods; use #pyo3_path::prelude::PyTypeMethods;
#deprecations
<#cls as #pyo3_path::impl_::pyclass::PyClassImpl>::lazy_type_object() <#cls as #pyo3_path::impl_::pyclass::PyClassImpl>::lazy_type_object()
.get_or_init(py) .get_or_init(py)
.as_type_ptr() .as_type_ptr()

View File

@ -4,7 +4,6 @@ use crate::{
self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute, self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute,
FromPyWithAttribute, NameAttribute, TextSignatureAttribute, FromPyWithAttribute, NameAttribute, TextSignatureAttribute,
}, },
deprecations::Deprecations,
method::{self, CallingConvention, FnArg}, method::{self, CallingConvention, FnArg},
pymethod::check_generic, pymethod::check_generic,
}; };
@ -252,7 +251,6 @@ pub fn impl_wrap_pyfunction(
text_signature, text_signature,
asyncness: func.sig.asyncness, asyncness: func.sig.asyncness,
unsafety: func.sig.unsafety, unsafety: func.sig.unsafety,
deprecations: Deprecations::new(ctx),
}; };
let vis = &func.vis; let vis = &func.vis;

View File

@ -130,7 +130,7 @@ pub fn impl_methods(
} }
syn::ImplItem::Const(konst) => { syn::ImplItem::Const(konst) => {
let ctx = &Ctx::new(&options.krate, None); let ctx = &Ctx::new(&options.krate, None);
let attributes = ConstAttributes::from_attrs(&mut konst.attrs, ctx)?; let attributes = ConstAttributes::from_attrs(&mut konst.attrs)?;
if attributes.is_class_attr { if attributes.is_class_attr {
let spec = ConstSpec { let spec = ConstSpec {
rust_ident: konst.ident.clone(), rust_ident: konst.ident.clone(),
@ -182,16 +182,14 @@ pub fn impl_methods(
}) })
} }
pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec<'_>, ctx: &Ctx) -> MethodAndMethodDef { pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec, ctx: &Ctx) -> MethodAndMethodDef {
let member = &spec.rust_ident; let member = &spec.rust_ident;
let wrapper_ident = format_ident!("__pymethod_{}__", member); let wrapper_ident = format_ident!("__pymethod_{}__", member);
let deprecations = &spec.attributes.deprecations;
let python_name = spec.null_terminated_python_name(ctx); let python_name = spec.null_terminated_python_name(ctx);
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
let associated_method = quote! { let associated_method = quote! {
fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
#deprecations
::std::result::Result::Ok(#pyo3_path::IntoPy::into_py(#cls::#member, py)) ::std::result::Result::Ok(#pyo3_path::IntoPy::into_py(#cls::#member, py))
} }
}; };

View File

@ -164,9 +164,8 @@ impl<'a> PyMethod<'a> {
sig: &'a mut syn::Signature, sig: &'a mut syn::Signature,
meth_attrs: &mut Vec<syn::Attribute>, meth_attrs: &mut Vec<syn::Attribute>,
options: PyFunctionOptions, options: PyFunctionOptions,
ctx: &'a Ctx,
) -> Result<Self> { ) -> Result<Self> {
let spec = FnSpec::parse(sig, meth_attrs, options, ctx)?; let spec = FnSpec::parse(sig, meth_attrs, options)?;
let method_name = spec.python_name.to_string(); let method_name = spec.python_name.to_string();
let kind = PyMethodKind::from_name(&method_name); let kind = PyMethodKind::from_name(&method_name);
@ -195,7 +194,7 @@ pub fn gen_py_method(
) -> Result<GeneratedPyMethod> { ) -> Result<GeneratedPyMethod> {
check_generic(sig)?; check_generic(sig)?;
ensure_function_options_valid(&options)?; ensure_function_options_valid(&options)?;
let method = PyMethod::parse(sig, meth_attrs, options, ctx)?; let method = PyMethod::parse(sig, meth_attrs, options)?;
let spec = &method.spec; let spec = &method.spec;
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
@ -356,7 +355,6 @@ pub fn impl_py_method_def_new(
|| quote!(::std::option::Option::None), || quote!(::std::option::Option::None),
|text_signature| quote!(::std::option::Option::Some(#text_signature)), |text_signature| quote!(::std::option::Option::Some(#text_signature)),
); );
let deprecations = &spec.deprecations;
let slot_def = quote! { let slot_def = quote! {
#pyo3_path::ffi::PyType_Slot { #pyo3_path::ffi::PyType_Slot {
slot: #pyo3_path::ffi::Py_tp_new, slot: #pyo3_path::ffi::Py_tp_new,
@ -365,10 +363,7 @@ pub fn impl_py_method_def_new(
subtype: *mut #pyo3_path::ffi::PyTypeObject, subtype: *mut #pyo3_path::ffi::PyTypeObject,
args: *mut #pyo3_path::ffi::PyObject, args: *mut #pyo3_path::ffi::PyObject,
kwargs: *mut #pyo3_path::ffi::PyObject, kwargs: *mut #pyo3_path::ffi::PyObject,
) -> *mut #pyo3_path::ffi::PyObject ) -> *mut #pyo3_path::ffi::PyObject {
{
#deprecations
use #pyo3_path::impl_::pyclass::*; use #pyo3_path::impl_::pyclass::*;
#[allow(unknown_lints, non_local_definitions)] #[allow(unknown_lints, non_local_definitions)]
impl PyClassNewTextSignature<#cls> for PyClassImplCollector<#cls> { impl PyClassNewTextSignature<#cls> for PyClassImplCollector<#cls> {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3-macros" name = "pyo3-macros"
version = "0.22.1" version = "0.23.0-dev"
description = "Proc macros for PyO3 package" description = "Proc macros for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]
@ -22,7 +22,7 @@ gil-refs = ["pyo3-macros-backend/gil-refs"]
proc-macro2 = { version = "1.0.60", default-features = false } proc-macro2 = { version = "1.0.60", default-features = false }
quote = "1" quote = "1"
syn = { version = "2", features = ["full", "extra-traits"] } syn = { version = "2", features = ["full", "extra-traits"] }
pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.22.1" } pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.23.0-dev" }
[lints] [lints]
workspace = true workspace = true

View File

@ -3,7 +3,7 @@
[tool.towncrier] [tool.towncrier]
filename = "CHANGELOG.md" filename = "CHANGELOG.md"
version = "0.22.1" version = "0.23.0-dev"
start_string = "<!-- towncrier release notes start -->\n" start_string = "<!-- towncrier release notes start -->\n"
template = ".towncrier.template.md" template = ".towncrier.template.md"
title_format = "## [{version}] - {project_date}" title_format = "## [{version}] - {project_date}"

View File

@ -8,7 +8,6 @@
#[cfg(feature = "experimental-async")] #[cfg(feature = "experimental-async")]
pub mod coroutine; pub mod coroutine;
pub mod deprecations;
pub mod exceptions; pub mod exceptions;
pub mod extract_argument; pub mod extract_argument;
pub mod freelist; pub mod freelist;

View File

@ -1,4 +0,0 @@
//! Symbols used to denote deprecated usages of PyO3's proc macros.
#[deprecated(since = "0.20.0", note = "use `#[new]` instead of `#[__new__]`")]
pub const PYMETHODS_NEW_DEPRECATED_FORM: () = ();

View File

@ -1384,14 +1384,6 @@ impl<T> Py<T> {
unsafe { ffi::Py_None() == self.as_ptr() } unsafe { ffi::Py_None() == self.as_ptr() }
} }
/// Returns whether the object is Ellipsis, e.g. `...`.
///
/// This is equivalent to the Python expression `self is ...`.
#[deprecated(since = "0.20.0", note = "use `.is(py.Ellipsis())` instead")]
pub fn is_ellipsis(&self) -> bool {
unsafe { ffi::Py_Ellipsis() == self.as_ptr() }
}
/// Returns whether the object is considered to be true. /// Returns whether the object is considered to be true.
/// ///
/// This is equivalent to the Python expression `bool(self)`. /// This is equivalent to the Python expression `bool(self)`.
@ -2173,23 +2165,6 @@ a = A()
}) })
} }
#[test]
#[allow(deprecated)]
fn test_is_ellipsis() {
Python::with_gil(|py| {
let v = py
.eval_bound("...", None, None)
.map_err(|e| e.display(py))
.unwrap()
.to_object(py);
assert!(v.is_ellipsis());
let not_ellipsis = 5.to_object(py);
assert!(!not_ellipsis.is_ellipsis());
});
}
#[test] #[test]
fn test_debug_fmt() { fn test_debug_fmt() {
Python::with_gil(|py| { Python::with_gil(|py| {

View File

@ -498,16 +498,6 @@ pub mod inspect;
// other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`). // other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`).
pub mod prelude; pub mod prelude;
/// Ths module only contains re-exports of pyo3 deprecation warnings and exists
/// purely to make compiler error messages nicer.
///
/// (The compiler uses this module in error messages, probably because it's a public
/// re-export at a shorter path than `pyo3::impl_::deprecations`.)
#[doc(hidden)]
pub mod deprecations {
pub use crate::impl_::deprecations::*;
}
/// Test readme and user guide /// Test readme and user guide
#[cfg(doctest)] #[cfg(doctest)]
pub mod doc_test { pub mod doc_test {

View File

@ -604,14 +604,6 @@ impl PyAny {
self.as_borrowed().is_none() self.as_borrowed().is_none()
} }
/// Returns whether the object is Ellipsis, e.g. `...`.
///
/// This is equivalent to the Python expression `self is ...`.
#[deprecated(since = "0.20.0", note = "use `.is(py.Ellipsis())` instead")]
pub fn is_ellipsis(&self) -> bool {
self.as_borrowed().is_ellipsis()
}
/// Returns true if the sequence or mapping has a length of 0. /// Returns true if the sequence or mapping has a length of 0.
/// ///
/// This is equivalent to the Python expression `len(self) == 0`. /// This is equivalent to the Python expression `len(self) == 0`.
@ -1495,6 +1487,7 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
/// Returns whether the object is Ellipsis, e.g. `...`. /// Returns whether the object is Ellipsis, e.g. `...`.
/// ///
/// This is equivalent to the Python expression `self is ...`. /// This is equivalent to the Python expression `self is ...`.
#[deprecated(since = "0.23.0", note = "use `.is(py.Ellipsis())` instead")]
fn is_ellipsis(&self) -> bool; fn is_ellipsis(&self) -> bool;
/// Returns true if the sequence or mapping has a length of 0. /// Returns true if the sequence or mapping has a length of 0.
@ -2785,6 +2778,7 @@ class SimpleClass:
} }
#[test] #[test]
#[allow(deprecated)]
fn test_is_ellipsis() { fn test_is_ellipsis() {
Python::with_gil(|py| { Python::with_gil(|py| {
let v = py let v = py

View File

@ -197,19 +197,6 @@ impl PyDict {
} }
} }
/// Deprecated version of `get_item`.
#[deprecated(
since = "0.20.0",
note = "this is now equivalent to `PyDict::get_item`"
)]
#[inline]
pub fn get_item_with_error<K>(&self, key: K) -> PyResult<Option<&PyAny>>
where
K: ToPyObject,
{
self.get_item(key)
}
/// Sets an item value. /// Sets an item value.
/// ///
/// This is equivalent to the Python statement `self[key] = value`. /// This is equivalent to the Python statement `self[key] = value`.
@ -957,31 +944,6 @@ mod tests {
}); });
} }
#[test]
#[allow(deprecated)]
#[cfg(all(not(any(PyPy, GraalPy)), feature = "gil-refs"))]
fn test_get_item_with_error() {
Python::with_gil(|py| {
let mut v = HashMap::new();
v.insert(7, 32);
let ob = v.to_object(py);
let dict = ob.downcast::<PyDict>(py).unwrap();
assert_eq!(
32,
dict.get_item_with_error(7i32)
.unwrap()
.unwrap()
.extract::<i32>()
.unwrap()
);
assert!(dict.get_item_with_error(8i32).unwrap().is_none());
assert!(dict
.get_item_with_error(dict)
.unwrap_err()
.is_instance_of::<crate::exceptions::PyTypeError>(py));
});
}
#[test] #[test]
fn test_set_item() { fn test_set_item() {
Python::with_gil(|py| { Python::with_gil(|py| {

View File

@ -3,19 +3,6 @@
use pyo3::prelude::*; use pyo3::prelude::*;
#[pyclass]
struct MyClass;
#[pymethods]
impl MyClass {
#[__new__]
fn new() -> Self {
Self
}
}
fn main() {}
fn extract_options(obj: &Bound<'_, PyAny>) -> PyResult<Option<i32>> { fn extract_options(obj: &Bound<'_, PyAny>) -> PyResult<Option<i32>> {
obj.extract() obj.extract()
} }
@ -43,3 +30,5 @@ pub enum SimpleEnumWithoutEq {
VariamtA, VariamtA,
VariantB, VariantB,
} }
fn main() {}

View File

@ -1,8 +1,10 @@
error: use of deprecated constant `pyo3::deprecations::PYMETHODS_NEW_DEPRECATED_FORM`: use `#[new]` instead of `#[__new__]` error: use of deprecated constant `__pyfunction_pyfunction_option_2::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
--> tests/ui/deprecations.rs:11:7 = note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:15:4
| |
11 | #[__new__] 15 | fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
| ^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> tests/ui/deprecations.rs:1:9 --> tests/ui/deprecations.rs:1:9
@ -10,34 +12,26 @@ note: the lint level is defined here
1 | #![deny(deprecated)] 1 | #![deny(deprecated)]
| ^^^^^^^^^^ | ^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_2::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:28:4
|
28 | fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_3::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments error: use of deprecated constant `__pyfunction_pyfunction_option_3::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out = note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior = help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:31:4 --> tests/ui/deprecations.rs:18:4
| |
31 | fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {} 18 | fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {}
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_4::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments error: use of deprecated constant `__pyfunction_pyfunction_option_4::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out = note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior = help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:34:4 --> tests/ui/deprecations.rs:21:4
| |
34 | fn pyfunction_option_4( 21 | fn pyfunction_option_4(
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `SimpleEnumWithoutEq::__pyo3__generated____richcmp__::DEPRECATION`: Implicit equality for simple enums is deprecated. Use `#[pyclass(eq, eq_int)` to keep the current behavior. error: use of deprecated constant `SimpleEnumWithoutEq::__pyo3__generated____richcmp__::DEPRECATION`: Implicit equality for simple enums is deprecated. Use `#[pyclass(eq, eq_int)` to keep the current behavior.
--> tests/ui/deprecations.rs:41:1 --> tests/ui/deprecations.rs:28:1
| |
41 | #[pyclass] 28 | #[pyclass]
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)