Skip to content

more macro hygiene cleanup: test #[pymethods] and more arg parsing and protos #1843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions pyo3-macros-backend/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl SlotDef {

pub const OBJECT: Proto = Proto {
name: "Object",
module: "pyo3::class::basic",
module: "::pyo3::class::basic",
methods: &[
MethodProto::new("__getattr__", "PyObjectGetAttrProtocol")
.args(&["Name"])
Expand Down Expand Up @@ -189,7 +189,7 @@ pub const OBJECT: Proto = Proto {

pub const ASYNC: Proto = Proto {
name: "Async",
module: "pyo3::class::pyasync",
module: "::pyo3::class::pyasync",
methods: &[
MethodProto::new("__await__", "PyAsyncAwaitProtocol").args(&["Receiver"]),
MethodProto::new("__aiter__", "PyAsyncAiterProtocol").args(&["Receiver"]),
Expand All @@ -212,7 +212,7 @@ pub const ASYNC: Proto = Proto {

pub const BUFFER: Proto = Proto {
name: "Buffer",
module: "pyo3::class::buffer",
module: "::pyo3::class::buffer",
methods: &[
MethodProto::new("bf_getbuffer", "PyBufferGetBufferProtocol").has_self(),
MethodProto::new("bf_releasebuffer", "PyBufferReleaseBufferProtocol").has_self(),
Expand All @@ -230,7 +230,7 @@ pub const BUFFER: Proto = Proto {

pub const CONTEXT: Proto = Proto {
name: "Context",
module: "pyo3::class::context",
module: "::pyo3::class::context",
methods: &[
MethodProto::new("__enter__", "PyContextEnterProtocol").has_self(),
MethodProto::new("__exit__", "PyContextExitProtocol")
Expand All @@ -246,7 +246,7 @@ pub const CONTEXT: Proto = Proto {

pub const GC: Proto = Proto {
name: "GC",
module: "pyo3::class::gc",
module: "::pyo3::class::gc",
methods: &[
MethodProto::new("__traverse__", "PyGCTraverseProtocol")
.has_self()
Expand All @@ -264,7 +264,7 @@ pub const GC: Proto = Proto {

pub const DESCR: Proto = Proto {
name: "Descr",
module: "pyo3::class::descr",
module: "::pyo3::class::descr",
methods: &[
MethodProto::new("__get__", "PyDescrGetProtocol").args(&["Receiver", "Inst", "Owner"]),
MethodProto::new("__set__", "PyDescrSetProtocol").args(&["Receiver", "Inst", "Value"]),
Expand All @@ -287,7 +287,7 @@ pub const DESCR: Proto = Proto {

pub const ITER: Proto = Proto {
name: "Iter",
module: "pyo3::class::iter",
module: "::pyo3::class::iter",
py_methods: &[],
methods: &[
MethodProto::new("__iter__", "PyIterIterProtocol").args(&["Receiver"]),
Expand All @@ -301,7 +301,7 @@ pub const ITER: Proto = Proto {

pub const MAPPING: Proto = Proto {
name: "Mapping",
module: "pyo3::class::mapping",
module: "::pyo3::class::mapping",
methods: &[
MethodProto::new("__len__", "PyMappingLenProtocol").has_self(),
MethodProto::new("__getitem__", "PyMappingGetItemProtocol")
Expand Down Expand Up @@ -334,7 +334,7 @@ pub const MAPPING: Proto = Proto {

pub const SEQ: Proto = Proto {
name: "Sequence",
module: "pyo3::class::sequence",
module: "::pyo3::class::sequence",
methods: &[
MethodProto::new("__len__", "PySequenceLenProtocol").has_self(),
MethodProto::new("__getitem__", "PySequenceGetItemProtocol")
Expand Down Expand Up @@ -391,7 +391,7 @@ pub const SEQ: Proto = Proto {

pub const NUM: Proto = Proto {
name: "Number",
module: "pyo3::class::number",
module: "::pyo3::class::number",
methods: &[
MethodProto::new("__add__", "PyNumberAddProtocol").args(&["Left", "Right"]),
MethodProto::new("__sub__", "PyNumberSubProtocol").args(&["Left", "Right"]),
Expand Down
2 changes: 1 addition & 1 deletion pyo3-macros-backend/src/deprecations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl ToTokens for Deprecations {
let ident = deprecation.ident(*span);
quote_spanned!(
*span =>
let _ = pyo3::impl_::deprecations::#ident;
let _ = ::pyo3::impl_::deprecations::#ident;
)
.to_tokens(tokens)
}
Expand Down
7 changes: 3 additions & 4 deletions pyo3-macros-backend/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,10 @@ impl<'a> FnSpec<'a> {
#deprecations
::pyo3::callback::handle_panic(|#py| {
#self_conversion
use ::std::option::Option;
let _kwnames: Option<&::pyo3::types::PyTuple> = #py.from_borrowed_ptr_or_opt(_kwnames);
let _kwnames: ::std::option::Option<&::pyo3::types::PyTuple> = #py.from_borrowed_ptr_or_opt(_kwnames);
// Safety: &PyAny has the same memory layout as `*mut ffi::PyObject`
let _args = _args as *const &::pyo3::PyAny;
let _kwargs = if let Option::Some(kwnames) = _kwnames {
let _kwargs = if let ::std::option::Option::Some(kwnames) = _kwnames {
::std::slice::from_raw_parts(_args.offset(_nargs), kwnames.len())
} else {
&[]
Expand Down Expand Up @@ -537,7 +536,7 @@ impl<'a> FnSpec<'a> {
let result = #arg_convert_and_rust_call;
let initializer: ::pyo3::PyClassInitializer::<#cls> = result.convert(#py)?;
let cell = initializer.create_cell_from_subtype(#py, subtype)?;
Ok(cell as *mut ::pyo3::ffi::PyObject)
::std::result::Result::Ok(cell as *mut ::pyo3::ffi::PyObject)
})
}
}
Expand Down
24 changes: 17 additions & 7 deletions pyo3-macros-backend/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub fn impl_arg_params(

if kwonly {
keyword_only_parameters.push(quote! {
pyo3::derive_utils::KeywordOnlyParameterDescription {
::pyo3::derive_utils::KeywordOnlyParameterDescription {
name: #name,
required: #required,
}
Expand Down Expand Up @@ -123,7 +123,7 @@ pub fn impl_arg_params(
let (accept_args, accept_kwargs) = accept_args_kwargs(&spec.attrs);

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::type_object::PyTypeInfo>::NAME) }
} else {
quote! { ::std::option::Option::None }
};
Expand Down Expand Up @@ -236,12 +236,22 @@ fn impl_arg_param(

let arg_value_or_default = match (spec.default_value(name), arg.optional.is_some()) {
(Some(default), true) if default.to_string() != "None" => {
quote_arg_span! { #arg_value.map_or_else(|| Ok(Some(#default)), |_obj| #extract)? }
quote_arg_span! {
#arg_value.map_or_else(|| ::std::result::Result::Ok(::std::option::Option::Some(#default)),
|_obj| #extract)?
}
}
(Some(default), _) => {
quote_arg_span! { #arg_value.map_or_else(|| Ok(#default), |_obj| #extract)? }
quote_arg_span! {
#arg_value.map_or_else(|| ::std::result::Result::Ok(#default), |_obj| #extract)?
}
}
(None, true) => {
quote_arg_span! {
#arg_value.map_or(::std::result::Result::Ok(::std::option::Option::None),
|_obj| #extract)?
}
}
(None, true) => quote_arg_span! { #arg_value.map_or(Ok(None), |_obj| #extract)? },
(None, false) => {
quote_arg_span! {
{
Expand All @@ -257,7 +267,7 @@ fn impl_arg_param(
let (target_ty, borrow_tmp) = if arg.optional.is_some() {
// Get Option<&T> from Option<PyRef<T>>
(
quote_arg_span! { Option<<#tref as pyo3::derive_utils::ExtractExt<'_>>::Target> },
quote_arg_span! { ::std::option::Option<<#tref as ::pyo3::derive_utils::ExtractExt<'_>>::Target> },
if mut_.is_some() {
quote_arg_span! { _tmp.as_deref_mut() }
} else {
Expand All @@ -267,7 +277,7 @@ fn impl_arg_param(
} else {
// Get &T from PyRef<T>
(
quote_arg_span! { <#tref as pyo3::derive_utils::ExtractExt<'_>>::Target },
quote_arg_span! { <#tref as ::pyo3::derive_utils::ExtractExt<'_>>::Target },
quote_arg_span! { &#mut_ *_tmp },
)
};
Expand Down
2 changes: 1 addition & 1 deletion pyo3-macros-backend/src/proto_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub(crate) fn impl_method_proto(
};

Ok(quote! {
impl<'p> ::#module::#proto<'p> for #cls {
impl<'p> #module::#proto<'p> for #cls {
#(#impl_types)*
#res_type_def
}
Expand Down
26 changes: 13 additions & 13 deletions pyo3-macros-backend/src/pyimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ fn gen_py_const(cls: &syn::Type, spec: &ConstSpec) -> TokenStream {
let deprecations = &spec.attributes.deprecations;
let python_name = &spec.null_terminated_python_name();
quote! {
pyo3::class::PyMethodDefType::ClassAttribute({
pyo3::class::PyClassAttributeDef::new(
::pyo3::class::PyMethodDefType::ClassAttribute({
::pyo3::class::PyClassAttributeDef::new(
#python_name,
pyo3::class::methods::PyClassAttributeFactory({
fn __wrap(py: pyo3::Python<'_>) -> pyo3::PyObject {
::pyo3::class::methods::PyClassAttributeFactory({
fn __wrap(py: ::pyo3::Python<'_>) -> ::pyo3::PyObject {
#deprecations
pyo3::IntoPy::into_py(#cls::#member, py)
::pyo3::IntoPy::into_py(#cls::#member, py)
}
__wrap
})
Expand All @@ -111,11 +111,11 @@ fn gen_py_const(cls: &syn::Type, spec: &ConstSpec) -> TokenStream {

fn impl_py_methods(ty: &syn::Type, methods: Vec<TokenStream>) -> TokenStream {
quote! {
impl pyo3::class::impl_::PyMethods<#ty>
for pyo3::class::impl_::PyClassImplCollector<#ty>
impl ::pyo3::class::impl_::PyMethods<#ty>
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
{
fn py_methods(self) -> &'static [pyo3::class::methods::PyMethodDefType] {
static METHODS: &[pyo3::class::methods::PyMethodDefType] = &[#(#methods),*];
fn py_methods(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
static METHODS: &[::pyo3::class::methods::PyMethodDefType] = &[#(#methods),*];
METHODS
}
}
Expand All @@ -128,10 +128,10 @@ fn submit_methods_inventory(ty: &syn::Type, methods: Vec<TokenStream>) -> TokenS
}

quote! {
pyo3::inventory::submit! {
#![crate = pyo3] {
type Inventory = <#ty as pyo3::class::impl_::HasMethodsInventory>::Methods;
<Inventory as pyo3::class::impl_::PyMethodsInventory>::new(vec![#(#methods),*])
::pyo3::inventory::submit! {
#![crate = ::pyo3] {
type Inventory = <#ty as ::pyo3::class::impl_::HasMethodsInventory>::Methods;
<Inventory as ::pyo3::class::impl_::PyMethodsInventory>::new(::std::vec![#(#methods),*])
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions pyo3-macros-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ pub fn gen_py_method(
FnType::FnClass => GeneratedPyMethod::Method(impl_py_method_def(
cls,
&spec,
Some(quote!(pyo3::ffi::METH_CLASS)),
Some(quote!(::pyo3::ffi::METH_CLASS)),
)?),
FnType::FnStatic => GeneratedPyMethod::Method(impl_py_method_def(
cls,
&spec,
Some(quote!(pyo3::ffi::METH_STATIC)),
Some(quote!(::pyo3::ffi::METH_STATIC)),
)?),
// special prototypes
FnType::FnNew => GeneratedPyMethod::New(impl_py_method_def_new(cls, &spec)?),
Expand Down Expand Up @@ -111,8 +111,8 @@ fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream>
let wrapper = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
Ok(quote! {
impl ::pyo3::class::impl_::PyClassNewImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
fn new_impl(self) -> Option<pyo3::ffi::newfunc> {
Some({
fn new_impl(self) -> ::std::option::Option<::pyo3::ffi::newfunc> {
::std::option::Option::Some({
#wrapper
#wrapper_ident
})
Expand All @@ -126,8 +126,8 @@ fn impl_py_method_def_call(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream
let wrapper = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
Ok(quote! {
impl ::pyo3::class::impl_::PyClassCallImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
fn call_impl(self) -> Option<pyo3::ffi::PyCFunctionWithKeywords> {
Some({
fn call_impl(self) -> ::std::option::Option<::pyo3::ffi::PyCFunctionWithKeywords> {
::std::option::Option::Some({
#wrapper
#wrapper_ident
})
Expand Down
10 changes: 5 additions & 5 deletions pyo3-macros-backend/src/pyproto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ fn impl_proto_methods(
{
fn buffer_procs(
self
) -> Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
) -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
static PROCS: ::pyo3::class::impl_::PyBufferProcs
= ::pyo3::class::impl_::PyBufferProcs {
bf_getbuffer: Some(pyo3::class::buffer::getbuffer::<#ty>),
bf_releasebuffer: Some(pyo3::class::buffer::releasebuffer::<#ty>),
bf_getbuffer: ::std::option::Option::Some(::pyo3::class::buffer::getbuffer::<#ty>),
bf_releasebuffer: ::std::option::Option::Some(::pyo3::class::buffer::releasebuffer::<#ty>),
};
Some(&PROCS)
::std::option::Option::Some(&PROCS)
}
}
});
Expand All @@ -164,7 +164,7 @@ fn impl_proto_methods(
quote! {{
::pyo3::ffi::PyType_Slot {
slot: ::pyo3::ffi::#slot,
pfunc: ::#module::#slot_impl::<#ty> as _
pfunc: #module::#slot_impl::<#ty> as _
}
}}
})
Expand Down
50 changes: 50 additions & 0 deletions tests/test_proc_macro_hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,43 @@ pub struct Bar {
c: ::std::option::Option<::pyo3::Py<Foo2>>,
}

#[::pyo3::proc_macro::pymethods]
impl Bar {
#[args(x = "1", "*", _z = "2")]
fn test(&self, _y: &Bar, _z: i32) {}
#[staticmethod]
fn staticmethod() {}
#[classmethod]
fn clsmethod(_: &::pyo3::types::PyType) {}
#[call]
#[args(args = "*", kwds = "**")]
fn __call__(
&self,
_args: &::pyo3::types::PyTuple,
_kwds: ::std::option::Option<&::pyo3::types::PyDict>,
) -> ::pyo3::PyResult<i32> {
::std::panic!("unimplemented isn't hygienic before 1.50")
}
#[new]
fn new(a: u8) -> Self {
Bar {
a,
b: Foo,
c: ::std::option::Option::None,
}
}
#[getter]
fn get(&self) -> i32 {
0
}
#[setter]
fn set(&self, _v: i32) {}
#[classattr]
fn class_attr() -> i32 {
0
}
}

#[::pyo3::proc_macro::pyproto]
impl ::pyo3::class::gc::PyGCProtocol for Bar {
fn __traverse__(
Expand All @@ -43,6 +80,19 @@ impl ::pyo3::class::gc::PyGCProtocol for Bar {
}
}

#[cfg(not(Py_LIMITED_API))]
#[::pyo3::proc_macro::pyproto]
impl ::pyo3::class::PyBufferProtocol for Bar {
fn bf_getbuffer(
_s: ::pyo3::PyRefMut<Self>,
_v: *mut ::pyo3::ffi::Py_buffer,
_f: ::std::os::raw::c_int,
) -> ::pyo3::PyResult<()> {
::std::panic!("unimplemented isn't hygienic before 1.50")
}
fn bf_releasebuffer(_s: ::pyo3::PyRefMut<Self>, _v: *mut ::pyo3::ffi::Py_buffer) {}
}

#[::pyo3::proc_macro::pyfunction]
fn do_something(x: i32) -> ::pyo3::PyResult<i32> {
::std::result::Result::Ok(x)
Expand Down