introduce PythonToken; cleanup number protocol
This commit is contained in:
parent
467cce6c6d
commit
6205be98b8
|
@ -439,68 +439,68 @@ pub const NUM: Proto = Proto {
|
|||
MethodProto::Binary {
|
||||
name: "__iadd__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIAddProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__isub__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberISubProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__imul__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIMulProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__imatmul__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIMatmulProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__itruediv__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberITruedivProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__ifloordiv__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIFloordivProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__imod__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIModProtocol"},
|
||||
MethodProto::Ternary {
|
||||
name: "__ipow__",
|
||||
arg1: "Other",
|
||||
arg2: "Modulo",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIPowProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__ilshift__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberILShiftProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__irshift__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIRShiftProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__iand__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIAndProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__ixor__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIXorProtocol"},
|
||||
MethodProto::Binary {
|
||||
name: "__ior__",
|
||||
arg: "Other",
|
||||
pyres: true,
|
||||
pyres: false,
|
||||
proto: "::pyo3::class::number::PyNumberIOrProtocol"},
|
||||
|
||||
MethodProto::Unary {
|
||||
|
|
|
@ -42,12 +42,14 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
match *meth {
|
||||
MethodProto::Unary{name: _, pyres, proto} => {
|
||||
let p = syn::Ident::from(proto);
|
||||
let succ = get_res_success(ty);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
let tmp = extract_decl(syn::parse_item(
|
||||
quote! {fn test(&self)
|
||||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
sig.decl.output = tmp.output.clone();
|
||||
modify_self_ty(sig);
|
||||
modify_py_ty(sig);
|
||||
|
||||
if pyres {
|
||||
quote! {
|
||||
|
@ -65,14 +67,14 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
}
|
||||
},
|
||||
MethodProto::Binary{name: n, arg, pyres, proto} => {
|
||||
if sig.decl.inputs.len() < 2 {
|
||||
if sig.decl.inputs.len() <= 2 {
|
||||
println!("Not enough arguments for {}", n);
|
||||
return Tokens::new();
|
||||
}
|
||||
let p = syn::Ident::from(proto);
|
||||
let arg_name = syn::Ident::from(arg);
|
||||
let arg_ty = get_arg_ty(sig, 2);
|
||||
let succ = get_res_success(ty);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
let tmp = extract_decl(syn::parse_item(
|
||||
quote! {fn test(
|
||||
|
@ -85,6 +87,8 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
arg: Option<<#cls as #p<'p>>::#arg_name>)
|
||||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
modify_arg_ty(sig, 2, &tmp, &tmp2);
|
||||
modify_self_ty(sig);
|
||||
modify_py_ty(sig);
|
||||
|
||||
if pyres {
|
||||
quote! {
|
||||
|
@ -104,7 +108,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
}
|
||||
},
|
||||
MethodProto::Ternary{name: n, arg1, arg2, pyres, proto} => {
|
||||
if sig.decl.inputs.len() < 3 {
|
||||
if sig.decl.inputs.len() <= 3 {
|
||||
print_err(format!("Not enough arguments {}", n), quote!(sig));
|
||||
return Tokens::new();
|
||||
}
|
||||
|
@ -113,7 +117,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
let arg1_ty = get_arg_ty(sig, 2);
|
||||
let arg2_name = syn::Ident::from(arg2);
|
||||
let arg2_ty = get_arg_ty(sig, 3);
|
||||
let succ = get_res_success(ty);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
// rewrite ty
|
||||
let tmp = extract_decl(syn::parse_item(
|
||||
|
@ -130,6 +134,8 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
modify_arg_ty(sig, 2, &tmp, &tmp2);
|
||||
modify_arg_ty(sig, 3, &tmp, &tmp2);
|
||||
modify_self_ty(sig);
|
||||
modify_py_ty(sig);
|
||||
|
||||
if pyres {
|
||||
quote! {
|
||||
|
@ -151,7 +157,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
}
|
||||
},
|
||||
MethodProto::Quaternary{name: n, arg1, arg2, arg3, proto} => {
|
||||
if sig.decl.inputs.len() < 4 {
|
||||
if sig.decl.inputs.len() <= 4 {
|
||||
print_err(format!("Not enough arguments {}", n), quote!(sig));
|
||||
return Tokens::new();
|
||||
}
|
||||
|
@ -162,7 +168,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
let arg2_ty = get_arg_ty(sig, 3);
|
||||
let arg3_name = syn::Ident::from(arg3);
|
||||
let arg3_ty = get_arg_ty(sig, 4);
|
||||
let succ = get_res_success(ty);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
// rewrite ty
|
||||
let tmp = extract_decl(syn::parse_item(
|
||||
|
@ -182,6 +188,8 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
modify_arg_ty(sig, 2, &tmp, &tmp2);
|
||||
modify_arg_ty(sig, 3, &tmp, &tmp2);
|
||||
modify_arg_ty(sig, 4, &tmp, &tmp2);
|
||||
modify_self_ty(sig);
|
||||
modify_py_ty(sig);
|
||||
|
||||
quote! {
|
||||
impl<'p> #p<'p> for #cls {
|
||||
|
@ -202,7 +210,7 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
|
||||
// TODO: better arg ty detection
|
||||
fn get_arg_ty(sig: &syn::MethodSig, idx: usize) -> syn::Ty {
|
||||
match sig.decl.inputs[idx] {
|
||||
let mut ty = match sig.decl.inputs[idx] {
|
||||
syn::FnArg::Captured(_, ref arg_ty) => {
|
||||
match arg_ty {
|
||||
&syn::Ty::Path(_, ref path) => {
|
||||
|
@ -220,25 +228,38 @@ fn get_arg_ty(sig: &syn::MethodSig, idx: usize) -> syn::Ty {
|
|||
}
|
||||
arg_ty.clone()
|
||||
},
|
||||
_ => {
|
||||
arg_ty.clone()
|
||||
}
|
||||
_ => arg_ty.clone()
|
||||
}
|
||||
},
|
||||
_ =>
|
||||
panic!("fn arg type is not supported"),
|
||||
_ => panic!("fn arg type is not supported"),
|
||||
};
|
||||
|
||||
match ty {
|
||||
syn::Ty::Rptr(ref mut lifetime, _) => {
|
||||
match lifetime {
|
||||
&mut None => {
|
||||
*lifetime = Some(syn::Lifetime {ident: syn::Ident::from("'p")})
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
// Success
|
||||
fn get_res_success(ty: &syn::Ty) -> syn::Ty {
|
||||
match ty {
|
||||
fn get_res_success(ty: &syn::Ty) -> (Tokens, syn::Ty) {
|
||||
let result;
|
||||
let mut succ = match ty {
|
||||
&syn::Ty::Path(_, ref path) => {
|
||||
if let Some(segment) = path.segments.last() {
|
||||
match segment.ident.as_ref() {
|
||||
// check result type
|
||||
"PyResult" => match segment.parameters {
|
||||
syn::PathParameters::AngleBracketed(ref data) => {
|
||||
result = true;
|
||||
data.types[0].clone()
|
||||
},
|
||||
_ => panic!("fn result type is not supported"),
|
||||
|
@ -253,7 +274,40 @@ fn get_res_success(ty: &syn::Ty) -> syn::Ty {
|
|||
}
|
||||
}
|
||||
_ => panic!("not supported: {:?}", ty),
|
||||
};
|
||||
|
||||
// add lifetime to Py<T>
|
||||
match succ {
|
||||
syn::Ty::Path(_, ref mut path) => {
|
||||
let last = path.segments.len()-1;
|
||||
let seg = path.segments[last].clone();
|
||||
|
||||
if seg.ident.as_ref() == "Py" {
|
||||
if let syn::PathParameters::AngleBracketed(ref data) = seg.parameters {
|
||||
path.segments[last] = syn::PathSegment{
|
||||
ident: seg.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(
|
||||
syn::AngleBracketedParameterData{
|
||||
lifetimes: vec![syn::Lifetime {
|
||||
ident: syn::Ident::from("'p")}],
|
||||
types: data.types.clone(),
|
||||
bindings: data.bindings.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// result
|
||||
let res = if result {
|
||||
quote! {PyResult<#succ>}
|
||||
} else {
|
||||
quote! {#ty}
|
||||
};
|
||||
|
||||
(res, succ)
|
||||
}
|
||||
|
||||
|
||||
|
@ -285,13 +339,54 @@ fn modify_arg_ty(sig: &mut syn::MethodSig, idx: usize,
|
|||
}
|
||||
}
|
||||
},
|
||||
_ =>
|
||||
panic!("not supported"),
|
||||
_ => panic!("not supported"),
|
||||
}
|
||||
|
||||
sig.decl.output = decl1.output.clone();
|
||||
}
|
||||
|
||||
fn modify_self_ty(sig: &mut syn::MethodSig)
|
||||
{
|
||||
match sig.decl.inputs[0] {
|
||||
syn::FnArg::SelfRef(ref mut lifetime, _) => {
|
||||
*lifetime = Some(syn::Lifetime {ident: syn::Ident::from("'p")})
|
||||
},
|
||||
_ => panic!("not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
// modify Python signature
|
||||
fn modify_py_ty(sig: &mut syn::MethodSig)
|
||||
{
|
||||
match sig.decl.inputs[1] {
|
||||
syn::FnArg::Captured(_, ref mut arg_ty) => {
|
||||
match arg_ty {
|
||||
&mut syn::Ty::Path(_, ref mut path) => {
|
||||
let last = path.segments.len()-1;
|
||||
let seg = path.segments[last].clone();
|
||||
if seg.ident.as_ref() == "Python" {
|
||||
if let syn::PathParameters::AngleBracketed(ref data) = seg.parameters {
|
||||
path.segments[last] = syn::PathSegment{
|
||||
ident: seg.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(
|
||||
syn::AngleBracketedParameterData{
|
||||
lifetimes: vec![syn::Lifetime {
|
||||
ident: syn::Ident::from("'p")}],
|
||||
types: data.types.clone(),
|
||||
bindings: data.bindings.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
},
|
||||
_ => panic!("not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn fix_name(pat: &syn::Pat, arg: &syn::FnArg) -> syn::FnArg {
|
||||
match arg {
|
||||
&syn::FnArg::Captured(_, ref arg_ty) =>
|
||||
|
|
|
@ -8,7 +8,8 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
|
|||
let base = syn::Ident::from("_pyo3::PyObject");
|
||||
|
||||
match ast.body {
|
||||
syn::Body::Struct(syn::VariantData::Struct(_)) => (),
|
||||
syn::Body::Struct(syn::VariantData::Struct(_)) => {
|
||||
},
|
||||
_ => panic!("#[class] can only be used with notmal structs"),
|
||||
}
|
||||
|
||||
|
@ -22,7 +23,6 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
|
|||
const #dummy_const: () = {
|
||||
extern crate pyo3 as _pyo3;
|
||||
use std;
|
||||
use pyo3::python::IntoPythonPointer;
|
||||
|
||||
#tokens
|
||||
};
|
||||
|
@ -30,6 +30,7 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
|
|||
}
|
||||
|
||||
fn impl_class(cls: &syn::Ident, base: &syn::Ident) -> Tokens {
|
||||
let token_name = syn::Ident::from("__py_token");
|
||||
let cls_name = quote! { #cls }.as_str().to_string();
|
||||
|
||||
quote! {
|
||||
|
@ -60,12 +61,22 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident) -> Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
impl _pyo3::IntoPyObject for #cls {
|
||||
impl _pyo3::python::ToPythonPointer for #cls {
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject> where Self: Sized
|
||||
{
|
||||
let ptr = py.init(self).into_ptr();
|
||||
_pyo3::PyObject::from_owned_ptr(py, ptr)
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}.offset(-offset) as *mut _pyo3::ffi::PyObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::python::PyClone for #cls {
|
||||
fn clone_ref(&self) -> PyPtr<#cls> {
|
||||
unsafe {
|
||||
let ptr = <#cls as _pyo3::python::ToPythonPointer>::as_ptr(self);
|
||||
_pyo3::PyPtr::from_borrowed_ptr(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ pub fn impl_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens
|
|||
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
|
||||
_pyo3::callback::cb_meth::<_, *mut _pyo3::ffi::PyObject>(LOCATION, |py| {
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let mut slf: Py<#cls> = Py::from_borrowed_ptr(py, slf);
|
||||
|
||||
let args: _pyo3::Py<_pyo3::PyTuple> = _pyo3::Py::from_borrowed_ptr(py, args);
|
||||
|
@ -70,18 +70,24 @@ pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
let body = impl_arg_params(&spec, cb);
|
||||
|
||||
quote! {
|
||||
unsafe extern "C" fn wrap<'p>(
|
||||
slf: *mut _pyo3::ffi::PyObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
|
||||
_pyo3::callback::handle(LOCATION, _pyo3::callback::PyObjectCallbackConverter, |py| {
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let mut slf: Py<#cls> = Py::from_borrowed_ptr(py, slf);
|
||||
|
||||
let args: _pyo3::Py<_pyo3::PyTuple> = _pyo3::Py::from_borrowed_ptr(py, args);
|
||||
let kwargs: Option<_pyo3::Py<_pyo3::PyDict>> =
|
||||
_pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
#body
|
||||
let result = {
|
||||
#body
|
||||
};
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -91,20 +97,28 @@ pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
pub fn impl_wrap_new(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let cb = impl_class_new(cls, name, spec);
|
||||
let body = impl_arg_params(spec, cb);
|
||||
let output = &spec.output;
|
||||
|
||||
quote! {
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap(cls: *mut _pyo3::ffi::PyTypeObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
||||
{
|
||||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".", stringify!(#name), "()");
|
||||
_pyo3::callback::handle(LOCATION, _pyo3::callback::PyObjectCallbackConverter, |py| {
|
||||
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name), "()");
|
||||
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let cls: _pyo3::Py<_pyo3::PyType> = _pyo3::Py::from_borrowed_ptr(
|
||||
py, cls as *mut _pyo3::ffi::PyObject);
|
||||
let args: _pyo3::Py<_pyo3::PyTuple> = _pyo3::Py::from_borrowed_ptr(py, args);
|
||||
let kwargs: Option<_pyo3::Py<_pyo3::PyDict>> =
|
||||
_pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
#body
|
||||
let result: #output = {
|
||||
#body
|
||||
};
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -120,8 +134,8 @@ fn impl_wrap_getter(cls: &Box<syn::Ty>, name: &syn::Ident, _spec: &FnSpec) -> To
|
|||
{
|
||||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".getter_", stringify!(#name), "()");
|
||||
_pyo3::callback::handle(LOCATION, _pyo3::callback::PyObjectCallbackConverter, |py| {
|
||||
let slf: _pyo3::Py<#cls> = _pyo3::Py::from_borrowed_ptr(py, slf);
|
||||
_pyo3::callback::cb_unary::<#cls, _, _, _>(
|
||||
LOCATION, slf, _pyo3::callback::PyObjectCallbackConverter, |py, slf| {
|
||||
slf.#name(py)
|
||||
})
|
||||
}
|
||||
|
@ -130,25 +144,33 @@ fn impl_wrap_getter(cls: &Box<syn::Ty>, name: &syn::Ident, _spec: &FnSpec) -> To
|
|||
|
||||
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||
fn impl_wrap_setter(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
if spec.args.len() < 1 {
|
||||
println!("Not enough arguments for setter {}::{}", quote!{#cls}, name);
|
||||
}
|
||||
let val_ty = spec.args[0].ty;
|
||||
|
||||
quote! {
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap(slf: *mut _pyo3::ffi::PyObject,
|
||||
value: *mut _pyo3::ffi::PyObject,
|
||||
_: *mut _pyo3::c_void) -> _pyo3::c_int
|
||||
{
|
||||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".setter", stringify!(#name), "()");
|
||||
_pyo3::callback::handle(LOCATION, _pyo3::callback::UnitCallbackConverter, |py| {
|
||||
let slf: _pyo3::Py<#cls> = _pyo3::Py::from_borrowed_ptr(py, slf);
|
||||
_pyo3::callback::cb_setter(LOCATION, |py| {
|
||||
let mut slf = _pyo3::Py::<#cls>::from_borrowed_ptr(py, slf);
|
||||
let value = _pyo3::PyObject::from_borrowed_ptr(py, value);
|
||||
|
||||
match <#val_ty as _pyo3::FromPyObject>::extract(&value) {
|
||||
Ok(val) => {
|
||||
let ret = slf.#name(val);
|
||||
ret.map(|o| ())
|
||||
}
|
||||
let result = match <#val_ty as _pyo3::FromPyObject>::extract(&value) {
|
||||
Ok(val) => slf.#name(py, val),
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -156,19 +178,17 @@ fn impl_wrap_setter(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tok
|
|||
}
|
||||
|
||||
|
||||
fn impl_call(cls: &Box<syn::Ty>, fname: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
fn impl_call(_cls: &Box<syn::Ty>, fname: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
quote! {{
|
||||
slf.#fname(py, #(#names),*)
|
||||
slf.as_mut().#fname(py, #(#names),*)
|
||||
}}
|
||||
}
|
||||
|
||||
fn impl_class_new(cls: &Box<syn::Ty>, fname: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
quote! {{
|
||||
let cls: _pyo3::Py<_pyo3::PyType> = _pyo3::Py::from_borrowed_ptr(
|
||||
py, cls as *mut _pyo3::ffi::PyObject);
|
||||
#cls::#fname(&cls, #(#names),*)
|
||||
#cls::#fname(&cls, py, #(#names),*)
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,8 +95,7 @@ fn impl_proto_impl(ty: &Box<syn::Ty>, impls: &mut Vec<syn::ImplItem>, proto: &de
|
|||
let name = syn::Ident::from(m.name);
|
||||
let proto = syn::Ident::from(m.proto);
|
||||
|
||||
let fn_spec = FnSpec::parse(
|
||||
&iimpl.ident, sig, &mut iimpl.attrs);
|
||||
let fn_spec = FnSpec::parse(&iimpl.ident, sig, &mut iimpl.attrs);
|
||||
let meth = py_method::impl_proto_wrap(ty, &iimpl.ident, &fn_spec);
|
||||
|
||||
py_methods.push(
|
||||
|
|
|
@ -21,7 +21,7 @@ pub trait CallbackConverter<S> {
|
|||
|
||||
pub struct PyObjectCallbackConverter;
|
||||
|
||||
impl <S> CallbackConverter<S> for PyObjectCallbackConverter
|
||||
impl<S> CallbackConverter<S> for PyObjectCallbackConverter
|
||||
where S: IntoPyObject
|
||||
{
|
||||
type R = *mut ffi::PyObject;
|
||||
|
@ -90,7 +90,7 @@ impl CallbackConverter<()> for UnitCallbackConverter {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct IterNextResultConverter;
|
||||
/*pub struct IterNextResultConverter;
|
||||
|
||||
impl <T> CallbackConverter<Option<T>>
|
||||
for IterNextResultConverter
|
||||
|
@ -112,7 +112,7 @@ impl <T> CallbackConverter<Option<T>>
|
|||
fn error_value() -> *mut ffi::PyObject {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub trait WrappingCastTo<T> {
|
||||
fn wrapping_cast(self) -> T;
|
||||
|
@ -250,7 +250,7 @@ pub unsafe fn cb_unary_unit<Slf, F>(location: &str, slf: *mut ffi::PyObject, f:
|
|||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn cb_meth<F, R>(location: &str, f: F) -> *mut ffi::PyObject
|
||||
pub unsafe fn cb_meth<F>(location: &str, f: F) -> *mut ffi::PyObject
|
||||
where F: for<'p> FnOnce(Python<'p>) -> *mut ffi::PyObject,
|
||||
F: panic::UnwindSafe
|
||||
{
|
||||
|
@ -270,6 +270,26 @@ pub unsafe fn cb_meth<F, R>(location: &str, f: F) -> *mut ffi::PyObject
|
|||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn cb_setter<F>(location: &str, f: F) -> c_int
|
||||
where F: for<'p> FnOnce(Python<'p>) -> c_int,
|
||||
F: panic::UnwindSafe
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
f(py)
|
||||
});
|
||||
let ret = match ret {
|
||||
Ok(r) => r,
|
||||
Err(ref err) => {
|
||||
handle_panic(Python::assume_gil_acquired(), err);
|
||||
-1
|
||||
}
|
||||
};
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn cb_convert<C, T>(_c: C, py: Python, value: PyResult<T>) -> C::R
|
||||
where C: CallbackConverter<T>
|
||||
|
|
|
@ -24,13 +24,13 @@ pub trait PyAsyncProtocol<'p>: PyTypeInfo + Sized + 'static {
|
|||
fn __aiter__(&'p self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyAsyncAiterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __anext__(&'p self, py: Python<'p>)
|
||||
fn __anext__(&'p mut self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyAsyncAnextProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __aenter__(&'p self, py: Python<'p>)
|
||||
fn __aenter__(&'p mut self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyAsyncAenterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __aexit__(&'p self, py: Python<'p>,
|
||||
fn __aexit__(&'p mut self, py: Python<'p>,
|
||||
exc_type: Option<Self::ExcType>,
|
||||
exc_value: Option<Self::ExcValue>,
|
||||
traceback: Option<Self::Traceback>)
|
||||
|
|
|
@ -31,10 +31,10 @@ pub trait PyObjectProtocol<'p>: PyTypeInfo + Sized + 'static {
|
|||
fn __getattr__(&'p self, py: Python<'p>, name: Self::Name)
|
||||
-> Self::Result where Self: PyObjectGetAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __setattr__(&'p self, py: Python<'p>, name: Self::Name, value: Self::Value)
|
||||
fn __setattr__(&'p mut self, py: Python<'p>, name: Self::Name, value: Self::Value)
|
||||
-> Self::Result where Self: PyObjectSetAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __delattr__(&'p self, py: Python<'p>, name: Self::Name)
|
||||
fn __delattr__(&'p mut self, py: Python<'p>, name: Self::Name)
|
||||
-> Self::Result where Self: PyObjectDelAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __str__(&'p self, py: Python<'p>)
|
||||
|
|
|
@ -16,10 +16,10 @@ use callback::PyObjectCallbackConverter;
|
|||
/// Iterator protocol
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyIterProtocol<'p> : PyTypeInfo {
|
||||
fn __iter__(&'p self, py: Python<'p>)
|
||||
fn __iter__(&'p mut self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyIterIterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __next__(&'p self, py: Python<'p>)
|
||||
fn __next__(&'p mut self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyIterNextProtocol<'p> { unimplemented!() }
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ macro_rules! py_unary_func {
|
|||
let ret = $crate::std::panic::catch_unwind(|| {
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let mut slf = $crate::Py::<T>::from_borrowed_ptr(py, slf);
|
||||
let res = slf.$f(py).into();
|
||||
let res = slf.as_mut().$f(py).into();
|
||||
|
||||
match res {
|
||||
Ok(val) => {
|
||||
|
@ -131,7 +131,7 @@ macro_rules! py_binary_func{
|
|||
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => {
|
||||
slf.$f(py, arg).into()
|
||||
slf.as_mut().$f(py, arg).into()
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
@ -164,6 +164,56 @@ macro_rules! py_binary_func{
|
|||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_binary_self_func{
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
let guard = $crate::callback::AbortOnDrop(LOCATION);
|
||||
let ret = $crate::std::panic::catch_unwind(|| {
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let mut slf1 = $crate::Py::<T>::from_borrowed_ptr(py, slf);
|
||||
let arg = $crate::PyObject::from_borrowed_ptr(py, arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => {
|
||||
slf1.as_mut().$f(py, arg).into()
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
slf
|
||||
}
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let ret = match ret {
|
||||
Ok(r) => r,
|
||||
Err(ref err) => {
|
||||
$crate::callback::handle_panic($crate::Python::assume_gil_acquired(), err);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
};
|
||||
$crate::mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_ssizearg_func {
|
||||
|
@ -180,7 +230,7 @@ macro_rules! py_ssizearg_func {
|
|||
let py = $crate::Python::assume_gil_acquired();
|
||||
let mut slf = $crate::Py::<T>::from_borrowed_ptr(py, slf);
|
||||
|
||||
let result = slf.$f(py, arg as isize).into();
|
||||
let result = slf.as_mut().$f(py, arg as isize).into();
|
||||
match result {
|
||||
Ok(val) => {
|
||||
<$conv as $crate::callback::CallbackConverter<$res_type>>
|
||||
|
@ -232,7 +282,7 @@ macro_rules! py_ternary_func{
|
|||
|
||||
let result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf.$f(py, arg1, arg2).into(),
|
||||
Ok(arg2) => slf.as_mut().$f(py, arg1, arg2).into(),
|
||||
Err(e) => Err(e.into())
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
|
@ -268,6 +318,58 @@ macro_rules! py_ternary_func{
|
|||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! py_ternary_self_func{
|
||||
($trait:ident, $class:ident :: $f:ident) => {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject)
|
||||
-> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
let guard = $crate::callback::AbortOnDrop(LOCATION);
|
||||
let ret = $crate::std::panic::catch_unwind(|| {
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let mut slf1 = $crate::Py::<T>::from_borrowed_ptr(py, slf);
|
||||
let arg1 = $crate::PyObject::from_borrowed_ptr(py, arg1);
|
||||
let arg2 = $crate::PyObject::from_borrowed_ptr(py, arg2);
|
||||
|
||||
let result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf1.as_mut().$f(py, arg1, arg2).into(),
|
||||
Err(e) => Err(e.into())
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(_) => slf,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let ret = match ret {
|
||||
Ok(r) => r,
|
||||
Err(ref err) => {
|
||||
$crate::callback::handle_panic(
|
||||
$crate::Python::assume_gil_acquired(), err);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
};
|
||||
$crate::mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
||||
Some(wrap::<T>)
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
|
@ -336,7 +438,7 @@ macro_rules! py_func_del{
|
|||
let name = PyObject::from_borrowed_ptr(py, name);
|
||||
let result = match name.extract() {
|
||||
Ok(name) =>
|
||||
slf.$f(py, name).into(),
|
||||
slf.as_mut().$f(py, name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
|
@ -394,7 +496,7 @@ macro_rules! py_func_set_del{
|
|||
if value.is_null() {
|
||||
let result = match name.extract() {
|
||||
Ok(name) =>
|
||||
slf.$f2(py, name).into(),
|
||||
slf.as_mut().$f2(py, name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
|
@ -410,7 +512,7 @@ macro_rules! py_func_set_del{
|
|||
let result = match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
Ok(value) => {
|
||||
slf.$f(py, name, value).into()
|
||||
slf.as_mut().$f(py, name, value).into()
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
|
|
|
@ -23,10 +23,10 @@ pub trait PyMappingProtocol<'p>: PyTypeInfo + Sized + 'static {
|
|||
fn __getitem__(&'p self, py: Python<'p>, key: Self::Key)
|
||||
-> Self::Result where Self: PyMappingGetItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __setitem__(&'p self, py: Python<'p>, key: Self::Key, value: Self::Value)
|
||||
fn __setitem__(&'p mut self, py: Python<'p>, key: Self::Key, value: Self::Value)
|
||||
-> Self::Result where Self: PyMappingSetItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __delitem__(&'p self, py: Python<'p>, key: Self::Key)
|
||||
fn __delitem__(&'p mut self, py: Python<'p>, key: Self::Key)
|
||||
-> Self::Result where Self: PyMappingDelItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __iter__(&'p self, py: Python<'p>)
|
||||
|
|
|
@ -74,31 +74,31 @@ pub trait PyNumberProtocol<'p>: PyTypeInfo {
|
|||
fn __ror__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberROrProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __iadd__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __iadd__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIAddProtocol<'p> { unimplemented!() }
|
||||
fn __isub__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __isub__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberISubProtocol<'p> { unimplemented!() }
|
||||
fn __imul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __imul__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIMulProtocol<'p> { unimplemented!() }
|
||||
fn __imatmul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __imatmul__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIMatmulProtocol<'p> { unimplemented!() }
|
||||
fn __itruediv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __itruediv__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberITruedivProtocol<'p> {unimplemented!()}
|
||||
fn __ifloordiv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __ifloordiv__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIFloordivProtocol<'p> {unimplemented!() }
|
||||
fn __imod__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __imod__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIModProtocol<'p> { unimplemented!() }
|
||||
fn __ipow__(&'p self, py: Python<'p>, other: Self::Other, modulo: Self::Modulo)
|
||||
fn __ipow__(&'p mut self, py: Python<'p>, other: Self::Other, modulo: Self::Modulo)
|
||||
-> Self::Result where Self: PyNumberIPowProtocol<'p> { unimplemented!() }
|
||||
fn __ilshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __ilshift__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberILShiftProtocol<'p> { unimplemented!() }
|
||||
fn __irshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __irshift__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIRShiftProtocol<'p> { unimplemented!() }
|
||||
fn __iand__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __iand__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIAndProtocol<'p> { unimplemented!() }
|
||||
fn __ixor__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __ixor__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIXorProtocol<'p> { unimplemented!() }
|
||||
fn __ior__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __ior__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIOrProtocol<'p> { unimplemented!() }
|
||||
|
||||
// Unary arithmetic
|
||||
|
@ -124,12 +124,12 @@ pub trait PyNumberProtocol<'p>: PyTypeInfo {
|
|||
|
||||
|
||||
pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: for<'a> FromPyObject<'a>;
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
pub trait PyNumberSubProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: for<'a> FromPyObject<'a>;
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
@ -270,74 +270,60 @@ pub trait PyNumberROrProtocol<'p>: PyNumberProtocol<'p> {
|
|||
|
||||
pub trait PyNumberIAddProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberISubProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIMulProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIMatmulProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberITruedivProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIFloordivProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIModProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Modulo: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberILShiftProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIRShiftProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIAndProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIXorProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
pub trait PyNumberIOrProtocol<'p>: PyNumberProtocol<'p> {
|
||||
type Other: FromPyObject<'p>;
|
||||
type Success: ToPyObject;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
type Result: Into<PyResult<()>>;
|
||||
}
|
||||
|
||||
pub trait PyNumberNegProtocol<'p>: PyNumberProtocol<'p> {
|
||||
|
@ -689,8 +675,7 @@ impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIAddProtocolImpl for T where T: for<'p> PyNumberIAddProtocol<'p> {
|
||||
fn nb_inplace_add() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIAddProtocol,
|
||||
T::__iadd__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIAddProtocol, T::__iadd__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -702,8 +687,7 @@ impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberISubProtocolImpl for T where T: for<'p> PyNumberISubProtocol<'p> {
|
||||
fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberISubProtocol,
|
||||
T::__isub__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberISubProtocol, T::__isub__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,8 +699,7 @@ impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIMulProtocolImpl for T where T: for<'p> PyNumberIMulProtocol<'p> {
|
||||
fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIMulProtocol,
|
||||
T::__imul__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIMulProtocol, T::__imul__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,8 +711,7 @@ impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIMatmulProtocolImpl for T where T: for<'p> PyNumberIMatmulProtocol<'p> {
|
||||
fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIMatmulProtocol,
|
||||
T::__imatmul__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIMatmulProtocol, T::__imatmul__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,8 +723,7 @@ impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberITruedivProtocolImpl for T where T: for<'p> PyNumberITruedivProtocol<'p> {
|
||||
fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberITruedivProtocol,
|
||||
T::__itruediv__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberITruedivProtocol, T::__itruediv__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,8 +735,7 @@ impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIFloordivProtocolImpl for T where T: for<'p> PyNumberIFloordivProtocol<'p> {
|
||||
fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIFloordivProtocol,
|
||||
T::__ifloordiv__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIFloordivProtocol, T::__ifloordiv__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -767,8 +747,7 @@ impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIModProtocolImpl for T where T: for<'p> PyNumberIModProtocol<'p> {
|
||||
fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIModProtocol,
|
||||
T::__imod__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIModProtocol, T::__imod__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,8 +759,7 @@ impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIPowProtocolImpl for T where T: for<'p> PyNumberIPowProtocol<'p> {
|
||||
fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
|
||||
py_ternary_func!(PyNumberIPowProtocol,
|
||||
T::__ipow__, T::Success, PyObjectCallbackConverter)
|
||||
py_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,8 +771,7 @@ impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberILShiftProtocolImpl for T where T: for<'p> PyNumberILShiftProtocol<'p> {
|
||||
fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberILShiftProtocol,
|
||||
T::__ilshift__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberILShiftProtocol, T::__ilshift__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -806,8 +783,7 @@ impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIRShiftProtocolImpl for T where T: for<'p> PyNumberIRShiftProtocol<'p> {
|
||||
fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIRShiftProtocol,
|
||||
T::__irshift__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIRShiftProtocol, T::__irshift__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -820,8 +796,7 @@ impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIAndProtocolImpl for T where T: for<'p> PyNumberIAndProtocol<'p> {
|
||||
fn nb_inplace_and() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIAndProtocol,
|
||||
T::__iand__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIAndProtocol, T::__iand__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,8 +808,7 @@ impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIXorProtocolImpl for T where T: for<'p> PyNumberIXorProtocol<'p> {
|
||||
fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIXorProtocol,
|
||||
T::__ixor__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIXorProtocol, T::__ixor__)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -846,8 +820,7 @@ impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {
|
|||
}
|
||||
impl<T> PyNumberIOrProtocolImpl for T where T: for<'p> PyNumberIOrProtocol<'p> {
|
||||
fn nb_inplace_or() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PyNumberIOrProtocol,
|
||||
T::__ior__, T::Success, PyObjectCallbackConverter)
|
||||
py_binary_self_func!(PyNumberIOrProtocol, T::__ior__)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@ pub trait PySequenceProtocol<'p>: PyTypeInfo + Sized + 'static {
|
|||
fn __getitem__(&'p self, py: Python<'p>, key: isize) -> Self::Result
|
||||
where Self: PySequenceGetItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __setitem__(&'p self, py: Python<'p>, key: isize, value: Self::Value) -> Self::Result
|
||||
fn __setitem__(&'p mut self, py: Python<'p>, key: isize, value: Self::Value) -> Self::Result
|
||||
where Self: PySequenceSetItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __delitem__(&'p self, py: Python<'p>, key: isize) -> Self::Result
|
||||
fn __delitem__(&'p mut self, py: Python<'p>, key: isize) -> Self::Result
|
||||
where Self: PySequenceDelItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __contains__(&'p self, py: Python<'p>, item: Self::Item) -> Self::Result
|
||||
|
@ -38,10 +38,10 @@ pub trait PySequenceProtocol<'p>: PyTypeInfo + Sized + 'static {
|
|||
fn __repeat__(&'p self, py: Python<'p>, count: isize) -> Self::Result
|
||||
where Self: PySequenceRepeatProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __inplace_concat__(&'p self, py: Python<'p>, other: Self::Other) -> Self::Result
|
||||
fn __inplace_concat__(&'p mut self, py: Python<'p>, other: Self::Other) -> Self::Result
|
||||
where Self: PySequenceInplaceConcatProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __inplace_repeat__(&'p self, py: Python<'p>, count: isize) -> Self::Result
|
||||
fn __inplace_repeat__(&'p mut self, py: Python<'p>, count: isize) -> Self::Result
|
||||
where Self: PySequenceInplaceRepeatProtocol<'p> { unimplemented!() }
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ pub trait IntoPyObject {
|
|||
#[inline]
|
||||
fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject>
|
||||
where Self: Sized;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,7 +99,7 @@ impl <'p, T: ?Sized> RefFromPyObject<'p> for T
|
|||
}
|
||||
|
||||
// Default IntoPyObject implementation
|
||||
impl <T> IntoPyObject for T where T: ToPyObject
|
||||
impl<T> IntoPyObject for T where T: ToPyObject
|
||||
{
|
||||
#[inline]
|
||||
default fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject> where Self: Sized
|
||||
|
@ -139,7 +138,7 @@ impl <T> ToPyObject for Option<T> where T: ToPyObject {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T> IntoPyObject for Option<T> where T: IntoPyObject {
|
||||
impl<T> IntoPyObject for Option<T> where T: IntoPyObject {
|
||||
|
||||
fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
match self {
|
||||
|
|
|
@ -69,9 +69,9 @@ pub use pyptr::{Py, PyPtr};
|
|||
|
||||
pub use err::{PyErr, PyResult, PyDowncastError};
|
||||
pub use objects::*;
|
||||
pub use python::{AsPy, Python};
|
||||
pub use python::{AsPy, Python, PythonToken};
|
||||
pub use pythonrun::{GILGuard, GILProtected, prepare_freethreaded_python};
|
||||
pub use conversion::{FromPyObject, /*RefFromPyObject,*/ ToPyObject, IntoPyObject, ToPyTuple};
|
||||
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, ToPyTuple};
|
||||
pub use class::{CompareOp};
|
||||
pub mod class;
|
||||
pub use class::*;
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
// Copyright (c) 2015 Daniel Grunwald
|
||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use std::fmt;
|
||||
use std::cmp::Ordering;
|
||||
|
@ -303,7 +289,6 @@ impl<T> fmt::Display for PyPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std;
|
||||
|
|
|
@ -22,22 +22,22 @@ macro_rules! pyobject_newtype(
|
|||
|
||||
impl<'p> $crate::python::AsPy<'p> for &'p $name {
|
||||
#[inline]
|
||||
fn py<'a>(&'a self) -> Python<'p> {
|
||||
fn py<'a>(&'a self) -> $crate::Python<'p> {
|
||||
unsafe { $crate::python::Python::assume_gil_acquired() }
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::python::ToPythonPointer for $name {
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self as *const _ as *mut ffi::PyObject
|
||||
fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
|
||||
self as *const _ as *mut $crate::ffi::PyObject
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::python::ToPythonPointer for &'a $name {
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self as *const _ as *mut ffi::PyObject
|
||||
fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
|
||||
self as *const _ as *mut $crate::ffi::PyObject
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,32 @@ macro_rules! pyobject_newtype(
|
|||
unsafe { &mut $crate::ffi::$typeobject }
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::std::fmt::Debug for $name {
|
||||
default fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let py = unsafe { $crate::python::Python::assume_gil_acquired() };
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_nullptr(
|
||||
py, $crate::ffi::PyObject_Repr(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let repr_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let py = unsafe { $crate::python::Python::assume_gil_acquired() };
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_nullptr(
|
||||
py, $crate::ffi::PyObject_Str(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let str_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&str_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
|
|
27
src/pyptr.rs
27
src/pyptr.rs
|
@ -20,6 +20,26 @@ pub struct PyPtr<T> {
|
|||
}
|
||||
|
||||
impl<T> PyPtr<T> {
|
||||
/// Creates a PyPtr instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the Py.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyPtr<T> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
PyPtr {inner: ptr, _t: PhantomData}
|
||||
}
|
||||
|
||||
/// Creates a PyPTr instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
/// Caller of this method has to have valid Py object.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyPtr<T> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
PyPtr {inner: ptr, _t: PhantomData}
|
||||
}
|
||||
|
||||
pub fn as_ref<'p>(&self, _py: Python<'p>) -> Py<'p, T> {
|
||||
Py{inner: self.inner, _t: PhantomData, _py: PhantomData}
|
||||
}
|
||||
|
@ -56,7 +76,6 @@ impl<T> IntoPythonPointer for PyPtr<T> {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
println!("INTO PTR: {:?}", self.inner);
|
||||
let ptr = self.inner;
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
|
@ -206,7 +225,7 @@ impl<'p, T> Py<'p, T>
|
|||
impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
||||
{
|
||||
/// Create new python object and move T instance under python management
|
||||
pub fn new(py: &Python<'p>, value: T) -> PyResult<Py<'p, T>> where T: PyObjectAlloc<Type=T>
|
||||
pub fn new(py: Python<'p>, value: T) -> PyResult<Py<'p, T>> where T: PyObjectAlloc<Type=T>
|
||||
{
|
||||
let ob = unsafe {
|
||||
try!(<T as PyObjectAlloc>::alloc(py, value))
|
||||
|
@ -463,10 +482,10 @@ impl <'a, T> ToPyObject for Py<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <'a, T> IntoPyObject for Py<'a, T> {
|
||||
impl<'p, T> IntoPyObject for Py<'p, T> {
|
||||
|
||||
#[inline]
|
||||
default fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
default fn into_object<'a>(self, py: Python<'a>) -> Py<'a, PyObject> {
|
||||
PyObject::from_borrowed_ptr(py, self.inner)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
// Copyright (c) 2015 Daniel Grunwald
|
||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use std;
|
||||
use std::ffi::CString;
|
||||
|
@ -42,11 +28,19 @@ use pythonrun::GILGuard;
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
||||
|
||||
pub struct PythonToken<T>(PhantomData<T>);
|
||||
|
||||
|
||||
pub trait AsPy<'p> {
|
||||
fn py<'a>(&'a self) -> Python<'p>;
|
||||
}
|
||||
|
||||
|
||||
pub trait PyClone : Sized {
|
||||
fn clone_ref(&self) -> PyPtr<Self>;
|
||||
}
|
||||
|
||||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
pub trait ToPythonPointer {
|
||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||
|
@ -55,7 +49,8 @@ pub trait ToPythonPointer {
|
|||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
pub trait IntoPythonPointer {
|
||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||
/// Retrieves the underlying FFI pointer. Whether pointer owned or borrowed
|
||||
/// depends on implementation.
|
||||
fn into_ptr(self) -> *mut ffi::PyObject;
|
||||
}
|
||||
|
||||
|
@ -82,6 +77,7 @@ impl <T> IntoPythonPointer for Option<T> where T: IntoPythonPointer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
|
||||
/// and stays acquired for the lifetime `'p`.
|
||||
|
@ -169,14 +165,6 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create new PyObject instance
|
||||
#[inline]
|
||||
pub fn init<T>(&'p self, value: T) -> Py<'p, T>
|
||||
where T: PyTypeInfo + PyObjectAlloc<Type=T>
|
||||
{
|
||||
Py::new(self, value).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `None`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
|
@ -219,8 +207,69 @@ impl<'p> Python<'p> {
|
|||
pub fn import(self, name : &str) -> PyResult<Py<'p, PyModule>> {
|
||||
PyModule::import(self, name)
|
||||
}
|
||||
|
||||
pub fn with_token<T, F>(self, f: F) -> Py<'p, T>
|
||||
where F: FnOnce(PythonToken<T>) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<Type=T>
|
||||
{
|
||||
let value = f(PythonToken(PhantomData));
|
||||
Py::new(self, value).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PythonToken<T> {
|
||||
|
||||
/// Gets the Python builtin value `None`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn None(self) -> PyPtr<PyObject> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_None()) }
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `True`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn True(self) -> PyPtr<PyBool> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_True()) }
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `False`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn False(self) -> PyPtr<PyBool> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_False()) }
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `NotImplemented`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn NotImplemented(self) -> PyPtr<PyObject> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_NotImplemented()) }
|
||||
}
|
||||
|
||||
/// Gets the Python type object for type T.
|
||||
pub fn get_type<U>(self) -> PyPtr<PyType> where U: PyTypeObject {
|
||||
U::type_object(Python(PhantomData)).into_pptr()
|
||||
}
|
||||
|
||||
/// Execute closure `F` with Python instance.
|
||||
/// Retrieve Python instance under the assumption that the GIL is already acquired
|
||||
/// at this point, and stays acquired during closure call.
|
||||
pub fn with_py<'p, F>(self, f: F) where F: FnOnce(Python<'p>)
|
||||
{
|
||||
f(Python(PhantomData))
|
||||
}
|
||||
|
||||
pub fn with_token<P, F>(self, f: F) -> PyPtr<P>
|
||||
where F: FnOnce(PythonToken<P>) -> P,
|
||||
P: PyTypeInfo + PyObjectAlloc<Type=P>
|
||||
{
|
||||
let value = f(PythonToken(PhantomData));
|
||||
Py::new(Python(PhantomData), value).unwrap().into_pptr()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use {Python, PyDict};
|
||||
|
|
|
@ -92,12 +92,12 @@ pub trait PyObjectAlloc {
|
|||
/// and initializes it using init_val.
|
||||
/// `ty` must be derived from the Self type, and the resulting object
|
||||
/// must be of type `ty`.
|
||||
unsafe fn alloc(_py: &Python, value: Self::Type) -> PyResult<*mut ffi::PyObject>;
|
||||
unsafe fn alloc(_py: Python, value: Self::Type) -> PyResult<*mut ffi::PyObject>;
|
||||
|
||||
/// Calls the rust destructor for the object and frees the memory
|
||||
/// (usually by calling ptr->ob_type->tp_free).
|
||||
/// This function is used as tp_dealloc implementation.
|
||||
unsafe fn dealloc(_py: &Python, obj: *mut ffi::PyObject);
|
||||
unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject);
|
||||
}
|
||||
|
||||
/// A PythonObject that is usable as a base type for #[class]
|
||||
|
@ -108,7 +108,7 @@ impl<T> PyObjectAlloc for T where T : PyTypeInfo {
|
|||
/// and initializes it using init_val.
|
||||
/// `ty` must be derived from the Self type, and the resulting object
|
||||
/// must be of type `ty`.
|
||||
unsafe fn alloc(_py: &Python, value: T::Type) -> PyResult<*mut ffi::PyObject> {
|
||||
unsafe fn alloc(_py: Python, value: T::Type) -> PyResult<*mut ffi::PyObject> {
|
||||
let obj = ffi::PyType_GenericAlloc(
|
||||
<Self as PyTypeInfo>::type_object(), 0);
|
||||
|
||||
|
@ -122,7 +122,7 @@ impl<T> PyObjectAlloc for T where T : PyTypeInfo {
|
|||
/// Calls the rust destructor for the object and frees the memory
|
||||
/// (usually by calling ptr->ob_type->tp_free).
|
||||
/// This function is used as tp_dealloc implementation.
|
||||
unsafe fn dealloc(_py: &Python, obj: *mut ffi::PyObject) {
|
||||
unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
||||
let ptr = (obj as *mut u8).offset(
|
||||
<Self as PyTypeInfo>::offset() as isize) as *mut Self::Type;
|
||||
std::ptr::drop_in_place(ptr);
|
||||
|
@ -296,7 +296,7 @@ unsafe extern "C" fn tp_dealloc_callback<T>(obj: *mut ffi::PyObject)
|
|||
println!("DEALLOC: {:?}", obj);
|
||||
let guard = AbortOnDrop("Cannot unwind out of tp_dealloc");
|
||||
let py = Python::assume_gil_acquired();
|
||||
let r = <T as PyObjectAlloc>::dealloc(&py, obj);
|
||||
let r = <T as PyObjectAlloc>::dealloc(py, obj);
|
||||
mem::forget(guard);
|
||||
r
|
||||
}
|
||||
|
@ -329,24 +329,24 @@ fn py_class_method_defs<T>() -> (Option<ffi::newfunc>,
|
|||
}
|
||||
}
|
||||
|
||||
for def in <T as class::basic::PyObjectProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::async::PyAsyncProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::context::PyContextProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::mapping::PyMappingProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::number::PyNumberProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::descr::PyDescrProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def())
|
||||
}
|
||||
//for def in <T as class::basic::PyObjectProtocolImpl>::methods() {
|
||||
// defs.push(def.as_method_def())
|
||||
//}
|
||||
//for def in <T as class::async::PyAsyncProtocolImpl>::methods() {
|
||||
// defs.push(def.as_method_def())
|
||||
//}
|
||||
//for def in <T as class::context::PyContextProtocolImpl>::methods() {
|
||||
// defs.push(def.as_method_def())
|
||||
//}
|
||||
//for def in <T as class::mapping::PyMappingProtocolImpl>::methods() {
|
||||
//defs.push(def.as_method_def())
|
||||
//}
|
||||
//for def in <T as class::number::PyNumberProtocolImpl>::methods() {
|
||||
// defs.push(def.as_method_def())
|
||||
//}
|
||||
//for def in <T as class::descr::PyDescrProtocolImpl>::methods() {
|
||||
// defs.push(def.as_method_def())
|
||||
//}
|
||||
|
||||
(new, call, defs)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ use std::cell::RefCell;
|
|||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use pyo3::ffi;
|
||||
use pyo3::python::ToPythonPointer;
|
||||
|
||||
|
||||
macro_rules! py_run {
|
||||
($py:expr, $val:ident, $code:expr) => {{
|
||||
|
@ -26,7 +28,7 @@ macro_rules! py_assert {
|
|||
macro_rules! py_expect_exception {
|
||||
($py:expr, $val:ident, $code:expr, $err:ident) => {{
|
||||
let d = PyDict::new($py);
|
||||
d.set_item($py, stringify!($val), &$val).unwrap();
|
||||
d.set_item(stringify!($val), &$val).unwrap();
|
||||
let res = $py.run($code, None, Some(&d));
|
||||
let err = res.unwrap_err();
|
||||
if !err.matches($py, $py.get_type::<exc::$err>()) {
|
||||
|
@ -71,7 +73,7 @@ struct EmptyClassWithNew { }
|
|||
#[py::methods]
|
||||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(cls: &PyType) -> PyResult<EmptyClassWithNew> {
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<EmptyClassWithNew> {
|
||||
Ok(EmptyClassWithNew{})
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +93,7 @@ struct NewWithOneArg {
|
|||
#[py::methods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, arg: i32) -> PyResult<NewWithOneArg> {
|
||||
fn __new__(_cls: &PyType, py: Python, arg: i32) -> PyResult<NewWithOneArg> {
|
||||
Ok(NewWithOneArg{_data: arg})
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +116,7 @@ struct NewWithTwoArgs {
|
|||
#[py::methods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, arg1: i32, arg2: i32) -> PyResult<NewWithTwoArgs> {
|
||||
fn __new__(_cls: &PyType, py: Python, arg1: i32, arg2: i32) -> PyResult<NewWithTwoArgs> {
|
||||
Ok(NewWithTwoArgs{_data1: arg1, _data2: arg2})
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +171,7 @@ struct InstanceMethod {
|
|||
|
||||
#[py::methods]
|
||||
impl InstanceMethod {
|
||||
fn method(&self) -> PyResult<i32> {
|
||||
fn method(&self, py: Python) -> PyResult<i32> {
|
||||
Ok(self.member)
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +182,7 @@ fn instance_method() {
|
|||
let py = gil.python();
|
||||
|
||||
let obj = py.init(InstanceMethod{member: 42});
|
||||
assert!(obj.method().unwrap() == 42);
|
||||
assert!(obj.method(py).unwrap() == 42);
|
||||
let d = PyDict::new(py);
|
||||
d.set_item("obj", obj).unwrap();
|
||||
py.run("assert obj.method() == 42", None, Some(&d)).unwrap();
|
||||
|
@ -192,7 +194,7 @@ struct InstanceMethodWithArgs {
|
|||
}
|
||||
#[py::methods]
|
||||
impl InstanceMethodWithArgs {
|
||||
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
||||
fn method(&self, py: Python, multiplier: i32) -> PyResult<i32> {
|
||||
Ok(self.member * multiplier)
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +205,7 @@ fn instance_method_with_args() {
|
|||
let py = gil.python();
|
||||
|
||||
let obj = py.init(InstanceMethodWithArgs{member: 7});
|
||||
assert!(obj.method(6).unwrap() == 42);
|
||||
assert!(obj.method(py, 6).unwrap() == 42);
|
||||
let d = PyDict::new(py);
|
||||
d.set_item("obj", obj).unwrap();
|
||||
py.run("assert obj.method(3) == 21", None, Some(&d)).unwrap();
|
||||
|
@ -261,7 +263,7 @@ struct StaticMethod {}
|
|||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<StaticMethod> {
|
||||
StaticMethod::create_instance(py)
|
||||
Ok(StaticMethod{}.into_object(py))
|
||||
}
|
||||
|
||||
//#[staticmethod]
|
||||
|
@ -303,18 +305,18 @@ impl StaticMethod {
|
|||
|
||||
#[py::class]
|
||||
struct GCIntegration {
|
||||
self_ref: RefCell<PyObject>,
|
||||
self_ref: RefCell<PyPtr<PyObject>>,
|
||||
dropped: TestDropCall,
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyGCProtocol for GCIntegration {
|
||||
fn __traverse__(&self, py: Python, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
visit.call(&*self.self_ref(py).borrow())
|
||||
visit.call(&*self.self_ref.borrow())
|
||||
}
|
||||
|
||||
fn __clear__(&self, py: Python) {
|
||||
let old_ref = mem::replace(&mut *self.self_ref(py).borrow_mut(), py.None());
|
||||
fn __clear__(&mut self, py: Python) {
|
||||
let old_ref = mem::replace(&mut *self.self_ref.borrow_mut(), py.None());
|
||||
// Release reference only after the mutable borrow has expired.
|
||||
old_ref.release_ref(py);
|
||||
}
|
||||
|
@ -326,12 +328,12 @@ fn gc_integration() {
|
|||
let py = gil.python();
|
||||
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
let inst = GCIntegration::create_instance(py,
|
||||
RefCell::new(py.None()),
|
||||
TestDropCall { drop_called: drop_called.clone() }
|
||||
).unwrap();
|
||||
*inst.self_ref(py).borrow_mut() = inst.as_object().clone_ref(py);
|
||||
inst.release_ref(py);
|
||||
let inst = py.init(GCIntegration{
|
||||
self_ref: RefCell::new(py.None()),
|
||||
dropped: TestDropCall { drop_called: drop_called.clone() }});
|
||||
|
||||
*inst.self_ref.borrow_mut() = inst.clone_ref().into_object().into_pptr();
|
||||
drop(inst);
|
||||
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
|
@ -345,7 +347,7 @@ pub struct Len {
|
|||
#[py::proto]
|
||||
impl PyMappingProtocol for Len {
|
||||
fn __len__(&self, py: Python) -> PyResult<usize> {
|
||||
Ok(*self.l(py))
|
||||
Ok(self.l)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,14 +356,14 @@ fn len() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let inst = Len::create_instance(py, 10).unwrap();
|
||||
let inst = Len{l: 10}.into_object(py);
|
||||
py_assert!(py, inst, "len(inst) == 10");
|
||||
unsafe {
|
||||
assert_eq!(ffi::PyObject_Size(inst.as_object().as_ptr()), 10);
|
||||
assert_eq!(ffi::PyMapping_Size(inst.as_object().as_ptr()), 10);
|
||||
assert_eq!(ffi::PyObject_Size(inst.as_ptr()), 10);
|
||||
assert_eq!(ffi::PyMapping_Size(inst.as_ptr()), 10);
|
||||
}
|
||||
|
||||
let inst = Len::create_instance(py, (isize::MAX as usize) + 1).unwrap();
|
||||
let inst = Len{l: (isize::MAX as usize) + 1}.into_object(py);
|
||||
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
||||
}
|
||||
|
||||
|
@ -391,16 +393,16 @@ fn iterator() {
|
|||
struct StringMethods {}
|
||||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for StringMethods {
|
||||
fn __str__(&self) -> PyResult<&'static str> {
|
||||
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
||||
fn __str__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("str")
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("repr")
|
||||
}
|
||||
|
||||
fn __format__(&self, format_spec: String) -> PyResult<String> {
|
||||
fn __format__(&self, py: Python, format_spec: String) -> PyResult<String> {
|
||||
Ok(format!("format({})", format_spec))
|
||||
}
|
||||
|
||||
|
@ -408,7 +410,7 @@ impl PyObjectProtocol for StringMethods {
|
|||
// Ok(PyString::new(py, "unicode"))
|
||||
//}
|
||||
|
||||
fn __bytes__(&self) -> PyResult<PyBytes> {
|
||||
fn __bytes__(&self, py: Python) -> PyResult<Py<PyBytes>> {
|
||||
Ok(PyBytes::new(py, b"bytes"))
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +420,7 @@ fn string_methods() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = StringMethods::create_instance(py).unwrap();
|
||||
let obj = StringMethods{}.into_object(py);
|
||||
py_assert!(py, obj, "str(obj) == 'str'");
|
||||
py_assert!(py, obj, "repr(obj) == 'repr'");
|
||||
py_assert!(py, obj, "'{0:x}'.format(obj) == 'format(x)'");
|
||||
|
@ -433,12 +435,12 @@ struct Comparisons {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for Comparisons {
|
||||
fn __hash__(&self) -> PyResult<usize> {
|
||||
Ok(*self.val(py) as usize)
|
||||
fn __hash__(&self, py: Python) -> PyResult<usize> {
|
||||
Ok(self.val as usize)
|
||||
}
|
||||
|
||||
fn __bool__(&self) -> PyResult<bool> {
|
||||
Ok(*self.val(py) != 0)
|
||||
fn __bool__(&self, py: Python) -> PyResult<bool> {
|
||||
Ok(self.val != 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,10 +450,10 @@ fn comparisons() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let zero = Comparisons::create_instance(py, 0).unwrap();
|
||||
let one = Comparisons::create_instance(py, 1).unwrap();
|
||||
let ten = Comparisons::create_instance(py, 10).unwrap();
|
||||
let minus_one = Comparisons::create_instance(py, -1).unwrap();
|
||||
let zero = Comparisons{val: 0}.into_object(py);
|
||||
let one = Comparisons{val: 1}.into_object(py);
|
||||
let ten = Comparisons{val: 10}.into_object(py);
|
||||
let minus_one = Comparisons{val: -1}.into_object(py);
|
||||
py_assert!(py, one, "hash(one) == 1");
|
||||
py_assert!(py, ten, "hash(ten) == 10");
|
||||
py_assert!(py, minus_one, "hash(minus_one) == -2");
|
||||
|
@ -466,11 +468,11 @@ struct Sequence {}
|
|||
|
||||
#[py::proto]
|
||||
impl PySequenceProtocol for Sequence {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
fn __len__(&self, py: Python) -> PyResult<usize> {
|
||||
Ok(5)
|
||||
}
|
||||
|
||||
fn __getitem__(&self, key: isize) -> PyResult<isize> {
|
||||
fn __getitem__(&self, py: Python, key: isize) -> PyResult<isize> {
|
||||
if key == 5 {
|
||||
return Err(PyErr::new::<exc::IndexError, NoArgs>(py, NoArgs));
|
||||
}
|
||||
|
@ -483,7 +485,7 @@ fn sequence() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Sequence::create_instance(py).unwrap();
|
||||
let c = Sequence{}.into_object(py);
|
||||
py_assert!(py, c, "list(c) == [0, 1, 2, 3, 4]");
|
||||
py_expect_exception!(py, c, "c['abc']", TypeError);
|
||||
}
|
||||
|
@ -496,7 +498,7 @@ struct Callable {}
|
|||
impl Callable {
|
||||
|
||||
#[__call__]
|
||||
fn __call__(&self, arg: i32) -> PyResult<i32> {
|
||||
fn __call__(&self, py: Python, arg: i32) -> PyResult<i32> {
|
||||
Ok(arg * 6)
|
||||
}
|
||||
}
|
||||
|
@ -506,11 +508,11 @@ fn callable() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Callable::create_instance(py).unwrap();
|
||||
let c = Callable{}.into_object(py);
|
||||
py_assert!(py, c, "callable(c)");
|
||||
py_assert!(py, c, "c(7) == 42");
|
||||
|
||||
let nc = Comparisons::create_instance(py, 0).unwrap();
|
||||
let nc = Comparisons{val: 0}.into_object(py);
|
||||
py_assert!(py, nc, "not callable(nc)");
|
||||
}
|
||||
|
||||
|
@ -522,9 +524,9 @@ struct SetItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol<'a> for SetItem {
|
||||
fn __setitem__(&self, key: i32, val: i32) -> PyResult<()> {
|
||||
*self.key_mut(py) = key;
|
||||
*self.val_mut(py) = val;
|
||||
fn __setitem__(&mut self, py: Python, key: i32, val: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
self.val = val;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -534,7 +536,7 @@ fn setitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = SetItem::create_instance(0, 0).unwrap();
|
||||
let c = py.init(SetItem{key: 0, val: 0});
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(c.key, 1);
|
||||
assert_eq!(c.val, 2);
|
||||
|
@ -548,8 +550,8 @@ struct DelItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol<'a> for DelItem {
|
||||
fn __delitem__(&self, key: i32) -> PyResult<()> {
|
||||
*self.key_mut(py) = key;
|
||||
fn __delitem__(&mut self, py: Python, key: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -559,9 +561,9 @@ fn delitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = DelItem::create_instance(py, 0).unwrap();
|
||||
let c = py.init(DelItem{key:0});
|
||||
py_run!(py, c, "del c[1]");
|
||||
assert_eq!(*c.key(py), 1);
|
||||
assert_eq!(c.key, 1);
|
||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
}
|
||||
|
||||
|
@ -572,13 +574,13 @@ struct SetDelItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for SetDelItem {
|
||||
fn __setitem__(&self, key: i32, val: i32) -> PyResult<()> {
|
||||
*self.val_mut(py) = Some(val);
|
||||
fn __setitem__(&mut self, py: Python, key: i32, val: i32) -> PyResult<()> {
|
||||
self.val = Some(val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __delitem__(&self, key: i32) -> PyResult<()> {
|
||||
*self.val_mut(py) = None;
|
||||
fn __delitem__(&mut self, py: Python, key: i32) -> PyResult<()> {
|
||||
self.val = None;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -588,11 +590,11 @@ fn setdelitem() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = SetDelItem::create_instance(py, None).unwrap();
|
||||
let c = py.init(SetDelItem{val: None});
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
assert_eq!(*c.val(py), Some(2));
|
||||
assert_eq!(c.val, Some(2));
|
||||
py_run!(py, c, "del c[1]");
|
||||
assert_eq!(*c.val(py), None);
|
||||
assert_eq!(c.val, None);
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -600,7 +602,7 @@ struct Reversed {}
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for Reversed{
|
||||
fn __reversed__(&self) -> PyResult<&'static str> {
|
||||
fn __reversed__(&self, py: Python) -> PyResult<&'static str> {
|
||||
println!("__reversed__");
|
||||
Ok("I am reversed")
|
||||
}
|
||||
|
@ -611,7 +613,7 @@ fn reversed() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Reversed::create_instance(py).unwrap();
|
||||
let c = Reversed{}.into_object(py);
|
||||
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
||||
}
|
||||
|
||||
|
@ -620,7 +622,7 @@ struct Contains {}
|
|||
|
||||
#[py::proto]
|
||||
impl PySequenceProtocol for Contains {
|
||||
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
||||
fn __contains__(&self, py: Python, item: i32) -> PyResult<bool> {
|
||||
Ok(item >= 0)
|
||||
}
|
||||
}
|
||||
|
@ -630,7 +632,7 @@ fn contains() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Contains::create_instance(py).unwrap();
|
||||
let c = Contains{}.into_object(py);
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", TypeError);
|
||||
|
@ -644,19 +646,19 @@ struct UnaryArithmetic {}
|
|||
#[py::proto]
|
||||
impl PyNumberProtocol for UnaryArithmetic {
|
||||
|
||||
fn __neg__(&self) -> PyResult<&'static str> {
|
||||
fn __neg__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("neg")
|
||||
}
|
||||
|
||||
fn __pos__(&self) -> PyResult<&'static str> {
|
||||
fn __pos__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("pos")
|
||||
}
|
||||
|
||||
fn __abs__(&self) -> PyResult<&'static str> {
|
||||
fn __abs__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("abs")
|
||||
}
|
||||
|
||||
fn __invert__(&self) -> PyResult<&'static str> {
|
||||
fn __invert__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("invert")
|
||||
}
|
||||
}
|
||||
|
@ -666,7 +668,7 @@ fn unary_arithmetic() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = UnaryArithmetic::create_instance(py).unwrap();
|
||||
let c = UnaryArithmetic{}.into_object(py);
|
||||
py_run!(py, c, "assert -c == 'neg'");
|
||||
py_run!(py, c, "assert +c == 'pos'");
|
||||
py_run!(py, c, "assert abs(c) == 'abs'");
|
||||
|
@ -679,43 +681,43 @@ struct BinaryArithmetic {}
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for BinaryArithmetic {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyNumberProtocol for BinaryArithmetic {
|
||||
fn __add__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", self.as_object(), rhs))
|
||||
fn __add__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __sub__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} - {:?}", self.as_object(), rhs))
|
||||
fn __sub__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} - {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __mul__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} * {:?}", self.as_object(), rhs))
|
||||
fn __mul__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} * {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __lshift__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} << {:?}", self.as_object(), rhs))
|
||||
fn __lshift__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} << {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __rshift__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} >> {:?}", self.as_object(), rhs))
|
||||
fn __rshift__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} >> {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __and__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} & {:?}", self.as_object(), rhs))
|
||||
fn __and__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} & {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __xor__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} ^ {:?}", self.as_object(), rhs))
|
||||
fn __xor__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} ^ {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __or__(&self, rhs: PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} | {:?}", self.as_object(), rhs))
|
||||
fn __or__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
Ok(format!("{:?} | {:?}", self, rhs))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,7 +726,7 @@ fn binary_arithmetic() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = BinaryArithmetic::create_instance(py).unwrap();
|
||||
let c = BinaryArithmetic{}.into_object(py);
|
||||
py_run!(py, c, "assert c + c == 'BA + BA'");
|
||||
py_run!(py, c, "assert c + 1 == 'BA + 1'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + BA'");
|
||||
|
@ -751,35 +753,38 @@ struct RichComparisons {}
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for RichComparisons {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("RC")
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, other: PyObject, op: CompareOp) -> PyResult<String> {
|
||||
fn __richcmp__(&self, py: Python, other: &PyObject, op: CompareOp) -> PyResult<String> {
|
||||
match op {
|
||||
CompareOp::Lt => Ok(format!("{:?} < {:?}", self.as_object(), other)),
|
||||
CompareOp::Le => Ok(format!("{:?} <= {:?}", self.as_object(), other)),
|
||||
CompareOp::Eq => Ok(format!("{:?} == {:?}", self.as_object(), other)),
|
||||
CompareOp::Ne => Ok(format!("{:?} != {:?}", self.as_object(), other)),
|
||||
CompareOp::Gt => Ok(format!("{:?} > {:?}", self.as_object(), other)),
|
||||
CompareOp::Ge => Ok(format!("{:?} >= {:?}", self.as_object(), other))
|
||||
CompareOp::Lt => Ok(format!("{:?} < {:?}", self.__repr__(py), other)),
|
||||
CompareOp::Le => Ok(format!("{:?} <= {:?}", self.__repr__(py), other)),
|
||||
CompareOp::Eq => Ok(format!("{:?} == {:?}", self.__repr__(py), other)),
|
||||
CompareOp::Ne => Ok(format!("{:?} != {:?}", self.__repr__(py), other)),
|
||||
CompareOp::Gt => Ok(format!("{:?} > {:?}", self.__repr__(py), other)),
|
||||
CompareOp::Ge => Ok(format!("{:?} >= {:?}", self.__repr__(py), other))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
struct RichComparisons2 {}
|
||||
struct RichComparisons2 {
|
||||
py: PythonToken<RichComparisons2>
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for RichComparisons2 {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
Ok("RC2")
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, other: PyObject, op: CompareOp) -> PyResult<PyObject> {
|
||||
fn __richcmp__(&self, py: Python,
|
||||
other: &PyObject, op: CompareOp) -> PyResult<Py<PyObject>> {
|
||||
match op {
|
||||
CompareOp::Eq => Ok(true.to_py_object(py).into_object()),
|
||||
CompareOp::Ne => Ok(false.to_py_object(py).into_object()),
|
||||
CompareOp::Eq => Ok(true.to_object(py).into_object()),
|
||||
CompareOp::Ne => Ok(false.to_object(py).into_object()),
|
||||
_ => Ok(py.NotImplemented())
|
||||
}
|
||||
}
|
||||
|
@ -790,7 +795,7 @@ fn rich_comparisons() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = RichComparisons::create_instance(py).unwrap();
|
||||
let c = RichComparisons{}.into_object(py);
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
|
@ -816,7 +821,7 @@ fn rich_comparisons_python_3_type_error() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c2 = RichComparisons2::create_instance(py).unwrap();
|
||||
let c2 = RichComparisons2{}.into_object(py);
|
||||
py_expect_exception!(py, c2, "c2 < c2", TypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", TypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", TypeError);
|
||||
|
@ -844,51 +849,51 @@ struct InPlaceOperations {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for InPlaceOperations {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("IPO({:?})", self.value(py)))
|
||||
fn __repr__(&self, py: Python) -> PyResult<String> {
|
||||
Ok(format!("IPO({:?})", self.value))
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) + other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __iadd__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value + other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __isub__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) - other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __isub__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value - other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __imul__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) * other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __imul__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value * other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ilshift__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) << other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __ilshift__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value << other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __irshift__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) >> other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __irshift__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value >> other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __iand__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) & other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __iand__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value & other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ixor__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) ^ other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __ixor__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value ^ other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ior__(&self, other: u32) -> PyResult<Self> {
|
||||
*self.value_mut(py) = *self.value(py) | other;
|
||||
Ok(self.clone_ref(py))
|
||||
fn __ior__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
self.value = self.value | other;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -897,28 +902,28 @@ fn inplace_operations() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 0).unwrap();
|
||||
let c = InPlaceOperations{value: 0}.into_object(py);
|
||||
py_run!(py, c, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 10).unwrap();
|
||||
let c = InPlaceOperations{value:10}.into_object(py);
|
||||
py_run!(py, c, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 3).unwrap();
|
||||
let c = InPlaceOperations{value: 3}.into_object(py);
|
||||
py_run!(py, c, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 3).unwrap();
|
||||
let c = InPlaceOperations{value: 3}.into_object(py);
|
||||
py_run!(py, c, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 12).unwrap();
|
||||
let c = InPlaceOperations{value: 12}.into_object(py);
|
||||
py_run!(py, c, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 12).unwrap();
|
||||
let c = InPlaceOperations{value: 12}.into_object(py);
|
||||
py_run!(py, c, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 12).unwrap();
|
||||
let c = InPlaceOperations{value: 12}.into_object(py);
|
||||
py_run!(py, c, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
|
||||
let c = InPlaceOperations::create_instance(py, 12).unwrap();
|
||||
let c = InPlaceOperations{value: 12}.into_object(py);
|
||||
py_run!(py, c, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
}
|
||||
|
||||
|
@ -930,11 +935,11 @@ struct ContextManager {
|
|||
#[py::proto]
|
||||
impl<'p> PyContextProtocol<'p> for ContextManager {
|
||||
|
||||
fn __enter__(&self) -> PyResult<i32> {
|
||||
fn __enter__(&mut self, py: Python) -> PyResult<i32> {
|
||||
Ok(42)
|
||||
}
|
||||
|
||||
fn __exit__(&mut self,
|
||||
fn __exit__(&mut self, py: Python,
|
||||
ty: Option<&'p PyType>,
|
||||
value: Option<&'p PyObject>,
|
||||
traceback: Option<&'p PyObject>) -> PyResult<bool> {
|
||||
|
@ -952,17 +957,19 @@ fn context_manager() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = ContextManager::create_instance(py, false).unwrap();
|
||||
let c = py.init(ContextManager{exit_called: false});
|
||||
py_run!(py, c, "with c as x:\n assert x == 42");
|
||||
assert!(*c.exit_called(py));
|
||||
assert!(c.exit_called);
|
||||
|
||||
*c.exit_called_mut(py) = false;
|
||||
c.exit_called = false;
|
||||
py_run!(py, c, "with c as x:\n raise ValueError");
|
||||
assert!(*c.exit_called(py));
|
||||
assert!(c.exit_called);
|
||||
|
||||
*c.exit_called_mut(py) = false;
|
||||
py_expect_exception!(py, c, "with c as x:\n raise NotImplementedError", NotImplementedError);
|
||||
assert!(*c.exit_called(py));
|
||||
c.exit_called = false;
|
||||
py_expect_exception!(
|
||||
py, c, "with c as x:\n raise NotImplementedError",
|
||||
NotImplementedError);
|
||||
assert!(c.exit_called);
|
||||
}
|
||||
|
||||
|
||||
|
@ -974,17 +981,17 @@ struct ClassWithProperties {
|
|||
#[py::methods]
|
||||
impl ClassWithProperties {
|
||||
|
||||
fn get_num(&self) -> PyResult<i32> {
|
||||
Ok(*self.num(py))
|
||||
fn get_num(&self, py: Python) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
}
|
||||
|
||||
#[getter(DATA)]
|
||||
fn get_data(&self) -> PyResult<i32> {
|
||||
Ok(*self.num(py))
|
||||
fn get_data(&self, py: Python) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
}
|
||||
#[setter(DATA)]
|
||||
fn set(&self, value: i32) -> PyResult<()> {
|
||||
*self.num_mut(py) = value;
|
||||
fn set(&self, py: Python, value: i32) -> PyResult<()> {
|
||||
self.num = value;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -995,7 +1002,7 @@ fn class_with_properties() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let inst = ClassWithProperties::create_instance(py, 10).unwrap();
|
||||
let inst = ClassWithProperties{num: 10}.into_object(py);
|
||||
|
||||
py_run!(py, inst, "assert inst.get_num() == 10");
|
||||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||
|
@ -1003,4 +1010,4 @@ fn class_with_properties() {
|
|||
py_run!(py, inst, "assert inst.get_num() == 20");
|
||||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue