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