Merge pull request #2022 from PyO3/pyo3_path
Hygiene: offer a way to set path to pyo3 crate
This commit is contained in:
commit
469d72a001
|
@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009)
|
||||
- Add `PyCapsule`, exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980)
|
||||
- All PyO3 proc-macros except the deprecated `#[pyproto]` now accept a supplemental attribute `#[pyo3(crate = "some::path")]` that specifies
|
||||
where to find the `pyo3` crate, in case it has been renamed or is re-exported and not found at the crate root. [#2022](https://github.com/PyO3/pyo3/pull/2022)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -139,3 +139,23 @@ a: <builtins.Inner object at 0x0000020044FCC670>
|
|||
b: <builtins.Inner object at 0x0000020044FCC670>
|
||||
```
|
||||
The downside to this approach is that any Rust code working on the `Outer` struct now has to acquire the GIL to do anything with its field.
|
||||
|
||||
## I want to use the `pyo3` crate re-exported from from dependency but the proc-macros fail!
|
||||
|
||||
All PyO3 proc-macros (`#[pyclass]`, `#[pyfunction]`, `#[derive(FromPyObject)]`
|
||||
and so on) expect the `pyo3` crate to be available under that name in your crate
|
||||
root, which is the normal situation when `pyo3` is a direct dependency of your
|
||||
crate.
|
||||
|
||||
However, when the dependency is renamed, or your crate only indirectly depends
|
||||
on `pyo3`, you need to let the macro code know where to find the crate. This is
|
||||
done with the `crate` attribute:
|
||||
|
||||
```rust
|
||||
# use pyo3::prelude::*;
|
||||
# pub extern crate pyo3;
|
||||
# mod reexported { pub use ::pyo3; }
|
||||
#[pyclass]
|
||||
#[pyo3(crate = "reexported::pyo3")]
|
||||
struct MyClass;
|
||||
```
|
||||
|
|
|
@ -2,7 +2,7 @@ use syn::{
|
|||
parse::{Parse, ParseStream},
|
||||
punctuated::Punctuated,
|
||||
token::Comma,
|
||||
Attribute, ExprPath, Ident, LitStr, Result, Token,
|
||||
Attribute, ExprPath, Ident, LitStr, Path, Result, Token,
|
||||
};
|
||||
|
||||
pub mod kw {
|
||||
|
@ -43,6 +43,19 @@ impl Parse for NameAttribute {
|
|||
}
|
||||
}
|
||||
|
||||
/// For specifying the path to the pyo3 crate.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct CrateAttribute(pub Path);
|
||||
|
||||
impl Parse for CrateAttribute {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let _: Token![crate] = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
let string_literal: LitStr = input.parse()?;
|
||||
string_literal.parse().map(CrateAttribute)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct TextSignatureAttribute {
|
||||
pub kw: kw::text_signature,
|
||||
|
|
|
@ -33,7 +33,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)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::attributes::{self, get_pyo3_options, FromPyWithAttribute};
|
||||
use crate::{
|
||||
attributes::{self, get_pyo3_options, CrateAttribute, FromPyWithAttribute},
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
|
@ -55,14 +58,14 @@ impl<'a> Enum<'a> {
|
|||
for (i, var) in self.variants.iter().enumerate() {
|
||||
let struct_derive = var.build();
|
||||
let ext = quote!(
|
||||
let maybe_ret = || -> ::pyo3::PyResult<Self> {
|
||||
let maybe_ret = || -> _pyo3::PyResult<Self> {
|
||||
#struct_derive
|
||||
}();
|
||||
|
||||
match maybe_ret {
|
||||
ok @ ::std::result::Result::Ok(_) => return ok,
|
||||
::std::result::Result::Err(err) => {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
err_reasons.push_str(&::std::format!("{}\n", err.value(py).str()?));
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +85,7 @@ impl<'a> Enum<'a> {
|
|||
#ty_name,
|
||||
#error_names,
|
||||
&err_reasons);
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyTypeError::new_err(err_msg))
|
||||
::std::result::Result::Err(_pyo3::exceptions::PyTypeError::new_err(err_msg))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -207,8 +210,8 @@ impl<'a> Container<'a> {
|
|||
);
|
||||
quote!(
|
||||
::std::result::Result::Ok(#self_ty{#ident: obj.extract().map_err(|inner| {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let new_err = ::pyo3::exceptions::PyTypeError::new_err(#error_msg);
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
let new_err = _pyo3::exceptions::PyTypeError::new_err(#error_msg);
|
||||
new_err.set_cause(py, ::std::option::Option::Some(inner));
|
||||
new_err
|
||||
})?})
|
||||
|
@ -222,11 +225,11 @@ impl<'a> Container<'a> {
|
|||
};
|
||||
quote!(
|
||||
::std::result::Result::Ok(#self_ty(obj.extract().map_err(|err| {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
let err_msg = ::std::format!("{}: {}",
|
||||
#error_msg,
|
||||
err.value(py).str().unwrap());
|
||||
::pyo3::exceptions::PyTypeError::new_err(err_msg)
|
||||
_pyo3::exceptions::PyTypeError::new_err(err_msg)
|
||||
})?))
|
||||
)
|
||||
}
|
||||
|
@ -238,9 +241,9 @@ impl<'a> Container<'a> {
|
|||
for i in 0..len {
|
||||
let error_msg = format!("failed to extract field {}.{}", quote!(#self_ty), i);
|
||||
fields.push(quote!(
|
||||
s.get_item(#i).and_then(::pyo3::types::PyAny::extract).map_err(|inner| {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let new_err = ::pyo3::exceptions::PyTypeError::new_err(#error_msg);
|
||||
s.get_item(#i).and_then(_pyo3::types::PyAny::extract).map_err(|inner| {
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
let new_err = _pyo3::exceptions::PyTypeError::new_err(#error_msg);
|
||||
new_err.set_cause(py, ::std::option::Option::Some(inner));
|
||||
new_err
|
||||
})?));
|
||||
|
@ -255,9 +258,9 @@ impl<'a> Container<'a> {
|
|||
quote!("")
|
||||
};
|
||||
quote!(
|
||||
let s = <::pyo3::types::PyTuple as ::pyo3::conversion::PyTryFrom>::try_from(obj)?;
|
||||
let s = <_pyo3::types::PyTuple as _pyo3::conversion::PyTryFrom>::try_from(obj)?;
|
||||
if s.len() != #len {
|
||||
return ::std::result::Result::Err(::pyo3::exceptions::PyValueError::new_err(#msg))
|
||||
return ::std::result::Result::Err(_pyo3::exceptions::PyValueError::new_err(#msg))
|
||||
}
|
||||
::std::result::Result::Ok(#self_ty(#fields))
|
||||
)
|
||||
|
@ -279,15 +282,15 @@ impl<'a> Container<'a> {
|
|||
let extractor = match &attrs.from_py_with {
|
||||
None => quote!(
|
||||
#get_field.extract().map_err(|inner| {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let new_err = ::pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg);
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
let new_err = _pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg);
|
||||
new_err.set_cause(py, ::std::option::Option::Some(inner));
|
||||
new_err
|
||||
})?),
|
||||
Some(FromPyWithAttribute(expr_path)) => quote! (
|
||||
#expr_path(#get_field).map_err(|inner| {
|
||||
let py = ::pyo3::PyNativeType::py(obj);
|
||||
let new_err = ::pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg);
|
||||
let py = _pyo3::PyNativeType::py(obj);
|
||||
let new_err = _pyo3::exceptions::PyTypeError::new_err(#conversion_error_msg);
|
||||
new_err.set_cause(py, ::std::option::Option::Some(inner));
|
||||
new_err
|
||||
})?
|
||||
|
@ -300,20 +303,25 @@ impl<'a> Container<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ContainerOptions {
|
||||
/// Treat the Container as a Wrapper, directly extract its fields from the input object.
|
||||
transparent: bool,
|
||||
/// Change the name of an enum variant in the generated error message.
|
||||
annotation: Option<syn::LitStr>,
|
||||
/// Change the path for the pyo3 crate
|
||||
krate: Option<CrateAttribute>,
|
||||
}
|
||||
|
||||
/// Attributes for deriving FromPyObject scoped on containers.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
enum ContainerPyO3Attribute {
|
||||
/// Treat the Container as a Wrapper, directly extract its fields from the input object.
|
||||
Transparent(attributes::kw::transparent),
|
||||
/// Change the name of an enum variant in the generated error message.
|
||||
ErrorAnnotation(LitStr),
|
||||
/// Change the path for the pyo3 crate
|
||||
Crate(CrateAttribute),
|
||||
}
|
||||
|
||||
impl Parse for ContainerPyO3Attribute {
|
||||
|
@ -326,6 +334,8 @@ impl Parse for ContainerPyO3Attribute {
|
|||
let _: attributes::kw::annotation = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
input.parse().map(ContainerPyO3Attribute::ErrorAnnotation)
|
||||
} else if lookahead.peek(Token![crate]) {
|
||||
input.parse().map(ContainerPyO3Attribute::Crate)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
|
@ -334,10 +344,8 @@ impl Parse for ContainerPyO3Attribute {
|
|||
|
||||
impl ContainerOptions {
|
||||
fn from_attrs(attrs: &[Attribute]) -> Result<Self> {
|
||||
let mut options = ContainerOptions {
|
||||
transparent: false,
|
||||
annotation: None,
|
||||
};
|
||||
let mut options = ContainerOptions::default();
|
||||
|
||||
for attr in attrs {
|
||||
if let Some(pyo3_attrs) = get_pyo3_options(attr)? {
|
||||
for pyo3_attr in pyo3_attrs {
|
||||
|
@ -356,6 +364,13 @@ impl ContainerOptions {
|
|||
);
|
||||
options.annotation = Some(lit_str);
|
||||
}
|
||||
ContainerPyO3Attribute::Crate(path) => {
|
||||
ensure_spanned!(
|
||||
options.krate.is_none(),
|
||||
path.0.span() => "`crate` may only be provided once"
|
||||
);
|
||||
options.krate = Some(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,13 +514,18 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
.predicates
|
||||
.push(parse_quote!(#gen_ident: FromPyObject<#lt_param>))
|
||||
}
|
||||
let options = ContainerOptions::from_attrs(&tokens.attrs)?;
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let derives = match &tokens.data {
|
||||
syn::Data::Enum(en) => {
|
||||
if options.transparent || options.annotation.is_some() {
|
||||
bail_spanned!(tokens.span() => "`transparent` or `annotation` is not supported \
|
||||
at top level for enums");
|
||||
}
|
||||
let en = Enum::new(en, &tokens.ident)?;
|
||||
en.build()
|
||||
}
|
||||
syn::Data::Struct(st) => {
|
||||
let options = ContainerOptions::from_attrs(&tokens.attrs)?;
|
||||
if let Some(lit_str) = &options.annotation {
|
||||
bail_spanned!(lit_str.span() => "`annotation` is unsupported for structs");
|
||||
}
|
||||
|
@ -520,11 +540,15 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
|
|||
|
||||
let ident = &tokens.ident;
|
||||
Ok(quote!(
|
||||
#[automatically_derived]
|
||||
impl#trait_generics ::pyo3::FromPyObject<#lt_param> for #ident#generics #where_clause {
|
||||
fn extract(obj: &#lt_param ::pyo3::PyAny) -> ::pyo3::PyResult<Self> {
|
||||
#derives
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#[automatically_derived]
|
||||
impl#trait_generics _pyo3::FromPyObject<#lt_param> for #ident#generics #where_clause {
|
||||
fn extract(obj: &#lt_param _pyo3::PyAny) -> _pyo3::PyResult<Self> {
|
||||
#derives
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::deprecations::Deprecation;
|
|||
use crate::params::{accept_args_kwargs, impl_arg_params};
|
||||
use crate::pyfunction::PyFunctionOptions;
|
||||
use crate::pyfunction::{PyFunctionArgPyO3Attributes, PyFunctionSignature};
|
||||
use crate::utils::{self, PythonDoc};
|
||||
use crate::utils::{self, get_pyo3_crate, PythonDoc};
|
||||
use crate::{deprecations::Deprecations, pyfunction::Argument};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::ToTokens;
|
||||
|
@ -106,12 +106,12 @@ impl FnType {
|
|||
}
|
||||
FnType::FnClass => {
|
||||
quote! {
|
||||
let _slf = ::pyo3::types::PyType::from_type_ptr(_py, _slf as *mut ::pyo3::ffi::PyTypeObject);
|
||||
let _slf = _pyo3::types::PyType::from_type_ptr(_py, _slf as *mut _pyo3::ffi::PyTypeObject);
|
||||
}
|
||||
}
|
||||
FnType::FnModule => {
|
||||
quote! {
|
||||
let _slf = _py.from_borrowed_ptr::<::pyo3::types::PyModule>(_slf);
|
||||
let _slf = _py.from_borrowed_ptr::<_pyo3::types::PyModule>(_slf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,13 +141,13 @@ impl SelfType {
|
|||
pub fn receiver(&self, cls: &syn::Type, error_mode: ExtractErrorMode) -> TokenStream {
|
||||
let cell = match error_mode {
|
||||
ExtractErrorMode::Raise => {
|
||||
quote! { _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>()? }
|
||||
quote! { _py.from_borrowed_ptr::<_pyo3::PyAny>(_slf).downcast::<_pyo3::PyCell<#cls>>()? }
|
||||
}
|
||||
ExtractErrorMode::NotImplemented => {
|
||||
quote! {
|
||||
match _py.from_borrowed_ptr::<::pyo3::PyAny>(_slf).downcast::<::pyo3::PyCell<#cls>>() {
|
||||
match _py.from_borrowed_ptr::<_pyo3::PyAny>(_slf).downcast::<_pyo3::PyCell<#cls>>() {
|
||||
::std::result::Result::Ok(cell) => cell,
|
||||
::std::result::Result::Err(_) => return ::pyo3::callback::convert(_py, _py.NotImplemented()),
|
||||
::std::result::Result::Err(_) => return _pyo3::callback::convert(_py, _py.NotImplemented()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +228,7 @@ pub struct FnSpec<'a> {
|
|||
pub deprecations: Deprecations,
|
||||
pub convention: CallingConvention,
|
||||
pub text_signature: Option<TextSignatureAttribute>,
|
||||
pub krate: syn::Path,
|
||||
}
|
||||
|
||||
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
|
||||
|
@ -254,12 +255,14 @@ pub fn parse_method_receiver(arg: &syn::FnArg) -> Result<SelfType> {
|
|||
impl<'a> FnSpec<'a> {
|
||||
/// Parser function signature and function attributes
|
||||
pub fn parse(
|
||||
// Signature is mutable to remove the `Python` argument.
|
||||
sig: &'a mut syn::Signature,
|
||||
meth_attrs: &mut Vec<syn::Attribute>,
|
||||
options: PyFunctionOptions,
|
||||
) -> Result<FnSpec<'a>> {
|
||||
let PyFunctionOptions {
|
||||
text_signature,
|
||||
krate,
|
||||
name,
|
||||
mut deprecations,
|
||||
..
|
||||
|
@ -278,6 +281,7 @@ impl<'a> FnSpec<'a> {
|
|||
let name = &sig.ident;
|
||||
let ty = get_return_info(&sig.output);
|
||||
let python_name = python_name.as_ref().unwrap_or(name).unraw();
|
||||
let krate = get_pyo3_crate(&krate);
|
||||
|
||||
let doc = utils::get_doc(
|
||||
meth_attrs,
|
||||
|
@ -311,6 +315,7 @@ impl<'a> FnSpec<'a> {
|
|||
doc,
|
||||
deprecations,
|
||||
text_signature,
|
||||
krate,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -471,17 +476,19 @@ impl<'a> FnSpec<'a> {
|
|||
quote!(#func_name)
|
||||
};
|
||||
let rust_call =
|
||||
quote! { ::pyo3::callback::convert(#py, #rust_name(#self_arg #(#arg_names),*)) };
|
||||
quote! { _pyo3::callback::convert(#py, #rust_name(#self_arg #(#arg_names),*)) };
|
||||
let krate = &self.krate;
|
||||
Ok(match self.convention {
|
||||
CallingConvention::Noargs => {
|
||||
quote! {
|
||||
unsafe extern "C" fn #ident (
|
||||
_slf: *mut ::pyo3::ffi::PyObject,
|
||||
_args: *mut ::pyo3::ffi::PyObject,
|
||||
) -> *mut ::pyo3::ffi::PyObject
|
||||
_slf: *mut #krate::ffi::PyObject,
|
||||
_args: *mut #krate::ffi::PyObject,
|
||||
) -> *mut #krate::ffi::PyObject
|
||||
{
|
||||
use #krate as _pyo3;
|
||||
#deprecations
|
||||
::pyo3::callback::handle_panic(|#py| {
|
||||
_pyo3::callback::handle_panic(|#py| {
|
||||
#self_conversion
|
||||
#rust_call
|
||||
})
|
||||
|
@ -492,17 +499,18 @@ impl<'a> FnSpec<'a> {
|
|||
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, true)?;
|
||||
quote! {
|
||||
unsafe extern "C" fn #ident (
|
||||
_slf: *mut ::pyo3::ffi::PyObject,
|
||||
_args: *const *mut ::pyo3::ffi::PyObject,
|
||||
_nargs: ::pyo3::ffi::Py_ssize_t,
|
||||
_kwnames: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
|
||||
_slf: *mut #krate::ffi::PyObject,
|
||||
_args: *const *mut #krate::ffi::PyObject,
|
||||
_nargs: #krate::ffi::Py_ssize_t,
|
||||
_kwnames: *mut #krate::ffi::PyObject) -> *mut #krate::ffi::PyObject
|
||||
{
|
||||
use #krate as _pyo3;
|
||||
#deprecations
|
||||
::pyo3::callback::handle_panic(|#py| {
|
||||
_pyo3::callback::handle_panic(|#py| {
|
||||
#self_conversion
|
||||
let _kwnames: ::std::option::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 _args = _args as *const &_pyo3::PyAny;
|
||||
let _kwargs = if let ::std::option::Option::Some(kwnames) = _kwnames {
|
||||
::std::slice::from_raw_parts(_args.offset(_nargs), kwnames.len())
|
||||
} else {
|
||||
|
@ -519,15 +527,16 @@ impl<'a> FnSpec<'a> {
|
|||
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, false)?;
|
||||
quote! {
|
||||
unsafe extern "C" fn #ident (
|
||||
_slf: *mut ::pyo3::ffi::PyObject,
|
||||
_args: *mut ::pyo3::ffi::PyObject,
|
||||
_kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
|
||||
_slf: *mut #krate::ffi::PyObject,
|
||||
_args: *mut #krate::ffi::PyObject,
|
||||
_kwargs: *mut #krate::ffi::PyObject) -> *mut #krate::ffi::PyObject
|
||||
{
|
||||
use #krate as _pyo3;
|
||||
#deprecations
|
||||
::pyo3::callback::handle_panic(|#py| {
|
||||
_pyo3::callback::handle_panic(|#py| {
|
||||
#self_conversion
|
||||
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_and_rust_call
|
||||
})
|
||||
|
@ -539,20 +548,21 @@ impl<'a> FnSpec<'a> {
|
|||
let arg_convert_and_rust_call = impl_arg_params(self, cls, rust_call, &py, false)?;
|
||||
quote! {
|
||||
unsafe extern "C" fn #ident (
|
||||
subtype: *mut ::pyo3::ffi::PyTypeObject,
|
||||
_args: *mut ::pyo3::ffi::PyObject,
|
||||
_kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
|
||||
subtype: *mut #krate::ffi::PyTypeObject,
|
||||
_args: *mut #krate::ffi::PyObject,
|
||||
_kwargs: *mut #krate::ffi::PyObject) -> *mut #krate::ffi::PyObject
|
||||
{
|
||||
use #krate as _pyo3;
|
||||
#deprecations
|
||||
use ::pyo3::callback::IntoPyCallbackOutput;
|
||||
::pyo3::callback::handle_panic(|#py| {
|
||||
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);
|
||||
use _pyo3::callback::IntoPyCallbackOutput;
|
||||
_pyo3::callback::handle_panic(|#py| {
|
||||
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 result = #arg_convert_and_rust_call;
|
||||
let initializer: ::pyo3::PyClassInitializer::<#cls> = result.convert(#py)?;
|
||||
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)
|
||||
::std::result::Result::Ok(cell as *mut _pyo3::ffi::PyObject)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -567,23 +577,23 @@ impl<'a> FnSpec<'a> {
|
|||
let doc = &self.doc;
|
||||
match self.convention {
|
||||
CallingConvention::Noargs => quote! {
|
||||
::pyo3::class::methods::PyMethodDef::noargs(
|
||||
_pyo3::class::methods::PyMethodDef::noargs(
|
||||
#python_name,
|
||||
::pyo3::class::methods::PyCFunction(#wrapper),
|
||||
_pyo3::class::methods::PyCFunction(#wrapper),
|
||||
#doc,
|
||||
)
|
||||
},
|
||||
CallingConvention::Fastcall => quote! {
|
||||
::pyo3::class::methods::PyMethodDef::fastcall_cfunction_with_keywords(
|
||||
_pyo3::class::methods::PyMethodDef::fastcall_cfunction_with_keywords(
|
||||
#python_name,
|
||||
::pyo3::class::methods::PyCFunctionFastWithKeywords(#wrapper),
|
||||
_pyo3::class::methods::PyCFunctionFastWithKeywords(#wrapper),
|
||||
#doc,
|
||||
)
|
||||
},
|
||||
CallingConvention::Varargs => quote! {
|
||||
::pyo3::class::methods::PyMethodDef::cfunction_with_keywords(
|
||||
_pyo3::class::methods::PyMethodDef::cfunction_with_keywords(
|
||||
#python_name,
|
||||
::pyo3::class::methods::PyCFunctionWithKeywords(#wrapper),
|
||||
_pyo3::class::methods::PyCFunctionWithKeywords(#wrapper),
|
||||
#doc,
|
||||
)
|
||||
},
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
//! Code generation for the function that initializes a python module and adds classes and function.
|
||||
|
||||
use crate::{
|
||||
attributes::{self, is_attribute_ident, take_attributes, take_pyo3_options, NameAttribute},
|
||||
attributes::{
|
||||
self, is_attribute_ident, take_attributes, take_pyo3_options, CrateAttribute, NameAttribute,
|
||||
},
|
||||
pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},
|
||||
utils::PythonDoc,
|
||||
utils::{get_pyo3_crate, PythonDoc},
|
||||
};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
@ -16,17 +18,20 @@ use syn::{
|
|||
Ident, Path, Result,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PyModuleOptions {
|
||||
krate: Option<CrateAttribute>,
|
||||
name: Option<syn::Ident>,
|
||||
}
|
||||
|
||||
impl PyModuleOptions {
|
||||
pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {
|
||||
let mut options: PyModuleOptions = PyModuleOptions { name: None };
|
||||
let mut options: PyModuleOptions = Default::default();
|
||||
|
||||
for option in take_pyo3_options(attrs)? {
|
||||
match option {
|
||||
PyModulePyO3Option::Name(name) => options.set_name(name.0)?,
|
||||
PyModulePyO3Option::Crate(path) => options.set_crate(path)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,12 +47,23 @@ impl PyModuleOptions {
|
|||
self.name = Some(name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_crate(&mut self, path: CrateAttribute) -> Result<()> {
|
||||
ensure_spanned!(
|
||||
self.krate.is_none(),
|
||||
path.0.span() => "`crate` may only be specified once"
|
||||
);
|
||||
|
||||
self.krate = Some(path);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the function that is called by the python interpreter to initialize the native
|
||||
/// module
|
||||
pub fn py_init(fnname: &Ident, options: PyModuleOptions, doc: PythonDoc) -> TokenStream {
|
||||
let name = options.name.unwrap_or_else(|| fnname.unraw());
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
let cb_name = Ident::new(&format!("PyInit_{}", name), Span::call_site());
|
||||
|
||||
quote! {
|
||||
|
@ -55,13 +71,14 @@ pub fn py_init(fnname: &Ident, options: PyModuleOptions, doc: PythonDoc) -> Toke
|
|||
#[allow(non_snake_case)]
|
||||
/// This autogenerated function is called by the python interpreter when importing
|
||||
/// the module.
|
||||
pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject {
|
||||
use ::pyo3::derive_utils::ModuleDef;
|
||||
pub unsafe extern "C" fn #cb_name() -> *mut #krate::ffi::PyObject {
|
||||
use #krate as _pyo3;
|
||||
use _pyo3::derive_utils::ModuleDef;
|
||||
static NAME: &str = concat!(stringify!(#name), "\0");
|
||||
static DOC: &str = #doc;
|
||||
static MODULE_DEF: ModuleDef = unsafe { ModuleDef::new(NAME, DOC) };
|
||||
|
||||
::pyo3::callback::handle_panic(|_py| { MODULE_DEF.make_module(_py, #fnname) })
|
||||
_pyo3::callback::handle_panic(|_py| { MODULE_DEF.make_module(_py, #fnname) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +160,7 @@ fn get_pyfn_attr(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Option<PyFnArgs
|
|||
}
|
||||
|
||||
enum PyModulePyO3Option {
|
||||
Crate(CrateAttribute),
|
||||
Name(NameAttribute),
|
||||
}
|
||||
|
||||
|
@ -151,6 +169,8 @@ impl Parse for PyModulePyO3Option {
|
|||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(attributes::kw::name) {
|
||||
input.parse().map(PyModulePyO3Option::Name)
|
||||
} else if lookahead.peek(syn::Token![crate]) {
|
||||
input.parse().map(PyModulePyO3Option::Crate)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
|
|
|
@ -95,7 +95,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,
|
||||
}
|
||||
|
@ -136,7 +136,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 }
|
||||
};
|
||||
|
@ -163,7 +163,7 @@ pub fn impl_arg_params(
|
|||
|
||||
// create array of arguments, and then parse
|
||||
Ok(quote! {{
|
||||
const DESCRIPTION: ::pyo3::derive_utils::FunctionDescription = ::pyo3::derive_utils::FunctionDescription {
|
||||
const DESCRIPTION: _pyo3::derive_utils::FunctionDescription = _pyo3::derive_utils::FunctionDescription {
|
||||
cls_name: #cls_name,
|
||||
func_name: stringify!(#python_name),
|
||||
positional_parameter_names: &[#(#positional_parameter_names),*],
|
||||
|
@ -214,7 +214,7 @@ fn impl_arg_param(
|
|||
let ty = arg.ty;
|
||||
let name = arg.name;
|
||||
let transform_error = quote! {
|
||||
|e| ::pyo3::derive_utils::argument_extraction_error(#py, stringify!(#name), e)
|
||||
|e| _pyo3::derive_utils::argument_extraction_error(#py, stringify!(#name), e)
|
||||
};
|
||||
|
||||
if is_args(&spec.attrs, name) {
|
||||
|
@ -283,7 +283,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! { ::std::option::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 {
|
||||
|
@ -293,7 +293,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 },
|
||||
)
|
||||
};
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use crate::attributes::{self, take_pyo3_options, NameAttribute, TextSignatureAttribute};
|
||||
use crate::attributes::{
|
||||
self, take_pyo3_options, CrateAttribute, NameAttribute, TextSignatureAttribute,
|
||||
};
|
||||
use crate::deprecations::Deprecations;
|
||||
use crate::konst::{ConstAttributes, ConstSpec};
|
||||
use crate::pyimpl::{gen_default_slot_impls, gen_py_const, PyClassMethodsType};
|
||||
use crate::pymethod::{impl_py_getter_def, impl_py_setter_def, PropertyType};
|
||||
use crate::utils::{self, unwrap_group, PythonDoc};
|
||||
use crate::utils::{self, get_pyo3_crate, unwrap_group, PythonDoc};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::ext::IdentExt;
|
||||
|
@ -58,7 +60,7 @@ impl PyClassArgs {
|
|||
freelist: None,
|
||||
name: None,
|
||||
module: None,
|
||||
base: parse_quote! { ::pyo3::PyAny },
|
||||
base: parse_quote! { _pyo3::PyAny },
|
||||
has_dict: false,
|
||||
has_weaklist: false,
|
||||
is_gc: false,
|
||||
|
@ -186,10 +188,12 @@ impl PyClassArgs {
|
|||
pub struct PyClassPyO3Options {
|
||||
pub text_signature: Option<TextSignatureAttribute>,
|
||||
pub deprecations: Deprecations,
|
||||
pub krate: Option<CrateAttribute>,
|
||||
}
|
||||
|
||||
enum PyClassPyO3Option {
|
||||
TextSignature(TextSignatureAttribute),
|
||||
Crate(CrateAttribute),
|
||||
}
|
||||
|
||||
impl Parse for PyClassPyO3Option {
|
||||
|
@ -197,6 +201,8 @@ impl Parse for PyClassPyO3Option {
|
|||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(attributes::kw::text_signature) {
|
||||
input.parse().map(PyClassPyO3Option::TextSignature)
|
||||
} else if lookahead.peek(Token![crate]) {
|
||||
input.parse().map(PyClassPyO3Option::Crate)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
|
@ -211,6 +217,9 @@ impl PyClassPyO3Options {
|
|||
PyClassPyO3Option::TextSignature(text_signature) => {
|
||||
options.set_text_signature(text_signature)?;
|
||||
}
|
||||
PyClassPyO3Option::Crate(path) => {
|
||||
options.set_crate(path)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(options)
|
||||
|
@ -227,6 +236,15 @@ impl PyClassPyO3Options {
|
|||
self.text_signature = Some(text_signature);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_crate(&mut self, path: CrateAttribute) -> syn::Result<()> {
|
||||
ensure_spanned!(
|
||||
self.krate.is_none(),
|
||||
path.0.span() => "`text_signature` may only be specified once"
|
||||
);
|
||||
self.krate = Some(path);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_py_class(
|
||||
|
@ -242,6 +260,7 @@ pub fn build_py_class(
|
|||
.as_ref()
|
||||
.map(|attr| (get_class_python_name(&class.ident, args), attr)),
|
||||
);
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
|
||||
ensure_spanned!(
|
||||
class.generics.params.is_empty(),
|
||||
|
@ -278,6 +297,7 @@ pub fn build_py_class(
|
|||
field_options,
|
||||
methods_type,
|
||||
options.deprecations,
|
||||
krate,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -358,6 +378,7 @@ fn impl_class(
|
|||
field_options: Vec<(&syn::Field, FieldPyO3Options)>,
|
||||
methods_type: PyClassMethodsType,
|
||||
deprecations: Deprecations,
|
||||
krate: syn::Path,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let pytypeinfo_impl = impl_pytypeinfo(cls, attr, Some(&deprecations));
|
||||
|
||||
|
@ -368,11 +389,15 @@ fn impl_class(
|
|||
let descriptors = impl_descriptors(cls, field_options)?;
|
||||
|
||||
Ok(quote! {
|
||||
#pytypeinfo_impl
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#py_class_impl
|
||||
#pytypeinfo_impl
|
||||
|
||||
#descriptors
|
||||
#py_class_impl
|
||||
|
||||
#descriptors
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -382,10 +407,12 @@ struct PyClassEnumVariant<'a> {
|
|||
}
|
||||
|
||||
pub fn build_py_enum(
|
||||
enum_: &syn::ItemEnum,
|
||||
args: PyClassArgs,
|
||||
enum_: &mut syn::ItemEnum,
|
||||
args: &PyClassArgs,
|
||||
method_type: PyClassMethodsType,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let options = PyClassPyO3Options::take_pyo3_options(&mut enum_.attrs)?;
|
||||
|
||||
if enum_.variants.is_empty() {
|
||||
bail_spanned!(enum_.brace_token.span => "Empty enums can't be #[pyclass].");
|
||||
}
|
||||
|
@ -394,33 +421,38 @@ pub fn build_py_enum(
|
|||
.iter()
|
||||
.map(extract_variant_data)
|
||||
.collect::<syn::Result<_>>()?;
|
||||
impl_enum(enum_, args, variants, method_type)
|
||||
impl_enum(enum_, args, variants, method_type, options)
|
||||
}
|
||||
|
||||
fn impl_enum(
|
||||
enum_: &syn::ItemEnum,
|
||||
attrs: PyClassArgs,
|
||||
args: &PyClassArgs,
|
||||
variants: Vec<PyClassEnumVariant>,
|
||||
methods_type: PyClassMethodsType,
|
||||
options: PyClassPyO3Options,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let enum_name = &enum_.ident;
|
||||
let doc = utils::get_doc(&enum_.attrs, None);
|
||||
let enum_cls = impl_enum_class(enum_name, &attrs, variants, doc, methods_type)?;
|
||||
|
||||
Ok(quote! {
|
||||
#enum_cls
|
||||
})
|
||||
let doc = utils::get_doc(
|
||||
&enum_.attrs,
|
||||
options
|
||||
.text_signature
|
||||
.as_ref()
|
||||
.map(|attr| (get_class_python_name(&enum_.ident, args), attr)),
|
||||
);
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
impl_enum_class(enum_name, args, variants, doc, methods_type, krate)
|
||||
}
|
||||
|
||||
fn impl_enum_class(
|
||||
cls: &syn::Ident,
|
||||
attr: &PyClassArgs,
|
||||
args: &PyClassArgs,
|
||||
variants: Vec<PyClassEnumVariant>,
|
||||
doc: PythonDoc,
|
||||
methods_type: PyClassMethodsType,
|
||||
krate: syn::Path,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let pytypeinfo = impl_pytypeinfo(cls, attr, None);
|
||||
let pyclass_impls = PyClassImplsBuilder::new(cls, attr, methods_type)
|
||||
let pytypeinfo = impl_pytypeinfo(cls, args, None);
|
||||
let pyclass_impls = PyClassImplsBuilder::new(cls, args, methods_type)
|
||||
.doc(doc)
|
||||
.impl_all();
|
||||
let descriptors = unit_variants_as_descriptors(cls, variants.iter().map(|v| v.ident));
|
||||
|
@ -447,15 +479,17 @@ fn impl_enum_class(
|
|||
|
||||
let default_impls = gen_default_slot_impls(cls, vec![default_repr_impl]);
|
||||
Ok(quote! {
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#pytypeinfo
|
||||
#pytypeinfo
|
||||
|
||||
#pyclass_impls
|
||||
#pyclass_impls
|
||||
|
||||
#descriptors
|
||||
|
||||
#default_impls
|
||||
#default_impls
|
||||
|
||||
#descriptors
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -477,11 +511,11 @@ fn unit_variants_as_descriptors<'a>(
|
|||
.map(|var| gen_py_const(&cls_type, &variant_to_attribute(var)));
|
||||
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::PyClassDescriptors<#cls>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#cls>
|
||||
impl _pyo3::class::impl_::PyClassDescriptors<#cls>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#cls>
|
||||
{
|
||||
fn py_class_descriptors(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[::pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
|
||||
fn py_class_descriptors(self) -> &'static [_pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[_pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
|
||||
METHODS
|
||||
}
|
||||
}
|
||||
|
@ -540,11 +574,11 @@ fn impl_descriptors(
|
|||
.collect::<syn::Result<_>>()?;
|
||||
|
||||
Ok(quote! {
|
||||
impl ::pyo3::class::impl_::PyClassDescriptors<#cls>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#cls>
|
||||
impl _pyo3::class::impl_::PyClassDescriptors<#cls>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#cls>
|
||||
{
|
||||
fn py_class_descriptors(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[::pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
|
||||
fn py_class_descriptors(self) -> &'static [_pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[_pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
|
||||
METHODS
|
||||
}
|
||||
}
|
||||
|
@ -565,17 +599,17 @@ fn impl_pytypeinfo(
|
|||
};
|
||||
|
||||
quote! {
|
||||
unsafe impl ::pyo3::type_object::PyTypeInfo for #cls {
|
||||
type AsRefTarget = ::pyo3::PyCell<Self>;
|
||||
unsafe impl _pyo3::type_object::PyTypeInfo for #cls {
|
||||
type AsRefTarget = _pyo3::PyCell<Self>;
|
||||
|
||||
const NAME: &'static str = #cls_name;
|
||||
const MODULE: ::std::option::Option<&'static str> = #module;
|
||||
|
||||
#[inline]
|
||||
fn type_object_raw(py: ::pyo3::Python<'_>) -> *mut ::pyo3::ffi::PyTypeObject {
|
||||
fn type_object_raw(py: _pyo3::Python<'_>) -> *mut _pyo3::ffi::PyTypeObject {
|
||||
#deprecations
|
||||
|
||||
use ::pyo3::type_object::LazyStaticType;
|
||||
use _pyo3::type_object::LazyStaticType;
|
||||
static TYPE_OBJECT: LazyStaticType = LazyStaticType::new();
|
||||
TYPE_OBJECT.get_or_init::<Self>(py)
|
||||
}
|
||||
|
@ -629,29 +663,29 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
let cls = self.cls;
|
||||
let attr = self.attr;
|
||||
let dict = if attr.has_dict {
|
||||
quote! { ::pyo3::pyclass_slots::PyClassDictSlot }
|
||||
quote! { _pyo3::pyclass_slots::PyClassDictSlot }
|
||||
} else if attr.has_extends {
|
||||
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::Dict }
|
||||
quote! { <Self::BaseType as _pyo3::class::impl_::PyClassBaseType>::Dict }
|
||||
} else {
|
||||
quote! { ::pyo3::pyclass_slots::PyClassDummySlot }
|
||||
quote! { _pyo3::pyclass_slots::PyClassDummySlot }
|
||||
};
|
||||
|
||||
// insert space for weak ref
|
||||
let weakref = if attr.has_weaklist {
|
||||
quote! { ::pyo3::pyclass_slots::PyClassWeakRefSlot }
|
||||
quote! { _pyo3::pyclass_slots::PyClassWeakRefSlot }
|
||||
} else if attr.has_extends {
|
||||
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::WeakRef }
|
||||
quote! { <Self::BaseType as _pyo3::class::impl_::PyClassBaseType>::WeakRef }
|
||||
} else {
|
||||
quote! { ::pyo3::pyclass_slots::PyClassDummySlot }
|
||||
quote! { _pyo3::pyclass_slots::PyClassDummySlot }
|
||||
};
|
||||
|
||||
let base_nativetype = if attr.has_extends {
|
||||
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::BaseNativeType }
|
||||
quote! { <Self::BaseType as _pyo3::class::impl_::PyClassBaseType>::BaseNativeType }
|
||||
} else {
|
||||
quote! { ::pyo3::PyAny }
|
||||
quote! { _pyo3::PyAny }
|
||||
};
|
||||
quote! {
|
||||
impl ::pyo3::PyClass for #cls {
|
||||
impl _pyo3::PyClass for #cls {
|
||||
type Dict = #dict;
|
||||
type WeakRef = #weakref;
|
||||
type BaseNativeType = #base_nativetype;
|
||||
|
@ -661,14 +695,14 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
fn impl_extractext(&self) -> TokenStream {
|
||||
let cls = self.cls;
|
||||
quote! {
|
||||
impl<'a> ::pyo3::derive_utils::ExtractExt<'a> for &'a #cls
|
||||
impl<'a> _pyo3::derive_utils::ExtractExt<'a> for &'a #cls
|
||||
{
|
||||
type Target = ::pyo3::PyRef<'a, #cls>;
|
||||
type Target = _pyo3::PyRef<'a, #cls>;
|
||||
}
|
||||
|
||||
impl<'a> ::pyo3::derive_utils::ExtractExt<'a> for &'a mut #cls
|
||||
impl<'a> _pyo3::derive_utils::ExtractExt<'a> for &'a mut #cls
|
||||
{
|
||||
type Target = ::pyo3::PyRefMut<'a, #cls>;
|
||||
type Target = _pyo3::PyRefMut<'a, #cls>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -679,9 +713,9 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
// If #cls is not extended type, we allow Self->PyObject conversion
|
||||
if !attr.has_extends {
|
||||
quote! {
|
||||
impl ::pyo3::IntoPy<::pyo3::PyObject> for #cls {
|
||||
fn into_py(self, py: ::pyo3::Python) -> ::pyo3::PyObject {
|
||||
::pyo3::IntoPy::into_py(::pyo3::Py::new(py, self).unwrap(), py)
|
||||
impl _pyo3::IntoPy<_pyo3::PyObject> for #cls {
|
||||
fn into_py(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
_pyo3::IntoPy::into_py(_pyo3::Py::new(py, self).unwrap(), py)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -698,13 +732,13 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
let is_subclass = self.attr.has_extends;
|
||||
|
||||
let thread_checker = if self.attr.has_unsendable {
|
||||
quote! { ::pyo3::class::impl_::ThreadCheckerImpl<#cls> }
|
||||
quote! { _pyo3::class::impl_::ThreadCheckerImpl<#cls> }
|
||||
} else if self.attr.has_extends {
|
||||
quote! {
|
||||
::pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as ::pyo3::class::impl_::PyClassImpl>::BaseType>
|
||||
_pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as _pyo3::class::impl_::PyClassImpl>::BaseType>
|
||||
}
|
||||
} else {
|
||||
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
|
||||
quote! { _pyo3::class::impl_::ThreadCheckerStub<#cls> }
|
||||
};
|
||||
|
||||
let (for_each_py_method, methods_protos, inventory, inventory_class) = match self
|
||||
|
@ -724,13 +758,13 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
);
|
||||
(
|
||||
quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(::pyo3::class::impl_::PyClassInventory::methods(inventory));
|
||||
for inventory in _pyo3::inventory::iter::<<Self as _pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(_pyo3::class::impl_::PyClassInventory::methods(inventory));
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(::pyo3::class::impl_::PyClassInventory::slots(inventory));
|
||||
for inventory in _pyo3::inventory::iter::<<Self as _pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(_pyo3::class::impl_::PyClassInventory::slots(inventory));
|
||||
}
|
||||
},
|
||||
Some(quote! { type Inventory = #inventory_class_name; }),
|
||||
|
@ -739,19 +773,19 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
}
|
||||
};
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::PyClassImpl for #cls {
|
||||
impl _pyo3::class::impl_::PyClassImpl for #cls {
|
||||
const DOC: &'static str = #doc;
|
||||
const IS_GC: bool = #is_gc;
|
||||
const IS_BASETYPE: bool = #is_basetype;
|
||||
const IS_SUBCLASS: bool = #is_subclass;
|
||||
|
||||
type Layout = ::pyo3::PyCell<Self>;
|
||||
type Layout = _pyo3::PyCell<Self>;
|
||||
type BaseType = #base;
|
||||
type ThreadChecker = #thread_checker;
|
||||
#inventory
|
||||
|
||||
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
|
||||
use ::pyo3::class::impl_::*;
|
||||
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[_pyo3::class::PyMethodDefType])) {
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
#for_each_py_method;
|
||||
visitor(collector.py_class_descriptors());
|
||||
|
@ -761,25 +795,25 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
visitor(collector.mapping_protocol_methods());
|
||||
visitor(collector.number_protocol_methods());
|
||||
}
|
||||
fn get_new() -> ::std::option::Option<::pyo3::ffi::newfunc> {
|
||||
use ::pyo3::class::impl_::*;
|
||||
fn get_new() -> ::std::option::Option<_pyo3::ffi::newfunc> {
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
collector.new_impl()
|
||||
}
|
||||
fn get_alloc() -> ::std::option::Option<::pyo3::ffi::allocfunc> {
|
||||
use ::pyo3::class::impl_::*;
|
||||
fn get_alloc() -> ::std::option::Option<_pyo3::ffi::allocfunc> {
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
collector.alloc_impl()
|
||||
}
|
||||
fn get_free() -> ::std::option::Option<::pyo3::ffi::freefunc> {
|
||||
use ::pyo3::class::impl_::*;
|
||||
fn get_free() -> ::std::option::Option<_pyo3::ffi::freefunc> {
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
collector.free_impl()
|
||||
}
|
||||
|
||||
fn for_each_proto_slot(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::ffi::PyType_Slot])) {
|
||||
fn for_each_proto_slot(visitor: &mut dyn ::std::ops::FnMut(&[_pyo3::ffi::PyType_Slot])) {
|
||||
// Implementation which uses dtolnay specialization to load all slots.
|
||||
use ::pyo3::class::impl_::*;
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
// This depends on Python implementation detail;
|
||||
// an old slot entry will be overriden by newer ones.
|
||||
|
@ -796,8 +830,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
#methods_protos
|
||||
}
|
||||
|
||||
fn get_buffer() -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
|
||||
use ::pyo3::class::impl_::*;
|
||||
fn get_buffer() -> ::std::option::Option<&'static _pyo3::class::impl_::PyBufferProcs> {
|
||||
use _pyo3::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<Self>::new();
|
||||
collector.buffer_procs()
|
||||
}
|
||||
|
@ -812,31 +846,31 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
|
||||
self.attr.freelist.as_ref().map_or(quote!{}, |freelist| {
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::PyClassWithFreeList for #cls {
|
||||
impl _pyo3::class::impl_::PyClassWithFreeList for #cls {
|
||||
#[inline]
|
||||
fn get_free_list(_py: ::pyo3::Python<'_>) -> &mut ::pyo3::impl_::freelist::FreeList<*mut ::pyo3::ffi::PyObject> {
|
||||
static mut FREELIST: *mut ::pyo3::impl_::freelist::FreeList<*mut ::pyo3::ffi::PyObject> = 0 as *mut _;
|
||||
fn get_free_list(_py: _pyo3::Python<'_>) -> &mut _pyo3::impl_::freelist::FreeList<*mut _pyo3::ffi::PyObject> {
|
||||
static mut FREELIST: *mut _pyo3::impl_::freelist::FreeList<*mut _pyo3::ffi::PyObject> = 0 as *mut _;
|
||||
unsafe {
|
||||
if FREELIST.is_null() {
|
||||
FREELIST = ::std::boxed::Box::into_raw(::std::boxed::Box::new(
|
||||
::pyo3::impl_::freelist::FreeList::with_capacity(#freelist)));
|
||||
_pyo3::impl_::freelist::FreeList::with_capacity(#freelist)));
|
||||
}
|
||||
&mut *FREELIST
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::class::impl_::PyClassAllocImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
impl _pyo3::class::impl_::PyClassAllocImpl<#cls> for _pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
#[inline]
|
||||
fn alloc_impl(self) -> ::std::option::Option<::pyo3::ffi::allocfunc> {
|
||||
::std::option::Option::Some(::pyo3::class::impl_::alloc_with_freelist::<#cls>)
|
||||
fn alloc_impl(self) -> ::std::option::Option<_pyo3::ffi::allocfunc> {
|
||||
::std::option::Option::Some(_pyo3::class::impl_::alloc_with_freelist::<#cls>)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::class::impl_::PyClassFreeImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
impl _pyo3::class::impl_::PyClassFreeImpl<#cls> for _pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
#[inline]
|
||||
fn free_impl(self) -> ::std::option::Option<::pyo3::ffi::freefunc> {
|
||||
::std::option::Option::Some(::pyo3::class::impl_::free_with_freelist::<#cls>)
|
||||
fn free_impl(self) -> ::std::option::Option<_pyo3::ffi::freefunc> {
|
||||
::std::option::Option::Some(_pyo3::class::impl_::free_with_freelist::<#cls>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -851,9 +885,9 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
let closure_token = syn::Ident::new(&closure_name, Span::call_site());
|
||||
quote! {
|
||||
fn #closure_token() {
|
||||
use ::pyo3::class;
|
||||
use _pyo3::class;
|
||||
|
||||
fn _assert_implements_protocol<'p, T: ::pyo3::class::PyGCProtocol<'p>>() {}
|
||||
fn _assert_implements_protocol<'p, T: _pyo3::class::PyGCProtocol<'p>>() {}
|
||||
_assert_implements_protocol::<#cls>();
|
||||
}
|
||||
}
|
||||
|
@ -867,23 +901,23 @@ fn define_inventory_class(inventory_class_name: &syn::Ident) -> TokenStream {
|
|||
quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #inventory_class_name {
|
||||
methods: &'static [::pyo3::class::PyMethodDefType],
|
||||
slots: &'static [::pyo3::ffi::PyType_Slot],
|
||||
methods: &'static [_pyo3::class::PyMethodDefType],
|
||||
slots: &'static [_pyo3::ffi::PyType_Slot],
|
||||
}
|
||||
impl #inventory_class_name {
|
||||
const fn new(
|
||||
methods: &'static [::pyo3::class::PyMethodDefType],
|
||||
slots: &'static [::pyo3::ffi::PyType_Slot],
|
||||
methods: &'static [_pyo3::class::PyMethodDefType],
|
||||
slots: &'static [_pyo3::ffi::PyType_Slot],
|
||||
) -> Self {
|
||||
Self { methods, slots }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::class::impl_::PyClassInventory for #inventory_class_name {
|
||||
fn methods(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
|
||||
impl _pyo3::class::impl_::PyClassInventory for #inventory_class_name {
|
||||
fn methods(&'static self) -> &'static [_pyo3::class::PyMethodDefType] {
|
||||
self.methods
|
||||
}
|
||||
fn slots(&'static self) -> &'static [::pyo3::ffi::PyType_Slot] {
|
||||
fn slots(&'static self) -> &'static [_pyo3::ffi::PyType_Slot] {
|
||||
self.slots
|
||||
}
|
||||
}
|
||||
|
@ -892,6 +926,6 @@ fn define_inventory_class(inventory_class_name: &syn::Ident) -> TokenStream {
|
|||
unsafe impl ::std::marker::Send for #inventory_class_name {}
|
||||
unsafe impl ::std::marker::Sync for #inventory_class_name {}
|
||||
|
||||
::pyo3::inventory::collect!(#inventory_class_name);
|
||||
_pyo3::inventory::collect!(#inventory_class_name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
use crate::{
|
||||
attributes::{
|
||||
self, get_pyo3_options, take_attributes, take_pyo3_options, FromPyWithAttribute,
|
||||
NameAttribute, TextSignatureAttribute,
|
||||
self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute,
|
||||
FromPyWithAttribute, NameAttribute, TextSignatureAttribute,
|
||||
},
|
||||
deprecations::Deprecations,
|
||||
method::{self, CallingConvention, FnArg},
|
||||
pymethod::check_generic,
|
||||
utils::{self, ensure_not_async_fn},
|
||||
utils::{self, ensure_not_async_fn, get_pyo3_crate},
|
||||
};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
@ -239,17 +239,12 @@ pub struct PyFunctionOptions {
|
|||
pub signature: Option<PyFunctionSignature>,
|
||||
pub text_signature: Option<TextSignatureAttribute>,
|
||||
pub deprecations: Deprecations,
|
||||
pub krate: Option<CrateAttribute>,
|
||||
}
|
||||
|
||||
impl Parse for PyFunctionOptions {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let mut options = PyFunctionOptions {
|
||||
pass_module: None,
|
||||
name: None,
|
||||
signature: None,
|
||||
text_signature: None,
|
||||
deprecations: Deprecations::new(),
|
||||
};
|
||||
let mut options = PyFunctionOptions::default();
|
||||
|
||||
while !input.is_empty() {
|
||||
let lookahead = input.lookahead1();
|
||||
|
@ -262,6 +257,9 @@ impl Parse for PyFunctionOptions {
|
|||
if !input.is_empty() {
|
||||
let _: Comma = input.parse()?;
|
||||
}
|
||||
} else if lookahead.peek(syn::Token![crate]) {
|
||||
// TODO needs duplicate check?
|
||||
options.krate = Some(input.parse()?);
|
||||
} else {
|
||||
// If not recognised attribute, this is "legacy" pyfunction syntax #[pyfunction(a, b)]
|
||||
//
|
||||
|
@ -280,6 +278,7 @@ pub enum PyFunctionOption {
|
|||
PassModule(attributes::kw::pass_module),
|
||||
Signature(PyFunctionSignature),
|
||||
TextSignature(TextSignatureAttribute),
|
||||
Crate(CrateAttribute),
|
||||
}
|
||||
|
||||
impl Parse for PyFunctionOption {
|
||||
|
@ -293,6 +292,8 @@ impl Parse for PyFunctionOption {
|
|||
input.parse().map(PyFunctionOption::Signature)
|
||||
} else if lookahead.peek(attributes::kw::text_signature) {
|
||||
input.parse().map(PyFunctionOption::TextSignature)
|
||||
} else if lookahead.peek(syn::Token![crate]) {
|
||||
input.parse().map(PyFunctionOption::Crate)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
|
@ -335,6 +336,13 @@ impl PyFunctionOptions {
|
|||
);
|
||||
self.text_signature = Some(text_signature);
|
||||
}
|
||||
PyFunctionOption::Crate(path) => {
|
||||
ensure_spanned!(
|
||||
self.krate.is_none(),
|
||||
path.0.span() => "`crate` may only be specified once"
|
||||
);
|
||||
self.krate = Some(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -410,6 +418,7 @@ pub fn impl_wrap_pyfunction(
|
|||
);
|
||||
|
||||
let function_wrapper_ident = function_wrapper_ident(&func.sig.ident);
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
|
||||
let spec = method::FnSpec {
|
||||
tp: if options.pass_module.is_some() {
|
||||
|
@ -426,6 +435,7 @@ pub fn impl_wrap_pyfunction(
|
|||
doc,
|
||||
deprecations: options.deprecations,
|
||||
text_signature: options.text_signature,
|
||||
krate: krate.clone(),
|
||||
};
|
||||
|
||||
let wrapper_ident = format_ident!("__pyo3_raw_{}", spec.name);
|
||||
|
@ -434,10 +444,12 @@ pub fn impl_wrap_pyfunction(
|
|||
|
||||
let wrapped_pyfunction = quote! {
|
||||
#wrapper
|
||||
|
||||
pub(crate) fn #function_wrapper_ident<'a>(
|
||||
args: impl ::std::convert::Into<::pyo3::derive_utils::PyFunctionArguments<'a>>
|
||||
) -> ::pyo3::PyResult<&'a ::pyo3::types::PyCFunction> {
|
||||
::pyo3::types::PyCFunction::internal_new(#methoddef, args.into())
|
||||
args: impl ::std::convert::Into<#krate::derive_utils::PyFunctionArguments<'a>>
|
||||
) -> #krate::PyResult<&'a #krate::types::PyCFunction> {
|
||||
use #krate as _pyo3;
|
||||
_pyo3::types::PyCFunction::internal_new(#methoddef, args.into())
|
||||
}
|
||||
};
|
||||
Ok((function_wrapper_ident, wrapped_pyfunction))
|
||||
|
|
|
@ -3,14 +3,20 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use crate::{
|
||||
attributes::{take_pyo3_options, CrateAttribute},
|
||||
konst::{ConstAttributes, ConstSpec},
|
||||
pyfunction::PyFunctionOptions,
|
||||
pymethod::{self, is_proto_method},
|
||||
utils::get_pyo3_crate,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use pymethod::GeneratedPyMethod;
|
||||
use quote::quote;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
spanned::Spanned,
|
||||
Result,
|
||||
};
|
||||
|
||||
/// The mechanism used to collect `#[pymethods]` into the type object
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -19,6 +25,50 @@ pub enum PyClassMethodsType {
|
|||
Inventory,
|
||||
}
|
||||
|
||||
enum PyImplPyO3Option {
|
||||
Crate(CrateAttribute),
|
||||
}
|
||||
|
||||
impl Parse for PyImplPyO3Option {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(syn::Token![crate]) {
|
||||
input.parse().map(PyImplPyO3Option::Crate)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PyImplOptions {
|
||||
krate: Option<CrateAttribute>,
|
||||
}
|
||||
|
||||
impl PyImplOptions {
|
||||
pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {
|
||||
let mut options: PyImplOptions = Default::default();
|
||||
|
||||
for option in take_pyo3_options(attrs)? {
|
||||
match option {
|
||||
PyImplPyO3Option::Crate(path) => options.set_crate(path)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
|
||||
fn set_crate(&mut self, path: CrateAttribute) -> Result<()> {
|
||||
ensure_spanned!(
|
||||
self.krate.is_none(),
|
||||
path.0.span() => "`crate` may only be specified once"
|
||||
);
|
||||
|
||||
self.krate = Some(path);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_py_methods(
|
||||
ast: &mut syn::ItemImpl,
|
||||
methods_type: PyClassMethodsType,
|
||||
|
@ -31,7 +81,8 @@ pub fn build_py_methods(
|
|||
"#[pymethods] cannot be used with lifetime parameters or generics"
|
||||
);
|
||||
} else {
|
||||
impl_methods(&ast.self_ty, &mut ast.items, methods_type)
|
||||
let options = PyImplOptions::from_attrs(&mut ast.attrs)?;
|
||||
impl_methods(&ast.self_ty, &mut ast.items, methods_type, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +90,7 @@ pub fn impl_methods(
|
|||
ty: &syn::Type,
|
||||
impls: &mut Vec<syn::ImplItem>,
|
||||
methods_type: PyClassMethodsType,
|
||||
options: PyImplOptions,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let mut trait_impls = Vec::new();
|
||||
let mut proto_impls = Vec::new();
|
||||
|
@ -49,8 +101,9 @@ pub fn impl_methods(
|
|||
for iimpl in impls.iter_mut() {
|
||||
match iimpl {
|
||||
syn::ImplItem::Method(meth) => {
|
||||
let options = PyFunctionOptions::from_attrs(&mut meth.attrs)?;
|
||||
match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, options)? {
|
||||
let mut fun_options = PyFunctionOptions::from_attrs(&mut meth.attrs)?;
|
||||
fun_options.krate = fun_options.krate.or_else(|| options.krate.clone());
|
||||
match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, fun_options)? {
|
||||
GeneratedPyMethod::Method(token_stream) => {
|
||||
let attrs = get_cfg_attributes(&meth.attrs);
|
||||
methods.push(quote!(#(#attrs)* #token_stream));
|
||||
|
@ -95,25 +148,35 @@ pub fn impl_methods(
|
|||
|
||||
add_shared_proto_slots(ty, &mut proto_impls, implemented_proto_fragments);
|
||||
|
||||
let krate = get_pyo3_crate(&options.krate);
|
||||
|
||||
Ok(match methods_type {
|
||||
PyClassMethodsType::Specialization => {
|
||||
let methods_registration = impl_py_methods(ty, methods);
|
||||
let protos_registration = impl_protos(ty, proto_impls);
|
||||
|
||||
quote! {
|
||||
#(#trait_impls)*
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#protos_registration
|
||||
#(#trait_impls)*
|
||||
|
||||
#methods_registration
|
||||
#protos_registration
|
||||
|
||||
#methods_registration
|
||||
};
|
||||
}
|
||||
}
|
||||
PyClassMethodsType::Inventory => {
|
||||
let inventory = submit_methods_inventory(ty, methods, proto_impls);
|
||||
quote! {
|
||||
#(#trait_impls)*
|
||||
const _: () = {
|
||||
use #krate as _pyo3;
|
||||
|
||||
#inventory
|
||||
#(#trait_impls)*
|
||||
|
||||
#inventory
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -124,13 +187,13 @@ pub 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
|
||||
})
|
||||
|
@ -182,11 +245,11 @@ pub fn gen_default_slot_impls(cls: &syn::Ident, method_defs: Vec<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
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +266,7 @@ fn add_shared_proto_slots(
|
|||
let first_implemented = implemented_proto_fragments.remove($first);
|
||||
let second_implemented = implemented_proto_fragments.remove($second);
|
||||
if first_implemented || second_implemented {
|
||||
proto_impls.push(quote! { ::pyo3::$slot!(#ty) })
|
||||
proto_impls.push(quote! { _pyo3::class::impl_::$slot!(#ty) })
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -235,10 +298,10 @@ fn add_shared_proto_slots(
|
|||
|
||||
fn impl_protos(ty: &syn::Type, proto_impls: Vec<TokenStream>) -> TokenStream {
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::PyMethodsProtocolSlots<#ty>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
impl _pyo3::class::impl_::PyMethodsProtocolSlots<#ty>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
{
|
||||
fn methods_protocol_slots(self) -> &'static [::pyo3::ffi::PyType_Slot] {
|
||||
fn methods_protocol_slots(self) -> &'static [_pyo3::ffi::PyType_Slot] {
|
||||
&[#(#proto_impls),*]
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +314,8 @@ fn submit_methods_inventory(
|
|||
proto_impls: Vec<TokenStream>,
|
||||
) -> TokenStream {
|
||||
quote! {
|
||||
::pyo3::inventory::submit! {
|
||||
type Inventory = <#ty as ::pyo3::class::impl_::PyClassImpl>::Inventory;
|
||||
_pyo3::inventory::submit! {
|
||||
type Inventory = <#ty as _pyo3::class::impl_::PyClassImpl>::Inventory;
|
||||
Inventory::new(&[#(#methods),*], &[#(#proto_impls),*])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,12 +120,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::TraitImpl(impl_py_method_def_new(cls, spec)?),
|
||||
|
@ -186,7 +186,7 @@ pub fn impl_py_method_def(
|
|||
};
|
||||
let methoddef = spec.get_methoddef(quote! {{ #wrapper_def #wrapper_ident }});
|
||||
Ok(quote! {
|
||||
::pyo3::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
|
||||
_pyo3::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,8 @@ fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream>
|
|||
let wrapper_ident = syn::Ident::new("__wrap", Span::call_site());
|
||||
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) -> ::std::option::Option<::pyo3::ffi::newfunc> {
|
||||
impl _pyo3::class::impl_::PyClassNewImpl<#cls> for _pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
fn new_impl(self) -> ::std::option::Option<_pyo3::ffi::newfunc> {
|
||||
::std::option::Option::Some({
|
||||
#wrapper
|
||||
#wrapper_ident
|
||||
|
@ -214,9 +214,9 @@ fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec) -> Result<TokenStream> {
|
|||
let wrapper = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
|
||||
Ok(quote! {{
|
||||
#wrapper
|
||||
::pyo3::ffi::PyType_Slot {
|
||||
slot: ::pyo3::ffi::Py_tp_call,
|
||||
pfunc: __wrap as ::pyo3::ffi::ternaryfunc as _
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::Py_tp_call,
|
||||
pfunc: __wrap as _pyo3::ffi::ternaryfunc as _
|
||||
}
|
||||
}})
|
||||
}
|
||||
|
@ -226,13 +226,13 @@ fn impl_py_class_attribute(cls: &syn::Type, spec: &FnSpec) -> TokenStream {
|
|||
let deprecations = &spec.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::#name(), py)
|
||||
_pyo3::IntoPy::into_py(#cls::#name(), py)
|
||||
}
|
||||
__wrap
|
||||
})
|
||||
|
@ -295,26 +295,26 @@ pub fn impl_py_setter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
|
|||
}
|
||||
};
|
||||
Ok(quote! {
|
||||
::pyo3::class::PyMethodDefType::Setter({
|
||||
_pyo3::class::PyMethodDefType::Setter({
|
||||
#deprecations
|
||||
::pyo3::class::PySetterDef::new(
|
||||
_pyo3::class::PySetterDef::new(
|
||||
#python_name,
|
||||
::pyo3::class::methods::PySetter({
|
||||
_pyo3::class::methods::PySetter({
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut ::pyo3::ffi::PyObject,
|
||||
_value: *mut ::pyo3::ffi::PyObject,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_value: *mut _pyo3::ffi::PyObject,
|
||||
_: *mut ::std::os::raw::c_void
|
||||
) -> ::std::os::raw::c_int {
|
||||
::pyo3::callback::handle_panic(|_py| {
|
||||
_pyo3::callback::handle_panic(|_py| {
|
||||
#slf
|
||||
let _value = _py
|
||||
.from_borrowed_ptr_or_opt(_value)
|
||||
.ok_or_else(|| {
|
||||
::pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
|
||||
_pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
|
||||
})?;
|
||||
let _val = ::pyo3::FromPyObject::extract(_value)?;
|
||||
let _val = _pyo3::FromPyObject::extract(_value)?;
|
||||
|
||||
::pyo3::callback::convert(_py, #setter_impl)
|
||||
_pyo3::callback::convert(_py, #setter_impl)
|
||||
})
|
||||
}
|
||||
__wrap
|
||||
|
@ -375,18 +375,18 @@ pub fn impl_py_getter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
|
|||
}
|
||||
};
|
||||
Ok(quote! {
|
||||
::pyo3::class::PyMethodDefType::Getter({
|
||||
_pyo3::class::PyMethodDefType::Getter({
|
||||
#deprecations
|
||||
::pyo3::class::PyGetterDef::new(
|
||||
_pyo3::class::PyGetterDef::new(
|
||||
#python_name,
|
||||
::pyo3::class::methods::PyGetter({
|
||||
_pyo3::class::methods::PyGetter({
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut ::pyo3::ffi::PyObject,
|
||||
_slf: *mut _pyo3::ffi::PyObject,
|
||||
_: *mut ::std::os::raw::c_void
|
||||
) -> *mut ::pyo3::ffi::PyObject {
|
||||
::pyo3::callback::handle_panic(|_py| {
|
||||
) -> *mut _pyo3::ffi::PyObject {
|
||||
_pyo3::callback::handle_panic(|_py| {
|
||||
#slf
|
||||
::pyo3::callback::convert(_py, #getter_impl)
|
||||
_pyo3::callback::convert(_py, #getter_impl)
|
||||
})
|
||||
}
|
||||
__wrap
|
||||
|
@ -459,10 +459,10 @@ const __GETATTR__: SlotDef = SlotDef::new("Py_tp_getattro", "getattrofunc")
|
|||
quote! {
|
||||
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
|
||||
// for existing fields and methods first
|
||||
let existing = ::pyo3::ffi::PyObject_GenericGetAttr(_slf, arg0);
|
||||
let existing = _pyo3::ffi::PyObject_GenericGetAttr(_slf, arg0);
|
||||
if existing.is_null() {
|
||||
// PyObject_HasAttr also tries to get an object and clears the error if it fails
|
||||
::pyo3::ffi::PyErr_Clear();
|
||||
_pyo3::ffi::PyErr_Clear();
|
||||
} else {
|
||||
return existing;
|
||||
}
|
||||
|
@ -473,7 +473,7 @@ const __REPR__: SlotDef = SlotDef::new("Py_tp_repr", "reprfunc");
|
|||
const __HASH__: SlotDef = SlotDef::new("Py_tp_hash", "hashfunc")
|
||||
.ret_ty(Ty::PyHashT)
|
||||
.return_conversion(TokenGenerator(
|
||||
|| quote! { ::pyo3::callback::HashCallbackOutput },
|
||||
|| quote! { _pyo3::callback::HashCallbackOutput },
|
||||
));
|
||||
const __RICHCMP__: SlotDef = SlotDef::new("Py_tp_richcompare", "richcmpfunc")
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
|
@ -482,12 +482,12 @@ const __GET__: SlotDef = SlotDef::new("Py_tp_descr_get", "descrgetfunc")
|
|||
.arguments(&[Ty::MaybeNullObject, Ty::MaybeNullObject]);
|
||||
const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc");
|
||||
const __NEXT__: SlotDef = SlotDef::new("Py_tp_iternext", "iternextfunc").return_conversion(
|
||||
TokenGenerator(|| quote! { ::pyo3::class::iter::IterNextOutput::<_, _> }),
|
||||
TokenGenerator(|| quote! { _pyo3::class::iter::IterNextOutput::<_, _> }),
|
||||
);
|
||||
const __AWAIT__: SlotDef = SlotDef::new("Py_am_await", "unaryfunc");
|
||||
const __AITER__: SlotDef = SlotDef::new("Py_am_aiter", "unaryfunc");
|
||||
const __ANEXT__: SlotDef = SlotDef::new("Py_am_anext", "unaryfunc").return_conversion(
|
||||
TokenGenerator(|| quote! { ::pyo3::class::pyasync::IterANextOutput::<_, _> }),
|
||||
TokenGenerator(|| quote! { _pyo3::class::pyasync::IterANextOutput::<_, _> }),
|
||||
);
|
||||
const __LEN__: SlotDef = SlotDef::new("Py_mp_length", "lenfunc").ret_ty(Ty::PySsizeT);
|
||||
const __CONTAINS__: SlotDef = SlotDef::new("Py_sq_contains", "objobjproc")
|
||||
|
@ -613,11 +613,11 @@ enum Ty {
|
|||
impl Ty {
|
||||
fn ffi_type(self) -> TokenStream {
|
||||
match self {
|
||||
Ty::Object | Ty::MaybeNullObject => quote! { *mut ::pyo3::ffi::PyObject },
|
||||
Ty::NonNullObject => quote! { ::std::ptr::NonNull<::pyo3::ffi::PyObject> },
|
||||
Ty::Object | Ty::MaybeNullObject => quote! { *mut _pyo3::ffi::PyObject },
|
||||
Ty::NonNullObject => quote! { ::std::ptr::NonNull<_pyo3::ffi::PyObject> },
|
||||
Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int },
|
||||
Ty::PyHashT => quote! { ::pyo3::ffi::Py_hash_t },
|
||||
Ty::PySsizeT => quote! { ::pyo3::ffi::Py_ssize_t },
|
||||
Ty::PyHashT => quote! { _pyo3::ffi::Py_hash_t },
|
||||
Ty::PySsizeT => quote! { _pyo3::ffi::Py_ssize_t },
|
||||
Ty::Void => quote! { () },
|
||||
}
|
||||
}
|
||||
|
@ -636,7 +636,7 @@ impl Ty {
|
|||
extract_error_mode,
|
||||
py,
|
||||
quote! {
|
||||
#py.from_borrowed_ptr::<::pyo3::PyAny>(#ident).extract()
|
||||
#py.from_borrowed_ptr::<_pyo3::PyAny>(#ident).extract()
|
||||
},
|
||||
);
|
||||
extract_object(cls, arg.ty, ident, extract)
|
||||
|
@ -646,9 +646,9 @@ impl Ty {
|
|||
extract_error_mode,
|
||||
py,
|
||||
quote! {
|
||||
#py.from_borrowed_ptr::<::pyo3::PyAny>(
|
||||
#py.from_borrowed_ptr::<_pyo3::PyAny>(
|
||||
if #ident.is_null() {
|
||||
::pyo3::ffi::Py_None()
|
||||
_pyo3::ffi::Py_None()
|
||||
} else {
|
||||
#ident
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ impl Ty {
|
|||
extract_error_mode,
|
||||
py,
|
||||
quote! {
|
||||
#py.from_borrowed_ptr::<::pyo3::PyAny>(#ident.as_ptr()).extract()
|
||||
#py.from_borrowed_ptr::<_pyo3::PyAny>(#ident.as_ptr()).extract()
|
||||
},
|
||||
);
|
||||
extract_object(cls, arg.ty, ident, extract)
|
||||
|
@ -672,8 +672,8 @@ impl Ty {
|
|||
extract_error_mode,
|
||||
py,
|
||||
quote! {
|
||||
::pyo3::class::basic::CompareOp::from_raw(#ident)
|
||||
.ok_or_else(|| ::pyo3::exceptions::PyValueError::new_err("invalid comparison operator"))
|
||||
_pyo3::class::basic::CompareOp::from_raw(#ident)
|
||||
.ok_or_else(|| _pyo3::exceptions::PyValueError::new_err("invalid comparison operator"))
|
||||
},
|
||||
);
|
||||
quote! {
|
||||
|
@ -695,7 +695,7 @@ fn handle_error(
|
|||
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()); },
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -712,7 +712,7 @@ fn extract_object(
|
|||
replace_self(&mut tref.elem, cls);
|
||||
let mut_ = tref.mutability;
|
||||
quote! {
|
||||
let #mut_ #ident: <#tref as ::pyo3::derive_utils::ExtractExt<'_>>::Target = #extract;
|
||||
let #mut_ #ident: <#tref as _pyo3::derive_utils::ExtractExt<'_>>::Target = #extract;
|
||||
let #ident = &#mut_ *#ident;
|
||||
}
|
||||
} else {
|
||||
|
@ -731,13 +731,13 @@ impl ReturnMode {
|
|||
fn return_call_output(&self, py: &syn::Ident, call: TokenStream) -> TokenStream {
|
||||
match self {
|
||||
ReturnMode::Conversion(conversion) => quote! {
|
||||
let _result: ::pyo3::PyResult<#conversion> = #call;
|
||||
::pyo3::callback::convert(#py, _result)
|
||||
let _result: _pyo3::PyResult<#conversion> = #call;
|
||||
_pyo3::callback::convert(#py, _result)
|
||||
},
|
||||
ReturnMode::ReturnSelf => quote! {
|
||||
let _result: ::pyo3::PyResult<()> = #call;
|
||||
let _result: _pyo3::PyResult<()> = #call;
|
||||
_result?;
|
||||
::pyo3::ffi::Py_XINCREF(_raw_slf);
|
||||
_pyo3::ffi::Py_XINCREF(_raw_slf);
|
||||
::std::result::Result::Ok(_raw_slf)
|
||||
},
|
||||
}
|
||||
|
@ -821,16 +821,16 @@ impl SlotDef {
|
|||
return_mode.as_ref(),
|
||||
)?;
|
||||
Ok(quote!({
|
||||
unsafe extern "C" fn __wrap(_raw_slf: *mut ::pyo3::ffi::PyObject, #(#method_arguments),*) -> #ret_ty {
|
||||
unsafe extern "C" fn __wrap(_raw_slf: *mut _pyo3::ffi::PyObject, #(#method_arguments),*) -> #ret_ty {
|
||||
let _slf = _raw_slf;
|
||||
#before_call_method
|
||||
::pyo3::callback::handle_panic(|#py| {
|
||||
_pyo3::callback::handle_panic(|#py| {
|
||||
#body
|
||||
})
|
||||
}
|
||||
::pyo3::ffi::PyType_Slot {
|
||||
slot: ::pyo3::ffi::#slot,
|
||||
pfunc: __wrap as ::pyo3::ffi::#func_ty as _
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::#slot,
|
||||
pfunc: __wrap as _pyo3::ffi::#func_ty as _
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
@ -858,7 +858,7 @@ fn generate_method_body(
|
|||
let rust_name = spec.name;
|
||||
let (arg_idents, conversions) =
|
||||
extract_proto_arguments(cls, py, &spec.args, arguments, extract_error_mode)?;
|
||||
let call = quote! { ::pyo3::callback::convert(#py, #cls::#rust_name(_slf, #(#arg_idents),*)) };
|
||||
let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(_slf, #(#arg_idents),*)) };
|
||||
let body = if let Some(return_mode) = return_mode {
|
||||
return_mode.return_call_output(py, call)
|
||||
} else {
|
||||
|
@ -912,15 +912,15 @@ impl SlotFragmentDef {
|
|||
let body = generate_method_body(cls, spec, &py, arguments, *extract_error_mode, None)?;
|
||||
let ret_ty = ret_ty.ffi_type();
|
||||
Ok(quote! {
|
||||
impl ::pyo3::class::impl_::#fragment_trait<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
impl _pyo3::class::impl_::#fragment_trait<#cls> for _pyo3::class::impl_::PyClassImplCollector<#cls> {
|
||||
|
||||
#[inline]
|
||||
unsafe fn #method(
|
||||
self,
|
||||
#py: ::pyo3::Python,
|
||||
_raw_slf: *mut ::pyo3::ffi::PyObject,
|
||||
#py: _pyo3::Python,
|
||||
_raw_slf: *mut _pyo3::ffi::PyObject,
|
||||
#(#method_arguments),*
|
||||
) -> ::pyo3::PyResult<#ret_ty> {
|
||||
) -> _pyo3::PyResult<#ret_ty> {
|
||||
let _slf = _raw_slf;
|
||||
#body
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ fn impl_proto_impl(
|
|||
|
||||
let flags = if m.can_coexist {
|
||||
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
|
||||
Some(quote!(::pyo3::ffi::METH_COEXIST))
|
||||
Some(quote!(_pyo3::ffi::METH_COEXIST))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -86,10 +86,14 @@ fn impl_proto_impl(
|
|||
}
|
||||
let normal_methods = impl_normal_methods(py_methods, ty, proto);
|
||||
let protocol_methods = impl_proto_methods(method_names, ty, proto);
|
||||
|
||||
Ok(quote! {
|
||||
#trait_impls
|
||||
#normal_methods
|
||||
#protocol_methods
|
||||
const _: () = {
|
||||
use ::pyo3 as _pyo3; // pyproto doesn't support specifying #[pyo3(crate)]
|
||||
#trait_impls
|
||||
#normal_methods
|
||||
#protocol_methods
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -105,11 +109,11 @@ fn impl_normal_methods(
|
|||
let methods_trait = proto.methods_trait();
|
||||
let methods_trait_methods = proto.methods_trait_methods();
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::#methods_trait<#ty>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
impl _pyo3::class::impl_::#methods_trait<#ty>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
{
|
||||
fn #methods_trait_methods(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[::pyo3::class::methods::PyMethodDefType] =
|
||||
fn #methods_trait_methods(self) -> &'static [_pyo3::class::methods::PyMethodDefType] {
|
||||
static METHODS: &[_pyo3::class::methods::PyMethodDefType] =
|
||||
&[#(#py_methods),*];
|
||||
METHODS
|
||||
}
|
||||
|
@ -138,16 +142,16 @@ fn impl_proto_methods(
|
|||
|
||||
if build_config.version <= PY39 && proto.name == "Buffer" {
|
||||
maybe_buffer_methods = Some(quote! {
|
||||
impl ::pyo3::class::impl_::PyBufferProtocolProcs<#ty>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
impl _pyo3::class::impl_::PyBufferProtocolProcs<#ty>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
{
|
||||
fn buffer_procs(
|
||||
self
|
||||
) -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
|
||||
static PROCS: ::pyo3::class::impl_::PyBufferProcs
|
||||
= ::pyo3::class::impl_::PyBufferProcs {
|
||||
bf_getbuffer: ::std::option::Option::Some(::pyo3::class::buffer::getbuffer::<#ty>),
|
||||
bf_releasebuffer: ::std::option::Option::Some(::pyo3::class::buffer::releasebuffer::<#ty>),
|
||||
) -> ::std::option::Option<&'static _pyo3::class::impl_::PyBufferProcs> {
|
||||
static PROCS: _pyo3::class::impl_::PyBufferProcs
|
||||
= _pyo3::class::impl_::PyBufferProcs {
|
||||
bf_getbuffer: ::std::option::Option::Some(_pyo3::class::buffer::getbuffer::<#ty>),
|
||||
bf_releasebuffer: ::std::option::Option::Some(_pyo3::class::buffer::releasebuffer::<#ty>),
|
||||
};
|
||||
::std::option::Option::Some(&PROCS)
|
||||
}
|
||||
|
@ -161,8 +165,8 @@ fn impl_proto_methods(
|
|||
let slot = syn::Ident::new(def.slot, Span::call_site());
|
||||
let slot_impl = syn::Ident::new(def.slot_impl, Span::call_site());
|
||||
quote! {{
|
||||
::pyo3::ffi::PyType_Slot {
|
||||
slot: ::pyo3::ffi::#slot,
|
||||
_pyo3::ffi::PyType_Slot {
|
||||
slot: _pyo3::ffi::#slot,
|
||||
pfunc: #module::#slot_impl::<#ty> as _
|
||||
}
|
||||
}}
|
||||
|
@ -176,10 +180,10 @@ fn impl_proto_methods(
|
|||
quote! {
|
||||
#maybe_buffer_methods
|
||||
|
||||
impl ::pyo3::class::impl_::#slots_trait<#ty>
|
||||
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
impl _pyo3::class::impl_::#slots_trait<#ty>
|
||||
for _pyo3::class::impl_::PyClassImplCollector<#ty>
|
||||
{
|
||||
fn #slots_trait_slots(self) -> &'static [::pyo3::ffi::PyType_Slot] {
|
||||
fn #slots_trait_slots(self) -> &'static [_pyo3::ffi::PyType_Slot] {
|
||||
&[#(#tokens),*]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use proc_macro2::{Span, TokenStream};
|
|||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
use crate::attributes::TextSignatureAttribute;
|
||||
use crate::attributes::{CrateAttribute, TextSignatureAttribute};
|
||||
|
||||
/// Macro inspired by `anyhow::anyhow!` to create a compiler error with the given span.
|
||||
macro_rules! err_spanned {
|
||||
|
@ -189,3 +189,10 @@ pub(crate) fn replace_self(ty: &mut syn::Type, cls: &syn::Type) {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the path to the pyo3 crate, or use the default (`::pyo3`).
|
||||
pub(crate) fn get_pyo3_crate(attr: &Option<CrateAttribute>) -> syn::Path {
|
||||
attr.as_ref()
|
||||
.map(|p| p.0.clone())
|
||||
.unwrap_or_else(|| syn::parse_str("::pyo3").unwrap())
|
||||
}
|
||||
|
|
|
@ -216,16 +216,16 @@ fn pyclass_impl(
|
|||
}
|
||||
|
||||
fn pyclass_enum_impl(
|
||||
attr: TokenStream,
|
||||
enum_: syn::ItemEnum,
|
||||
attrs: TokenStream,
|
||||
mut ast: syn::ItemEnum,
|
||||
methods_type: PyClassMethodsType,
|
||||
) -> TokenStream {
|
||||
let args = parse_macro_input!(attr with PyClassArgs::parse_enum_args);
|
||||
let args = parse_macro_input!(attrs with PyClassArgs::parse_enum_args);
|
||||
let expanded =
|
||||
build_py_enum(&enum_, args, methods_type).unwrap_or_else(|e| e.into_compile_error());
|
||||
build_py_enum(&mut ast, &args, methods_type).unwrap_or_else(|e| e.into_compile_error());
|
||||
|
||||
quote!(
|
||||
#enum_
|
||||
#ast
|
||||
#expanded
|
||||
)
|
||||
.into()
|
||||
|
|
|
@ -183,6 +183,7 @@ macro_rules! define_pyclass_setattr_slot {
|
|||
}
|
||||
}};
|
||||
}
|
||||
pub use $generate_macro;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -292,6 +293,7 @@ macro_rules! define_pyclass_binary_operator_slot {
|
|||
}
|
||||
}};
|
||||
}
|
||||
pub use $generate_macro;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -484,6 +486,7 @@ macro_rules! generate_pyclass_pow_slot {
|
|||
}
|
||||
}};
|
||||
}
|
||||
pub use generate_pyclass_pow_slot;
|
||||
|
||||
pub trait PyClassAllocImpl<T> {
|
||||
fn alloc_impl(self) -> Option<ffi::allocfunc>;
|
||||
|
|
|
@ -360,6 +360,11 @@ pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, pyproto, FromPyO
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
/// Test macro hygiene - this is in the crate since we won't have
|
||||
/// `pyo3` available in the crate root.
|
||||
#[cfg(all(test, feature = "macros"))]
|
||||
mod test_hygiene;
|
||||
|
||||
/// Test readme and user guide
|
||||
#[cfg(doctest)]
|
||||
pub mod doc_test {
|
||||
|
|
29
src/test_hygiene/misc.rs
Normal file
29
src/test_hygiene/misc.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
#![no_implicit_prelude]
|
||||
|
||||
#[derive(crate::FromPyObject)]
|
||||
#[pyo3(crate = "crate")]
|
||||
struct Derive1(i32); // newtype case
|
||||
|
||||
#[derive(crate::FromPyObject)]
|
||||
#[pyo3(crate = "crate")]
|
||||
#[allow(dead_code)]
|
||||
struct Derive2(i32, i32); // tuple case
|
||||
|
||||
#[derive(crate::FromPyObject)]
|
||||
#[pyo3(crate = "crate")]
|
||||
#[allow(dead_code)]
|
||||
struct Derive3 {
|
||||
f: i32,
|
||||
g: i32,
|
||||
} // struct case
|
||||
|
||||
#[derive(crate::FromPyObject)]
|
||||
#[pyo3(crate = "crate")]
|
||||
#[allow(dead_code)]
|
||||
enum Derive4 {
|
||||
A(i32),
|
||||
B { f: i32 },
|
||||
} // enum case
|
||||
|
||||
crate::create_exception!(mymodule, CustomError, crate::exceptions::PyException);
|
||||
crate::import_exception!(socket, gaierror);
|
5
src/test_hygiene/mod.rs
Normal file
5
src/test_hygiene/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod misc;
|
||||
mod pyclass;
|
||||
mod pyfunction;
|
||||
mod pymethods;
|
||||
mod pymodule;
|
|
@ -1,27 +1,30 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
#[crate::pyclass]
|
||||
#[pyo3(crate = "crate")]
|
||||
#[derive(::std::clone::Clone)]
|
||||
pub struct Foo;
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
#[crate::pyclass]
|
||||
#[pyo3(crate = "crate")]
|
||||
pub struct Foo2;
|
||||
|
||||
#[::pyo3::pyclass(
|
||||
#[crate::pyclass(
|
||||
name = "ActuallyBar",
|
||||
freelist = 8,
|
||||
weakref,
|
||||
unsendable,
|
||||
subclass,
|
||||
extends = ::pyo3::types::PyAny,
|
||||
extends = crate::types::PyAny,
|
||||
module = "Spam"
|
||||
)]
|
||||
#[pyo3(crate = "crate")]
|
||||
pub struct Bar {
|
||||
#[pyo3(get, set)]
|
||||
a: u8,
|
||||
#[pyo3(get, set)]
|
||||
b: Foo,
|
||||
#[pyo3(get, set)]
|
||||
c: ::std::option::Option<::pyo3::Py<Foo2>>,
|
||||
c: ::std::option::Option<crate::Py<Foo2>>,
|
||||
}
|
16
src/test_hygiene/pyfunction.rs
Normal file
16
src/test_hygiene/pyfunction.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[crate::pyfunction]
|
||||
#[pyo3(crate = "crate")]
|
||||
fn do_something(x: i32) -> crate::PyResult<i32> {
|
||||
::std::result::Result::Ok(x)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invoke_wrap_pyfunction() {
|
||||
crate::Python::with_gil(|py| {
|
||||
let func = crate::wrap_pyfunction!(do_something)(py).unwrap();
|
||||
crate::py_run!(py, func, r#"func(5)"#);
|
||||
});
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
#[crate::pyclass]
|
||||
#[pyo3(crate = "crate")]
|
||||
pub struct Dummy;
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
#[crate::pyclass]
|
||||
#[pyo3(crate = "crate")]
|
||||
pub struct DummyIter;
|
||||
|
||||
#[::pyo3::pymethods]
|
||||
#[crate::pymethods]
|
||||
#[pyo3(crate = "crate")]
|
||||
impl Dummy {
|
||||
//////////////////////
|
||||
// Basic customization
|
||||
|
@ -20,8 +23,8 @@ impl Dummy {
|
|||
"Dummy"
|
||||
}
|
||||
|
||||
fn __bytes__<'py>(&self, py: ::pyo3::Python<'py>) -> &'py ::pyo3::types::PyBytes {
|
||||
::pyo3::types::PyBytes::new(py, &[0])
|
||||
fn __bytes__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyBytes {
|
||||
crate::types::PyBytes::new(py, &[0])
|
||||
}
|
||||
|
||||
fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String {
|
||||
|
@ -60,11 +63,11 @@ impl Dummy {
|
|||
// Customizing attribute access
|
||||
//////////////////////
|
||||
|
||||
fn __getattr__(&self, name: ::std::string::String) -> &::pyo3::PyAny {
|
||||
fn __getattr__(&self, name: ::std::string::String) -> &crate::PyAny {
|
||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||
}
|
||||
|
||||
fn __getattribute__(&self, name: ::std::string::String) -> &::pyo3::PyAny {
|
||||
fn __getattribute__(&self, name: ::std::string::String) -> &crate::PyAny {
|
||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||
}
|
||||
|
||||
|
@ -72,8 +75,8 @@ impl Dummy {
|
|||
|
||||
fn __delattr__(&mut self, name: ::std::string::String) {}
|
||||
|
||||
fn __dir__<'py>(&self, py: ::pyo3::Python<'py>) -> &'py ::pyo3::types::PyList {
|
||||
::pyo3::types::PyList::new(py, ::std::vec![0_u8])
|
||||
fn __dir__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyList {
|
||||
crate::types::PyList::new(py, ::std::vec![0_u8])
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
@ -82,17 +85,17 @@ impl Dummy {
|
|||
|
||||
fn __get__(
|
||||
&self,
|
||||
instance: &::pyo3::PyAny,
|
||||
owner: &::pyo3::PyAny,
|
||||
) -> ::pyo3::PyResult<&::pyo3::PyAny> {
|
||||
instance: &crate::PyAny,
|
||||
owner: &crate::PyAny,
|
||||
) -> crate::PyResult<&crate::PyAny> {
|
||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||
}
|
||||
|
||||
fn __set__(&self, instance: &::pyo3::PyAny, owner: &::pyo3::PyAny) {}
|
||||
fn __set__(&self, instance: &crate::PyAny, owner: &crate::PyAny) {}
|
||||
|
||||
fn __delete__(&self, instance: &::pyo3::PyAny) {}
|
||||
fn __delete__(&self, instance: &crate::PyAny) {}
|
||||
|
||||
fn __set_name__(&self, owner: &::pyo3::PyAny, name: &::pyo3::PyAny) {}
|
||||
fn __set_name__(&self, owner: &crate::PyAny, name: &crate::PyAny) {}
|
||||
|
||||
//////////////////////
|
||||
// Implementing Descriptors
|
||||
|
@ -102,24 +105,24 @@ impl Dummy {
|
|||
0
|
||||
}
|
||||
|
||||
fn __getitem__(&self, key: u32) -> ::pyo3::PyResult<u32> {
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyKeyError::new_err("boo"))
|
||||
fn __getitem__(&self, key: u32) -> crate::PyResult<u32> {
|
||||
::std::result::Result::Err(crate::exceptions::PyKeyError::new_err("boo"))
|
||||
}
|
||||
|
||||
fn __setitem__(&self, key: u32, value: u32) {}
|
||||
|
||||
fn __delitem__(&self, key: u32) {}
|
||||
|
||||
fn __iter__(_: ::pyo3::pycell::PyRef<Self>, py: ::pyo3::Python) -> ::pyo3::Py<DummyIter> {
|
||||
::pyo3::Py::new(py, DummyIter {}).unwrap()
|
||||
fn __iter__(_: crate::pycell::PyRef<Self>, py: crate::Python) -> crate::Py<DummyIter> {
|
||||
crate::Py::new(py, DummyIter {}).unwrap()
|
||||
}
|
||||
|
||||
fn __next__(&mut self) -> ::std::option::Option<()> {
|
||||
::std::option::Option::None
|
||||
}
|
||||
|
||||
fn __reversed__(slf: ::pyo3::pycell::PyRef<Self>, py: ::pyo3::Python) -> ::pyo3::Py<DummyIter> {
|
||||
::pyo3::Py::new(py, DummyIter {}).unwrap()
|
||||
fn __reversed__(slf: crate::pycell::PyRef<Self>, py: crate::Python) -> crate::Py<DummyIter> {
|
||||
crate::Py::new(py, DummyIter {}).unwrap()
|
||||
}
|
||||
|
||||
fn __contains__(&self, item: u32) -> bool {
|
||||
|
@ -142,12 +145,12 @@ impl Dummy {
|
|||
Dummy {}
|
||||
}
|
||||
|
||||
fn __truediv__(&self, _other: &Self) -> ::pyo3::PyResult<()> {
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
fn __truediv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||
::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
}
|
||||
|
||||
fn __floordiv__(&self, _other: &Self) -> ::pyo3::PyResult<()> {
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
fn __floordiv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||
::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
}
|
||||
|
||||
fn __mod__(&self, _other: &Self) -> u32 {
|
||||
|
@ -194,12 +197,12 @@ impl Dummy {
|
|||
Dummy {}
|
||||
}
|
||||
|
||||
fn __rtruediv__(&self, _other: &Self) -> ::pyo3::PyResult<()> {
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
fn __rtruediv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||
::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
}
|
||||
|
||||
fn __rfloordiv__(&self, _other: &Self) -> ::pyo3::PyResult<()> {
|
||||
::std::result::Result::Err(::pyo3::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
fn __rfloordiv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||
::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo"))
|
||||
}
|
||||
|
||||
fn __rmod__(&self, _other: &Self) -> u32 {
|
||||
|
@ -258,24 +261,24 @@ impl Dummy {
|
|||
|
||||
fn __ior__(&mut self, other: &Self) {}
|
||||
|
||||
fn __neg__(slf: ::pyo3::pycell::PyRef<Self>) -> ::pyo3::pycell::PyRef<Self> {
|
||||
fn __neg__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
fn __pos__(slf: ::pyo3::pycell::PyRef<Self>) -> ::pyo3::pycell::PyRef<Self> {
|
||||
fn __pos__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
fn __abs__(slf: ::pyo3::pycell::PyRef<Self>) -> ::pyo3::pycell::PyRef<Self> {
|
||||
fn __abs__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
fn __invert__(slf: ::pyo3::pycell::PyRef<Self>) -> ::pyo3::pycell::PyRef<Self> {
|
||||
fn __invert__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
fn __complex__<'py>(&self, py: ::pyo3::Python<'py>) -> &'py ::pyo3::types::PyComplex {
|
||||
::pyo3::types::PyComplex::from_doubles(py, 0.0, 0.0)
|
||||
fn __complex__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyComplex {
|
||||
crate::types::PyComplex::from_doubles(py, 0.0, 0.0)
|
||||
}
|
||||
|
||||
fn __int__(&self) -> u32 {
|
||||
|
@ -314,9 +317,9 @@ impl Dummy {
|
|||
|
||||
fn __exit__(
|
||||
&mut self,
|
||||
exc_type: &::pyo3::PyAny,
|
||||
exc_value: &::pyo3::PyAny,
|
||||
traceback: &::pyo3::PyAny,
|
||||
exc_type: &crate::PyAny,
|
||||
exc_value: &crate::PyAny,
|
||||
traceback: &crate::PyAny,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -324,7 +327,7 @@ impl Dummy {
|
|||
// Awaitable Objects
|
||||
//////////////////////
|
||||
|
||||
fn __await__(slf: ::pyo3::pycell::PyRef<Self>) -> ::pyo3::pycell::PyRef<Self> {
|
||||
fn __await__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
|
@ -333,8 +336,8 @@ impl Dummy {
|
|||
// Asynchronous Iterators
|
||||
//////////////////////
|
||||
|
||||
fn __aiter__(slf: ::pyo3::pycell::PyRef<Self>, py: ::pyo3::Python) -> ::pyo3::Py<DummyIter> {
|
||||
::pyo3::Py::new(py, DummyIter {}).unwrap()
|
||||
fn __aiter__(slf: crate::pycell::PyRef<Self>, py: crate::Python) -> crate::Py<DummyIter> {
|
||||
crate::Py::new(py, DummyIter {}).unwrap()
|
||||
}
|
||||
|
||||
fn __anext__(&mut self) -> ::std::option::Option<()> {
|
||||
|
@ -349,9 +352,9 @@ impl Dummy {
|
|||
|
||||
fn __aexit__(
|
||||
&mut self,
|
||||
exc_type: &::pyo3::PyAny,
|
||||
exc_value: &::pyo3::PyAny,
|
||||
traceback: &::pyo3::PyAny,
|
||||
exc_type: &crate::PyAny,
|
||||
exc_value: &crate::PyAny,
|
||||
traceback: &crate::PyAny,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -362,13 +365,13 @@ impl Dummy {
|
|||
#[staticmethod]
|
||||
fn staticmethod() {}
|
||||
#[classmethod]
|
||||
fn clsmethod(_: &::pyo3::types::PyType) {}
|
||||
fn clsmethod(_: &crate::types::PyType) {}
|
||||
#[args(args = "*", kwds = "**")]
|
||||
fn __call__(
|
||||
&self,
|
||||
_args: &::pyo3::types::PyTuple,
|
||||
_kwds: ::std::option::Option<&::pyo3::types::PyDict>,
|
||||
) -> ::pyo3::PyResult<i32> {
|
||||
_args: &crate::types::PyTuple,
|
||||
_kwds: ::std::option::Option<&crate::types::PyDict>,
|
||||
) -> crate::PyResult<i32> {
|
||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||
}
|
||||
#[new]
|
||||
|
@ -391,8 +394,8 @@ impl Dummy {
|
|||
fn __richcmp__(
|
||||
&self,
|
||||
other: &Self,
|
||||
op: ::pyo3::class::basic::CompareOp,
|
||||
) -> ::pyo3::PyResult<bool> {
|
||||
op: crate::class::basic::CompareOp,
|
||||
) -> crate::PyResult<bool> {
|
||||
::std::result::Result::Ok(false)
|
||||
}
|
||||
// PyGcProtocol
|
23
src/test_hygiene/pymodule.rs
Normal file
23
src/test_hygiene/pymodule.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[crate::pyfunction]
|
||||
#[pyo3(crate = "crate")]
|
||||
fn do_something(x: i32) -> crate::PyResult<i32> {
|
||||
::std::result::Result::Ok(x)
|
||||
}
|
||||
|
||||
#[crate::pymodule]
|
||||
#[pyo3(crate = "crate")]
|
||||
fn foo(_py: crate::Python, _m: &crate::types::PyModule) -> crate::PyResult<()> {
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
#[crate::pymodule]
|
||||
#[pyo3(crate = "crate")]
|
||||
fn my_module(_py: crate::Python, m: &crate::types::PyModule) -> crate::PyResult<()> {
|
||||
m.add_function(crate::wrap_pyfunction!(do_something, m)?)?;
|
||||
m.add_wrapped(crate::wrap_pymodule!(foo))?;
|
||||
|
||||
::std::result::Result::Ok(())
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#![no_implicit_prelude]
|
||||
|
||||
#[derive(::pyo3::FromPyObject)]
|
||||
struct Derive1(i32); // newtype case
|
||||
|
||||
#[derive(::pyo3::FromPyObject)]
|
||||
#[allow(dead_code)]
|
||||
struct Derive2(i32, i32); // tuple case
|
||||
|
||||
#[derive(::pyo3::FromPyObject)]
|
||||
#[allow(dead_code)]
|
||||
struct Derive3 {
|
||||
f: i32,
|
||||
g: i32,
|
||||
} // struct case
|
||||
|
||||
#[derive(::pyo3::FromPyObject)]
|
||||
#[allow(dead_code)]
|
||||
enum Derive4 {
|
||||
A(i32),
|
||||
B { f: i32 },
|
||||
} // enum case
|
||||
|
||||
::pyo3::create_exception!(mymodule, CustomError, ::pyo3::exceptions::PyException);
|
||||
::pyo3::import_exception!(socket, gaierror);
|
|
@ -1,15 +0,0 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[::pyo3::pyfunction]
|
||||
fn do_something(x: i32) -> ::pyo3::PyResult<i32> {
|
||||
::std::result::Result::Ok(x)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invoke_wrap_pyfunction() {
|
||||
::pyo3::Python::with_gil(|py| {
|
||||
let func = ::pyo3::wrap_pyfunction!(do_something)(py).unwrap();
|
||||
::pyo3::py_run!(py, func, r#"func(5)"#);
|
||||
});
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[::pyo3::pyfunction]
|
||||
fn do_something(x: i32) -> ::pyo3::PyResult<i32> {
|
||||
::std::result::Result::Ok(x)
|
||||
}
|
||||
|
||||
#[::pyo3::pymodule]
|
||||
fn foo(_py: ::pyo3::Python, _m: &::pyo3::types::PyModule) -> ::pyo3::PyResult<()> {
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
#[::pyo3::pymodule]
|
||||
fn my_module(_py: ::pyo3::Python, m: &::pyo3::types::PyModule) -> ::pyo3::PyResult<()> {
|
||||
m.add_function(::pyo3::wrap_pyfunction!(do_something, m)?)?;
|
||||
m.add_wrapped(::pyo3::wrap_pymodule!(foo))?;
|
||||
|
||||
::std::result::Result::Ok(())
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
#![no_implicit_prelude]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
#[derive(::std::clone::Clone)]
|
||||
pub struct Foo;
|
||||
|
||||
#[::pyo3::pyclass]
|
||||
pub struct Foo2;
|
||||
|
||||
#[::pyo3::pyclass(
|
||||
name = "ActuallyBar",
|
||||
freelist = 8,
|
||||
weakref,
|
||||
unsendable,
|
||||
gc,
|
||||
subclass,
|
||||
extends = ::pyo3::types::PyAny,
|
||||
module = "Spam"
|
||||
)]
|
||||
pub struct Bar {
|
||||
#[pyo3(get, set)]
|
||||
a: u8,
|
||||
#[pyo3(get, set)]
|
||||
b: Foo,
|
||||
#[pyo3(get, set)]
|
||||
c: ::std::option::Option<::pyo3::Py<Foo2>>,
|
||||
}
|
||||
|
||||
#[::pyo3::pyproto]
|
||||
impl ::pyo3::class::gc::PyGCProtocol for Bar {
|
||||
fn __traverse__(
|
||||
&self,
|
||||
visit: ::pyo3::class::gc::PyVisit,
|
||||
) -> ::std::result::Result<(), ::pyo3::class::gc::PyTraverseError> {
|
||||
if let ::std::option::Option::Some(obj) = &self.c {
|
||||
visit.call(obj)?
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn __clear__(&mut self) {
|
||||
self.c = ::std::option::Option::None;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
#[::pyo3::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) {}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#![cfg(feature = "macros")]
|
||||
|
||||
mod hygiene {
|
||||
mod misc;
|
||||
mod pyclass;
|
||||
mod pyfunction;
|
||||
mod pymethods;
|
||||
mod pymodule;
|
||||
mod pyproto;
|
||||
}
|
|
@ -132,7 +132,7 @@ error: only one of `attribute` or `item` can be provided
|
|||
118 | #[pyo3(item, attribute)]
|
||||
| ^
|
||||
|
||||
error: expected `transparent` or `annotation`
|
||||
error: expected one of: `transparent`, `annotation`, `crate`
|
||||
--> tests/ui/invalid_frompy_derive.rs:123:8
|
||||
|
|
||||
123 | #[pyo3(unknown = "should not work")]
|
||||
|
|
Loading…
Reference in a new issue