Merge pull request #2083 from aviramha/magic_methods
verify py method args count
This commit is contained in:
commit
2cee7feaaf
|
@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Expose `pyo3-build-config` APIs for cross-compiling and Python configuration discovery for use in other projects. [#1996](https://github.com/PyO3/pyo3/pull/1996)
|
- Expose `pyo3-build-config` APIs for cross-compiling and Python configuration discovery for use in other projects. [#1996](https://github.com/PyO3/pyo3/pull/1996)
|
||||||
- Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067)
|
- Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067)
|
||||||
- Accept paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081)
|
- Accept paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081)
|
||||||
|
- Add check for correct number of arguments on magic methods. [#2083](https://github.com/PyO3/pyo3/pull/2083)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -46,6 +47,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074)
|
- internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074)
|
||||||
- `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085)
|
- `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085)
|
||||||
- `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081)
|
- `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081)
|
||||||
|
- `__ipow__` now supports modulo argument on Python 3.8+. [#2083](https://github.com/PyO3/pyo3/pull/2083)
|
||||||
|
- `pyo3-macros-backend` is now compiled with PyO3 cfgs to enable different magic method definitions based on version. [#2083](https://github.com/PyO3/pyo3/pull/2083)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
|
@ -289,13 +289,15 @@ This trait also has support the augmented arithmetic assignments (`+=`, `-=`,
|
||||||
* `fn __itruediv__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __itruediv__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __ifloordiv__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __ifloordiv__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __imod__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __imod__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __ipow__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __ipow__(&'p mut self, other: impl FromPyObject, modulo: impl FromPyObject) -> PyResult<()>` on Python 3.8^
|
||||||
|
* `fn __ipow__(&'p mut self, other: impl FromPyObject) -> PyResult<()>` on Python 3.7 see https://bugs.python.org/issue36379
|
||||||
* `fn __ilshift__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __ilshift__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __irshift__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __irshift__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __iand__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __iand__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __ior__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __ior__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
* `fn __ixor__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
* `fn __ixor__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||||
|
|
||||||
|
|
||||||
The following methods implement the unary arithmetic operations (`-`, `+`, `abs()` and `~`):
|
The following methods implement the unary arithmetic operations (`-`, `+`, `abs()` and `~`):
|
||||||
|
|
||||||
* `fn __neg__(&'p self) -> PyResult<impl ToPyObject>`
|
* `fn __neg__(&'p self) -> PyResult<impl ToPyObject>`
|
||||||
|
|
|
@ -421,7 +421,7 @@ pub const NUM: Proto = Proto {
|
||||||
.args(&["Other"])
|
.args(&["Other"])
|
||||||
.has_self(),
|
.has_self(),
|
||||||
MethodProto::new("__ipow__", "PyNumberIPowProtocol")
|
MethodProto::new("__ipow__", "PyNumberIPowProtocol")
|
||||||
.args(&["Other"])
|
.args(&["Other", "Modulo"])
|
||||||
.has_self(),
|
.has_self(),
|
||||||
MethodProto::new("__ilshift__", "PyNumberILShiftProtocol")
|
MethodProto::new("__ilshift__", "PyNumberILShiftProtocol")
|
||||||
.args(&["Other"])
|
.args(&["Other"])
|
||||||
|
|
|
@ -532,8 +532,8 @@ const __IMOD__: SlotDef = SlotDef::new("Py_nb_inplace_remainder", "binaryfunc")
|
||||||
.arguments(&[Ty::Object])
|
.arguments(&[Ty::Object])
|
||||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ternaryfunc")
|
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ipowfunc")
|
||||||
.arguments(&[Ty::Object, Ty::Object])
|
.arguments(&[Ty::Object, Ty::IPowModulo])
|
||||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||||
.return_self();
|
.return_self();
|
||||||
const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc")
|
const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc")
|
||||||
|
@ -613,6 +613,7 @@ enum Ty {
|
||||||
Object,
|
Object,
|
||||||
MaybeNullObject,
|
MaybeNullObject,
|
||||||
NonNullObject,
|
NonNullObject,
|
||||||
|
IPowModulo,
|
||||||
CompareOp,
|
CompareOp,
|
||||||
Int,
|
Int,
|
||||||
PyHashT,
|
PyHashT,
|
||||||
|
@ -626,6 +627,7 @@ impl Ty {
|
||||||
match self {
|
match self {
|
||||||
Ty::Object | Ty::MaybeNullObject => quote! { *mut _pyo3::ffi::PyObject },
|
Ty::Object | Ty::MaybeNullObject => quote! { *mut _pyo3::ffi::PyObject },
|
||||||
Ty::NonNullObject => quote! { ::std::ptr::NonNull<_pyo3::ffi::PyObject> },
|
Ty::NonNullObject => quote! { ::std::ptr::NonNull<_pyo3::ffi::PyObject> },
|
||||||
|
Ty::IPowModulo => quote! { _pyo3::impl_::pymethods::IPowModulo },
|
||||||
Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int },
|
Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int },
|
||||||
Ty::PyHashT => quote! { _pyo3::ffi::Py_hash_t },
|
Ty::PyHashT => quote! { _pyo3::ffi::Py_hash_t },
|
||||||
Ty::PySsizeT => quote! { _pyo3::ffi::Py_ssize_t },
|
Ty::PySsizeT => quote! { _pyo3::ffi::Py_ssize_t },
|
||||||
|
@ -679,6 +681,16 @@ impl Ty {
|
||||||
);
|
);
|
||||||
extract_object(cls, arg.ty, ident, extract)
|
extract_object(cls, arg.ty, ident, extract)
|
||||||
}
|
}
|
||||||
|
Ty::IPowModulo => {
|
||||||
|
let extract = handle_error(
|
||||||
|
extract_error_mode,
|
||||||
|
py,
|
||||||
|
quote! {
|
||||||
|
#ident.extract(#py)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
extract_object(cls, arg.ty, ident, extract)
|
||||||
|
}
|
||||||
Ty::CompareOp => {
|
Ty::CompareOp => {
|
||||||
let extract = handle_error(
|
let extract = handle_error(
|
||||||
extract_error_mode,
|
extract_error_mode,
|
||||||
|
@ -888,8 +900,11 @@ fn generate_method_body(
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode);
|
let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode);
|
||||||
let rust_name = spec.name;
|
let rust_name = spec.name;
|
||||||
let (arg_idents, conversions) =
|
let (arg_idents, arg_count, conversions) =
|
||||||
extract_proto_arguments(cls, py, &spec.args, arguments, extract_error_mode)?;
|
extract_proto_arguments(cls, py, &spec.args, arguments, extract_error_mode)?;
|
||||||
|
if arg_count != arguments.len() {
|
||||||
|
bail_spanned!(spec.name.span() => format!("Expected {} arguments, got {}", arguments.len(), arg_count));
|
||||||
|
}
|
||||||
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 {
|
let body = if let Some(return_mode) = return_mode {
|
||||||
return_mode.return_call_output(py, call)
|
return_mode.return_call_output(py, call)
|
||||||
|
@ -1058,7 +1073,7 @@ fn extract_proto_arguments(
|
||||||
method_args: &[FnArg],
|
method_args: &[FnArg],
|
||||||
proto_args: &[Ty],
|
proto_args: &[Ty],
|
||||||
extract_error_mode: ExtractErrorMode,
|
extract_error_mode: ExtractErrorMode,
|
||||||
) -> Result<(Vec<Ident>, TokenStream)> {
|
) -> Result<(Vec<Ident>, usize, TokenStream)> {
|
||||||
let mut arg_idents = Vec::with_capacity(method_args.len());
|
let mut arg_idents = Vec::with_capacity(method_args.len());
|
||||||
let mut non_python_args = 0;
|
let mut non_python_args = 0;
|
||||||
|
|
||||||
|
@ -1077,9 +1092,8 @@ fn extract_proto_arguments(
|
||||||
arg_idents.push(ident);
|
arg_idents.push(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let conversions = quote!(#(#args_conversions)*);
|
let conversions = quote!(#(#args_conversions)*);
|
||||||
Ok((arg_idents, conversions))
|
Ok((arg_idents, non_python_args, conversions))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StaticIdent(&'static str);
|
struct StaticIdent(&'static str);
|
||||||
|
|
|
@ -221,7 +221,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result
|
fn __ipow__(&'p mut self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result
|
||||||
where
|
where
|
||||||
Self: PyNumberIPowProtocol<'p>,
|
Self: PyNumberIPowProtocol<'p>,
|
||||||
{
|
{
|
||||||
|
@ -504,6 +504,8 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
|
||||||
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
|
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
|
||||||
type Other: FromPyObject<'p>;
|
type Other: FromPyObject<'p>;
|
||||||
type Result: IntoPyCallbackOutput<()>;
|
type Result: IntoPyCallbackOutput<()>;
|
||||||
|
// See https://bugs.python.org/issue36379
|
||||||
|
type Modulo: FromPyObject<'p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
@ -718,17 +720,28 @@ py_binary_self_func!(imod, PyNumberIModProtocol, T::__imod__);
|
||||||
pub unsafe extern "C" fn ipow<T>(
|
pub unsafe extern "C" fn ipow<T>(
|
||||||
slf: *mut ffi::PyObject,
|
slf: *mut ffi::PyObject,
|
||||||
other: *mut ffi::PyObject,
|
other: *mut ffi::PyObject,
|
||||||
_modulo: *mut ffi::PyObject,
|
modulo: crate::impl_::pymethods::IPowModulo,
|
||||||
) -> *mut ffi::PyObject
|
) -> *mut ffi::PyObject
|
||||||
where
|
where
|
||||||
T: for<'p> PyNumberIPowProtocol<'p>,
|
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||||
{
|
{
|
||||||
// NOTE: Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract,
|
|
||||||
// so we ignore it. It's the same as what CPython does.
|
|
||||||
crate::callback_body!(py, {
|
crate::callback_body!(py, {
|
||||||
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||||
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
||||||
call_operator_mut!(py, slf_cell, __ipow__, other).convert(py)?;
|
slf_cell
|
||||||
|
.try_borrow_mut()?
|
||||||
|
.__ipow__(
|
||||||
|
extract_or_return_not_implemented!(other),
|
||||||
|
match modulo.extract(py) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(_) => {
|
||||||
|
let res = crate::ffi::Py_NotImplemented();
|
||||||
|
crate::ffi::Py_INCREF(res);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.convert(py)?;
|
||||||
ffi::Py_INCREF(slf);
|
ffi::Py_INCREF(slf);
|
||||||
Ok::<_, PyErr>(slf)
|
Ok::<_, PyErr>(slf)
|
||||||
})
|
})
|
||||||
|
|
|
@ -204,3 +204,7 @@ mod cpython;
|
||||||
|
|
||||||
#[cfg(not(Py_LIMITED_API))]
|
#[cfg(not(Py_LIMITED_API))]
|
||||||
pub use self::cpython::*;
|
pub use self::cpython::*;
|
||||||
|
|
||||||
|
/// Helper to enable #\[pymethods\] to see the workaround for __ipow__ on Python 3.7
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::impl_::pymethods::ipowfunc;
|
||||||
|
|
|
@ -12,4 +12,6 @@ pub mod frompyobject;
|
||||||
pub(crate) mod not_send;
|
pub(crate) mod not_send;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod pyclass;
|
pub mod pyclass;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod pymethods;
|
||||||
pub mod pymodule;
|
pub mod pymodule;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
use crate::{ffi, FromPyObject, PyAny, PyResult, Python};
|
||||||
|
|
||||||
|
/// Python 3.8 and up - __ipow__ has modulo argument correctly populated.
|
||||||
|
#[cfg(Py_3_8)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct IPowModulo(*mut ffi::PyObject);
|
||||||
|
|
||||||
|
/// Python 3.7 and older - __ipow__ does not have modulo argument correctly populated.
|
||||||
|
#[cfg(not(Py_3_8))]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct IPowModulo(std::mem::MaybeUninit<*mut ffi::PyObject>);
|
||||||
|
|
||||||
|
/// Helper to use as pymethod ffi definition
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type ipowfunc = unsafe extern "C" fn(
|
||||||
|
arg1: *mut ffi::PyObject,
|
||||||
|
arg2: *mut ffi::PyObject,
|
||||||
|
arg3: IPowModulo,
|
||||||
|
) -> *mut ffi::PyObject;
|
||||||
|
|
||||||
|
impl IPowModulo {
|
||||||
|
#[cfg(Py_3_8)]
|
||||||
|
#[inline]
|
||||||
|
pub fn extract<'a, T: FromPyObject<'a>>(self, py: Python<'a>) -> PyResult<T> {
|
||||||
|
unsafe { py.from_borrowed_ptr::<PyAny>(self.0) }.extract()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(Py_3_8))]
|
||||||
|
#[inline]
|
||||||
|
pub fn extract<'a, T: FromPyObject<'a>>(self, py: Python<'a>) -> PyResult<T> {
|
||||||
|
unsafe { py.from_borrowed_ptr::<PyAny>(ffi::Py_None()) }.extract()
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ pub struct Dummy;
|
||||||
#[pyo3(crate = "crate")]
|
#[pyo3(crate = "crate")]
|
||||||
pub struct DummyIter;
|
pub struct DummyIter;
|
||||||
|
|
||||||
|
#[cfg(Py_3_8)]
|
||||||
#[crate::pymethods]
|
#[crate::pymethods]
|
||||||
#[pyo3(crate = "crate")]
|
#[pyo3(crate = "crate")]
|
||||||
impl Dummy {
|
impl Dummy {
|
||||||
|
@ -401,3 +402,396 @@ impl Dummy {
|
||||||
// PyGcProtocol
|
// PyGcProtocol
|
||||||
// Buffer protocol?
|
// Buffer protocol?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(Py_3_8))]
|
||||||
|
#[crate::pymethods]
|
||||||
|
#[pyo3(crate = "crate")]
|
||||||
|
impl Dummy {
|
||||||
|
//////////////////////
|
||||||
|
// Basic customization
|
||||||
|
//////////////////////
|
||||||
|
fn __repr__(&self) -> &'static str {
|
||||||
|
"Dummy"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __str__(&self) -> &'static str {
|
||||||
|
"Dummy"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __lt__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __le__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn __eq__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn __ne__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn __gt__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn __ge__(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __hash__(&self) -> u64 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __bool__(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Customizing attribute access
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
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) -> &crate::PyAny {
|
||||||
|
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {}
|
||||||
|
|
||||||
|
fn __delattr__(&mut self, name: ::std::string::String) {}
|
||||||
|
|
||||||
|
fn __dir__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyList {
|
||||||
|
crate::types::PyList::new(py, ::std::vec![0_u8])
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Implementing Descriptors
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __get__(
|
||||||
|
&self,
|
||||||
|
instance: &crate::PyAny,
|
||||||
|
owner: &crate::PyAny,
|
||||||
|
) -> crate::PyResult<&crate::PyAny> {
|
||||||
|
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __set__(&self, instance: &crate::PyAny, owner: &crate::PyAny) {}
|
||||||
|
|
||||||
|
fn __delete__(&self, instance: &crate::PyAny) {}
|
||||||
|
|
||||||
|
fn __set_name__(&self, owner: &crate::PyAny, name: &crate::PyAny) {}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Implementing Descriptors
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __len__(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
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__(_: 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: crate::pycell::PyRef<Self>, py: crate::Python) -> crate::Py<DummyIter> {
|
||||||
|
crate::Py::new(py, DummyIter {}).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __contains__(&self, item: u32) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Emulating numeric types
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __add__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __sub__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __mul__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __truediv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||||
|
::std::result::Result::Err(crate::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 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __divmod__(&self, _other: &Self) -> (u32, u32) {
|
||||||
|
(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __pow__(&self, _other: &Self, modulo: ::std::option::Option<i32>) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __lshift__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rshift__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __and__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __xor__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __or__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __radd__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rrsub__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rmul__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rtruediv__(&self, _other: &Self) -> crate::PyResult<()> {
|
||||||
|
::std::result::Result::Err(crate::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 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rdivmod__(&self, _other: &Self) -> (u32, u32) {
|
||||||
|
(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rpow__(&self, _other: &Self, modulo: ::std::option::Option<i32>) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rlshift__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rrshift__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rand__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __rxor__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __ror__(&self, other: &Self) -> Dummy {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __iadd__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __irsub__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __imul__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __itruediv__(&mut self, _other: &Self) {}
|
||||||
|
|
||||||
|
fn __ifloordiv__(&mut self, _other: &Self) {}
|
||||||
|
|
||||||
|
fn __imod__(&mut self, _other: &Self) {}
|
||||||
|
|
||||||
|
fn __ipow__(&mut self, _other: &Self, _modulo: ::std::option::Option<u32>) {}
|
||||||
|
fn __ilshift__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __irshift__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __iand__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __ixor__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __ior__(&mut self, other: &Self) {}
|
||||||
|
|
||||||
|
fn __neg__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __pos__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __abs__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __invert__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __float__(&self) -> f64 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __index__(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __round__(&self, ndigits: ::std::option::Option<u32>) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __trunc__(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __floor__(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __ceil__(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// With Statement Context Managers
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __enter__(&mut self) {}
|
||||||
|
|
||||||
|
fn __exit__(
|
||||||
|
&mut self,
|
||||||
|
exc_type: &crate::PyAny,
|
||||||
|
exc_value: &crate::PyAny,
|
||||||
|
traceback: &crate::PyAny,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Awaitable Objects
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __await__(slf: crate::pycell::PyRef<Self>) -> crate::pycell::PyRef<Self> {
|
||||||
|
slf
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
// Asynchronous Iterators
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
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<()> {
|
||||||
|
::std::option::Option::None
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Asynchronous Context Managers
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
fn __aenter__(&mut self) {}
|
||||||
|
|
||||||
|
fn __aexit__(
|
||||||
|
&mut self,
|
||||||
|
exc_type: &crate::PyAny,
|
||||||
|
exc_value: &crate::PyAny,
|
||||||
|
traceback: &crate::PyAny,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Things with attributes
|
||||||
|
|
||||||
|
#[args(x = "1", "*", _z = "2")]
|
||||||
|
fn test(&self, _y: &Dummy, _z: i32) {}
|
||||||
|
#[staticmethod]
|
||||||
|
fn staticmethod() {}
|
||||||
|
#[classmethod]
|
||||||
|
fn clsmethod(_: &crate::types::PyType) {}
|
||||||
|
#[args(args = "*", kwds = "**")]
|
||||||
|
fn __call__(
|
||||||
|
&self,
|
||||||
|
_args: &crate::types::PyTuple,
|
||||||
|
_kwds: ::std::option::Option<&crate::types::PyDict>,
|
||||||
|
) -> crate::PyResult<i32> {
|
||||||
|
::std::panic!("unimplemented isn't hygienic before 1.50")
|
||||||
|
}
|
||||||
|
#[new]
|
||||||
|
fn new(a: u8) -> Self {
|
||||||
|
Dummy {}
|
||||||
|
}
|
||||||
|
#[getter]
|
||||||
|
fn get(&self) -> i32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
#[setter]
|
||||||
|
fn set(&mut self, _v: i32) {}
|
||||||
|
#[classattr]
|
||||||
|
fn class_attr() -> i32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dunder methods invented for protocols
|
||||||
|
|
||||||
|
fn __richcmp__(
|
||||||
|
&self,
|
||||||
|
other: &Self,
|
||||||
|
op: crate::class::basic::CompareOp,
|
||||||
|
) -> crate::PyResult<bool> {
|
||||||
|
::std::result::Result::Ok(false)
|
||||||
|
}
|
||||||
|
// PyGcProtocol
|
||||||
|
// Buffer protocol?
|
||||||
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl InPlaceOperations {
|
||||||
self.value |= other;
|
self.value |= other;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __ipow__(&mut self, other: u32) {
|
fn __ipow__(&mut self, other: u32, _modulo: Option<u32>) {
|
||||||
self.value = self.value.pow(other);
|
self.value = self.value.pow(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,12 +566,12 @@ mod return_not_implemented {
|
||||||
fn __itruediv__(&mut self, _other: PyRef<Self>) {}
|
fn __itruediv__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __ifloordiv__(&mut self, _other: PyRef<Self>) {}
|
fn __ifloordiv__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __imod__(&mut self, _other: PyRef<Self>) {}
|
fn __imod__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __ipow__(&mut self, _other: PyRef<Self>) {}
|
|
||||||
fn __ilshift__(&mut self, _other: PyRef<Self>) {}
|
fn __ilshift__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __irshift__(&mut self, _other: PyRef<Self>) {}
|
fn __irshift__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __iand__(&mut self, _other: PyRef<Self>) {}
|
fn __iand__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __ior__(&mut self, _other: PyRef<Self>) {}
|
fn __ior__(&mut self, _other: PyRef<Self>) {}
|
||||||
fn __ixor__(&mut self, _other: PyRef<Self>) {}
|
fn __ixor__(&mut self, _other: PyRef<Self>) {}
|
||||||
|
fn __ipow__(&mut self, _other: PyRef<Self>, _modulo: Option<u8>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _test_binary_dunder(dunder: &str) {
|
fn _test_binary_dunder(dunder: &str) {
|
||||||
|
|
|
@ -108,11 +108,10 @@ impl PyNumberProtocol for InPlaceOperations {
|
||||||
self.value |= other;
|
self.value |= other;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __ipow__(&mut self, other: u32) {
|
fn __ipow__(&mut self, other: u32, _modulo: Option<u32>) {
|
||||||
self.value = self.value.pow(other);
|
self.value = self.value.pow(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inplace_operations() {
|
fn inplace_operations() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
|
@ -589,7 +588,7 @@ mod return_not_implemented {
|
||||||
fn __itruediv__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __itruediv__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
fn __ifloordiv__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __ifloordiv__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
fn __imod__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __imod__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
fn __ipow__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __ipow__(&'p mut self, _other: PyRef<'p, Self>, _modulo: Option<u8>) {}
|
||||||
fn __ilshift__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __ilshift__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
fn __irshift__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __irshift__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
fn __iand__(&'p mut self, _other: PyRef<'p, Self>) {}
|
fn __iand__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||||
|
|
|
@ -32,6 +32,8 @@ fn _test_compile_errors() {
|
||||||
t.compile_fail("tests/ui/missing_clone.rs");
|
t.compile_fail("tests/ui/missing_clone.rs");
|
||||||
t.compile_fail("tests/ui/reject_generics.rs");
|
t.compile_fail("tests/ui/reject_generics.rs");
|
||||||
t.compile_fail("tests/ui/not_send.rs");
|
t.compile_fail("tests/ui/not_send.rs");
|
||||||
|
t.compile_fail("tests/ui/invalid_pymethod_proto_args.rs");
|
||||||
|
t.compile_fail("tests/ui/invalid_pymethod_proto_args_py.rs");
|
||||||
|
|
||||||
tests_rust_1_49(&t);
|
tests_rust_1_49(&t);
|
||||||
tests_rust_1_55(&t);
|
tests_rust_1_55(&t);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
struct MyClass {}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl MyClass {
|
||||||
|
fn __truediv__(&self) -> PyResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
error: Expected 1 arguments, got 0
|
||||||
|
--> tests/ui/invalid_pymethod_proto_args.rs:8:8
|
||||||
|
|
|
||||||
|
8 | fn __truediv__(&self) -> PyResult<()> {
|
||||||
|
| ^^^^^^^^^^^
|
|
@ -0,0 +1,13 @@
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
struct MyClass {}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl MyClass {
|
||||||
|
fn __truediv__(&self, _py: Python) -> PyResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
error: Expected 1 arguments, got 0
|
||||||
|
--> tests/ui/invalid_pymethod_proto_args_py.rs:8:8
|
||||||
|
|
|
||||||
|
8 | fn __truediv__(&self, _py: Python) -> PyResult<()> {
|
||||||
|
| ^^^^^^^^^^^
|
Loading…
Reference in New Issue