2021-12-03 00:03:32 +00:00
|
|
|
#![cfg(feature = "macros")]
|
|
|
|
|
2020-12-13 22:51:19 +00:00
|
|
|
use pyo3::exceptions::PyValueError;
|
2018-05-02 18:49:40 +00:00
|
|
|
use pyo3::prelude::*;
|
2022-11-19 06:33:43 +00:00
|
|
|
use pyo3::types::IntoPyDict;
|
2018-05-02 18:49:40 +00:00
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2018-09-02 21:33:45 +00:00
|
|
|
struct EmptyClassWithNew {}
|
2018-05-02 18:49:40 +00:00
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pymethods]
|
2018-05-02 18:49:40 +00:00
|
|
|
impl EmptyClassWithNew {
|
2019-02-23 17:38:00 +00:00
|
|
|
#[new]
|
2019-12-14 14:16:39 +00:00
|
|
|
fn new() -> EmptyClassWithNew {
|
|
|
|
EmptyClassWithNew {}
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty_class_with_new() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<EmptyClassWithNew>();
|
|
|
|
assert!(typeobj
|
|
|
|
.call((), None)
|
|
|
|
.unwrap()
|
2022-11-14 06:15:33 +00:00
|
|
|
.downcast::<PyCell<EmptyClassWithNew>>()
|
2022-07-19 17:34:23 +00:00
|
|
|
.is_ok());
|
2022-11-19 06:33:43 +00:00
|
|
|
|
|
|
|
// Calling with arbitrary args or kwargs is not ok
|
|
|
|
assert!(typeobj.call(("some", "args"), None).is_err());
|
|
|
|
assert!(typeobj
|
|
|
|
.call((), Some([("some", "kwarg")].into_py_dict(py)))
|
|
|
|
.is_err());
|
2022-07-19 17:34:23 +00:00
|
|
|
});
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 16:04:25 +00:00
|
|
|
#[pyclass]
|
|
|
|
struct UnitClassWithNew;
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl UnitClassWithNew {
|
|
|
|
#[new]
|
|
|
|
fn new() -> Self {
|
|
|
|
Self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unit_class_with_new() {
|
2021-03-18 13:09:46 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<UnitClassWithNew>();
|
|
|
|
assert!(typeobj
|
|
|
|
.call((), None)
|
|
|
|
.unwrap()
|
2022-11-14 06:15:33 +00:00
|
|
|
.downcast::<PyCell<UnitClassWithNew>>()
|
2021-03-18 13:09:46 +00:00
|
|
|
.is_ok());
|
|
|
|
});
|
2021-03-17 16:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
struct TupleClassWithNew(i32);
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl TupleClassWithNew {
|
|
|
|
#[new]
|
|
|
|
fn new(arg: i32) -> Self {
|
|
|
|
Self(arg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn tuple_class_with_new() {
|
2021-03-18 13:09:46 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<TupleClassWithNew>();
|
|
|
|
let wrp = typeobj.call((42,), None).unwrap();
|
2022-11-14 06:15:33 +00:00
|
|
|
let obj = wrp.downcast::<PyCell<TupleClassWithNew>>().unwrap();
|
2021-03-18 13:09:46 +00:00
|
|
|
let obj_ref = obj.borrow();
|
|
|
|
assert_eq!(obj_ref.0, 42);
|
|
|
|
});
|
2021-03-17 16:04:25 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2019-12-14 14:16:39 +00:00
|
|
|
#[derive(Debug)]
|
2018-05-02 18:49:40 +00:00
|
|
|
struct NewWithOneArg {
|
|
|
|
_data: i32,
|
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pymethods]
|
2018-05-02 18:49:40 +00:00
|
|
|
impl NewWithOneArg {
|
|
|
|
#[new]
|
2019-12-14 14:16:39 +00:00
|
|
|
fn new(arg: i32) -> NewWithOneArg {
|
|
|
|
NewWithOneArg { _data: arg }
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_with_one_arg() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<NewWithOneArg>();
|
|
|
|
let wrp = typeobj.call((42,), None).unwrap();
|
2022-11-14 06:15:33 +00:00
|
|
|
let obj = wrp.downcast::<PyCell<NewWithOneArg>>().unwrap();
|
2022-07-19 17:34:23 +00:00
|
|
|
let obj_ref = obj.borrow();
|
|
|
|
assert_eq!(obj_ref._data, 42);
|
|
|
|
});
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2018-05-02 18:49:40 +00:00
|
|
|
struct NewWithTwoArgs {
|
|
|
|
_data1: i32,
|
|
|
|
_data2: i32,
|
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pymethods]
|
2018-05-02 18:49:40 +00:00
|
|
|
impl NewWithTwoArgs {
|
|
|
|
#[new]
|
2019-12-14 14:16:39 +00:00
|
|
|
fn new(arg1: i32, arg2: i32) -> Self {
|
|
|
|
NewWithTwoArgs {
|
2018-06-15 19:21:12 +00:00
|
|
|
_data1: arg1,
|
|
|
|
_data2: arg2,
|
2019-12-14 14:16:39 +00:00
|
|
|
}
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_with_two_args() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<NewWithTwoArgs>();
|
|
|
|
let wrp = typeobj
|
|
|
|
.call((10, 20), None)
|
|
|
|
.map_err(|e| e.print(py))
|
|
|
|
.unwrap();
|
2022-11-14 06:15:33 +00:00
|
|
|
let obj = wrp.downcast::<PyCell<NewWithTwoArgs>>().unwrap();
|
2022-07-19 17:34:23 +00:00
|
|
|
let obj_ref = obj.borrow();
|
|
|
|
assert_eq!(obj_ref._data1, 10);
|
|
|
|
assert_eq!(obj_ref._data2, 20);
|
|
|
|
});
|
2018-06-15 19:21:12 +00:00
|
|
|
}
|
2020-06-21 14:38:26 +00:00
|
|
|
|
|
|
|
#[pyclass(subclass)]
|
|
|
|
struct SuperClass {
|
|
|
|
#[pyo3(get)]
|
|
|
|
from_rust: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl SuperClass {
|
|
|
|
#[new]
|
|
|
|
fn new() -> Self {
|
|
|
|
SuperClass { from_rust: true }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that `subclass.__new__` works correctly.
|
|
|
|
/// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug.
|
|
|
|
#[test]
|
|
|
|
fn subclass_new() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let super_cls = py.get_type::<SuperClass>();
|
|
|
|
let source = pyo3::indoc::indoc!(
|
|
|
|
r#"
|
2020-06-21 14:38:26 +00:00
|
|
|
class Class(SuperClass):
|
|
|
|
def __new__(cls):
|
|
|
|
return super().__new__(cls) # This should return an instance of Class
|
|
|
|
|
|
|
|
@property
|
|
|
|
def from_rust(self):
|
|
|
|
return False
|
|
|
|
c = Class()
|
|
|
|
assert c.from_rust is False
|
|
|
|
"#
|
2022-07-19 17:34:23 +00:00
|
|
|
);
|
|
|
|
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
|
|
|
globals.set_item("SuperClass", super_cls).unwrap();
|
|
|
|
py.run(source, Some(globals), None)
|
|
|
|
.map_err(|e| e.print(py))
|
|
|
|
.unwrap();
|
|
|
|
});
|
2020-06-21 14:38:26 +00:00
|
|
|
}
|
2020-12-13 22:51:19 +00:00
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct NewWithCustomError {}
|
|
|
|
|
|
|
|
struct CustomError;
|
|
|
|
|
|
|
|
impl From<CustomError> for PyErr {
|
|
|
|
fn from(_error: CustomError) -> PyErr {
|
|
|
|
PyValueError::new_err("custom error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl NewWithCustomError {
|
|
|
|
#[new]
|
|
|
|
fn new() -> Result<NewWithCustomError, CustomError> {
|
|
|
|
Err(CustomError)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_with_custom_error() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let typeobj = py.get_type::<NewWithCustomError>();
|
|
|
|
let err = typeobj.call0().unwrap_err();
|
|
|
|
assert_eq!(err.to_string(), "ValueError: custom error");
|
|
|
|
});
|
2020-12-13 22:51:19 +00:00
|
|
|
}
|