`__ipow__` now supports modulo argument on Python 3.8+.
`pyo3-macros-backend` is now compiled with PyO3 cfgs to enable different magic method definitions based on version. Add check for correct number of arguments on magic methods.
This commit is contained in:
parent
2503a2dd5e
commit
50659b6b02
|
@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
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)
|
||||
- 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)
|
||||
- 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
|
||||
|
||||
|
@ -45,6 +46,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)
|
||||
- `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075)
|
||||
- `#[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
|
||||
|
||||
|
|
|
@ -288,13 +288,15 @@ This trait also has support the augmented arithmetic assignments (`+=`, `-=`,
|
|||
* `fn __itruediv__(&'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 __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 __irshift__(&'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 __ixor__(&'p mut self, other: impl FromPyObject) -> PyResult<()>`
|
||||
|
||||
|
||||
The following methods implement the unary arithmetic operations (`-`, `+`, `abs()` and `~`):
|
||||
|
||||
* `fn __neg__(&'p self) -> PyResult<impl ToPyObject>`
|
||||
|
|
|
@ -18,6 +18,9 @@ quote = { version = "1", default-features = false }
|
|||
proc-macro2 = { version = "1", default-features = false }
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "0.15.1", features = ["resolve-config"] }
|
||||
|
||||
[build-dependencies]
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "0.15.1", features = ["resolve-config"] }
|
||||
|
||||
[dependencies.syn]
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
use pyo3_build_config::pyo3_build_script_impl::{errors::Result, resolve_interpreter_config};
|
||||
|
||||
fn configure_pyo3() -> Result<()> {
|
||||
let interpreter_config = resolve_interpreter_config()?;
|
||||
interpreter_config.emit_pyo3_cfgs();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = configure_pyo3() {
|
||||
eprintln!("error: {}", e.report());
|
||||
std::process::exit(1)
|
||||
}
|
||||
}
|
|
@ -420,6 +420,12 @@ pub const NUM: Proto = Proto {
|
|||
MethodProto::new("__imod__", "PyNumberIModProtocol")
|
||||
.args(&["Other"])
|
||||
.has_self(),
|
||||
// See https://bugs.python.org/issue36379
|
||||
#[cfg(Py_3_8)]
|
||||
MethodProto::new("__ipow__", "PyNumberIPowProtocol")
|
||||
.args(&["Other", "Modulo"])
|
||||
.has_self(),
|
||||
#[cfg(not(Py_3_8))]
|
||||
MethodProto::new("__ipow__", "PyNumberIPowProtocol")
|
||||
.args(&["Other"])
|
||||
.has_self(),
|
||||
|
|
|
@ -532,10 +532,16 @@ const __IMOD__: SlotDef = SlotDef::new("Py_nb_inplace_remainder", "binaryfunc")
|
|||
.arguments(&[Ty::Object])
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
.return_self();
|
||||
#[cfg(Py_3_8)]
|
||||
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ternaryfunc")
|
||||
.arguments(&[Ty::Object, Ty::Object])
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
.return_self();
|
||||
#[cfg(not(Py_3_8))]
|
||||
const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "binaryfunc")
|
||||
.arguments(&[Ty::Object])
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
.return_self();
|
||||
const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc")
|
||||
.arguments(&[Ty::Object])
|
||||
.extract_error_mode(ExtractErrorMode::NotImplemented)
|
||||
|
@ -856,8 +862,11 @@ fn generate_method_body(
|
|||
) -> Result<TokenStream> {
|
||||
let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode);
|
||||
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)?;
|
||||
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 body = if let Some(return_mode) = return_mode {
|
||||
return_mode.return_call_output(py, call)
|
||||
|
@ -1026,7 +1035,7 @@ fn extract_proto_arguments(
|
|||
method_args: &[FnArg],
|
||||
proto_args: &[Ty],
|
||||
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 non_python_args = 0;
|
||||
|
||||
|
@ -1045,9 +1054,8 @@ fn extract_proto_arguments(
|
|||
arg_idents.push(ident);
|
||||
}
|
||||
}
|
||||
|
||||
let conversions = quote!(#(#args_conversions)*);
|
||||
Ok((arg_idents, conversions))
|
||||
Ok((arg_idents, non_python_args, conversions))
|
||||
}
|
||||
|
||||
struct StaticIdent(&'static str);
|
||||
|
|
|
@ -221,6 +221,14 @@ pub trait PyNumberProtocol<'p>: PyClass {
|
|||
{
|
||||
unimplemented!()
|
||||
}
|
||||
#[cfg(Py_3_8)]
|
||||
fn __ipow__(&'p mut self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result
|
||||
where
|
||||
Self: PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
#[cfg(not(Py_3_8))]
|
||||
fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result
|
||||
where
|
||||
Self: PyNumberIPowProtocol<'p>,
|
||||
|
@ -504,6 +512,8 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
|
|||
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Result: IntoPyCallbackOutput<()>;
|
||||
#[cfg(Py_3_8)]
|
||||
type Modulo: FromPyObject<'p>;
|
||||
}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
|
@ -714,11 +724,13 @@ py_binary_self_func!(isub, PyNumberISubProtocol, T::__isub__);
|
|||
py_binary_self_func!(imul, PyNumberIMulProtocol, T::__imul__);
|
||||
py_binary_self_func!(imod, PyNumberIModProtocol, T::__imod__);
|
||||
|
||||
// See https://bugs.python.org/issue36379
|
||||
#[doc(hidden)]
|
||||
#[cfg(Py_3_8)]
|
||||
pub unsafe extern "C" fn ipow<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
other: *mut ffi::PyObject,
|
||||
_modulo: *mut ffi::PyObject,
|
||||
modulo: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||
|
@ -728,7 +740,35 @@ where
|
|||
crate::callback_body!(py, {
|
||||
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
||||
call_operator_mut!(py, slf_cell, __ipow__, other).convert(py)?;
|
||||
let modulo = py.from_borrowed_ptr::<crate::PyAny>(modulo);
|
||||
slf_cell
|
||||
.try_borrow_mut()?
|
||||
.__ipow__(
|
||||
extract_or_return_not_implemented!(other),
|
||||
extract_or_return_not_implemented!(modulo),
|
||||
)
|
||||
.convert(py)?;
|
||||
ffi::Py_INCREF(slf);
|
||||
Ok::<_, PyErr>(slf)
|
||||
})
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(Py_3_8))]
|
||||
pub unsafe extern "C" fn ipow<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
other: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject
|
||||
where
|
||||
T: for<'p> PyNumberIPowProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf_cell = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let other = py.from_borrowed_ptr::<crate::PyAny>(other);
|
||||
slf_cell
|
||||
.try_borrow_mut()?
|
||||
.__ipow__(extract_or_return_not_implemented!(other))
|
||||
.convert(py)?;
|
||||
ffi::Py_INCREF(slf);
|
||||
Ok::<_, PyErr>(slf)
|
||||
})
|
||||
|
|
|
@ -9,6 +9,7 @@ pub struct Dummy;
|
|||
#[pyo3(crate = "crate")]
|
||||
pub struct DummyIter;
|
||||
|
||||
#[cfg(Py_3_8)]
|
||||
#[crate::pymethods]
|
||||
#[pyo3(crate = "crate")]
|
||||
impl Dummy {
|
||||
|
@ -401,3 +402,396 @@ impl Dummy {
|
|||
// PyGcProtocol
|
||||
// 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) {}
|
||||
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?
|
||||
}
|
||||
|
|
|
@ -57,6 +57,51 @@ struct InPlaceOperations {
|
|||
value: u32,
|
||||
}
|
||||
|
||||
#[cfg(Py_3_8)]
|
||||
#[pymethods]
|
||||
impl InPlaceOperations {
|
||||
fn __repr__(&self) -> String {
|
||||
format!("IPO({:?})", self.value)
|
||||
}
|
||||
|
||||
fn __iadd__(&mut self, other: u32) {
|
||||
self.value += other;
|
||||
}
|
||||
|
||||
fn __isub__(&mut self, other: u32) {
|
||||
self.value -= other;
|
||||
}
|
||||
|
||||
fn __imul__(&mut self, other: u32) {
|
||||
self.value *= other;
|
||||
}
|
||||
|
||||
fn __ilshift__(&mut self, other: u32) {
|
||||
self.value <<= other;
|
||||
}
|
||||
|
||||
fn __irshift__(&mut self, other: u32) {
|
||||
self.value >>= other;
|
||||
}
|
||||
|
||||
fn __iand__(&mut self, other: u32) {
|
||||
self.value &= other;
|
||||
}
|
||||
|
||||
fn __ixor__(&mut self, other: u32) {
|
||||
self.value ^= other;
|
||||
}
|
||||
|
||||
fn __ior__(&mut self, other: u32) {
|
||||
self.value |= other;
|
||||
}
|
||||
|
||||
fn __ipow__(&mut self, other: u32, _modulo: Option<u32>) {
|
||||
self.value = self.value.pow(other);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_8))]
|
||||
#[pymethods]
|
||||
impl InPlaceOperations {
|
||||
fn __repr__(&self) -> String {
|
||||
|
@ -505,6 +550,7 @@ mod return_not_implemented {
|
|||
#[pyclass]
|
||||
struct RichComparisonToSelf {}
|
||||
|
||||
#[cfg(Py_3_8)]
|
||||
#[pymethods]
|
||||
impl RichComparisonToSelf {
|
||||
fn __repr__(&self) -> &'static str {
|
||||
|
@ -566,12 +612,82 @@ mod return_not_implemented {
|
|||
fn __itruediv__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ifloordiv__(&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 __irshift__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __iand__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ior__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ixor__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ipow__(&mut self, _other: PyRef<Self>, _modulo: Option<u8>) {}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_8))]
|
||||
#[pymethods]
|
||||
impl RichComparisonToSelf {
|
||||
fn __repr__(&self) -> &'static str {
|
||||
"RC_Self"
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, other: PyRef<Self>, _op: CompareOp) -> PyObject {
|
||||
other.py().None()
|
||||
}
|
||||
|
||||
fn __add__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __sub__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __mul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __matmul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __truediv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __floordiv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __pow__(slf: PyRef<Self>, _other: u8, _modulo: Option<u8>) -> PyRef<Self> {
|
||||
slf
|
||||
}
|
||||
fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __rshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __divmod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __and__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __or__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
fn __xor__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {
|
||||
slf
|
||||
}
|
||||
|
||||
// Inplace assignments
|
||||
fn __iadd__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __isub__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __imul__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __imatmul__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __itruediv__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ifloordiv__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __imod__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ilshift__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __irshift__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __iand__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ior__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ixor__(&mut self, _other: PyRef<Self>) {}
|
||||
fn __ipow__(&mut self, _other: PyRef<Self>) {}
|
||||
}
|
||||
|
||||
fn _test_binary_dunder(dunder: &str) {
|
||||
|
|
|
@ -74,6 +74,7 @@ impl PyObjectProtocol for InPlaceOperations {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_8))]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&mut self, other: u32) {
|
||||
|
@ -113,6 +114,45 @@ impl PyNumberProtocol for InPlaceOperations {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3_8)]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&mut self, other: u32) {
|
||||
self.value += other;
|
||||
}
|
||||
|
||||
fn __isub__(&mut self, other: u32) {
|
||||
self.value -= other;
|
||||
}
|
||||
|
||||
fn __imul__(&mut self, other: u32) {
|
||||
self.value *= other;
|
||||
}
|
||||
|
||||
fn __ilshift__(&mut self, other: u32) {
|
||||
self.value <<= other;
|
||||
}
|
||||
|
||||
fn __irshift__(&mut self, other: u32) {
|
||||
self.value >>= other;
|
||||
}
|
||||
|
||||
fn __iand__(&mut self, other: u32) {
|
||||
self.value &= other;
|
||||
}
|
||||
|
||||
fn __ixor__(&mut self, other: u32) {
|
||||
self.value ^= other;
|
||||
}
|
||||
|
||||
fn __ior__(&mut self, other: u32) {
|
||||
self.value |= other;
|
||||
}
|
||||
|
||||
fn __ipow__(&mut self, other: u32, _modulo: Option<u32>) {
|
||||
self.value = self.value.pow(other);
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn inplace_operations() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -536,6 +576,69 @@ mod return_not_implemented {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3_8)]
|
||||
#[pyproto]
|
||||
impl<'p> PyNumberProtocol<'p> for RichComparisonToSelf {
|
||||
fn __add__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __sub__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __mul__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __matmul__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __truediv__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __floordiv__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __mod__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __pow__(lhs: &'p PyAny, _other: u8, _modulo: Option<u8>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __lshift__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __rshift__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __divmod__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __and__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __or__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
fn __xor__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
lhs
|
||||
}
|
||||
|
||||
// Inplace assignments
|
||||
fn __iadd__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __isub__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __imul__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __imatmul__(&'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 __imod__(&'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 __irshift__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __iand__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __ior__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
fn __ixor__(&'p mut self, _other: PyRef<'p, Self>) {}
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_8))]
|
||||
#[pyproto]
|
||||
impl<'p> PyNumberProtocol<'p> for RichComparisonToSelf {
|
||||
fn __add__(lhs: &'p PyAny, _other: PyRef<'p, Self>) -> &'p PyAny {
|
||||
|
|
|
@ -30,6 +30,7 @@ fn _test_compile_errors() {
|
|||
t.compile_fail("tests/ui/missing_clone.rs");
|
||||
t.compile_fail("tests/ui/reject_generics.rs");
|
||||
t.compile_fail("tests/ui/not_send.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_proto_args.rs");
|
||||
|
||||
tests_rust_1_49(&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<()> {
|
||||
| ^^^^^^^^^^^
|
Loading…
Reference in New Issue