Merge pull request #3356 from davidhewitt/py-idents

remove all #py quoting
This commit is contained in:
David Hewitt 2023-08-20 10:52:13 +00:00 committed by GitHub
commit 637e39deb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 72 deletions

View File

@ -141,13 +141,13 @@ pub enum ExtractErrorMode {
}
impl ExtractErrorMode {
pub fn handle_error(self, py: &syn::Ident, extract: TokenStream) -> TokenStream {
pub fn handle_error(self, extract: TokenStream) -> TokenStream {
match self {
ExtractErrorMode::Raise => quote! { #extract? },
ExtractErrorMode::NotImplemented => quote! {
match #extract {
::std::result::Result::Ok(value) => value,
::std::result::Result::Err(_) => { return _pyo3::callback::convert(#py, #py.NotImplemented()); },
::std::result::Result::Err(_) => { return _pyo3::callback::convert(py, py.NotImplemented()); },
}
},
}
@ -156,6 +156,8 @@ impl ExtractErrorMode {
impl SelfType {
pub fn receiver(&self, cls: &syn::Type, error_mode: ExtractErrorMode) -> TokenStream {
// Due to use of quote_spanned in this function, need to bind these idents to the
// main macro callsite.
let py = syn::Ident::new("py", Span::call_site());
let slf = syn::Ident::new("_slf", Span::call_site());
match self {
@ -165,19 +167,15 @@ impl SelfType {
} else {
syn::Ident::new("extract_pyclass_ref", *span)
};
error_mode.handle_error(
&py,
quote_spanned! { *span =>
_pyo3::impl_::extract_argument::#method::<#cls>(
#py.from_borrowed_ptr::<_pyo3::PyAny>(#slf),
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
)
},
)
error_mode.handle_error(quote_spanned! { *span =>
_pyo3::impl_::extract_argument::#method::<#cls>(
#py.from_borrowed_ptr::<_pyo3::PyAny>(#slf),
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
)
})
}
SelfType::TryFromPyCell(span) => {
error_mode.handle_error(
&py,
quote_spanned! { *span =>
#py.from_borrowed_ptr::<_pyo3::PyAny>(#slf).downcast::<_pyo3::PyCell<#cls>>()
.map_err(::std::convert::Into::<_pyo3::PyErr>::into)
@ -410,7 +408,6 @@ impl<'a> FnSpec<'a> {
cls: Option<&syn::Type>,
) -> Result<TokenStream> {
let self_arg = self.tp.self_arg(cls, ExtractErrorMode::Raise);
let py = syn::Ident::new("py", Span::call_site());
let func_name = &self.name;
let rust_call = |args: Vec<TokenStream>| {
@ -427,14 +424,14 @@ impl<'a> FnSpec<'a> {
CallingConvention::Noargs => {
let call = if !self.signature.arguments.is_empty() {
// Only `py` arg can be here
rust_call(vec![quote!(#py)])
rust_call(vec![quote!(py)])
} else {
rust_call(vec![])
};
quote! {
unsafe fn #ident<'py>(
#py: _pyo3::Python<'py>,
py: _pyo3::Python<'py>,
_slf: *mut _pyo3::ffi::PyObject,
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
let function = #rust_name; // Shadow the function name to avoid #3017
@ -443,11 +440,11 @@ impl<'a> FnSpec<'a> {
}
}
CallingConvention::Fastcall => {
let (arg_convert, args) = impl_arg_params(self, cls, &py, true)?;
let (arg_convert, args) = impl_arg_params(self, cls, true)?;
let call = rust_call(args);
quote! {
unsafe fn #ident<'py>(
#py: _pyo3::Python<'py>,
py: _pyo3::Python<'py>,
_slf: *mut _pyo3::ffi::PyObject,
_args: *const *mut _pyo3::ffi::PyObject,
_nargs: _pyo3::ffi::Py_ssize_t,
@ -460,11 +457,11 @@ impl<'a> FnSpec<'a> {
}
}
CallingConvention::Varargs => {
let (arg_convert, args) = impl_arg_params(self, cls, &py, false)?;
let (arg_convert, args) = impl_arg_params(self, cls, false)?;
let call = rust_call(args);
quote! {
unsafe fn #ident<'py>(
#py: _pyo3::Python<'py>,
py: _pyo3::Python<'py>,
_slf: *mut _pyo3::ffi::PyObject,
_args: *mut _pyo3::ffi::PyObject,
_kwargs: *mut _pyo3::ffi::PyObject
@ -476,17 +473,17 @@ impl<'a> FnSpec<'a> {
}
}
CallingConvention::TpNew => {
let (arg_convert, args) = impl_arg_params(self, cls, &py, false)?;
let (arg_convert, args) = impl_arg_params(self, cls, false)?;
let call = match &self.tp {
FnType::FnNew => quote! { #rust_name(#(#args),*) },
FnType::FnNewClass => {
quote! { #rust_name(_pyo3::types::PyType::from_type_ptr(#py, subtype), #(#args),*) }
quote! { #rust_name(_pyo3::types::PyType::from_type_ptr(py, subtype), #(#args),*) }
}
x => panic!("Only `FnNew` or `FnNewClass` may use the `TpNew` calling convention. Got: {:?}", x),
};
quote! {
unsafe fn #ident(
#py: _pyo3::Python<'_>,
py: _pyo3::Python<'_>,
subtype: *mut _pyo3::ffi::PyTypeObject,
_args: *mut _pyo3::ffi::PyObject,
_kwargs: *mut _pyo3::ffi::PyObject
@ -495,8 +492,8 @@ impl<'a> FnSpec<'a> {
let function = #rust_name; // Shadow the function name to avoid #3017
#arg_convert
let result = #call;
let initializer: _pyo3::PyClassInitializer::<#cls> = result.convert(#py)?;
let cell = initializer.create_cell_from_subtype(#py, subtype)?;
let initializer: _pyo3::PyClassInitializer::<#cls> = result.convert(py)?;
let cell = initializer.create_cell_from_subtype(py, subtype)?;
::std::result::Result::Ok(cell as *mut _pyo3::ffi::PyObject)
}
}

View File

@ -27,7 +27,6 @@ pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {
pub fn impl_arg_params(
spec: &FnSpec<'_>,
self_: Option<&syn::Type>,
py: &syn::Ident,
fastcall: bool,
) -> Result<(TokenStream, Vec<TokenStream>)> {
let args_array = syn::Ident::new("output", Span::call_site());
@ -39,12 +38,12 @@ pub fn impl_arg_params(
.signature
.arguments
.iter()
.map(|arg| impl_arg_param(arg, &mut 0, py, &args_array))
.map(|arg| impl_arg_param(arg, &mut 0, &args_array))
.collect::<Result<_>>()?;
return Ok((
quote! {
let _args = #py.from_borrowed_ptr::<_pyo3::types::PyTuple>(_args);
let _kwargs: ::std::option::Option<&_pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
let _args = py.from_borrowed_ptr::<_pyo3::types::PyTuple>(_args);
let _kwargs: ::std::option::Option<&_pyo3::types::PyDict> = py.from_borrowed_ptr_or_opt(_kwargs);
},
arg_convert,
));
@ -77,7 +76,7 @@ pub fn impl_arg_params(
.signature
.arguments
.iter()
.map(|arg| impl_arg_param(arg, &mut option_pos, py, &args_array))
.map(|arg| impl_arg_param(arg, &mut option_pos, &args_array))
.collect::<Result<_>>()?;
let args_handler = if spec.signature.python_signature.varargs.is_some() {
@ -101,7 +100,7 @@ pub fn impl_arg_params(
let extract_expression = if fastcall {
quote! {
DESCRIPTION.extract_arguments_fastcall::<#args_handler, #kwargs_handler>(
#py,
py,
_args,
_nargs,
_kwnames,
@ -111,7 +110,7 @@ pub fn impl_arg_params(
} else {
quote! {
DESCRIPTION.extract_arguments_tuple_dict::<#args_handler, #kwargs_handler>(
#py,
py,
_args,
_kwargs,
&mut #args_array
@ -143,7 +142,6 @@ pub fn impl_arg_params(
fn impl_arg_param(
arg: &FnArg<'_>,
option_pos: &mut usize,
py: &syn::Ident,
args_array: &syn::Ident,
) -> Result<TokenStream> {
// Use this macro inside this function, to ensure that all code generated here is associated
@ -153,7 +151,7 @@ fn impl_arg_param(
}
if arg.py {
return Ok(quote_arg_span! { #py });
return Ok(quote! { py });
}
let name = arg.name;

View File

@ -908,7 +908,6 @@ impl Ty {
fn extract(
self,
py: &syn::Ident,
ident: &syn::Ident,
arg: &FnArg<'_>,
extract_error_mode: ExtractErrorMode,
@ -917,18 +916,16 @@ impl Ty {
match self {
Ty::Object => extract_object(
extract_error_mode,
py,
&name_str,
quote! {
#py.from_borrowed_ptr::<_pyo3::PyAny>(#ident)
py.from_borrowed_ptr::<_pyo3::PyAny>(#ident)
},
),
Ty::MaybeNullObject => extract_object(
extract_error_mode,
py,
&name_str,
quote! {
#py.from_borrowed_ptr::<_pyo3::PyAny>(
py.from_borrowed_ptr::<_pyo3::PyAny>(
if #ident.is_null() {
_pyo3::ffi::Py_None()
} else {
@ -939,22 +936,19 @@ impl Ty {
),
Ty::NonNullObject => extract_object(
extract_error_mode,
py,
&name_str,
quote! {
#py.from_borrowed_ptr::<_pyo3::PyAny>(#ident.as_ptr())
py.from_borrowed_ptr::<_pyo3::PyAny>(#ident.as_ptr())
},
),
Ty::IPowModulo => extract_object(
extract_error_mode,
py,
&name_str,
quote! {
#ident.to_borrowed_any(#py)
#ident.to_borrowed_any(py)
},
),
Ty::CompareOp => extract_error_mode.handle_error(
py,
quote! {
_pyo3::class::basic::CompareOp::from_raw(#ident)
.ok_or_else(|| _pyo3::exceptions::PyValueError::new_err("invalid comparison operator"))
@ -963,7 +957,6 @@ impl Ty {
Ty::PySsizeT => {
let ty = arg.ty;
extract_error_mode.handle_error(
py,
quote! {
::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| _pyo3::exceptions::PyValueError::new_err(e.to_string()))
},
@ -977,20 +970,16 @@ impl Ty {
fn extract_object(
extract_error_mode: ExtractErrorMode,
py: &syn::Ident,
name: &str,
source: TokenStream,
) -> TokenStream {
extract_error_mode.handle_error(
py,
quote! {
_pyo3::impl_::extract_argument::extract_argument(
#source,
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
#name
)
},
)
extract_error_mode.handle_error(quote! {
_pyo3::impl_::extract_argument::extract_argument(
#source,
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
#name
)
})
}
enum ReturnMode {
@ -999,11 +988,11 @@ enum ReturnMode {
}
impl ReturnMode {
fn return_call_output(&self, py: &syn::Ident, call: TokenStream) -> TokenStream {
fn return_call_output(&self, call: TokenStream) -> TokenStream {
match self {
ReturnMode::Conversion(conversion) => quote! {
let _result: _pyo3::PyResult<#conversion> = #call;
_pyo3::callback::convert(#py, _result)
_pyo3::callback::convert(py, _result)
},
ReturnMode::ReturnSelf => quote! {
let _result: _pyo3::PyResult<()> = #call;
@ -1091,7 +1080,6 @@ impl SlotDef {
spec.name.span() => format!("`{}` must be `unsafe fn`", method_name)
);
}
let py = syn::Ident::new("py", Span::call_site());
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
let arg_idents: &Vec<_> = &(0..arguments.len())
.map(|i| format_ident!("arg{}", i))
@ -1101,7 +1089,6 @@ impl SlotDef {
let body = generate_method_body(
cls,
spec,
&py,
arguments,
*extract_error_mode,
return_mode.as_ref(),
@ -1109,7 +1096,7 @@ impl SlotDef {
let name = spec.name;
let associated_method = quote! {
unsafe fn #wrapper_ident(
#py: _pyo3::Python<'_>,
py: _pyo3::Python<'_>,
_raw_slf: *mut _pyo3::ffi::PyObject,
#(#arg_idents: #arg_types),*
) -> _pyo3::PyResult<#ret_ty> {
@ -1146,17 +1133,16 @@ impl SlotDef {
fn generate_method_body(
cls: &syn::Type,
spec: &FnSpec<'_>,
py: &syn::Ident,
arguments: &[Ty],
extract_error_mode: ExtractErrorMode,
return_mode: Option<&ReturnMode>,
) -> Result<TokenStream> {
let self_arg = spec.tp.self_arg(Some(cls), extract_error_mode);
let rust_name = spec.name;
let args = extract_proto_arguments(py, spec, arguments, extract_error_mode)?;
let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(#self_arg #(#args),*)) };
let args = extract_proto_arguments(spec, arguments, extract_error_mode)?;
let call = quote! { _pyo3::callback::convert(py, #cls::#rust_name(#self_arg #(#args),*)) };
Ok(if let Some(return_mode) = return_mode {
return_mode.return_call_output(py, call)
return_mode.return_call_output(call)
} else {
call
})
@ -1199,12 +1185,11 @@ impl SlotFragmentDef {
let fragment_trait = format_ident!("PyClass{}SlotFragment", fragment);
let method = syn::Ident::new(fragment, Span::call_site());
let wrapper_ident = format_ident!("__pymethod_{}__", fragment);
let py = syn::Ident::new("py", Span::call_site());
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
let arg_idents: &Vec<_> = &(0..arguments.len())
.map(|i| format_ident!("arg{}", i))
.collect();
let body = generate_method_body(cls, spec, &py, arguments, *extract_error_mode, None)?;
let body = generate_method_body(cls, spec, arguments, *extract_error_mode, None)?;
let ret_ty = ret_ty.ffi_type();
Ok(quote! {
impl _pyo3::impl_::pyclass::#fragment_trait<#cls> for _pyo3::impl_::pyclass::PyClassImplCollector<#cls> {
@ -1212,13 +1197,13 @@ impl SlotFragmentDef {
#[inline]
unsafe fn #method(
self,
#py: _pyo3::Python,
py: _pyo3::Python,
_raw_slf: *mut _pyo3::ffi::PyObject,
#(#arg_idents: #arg_types),*
) -> _pyo3::PyResult<#ret_ty> {
impl #cls {
unsafe fn #wrapper_ident(
#py: _pyo3::Python,
py: _pyo3::Python,
_raw_slf: *mut _pyo3::ffi::PyObject,
#(#arg_idents: #arg_types),*
) -> _pyo3::PyResult<#ret_ty> {
@ -1226,7 +1211,7 @@ impl SlotFragmentDef {
#body
}
}
#cls::#wrapper_ident(#py, _raw_slf, #(#arg_idents),*)
#cls::#wrapper_ident(py, _raw_slf, #(#arg_idents),*)
}
}
})
@ -1308,7 +1293,6 @@ const __GE__: SlotFragmentDef = SlotFragmentDef::new("__ge__", &[Ty::Object])
.ret_ty(Ty::Object);
fn extract_proto_arguments(
py: &syn::Ident,
spec: &FnSpec<'_>,
proto_args: &[Ty],
extract_error_mode: ExtractErrorMode,
@ -1318,12 +1302,12 @@ fn extract_proto_arguments(
for arg in &spec.signature.arguments {
if arg.py {
args.push(quote! { #py });
args.push(quote! { py });
} else {
let ident = syn::Ident::new(&format!("arg{}", non_python_args), Span::call_site());
let conversions = proto_args.get(non_python_args)
.ok_or_else(|| err_spanned!(arg.ty.span() => format!("Expected at most {} non-python arguments", proto_args.len())))?
.extract(py, &ident, arg, extract_error_mode);
.extract(&ident, arg, extract_error_mode);
non_python_args += 1;
args.push(conversions);
}