Thread pyo3's path through the builder functions (#3907)
* Thread pyo3's path through the builder functions * preserve span of pyo3_path --------- Co-authored-by: David Hewitt <mail@davidhewitt.dev>
This commit is contained in:
parent
70a7aa808d
commit
4114dcb1a0
|
@ -1,3 +1,4 @@
|
|||
use crate::utils::Ctx;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote_spanned, ToTokens};
|
||||
|
||||
|
@ -14,12 +15,11 @@ impl Deprecation {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Deprecations(Vec<(Deprecation, Span)>);
|
||||
pub struct Deprecations<'ctx>(Vec<(Deprecation, Span)>, &'ctx Ctx);
|
||||
|
||||
impl Deprecations {
|
||||
pub fn new() -> Self {
|
||||
Deprecations(Vec::new())
|
||||
impl<'ctx> Deprecations<'ctx> {
|
||||
pub fn new(ctx: &'ctx Ctx) -> Self {
|
||||
Deprecations(Vec::new(), ctx)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, deprecation: Deprecation, span: Span) {
|
||||
|
@ -27,15 +27,18 @@ impl Deprecations {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Deprecations {
|
||||
impl<'ctx> ToTokens for Deprecations<'ctx> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
for (deprecation, span) in &self.0 {
|
||||
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::impl_::deprecations::#ident;
|
||||
let _ = #pyo3_path::impl_::deprecations::#ident;
|
||||
}
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use crate::{
|
||||
attributes::{self, get_pyo3_options, CrateAttribute, FromPyWithAttribute},
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use crate::attributes::{self, get_pyo3_options, CrateAttribute, FromPyWithAttribute};
|
||||
use crate::utils::Ctx;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
|
@ -46,14 +44,15 @@ impl<'a> Enum<'a> {
|
|||
}
|
||||
|
||||
/// Build derivation body for enums.
|
||||
fn build(&self) -> TokenStream {
|
||||
fn build(&self, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let mut var_extracts = Vec::new();
|
||||
let mut variant_names = Vec::new();
|
||||
let mut error_names = Vec::new();
|
||||
for var in &self.variants {
|
||||
let struct_derive = var.build();
|
||||
let struct_derive = var.build(ctx);
|
||||
let ext = quote!({
|
||||
let maybe_ret = || -> _pyo3::PyResult<Self> {
|
||||
let maybe_ret = || -> #pyo3_path::PyResult<Self> {
|
||||
#struct_derive
|
||||
}();
|
||||
|
||||
|
@ -73,7 +72,7 @@ impl<'a> Enum<'a> {
|
|||
#(#var_extracts),*
|
||||
];
|
||||
::std::result::Result::Err(
|
||||
_pyo3::impl_::frompyobject::failed_to_extract_enum(
|
||||
#pyo3_path::impl_::frompyobject::failed_to_extract_enum(
|
||||
obj.py(),
|
||||
#ty_name,
|
||||
&[#(#variant_names),*],
|
||||
|
@ -239,16 +238,16 @@ impl<'a> Container<'a> {
|
|||
}
|
||||
|
||||
/// Build derivation body for a struct.
|
||||
fn build(&self) -> TokenStream {
|
||||
fn build(&self, ctx: &Ctx) -> TokenStream {
|
||||
match &self.ty {
|
||||
ContainerType::StructNewtype(ident, from_py_with) => {
|
||||
self.build_newtype_struct(Some(ident), from_py_with)
|
||||
self.build_newtype_struct(Some(ident), from_py_with, ctx)
|
||||
}
|
||||
ContainerType::TupleNewtype(from_py_with) => {
|
||||
self.build_newtype_struct(None, from_py_with)
|
||||
self.build_newtype_struct(None, from_py_with, ctx)
|
||||
}
|
||||
ContainerType::Tuple(tups) => self.build_tuple_struct(tups),
|
||||
ContainerType::Struct(tups) => self.build_struct(tups),
|
||||
ContainerType::Tuple(tups) => self.build_tuple_struct(tups, ctx),
|
||||
ContainerType::Struct(tups) => self.build_struct(tups, ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +255,9 @@ impl<'a> Container<'a> {
|
|||
&self,
|
||||
field_ident: Option<&Ident>,
|
||||
from_py_with: &Option<FromPyWithAttribute>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let self_ty = &self.path;
|
||||
let struct_name = self.name();
|
||||
if let Some(ident) = field_ident {
|
||||
|
@ -264,32 +265,33 @@ impl<'a> Container<'a> {
|
|||
match from_py_with {
|
||||
None => quote! {
|
||||
Ok(#self_ty {
|
||||
#ident: _pyo3::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)?
|
||||
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)?
|
||||
})
|
||||
},
|
||||
Some(FromPyWithAttribute {
|
||||
value: expr_path, ..
|
||||
}) => quote! {
|
||||
Ok(#self_ty {
|
||||
#ident: _pyo3::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, #field_name)?
|
||||
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, #field_name)?
|
||||
})
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match from_py_with {
|
||||
None => quote!(
|
||||
_pyo3::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty)
|
||||
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty)
|
||||
),
|
||||
Some(FromPyWithAttribute {
|
||||
value: expr_path, ..
|
||||
}) => quote! (
|
||||
_pyo3::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, 0).map(#self_ty)
|
||||
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, 0).map(#self_ty)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_tuple_struct(&self, struct_fields: &[TupleStructField]) -> TokenStream {
|
||||
fn build_tuple_struct(&self, struct_fields: &[TupleStructField], ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let self_ty = &self.path;
|
||||
let struct_name = &self.name();
|
||||
let field_idents: Vec<_> = (0..struct_fields.len())
|
||||
|
@ -298,12 +300,12 @@ impl<'a> Container<'a> {
|
|||
let fields = struct_fields.iter().zip(&field_idents).enumerate().map(|(index, (field, ident))| {
|
||||
match &field.from_py_with {
|
||||
None => quote!(
|
||||
_pyo3::impl_::frompyobject::extract_tuple_struct_field(&#ident, #struct_name, #index)?
|
||||
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field(&#ident, #struct_name, #index)?
|
||||
),
|
||||
Some(FromPyWithAttribute {
|
||||
value: expr_path, ..
|
||||
}) => quote! (
|
||||
_pyo3::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, &#ident, #struct_name, #index)?
|
||||
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, &#ident, #struct_name, #index)?
|
||||
),
|
||||
}
|
||||
});
|
||||
|
@ -315,7 +317,8 @@ impl<'a> Container<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
fn build_struct(&self, struct_fields: &[NamedStructField<'_>]) -> TokenStream {
|
||||
fn build_struct(&self, struct_fields: &[NamedStructField<'_>], ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let self_ty = &self.path;
|
||||
let struct_name = &self.name();
|
||||
let mut fields: Punctuated<TokenStream, syn::Token![,]> = Punctuated::new();
|
||||
|
@ -324,27 +327,27 @@ impl<'a> Container<'a> {
|
|||
let field_name = ident.to_string();
|
||||
let getter = match field.getter.as_ref().unwrap_or(&FieldGetter::GetAttr(None)) {
|
||||
FieldGetter::GetAttr(Some(name)) => {
|
||||
quote!(getattr(_pyo3::intern!(obj.py(), #name)))
|
||||
quote!(getattr(#pyo3_path::intern!(obj.py(), #name)))
|
||||
}
|
||||
FieldGetter::GetAttr(None) => {
|
||||
quote!(getattr(_pyo3::intern!(obj.py(), #field_name)))
|
||||
quote!(getattr(#pyo3_path::intern!(obj.py(), #field_name)))
|
||||
}
|
||||
FieldGetter::GetItem(Some(syn::Lit::Str(key))) => {
|
||||
quote!(get_item(_pyo3::intern!(obj.py(), #key)))
|
||||
quote!(get_item(#pyo3_path::intern!(obj.py(), #key)))
|
||||
}
|
||||
FieldGetter::GetItem(Some(key)) => quote!(get_item(#key)),
|
||||
FieldGetter::GetItem(None) => {
|
||||
quote!(get_item(_pyo3::intern!(obj.py(), #field_name)))
|
||||
quote!(get_item(#pyo3_path::intern!(obj.py(), #field_name)))
|
||||
}
|
||||
};
|
||||
let extractor = match &field.from_py_with {
|
||||
None => {
|
||||
quote!(_pyo3::impl_::frompyobject::extract_struct_field(&obj.#getter?, #struct_name, #field_name)?)
|
||||
quote!(#pyo3_path::impl_::frompyobject::extract_struct_field(&obj.#getter?, #struct_name, #field_name)?)
|
||||
}
|
||||
Some(FromPyWithAttribute {
|
||||
value: expr_path, ..
|
||||
}) => {
|
||||
quote! (_pyo3::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, &obj.#getter?, #struct_name, #field_name)?)
|
||||
quote! (#pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, &obj.#getter?, #struct_name, #field_name)?)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -579,7 +582,9 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
.push(parse_quote!(#gen_ident: FromPyObject<#lt_param>))
|
||||
}
|
||||
let options = ContainerOptions::from_attrs(&tokens.attrs)?;
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let Ctx { pyo3_path } = &ctx;
|
||||
|
||||
let derives = match &tokens.data {
|
||||
syn::Data::Enum(en) => {
|
||||
if options.transparent || options.annotation.is_some() {
|
||||
|
@ -587,7 +592,7 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
at top level for enums");
|
||||
}
|
||||
let en = Enum::new(en, &tokens.ident)?;
|
||||
en.build()
|
||||
en.build(ctx)
|
||||
}
|
||||
syn::Data::Struct(st) => {
|
||||
if let Some(lit_str) = &options.annotation {
|
||||
|
@ -595,7 +600,7 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
}
|
||||
let ident = &tokens.ident;
|
||||
let st = Container::new(&st.fields, parse_quote!(#ident), options)?;
|
||||
st.build()
|
||||
st.build(ctx)
|
||||
}
|
||||
syn::Data::Union(_) => bail_spanned!(
|
||||
tokens.span() => "#[derive(FromPyObject)] is not supported for unions"
|
||||
|
@ -607,12 +612,11 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
use _pyo3::prelude::PyAnyMethods;
|
||||
use #pyo3_path::prelude::PyAnyMethods;
|
||||
|
||||
#[automatically_derived]
|
||||
impl #trait_generics _pyo3::FromPyObject<#lt_param> for #ident #generics #where_clause {
|
||||
fn extract_bound(obj: &_pyo3::Bound<#lt_param, _pyo3::PyAny>) -> _pyo3::PyResult<Self> {
|
||||
impl #trait_generics #pyo3_path::FromPyObject<#lt_param> for #ident #generics #where_clause {
|
||||
fn extract_bound(obj: &#pyo3_path::Bound<#lt_param, #pyo3_path::PyAny>) -> #pyo3_path::PyResult<Self> {
|
||||
#derives
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
attributes::{self, get_pyo3_options, take_attributes, NameAttribute},
|
||||
deprecations::Deprecations,
|
||||
|
@ -13,12 +14,12 @@ use syn::{
|
|||
Result,
|
||||
};
|
||||
|
||||
pub struct ConstSpec {
|
||||
pub struct ConstSpec<'ctx> {
|
||||
pub rust_ident: syn::Ident,
|
||||
pub attributes: ConstAttributes,
|
||||
pub attributes: ConstAttributes<'ctx>,
|
||||
}
|
||||
|
||||
impl ConstSpec {
|
||||
impl ConstSpec<'_> {
|
||||
pub fn python_name(&self) -> Cow<'_, Ident> {
|
||||
if let Some(name) = &self.attributes.name {
|
||||
Cow::Borrowed(&name.value.0)
|
||||
|
@ -34,10 +35,10 @@ impl ConstSpec {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ConstAttributes {
|
||||
pub struct ConstAttributes<'ctx> {
|
||||
pub is_class_attr: bool,
|
||||
pub name: Option<NameAttribute>,
|
||||
pub deprecations: Deprecations,
|
||||
pub deprecations: Deprecations<'ctx>,
|
||||
}
|
||||
|
||||
pub enum PyO3ConstAttribute {
|
||||
|
@ -55,12 +56,12 @@ impl Parse for PyO3ConstAttribute {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConstAttributes {
|
||||
pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Self> {
|
||||
impl<'ctx> ConstAttributes<'ctx> {
|
||||
pub fn from_attrs(attrs: &mut Vec<syn::Attribute>, ctx: &'ctx Ctx) -> syn::Result<Self> {
|
||||
let mut attributes = ConstAttributes {
|
||||
is_class_attr: false,
|
||||
name: None,
|
||||
deprecations: Deprecations::new(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
};
|
||||
|
||||
take_attributes(attrs, |attr| {
|
||||
|
|
|
@ -4,6 +4,7 @@ use proc_macro2::{Span, TokenStream};
|
|||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use syn::{ext::IdentExt, spanned::Spanned, Ident, Result};
|
||||
|
||||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
attributes::{TextSignatureAttribute, TextSignatureAttributeValue},
|
||||
deprecations::{Deprecation, Deprecations},
|
||||
|
@ -108,13 +109,16 @@ impl FnType {
|
|||
cls: Option<&syn::Type>,
|
||||
error_mode: ExtractErrorMode,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
match self {
|
||||
FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) => {
|
||||
let mut receiver = st.receiver(
|
||||
cls.expect("no class given for Fn with a \"self\" receiver"),
|
||||
error_mode,
|
||||
holders,
|
||||
ctx,
|
||||
);
|
||||
syn::Token![,](Span::call_site()).to_tokens(&mut receiver);
|
||||
receiver
|
||||
|
@ -125,22 +129,24 @@ impl FnType {
|
|||
FnType::FnClass(span) | FnType::FnNewClass(span) => {
|
||||
let py = syn::Ident::new("py", Span::call_site());
|
||||
let slf: Ident = syn::Ident::new("_slf", Span::call_site());
|
||||
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
||||
quote_spanned! { *span =>
|
||||
#[allow(clippy::useless_conversion)]
|
||||
::std::convert::Into::into(
|
||||
_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf.cast())
|
||||
.downcast_unchecked::<_pyo3::types::PyType>()
|
||||
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf.cast())
|
||||
.downcast_unchecked::<#pyo3_path::types::PyType>()
|
||||
),
|
||||
}
|
||||
}
|
||||
FnType::FnModule(span) => {
|
||||
let py = syn::Ident::new("py", Span::call_site());
|
||||
let slf: Ident = syn::Ident::new("_slf", Span::call_site());
|
||||
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
||||
quote_spanned! { *span =>
|
||||
#[allow(clippy::useless_conversion)]
|
||||
::std::convert::Into::into(
|
||||
_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf.cast())
|
||||
.downcast_unchecked::<_pyo3::types::PyModule>()
|
||||
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf.cast())
|
||||
.downcast_unchecked::<#pyo3_path::types::PyModule>()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -161,13 +167,14 @@ pub enum ExtractErrorMode {
|
|||
}
|
||||
|
||||
impl ExtractErrorMode {
|
||||
pub fn handle_error(self, extract: TokenStream) -> TokenStream {
|
||||
pub fn handle_error(self, extract: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
match self {
|
||||
ExtractErrorMode::Raise => quote! { #extract? },
|
||||
ExtractErrorMode::NotImplemented => quote! {
|
||||
match #extract {
|
||||
::std::result::Result::Ok(value) => value,
|
||||
::std::result::Result::Err(_) => { return _pyo3::callback::convert(py, py.NotImplemented()); },
|
||||
::std::result::Result::Err(_) => { return #pyo3_path::callback::convert(py, py.NotImplemented()); },
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -180,11 +187,13 @@ impl SelfType {
|
|||
cls: &syn::Type,
|
||||
error_mode: ExtractErrorMode,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
// Due to use of quote_spanned in this function, need to bind these idents to the
|
||||
// main macro callsite.
|
||||
let py = syn::Ident::new("py", Span::call_site());
|
||||
let slf = syn::Ident::new("_slf", Span::call_site());
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
match self {
|
||||
SelfType::Receiver { span, mutable } => {
|
||||
let method = if *mutable {
|
||||
|
@ -193,29 +202,35 @@ impl SelfType {
|
|||
syn::Ident::new("extract_pyclass_ref", *span)
|
||||
};
|
||||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), *span);
|
||||
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
||||
holders.push(quote_spanned! { *span =>
|
||||
#[allow(clippy::let_unit_value)]
|
||||
let mut #holder = _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
let mut #slf = _pyo3::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf);
|
||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
let mut #slf = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf);
|
||||
});
|
||||
error_mode.handle_error(quote_spanned! { *span =>
|
||||
_pyo3::impl_::extract_argument::#method::<#cls>(
|
||||
&#slf,
|
||||
&mut #holder,
|
||||
)
|
||||
})
|
||||
}
|
||||
SelfType::TryFromBoundRef(span) => {
|
||||
error_mode.handle_error(
|
||||
quote_spanned! { *span =>
|
||||
_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).downcast::<#cls>()
|
||||
.map_err(::std::convert::Into::<_pyo3::PyErr>::into)
|
||||
#pyo3_path::impl_::extract_argument::#method::<#cls>(
|
||||
&#slf,
|
||||
&mut #holder,
|
||||
)
|
||||
},
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
SelfType::TryFromBoundRef(span) => {
|
||||
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
||||
error_mode.handle_error(
|
||||
quote_spanned! { *span =>
|
||||
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).downcast::<#cls>()
|
||||
.map_err(::std::convert::Into::<#pyo3_path::PyErr>::into)
|
||||
.and_then(
|
||||
#[allow(unknown_lints, clippy::unnecessary_fallible_conversions)] // In case slf is Py<Self> (unknown_lints can be removed when MSRV is 1.75+)
|
||||
|bound| ::std::convert::TryFrom::try_from(bound).map_err(::std::convert::Into::into)
|
||||
)
|
||||
|
||||
}
|
||||
},
|
||||
ctx
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +279,7 @@ pub struct FnSpec<'a> {
|
|||
pub text_signature: Option<TextSignatureAttribute>,
|
||||
pub asyncness: Option<syn::Token![async]>,
|
||||
pub unsafety: Option<syn::Token![unsafe]>,
|
||||
pub deprecations: Deprecations,
|
||||
pub deprecations: Deprecations<'a>,
|
||||
}
|
||||
|
||||
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
|
||||
|
@ -303,6 +318,7 @@ impl<'a> FnSpec<'a> {
|
|||
sig: &'a mut syn::Signature,
|
||||
meth_attrs: &mut Vec<syn::Attribute>,
|
||||
options: PyFunctionOptions,
|
||||
ctx: &'a Ctx,
|
||||
) -> Result<FnSpec<'a>> {
|
||||
let PyFunctionOptions {
|
||||
text_signature,
|
||||
|
@ -312,7 +328,7 @@ impl<'a> FnSpec<'a> {
|
|||
} = options;
|
||||
|
||||
let mut python_name = name.map(|name| name.value.0);
|
||||
let mut deprecations = Deprecations::new();
|
||||
let mut deprecations = Deprecations::new(ctx);
|
||||
|
||||
let fn_type = Self::parse_fn_type(sig, meth_attrs, &mut python_name, &mut deprecations)?;
|
||||
ensure_signatures_on_valid_method(&fn_type, signature.as_ref(), text_signature.as_ref())?;
|
||||
|
@ -366,7 +382,7 @@ impl<'a> FnSpec<'a> {
|
|||
sig: &syn::Signature,
|
||||
meth_attrs: &mut Vec<syn::Attribute>,
|
||||
python_name: &mut Option<syn::Ident>,
|
||||
deprecations: &mut Deprecations,
|
||||
deprecations: &mut Deprecations<'_>,
|
||||
) -> Result<FnType> {
|
||||
let mut method_attributes = parse_method_attributes(meth_attrs, deprecations)?;
|
||||
|
||||
|
@ -480,7 +496,9 @@ impl<'a> FnSpec<'a> {
|
|||
&self,
|
||||
ident: &proc_macro2::Ident,
|
||||
cls: Option<&syn::Type>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let mut cancel_handle_iter = self
|
||||
.signature
|
||||
.arguments
|
||||
|
@ -495,7 +513,7 @@ impl<'a> FnSpec<'a> {
|
|||
}
|
||||
|
||||
let rust_call = |args: Vec<TokenStream>, holders: &mut Vec<TokenStream>| {
|
||||
let self_arg = self.tp.self_arg(cls, ExtractErrorMode::Raise, holders);
|
||||
let self_arg = self.tp.self_arg(cls, ExtractErrorMode::Raise, holders, ctx);
|
||||
|
||||
let call = if self.asyncness.is_some() {
|
||||
let throw_callback = if cancel_handle.is_some() {
|
||||
|
@ -505,7 +523,7 @@ impl<'a> FnSpec<'a> {
|
|||
};
|
||||
let python_name = &self.python_name;
|
||||
let qualname_prefix = match cls {
|
||||
Some(cls) => quote!(Some(<#cls as _pyo3::PyTypeInfo>::NAME)),
|
||||
Some(cls) => quote!(Some(<#cls as #pyo3_path::PyTypeInfo>::NAME)),
|
||||
None => quote!(None),
|
||||
};
|
||||
let future = match self.tp {
|
||||
|
@ -513,7 +531,7 @@ impl<'a> FnSpec<'a> {
|
|||
holders.pop().unwrap(); // does not actually use holder created by `self_arg`
|
||||
|
||||
quote! {{
|
||||
let __guard = _pyo3::impl_::coroutine::RefGuard::<#cls>::new(&_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||
let __guard = #pyo3_path::impl_::coroutine::RefGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||
async move { function(&__guard, #(#args),*).await }
|
||||
}}
|
||||
}
|
||||
|
@ -521,7 +539,7 @@ impl<'a> FnSpec<'a> {
|
|||
holders.pop().unwrap(); // does not actually use holder created by `self_arg`
|
||||
|
||||
quote! {{
|
||||
let mut __guard = _pyo3::impl_::coroutine::RefMutGuard::<#cls>::new(&_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||
let mut __guard = #pyo3_path::impl_::coroutine::RefMutGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||
async move { function(&mut __guard, #(#args),*).await }
|
||||
}}
|
||||
}
|
||||
|
@ -529,16 +547,16 @@ impl<'a> FnSpec<'a> {
|
|||
};
|
||||
let mut call = quote! {{
|
||||
let future = #future;
|
||||
_pyo3::impl_::coroutine::new_coroutine(
|
||||
_pyo3::intern!(py, stringify!(#python_name)),
|
||||
#pyo3_path::impl_::coroutine::new_coroutine(
|
||||
#pyo3_path::intern!(py, stringify!(#python_name)),
|
||||
#qualname_prefix,
|
||||
#throw_callback,
|
||||
async move { _pyo3::impl_::wrap::OkWrap::wrap(future.await) },
|
||||
async move { #pyo3_path::impl_::wrap::OkWrap::wrap(future.await) },
|
||||
)
|
||||
}};
|
||||
if cancel_handle.is_some() {
|
||||
call = quote! {{
|
||||
let __cancel_handle = _pyo3::coroutine::CancelHandle::new();
|
||||
let __cancel_handle = #pyo3_path::coroutine::CancelHandle::new();
|
||||
let __throw_callback = __cancel_handle.throw_callback();
|
||||
#call
|
||||
}};
|
||||
|
@ -547,7 +565,7 @@ impl<'a> FnSpec<'a> {
|
|||
} else {
|
||||
quote! { function(#self_arg #(#args),*) }
|
||||
};
|
||||
quotes::map_result_into_ptr(quotes::ok_wrap(call))
|
||||
quotes::map_result_into_ptr(quotes::ok_wrap(call, ctx), ctx)
|
||||
};
|
||||
|
||||
let func_name = &self.name;
|
||||
|
@ -578,9 +596,9 @@ impl<'a> FnSpec<'a> {
|
|||
|
||||
quote! {
|
||||
unsafe fn #ident<'py>(
|
||||
py: _pyo3::Python<'py>,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
|
||||
py: #pyo3_path::Python<'py>,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||
let function = #rust_name; // Shadow the function name to avoid #3017
|
||||
#( #holders )*
|
||||
let result = #call;
|
||||
|
@ -590,16 +608,16 @@ impl<'a> FnSpec<'a> {
|
|||
}
|
||||
CallingConvention::Fastcall => {
|
||||
let mut holders = Vec::new();
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders)?;
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx)?;
|
||||
let call = rust_call(args, &mut holders);
|
||||
quote! {
|
||||
unsafe fn #ident<'py>(
|
||||
py: _pyo3::Python<'py>,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_args: *const *mut _pyo3::ffi::PyObject,
|
||||
_nargs: _pyo3::ffi::Py_ssize_t,
|
||||
_kwnames: *mut _pyo3::ffi::PyObject
|
||||
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
|
||||
py: #pyo3_path::Python<'py>,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_args: *const *mut #pyo3_path::ffi::PyObject,
|
||||
_nargs: #pyo3_path::ffi::Py_ssize_t,
|
||||
_kwnames: *mut #pyo3_path::ffi::PyObject
|
||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||
let function = #rust_name; // Shadow the function name to avoid #3017
|
||||
#arg_convert
|
||||
#( #holders )*
|
||||
|
@ -610,15 +628,15 @@ impl<'a> FnSpec<'a> {
|
|||
}
|
||||
CallingConvention::Varargs => {
|
||||
let mut holders = Vec::new();
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders)?;
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
||||
let call = rust_call(args, &mut holders);
|
||||
quote! {
|
||||
unsafe fn #ident<'py>(
|
||||
py: _pyo3::Python<'py>,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_args: *mut _pyo3::ffi::PyObject,
|
||||
_kwargs: *mut _pyo3::ffi::PyObject
|
||||
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
|
||||
py: #pyo3_path::Python<'py>,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_args: *mut #pyo3_path::ffi::PyObject,
|
||||
_kwargs: *mut #pyo3_path::ffi::PyObject
|
||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||
let function = #rust_name; // Shadow the function name to avoid #3017
|
||||
#arg_convert
|
||||
#( #holders )*
|
||||
|
@ -629,23 +647,25 @@ impl<'a> FnSpec<'a> {
|
|||
}
|
||||
CallingConvention::TpNew => {
|
||||
let mut holders = Vec::new();
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders)?;
|
||||
let self_arg = self.tp.self_arg(cls, ExtractErrorMode::Raise, &mut holders);
|
||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
||||
let self_arg = self
|
||||
.tp
|
||||
.self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx);
|
||||
let call = quote! { #rust_name(#self_arg #(#args),*) };
|
||||
quote! {
|
||||
unsafe fn #ident(
|
||||
py: _pyo3::Python<'_>,
|
||||
_slf: *mut _pyo3::ffi::PyTypeObject,
|
||||
_args: *mut _pyo3::ffi::PyObject,
|
||||
_kwargs: *mut _pyo3::ffi::PyObject
|
||||
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
|
||||
use _pyo3::callback::IntoPyCallbackOutput;
|
||||
py: #pyo3_path::Python<'_>,
|
||||
_slf: *mut #pyo3_path::ffi::PyTypeObject,
|
||||
_args: *mut #pyo3_path::ffi::PyObject,
|
||||
_kwargs: *mut #pyo3_path::ffi::PyObject
|
||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||
use #pyo3_path::callback::IntoPyCallbackOutput;
|
||||
let function = #rust_name; // Shadow the function name to avoid #3017
|
||||
#arg_convert
|
||||
#( #holders )*
|
||||
let result = #call;
|
||||
let initializer: _pyo3::PyClassInitializer::<#cls> = result.convert(py)?;
|
||||
_pyo3::impl_::pymethods::tp_new_impl(py, initializer, _slf)
|
||||
let initializer: #pyo3_path::PyClassInitializer::<#cls> = result.convert(py)?;
|
||||
#pyo3_path::impl_::pymethods::tp_new_impl(py, initializer, _slf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,19 +674,20 @@ impl<'a> FnSpec<'a> {
|
|||
|
||||
/// Return a `PyMethodDef` constructor for this function, matching the selected
|
||||
/// calling convention.
|
||||
pub fn get_methoddef(&self, wrapper: impl ToTokens, doc: &PythonDoc) -> TokenStream {
|
||||
pub fn get_methoddef(&self, wrapper: impl ToTokens, doc: &PythonDoc, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let python_name = self.null_terminated_python_name();
|
||||
match self.convention {
|
||||
CallingConvention::Noargs => quote! {
|
||||
_pyo3::impl_::pymethods::PyMethodDef::noargs(
|
||||
#pyo3_path::impl_::pymethods::PyMethodDef::noargs(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyCFunction({
|
||||
#pyo3_path::impl_::pymethods::PyCFunction({
|
||||
unsafe extern "C" fn trampoline(
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_args: *mut _pyo3::ffi::PyObject,
|
||||
) -> *mut _pyo3::ffi::PyObject
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_args: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> *mut #pyo3_path::ffi::PyObject
|
||||
{
|
||||
_pyo3::impl_::trampoline::noargs(
|
||||
#pyo3_path::impl_::trampoline::noargs(
|
||||
_slf,
|
||||
_args,
|
||||
#wrapper
|
||||
|
@ -678,17 +699,17 @@ impl<'a> FnSpec<'a> {
|
|||
)
|
||||
},
|
||||
CallingConvention::Fastcall => quote! {
|
||||
_pyo3::impl_::pymethods::PyMethodDef::fastcall_cfunction_with_keywords(
|
||||
#pyo3_path::impl_::pymethods::PyMethodDef::fastcall_cfunction_with_keywords(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyCFunctionFastWithKeywords({
|
||||
#pyo3_path::impl_::pymethods::PyCFunctionFastWithKeywords({
|
||||
unsafe extern "C" fn trampoline(
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_args: *const *mut _pyo3::ffi::PyObject,
|
||||
_nargs: _pyo3::ffi::Py_ssize_t,
|
||||
_kwnames: *mut _pyo3::ffi::PyObject
|
||||
) -> *mut _pyo3::ffi::PyObject
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_args: *const *mut #pyo3_path::ffi::PyObject,
|
||||
_nargs: #pyo3_path::ffi::Py_ssize_t,
|
||||
_kwnames: *mut #pyo3_path::ffi::PyObject
|
||||
) -> *mut #pyo3_path::ffi::PyObject
|
||||
{
|
||||
_pyo3::impl_::trampoline::fastcall_with_keywords(
|
||||
#pyo3_path::impl_::trampoline::fastcall_with_keywords(
|
||||
_slf,
|
||||
_args,
|
||||
_nargs,
|
||||
|
@ -702,16 +723,16 @@ impl<'a> FnSpec<'a> {
|
|||
)
|
||||
},
|
||||
CallingConvention::Varargs => quote! {
|
||||
_pyo3::impl_::pymethods::PyMethodDef::cfunction_with_keywords(
|
||||
#pyo3_path::impl_::pymethods::PyMethodDef::cfunction_with_keywords(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyCFunctionWithKeywords({
|
||||
#pyo3_path::impl_::pymethods::PyCFunctionWithKeywords({
|
||||
unsafe extern "C" fn trampoline(
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_args: *mut _pyo3::ffi::PyObject,
|
||||
_kwargs: *mut _pyo3::ffi::PyObject,
|
||||
) -> *mut _pyo3::ffi::PyObject
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_args: *mut #pyo3_path::ffi::PyObject,
|
||||
_kwargs: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> *mut #pyo3_path::ffi::PyObject
|
||||
{
|
||||
_pyo3::impl_::trampoline::cfunction_with_keywords(
|
||||
#pyo3_path::impl_::trampoline::cfunction_with_keywords(
|
||||
_slf,
|
||||
_args,
|
||||
_kwargs,
|
||||
|
@ -783,7 +804,7 @@ impl MethodTypeAttribute {
|
|||
/// Otherwise will either return a parse error or the attribute.
|
||||
fn parse_if_matching_attribute(
|
||||
attr: &syn::Attribute,
|
||||
deprecations: &mut Deprecations,
|
||||
deprecations: &mut Deprecations<'_>,
|
||||
) -> Result<Option<Self>> {
|
||||
fn ensure_no_arguments(meta: &syn::Meta, ident: &str) -> syn::Result<()> {
|
||||
match meta {
|
||||
|
@ -869,7 +890,7 @@ impl Display for MethodTypeAttribute {
|
|||
|
||||
fn parse_method_attributes(
|
||||
attrs: &mut Vec<syn::Attribute>,
|
||||
deprecations: &mut Deprecations,
|
||||
deprecations: &mut Deprecations<'_>,
|
||||
) -> Result<Vec<MethodTypeAttribute>> {
|
||||
let mut new_attrs = Vec::new();
|
||||
let mut found_attrs = Vec::new();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Code generation for the function that initializes a python module and adds classes and function.
|
||||
|
||||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
attributes::{self, take_attributes, take_pyo3_options, CrateAttribute, NameAttribute},
|
||||
get_doc,
|
||||
pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
@ -73,7 +73,8 @@ pub fn pymodule_module_impl(mut module: syn::ItemMod) -> Result<TokenStream> {
|
|||
bail_spanned!(module.span() => "`#[pymodule]` can only be used on inline modules")
|
||||
};
|
||||
let options = PyModuleOptions::from_attrs(attrs)?;
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let doc = get_doc(attrs, None);
|
||||
|
||||
let mut module_items = Vec::new();
|
||||
|
@ -164,8 +165,8 @@ pub fn pymodule_module_impl(mut module: syn::ItemMod) -> Result<TokenStream> {
|
|||
#initialization
|
||||
|
||||
impl MakeDef {
|
||||
const fn make_def() -> #krate::impl_::pymodule::ModuleDef {
|
||||
use #krate::impl_::pymodule as impl_;
|
||||
const fn make_def() -> #pyo3_path::impl_::pymodule::ModuleDef {
|
||||
use #pyo3_path::impl_::pymodule as impl_;
|
||||
const INITIALIZER: impl_::ModuleInitializer = impl_::ModuleInitializer(__pyo3_pymodule);
|
||||
unsafe {
|
||||
impl_::ModuleDef::new(
|
||||
|
@ -177,8 +178,8 @@ pub fn pymodule_module_impl(mut module: syn::ItemMod) -> Result<TokenStream> {
|
|||
}
|
||||
}
|
||||
|
||||
fn __pyo3_pymodule(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
|
||||
use #krate::impl_::pymodule::PyAddToModule;
|
||||
fn __pyo3_pymodule(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {
|
||||
use #pyo3_path::impl_::pymodule::PyAddToModule;
|
||||
#(
|
||||
#(#module_items_cfg_attrs)*
|
||||
#module_items::add_to_module(module)?;
|
||||
|
@ -195,7 +196,8 @@ pub fn pymodule_module_impl(mut module: syn::ItemMod) -> Result<TokenStream> {
|
|||
pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream> {
|
||||
let options = PyModuleOptions::from_attrs(&mut function.attrs)?;
|
||||
process_functions_in_module(&options, &mut function)?;
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let ident = &function.sig.ident;
|
||||
let vis = &function.vis;
|
||||
let doc = get_doc(&function.attrs, None);
|
||||
|
@ -222,10 +224,10 @@ pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream>
|
|||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate::impl_::pymodule as impl_;
|
||||
use #krate::impl_::pymethods::BoundRef;
|
||||
use #pyo3_path::impl_::pymodule as impl_;
|
||||
use #pyo3_path::impl_::pymethods::BoundRef;
|
||||
|
||||
fn __pyo3_pymodule(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
|
||||
fn __pyo3_pymodule(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {
|
||||
#ident(#(#module_args),*)
|
||||
}
|
||||
|
||||
|
@ -247,36 +249,37 @@ pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream>
|
|||
|
||||
fn module_initialization(options: PyModuleOptions, ident: &syn::Ident) -> TokenStream {
|
||||
let name = options.name.unwrap_or_else(|| ident.unraw());
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let pyinit_symbol = format!("PyInit_{}", name);
|
||||
|
||||
quote! {
|
||||
pub const __PYO3_NAME: &'static str = concat!(stringify!(#name), "\0");
|
||||
|
||||
pub(super) struct MakeDef;
|
||||
pub static DEF: #krate::impl_::pymodule::ModuleDef = MakeDef::make_def();
|
||||
pub static DEF: #pyo3_path::impl_::pymodule::ModuleDef = MakeDef::make_def();
|
||||
|
||||
pub fn add_to_module(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
|
||||
use #krate::prelude::PyModuleMethods;
|
||||
pub fn add_to_module(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {
|
||||
use #pyo3_path::prelude::PyModuleMethods;
|
||||
module.add_submodule(DEF.make_module(module.py())?.bind(module.py()))
|
||||
}
|
||||
|
||||
/// This autogenerated function is called by the python interpreter when importing
|
||||
/// the module.
|
||||
#[export_name = #pyinit_symbol]
|
||||
pub unsafe extern "C" fn __pyo3_init() -> *mut #krate::ffi::PyObject {
|
||||
#krate::impl_::trampoline::module_init(|py| DEF.make_module(py))
|
||||
pub unsafe extern "C" fn __pyo3_init() -> *mut #pyo3_path::ffi::PyObject {
|
||||
#pyo3_path::impl_::trampoline::module_init(|py| DEF.make_module(py))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds and takes care of the #[pyfn(...)] in `#[pymodule]`
|
||||
fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn) -> Result<()> {
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let mut stmts: Vec<syn::Stmt> = vec![syn::parse_quote!(
|
||||
#[allow(unknown_lints, unused_imports, redundant_imports)]
|
||||
use #krate::{PyNativeType, types::PyModuleMethods};
|
||||
use #pyo3_path::{PyNativeType, types::PyModuleMethods};
|
||||
)];
|
||||
|
||||
for mut stmt in func.block.stmts.drain(..) {
|
||||
|
@ -287,7 +290,7 @@ fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn
|
|||
let name = &func.sig.ident;
|
||||
let statements: Vec<syn::Stmt> = syn::parse_quote! {
|
||||
#wrapped_function
|
||||
#module_name.as_borrowed().add_function(#krate::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?;
|
||||
#module_name.as_borrowed().add_function(#pyo3_path::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?;
|
||||
};
|
||||
stmts.extend(statements);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
method::{FnArg, FnSpec},
|
||||
pyfunction::FunctionSignature,
|
||||
|
@ -30,8 +31,10 @@ pub fn impl_arg_params(
|
|||
self_: Option<&syn::Type>,
|
||||
fastcall: bool,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<(TokenStream, Vec<TokenStream>)> {
|
||||
let args_array = syn::Ident::new("output", Span::call_site());
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
if !fastcall && is_forwarded_args(&spec.signature) {
|
||||
// In the varargs convention, we can just pass though if the signature
|
||||
|
@ -40,12 +43,12 @@ pub fn impl_arg_params(
|
|||
.signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| impl_arg_param(arg, &mut 0, &args_array, holders))
|
||||
.map(|arg| impl_arg_param(arg, &mut 0, &args_array, holders, ctx))
|
||||
.collect::<Result<_>>()?;
|
||||
return Ok((
|
||||
quote! {
|
||||
let _args = _pyo3::impl_::pymethods::BoundRef::ref_from_ptr(py, &_args);
|
||||
let _kwargs = _pyo3::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_kwargs);
|
||||
let _args = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_args);
|
||||
let _kwargs = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_kwargs);
|
||||
},
|
||||
arg_convert,
|
||||
));
|
||||
|
@ -64,7 +67,7 @@ pub fn impl_arg_params(
|
|||
.iter()
|
||||
.map(|(name, required)| {
|
||||
quote! {
|
||||
_pyo3::impl_::extract_argument::KeywordOnlyParameterDescription {
|
||||
#pyo3_path::impl_::extract_argument::KeywordOnlyParameterDescription {
|
||||
name: #name,
|
||||
required: #required,
|
||||
}
|
||||
|
@ -78,22 +81,22 @@ pub fn impl_arg_params(
|
|||
.signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| impl_arg_param(arg, &mut option_pos, &args_array, holders))
|
||||
.map(|arg| impl_arg_param(arg, &mut option_pos, &args_array, holders, ctx))
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
let args_handler = if spec.signature.python_signature.varargs.is_some() {
|
||||
quote! { _pyo3::impl_::extract_argument::TupleVarargs }
|
||||
quote! { #pyo3_path::impl_::extract_argument::TupleVarargs }
|
||||
} else {
|
||||
quote! { _pyo3::impl_::extract_argument::NoVarargs }
|
||||
quote! { #pyo3_path::impl_::extract_argument::NoVarargs }
|
||||
};
|
||||
let kwargs_handler = if spec.signature.python_signature.kwargs.is_some() {
|
||||
quote! { _pyo3::impl_::extract_argument::DictVarkeywords }
|
||||
quote! { #pyo3_path::impl_::extract_argument::DictVarkeywords }
|
||||
} else {
|
||||
quote! { _pyo3::impl_::extract_argument::NoVarkeywords }
|
||||
quote! { #pyo3_path::impl_::extract_argument::NoVarkeywords }
|
||||
};
|
||||
|
||||
let cls_name = if let Some(cls) = self_ {
|
||||
quote! { ::std::option::Option::Some(<#cls as _pyo3::type_object::PyTypeInfo>::NAME) }
|
||||
quote! { ::std::option::Option::Some(<#cls as #pyo3_path::type_object::PyTypeInfo>::NAME) }
|
||||
} else {
|
||||
quote! { ::std::option::Option::None }
|
||||
};
|
||||
|
@ -123,7 +126,7 @@ pub fn impl_arg_params(
|
|||
// create array of arguments, and then parse
|
||||
Ok((
|
||||
quote! {
|
||||
const DESCRIPTION: _pyo3::impl_::extract_argument::FunctionDescription = _pyo3::impl_::extract_argument::FunctionDescription {
|
||||
const DESCRIPTION: #pyo3_path::impl_::extract_argument::FunctionDescription = #pyo3_path::impl_::extract_argument::FunctionDescription {
|
||||
cls_name: #cls_name,
|
||||
func_name: stringify!(#python_name),
|
||||
positional_parameter_names: &[#(#positional_parameter_names),*],
|
||||
|
@ -145,7 +148,11 @@ fn impl_arg_param(
|
|||
option_pos: &mut usize,
|
||||
args_array: &syn::Ident,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let pyo3_path = pyo3_path.to_tokens_spanned(arg.ty.span());
|
||||
|
||||
// Use this macro inside this function, to ensure that all code generated here is associated
|
||||
// with the function argument
|
||||
macro_rules! quote_arg_span {
|
||||
|
@ -167,7 +174,7 @@ fn impl_arg_param(
|
|||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), arg.ty.span());
|
||||
holders.push(quote_arg_span! {
|
||||
#[allow(clippy::let_unit_value)]
|
||||
let mut #holder = _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
});
|
||||
holder
|
||||
};
|
||||
|
@ -179,7 +186,7 @@ fn impl_arg_param(
|
|||
);
|
||||
let holder = push_holder();
|
||||
return Ok(quote_arg_span! {
|
||||
_pyo3::impl_::extract_argument::extract_argument(
|
||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||
&_args,
|
||||
&mut #holder,
|
||||
#name_str
|
||||
|
@ -192,7 +199,7 @@ fn impl_arg_param(
|
|||
);
|
||||
let holder = push_holder();
|
||||
return Ok(quote_arg_span! {
|
||||
_pyo3::impl_::extract_argument::extract_optional_argument(
|
||||
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
||||
_kwargs.as_deref(),
|
||||
&mut #holder,
|
||||
#name_str,
|
||||
|
@ -209,14 +216,17 @@ fn impl_arg_param(
|
|||
// Option<T> arguments have special treatment: the default should be specified _without_ the
|
||||
// Some() wrapper. Maybe this should be changed in future?!
|
||||
if arg.optional.is_some() {
|
||||
default = Some(default.map_or_else(|| quote!(::std::option::Option::None), some_wrap));
|
||||
default = Some(default.map_or_else(
|
||||
|| quote!(::std::option::Option::None),
|
||||
|tokens| some_wrap(tokens, ctx),
|
||||
));
|
||||
}
|
||||
|
||||
let tokens = if let Some(expr_path) = arg.attrs.from_py_with.as_ref().map(|attr| &attr.value) {
|
||||
if let Some(default) = default {
|
||||
quote_arg_span! {
|
||||
#[allow(clippy::redundant_closure)]
|
||||
_pyo3::impl_::extract_argument::from_py_with_with_default(
|
||||
#pyo3_path::impl_::extract_argument::from_py_with_with_default(
|
||||
#arg_value.as_deref(),
|
||||
#name_str,
|
||||
#expr_path as fn(_) -> _,
|
||||
|
@ -225,8 +235,8 @@ fn impl_arg_param(
|
|||
}
|
||||
} else {
|
||||
quote_arg_span! {
|
||||
_pyo3::impl_::extract_argument::from_py_with(
|
||||
&_pyo3::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
||||
#pyo3_path::impl_::extract_argument::from_py_with(
|
||||
&#pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
||||
#name_str,
|
||||
#expr_path as fn(_) -> _,
|
||||
)?
|
||||
|
@ -236,7 +246,7 @@ fn impl_arg_param(
|
|||
let holder = push_holder();
|
||||
quote_arg_span! {
|
||||
#[allow(clippy::redundant_closure)]
|
||||
_pyo3::impl_::extract_argument::extract_optional_argument(
|
||||
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
||||
#arg_value.as_deref(),
|
||||
&mut #holder,
|
||||
#name_str,
|
||||
|
@ -247,7 +257,7 @@ fn impl_arg_param(
|
|||
let holder = push_holder();
|
||||
quote_arg_span! {
|
||||
#[allow(clippy::redundant_closure)]
|
||||
_pyo3::impl_::extract_argument::extract_argument_with_default(
|
||||
#pyo3_path::impl_::extract_argument::extract_argument_with_default(
|
||||
#arg_value.as_deref(),
|
||||
&mut #holder,
|
||||
#name_str,
|
||||
|
@ -257,8 +267,8 @@ fn impl_arg_param(
|
|||
} else {
|
||||
let holder = push_holder();
|
||||
quote_arg_span! {
|
||||
_pyo3::impl_::extract_argument::extract_argument(
|
||||
&_pyo3::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||
&#pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
||||
&mut #holder,
|
||||
#name_str
|
||||
)?
|
||||
|
|
|
@ -13,7 +13,8 @@ use crate::pymethod::{
|
|||
impl_py_getter_def, impl_py_setter_def, MethodAndMethodDef, MethodAndSlotDef, PropertyType,
|
||||
SlotDef, __INT__, __REPR__, __RICHCMP__,
|
||||
};
|
||||
use crate::utils::{self, apply_renaming_rule, get_pyo3_crate, PythonDoc};
|
||||
use crate::utils::Ctx;
|
||||
use crate::utils::{self, apply_renaming_rule, PythonDoc};
|
||||
use crate::PyFunctionOptions;
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
@ -189,7 +190,8 @@ pub fn build_py_class(
|
|||
) -> syn::Result<TokenStream> {
|
||||
args.options.take_pyo3_options(&mut class.attrs)?;
|
||||
let doc = utils::get_doc(&class.attrs, None);
|
||||
let krate = get_pyo3_crate(&args.options.krate);
|
||||
|
||||
let ctx = &Ctx::new(&args.options.krate);
|
||||
|
||||
if let Some(lt) = class.generics.lifetimes().next() {
|
||||
bail_spanned!(
|
||||
|
@ -251,7 +253,7 @@ pub fn build_py_class(
|
|||
}
|
||||
}
|
||||
|
||||
impl_class(&class.ident, &args, doc, field_options, methods_type, krate)
|
||||
impl_class(&class.ident, &args, doc, field_options, methods_type, ctx)
|
||||
}
|
||||
|
||||
enum Annotated<X, Y> {
|
||||
|
@ -342,9 +344,10 @@ fn impl_class(
|
|||
doc: PythonDoc,
|
||||
field_options: Vec<(&syn::Field, FieldPyO3Options)>,
|
||||
methods_type: PyClassMethodsType,
|
||||
krate: syn::Path,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let pytypeinfo_impl = impl_pytypeinfo(cls, args, None);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let pytypeinfo_impl = impl_pytypeinfo(cls, args, None, ctx);
|
||||
|
||||
let py_class_impl = PyClassImplsBuilder::new(
|
||||
cls,
|
||||
|
@ -355,19 +358,18 @@ fn impl_class(
|
|||
args.options.rename_all.as_ref(),
|
||||
args.options.frozen,
|
||||
field_options,
|
||||
ctx,
|
||||
)?,
|
||||
vec![],
|
||||
)
|
||||
.doc(doc)
|
||||
.impl_all()?;
|
||||
.impl_all(ctx)?;
|
||||
|
||||
Ok(quote! {
|
||||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
impl _pyo3::types::DerefToPyAny for #cls {}
|
||||
impl #pyo3_path::types::DerefToPyAny for #cls {}
|
||||
|
||||
#pytypeinfo_impl
|
||||
|
||||
|
@ -405,6 +407,7 @@ pub fn build_py_enum(
|
|||
) -> syn::Result<TokenStream> {
|
||||
args.options.take_pyo3_options(&mut enum_.attrs)?;
|
||||
|
||||
let ctx = &Ctx::new(&args.options.krate);
|
||||
if let Some(extends) = &args.options.extends {
|
||||
bail_spanned!(extends.span() => "enums can't extend from other classes");
|
||||
} else if let Some(subclass) = &args.options.subclass {
|
||||
|
@ -415,7 +418,7 @@ pub fn build_py_enum(
|
|||
|
||||
let doc = utils::get_doc(&enum_.attrs, None);
|
||||
let enum_ = PyClassEnum::new(enum_)?;
|
||||
impl_enum(enum_, &args, doc, method_type)
|
||||
impl_enum(enum_, &args, doc, method_type, ctx)
|
||||
}
|
||||
|
||||
struct PyClassSimpleEnum<'a> {
|
||||
|
@ -665,11 +668,14 @@ fn impl_enum(
|
|||
args: &PyClassArgs,
|
||||
doc: PythonDoc,
|
||||
methods_type: PyClassMethodsType,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
match enum_ {
|
||||
PyClassEnum::Simple(simple_enum) => impl_simple_enum(simple_enum, args, doc, methods_type),
|
||||
PyClassEnum::Simple(simple_enum) => {
|
||||
impl_simple_enum(simple_enum, args, doc, methods_type, ctx)
|
||||
}
|
||||
PyClassEnum::Complex(complex_enum) => {
|
||||
impl_complex_enum(complex_enum, args, doc, methods_type)
|
||||
impl_complex_enum(complex_enum, args, doc, methods_type, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -679,12 +685,13 @@ fn impl_simple_enum(
|
|||
args: &PyClassArgs,
|
||||
doc: PythonDoc,
|
||||
methods_type: PyClassMethodsType,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let krate = get_pyo3_crate(&args.options.krate);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = simple_enum.ident;
|
||||
let ty: syn::Type = syn::parse_quote!(#cls);
|
||||
let variants = simple_enum.variants;
|
||||
let pytypeinfo = impl_pytypeinfo(cls, args, None);
|
||||
let pytypeinfo = impl_pytypeinfo(cls, args, None, ctx);
|
||||
|
||||
let (default_repr, default_repr_slot) = {
|
||||
let variants_repr = variants.iter().map(|variant| {
|
||||
|
@ -704,7 +711,8 @@ fn impl_simple_enum(
|
|||
}
|
||||
}
|
||||
};
|
||||
let repr_slot = generate_default_protocol_slot(&ty, &mut repr_impl, &__REPR__).unwrap();
|
||||
let repr_slot =
|
||||
generate_default_protocol_slot(&ty, &mut repr_impl, &__REPR__, ctx).unwrap();
|
||||
(repr_impl, repr_slot)
|
||||
};
|
||||
|
||||
|
@ -723,7 +731,7 @@ fn impl_simple_enum(
|
|||
}
|
||||
}
|
||||
};
|
||||
let int_slot = generate_default_protocol_slot(&ty, &mut int_impl, &__INT__).unwrap();
|
||||
let int_slot = generate_default_protocol_slot(&ty, &mut int_impl, &__INT__, ctx).unwrap();
|
||||
(int_impl, int_slot)
|
||||
};
|
||||
|
||||
|
@ -731,30 +739,30 @@ fn impl_simple_enum(
|
|||
let mut richcmp_impl: syn::ImplItemFn = syn::parse_quote! {
|
||||
fn __pyo3__richcmp__(
|
||||
&self,
|
||||
py: _pyo3::Python,
|
||||
other: &_pyo3::PyAny,
|
||||
op: _pyo3::basic::CompareOp
|
||||
) -> _pyo3::PyResult<_pyo3::PyObject> {
|
||||
use _pyo3::conversion::ToPyObject;
|
||||
py: #pyo3_path::Python,
|
||||
other: &#pyo3_path::PyAny,
|
||||
op: #pyo3_path::basic::CompareOp
|
||||
) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
|
||||
use #pyo3_path::conversion::ToPyObject;
|
||||
use ::core::result::Result::*;
|
||||
match op {
|
||||
_pyo3::basic::CompareOp::Eq => {
|
||||
#pyo3_path::basic::CompareOp::Eq => {
|
||||
let self_val = self.__pyo3__int__();
|
||||
if let Ok(i) = other.extract::<#repr_type>() {
|
||||
return Ok((self_val == i).to_object(py));
|
||||
}
|
||||
if let Ok(other) = other.extract::<_pyo3::PyRef<Self>>() {
|
||||
if let Ok(other) = other.extract::<#pyo3_path::PyRef<Self>>() {
|
||||
return Ok((self_val == other.__pyo3__int__()).to_object(py));
|
||||
}
|
||||
|
||||
return Ok(py.NotImplemented());
|
||||
}
|
||||
_pyo3::basic::CompareOp::Ne => {
|
||||
#pyo3_path::basic::CompareOp::Ne => {
|
||||
let self_val = self.__pyo3__int__();
|
||||
if let Ok(i) = other.extract::<#repr_type>() {
|
||||
return Ok((self_val != i).to_object(py));
|
||||
}
|
||||
if let Ok(other) = other.extract::<_pyo3::PyRef<Self>>() {
|
||||
if let Ok(other) = other.extract::<#pyo3_path::PyRef<Self>>() {
|
||||
return Ok((self_val != other.__pyo3__int__()).to_object(py));
|
||||
}
|
||||
|
||||
|
@ -765,7 +773,7 @@ fn impl_simple_enum(
|
|||
}
|
||||
};
|
||||
let richcmp_slot =
|
||||
generate_default_protocol_slot(&ty, &mut richcmp_impl, &__RICHCMP__).unwrap();
|
||||
generate_default_protocol_slot(&ty, &mut richcmp_impl, &__RICHCMP__, ctx).unwrap();
|
||||
(richcmp_impl, richcmp_slot)
|
||||
};
|
||||
|
||||
|
@ -778,18 +786,17 @@ fn impl_simple_enum(
|
|||
simple_enum_default_methods(
|
||||
cls,
|
||||
variants.iter().map(|v| (v.ident, v.get_python_name(args))),
|
||||
ctx,
|
||||
),
|
||||
default_slots,
|
||||
)
|
||||
.doc(doc)
|
||||
.impl_all()?;
|
||||
.impl_all(ctx)?;
|
||||
|
||||
Ok(quote! {
|
||||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#pytypeinfo
|
||||
|
||||
#pyclass_impls
|
||||
|
@ -810,7 +817,10 @@ fn impl_complex_enum(
|
|||
args: &PyClassArgs,
|
||||
doc: PythonDoc,
|
||||
methods_type: PyClassMethodsType,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
// Need to rig the enum PyClass options
|
||||
let args = {
|
||||
let mut rigged_args = args.clone();
|
||||
|
@ -821,10 +831,10 @@ fn impl_complex_enum(
|
|||
rigged_args
|
||||
};
|
||||
|
||||
let krate = get_pyo3_crate(&args.options.krate);
|
||||
let ctx = &Ctx::new(&args.options.krate);
|
||||
let cls = complex_enum.ident;
|
||||
let variants = complex_enum.variants;
|
||||
let pytypeinfo = impl_pytypeinfo(cls, &args, None);
|
||||
let pytypeinfo = impl_pytypeinfo(cls, &args, None, ctx);
|
||||
|
||||
let default_slots = vec![];
|
||||
|
||||
|
@ -837,6 +847,7 @@ fn impl_complex_enum(
|
|||
variants
|
||||
.iter()
|
||||
.map(|v| (v.get_ident(), v.get_python_name(&args))),
|
||||
ctx,
|
||||
),
|
||||
default_slots,
|
||||
)
|
||||
|
@ -851,17 +862,17 @@ fn impl_complex_enum(
|
|||
let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.get_ident());
|
||||
quote! {
|
||||
#cls::#variant_ident { .. } => {
|
||||
let pyclass_init = _pyo3::PyClassInitializer::from(self).add_subclass(#variant_cls);
|
||||
let variant_value = _pyo3::Py::new(py, pyclass_init).unwrap();
|
||||
_pyo3::IntoPy::into_py(variant_value, py)
|
||||
let pyclass_init = #pyo3_path::PyClassInitializer::from(self).add_subclass(#variant_cls);
|
||||
let variant_value = #pyo3_path::Py::new(py, pyclass_init).unwrap();
|
||||
#pyo3_path::IntoPy::into_py(variant_value, py)
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
impl _pyo3::IntoPy<_pyo3::PyObject> for #cls {
|
||||
fn into_py(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
impl #pyo3_path::IntoPy<#pyo3_path::PyObject> for #cls {
|
||||
fn into_py(self, py: #pyo3_path::Python) -> #pyo3_path::PyObject {
|
||||
match self {
|
||||
#(#match_arms)*
|
||||
}
|
||||
|
@ -871,11 +882,11 @@ fn impl_complex_enum(
|
|||
};
|
||||
|
||||
let pyclass_impls: TokenStream = vec![
|
||||
impl_builder.impl_pyclass(),
|
||||
impl_builder.impl_extractext(),
|
||||
impl_builder.impl_pyclass(ctx),
|
||||
impl_builder.impl_extractext(ctx),
|
||||
enum_into_py_impl,
|
||||
impl_builder.impl_pyclassimpl()?,
|
||||
impl_builder.impl_freelist(),
|
||||
impl_builder.impl_pyclassimpl(ctx)?,
|
||||
impl_builder.impl_freelist(ctx),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -900,12 +911,12 @@ fn impl_complex_enum(
|
|||
options: parse_quote!(extends = #cls, frozen),
|
||||
};
|
||||
|
||||
let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, None);
|
||||
let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, None, ctx);
|
||||
variant_cls_pytypeinfos.push(variant_cls_pytypeinfo);
|
||||
|
||||
let variant_new = complex_enum_variant_new(cls, variant)?;
|
||||
let variant_new = complex_enum_variant_new(cls, variant, ctx)?;
|
||||
|
||||
let (variant_cls_impl, field_getters) = impl_complex_enum_variant_cls(cls, variant)?;
|
||||
let (variant_cls_impl, field_getters) = impl_complex_enum_variant_cls(cls, variant, ctx)?;
|
||||
variant_cls_impls.push(variant_cls_impl);
|
||||
|
||||
let pyclass_impl = PyClassImplsBuilder::new(
|
||||
|
@ -915,7 +926,7 @@ fn impl_complex_enum(
|
|||
field_getters,
|
||||
vec![variant_new],
|
||||
)
|
||||
.impl_all()?;
|
||||
.impl_all(ctx)?;
|
||||
|
||||
variant_cls_pyclass_impls.push(pyclass_impl);
|
||||
}
|
||||
|
@ -924,8 +935,6 @@ fn impl_complex_enum(
|
|||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#pytypeinfo
|
||||
|
||||
#pyclass_impls
|
||||
|
@ -948,10 +957,11 @@ fn impl_complex_enum(
|
|||
fn impl_complex_enum_variant_cls(
|
||||
enum_name: &syn::Ident,
|
||||
variant: &PyClassEnumVariant<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<(TokenStream, Vec<MethodAndMethodDef>)> {
|
||||
match variant {
|
||||
PyClassEnumVariant::Struct(struct_variant) => {
|
||||
impl_complex_enum_struct_variant_cls(enum_name, struct_variant)
|
||||
impl_complex_enum_struct_variant_cls(enum_name, struct_variant, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -959,7 +969,9 @@ fn impl_complex_enum_variant_cls(
|
|||
fn impl_complex_enum_struct_variant_cls(
|
||||
enum_name: &syn::Ident,
|
||||
variant: &PyClassEnumStructVariant<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<(TokenStream, Vec<MethodAndMethodDef>)> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let variant_ident = &variant.ident;
|
||||
let variant_cls = gen_complex_enum_variant_class_ident(enum_name, variant.ident);
|
||||
let variant_cls_type = parse_quote!(#variant_cls);
|
||||
|
@ -978,10 +990,11 @@ fn impl_complex_enum_struct_variant_cls(
|
|||
field_name,
|
||||
field_type,
|
||||
field.span,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
let field_getter_impl = quote! {
|
||||
fn #field_name(slf: _pyo3::PyRef<Self>) -> _pyo3::PyResult<#field_type> {
|
||||
fn #field_name(slf: #pyo3_path::PyRef<Self>) -> #pyo3_path::PyResult<#field_type> {
|
||||
match &*slf.into_super() {
|
||||
#enum_name::#variant_ident { #field_name, .. } => Ok(#field_name.clone()),
|
||||
_ => unreachable!("Wrong complex enum variant found in variant wrapper PyClass"),
|
||||
|
@ -999,9 +1012,9 @@ fn impl_complex_enum_struct_variant_cls(
|
|||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
impl #variant_cls {
|
||||
fn __pymethod_constructor__(py: _pyo3::Python<'_>, #(#fields_with_types,)*) -> _pyo3::PyClassInitializer<#variant_cls> {
|
||||
fn __pymethod_constructor__(py: #pyo3_path::Python<'_>, #(#fields_with_types,)*) -> #pyo3_path::PyClassInitializer<#variant_cls> {
|
||||
let base_value = #enum_name::#variant_ident { #(#field_names,)* };
|
||||
_pyo3::PyClassInitializer::from(base_value).add_subclass(#variant_cls)
|
||||
#pyo3_path::PyClassInitializer::from(base_value).add_subclass(#variant_cls)
|
||||
}
|
||||
|
||||
#(#field_getter_impls)*
|
||||
|
@ -1019,11 +1032,13 @@ fn generate_default_protocol_slot(
|
|||
cls: &syn::Type,
|
||||
method: &mut syn::ImplItemFn,
|
||||
slot: &SlotDef,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<MethodAndSlotDef> {
|
||||
let spec = FnSpec::parse(
|
||||
&mut method.sig,
|
||||
&mut Vec::new(),
|
||||
PyFunctionOptions::default(),
|
||||
ctx,
|
||||
)
|
||||
.unwrap();
|
||||
let name = spec.name.to_string();
|
||||
|
@ -1031,12 +1046,14 @@ fn generate_default_protocol_slot(
|
|||
&syn::parse_quote!(#cls),
|
||||
&spec,
|
||||
&format!("__default_{}__", name),
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
fn simple_enum_default_methods<'a>(
|
||||
cls: &'a syn::Ident,
|
||||
unit_variant_names: impl IntoIterator<Item = (&'a syn::Ident, Cow<'a, syn::Ident>)>,
|
||||
ctx: &Ctx,
|
||||
) -> Vec<MethodAndMethodDef> {
|
||||
let cls_type = syn::parse_quote!(#cls);
|
||||
let variant_to_attribute = |var_ident: &syn::Ident, py_ident: &syn::Ident| ConstSpec {
|
||||
|
@ -1047,18 +1064,19 @@ fn simple_enum_default_methods<'a>(
|
|||
kw: syn::parse_quote! { name },
|
||||
value: NameLitStr(py_ident.clone()),
|
||||
}),
|
||||
deprecations: Default::default(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
},
|
||||
};
|
||||
unit_variant_names
|
||||
.into_iter()
|
||||
.map(|(var, py_name)| gen_py_const(&cls_type, &variant_to_attribute(var, &py_name)))
|
||||
.map(|(var, py_name)| gen_py_const(&cls_type, &variant_to_attribute(var, &py_name), ctx))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn complex_enum_default_methods<'a>(
|
||||
cls: &'a syn::Ident,
|
||||
variant_names: impl IntoIterator<Item = (&'a syn::Ident, Cow<'a, syn::Ident>)>,
|
||||
ctx: &Ctx,
|
||||
) -> Vec<MethodAndMethodDef> {
|
||||
let cls_type = syn::parse_quote!(#cls);
|
||||
let variant_to_attribute = |var_ident: &syn::Ident, py_ident: &syn::Ident| ConstSpec {
|
||||
|
@ -1069,13 +1087,13 @@ fn complex_enum_default_methods<'a>(
|
|||
kw: syn::parse_quote! { name },
|
||||
value: NameLitStr(py_ident.clone()),
|
||||
}),
|
||||
deprecations: Default::default(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
},
|
||||
};
|
||||
variant_names
|
||||
.into_iter()
|
||||
.map(|(var, py_name)| {
|
||||
gen_complex_enum_variant_attr(cls, &cls_type, &variant_to_attribute(var, &py_name))
|
||||
gen_complex_enum_variant_attr(cls, &cls_type, &variant_to_attribute(var, &py_name), ctx)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -1083,8 +1101,10 @@ fn complex_enum_default_methods<'a>(
|
|||
pub fn gen_complex_enum_variant_attr(
|
||||
cls: &syn::Ident,
|
||||
cls_type: &syn::Type,
|
||||
spec: &ConstSpec,
|
||||
spec: &ConstSpec<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> MethodAndMethodDef {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let member = &spec.rust_ident;
|
||||
let wrapper_ident = format_ident!("__pymethod_variant_cls_{}__", member);
|
||||
let deprecations = &spec.attributes.deprecations;
|
||||
|
@ -1092,17 +1112,17 @@ pub fn gen_complex_enum_variant_attr(
|
|||
|
||||
let variant_cls = format_ident!("{}_{}", cls, member);
|
||||
let associated_method = quote! {
|
||||
fn #wrapper_ident(py: _pyo3::Python<'_>) -> _pyo3::PyResult<_pyo3::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())
|
||||
}
|
||||
};
|
||||
|
||||
let method_def = quote! {
|
||||
_pyo3::class::PyMethodDefType::ClassAttribute({
|
||||
_pyo3::class::PyClassAttributeDef::new(
|
||||
#pyo3_path::class::PyMethodDefType::ClassAttribute({
|
||||
#pyo3_path::class::PyClassAttributeDef::new(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyClassAttributeFactory(#cls_type::#wrapper_ident)
|
||||
#pyo3_path::impl_::pymethods::PyClassAttributeFactory(#cls_type::#wrapper_ident)
|
||||
)
|
||||
})
|
||||
};
|
||||
|
@ -1116,10 +1136,11 @@ pub fn gen_complex_enum_variant_attr(
|
|||
fn complex_enum_variant_new<'a>(
|
||||
cls: &'a syn::Ident,
|
||||
variant: &'a PyClassEnumVariant<'a>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndSlotDef> {
|
||||
match variant {
|
||||
PyClassEnumVariant::Struct(struct_variant) => {
|
||||
complex_enum_struct_variant_new(cls, struct_variant)
|
||||
complex_enum_struct_variant_new(cls, struct_variant, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1127,12 +1148,14 @@ fn complex_enum_variant_new<'a>(
|
|||
fn complex_enum_struct_variant_new<'a>(
|
||||
cls: &'a syn::Ident,
|
||||
variant: &'a PyClassEnumStructVariant<'a>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndSlotDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let variant_cls = format_ident!("{}_{}", cls, variant.ident);
|
||||
let variant_cls_type: syn::Type = parse_quote!(#variant_cls);
|
||||
|
||||
let arg_py_ident: syn::Ident = parse_quote!(py);
|
||||
let arg_py_type: syn::Type = parse_quote!(_pyo3::Python<'_>);
|
||||
let arg_py_type: syn::Type = parse_quote!(#pyo3_path::Python<'_>);
|
||||
|
||||
let args = {
|
||||
let mut no_pyo3_attrs = vec![];
|
||||
|
@ -1180,10 +1203,10 @@ fn complex_enum_struct_variant_new<'a>(
|
|||
text_signature: None,
|
||||
asyncness: None,
|
||||
unsafety: None,
|
||||
deprecations: Deprecations::default(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
};
|
||||
|
||||
crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec)
|
||||
crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx)
|
||||
}
|
||||
|
||||
fn complex_enum_variant_field_getter<'a>(
|
||||
|
@ -1191,6 +1214,7 @@ fn complex_enum_variant_field_getter<'a>(
|
|||
field_name: &'a syn::Ident,
|
||||
field_type: &'a syn::Type,
|
||||
field_span: Span,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndMethodDef> {
|
||||
let signature = crate::pyfunction::FunctionSignature::from_arguments(vec![])?;
|
||||
|
||||
|
@ -1206,7 +1230,7 @@ fn complex_enum_variant_field_getter<'a>(
|
|||
text_signature: None,
|
||||
asyncness: None,
|
||||
unsafety: None,
|
||||
deprecations: Deprecations::default(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
};
|
||||
|
||||
let property_type = crate::pymethod::PropertyType::Function {
|
||||
|
@ -1215,7 +1239,7 @@ fn complex_enum_variant_field_getter<'a>(
|
|||
doc: crate::get_doc(&[], None),
|
||||
};
|
||||
|
||||
let getter = crate::pymethod::impl_py_getter_def(variant_cls_type, property_type)?;
|
||||
let getter = crate::pymethod::impl_py_getter_def(variant_cls_type, property_type, ctx)?;
|
||||
Ok(getter)
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1248,7 @@ fn descriptors_to_items(
|
|||
rename_all: Option<&RenameAllAttribute>,
|
||||
frozen: Option<frozen>,
|
||||
field_options: Vec<(&syn::Field, FieldPyO3Options)>,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<Vec<MethodAndMethodDef>> {
|
||||
let ty = syn::parse_quote!(#cls);
|
||||
let mut items = Vec::new();
|
||||
|
@ -1246,6 +1271,7 @@ fn descriptors_to_items(
|
|||
python_name: options.name.as_ref(),
|
||||
renaming_rule: rename_all.map(|rename_all| rename_all.value.rule),
|
||||
},
|
||||
ctx,
|
||||
)?;
|
||||
items.push(getter);
|
||||
}
|
||||
|
@ -1260,6 +1286,7 @@ fn descriptors_to_items(
|
|||
python_name: options.name.as_ref(),
|
||||
renaming_rule: rename_all.map(|rename_all| rename_all.value.rule),
|
||||
},
|
||||
ctx,
|
||||
)?;
|
||||
items.push(setter);
|
||||
};
|
||||
|
@ -1270,8 +1297,10 @@ fn descriptors_to_items(
|
|||
fn impl_pytypeinfo(
|
||||
cls: &syn::Ident,
|
||||
attr: &PyClassArgs,
|
||||
deprecations: Option<&Deprecations>,
|
||||
deprecations: Option<&Deprecations<'_>>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls_name = get_class_python_name(cls, attr).to_string();
|
||||
|
||||
let module = if let Some(ModuleAttribute { value, .. }) = &attr.options.module {
|
||||
|
@ -1282,20 +1311,20 @@ fn impl_pytypeinfo(
|
|||
|
||||
quote! {
|
||||
#[allow(deprecated)]
|
||||
unsafe impl _pyo3::type_object::HasPyGilRef for #cls {
|
||||
type AsRefTarget = _pyo3::PyCell<Self>;
|
||||
unsafe impl #pyo3_path::type_object::HasPyGilRef for #cls {
|
||||
type AsRefTarget = #pyo3_path::PyCell<Self>;
|
||||
}
|
||||
|
||||
unsafe impl _pyo3::type_object::PyTypeInfo for #cls {
|
||||
unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls {
|
||||
const NAME: &'static str = #cls_name;
|
||||
const MODULE: ::std::option::Option<&'static str> = #module;
|
||||
|
||||
#[inline]
|
||||
fn type_object_raw(py: _pyo3::Python<'_>) -> *mut _pyo3::ffi::PyTypeObject {
|
||||
use _pyo3::prelude::PyTypeMethods;
|
||||
fn type_object_raw(py: #pyo3_path::Python<'_>) -> *mut #pyo3_path::ffi::PyTypeObject {
|
||||
use #pyo3_path::prelude::PyTypeMethods;
|
||||
#deprecations
|
||||
|
||||
<#cls as _pyo3::impl_::pyclass::PyClassImpl>::lazy_type_object()
|
||||
<#cls as #pyo3_path::impl_::pyclass::PyClassImpl>::lazy_type_object()
|
||||
.get_or_init(py)
|
||||
.as_type_ptr()
|
||||
}
|
||||
|
@ -1342,82 +1371,85 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn impl_all(&self) -> Result<TokenStream> {
|
||||
fn impl_all(&self, ctx: &Ctx) -> Result<TokenStream> {
|
||||
let tokens = vec![
|
||||
self.impl_pyclass(),
|
||||
self.impl_extractext(),
|
||||
self.impl_into_py(),
|
||||
self.impl_pyclassimpl()?,
|
||||
self.impl_freelist(),
|
||||
self.impl_pyclass(ctx),
|
||||
self.impl_extractext(ctx),
|
||||
self.impl_into_py(ctx),
|
||||
self.impl_pyclassimpl(ctx)?,
|
||||
self.impl_freelist(ctx),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
Ok(tokens)
|
||||
}
|
||||
|
||||
fn impl_pyclass(&self) -> TokenStream {
|
||||
fn impl_pyclass(&self, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = self.cls;
|
||||
|
||||
let frozen = if self.attr.options.frozen.is_some() {
|
||||
quote! { _pyo3::pyclass::boolean_struct::True }
|
||||
quote! { #pyo3_path::pyclass::boolean_struct::True }
|
||||
} else {
|
||||
quote! { _pyo3::pyclass::boolean_struct::False }
|
||||
quote! { #pyo3_path::pyclass::boolean_struct::False }
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl _pyo3::PyClass for #cls {
|
||||
impl #pyo3_path::PyClass for #cls {
|
||||
type Frozen = #frozen;
|
||||
}
|
||||
}
|
||||
}
|
||||
fn impl_extractext(&self) -> TokenStream {
|
||||
fn impl_extractext(&self, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = self.cls;
|
||||
if self.attr.options.frozen.is_some() {
|
||||
quote! {
|
||||
impl<'a, 'py> _pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls
|
||||
impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls
|
||||
{
|
||||
type Holder = ::std::option::Option<_pyo3::PyRef<'py, #cls>>;
|
||||
type Holder = ::std::option::Option<#pyo3_path::PyRef<'py, #cls>>;
|
||||
|
||||
#[inline]
|
||||
fn extract(obj: &'a _pyo3::Bound<'py, _pyo3::PyAny>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
|
||||
_pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder)
|
||||
fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult<Self> {
|
||||
#pyo3_path::impl_::extract_argument::extract_pyclass_ref(obj, holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
impl<'a, 'py> _pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls
|
||||
impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls
|
||||
{
|
||||
type Holder = ::std::option::Option<_pyo3::PyRef<'py, #cls>>;
|
||||
type Holder = ::std::option::Option<#pyo3_path::PyRef<'py, #cls>>;
|
||||
|
||||
#[inline]
|
||||
fn extract(obj: &'a _pyo3::Bound<'py, _pyo3::PyAny>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
|
||||
_pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder)
|
||||
fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult<Self> {
|
||||
#pyo3_path::impl_::extract_argument::extract_pyclass_ref(obj, holder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'py> _pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a mut #cls
|
||||
impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a mut #cls
|
||||
{
|
||||
type Holder = ::std::option::Option<_pyo3::PyRefMut<'py, #cls>>;
|
||||
type Holder = ::std::option::Option<#pyo3_path::PyRefMut<'py, #cls>>;
|
||||
|
||||
#[inline]
|
||||
fn extract(obj: &'a _pyo3::Bound<'py, _pyo3::PyAny>, holder: &'a mut Self::Holder) -> _pyo3::PyResult<Self> {
|
||||
_pyo3::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder)
|
||||
fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult<Self> {
|
||||
#pyo3_path::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_into_py(&self) -> TokenStream {
|
||||
fn impl_into_py(&self, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = self.cls;
|
||||
let attr = self.attr;
|
||||
// If #cls is not extended type, we allow Self->PyObject conversion
|
||||
if attr.options.extends.is_none() {
|
||||
quote! {
|
||||
impl _pyo3::IntoPy<_pyo3::PyObject> for #cls {
|
||||
fn into_py(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
_pyo3::IntoPy::into_py(_pyo3::Py::new(py, self).unwrap(), py)
|
||||
impl #pyo3_path::IntoPy<#pyo3_path::PyObject> for #cls {
|
||||
fn into_py(self, py: #pyo3_path::Python) -> #pyo3_path::PyObject {
|
||||
#pyo3_path::IntoPy::into_py(#pyo3_path::Py::new(py, self).unwrap(), py)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1425,13 +1457,14 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
quote! {}
|
||||
}
|
||||
}
|
||||
fn impl_pyclassimpl(&self) -> Result<TokenStream> {
|
||||
fn impl_pyclassimpl(&self, ctx: &Ctx) -> Result<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = self.cls;
|
||||
let doc = self.doc.as_ref().map_or(quote! {"\0"}, |doc| quote! {#doc});
|
||||
let is_basetype = self.attr.options.subclass.is_some();
|
||||
let base = match &self.attr.options.extends {
|
||||
Some(extends_attr) => extends_attr.value.clone(),
|
||||
None => parse_quote! { _pyo3::PyAny },
|
||||
None => parse_quote! { #pyo3_path::PyAny },
|
||||
};
|
||||
let is_subclass = self.attr.options.extends.is_some();
|
||||
let is_mapping: bool = self.attr.options.mapping.is_some();
|
||||
|
@ -1444,8 +1477,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
|
||||
let dict_offset = if self.attr.options.dict.is_some() {
|
||||
quote! {
|
||||
fn dict_offset() -> ::std::option::Option<_pyo3::ffi::Py_ssize_t> {
|
||||
::std::option::Option::Some(_pyo3::impl_::pyclass::dict_offset::<Self>())
|
||||
fn dict_offset() -> ::std::option::Option<#pyo3_path::ffi::Py_ssize_t> {
|
||||
::std::option::Option::Some(#pyo3_path::impl_::pyclass::dict_offset::<Self>())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1455,8 +1488,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
// insert space for weak ref
|
||||
let weaklist_offset = if self.attr.options.weakref.is_some() {
|
||||
quote! {
|
||||
fn weaklist_offset() -> ::std::option::Option<_pyo3::ffi::Py_ssize_t> {
|
||||
::std::option::Option::Some(_pyo3::impl_::pyclass::weaklist_offset::<Self>())
|
||||
fn weaklist_offset() -> ::std::option::Option<#pyo3_path::ffi::Py_ssize_t> {
|
||||
::std::option::Option::Some(#pyo3_path::impl_::pyclass::weaklist_offset::<Self>())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1464,9 +1497,9 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
};
|
||||
|
||||
let thread_checker = if self.attr.options.unsendable.is_some() {
|
||||
quote! { _pyo3::impl_::pyclass::ThreadCheckerImpl }
|
||||
quote! { #pyo3_path::impl_::pyclass::ThreadCheckerImpl }
|
||||
} else {
|
||||
quote! { _pyo3::impl_::pyclass::SendablePyClass<#cls> }
|
||||
quote! { #pyo3_path::impl_::pyclass::SendablePyClass<#cls> }
|
||||
};
|
||||
|
||||
let (pymethods_items, inventory, inventory_class) = match self.methods_type {
|
||||
|
@ -1481,13 +1514,13 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
quote! {
|
||||
::std::boxed::Box::new(
|
||||
::std::iter::Iterator::map(
|
||||
_pyo3::inventory::iter::<<Self as _pyo3::impl_::pyclass::PyClassImpl>::Inventory>(),
|
||||
_pyo3::impl_::pyclass::PyClassInventory::items
|
||||
#pyo3_path::inventory::iter::<<Self as #pyo3_path::impl_::pyclass::PyClassImpl>::Inventory>(),
|
||||
#pyo3_path::impl_::pyclass::PyClassInventory::items
|
||||
)
|
||||
)
|
||||
},
|
||||
Some(quote! { type Inventory = #inventory_class_name; }),
|
||||
Some(define_inventory_class(&inventory_class_name)),
|
||||
Some(define_inventory_class(&inventory_class_name, ctx)),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -1504,7 +1537,7 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
|
||||
let default_method_defs = self.default_methods.iter().map(|meth| &meth.method_def);
|
||||
let default_slot_defs = self.default_slots.iter().map(|slot| &slot.slot_def);
|
||||
let freelist_slots = self.freelist_slots();
|
||||
let freelist_slots = self.freelist_slots(ctx);
|
||||
|
||||
let class_mutability = if self.attr.options.frozen.is_some() {
|
||||
quote! {
|
||||
|
@ -1519,26 +1552,26 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
let cls = self.cls;
|
||||
let attr = self.attr;
|
||||
let dict = if attr.options.dict.is_some() {
|
||||
quote! { _pyo3::impl_::pyclass::PyClassDictSlot }
|
||||
quote! { #pyo3_path::impl_::pyclass::PyClassDictSlot }
|
||||
} else {
|
||||
quote! { _pyo3::impl_::pyclass::PyClassDummySlot }
|
||||
quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot }
|
||||
};
|
||||
|
||||
// insert space for weak ref
|
||||
let weakref = if attr.options.weakref.is_some() {
|
||||
quote! { _pyo3::impl_::pyclass::PyClassWeakRefSlot }
|
||||
quote! { #pyo3_path::impl_::pyclass::PyClassWeakRefSlot }
|
||||
} else {
|
||||
quote! { _pyo3::impl_::pyclass::PyClassDummySlot }
|
||||
quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot }
|
||||
};
|
||||
|
||||
let base_nativetype = if attr.options.extends.is_some() {
|
||||
quote! { <Self::BaseType as _pyo3::impl_::pyclass::PyClassBaseType>::BaseNativeType }
|
||||
quote! { <Self::BaseType as #pyo3_path::impl_::pyclass::PyClassBaseType>::BaseNativeType }
|
||||
} else {
|
||||
quote! { _pyo3::PyAny }
|
||||
quote! { #pyo3_path::PyAny }
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
impl _pyo3::impl_::pyclass::PyClassImpl for #cls {
|
||||
impl #pyo3_path::impl_::pyclass::PyClassImpl for #cls {
|
||||
const IS_BASETYPE: bool = #is_basetype;
|
||||
const IS_SUBCLASS: bool = #is_subclass;
|
||||
const IS_MAPPING: bool = #is_mapping;
|
||||
|
@ -1547,13 +1580,13 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
type BaseType = #base;
|
||||
type ThreadChecker = #thread_checker;
|
||||
#inventory
|
||||
type PyClassMutability = <<#base as _pyo3::impl_::pyclass::PyClassBaseType>::PyClassMutability as _pyo3::impl_::pycell::PyClassMutability>::#class_mutability;
|
||||
type PyClassMutability = <<#base as #pyo3_path::impl_::pyclass::PyClassBaseType>::PyClassMutability as #pyo3_path::impl_::pycell::PyClassMutability>::#class_mutability;
|
||||
type Dict = #dict;
|
||||
type WeakRef = #weakref;
|
||||
type BaseNativeType = #base_nativetype;
|
||||
|
||||
fn items_iter() -> _pyo3::impl_::pyclass::PyClassItemsIter {
|
||||
use _pyo3::impl_::pyclass::*;
|
||||
fn items_iter() -> #pyo3_path::impl_::pyclass::PyClassItemsIter {
|
||||
use #pyo3_path::impl_::pyclass::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
static INTRINSIC_ITEMS: PyClassItems = PyClassItems {
|
||||
methods: &[#(#default_method_defs),*],
|
||||
|
@ -1562,12 +1595,12 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
PyClassItemsIter::new(&INTRINSIC_ITEMS, #pymethods_items)
|
||||
}
|
||||
|
||||
fn doc(py: _pyo3::Python<'_>) -> _pyo3::PyResult<&'static ::std::ffi::CStr> {
|
||||
use _pyo3::impl_::pyclass::*;
|
||||
static DOC: _pyo3::sync::GILOnceCell<::std::borrow::Cow<'static, ::std::ffi::CStr>> = _pyo3::sync::GILOnceCell::new();
|
||||
fn doc(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<&'static ::std::ffi::CStr> {
|
||||
use #pyo3_path::impl_::pyclass::*;
|
||||
static DOC: #pyo3_path::sync::GILOnceCell<::std::borrow::Cow<'static, ::std::ffi::CStr>> = #pyo3_path::sync::GILOnceCell::new();
|
||||
DOC.get_or_try_init(py, || {
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
build_pyclass_doc(<#cls as _pyo3::PyTypeInfo>::NAME, #doc, collector.new_text_signature())
|
||||
build_pyclass_doc(<#cls as #pyo3_path::PyTypeInfo>::NAME, #doc, collector.new_text_signature())
|
||||
}).map(::std::ops::Deref::deref)
|
||||
}
|
||||
|
||||
|
@ -1575,8 +1608,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
|
||||
#weaklist_offset
|
||||
|
||||
fn lazy_type_object() -> &'static _pyo3::impl_::pyclass::LazyTypeObject<Self> {
|
||||
use _pyo3::impl_::pyclass::LazyTypeObject;
|
||||
fn lazy_type_object() -> &'static #pyo3_path::impl_::pyclass::LazyTypeObject<Self> {
|
||||
use #pyo3_path::impl_::pyclass::LazyTypeObject;
|
||||
static TYPE_OBJECT: LazyTypeObject<#cls> = LazyTypeObject::new();
|
||||
&TYPE_OBJECT
|
||||
}
|
||||
|
@ -1592,20 +1625,21 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn impl_freelist(&self) -> TokenStream {
|
||||
fn impl_freelist(&self, ctx: &Ctx) -> TokenStream {
|
||||
let cls = self.cls;
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
self.attr.options.freelist.as_ref().map_or(quote!{}, |freelist| {
|
||||
let freelist = &freelist.value;
|
||||
quote! {
|
||||
impl _pyo3::impl_::pyclass::PyClassWithFreeList for #cls {
|
||||
impl #pyo3_path::impl_::pyclass::PyClassWithFreeList for #cls {
|
||||
#[inline]
|
||||
fn get_free_list(py: _pyo3::Python<'_>) -> &mut _pyo3::impl_::freelist::FreeList<*mut _pyo3::ffi::PyObject> {
|
||||
static mut FREELIST: *mut _pyo3::impl_::freelist::FreeList<*mut _pyo3::ffi::PyObject> = 0 as *mut _;
|
||||
fn get_free_list(py: #pyo3_path::Python<'_>) -> &mut #pyo3_path::impl_::freelist::FreeList<*mut #pyo3_path::ffi::PyObject> {
|
||||
static mut FREELIST: *mut #pyo3_path::impl_::freelist::FreeList<*mut #pyo3_path::ffi::PyObject> = 0 as *mut _;
|
||||
unsafe {
|
||||
if FREELIST.is_null() {
|
||||
FREELIST = ::std::boxed::Box::into_raw(::std::boxed::Box::new(
|
||||
_pyo3::impl_::freelist::FreeList::with_capacity(#freelist)));
|
||||
#pyo3_path::impl_::freelist::FreeList::with_capacity(#freelist)));
|
||||
}
|
||||
&mut *FREELIST
|
||||
}
|
||||
|
@ -1615,21 +1649,22 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn freelist_slots(&self) -> Vec<TokenStream> {
|
||||
fn freelist_slots(&self, ctx: &Ctx) -> Vec<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let cls = self.cls;
|
||||
|
||||
if self.attr.options.freelist.is_some() {
|
||||
vec![
|
||||
quote! {
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_alloc,
|
||||
pfunc: _pyo3::impl_::pyclass::alloc_with_freelist::<#cls> as *mut _,
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::Py_tp_alloc,
|
||||
pfunc: #pyo3_path::impl_::pyclass::alloc_with_freelist::<#cls> as *mut _,
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_free,
|
||||
pfunc: _pyo3::impl_::pyclass::free_with_freelist::<#cls> as *mut _,
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::Py_tp_free,
|
||||
pfunc: #pyo3_path::impl_::pyclass::free_with_freelist::<#cls> as *mut _,
|
||||
}
|
||||
},
|
||||
]
|
||||
|
@ -1639,25 +1674,26 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn define_inventory_class(inventory_class_name: &syn::Ident) -> TokenStream {
|
||||
fn define_inventory_class(inventory_class_name: &syn::Ident, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #inventory_class_name {
|
||||
items: _pyo3::impl_::pyclass::PyClassItems,
|
||||
items: #pyo3_path::impl_::pyclass::PyClassItems,
|
||||
}
|
||||
impl #inventory_class_name {
|
||||
pub const fn new(items: _pyo3::impl_::pyclass::PyClassItems) -> Self {
|
||||
pub const fn new(items: #pyo3_path::impl_::pyclass::PyClassItems) -> Self {
|
||||
Self { items }
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::impl_::pyclass::PyClassInventory for #inventory_class_name {
|
||||
fn items(&self) -> &_pyo3::impl_::pyclass::PyClassItems {
|
||||
impl #pyo3_path::impl_::pyclass::PyClassInventory for #inventory_class_name {
|
||||
fn items(&self) -> &#pyo3_path::impl_::pyclass::PyClassItems {
|
||||
&self.items
|
||||
}
|
||||
}
|
||||
|
||||
_pyo3::inventory::collect!(#inventory_class_name);
|
||||
#pyo3_path::inventory::collect!(#inventory_class_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
attributes::{
|
||||
self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute,
|
||||
|
@ -6,7 +7,6 @@ use crate::{
|
|||
deprecations::Deprecations,
|
||||
method::{self, CallingConvention, FnArg},
|
||||
pymethod::check_generic,
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
@ -205,6 +205,9 @@ pub fn impl_wrap_pyfunction(
|
|||
krate,
|
||||
} = options;
|
||||
|
||||
let ctx = &Ctx::new(&krate);
|
||||
let Ctx { pyo3_path } = &ctx;
|
||||
|
||||
let python_name = name.map_or_else(|| func.sig.ident.unraw(), |name| name.value.0);
|
||||
|
||||
let tp = if pass_module.is_some() {
|
||||
|
@ -249,17 +252,15 @@ pub fn impl_wrap_pyfunction(
|
|||
text_signature,
|
||||
asyncness: func.sig.asyncness,
|
||||
unsafety: func.sig.unsafety,
|
||||
deprecations: Deprecations::new(),
|
||||
deprecations: Deprecations::new(ctx),
|
||||
};
|
||||
|
||||
let krate = get_pyo3_crate(&krate);
|
||||
|
||||
let vis = &func.vis;
|
||||
let name = &func.sig.ident;
|
||||
|
||||
let wrapper_ident = format_ident!("__pyfunction_{}", spec.name);
|
||||
let wrapper = spec.get_wrapper_function(&wrapper_ident, None)?;
|
||||
let methoddef = spec.get_methoddef(wrapper_ident, &spec.get_doc(&func.attrs));
|
||||
let wrapper = spec.get_wrapper_function(&wrapper_ident, None, ctx)?;
|
||||
let methoddef = spec.get_methoddef(wrapper_ident, &spec.get_doc(&func.attrs), ctx);
|
||||
|
||||
let wrapped_pyfunction = quote! {
|
||||
|
||||
|
@ -268,12 +269,12 @@ pub fn impl_wrap_pyfunction(
|
|||
#[doc(hidden)]
|
||||
#vis mod #name {
|
||||
pub(crate) struct MakeDef;
|
||||
pub const DEF: #krate::impl_::pymethods::PyMethodDef = MakeDef::DEF;
|
||||
pub const DEF: #pyo3_path::impl_::pymethods::PyMethodDef = MakeDef::DEF;
|
||||
|
||||
pub fn add_to_module(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
|
||||
use #krate::prelude::PyModuleMethods;
|
||||
pub fn add_to_module(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {
|
||||
use #pyo3_path::prelude::PyModuleMethods;
|
||||
use ::std::convert::Into;
|
||||
module.add_function(#krate::types::PyCFunction::internal_new(module.py(), &DEF, module.into())?)
|
||||
module.add_function(#pyo3_path::types::PyCFunction::internal_new(module.py(), &DEF, module.into())?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,10 +285,8 @@ pub fn impl_wrap_pyfunction(
|
|||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
impl #name::MakeDef {
|
||||
const DEF: #krate::impl_::pymethods::PyMethodDef = #methoddef;
|
||||
const DEF: #pyo3_path::impl_::pymethods::PyMethodDef = #methoddef;
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use crate::utils::Ctx;
|
||||
use crate::{
|
||||
attributes::{take_pyo3_options, CrateAttribute},
|
||||
konst::{ConstAttributes, ConstSpec},
|
||||
pyfunction::PyFunctionOptions,
|
||||
pymethod::{self, is_proto_method, MethodAndMethodDef, MethodAndSlotDef},
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use pymethod::GeneratedPyMethod;
|
||||
|
@ -90,6 +90,7 @@ pub fn impl_methods(
|
|||
methods_type: PyClassMethodsType,
|
||||
options: PyImplOptions,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
let mut trait_impls = Vec::new();
|
||||
let mut proto_impls = Vec::new();
|
||||
let mut methods = Vec::new();
|
||||
|
@ -102,7 +103,8 @@ pub fn impl_methods(
|
|||
syn::ImplItem::Fn(meth) => {
|
||||
let mut fun_options = PyFunctionOptions::from_attrs(&mut meth.attrs)?;
|
||||
fun_options.krate = fun_options.krate.or_else(|| options.krate.clone());
|
||||
match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, fun_options)? {
|
||||
match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, fun_options, ctx)?
|
||||
{
|
||||
GeneratedPyMethod::Method(MethodAndMethodDef {
|
||||
associated_method,
|
||||
method_def,
|
||||
|
@ -127,7 +129,7 @@ pub fn impl_methods(
|
|||
}
|
||||
}
|
||||
syn::ImplItem::Const(konst) => {
|
||||
let attributes = ConstAttributes::from_attrs(&mut konst.attrs)?;
|
||||
let attributes = ConstAttributes::from_attrs(&mut konst.attrs, ctx)?;
|
||||
if attributes.is_class_attr {
|
||||
let spec = ConstSpec {
|
||||
rust_ident: konst.ident.clone(),
|
||||
|
@ -137,7 +139,7 @@ pub fn impl_methods(
|
|||
let MethodAndMethodDef {
|
||||
associated_method,
|
||||
method_def,
|
||||
} = gen_py_const(ty, &spec);
|
||||
} = gen_py_const(ty, &spec, ctx);
|
||||
methods.push(quote!(#(#attrs)* #method_def));
|
||||
associated_methods.push(quote!(#(#attrs)* #associated_method));
|
||||
if is_proto_method(&spec.python_name().to_string()) {
|
||||
|
@ -158,21 +160,19 @@ pub fn impl_methods(
|
|||
}
|
||||
}
|
||||
|
||||
add_shared_proto_slots(ty, &mut proto_impls, implemented_proto_fragments);
|
||||
add_shared_proto_slots(ty, &mut proto_impls, implemented_proto_fragments, ctx);
|
||||
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let ctx = &Ctx::new(&options.krate);
|
||||
|
||||
let items = match methods_type {
|
||||
PyClassMethodsType::Specialization => impl_py_methods(ty, methods, proto_impls),
|
||||
PyClassMethodsType::Inventory => submit_methods_inventory(ty, methods, proto_impls),
|
||||
PyClassMethodsType::Specialization => impl_py_methods(ty, methods, proto_impls, ctx),
|
||||
PyClassMethodsType::Inventory => submit_methods_inventory(ty, methods, proto_impls, ctx),
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
// FIXME https://github.com/PyO3/pyo3/issues/3903
|
||||
#[allow(unknown_lints, non_local_definitions)]
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#(#trait_impls)*
|
||||
|
||||
#items
|
||||
|
@ -186,24 +186,25 @@ pub fn impl_methods(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec) -> MethodAndMethodDef {
|
||||
pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec<'_>, ctx: &Ctx) -> MethodAndMethodDef {
|
||||
let member = &spec.rust_ident;
|
||||
let wrapper_ident = format_ident!("__pymethod_{}__", member);
|
||||
let deprecations = &spec.attributes.deprecations;
|
||||
let python_name = &spec.null_terminated_python_name();
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
let associated_method = quote! {
|
||||
fn #wrapper_ident(py: _pyo3::Python<'_>) -> _pyo3::PyResult<_pyo3::PyObject> {
|
||||
fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
|
||||
#deprecations
|
||||
::std::result::Result::Ok(_pyo3::IntoPy::into_py(#cls::#member, py))
|
||||
::std::result::Result::Ok(#pyo3_path::IntoPy::into_py(#cls::#member, py))
|
||||
}
|
||||
};
|
||||
|
||||
let method_def = quote! {
|
||||
_pyo3::class::PyMethodDefType::ClassAttribute({
|
||||
_pyo3::class::PyClassAttributeDef::new(
|
||||
#pyo3_path::class::PyMethodDefType::ClassAttribute({
|
||||
#pyo3_path::class::PyClassAttributeDef::new(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyClassAttributeFactory(#cls::#wrapper_ident)
|
||||
#pyo3_path::impl_::pymethods::PyClassAttributeFactory(#cls::#wrapper_ident)
|
||||
)
|
||||
})
|
||||
};
|
||||
|
@ -218,13 +219,15 @@ fn impl_py_methods(
|
|||
ty: &syn::Type,
|
||||
methods: Vec<TokenStream>,
|
||||
proto_impls: Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
impl _pyo3::impl_::pyclass::PyMethods<#ty>
|
||||
for _pyo3::impl_::pyclass::PyClassImplCollector<#ty>
|
||||
impl #pyo3_path::impl_::pyclass::PyMethods<#ty>
|
||||
for #pyo3_path::impl_::pyclass::PyClassImplCollector<#ty>
|
||||
{
|
||||
fn py_methods(self) -> &'static _pyo3::impl_::pyclass::PyClassItems {
|
||||
static ITEMS: _pyo3::impl_::pyclass::PyClassItems = _pyo3::impl_::pyclass::PyClassItems {
|
||||
fn py_methods(self) -> &'static #pyo3_path::impl_::pyclass::PyClassItems {
|
||||
static ITEMS: #pyo3_path::impl_::pyclass::PyClassItems = #pyo3_path::impl_::pyclass::PyClassItems {
|
||||
methods: &[#(#methods),*],
|
||||
slots: &[#(#proto_impls),*]
|
||||
};
|
||||
|
@ -238,13 +241,15 @@ fn add_shared_proto_slots(
|
|||
ty: &syn::Type,
|
||||
proto_impls: &mut Vec<TokenStream>,
|
||||
mut implemented_proto_fragments: HashSet<String>,
|
||||
ctx: &Ctx,
|
||||
) {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
macro_rules! try_add_shared_slot {
|
||||
($slot:ident, $($fragments:literal),*) => {{
|
||||
let mut implemented = false;
|
||||
$(implemented |= implemented_proto_fragments.remove($fragments));*;
|
||||
if implemented {
|
||||
proto_impls.push(quote! { _pyo3::impl_::pyclass::$slot!(#ty) })
|
||||
proto_impls.push(quote! { #pyo3_path::impl_::pyclass::$slot!(#ty) })
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -294,11 +299,13 @@ fn submit_methods_inventory(
|
|||
ty: &syn::Type,
|
||||
methods: Vec<TokenStream>,
|
||||
proto_impls: Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
_pyo3::inventory::submit! {
|
||||
type Inventory = <#ty as _pyo3::impl_::pyclass::PyClassImpl>::Inventory;
|
||||
Inventory::new(_pyo3::impl_::pyclass::PyClassItems { methods: &[#(#methods),*], slots: &[#(#proto_impls),*] })
|
||||
#pyo3_path::inventory::submit! {
|
||||
type Inventory = <#ty as #pyo3_path::impl_::pyclass::PyClassImpl>::Inventory;
|
||||
Inventory::new(#pyo3_path::impl_::pyclass::PyClassItems { methods: &[#(#methods),*], slots: &[#(#proto_impls),*] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use crate::attributes::{NameAttribute, RenamingRule};
|
||||
use crate::method::{CallingConvention, ExtractErrorMode};
|
||||
use crate::utils::Ctx;
|
||||
use crate::utils::PythonDoc;
|
||||
use crate::{
|
||||
method::{FnArg, FnSpec, FnType, SelfType},
|
||||
|
@ -160,8 +161,9 @@ impl<'a> PyMethod<'a> {
|
|||
sig: &'a mut syn::Signature,
|
||||
meth_attrs: &mut Vec<syn::Attribute>,
|
||||
options: PyFunctionOptions,
|
||||
ctx: &'a Ctx,
|
||||
) -> Result<Self> {
|
||||
let spec = FnSpec::parse(sig, meth_attrs, options)?;
|
||||
let spec = FnSpec::parse(sig, meth_attrs, options, ctx)?;
|
||||
|
||||
let method_name = spec.python_name.to_string();
|
||||
let kind = PyMethodKind::from_name(&method_name);
|
||||
|
@ -186,33 +188,35 @@ pub fn gen_py_method(
|
|||
sig: &mut syn::Signature,
|
||||
meth_attrs: &mut Vec<syn::Attribute>,
|
||||
options: PyFunctionOptions,
|
||||
ctx: &Ctx,
|
||||
) -> Result<GeneratedPyMethod> {
|
||||
check_generic(sig)?;
|
||||
ensure_function_options_valid(&options)?;
|
||||
let method = PyMethod::parse(sig, meth_attrs, options)?;
|
||||
let method = PyMethod::parse(sig, meth_attrs, options, ctx)?;
|
||||
let spec = &method.spec;
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
Ok(match (method.kind, &spec.tp) {
|
||||
// Class attributes go before protos so that class attributes can be used to set proto
|
||||
// method to None.
|
||||
(_, FnType::ClassAttribute) => {
|
||||
GeneratedPyMethod::Method(impl_py_class_attribute(cls, spec)?)
|
||||
GeneratedPyMethod::Method(impl_py_class_attribute(cls, spec, ctx)?)
|
||||
}
|
||||
(PyMethodKind::Proto(proto_kind), _) => {
|
||||
ensure_no_forbidden_protocol_attributes(&proto_kind, spec, &method.method_name)?;
|
||||
match proto_kind {
|
||||
PyMethodProtoKind::Slot(slot_def) => {
|
||||
let slot = slot_def.generate_type_slot(cls, spec, &method.method_name)?;
|
||||
let slot = slot_def.generate_type_slot(cls, spec, &method.method_name, ctx)?;
|
||||
GeneratedPyMethod::Proto(slot)
|
||||
}
|
||||
PyMethodProtoKind::Call => {
|
||||
GeneratedPyMethod::Proto(impl_call_slot(cls, method.spec)?)
|
||||
GeneratedPyMethod::Proto(impl_call_slot(cls, method.spec, ctx)?)
|
||||
}
|
||||
PyMethodProtoKind::Traverse => {
|
||||
GeneratedPyMethod::Proto(impl_traverse_slot(cls, spec)?)
|
||||
GeneratedPyMethod::Proto(impl_traverse_slot(cls, spec, ctx)?)
|
||||
}
|
||||
PyMethodProtoKind::SlotFragment(slot_fragment_def) => {
|
||||
let proto = slot_fragment_def.generate_pyproto_fragment(cls, spec)?;
|
||||
let proto = slot_fragment_def.generate_pyproto_fragment(cls, spec, ctx)?;
|
||||
GeneratedPyMethod::SlotTraitImpl(method.method_name, proto)
|
||||
}
|
||||
}
|
||||
|
@ -223,22 +227,25 @@ pub fn gen_py_method(
|
|||
spec,
|
||||
&spec.get_doc(meth_attrs),
|
||||
None,
|
||||
ctx,
|
||||
)?),
|
||||
(_, FnType::FnClass(_)) => GeneratedPyMethod::Method(impl_py_method_def(
|
||||
cls,
|
||||
spec,
|
||||
&spec.get_doc(meth_attrs),
|
||||
Some(quote!(_pyo3::ffi::METH_CLASS)),
|
||||
Some(quote!(#pyo3_path::ffi::METH_CLASS)),
|
||||
ctx,
|
||||
)?),
|
||||
(_, FnType::FnStatic) => GeneratedPyMethod::Method(impl_py_method_def(
|
||||
cls,
|
||||
spec,
|
||||
&spec.get_doc(meth_attrs),
|
||||
Some(quote!(_pyo3::ffi::METH_STATIC)),
|
||||
Some(quote!(#pyo3_path::ffi::METH_STATIC)),
|
||||
ctx,
|
||||
)?),
|
||||
// special prototypes
|
||||
(_, FnType::FnNew) | (_, FnType::FnNewClass(_)) => {
|
||||
GeneratedPyMethod::Proto(impl_py_method_def_new(cls, spec)?)
|
||||
GeneratedPyMethod::Proto(impl_py_method_def_new(cls, spec, ctx)?)
|
||||
}
|
||||
|
||||
(_, FnType::Getter(self_type)) => GeneratedPyMethod::Method(impl_py_getter_def(
|
||||
|
@ -248,6 +255,7 @@ pub fn gen_py_method(
|
|||
spec,
|
||||
doc: spec.get_doc(meth_attrs),
|
||||
},
|
||||
ctx,
|
||||
)?),
|
||||
(_, FnType::Setter(self_type)) => GeneratedPyMethod::Method(impl_py_setter_def(
|
||||
cls,
|
||||
|
@ -256,6 +264,7 @@ pub fn gen_py_method(
|
|||
spec,
|
||||
doc: spec.get_doc(meth_attrs),
|
||||
},
|
||||
ctx,
|
||||
)?),
|
||||
(_, FnType::FnModule(_)) => {
|
||||
unreachable!("methods cannot be FnModule")
|
||||
|
@ -305,18 +314,20 @@ pub fn impl_py_method_def(
|
|||
spec: &FnSpec<'_>,
|
||||
doc: &PythonDoc,
|
||||
flags: Option<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndMethodDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let wrapper_ident = format_ident!("__pymethod_{}__", spec.python_name);
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?;
|
||||
let add_flags = flags.map(|flags| quote!(.flags(#flags)));
|
||||
let methoddef_type = match spec.tp {
|
||||
FnType::FnStatic => quote!(Static),
|
||||
FnType::FnClass(_) => quote!(Class),
|
||||
_ => quote!(Method),
|
||||
};
|
||||
let methoddef = spec.get_methoddef(quote! { #cls::#wrapper_ident }, doc);
|
||||
let methoddef = spec.get_methoddef(quote! { #cls::#wrapper_ident }, doc, ctx);
|
||||
let method_def = quote! {
|
||||
_pyo3::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
|
||||
#pyo3_path::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
|
||||
};
|
||||
Ok(MethodAndMethodDef {
|
||||
associated_method,
|
||||
|
@ -325,9 +336,14 @@ pub fn impl_py_method_def(
|
|||
}
|
||||
|
||||
/// Also used by pyclass.
|
||||
pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<MethodAndSlotDef> {
|
||||
pub fn impl_py_method_def_new(
|
||||
cls: &syn::Type,
|
||||
spec: &FnSpec<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndSlotDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let wrapper_ident = syn::Ident::new("__pymethod___new____", Span::call_site());
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?;
|
||||
// Use just the text_signature_call_signature() because the class' Python name
|
||||
// isn't known to `#[pymethods]` - that has to be attached at runtime from the PyClassImpl
|
||||
// trait implementation created by `#[pyclass]`.
|
||||
|
@ -337,18 +353,18 @@ pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<Meth
|
|||
);
|
||||
let deprecations = &spec.deprecations;
|
||||
let slot_def = quote! {
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_new,
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::Py_tp_new,
|
||||
pfunc: {
|
||||
unsafe extern "C" fn trampoline(
|
||||
subtype: *mut _pyo3::ffi::PyTypeObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject,
|
||||
) -> *mut _pyo3::ffi::PyObject
|
||||
subtype: *mut #pyo3_path::ffi::PyTypeObject,
|
||||
args: *mut #pyo3_path::ffi::PyObject,
|
||||
kwargs: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> *mut #pyo3_path::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
|
||||
use _pyo3::impl_::pyclass::*;
|
||||
use #pyo3_path::impl_::pyclass::*;
|
||||
impl PyClassNewTextSignature<#cls> for PyClassImplCollector<#cls> {
|
||||
#[inline]
|
||||
fn new_text_signature(self) -> ::std::option::Option<&'static str> {
|
||||
|
@ -356,7 +372,7 @@ pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<Meth
|
|||
}
|
||||
}
|
||||
|
||||
_pyo3::impl_::trampoline::newfunc(
|
||||
#pyo3_path::impl_::trampoline::newfunc(
|
||||
subtype,
|
||||
args,
|
||||
kwargs,
|
||||
|
@ -364,7 +380,7 @@ pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<Meth
|
|||
)
|
||||
}
|
||||
trampoline
|
||||
} as _pyo3::ffi::newfunc as _
|
||||
} as #pyo3_path::ffi::newfunc as _
|
||||
}
|
||||
};
|
||||
Ok(MethodAndSlotDef {
|
||||
|
@ -373,24 +389,26 @@ pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<Meth
|
|||
})
|
||||
}
|
||||
|
||||
fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec<'_>) -> Result<MethodAndSlotDef> {
|
||||
fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec<'_>, ctx: &Ctx) -> Result<MethodAndSlotDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
|
||||
// HACK: __call__ proto slot must always use varargs calling convention, so change the spec.
|
||||
// Probably indicates there's a refactoring opportunity somewhere.
|
||||
spec.convention = CallingConvention::Varargs;
|
||||
|
||||
let wrapper_ident = syn::Ident::new("__pymethod___call____", Span::call_site());
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
|
||||
let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?;
|
||||
let slot_def = quote! {
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_call,
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::Py_tp_call,
|
||||
pfunc: {
|
||||
unsafe extern "C" fn trampoline(
|
||||
slf: *mut _pyo3::ffi::PyObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject,
|
||||
) -> *mut _pyo3::ffi::PyObject
|
||||
slf: *mut #pyo3_path::ffi::PyObject,
|
||||
args: *mut #pyo3_path::ffi::PyObject,
|
||||
kwargs: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> *mut #pyo3_path::ffi::PyObject
|
||||
{
|
||||
_pyo3::impl_::trampoline::ternaryfunc(
|
||||
#pyo3_path::impl_::trampoline::ternaryfunc(
|
||||
slf,
|
||||
args,
|
||||
kwargs,
|
||||
|
@ -398,7 +416,7 @@ fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec<'_>) -> Result<MethodAndSlot
|
|||
)
|
||||
}
|
||||
trampoline
|
||||
} as _pyo3::ffi::ternaryfunc as _
|
||||
} as #pyo3_path::ffi::ternaryfunc as _
|
||||
}
|
||||
};
|
||||
Ok(MethodAndSlotDef {
|
||||
|
@ -407,7 +425,12 @@ fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec<'_>) -> Result<MethodAndSlot
|
|||
})
|
||||
}
|
||||
|
||||
fn impl_traverse_slot(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<MethodAndSlotDef> {
|
||||
fn impl_traverse_slot(
|
||||
cls: &syn::Type,
|
||||
spec: &FnSpec<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<MethodAndSlotDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
if let (Some(py_arg), _) = split_off_python_arg(&spec.signature.arguments) {
|
||||
return Err(syn::Error::new_spanned(py_arg.ty, "__traverse__ may not take `Python`. \
|
||||
Usually, an implementation of `__traverse__` should do nothing but calls to `visit.call`. \
|
||||
|
@ -419,17 +442,17 @@ fn impl_traverse_slot(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<MethodA
|
|||
|
||||
let associated_method = quote! {
|
||||
pub unsafe extern "C" fn __pymethod_traverse__(
|
||||
slf: *mut _pyo3::ffi::PyObject,
|
||||
visit: _pyo3::ffi::visitproc,
|
||||
slf: *mut #pyo3_path::ffi::PyObject,
|
||||
visit: #pyo3_path::ffi::visitproc,
|
||||
arg: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int {
|
||||
_pyo3::impl_::pymethods::_call_traverse::<#cls>(slf, #cls::#rust_fn_ident, visit, arg)
|
||||
#pyo3_path::impl_::pymethods::_call_traverse::<#cls>(slf, #cls::#rust_fn_ident, visit, arg)
|
||||
}
|
||||
};
|
||||
let slot_def = quote! {
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_traverse,
|
||||
pfunc: #cls::__pymethod_traverse__ as _pyo3::ffi::traverseproc as _
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::Py_tp_traverse,
|
||||
pfunc: #cls::__pymethod_traverse__ as #pyo3_path::ffi::traverseproc as _
|
||||
}
|
||||
};
|
||||
Ok(MethodAndSlotDef {
|
||||
|
@ -438,7 +461,12 @@ fn impl_traverse_slot(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<MethodA
|
|||
})
|
||||
}
|
||||
|
||||
fn impl_py_class_attribute(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<MethodAndMethodDef> {
|
||||
fn impl_py_class_attribute(
|
||||
cls: &syn::Type,
|
||||
spec: &FnSpec<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<MethodAndMethodDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
||||
ensure_spanned!(
|
||||
args.is_empty(),
|
||||
|
@ -454,20 +482,20 @@ fn impl_py_class_attribute(cls: &syn::Type, spec: &FnSpec<'_>) -> syn::Result<Me
|
|||
|
||||
let wrapper_ident = format_ident!("__pymethod_{}__", name);
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
let body = quotes::ok_wrap(fncall);
|
||||
let body = quotes::ok_wrap(fncall, ctx);
|
||||
|
||||
let associated_method = quote! {
|
||||
fn #wrapper_ident(py: _pyo3::Python<'_>) -> _pyo3::PyResult<_pyo3::PyObject> {
|
||||
fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
|
||||
let function = #cls::#name; // Shadow the method name to avoid #3017
|
||||
_pyo3::impl_::wrap::map_result_into_py(py, #body)
|
||||
#pyo3_path::impl_::wrap::map_result_into_py(py, #body)
|
||||
}
|
||||
};
|
||||
|
||||
let method_def = quote! {
|
||||
_pyo3::class::PyMethodDefType::ClassAttribute({
|
||||
_pyo3::class::PyClassAttributeDef::new(
|
||||
#pyo3_path::class::PyMethodDefType::ClassAttribute({
|
||||
#pyo3_path::class::PyClassAttributeDef::new(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyClassAttributeFactory(#cls::#wrapper_ident)
|
||||
#pyo3_path::impl_::pymethods::PyClassAttributeFactory(#cls::#wrapper_ident)
|
||||
)
|
||||
})
|
||||
};
|
||||
|
@ -483,9 +511,10 @@ fn impl_call_setter(
|
|||
spec: &FnSpec<'_>,
|
||||
self_type: &SelfType,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
||||
let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders);
|
||||
let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx);
|
||||
|
||||
if args.is_empty() {
|
||||
bail_spanned!(spec.name.span() => "setter function expected to have one argument");
|
||||
|
@ -510,7 +539,9 @@ fn impl_call_setter(
|
|||
pub fn impl_py_setter_def(
|
||||
cls: &syn::Type,
|
||||
property_type: PropertyType<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndMethodDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let python_name = property_type.null_terminated_python_name()?;
|
||||
let doc = property_type.doc();
|
||||
let mut holders = Vec::new();
|
||||
|
@ -522,7 +553,7 @@ pub fn impl_py_setter_def(
|
|||
mutable: true,
|
||||
span: Span::call_site(),
|
||||
}
|
||||
.receiver(cls, ExtractErrorMode::Raise, &mut holders);
|
||||
.receiver(cls, ExtractErrorMode::Raise, &mut holders, ctx);
|
||||
if let Some(ident) = &field.ident {
|
||||
// named struct field
|
||||
quote!({ #slf.#ident = _val; })
|
||||
|
@ -534,7 +565,7 @@ pub fn impl_py_setter_def(
|
|||
}
|
||||
PropertyType::Function {
|
||||
spec, self_type, ..
|
||||
} => impl_call_setter(cls, spec, self_type, &mut holders)?,
|
||||
} => impl_call_setter(cls, spec, self_type, &mut holders, ctx)?,
|
||||
};
|
||||
|
||||
let wrapper_ident = match property_type {
|
||||
|
@ -568,27 +599,27 @@ pub fn impl_py_setter_def(
|
|||
let associated_method = quote! {
|
||||
#cfg_attrs
|
||||
unsafe fn #wrapper_ident(
|
||||
py: _pyo3::Python<'_>,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_value: *mut _pyo3::ffi::PyObject,
|
||||
) -> _pyo3::PyResult<::std::os::raw::c_int> {
|
||||
py: #pyo3_path::Python<'_>,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
_value: *mut #pyo3_path::ffi::PyObject,
|
||||
) -> #pyo3_path::PyResult<::std::os::raw::c_int> {
|
||||
use ::std::convert::Into;
|
||||
let _value = _pyo3::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_value)
|
||||
let _value = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_value)
|
||||
.ok_or_else(|| {
|
||||
_pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
|
||||
#pyo3_path::exceptions::PyAttributeError::new_err("can't delete attribute")
|
||||
})?;
|
||||
let _val = _pyo3::FromPyObject::extract_bound(_value.into())?;
|
||||
let _val = #pyo3_path::FromPyObject::extract_bound(_value.into())?;
|
||||
#( #holders )*
|
||||
_pyo3::callback::convert(py, #setter_impl)
|
||||
#pyo3_path::callback::convert(py, #setter_impl)
|
||||
}
|
||||
};
|
||||
|
||||
let method_def = quote! {
|
||||
#cfg_attrs
|
||||
_pyo3::class::PyMethodDefType::Setter(
|
||||
_pyo3::class::PySetterDef::new(
|
||||
#pyo3_path::class::PyMethodDefType::Setter(
|
||||
#pyo3_path::class::PySetterDef::new(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PySetter(#cls::#wrapper_ident),
|
||||
#pyo3_path::impl_::pymethods::PySetter(#cls::#wrapper_ident),
|
||||
#doc
|
||||
)
|
||||
)
|
||||
|
@ -605,9 +636,10 @@ fn impl_call_getter(
|
|||
spec: &FnSpec<'_>,
|
||||
self_type: &SelfType,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
||||
let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders);
|
||||
let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx);
|
||||
ensure_spanned!(
|
||||
args.is_empty(),
|
||||
args[0].ty.span() => "getter function can only have one argument (of type pyo3::Python)"
|
||||
|
@ -627,7 +659,9 @@ fn impl_call_getter(
|
|||
pub fn impl_py_getter_def(
|
||||
cls: &syn::Type,
|
||||
property_type: PropertyType<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndMethodDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let python_name = property_type.null_terminated_python_name()?;
|
||||
let doc = property_type.doc();
|
||||
|
||||
|
@ -640,7 +674,7 @@ pub fn impl_py_getter_def(
|
|||
mutable: false,
|
||||
span: Span::call_site(),
|
||||
}
|
||||
.receiver(cls, ExtractErrorMode::Raise, &mut holders);
|
||||
.receiver(cls, ExtractErrorMode::Raise, &mut holders, ctx);
|
||||
let field_token = if let Some(ident) = &field.ident {
|
||||
// named struct field
|
||||
ident.to_token_stream()
|
||||
|
@ -648,17 +682,23 @@ pub fn impl_py_getter_def(
|
|||
// tuple struct field
|
||||
syn::Index::from(field_index).to_token_stream()
|
||||
};
|
||||
quotes::map_result_into_ptr(quotes::ok_wrap(quote! {
|
||||
::std::clone::Clone::clone(&(#slf.#field_token))
|
||||
}))
|
||||
quotes::map_result_into_ptr(
|
||||
quotes::ok_wrap(
|
||||
quote! {
|
||||
::std::clone::Clone::clone(&(#slf.#field_token))
|
||||
},
|
||||
ctx,
|
||||
),
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
// Forward to `IntoPyCallbackOutput`, to handle `#[getter]`s returning results.
|
||||
PropertyType::Function {
|
||||
spec, self_type, ..
|
||||
} => {
|
||||
let call = impl_call_getter(cls, spec, self_type, &mut holders)?;
|
||||
let call = impl_call_getter(cls, spec, self_type, &mut holders, ctx)?;
|
||||
quote! {
|
||||
_pyo3::callback::convert(py, #call)
|
||||
#pyo3_path::callback::convert(py, #call)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -694,9 +734,9 @@ pub fn impl_py_getter_def(
|
|||
let associated_method = quote! {
|
||||
#cfg_attrs
|
||||
unsafe fn #wrapper_ident(
|
||||
py: _pyo3::Python<'_>,
|
||||
_slf: *mut _pyo3::ffi::PyObject
|
||||
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
|
||||
py: #pyo3_path::Python<'_>,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject
|
||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||
#( #holders )*
|
||||
let result = #body;
|
||||
result
|
||||
|
@ -705,10 +745,10 @@ pub fn impl_py_getter_def(
|
|||
|
||||
let method_def = quote! {
|
||||
#cfg_attrs
|
||||
_pyo3::class::PyMethodDefType::Getter(
|
||||
_pyo3::class::PyGetterDef::new(
|
||||
#pyo3_path::class::PyMethodDefType::Getter(
|
||||
#pyo3_path::class::PyGetterDef::new(
|
||||
#python_name,
|
||||
_pyo3::impl_::pymethods::PyGetter(#cls::#wrapper_ident),
|
||||
#pyo3_path::impl_::pymethods::PyGetter(#cls::#wrapper_ident),
|
||||
#doc
|
||||
)
|
||||
)
|
||||
|
@ -786,7 +826,7 @@ pub const __REPR__: SlotDef = SlotDef::new("Py_tp_repr", "reprfunc");
|
|||
const __HASH__: SlotDef = SlotDef::new("Py_tp_hash", "hashfunc")
|
||||
.ret_ty(Ty::PyHashT)
|
||||
.return_conversion(TokenGenerator(
|
||||
|| quote! { _pyo3::callback::HashCallbackOutput },
|
||||
|Ctx { pyo3_path }: &Ctx| quote! { #pyo3_path::callback::HashCallbackOutput },
|
||||
));
|
||||
pub const __RICHCMP__: SlotDef = SlotDef::new("Py_tp_richcompare", "richcmpfunc")
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
|
@ -796,14 +836,16 @@ const __GET__: SlotDef = SlotDef::new("Py_tp_descr_get", "descrgetfunc")
|
|||
const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc");
|
||||
const __NEXT__: SlotDef = SlotDef::new("Py_tp_iternext", "iternextfunc")
|
||||
.return_specialized_conversion(
|
||||
TokenGenerator(|| quote! { IterBaseKind, IterOptionKind, IterResultOptionKind }),
|
||||
TokenGenerator(|| quote! { iter_tag }),
|
||||
TokenGenerator(|_| quote! { IterBaseKind, IterOptionKind, IterResultOptionKind }),
|
||||
TokenGenerator(|_| quote! { iter_tag }),
|
||||
);
|
||||
const __AWAIT__: SlotDef = SlotDef::new("Py_am_await", "unaryfunc");
|
||||
const __AITER__: SlotDef = SlotDef::new("Py_am_aiter", "unaryfunc");
|
||||
const __ANEXT__: SlotDef = SlotDef::new("Py_am_anext", "unaryfunc").return_specialized_conversion(
|
||||
TokenGenerator(|| quote! { AsyncIterBaseKind, AsyncIterOptionKind, AsyncIterResultOptionKind }),
|
||||
TokenGenerator(|| quote! { async_iter_tag }),
|
||||
TokenGenerator(
|
||||
|_| quote! { AsyncIterBaseKind, AsyncIterOptionKind, AsyncIterResultOptionKind },
|
||||
),
|
||||
TokenGenerator(|_| quote! { async_iter_tag }),
|
||||
);
|
||||
const __LEN__: SlotDef = SlotDef::new("Py_mp_length", "lenfunc").ret_ty(Ty::PySsizeT);
|
||||
const __CONTAINS__: SlotDef = SlotDef::new("Py_sq_contains", "objobjproc")
|
||||
|
@ -905,16 +947,17 @@ enum Ty {
|
|||
}
|
||||
|
||||
impl Ty {
|
||||
fn ffi_type(self) -> TokenStream {
|
||||
fn ffi_type(self, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
match self {
|
||||
Ty::Object | Ty::MaybeNullObject => quote! { *mut _pyo3::ffi::PyObject },
|
||||
Ty::NonNullObject => quote! { ::std::ptr::NonNull<_pyo3::ffi::PyObject> },
|
||||
Ty::IPowModulo => quote! { _pyo3::impl_::pymethods::IPowModulo },
|
||||
Ty::Object | Ty::MaybeNullObject => quote! { *mut #pyo3_path::ffi::PyObject },
|
||||
Ty::NonNullObject => quote! { ::std::ptr::NonNull<#pyo3_path::ffi::PyObject> },
|
||||
Ty::IPowModulo => quote! { #pyo3_path::impl_::pymethods::IPowModulo },
|
||||
Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int },
|
||||
Ty::PyHashT => quote! { _pyo3::ffi::Py_hash_t },
|
||||
Ty::PySsizeT => quote! { _pyo3::ffi::Py_ssize_t },
|
||||
Ty::PyHashT => quote! { #pyo3_path::ffi::Py_hash_t },
|
||||
Ty::PySsizeT => quote! { #pyo3_path::ffi::Py_ssize_t },
|
||||
Ty::Void => quote! { () },
|
||||
Ty::PyBuffer => quote! { *mut _pyo3::ffi::Py_buffer },
|
||||
Ty::PyBuffer => quote! { *mut #pyo3_path::ffi::Py_buffer },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -924,14 +967,16 @@ impl Ty {
|
|||
arg: &FnArg<'_>,
|
||||
extract_error_mode: ExtractErrorMode,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let name_str = arg.name.unraw().to_string();
|
||||
match self {
|
||||
Ty::Object => extract_object(
|
||||
extract_error_mode,
|
||||
holders,
|
||||
&name_str,
|
||||
quote! { #ident },
|
||||
quote! { #ident },ctx
|
||||
),
|
||||
Ty::MaybeNullObject => extract_object(
|
||||
extract_error_mode,
|
||||
|
@ -939,36 +984,36 @@ impl Ty {
|
|||
&name_str,
|
||||
quote! {
|
||||
if #ident.is_null() {
|
||||
_pyo3::ffi::Py_None()
|
||||
#pyo3_path::ffi::Py_None()
|
||||
} else {
|
||||
#ident
|
||||
}
|
||||
},
|
||||
},ctx
|
||||
),
|
||||
Ty::NonNullObject => extract_object(
|
||||
extract_error_mode,
|
||||
holders,
|
||||
&name_str,
|
||||
quote! { #ident.as_ptr() },
|
||||
quote! { #ident.as_ptr() },ctx
|
||||
),
|
||||
Ty::IPowModulo => extract_object(
|
||||
extract_error_mode,
|
||||
holders,
|
||||
&name_str,
|
||||
quote! { #ident.as_ptr() },
|
||||
quote! { #ident.as_ptr() },ctx
|
||||
),
|
||||
Ty::CompareOp => extract_error_mode.handle_error(
|
||||
quote! {
|
||||
_pyo3::class::basic::CompareOp::from_raw(#ident)
|
||||
.ok_or_else(|| _pyo3::exceptions::PyValueError::new_err("invalid comparison operator"))
|
||||
},
|
||||
#pyo3_path::class::basic::CompareOp::from_raw(#ident)
|
||||
.ok_or_else(|| #pyo3_path::exceptions::PyValueError::new_err("invalid comparison operator"))
|
||||
},ctx
|
||||
),
|
||||
Ty::PySsizeT => {
|
||||
let ty = arg.ty;
|
||||
extract_error_mode.handle_error(
|
||||
quote! {
|
||||
::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| _pyo3::exceptions::PyValueError::new_err(e.to_string()))
|
||||
},
|
||||
::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| #pyo3_path::exceptions::PyValueError::new_err(e.to_string()))
|
||||
},ctx
|
||||
)
|
||||
}
|
||||
// Just pass other types through unmodified
|
||||
|
@ -982,19 +1027,24 @@ fn extract_object(
|
|||
holders: &mut Vec<TokenStream>,
|
||||
name: &str,
|
||||
source_ptr: TokenStream,
|
||||
ctx: &Ctx,
|
||||
) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), Span::call_site());
|
||||
holders.push(quote! {
|
||||
#[allow(clippy::let_unit_value)]
|
||||
let mut #holder = _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
||||
});
|
||||
extract_error_mode.handle_error(quote! {
|
||||
_pyo3::impl_::extract_argument::extract_argument(
|
||||
&_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr),
|
||||
&mut #holder,
|
||||
#name
|
||||
)
|
||||
})
|
||||
extract_error_mode.handle_error(
|
||||
quote! {
|
||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||
&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr),
|
||||
&mut #holder,
|
||||
#name
|
||||
)
|
||||
},
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
enum ReturnMode {
|
||||
|
@ -1004,21 +1054,29 @@ enum ReturnMode {
|
|||
}
|
||||
|
||||
impl ReturnMode {
|
||||
fn return_call_output(&self, call: TokenStream) -> TokenStream {
|
||||
fn return_call_output(&self, call: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
match self {
|
||||
ReturnMode::Conversion(conversion) => quote! {
|
||||
let _result: _pyo3::PyResult<#conversion> = _pyo3::callback::convert(py, #call);
|
||||
_pyo3::callback::convert(py, _result)
|
||||
},
|
||||
ReturnMode::SpecializedConversion(traits, tag) => quote! {
|
||||
let _result = #call;
|
||||
use _pyo3::impl_::pymethods::{#traits};
|
||||
(&_result).#tag().convert(py, _result)
|
||||
},
|
||||
ReturnMode::Conversion(conversion) => {
|
||||
let conversion = TokenGeneratorCtx(*conversion, ctx);
|
||||
quote! {
|
||||
let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::callback::convert(py, #call);
|
||||
#pyo3_path::callback::convert(py, _result)
|
||||
}
|
||||
}
|
||||
ReturnMode::SpecializedConversion(traits, tag) => {
|
||||
let traits = TokenGeneratorCtx(*traits, ctx);
|
||||
let tag = TokenGeneratorCtx(*tag, ctx);
|
||||
quote! {
|
||||
let _result = #call;
|
||||
use #pyo3_path::impl_::pymethods::{#traits};
|
||||
(&_result).#tag().convert(py, _result)
|
||||
}
|
||||
}
|
||||
ReturnMode::ReturnSelf => quote! {
|
||||
let _result: _pyo3::PyResult<()> = _pyo3::callback::convert(py, #call);
|
||||
let _result: #pyo3_path::PyResult<()> = #pyo3_path::callback::convert(py, #call);
|
||||
_result?;
|
||||
_pyo3::ffi::Py_XINCREF(_raw_slf);
|
||||
#pyo3_path::ffi::Py_XINCREF(_raw_slf);
|
||||
::std::result::Result::Ok(_raw_slf)
|
||||
},
|
||||
}
|
||||
|
@ -1094,7 +1152,9 @@ impl SlotDef {
|
|||
cls: &syn::Type,
|
||||
spec: &FnSpec<'_>,
|
||||
method_name: &str,
|
||||
ctx: &Ctx,
|
||||
) -> Result<MethodAndSlotDef> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let SlotDef {
|
||||
slot,
|
||||
func_ty,
|
||||
|
@ -1110,12 +1170,12 @@ impl SlotDef {
|
|||
spec.name.span() => format!("`{}` must be `unsafe fn`", method_name)
|
||||
);
|
||||
}
|
||||
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
|
||||
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type(ctx)).collect();
|
||||
let arg_idents: &Vec<_> = &(0..arguments.len())
|
||||
.map(|i| format_ident!("arg{}", i))
|
||||
.collect();
|
||||
let wrapper_ident = format_ident!("__pymethod_{}__", method_name);
|
||||
let ret_ty = ret_ty.ffi_type();
|
||||
let ret_ty = ret_ty.ffi_type(ctx);
|
||||
let mut holders = Vec::new();
|
||||
let body = generate_method_body(
|
||||
cls,
|
||||
|
@ -1124,14 +1184,15 @@ impl SlotDef {
|
|||
*extract_error_mode,
|
||||
&mut holders,
|
||||
return_mode.as_ref(),
|
||||
ctx,
|
||||
)?;
|
||||
let name = spec.name;
|
||||
let associated_method = quote! {
|
||||
unsafe fn #wrapper_ident(
|
||||
py: _pyo3::Python<'_>,
|
||||
_raw_slf: *mut _pyo3::ffi::PyObject,
|
||||
py: #pyo3_path::Python<'_>,
|
||||
_raw_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
#(#arg_idents: #arg_types),*
|
||||
) -> _pyo3::PyResult<#ret_ty> {
|
||||
) -> #pyo3_path::PyResult<#ret_ty> {
|
||||
let function = #cls::#name; // Shadow the method name to avoid #3017
|
||||
let _slf = _raw_slf;
|
||||
#( #holders )*
|
||||
|
@ -1140,20 +1201,20 @@ impl SlotDef {
|
|||
};
|
||||
let slot_def = quote! {{
|
||||
unsafe extern "C" fn trampoline(
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
#(#arg_idents: #arg_types),*
|
||||
) -> #ret_ty
|
||||
{
|
||||
_pyo3::impl_::trampoline:: #func_ty (
|
||||
#pyo3_path::impl_::trampoline:: #func_ty (
|
||||
_slf,
|
||||
#(#arg_idents,)*
|
||||
#cls::#wrapper_ident
|
||||
)
|
||||
}
|
||||
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::#slot,
|
||||
pfunc: trampoline as _pyo3::ffi::#func_ty as _
|
||||
#pyo3_path::ffi::PyType_Slot {
|
||||
slot: #pyo3_path::ffi::#slot,
|
||||
pfunc: trampoline as #pyo3_path::ffi::#func_ty as _
|
||||
}
|
||||
}};
|
||||
Ok(MethodAndSlotDef {
|
||||
|
@ -1170,15 +1231,19 @@ fn generate_method_body(
|
|||
extract_error_mode: ExtractErrorMode,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
return_mode: Option<&ReturnMode>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let self_arg = spec.tp.self_arg(Some(cls), extract_error_mode, holders);
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let self_arg = spec
|
||||
.tp
|
||||
.self_arg(Some(cls), extract_error_mode, holders, ctx);
|
||||
let rust_name = spec.name;
|
||||
let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders)?;
|
||||
let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?;
|
||||
let call = quote! { #cls::#rust_name(#self_arg #(#args),*) };
|
||||
Ok(if let Some(return_mode) = return_mode {
|
||||
return_mode.return_call_output(call)
|
||||
return_mode.return_call_output(call, ctx)
|
||||
} else {
|
||||
quote! { _pyo3::callback::convert(py, #call) }
|
||||
quote! { #pyo3_path::callback::convert(py, #call) }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1209,7 +1274,13 @@ impl SlotFragmentDef {
|
|||
self
|
||||
}
|
||||
|
||||
fn generate_pyproto_fragment(&self, cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStream> {
|
||||
fn generate_pyproto_fragment(
|
||||
&self,
|
||||
cls: &syn::Type,
|
||||
spec: &FnSpec<'_>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<TokenStream> {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
let SlotFragmentDef {
|
||||
fragment,
|
||||
arguments,
|
||||
|
@ -1219,7 +1290,7 @@ impl SlotFragmentDef {
|
|||
let fragment_trait = format_ident!("PyClass{}SlotFragment", fragment);
|
||||
let method = syn::Ident::new(fragment, Span::call_site());
|
||||
let wrapper_ident = format_ident!("__pymethod_{}__", fragment);
|
||||
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
|
||||
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type(ctx)).collect();
|
||||
let arg_idents: &Vec<_> = &(0..arguments.len())
|
||||
.map(|i| format_ident!("arg{}", i))
|
||||
.collect();
|
||||
|
@ -1231,30 +1302,31 @@ impl SlotFragmentDef {
|
|||
*extract_error_mode,
|
||||
&mut holders,
|
||||
None,
|
||||
ctx,
|
||||
)?;
|
||||
let ret_ty = ret_ty.ffi_type();
|
||||
let ret_ty = ret_ty.ffi_type(ctx);
|
||||
Ok(quote! {
|
||||
impl #cls {
|
||||
unsafe fn #wrapper_ident(
|
||||
py: _pyo3::Python,
|
||||
_raw_slf: *mut _pyo3::ffi::PyObject,
|
||||
py: #pyo3_path::Python,
|
||||
_raw_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
#(#arg_idents: #arg_types),*
|
||||
) -> _pyo3::PyResult<#ret_ty> {
|
||||
) -> #pyo3_path::PyResult<#ret_ty> {
|
||||
let _slf = _raw_slf;
|
||||
#( #holders )*
|
||||
#body
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::impl_::pyclass::#fragment_trait<#cls> for _pyo3::impl_::pyclass::PyClassImplCollector<#cls> {
|
||||
impl #pyo3_path::impl_::pyclass::#fragment_trait<#cls> for #pyo3_path::impl_::pyclass::PyClassImplCollector<#cls> {
|
||||
|
||||
#[inline]
|
||||
unsafe fn #method(
|
||||
self,
|
||||
py: _pyo3::Python,
|
||||
_raw_slf: *mut _pyo3::ffi::PyObject,
|
||||
py: #pyo3_path::Python,
|
||||
_raw_slf: *mut #pyo3_path::ffi::PyObject,
|
||||
#(#arg_idents: #arg_types),*
|
||||
) -> _pyo3::PyResult<#ret_ty> {
|
||||
) -> #pyo3_path::PyResult<#ret_ty> {
|
||||
#cls::#wrapper_ident(py, _raw_slf, #(#arg_idents),*)
|
||||
}
|
||||
}
|
||||
|
@ -1341,6 +1413,7 @@ fn extract_proto_arguments(
|
|||
proto_args: &[Ty],
|
||||
extract_error_mode: ExtractErrorMode,
|
||||
holders: &mut Vec<TokenStream>,
|
||||
ctx: &Ctx,
|
||||
) -> Result<Vec<TokenStream>> {
|
||||
let mut args = Vec::with_capacity(spec.signature.arguments.len());
|
||||
let mut non_python_args = 0;
|
||||
|
@ -1352,7 +1425,7 @@ fn extract_proto_arguments(
|
|||
let ident = syn::Ident::new(&format!("arg{}", non_python_args), Span::call_site());
|
||||
let conversions = proto_args.get(non_python_args)
|
||||
.ok_or_else(|| err_spanned!(arg.ty.span() => format!("Expected at most {} non-python arguments", proto_args.len())))?
|
||||
.extract(&ident, arg, extract_error_mode, holders);
|
||||
.extract(&ident, arg, extract_error_mode, holders, ctx);
|
||||
non_python_args += 1;
|
||||
args.push(conversions);
|
||||
}
|
||||
|
@ -1372,10 +1445,14 @@ impl ToTokens for StaticIdent {
|
|||
}
|
||||
}
|
||||
|
||||
struct TokenGenerator(fn() -> TokenStream);
|
||||
#[derive(Clone, Copy)]
|
||||
struct TokenGenerator(fn(&Ctx) -> TokenStream);
|
||||
|
||||
impl ToTokens for TokenGenerator {
|
||||
struct TokenGeneratorCtx<'ctx>(TokenGenerator, &'ctx Ctx);
|
||||
|
||||
impl ToTokens for TokenGeneratorCtx<'_> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.0().to_tokens(tokens)
|
||||
let Self(TokenGenerator(gen), ctx) = self;
|
||||
(gen)(ctx).to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
use crate::utils::Ctx;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub(crate) fn some_wrap(obj: TokenStream) -> TokenStream {
|
||||
pub(crate) fn some_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
_pyo3::impl_::wrap::SomeWrap::wrap(#obj)
|
||||
#pyo3_path::impl_::wrap::SomeWrap::wrap(#obj)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ok_wrap(obj: TokenStream) -> TokenStream {
|
||||
pub(crate) fn ok_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
_pyo3::impl_::wrap::OkWrap::wrap(#obj)
|
||||
.map_err(::core::convert::Into::<_pyo3::PyErr>::into)
|
||||
#pyo3_path::impl_::wrap::OkWrap::wrap(#obj)
|
||||
.map_err(::core::convert::Into::<#pyo3_path::PyErr>::into)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_result_into_ptr(result: TokenStream) -> TokenStream {
|
||||
pub(crate) fn map_result_into_ptr(result: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||
let Ctx { pyo3_path } = ctx;
|
||||
quote! {
|
||||
_pyo3::impl_::wrap::map_result_into_ptr(py, #result)
|
||||
#pyo3_path::impl_::wrap::map_result_into_ptr(py, #result)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,11 +144,41 @@ pub fn unwrap_ty_group(mut ty: &syn::Type) -> &syn::Type {
|
|||
ty
|
||||
}
|
||||
|
||||
/// Extract the path to the pyo3 crate, or use the default (`::pyo3`).
|
||||
pub(crate) fn get_pyo3_crate(attr: &Option<CrateAttribute>) -> syn::Path {
|
||||
match attr {
|
||||
Some(attr) => attr.value.0.clone(),
|
||||
None => syn::parse_str("::pyo3").unwrap(),
|
||||
pub struct Ctx {
|
||||
pub pyo3_path: PyO3CratePath,
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
pub(crate) fn new(attr: &Option<CrateAttribute>) -> Self {
|
||||
let pyo3_path = match attr {
|
||||
Some(attr) => PyO3CratePath::Given(attr.value.0.clone()),
|
||||
None => PyO3CratePath::Default,
|
||||
};
|
||||
|
||||
Self { pyo3_path }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PyO3CratePath {
|
||||
Given(syn::Path),
|
||||
Default,
|
||||
}
|
||||
|
||||
impl PyO3CratePath {
|
||||
pub fn to_tokens_spanned(&self, span: Span) -> TokenStream {
|
||||
match self {
|
||||
Self::Given(path) => quote::quote_spanned! { span => #path },
|
||||
Self::Default => quote::quote_spanned! { span => ::pyo3 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl quote::ToTokens for PyO3CratePath {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
Self::Given(path) => path.to_tokens(tokens),
|
||||
Self::Default => quote::quote! { ::pyo3 }.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,4 +31,4 @@ error[E0592]: duplicate definitions with name `__pymethod___richcmp____`
|
|||
| duplicate definitions for `__pymethod___richcmp____`
|
||||
| other definition for `__pymethod___richcmp____`
|
||||
|
|
||||
= note: this error originates in the macro `_pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
= note: this error originates in the macro `::pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
Loading…
Reference in New Issue