Merge pull request #42 from PyO3/py-ptr
Use reference for native objects
This commit is contained in:
commit
736ad15aee
|
@ -62,7 +62,6 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
-> <#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! {
|
||||
|
@ -80,13 +79,13 @@ 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() <= 1 {
|
||||
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 arg_ty = get_arg_ty(sig, 1);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
let tmp = extract_decl(syn::parse_item(
|
||||
|
@ -99,9 +98,8 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
&self,
|
||||
arg: Option<<#cls as #p<'p>>::#arg_name>)
|
||||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
modify_arg_ty(sig, 2, &tmp, &tmp2);
|
||||
modify_arg_ty(sig, 1, &tmp, &tmp2);
|
||||
modify_self_ty(sig);
|
||||
modify_py_ty(sig);
|
||||
|
||||
if pyres {
|
||||
quote! {
|
||||
|
@ -121,15 +119,15 @@ 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() <= 2 {
|
||||
print_err(format!("Not enough arguments {}", n), quote!(sig));
|
||||
return Tokens::new();
|
||||
}
|
||||
let p = syn::Ident::from(proto);
|
||||
let arg1_name = syn::Ident::from(arg1);
|
||||
let arg1_ty = get_arg_ty(sig, 2);
|
||||
let arg1_ty = get_arg_ty(sig, 1);
|
||||
let arg2_name = syn::Ident::from(arg2);
|
||||
let arg2_ty = get_arg_ty(sig, 3);
|
||||
let arg2_ty = get_arg_ty(sig, 2);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
// rewrite ty
|
||||
|
@ -145,10 +143,9 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
arg1: Option<<#cls as #p<'p>>::#arg1_name>,
|
||||
arg2: Option<<#cls as #p<'p>>::#arg2_name>)
|
||||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
modify_arg_ty(sig, 1, &tmp, &tmp2);
|
||||
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! {
|
||||
|
@ -170,17 +167,17 @@ 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() <= 3 {
|
||||
print_err(format!("Not enough arguments {}", n), quote!(sig));
|
||||
return Tokens::new();
|
||||
}
|
||||
let p = syn::Ident::from(proto);
|
||||
let arg1_name = syn::Ident::from(arg1);
|
||||
let arg1_ty = get_arg_ty(sig, 2);
|
||||
let arg1_ty = get_arg_ty(sig, 1);
|
||||
let arg2_name = syn::Ident::from(arg2);
|
||||
let arg2_ty = get_arg_ty(sig, 3);
|
||||
let arg2_ty = get_arg_ty(sig, 2);
|
||||
let arg3_name = syn::Ident::from(arg3);
|
||||
let arg3_ty = get_arg_ty(sig, 4);
|
||||
let arg3_ty = get_arg_ty(sig, 3);
|
||||
let (ty, succ) = get_res_success(ty);
|
||||
|
||||
// rewrite ty
|
||||
|
@ -198,11 +195,10 @@ pub fn impl_method_proto(cls: &Box<syn::Ty>,
|
|||
arg2: Option<<#cls as #p<'p>>::#arg2_name>,
|
||||
arg3: Option<<#cls as #p<'p>>::#arg3_name>)
|
||||
-> <#cls as #p<'p>>::Result {}}.as_str()).unwrap());
|
||||
modify_arg_ty(sig, 1, &tmp, &tmp2);
|
||||
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 {
|
||||
|
@ -338,13 +334,13 @@ fn modify_arg_ty(sig: &mut syn::MethodSig, idx: usize,
|
|||
&syn::Ty::Path(_, ref path) => {
|
||||
let seg = path.segments.last().unwrap().clone();
|
||||
if seg.ident.as_ref() == "Option" {
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl2.inputs[idx-1]);
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl2.inputs[idx]);
|
||||
} else {
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl1.inputs[idx-1]);
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl1.inputs[idx]);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl1.inputs[idx-1]);
|
||||
sig.decl.inputs[idx] = fix_name(pat, &decl1.inputs[idx]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -364,41 +360,6 @@ fn modify_self_ty(sig: &mut syn::MethodSig)
|
|||
}
|
||||
}
|
||||
|
||||
// modify Python signature
|
||||
fn modify_py_ty(sig: &mut syn::MethodSig)
|
||||
{
|
||||
if sig.decl.inputs.len() <= 1 {
|
||||
return
|
||||
}
|
||||
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) =>
|
||||
|
|
|
@ -13,6 +13,7 @@ pub struct FnArg<'a> {
|
|||
pub mode: &'a syn::BindingMode,
|
||||
pub ty: &'a syn::Ty,
|
||||
pub optional: Option<&'a syn::Ty>,
|
||||
pub py: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
|
@ -42,7 +43,6 @@ impl<'a> FnSpec<'a> {
|
|||
let (fn_type, fn_attrs) = parse_attributes(meth_attrs);
|
||||
|
||||
let mut has_self = false;
|
||||
let mut py = false;
|
||||
let mut arguments = Vec::new();
|
||||
|
||||
for input in sig.decl.inputs.iter() {
|
||||
|
@ -67,21 +67,26 @@ impl<'a> FnSpec<'a> {
|
|||
panic!("unsupported argument: {:?}", pat),
|
||||
};
|
||||
|
||||
if !py {
|
||||
match ty {
|
||||
&syn::Ty::Path(_, ref path) =>
|
||||
if let Some(segment) = path.segments.last() {
|
||||
if segment.ident.as_ref() == "Python" {
|
||||
py = true;
|
||||
continue;
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
let py = match ty {
|
||||
&syn::Ty::Path(_, ref path) =>
|
||||
if let Some(segment) = path.segments.last() {
|
||||
segment.ident.as_ref() == "Python"
|
||||
} else {
|
||||
false
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
|
||||
let opt = check_arg_ty_and_optional(name, ty);
|
||||
arguments.push(FnArg{name: ident, mode: mode, ty: ty, optional: opt});
|
||||
arguments.push(
|
||||
FnArg {
|
||||
name: ident,
|
||||
mode: mode,
|
||||
ty: ty,
|
||||
optional: opt,
|
||||
py: py,
|
||||
}
|
||||
);
|
||||
}
|
||||
&syn::FnArg::Ignored(_) =>
|
||||
panic!("ignored argument: {:?}", name),
|
||||
|
|
|
@ -45,42 +45,37 @@ pub fn py3_init(fnname: &syn::Ident, name: &String, doc: syn::Lit) -> Tokens {
|
|||
pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject {
|
||||
use std;
|
||||
extern crate pyo3 as _pyo3;
|
||||
use pyo3::IntoPyPointer;
|
||||
use pyo3::{IntoPyPointer, ObjectProtocol};
|
||||
|
||||
static mut MODULE_DEF: _pyo3::ffi::PyModuleDef = _pyo3::ffi::PyModuleDef_INIT;
|
||||
// We can't convert &'static str to *const c_char within a static initializer,
|
||||
// so we'll do it here in the module initialization:
|
||||
MODULE_DEF.m_name = concat!(stringify!(#cb_name), "\0").as_ptr() as *const _;
|
||||
|
||||
let guard = _pyo3::callback::AbortOnDrop("py_module_init");
|
||||
let py = _pyo3::Python::assume_gil_acquired();
|
||||
_pyo3::ffi::PyEval_InitThreads();
|
||||
let module = _pyo3::ffi::PyModule_Create(&mut MODULE_DEF);
|
||||
if module.is_null() {
|
||||
std::mem::forget(guard);
|
||||
return module;
|
||||
}
|
||||
_pyo3::callback::cb_meth("py_module_init", |py| {
|
||||
_pyo3::ffi::PyEval_InitThreads();
|
||||
|
||||
let module = match _pyo3::PyObject::from_owned_ptr(
|
||||
py, module).cast_into::<PyModule>(py)
|
||||
{
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
_pyo3::PyErr::from(e).restore(py);
|
||||
std::mem::forget(guard);
|
||||
return std::ptr::null_mut();
|
||||
let module = _pyo3::ffi::PyModule_Create(&mut MODULE_DEF);
|
||||
if module.is_null() {
|
||||
return module;
|
||||
}
|
||||
};
|
||||
module.add(py, "__doc__", #doc).expect("Failed to add doc for module");
|
||||
let ret = match #fnname(py, &module) {
|
||||
Ok(_) => module.into_ptr(),
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
std::ptr::null_mut()
|
||||
|
||||
let module = match py.cast_from_ptr_or_err::<_pyo3::PyModule>(module) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
_pyo3::PyErr::from(e).restore(py);
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
};
|
||||
module.add("__doc__", #doc).expect("Failed to add doc for module");
|
||||
match #fnname(py, module) {
|
||||
Ok(_) => module.into_ptr(),
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
};
|
||||
std::mem::forget(guard);
|
||||
ret
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,9 +128,7 @@ pub fn py2_init(fnname: &syn::Ident, name: &String, doc: syn::Lit) -> Tokens {
|
|||
return
|
||||
}
|
||||
|
||||
let module = match pyo3::PyObject::from_borrowed_ptr(
|
||||
py, module).cast_into::<pyo3::PyModule>(py)
|
||||
{
|
||||
let module = match py.cast_from_ptr_or_err::<_pyo3::PyModule>(module) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
_pyo3::PyErr::from(e).restore(py);
|
||||
|
@ -143,8 +136,8 @@ pub fn py2_init(fnname: &syn::Ident, name: &String, doc: syn::Lit) -> Tokens {
|
|||
return
|
||||
}
|
||||
};
|
||||
module.add(py, "__doc__", #doc).expect("Failed to add doc for module");
|
||||
let ret = match #fnname(py, &module) {
|
||||
module.add("__doc__", #doc).expect("Failed to add doc for module");
|
||||
let ret = match #fnname(py, module) {
|
||||
Ok(()) => (),
|
||||
Err(e) => e.restore(py)
|
||||
};
|
||||
|
@ -207,7 +200,6 @@ fn wrap_fn(item: &mut syn::Item) -> Option<Box<syn::Block>> {
|
|||
|
||||
match item.node {
|
||||
syn::ItemKind::Fn(ref decl, _, _, _, _, _) => {
|
||||
let mut py = false;
|
||||
let mut arguments = Vec::new();
|
||||
|
||||
for input in decl.inputs.iter() {
|
||||
|
@ -221,24 +213,22 @@ fn wrap_fn(item: &mut syn::Item) -> Option<Box<syn::Block>> {
|
|||
panic!("unsupported argument: {:?}", pat),
|
||||
};
|
||||
|
||||
if !py {
|
||||
match ty {
|
||||
&syn::Ty::Path(_, ref path) =>
|
||||
if let Some(segment) = path.segments.last() {
|
||||
if segment.ident.as_ref() == "Python" {
|
||||
py = true;
|
||||
continue;
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
let py = match ty {
|
||||
&syn::Ty::Path(_, ref path) =>
|
||||
if let Some(segment) = path.segments.last() {
|
||||
segment.ident.as_ref() == "Python"
|
||||
} else {
|
||||
false
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
|
||||
let opt = method::check_arg_ty_and_optional(&name, ty);
|
||||
arguments.push(method::FnArg {name: ident,
|
||||
mode: mode,
|
||||
ty: ty,
|
||||
optional: opt});
|
||||
optional: opt,
|
||||
py: py});
|
||||
}
|
||||
&syn::FnArg::Ignored(_) =>
|
||||
panic!("ignored argument: {:?}", name),
|
||||
|
@ -286,7 +276,7 @@ fn wrap_fn(item: &mut syn::Item) -> Option<Box<syn::Block>> {
|
|||
Box::into_raw(Box::new(def.as_method_def())),
|
||||
std::ptr::null_mut()));
|
||||
|
||||
#m.add(py, stringify!(#fnname), func)?
|
||||
#m.add(stringify!(#fnname), func)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,16 +299,17 @@ fn wrap_fn(item: &mut syn::Item) -> Option<Box<syn::Block>> {
|
|||
|
||||
/// Generate static method wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||
pub fn impl_wrap(name: &syn::Ident, spec: &method::FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
let names: Vec<syn::Ident> = spec.args.iter().map(
|
||||
|item| if item.py {syn::Ident::from("py")} else {item.name.clone()}).collect();
|
||||
let cb = quote! {{
|
||||
#name(py, #(#names),*)
|
||||
#name(#(#names),*)
|
||||
}};
|
||||
|
||||
let body = py_method::impl_arg_params(spec, cb);
|
||||
let output = &spec.output;
|
||||
|
||||
quote! {
|
||||
#[allow(unused_mut)]
|
||||
#[allow(unused_variables)]
|
||||
unsafe extern "C" fn wrap(_slf: *mut _pyo3::ffi::PyObject,
|
||||
args: *mut _pyo3::ffi::PyObject,
|
||||
kwargs: *mut _pyo3::ffi::PyObject) -> *mut _pyo3::ffi::PyObject
|
||||
|
@ -326,14 +317,12 @@ pub fn impl_wrap(name: &syn::Ident, spec: &method::FnSpec) -> Tokens {
|
|||
const LOCATION: &'static str = concat!(stringify!(#name), "()");
|
||||
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result: #output = {
|
||||
#body
|
||||
};
|
||||
py.release(kwargs);
|
||||
py.release(args);
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
|
|
|
@ -13,7 +13,7 @@ pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
|||
let params = parse_attribute(attr);
|
||||
let doc = utils::get_doc(&ast.attrs, true);
|
||||
|
||||
let base = syn::Ident::from("_pyo3::PyObject");
|
||||
let base = syn::Ident::from("_pyo3::PyInstance");
|
||||
let mut token: Option<syn::Ident> = None;
|
||||
|
||||
match ast.body {
|
||||
|
@ -55,16 +55,16 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
let extra = if let Some(token) = token {
|
||||
Some(quote! {
|
||||
impl _pyo3::PyObjectWithToken for #cls {
|
||||
#[inline]
|
||||
fn token<'p>(&'p self) -> _pyo3::Python<'p> {
|
||||
self.#token.token()
|
||||
self.#token.py()
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::ToPyObject for #cls
|
||||
{
|
||||
#[inline]
|
||||
fn to_object<'p>(&self, py: _pyo3::Python<'p>) -> _pyo3::PyObject {
|
||||
_pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -78,11 +78,11 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
{
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
_pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
impl std::convert::AsRef<PyObject> for #cls {
|
||||
fn as_ref(&self) -> &_pyo3::PyObject {
|
||||
impl std::convert::AsRef<PyInstance> for #cls {
|
||||
fn as_ref(&self) -> &_pyo3::PyInstance {
|
||||
unsafe{std::mem::transmute(self.as_ptr())}
|
||||
}
|
||||
}
|
||||
|
@ -98,29 +98,16 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
|
||||
impl std::fmt::Debug for #cls {
|
||||
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let py = _pyo3::PyObjectWithToken::token(self);
|
||||
let ptr = <#cls as _pyo3::ToPyPointer>::as_ptr(self);
|
||||
let repr = unsafe {
|
||||
_pyo3::PyString::downcast_from_ptr(
|
||||
py, _pyo3::ffi::PyObject_Repr(ptr)).map_err(|_| std::fmt::Error)?
|
||||
};
|
||||
let result = f.write_str(&repr.to_string_lossy(py));
|
||||
py.release(repr);
|
||||
result
|
||||
use pyo3::ObjectProtocol;
|
||||
let s = try!(self.repr().map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #cls {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let py = _pyo3::PyObjectWithToken::token(self);
|
||||
let ptr = <#cls as _pyo3::ToPyPointer>::as_ptr(self);
|
||||
let str_obj = unsafe {
|
||||
_pyo3::PyString::downcast_from_ptr(
|
||||
py, _pyo3::ffi::PyObject_Str(ptr)).map_err(|_| std::fmt::Error)?
|
||||
};
|
||||
let result = f.write_str(&str_obj.to_string_lossy(py));
|
||||
py.release(str_obj);
|
||||
result
|
||||
use pyo3::ObjectProtocol;
|
||||
let s = try!(self.str().map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -184,6 +171,12 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
|
||||
unsafe { &mut TYPE_OBJECT }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_instance(ptr: *mut ffi::PyObject) -> bool {
|
||||
unsafe {ffi::PyObject_TypeCheck(
|
||||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0}
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::typeob::PyTypeObject for #cls {
|
||||
|
@ -195,13 +188,12 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
|
||||
if (ty.tp_flags & _pyo3::ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let to = _pyo3::typeob::initialize_type::<#cls>(
|
||||
_pyo3::typeob::initialize_type::<#cls>(
|
||||
py, None, <#cls as _pyo3::typeob::PyTypeInfo>::type_name(),
|
||||
<#cls as _pyo3::typeob::PyTypeInfo>::type_description(), ty).expect(
|
||||
format!("An error occurred while initializing class {}",
|
||||
<#cls as _pyo3::typeob::PyTypeInfo>::type_name())
|
||||
.as_ref());
|
||||
py.release(to);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -209,8 +201,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
|
||||
impl _pyo3::PyDowncastFrom for #cls
|
||||
{
|
||||
fn downcast_from<'a, 'p>(py: Python<'p>, ob: &'a _pyo3::PyObject)
|
||||
-> Result<&'a #cls, _pyo3::PyDowncastError<'p>>
|
||||
fn downcast_from(ob: &_pyo3::PyInstance) -> Result<&#cls, _pyo3::PyDowncastError>
|
||||
{
|
||||
unsafe {
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
|
@ -221,15 +212,28 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
Ok(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
Err(_pyo3::PyDowncastError(py, None))
|
||||
Err(_pyo3::PyDowncastError(ob.token(), None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyInstance) -> &Self
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
std::mem::transmute(ptr)
|
||||
}
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyInstance) -> &mut Self
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
std::mem::transmute(ptr)
|
||||
}
|
||||
}
|
||||
impl _pyo3::PyMutDowncastFrom for #cls
|
||||
{
|
||||
fn downcast_mut_from<'a, 'p>(py: Python<'p>, ob: &'a mut _pyo3::PyObject)
|
||||
-> Result<&'a mut #cls, _pyo3::PyDowncastError<'p>>
|
||||
fn downcast_mut_from(ob: &mut _pyo3::PyInstance)
|
||||
-> Result<&mut #cls, _pyo3::PyDowncastError>
|
||||
{
|
||||
unsafe {
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
|
@ -240,7 +244,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
Ok(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
Err(_pyo3::PyDowncastError(py, None))
|
||||
Err(_pyo3::PyDowncastError(ob.token(), None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ fn impl_methods(ty: &Box<syn::Ty>, impls: &mut Vec<syn::ImplItem>) -> Tokens {
|
|||
quote! {
|
||||
#[feature(specialization)]
|
||||
#[allow(non_upper_case_globals, unused_attributes,
|
||||
unused_qualifications, unused_variables)]
|
||||
unused_qualifications, unused_variables, unused_imports)]
|
||||
const #dummy_const: () = {
|
||||
extern crate pyo3 as _pyo3;
|
||||
|
||||
|
|
|
@ -53,17 +53,13 @@ pub fn impl_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec, noargs: b
|
|||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".", stringify!(#name), "()");
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let slf = _pyo3::Py::<#cls>::from_borrowed_ptr(slf);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<#cls>(slf);
|
||||
|
||||
let result = {
|
||||
let result: #output = {
|
||||
#cb
|
||||
};
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
let result: #output = {
|
||||
#cb
|
||||
};
|
||||
py.release(slf);
|
||||
result
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -79,21 +75,16 @@ pub fn impl_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec, noargs: b
|
|||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".", stringify!(#name), "()");
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let slf = _pyo3::Py::<#cls>::from_borrowed_ptr(slf);
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
use pyo3::ToPyPointer;
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<#cls>(slf);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result = {
|
||||
let result: #output = {
|
||||
#body
|
||||
};
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
let result: #output = {
|
||||
#body
|
||||
};
|
||||
py.release(kwargs);
|
||||
py.release(args);
|
||||
py.release(slf);
|
||||
result
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -113,14 +104,13 @@ pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let slf = _pyo3::Py::<#cls>::from_borrowed_ptr(slf);
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<#cls>(slf);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result = {
|
||||
#body
|
||||
};
|
||||
py.release(slf);
|
||||
_pyo3::callback::cb_convert(
|
||||
_pyo3::callback::PyObjectCallbackConverter, py, result)
|
||||
})
|
||||
|
@ -130,9 +120,10 @@ pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
|
||||
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||
pub fn impl_wrap_type(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
let names: Vec<syn::Ident> = spec.args.iter().map(
|
||||
|item| if item.py {syn::Ident::from("py")} else {item.name.clone()}).collect();
|
||||
let cb = quote! {{
|
||||
#cls::#name(&cls, py, #(#names),*)
|
||||
#cls::#name(&cls, #(#names),*)
|
||||
}};
|
||||
|
||||
let body = impl_arg_params(spec, cb);
|
||||
|
@ -148,7 +139,7 @@ pub fn impl_wrap_type(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> T
|
|||
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let cls = _pyo3::PyType::from_type_ptr(py, cls);
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result: #output = {
|
||||
|
@ -163,9 +154,10 @@ pub fn impl_wrap_type(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> T
|
|||
|
||||
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||
pub fn impl_wrap_class(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
let names: Vec<syn::Ident> = spec.args.iter().map(
|
||||
|item| if item.py {syn::Ident::from("py")} else {item.name.clone()}).collect();
|
||||
let cb = quote! {{
|
||||
#cls::#name(&cls, py, #(#names),*)
|
||||
#cls::#name(&cls, #(#names),*)
|
||||
}};
|
||||
let body = impl_arg_params(spec, cb);
|
||||
let output = &spec.output;
|
||||
|
@ -180,7 +172,7 @@ pub fn impl_wrap_class(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let cls = _pyo3::PyType::from_type_ptr(py, cls as *mut _pyo3::ffi::PyTypeObject);
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result: #output = {
|
||||
|
@ -195,9 +187,10 @@ pub fn impl_wrap_class(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
|
||||
/// Generate static method wrapper (PyCFunction, PyCFunctionWithKeywords)
|
||||
pub fn impl_wrap_static(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
let names: Vec<syn::Ident> = spec.args.iter().map(
|
||||
|item| if item.py {syn::Ident::from("py")} else {item.name.clone()}).collect();
|
||||
let cb = quote! {{
|
||||
#cls::#name(py, #(#names),*)
|
||||
#cls::#name(#(#names),*)
|
||||
}};
|
||||
|
||||
let body = impl_arg_params(spec, cb);
|
||||
|
@ -212,7 +205,7 @@ pub fn impl_wrap_static(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
|
|||
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name), "()");
|
||||
|
||||
_pyo3::callback::cb_meth(LOCATION, |py| {
|
||||
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
|
||||
let args = py.cast_from_borrowed_ptr::<_pyo3::PyTuple>(args);
|
||||
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
|
||||
|
||||
let result: #output = {
|
||||
|
@ -236,8 +229,8 @@ fn impl_wrap_getter(cls: &Box<syn::Ty>, name: &syn::Ident, _spec: &FnSpec) -> To
|
|||
stringify!(#cls), ".getter_", stringify!(#name), "()");
|
||||
_pyo3::callback::cb_unary::<#cls, _, _, _>(
|
||||
LOCATION, slf, _pyo3::callback::PyObjectCallbackConverter, |py, slf| {
|
||||
slf.#name(py)
|
||||
})
|
||||
slf.#name()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,14 +251,13 @@ fn impl_wrap_setter(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tok
|
|||
const LOCATION: &'static str = concat!(
|
||||
stringify!(#cls), ".setter", stringify!(#name), "()");
|
||||
_pyo3::callback::cb_setter(LOCATION, |py| {
|
||||
let slf = _pyo3::Py::<#cls>::from_borrowed_ptr(slf);
|
||||
let value = _pyo3::PyObject::from_borrowed_ptr(py, value);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<#cls>(slf);
|
||||
let value = py.cast_from_borrowed_ptr(value);
|
||||
|
||||
let result = match <#val_ty as _pyo3::FromPyObject>::extract(py, &value) {
|
||||
Ok(val) => slf.as_mut(py).#name(py, val),
|
||||
let result = match <#val_ty as _pyo3::FromPyObject>::extract(value) {
|
||||
Ok(val) => slf.#name(val),
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
py.release(slf);
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
|
@ -280,20 +272,26 @@ 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 {
|
||||
let names: Vec<&syn::Ident> = spec.args.iter().map(|item| item.name).collect();
|
||||
let names: Vec<syn::Ident> = spec.args.iter().map(
|
||||
|item| if item.py {syn::Ident::from("py")} else {item.name.clone()}).collect();
|
||||
quote! {{
|
||||
slf.as_mut(py).#fname(py, #(#names),*)
|
||||
slf.#fname(#(#names),*)
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn impl_arg_params(spec: &FnSpec, body: Tokens) -> Tokens {
|
||||
if spec.args.is_empty() {
|
||||
let args: Vec<FnArg> = spec.args.iter()
|
||||
.filter(|item| !item.py).map(|item| item.clone()).collect();
|
||||
if args.is_empty() {
|
||||
return body
|
||||
}
|
||||
|
||||
let mut params = Vec::new();
|
||||
|
||||
for arg in spec.args.iter() {
|
||||
if arg.py {
|
||||
continue
|
||||
}
|
||||
if ! (spec.is_args(&arg.name) || spec.is_kwargs(&arg.name)) {
|
||||
let name = arg.name.as_ref();
|
||||
let kwonly = if spec.is_kw_only(&arg.name) {
|
||||
|
@ -341,9 +339,9 @@ pub fn impl_arg_params(spec: &FnSpec, body: Tokens) -> Tokens {
|
|||
];
|
||||
|
||||
let mut output = [#(#placeholders),*];
|
||||
let result = match _pyo3::argparse::parse_args(
|
||||
match _pyo3::argparse::parse_args(
|
||||
py, Some(LOCATION), PARAMS, &args,
|
||||
kwargs.as_ref(), #accept_args, #accept_kwargs, &mut output)
|
||||
kwargs, #accept_args, #accept_kwargs, &mut output)
|
||||
{
|
||||
Ok(_) => {
|
||||
let mut _iter = output.iter();
|
||||
|
@ -351,18 +349,14 @@ pub fn impl_arg_params(spec: &FnSpec, body: Tokens) -> Tokens {
|
|||
#body
|
||||
},
|
||||
Err(err) => Err(err)
|
||||
};
|
||||
for p in output.iter_mut() {
|
||||
if let Some(ob) = p.take() {
|
||||
py.release(ob);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
||||
if arg.py {
|
||||
return body.clone()
|
||||
}
|
||||
let ty = arg.ty;
|
||||
let name = arg.name;
|
||||
|
||||
|
@ -372,7 +366,7 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
|||
|
||||
if spec.is_args(&name) {
|
||||
quote! {
|
||||
match <#ty as _pyo3::FromPyObject>::extract(py, args.as_ref())
|
||||
match <#ty as _pyo3::FromPyObject>::extract(args.as_ref())
|
||||
{
|
||||
Ok(#name) => {
|
||||
#body
|
||||
|
@ -383,7 +377,7 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
|||
}
|
||||
else if spec.is_kwargs(&name) {
|
||||
quote! {
|
||||
let #name = kwargs.as_ref();
|
||||
let #name = kwargs;
|
||||
#body
|
||||
}
|
||||
}
|
||||
|
@ -402,10 +396,10 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
|||
match
|
||||
match _iter.next().unwrap().as_ref() {
|
||||
Some(obj) => {
|
||||
if obj.is_none(py) {
|
||||
if obj.is_none() {
|
||||
Ok(#default)
|
||||
} else {
|
||||
match obj.extract(py) {
|
||||
match obj.extract() {
|
||||
Ok(obj) => Ok(Some(obj)),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
|
@ -422,10 +416,10 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
|||
quote! {
|
||||
match match _iter.next().unwrap().as_ref() {
|
||||
Some(obj) => {
|
||||
if obj.is_none(py) {
|
||||
if obj.is_none() {
|
||||
Ok(#default)
|
||||
} else {
|
||||
match obj.extract(py) {
|
||||
match obj.extract() {
|
||||
Ok(obj) => Ok(obj),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
|
@ -440,7 +434,7 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &Tokens) -> Tokens {
|
|||
}
|
||||
else {
|
||||
quote! {
|
||||
match _iter.next().unwrap().as_ref().unwrap().extract(py)
|
||||
match _iter.next().unwrap().as_ref().unwrap().extract()
|
||||
{
|
||||
Ok(#name) => {
|
||||
#body
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
use ffi;
|
||||
use python::Python;
|
||||
use objects::{PyObject, PyTuple, PyDict, PyString, exc};
|
||||
use conversion::RefFromPyObject;
|
||||
use objects::{PyInstance, PyTuple, PyDict, PyString, exc};
|
||||
//use conversion::RefFromPyObject;
|
||||
use err::{self, PyResult};
|
||||
|
||||
/// Description of a python parameter; used for `parse_args()`.
|
||||
|
@ -16,7 +16,7 @@ pub struct ParamDescription<'a> {
|
|||
/// Whether the parameter is optional.
|
||||
pub is_optional: bool,
|
||||
/// Whether the parameter is optional.
|
||||
pub kw_only: bool
|
||||
pub kw_only: bool,
|
||||
}
|
||||
|
||||
/// Parse argument list
|
||||
|
@ -31,12 +31,12 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
fname: Option<&str>, params: &[ParamDescription],
|
||||
args: &'p PyTuple, kwargs: Option<&'p PyDict>,
|
||||
accept_args: bool, accept_kwargs: bool,
|
||||
output: &mut[Option<PyObject>]) -> PyResult<()>
|
||||
output: &mut[Option<&'p PyInstance>]) -> PyResult<()>
|
||||
{
|
||||
assert!(params.len() == output.len());
|
||||
|
||||
let nargs = args.len(py);
|
||||
let nkeywords = kwargs.map_or(0, |d| d.len(py));
|
||||
|
||||
let nargs = args.len();
|
||||
let nkeywords = kwargs.map_or(0, |d| d.len());
|
||||
if !accept_args && (nargs + nkeywords > params.len()) {
|
||||
return Err(err::PyErr::new::<exc::TypeError, _>(
|
||||
py,
|
||||
|
@ -51,7 +51,7 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
let mut used_keywords = 0;
|
||||
// Iterate through the parameters and assign values to output:
|
||||
for (i, (p, out)) in params.iter().zip(output).enumerate() {
|
||||
match kwargs.and_then(|d| d.get_item(py, p.name)) {
|
||||
match kwargs.and_then(|d| d.get_item(p.name)) {
|
||||
Some(kwarg) => {
|
||||
*out = Some(kwarg);
|
||||
used_keywords += 1;
|
||||
|
@ -66,7 +66,7 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
*out = None;
|
||||
}
|
||||
else if i < nargs {
|
||||
*out = Some(args.get_item(py, i));
|
||||
*out = Some(args.get_item(i));
|
||||
} else {
|
||||
*out = None;
|
||||
if !p.is_optional {
|
||||
|
@ -81,8 +81,8 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
}
|
||||
if !accept_kwargs && used_keywords != nkeywords {
|
||||
// check for extraneous keyword arguments
|
||||
for (key, _value) in kwargs.unwrap().items(py) {
|
||||
let key = try!(try!(key.cast_as::<PyString>(py)).to_string(py));
|
||||
for (key, _value) in kwargs.unwrap().items() {
|
||||
let key = try!(try!(key.cast_as::<PyString>(py)).to_string());
|
||||
if !params.iter().any(|p| p.name == key) {
|
||||
return Err(err::PyErr::new::<exc::TypeError, _>(
|
||||
py,
|
||||
|
@ -96,25 +96,25 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn get_kwargs(py: Python, ptr: *mut ffi::PyObject) -> Option<PyDict> {
|
||||
pub unsafe fn get_kwargs<'p>(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&PyDict> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyDict::from_borrowed_ptr(py, ptr))
|
||||
Some(py.cast_from_ptr::<PyDict>(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)] // used in py_argparse_extract!() macro
|
||||
pub fn with_extracted_or_default<'p, P: ?Sized, R, F>(
|
||||
py: Python, obj: Option<&'p PyObject>, f: F, default: &'static P) -> PyResult<R>
|
||||
/*#[doc(hidden)] // used in py_argparse_extract!() macro
|
||||
pub fn with_extracted_or_default<P: ?Sized, R, F>(
|
||||
py: Python, obj: Option<&PyInstance>, f: F, default: &'static P) -> PyResult<R>
|
||||
where F: FnOnce(&P) -> PyResult<R>,
|
||||
P: RefFromPyObject<'p>
|
||||
P: RefFromPyObject
|
||||
{
|
||||
match obj {
|
||||
Some(obj) => match P::with_extracted(py, obj, f) {
|
||||
Some(obj) => match P::with_extracted(obj, f) {
|
||||
Ok(result) => result,
|
||||
Err(e) => Err(e)
|
||||
},
|
||||
None => f(default)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -25,7 +25,7 @@ use ffi;
|
|||
use exc;
|
||||
use err::{self, PyResult};
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::PyObject;
|
||||
use objects::PyInstance;
|
||||
|
||||
/// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`.
|
||||
pub struct PyBuffer(Box<ffi::Py_buffer>); // use Box<> because Python expects that the Py_buffer struct has a stable memory address
|
||||
|
@ -138,7 +138,7 @@ fn validate(b: &ffi::Py_buffer) {
|
|||
|
||||
impl PyBuffer {
|
||||
/// Get the underlying buffer from the specified python object.
|
||||
pub fn get(py: Python, obj: &PyObject) -> PyResult<PyBuffer> {
|
||||
pub fn get(py: Python, obj: &PyInstance) -> PyResult<PyBuffer> {
|
||||
unsafe {
|
||||
let mut buf = Box::new(mem::zeroed::<ffi::Py_buffer>());
|
||||
err::error_on_minusone(
|
||||
|
@ -621,8 +621,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let array = py.import("array").unwrap().call_method(
|
||||
py, "array", ("f", (1.0, 1.5, 2.0, 2.5)), None).unwrap();
|
||||
let buffer = PyBuffer::get(py, &array).unwrap();
|
||||
"array", ("f", (1.0, 1.5, 2.0, 2.5)), None).unwrap();
|
||||
let buffer = PyBuffer::get(py, array.into()).unwrap();
|
||||
assert_eq!(buffer.dimensions(), 1);
|
||||
assert_eq!(buffer.item_count(), 4);
|
||||
assert_eq!(buffer.format().to_str().unwrap(), "f");
|
||||
|
|
|
@ -4,12 +4,13 @@ use std::os::raw::c_int;
|
|||
use std::{any, mem, ptr, isize, io, panic};
|
||||
use libc;
|
||||
|
||||
use pythonrun;
|
||||
use python::{Python, IntoPyPointer};
|
||||
use objects::exc;
|
||||
use conversion::IntoPyObject;
|
||||
use ffi::{self, Py_hash_t};
|
||||
use err::{PyErr, PyResult};
|
||||
use token::{Py, AsPyRef};
|
||||
use instance::{Py, AsPyRef};
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
|
||||
|
@ -170,6 +171,7 @@ pub unsafe fn handle<'p, F, T, C>(location: &str, _c: C, f: F) -> C::R
|
|||
C: CallbackConverter<T>
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
match f(py) {
|
||||
|
@ -189,6 +191,7 @@ pub unsafe fn handle<'p, F, T, C>(location: &str, _c: C, f: F) -> C::R
|
|||
C::error_value()
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
@ -202,6 +205,7 @@ pub unsafe fn cb_unary<Slf, F, T, C>(location: &str,
|
|||
C: CallbackConverter<T>
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
let slf = Py::<Slf>::from_borrowed_ptr(slf);
|
||||
|
@ -225,6 +229,7 @@ pub unsafe fn cb_unary<Slf, F, T, C>(location: &str,
|
|||
C::error_value()
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
@ -236,6 +241,7 @@ pub unsafe fn cb_unary_unit<Slf, F>(location: &str, slf: *mut ffi::PyObject, f:
|
|||
Slf: PyTypeInfo,
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
let slf = Py::<Slf>::from_borrowed_ptr(slf);
|
||||
|
@ -251,6 +257,7 @@ pub unsafe fn cb_unary_unit<Slf, F>(location: &str, slf: *mut ffi::PyObject, f:
|
|||
-1
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
@ -260,6 +267,7 @@ pub unsafe fn cb_meth<F>(location: &str, f: F) -> *mut ffi::PyObject
|
|||
F: panic::UnwindSafe
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
f(py)
|
||||
|
@ -271,6 +279,7 @@ pub unsafe fn cb_meth<F>(location: &str, f: F) -> *mut ffi::PyObject
|
|||
ptr::null_mut()
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
@ -281,6 +290,7 @@ pub unsafe fn cb_pyfunc<F, C, T>(location: &str, _c: C, f: F) -> C::R
|
|||
C: CallbackConverter<T>
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
f(py)
|
||||
|
@ -292,6 +302,7 @@ pub unsafe fn cb_pyfunc<F, C, T>(location: &str, _c: C, f: F) -> C::R
|
|||
C::error_value()
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
@ -301,6 +312,7 @@ pub unsafe fn cb_setter<F>(location: &str, f: F) -> c_int
|
|||
F: panic::UnwindSafe
|
||||
{
|
||||
let guard = AbortOnDrop(location);
|
||||
let pool = pythonrun::Pool::new();
|
||||
let ret = panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
f(py)
|
||||
|
@ -312,6 +324,7 @@ pub unsafe fn cb_setter<F>(location: &str, f: F) -> c_int
|
|||
-1
|
||||
}
|
||||
};
|
||||
drop(pool);
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use python::PyDowncastFrom;
|
||||
use callback::PyObjectCallbackConverter;
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
|
@ -20,21 +20,21 @@ use class::methods::PyMethodDef;
|
|||
///
|
||||
/// Each method in this trait corresponds to Python async/await implementation.
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyAsyncProtocol<'p>: PyTypeInfo + Sized + 'static {
|
||||
pub trait PyAsyncProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
|
||||
fn __await__(&'p self, py: Python<'p>)
|
||||
fn __await__(&'p self)
|
||||
-> Self::Result where Self: PyAsyncAwaitProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __aiter__(&'p self, py: Python<'p>)
|
||||
fn __aiter__(&'p self)
|
||||
-> Self::Result where Self: PyAsyncAiterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __anext__(&'p mut self, py: Python<'p>)
|
||||
fn __anext__(&'p mut self)
|
||||
-> Self::Result where Self: PyAsyncAnextProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __aenter__(&'p mut self, py: Python<'p>)
|
||||
fn __aenter__(&'p mut self)
|
||||
-> Self::Result where Self: PyAsyncAenterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __aexit__(&'p mut self, py: Python<'p>,
|
||||
fn __aexit__(&'p mut self,
|
||||
exc_type: Option<Self::ExcType>,
|
||||
exc_value: Option<Self::ExcValue>,
|
||||
traceback: Option<Self::Traceback>)
|
||||
|
|
|
@ -11,13 +11,13 @@ use std::os::raw::c_int;
|
|||
|
||||
use ::CompareOp;
|
||||
use ffi;
|
||||
use callback;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, IntoPyPointer};
|
||||
use objects::PyObject;
|
||||
use objects::exc;
|
||||
use token::{Py, AsPyRef};
|
||||
use python::{Python, IntoPyPointer, PyDowncastFrom};
|
||||
use objects::{exc, PyInstance};
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::{FromPyObject, IntoPyObject};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use callback::{PyObjectCallbackConverter, HashConverter, BoolCallbackConverter};
|
||||
use class::methods::PyMethodDef;
|
||||
|
||||
|
@ -27,40 +27,40 @@ use class::methods::PyMethodDef;
|
|||
|
||||
/// Basic python class customization
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyObjectProtocol<'p>: PyTypeInfo + Sized + 'static {
|
||||
pub trait PyObjectProtocol<'p>: PyTypeInfo + PyDowncastFrom + Sized + 'static {
|
||||
|
||||
fn __getattr__(&'p self, py: Python<'p>, name: Self::Name)
|
||||
fn __getattr__(&'p self, name: Self::Name)
|
||||
-> Self::Result where Self: PyObjectGetAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __setattr__(&'p mut self, py: Python<'p>, name: Self::Name, value: Self::Value)
|
||||
fn __setattr__(&'p mut self, name: Self::Name, value: Self::Value)
|
||||
-> Self::Result where Self: PyObjectSetAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __delattr__(&'p mut self, py: Python<'p>, name: Self::Name)
|
||||
fn __delattr__(&'p mut self, name: Self::Name)
|
||||
-> Self::Result where Self: PyObjectDelAttrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __str__(&'p self, py: Python<'p>)
|
||||
fn __str__(&'p self)
|
||||
-> Self::Result where Self: PyObjectStrProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __repr__(&'p self, py: Python<'p>)
|
||||
fn __repr__(&'p self)
|
||||
-> Self::Result where Self: PyObjectReprProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __format__(&'p self, py: Python<'p>, format_spec: Self::Format)
|
||||
fn __format__(&'p self, format_spec: Self::Format)
|
||||
-> Self::Result where Self: PyObjectFormatProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __hash__(&'p self, py: Python<'p>)
|
||||
fn __hash__(&'p self)
|
||||
-> Self::Result where Self: PyObjectHashProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __bool__(&'p self, py: Python<'p>)
|
||||
fn __bool__(&'p self)
|
||||
-> Self::Result where Self: PyObjectBoolProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __bytes__(&'p self, py: Python<'p>)
|
||||
fn __bytes__(&'p self)
|
||||
-> Self::Result where Self: PyObjectBytesProtocol<'p> {unimplemented!()}
|
||||
|
||||
/// This method is used by Python2 only.
|
||||
fn __unicode__(&'p self, py: Python<'p>)
|
||||
fn __unicode__(&'p self)
|
||||
-> Self::Result where Self: PyObjectUnicodeProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __richcmp__(&'p self, py: Python<'p>, other: Self::Other, op: CompareOp)
|
||||
fn __richcmp__(&'p self, other: Self::Other, op: CompareOp)
|
||||
-> Self::Result where Self: PyObjectRichcmpProtocol<'p> {unimplemented!()}
|
||||
}
|
||||
|
||||
|
@ -355,59 +355,39 @@ impl<'p, T> PyObjectRichcmpProtocolImpl for T where T: PyObjectProtocol<'p>
|
|||
}
|
||||
}
|
||||
impl<T> PyObjectRichcmpProtocolImpl for T
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p>
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p> + PyDowncastFrom
|
||||
{
|
||||
#[inline]
|
||||
fn tp_richcompare() -> Option<ffi::richcmpfunc> {
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
op: c_int) -> *mut ffi::PyObject
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p>
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p> + PyDowncastFrom
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(T), ".__richcmp__()");
|
||||
|
||||
let guard = ::callback::AbortOnDrop(LOCATION);
|
||||
let ret = std::panic::catch_unwind(|| {
|
||||
let py = Python::assume_gil_acquired();
|
||||
let slf = Py::<T>::from_borrowed_ptr(slf);
|
||||
let arg = PyObject::from_borrowed_ptr(py, arg);
|
||||
callback::cb_meth(LOCATION, |py| {
|
||||
let slf = py.cast_from_borrowed_ptr::<T>(slf);
|
||||
let arg = py.cast_from_borrowed_ptr::<PyInstance>(arg);
|
||||
|
||||
let result = {
|
||||
let res = match extract_op(py, op) {
|
||||
Ok(op) => {
|
||||
match arg.extract(py) {
|
||||
Ok(arg) => {
|
||||
slf.as_ref(py).__richcmp__(py, arg, op).into()
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
match res {
|
||||
Ok(val) => {
|
||||
val.into_object(py).into_ptr()
|
||||
}
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
let res = match extract_op(py, op) {
|
||||
Ok(op) => match arg.extract() {
|
||||
Ok(arg) =>
|
||||
slf.__richcmp__(arg, op).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
};
|
||||
py.release(arg);
|
||||
py.release(slf);
|
||||
result
|
||||
});
|
||||
|
||||
let ret = match ret {
|
||||
Ok(r) => r,
|
||||
Err(ref err) => {
|
||||
::callback::handle_panic(Python::assume_gil_acquired(), err);
|
||||
std::ptr::null_mut()
|
||||
match res {
|
||||
Ok(val) => {
|
||||
val.into_object(py).into_ptr()
|
||||
}
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
};
|
||||
std::mem::forget(guard);
|
||||
ret
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use typeob::PyTypeInfo;
|
||||
use callback::UnitCallbackConverter;
|
||||
|
||||
|
@ -18,11 +17,11 @@ use callback::UnitCallbackConverter;
|
|||
#[allow(unused_variables)]
|
||||
pub trait PyBufferProtocol<'p> : PyTypeInfo + Sized + 'static
|
||||
{
|
||||
fn bf_getbuffer(&'p self, py: Python<'p>,
|
||||
fn bf_getbuffer(&'p self,
|
||||
view: *mut ffi::Py_buffer, flags: c_int) -> Self::Result
|
||||
where Self: PyBufferGetBufferProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn bf_releasebuffer(&'p self, py: Python<'p>, view: *mut ffi::Py_buffer) -> Self::Result
|
||||
fn bf_releasebuffer(&'p self, view: *mut ffi::Py_buffer) -> Self::Result
|
||||
where Self: PyBufferReleaseBufferProtocol<'p> { unimplemented!() }
|
||||
}
|
||||
|
||||
|
@ -79,8 +78,8 @@ impl<T> PyBufferGetBufferProtocolImpl for T
|
|||
where T: for<'p> PyBufferGetBufferProtocol<'p>
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(T), ".buffer_get::<PyBufferProtocol>()");
|
||||
::callback::cb_unary::<T, _, _, _>(LOCATION, slf, UnitCallbackConverter, |py, slf| {
|
||||
slf.bf_getbuffer(py, arg1, arg2).into()
|
||||
::callback::cb_unary::<T, _, _, _>(LOCATION, slf, UnitCallbackConverter, |_, slf| {
|
||||
slf.bf_getbuffer(arg1, arg2).into()
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
//!
|
||||
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
|
||||
|
@ -14,10 +13,10 @@ use class::methods::PyMethodDef;
|
|||
#[allow(unused_variables)]
|
||||
pub trait PyContextProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __enter__(&'p mut self, py: Python<'p>)
|
||||
fn __enter__(&'p mut self)
|
||||
-> Self::Result where Self: PyContextEnterProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __exit__(&'p mut self, py: Python<'p>,
|
||||
fn __exit__(&'p mut self,
|
||||
exc_type: Option<Self::ExcType>,
|
||||
exc_value: Option<Self::ExcValue>,
|
||||
traceback: Option<Self::Traceback>)
|
||||
|
|
|
@ -9,8 +9,8 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use objects::{PyType, PyObject};
|
||||
use python::PyDowncastFrom;
|
||||
use objects::{PyType, PyInstance};
|
||||
use callback::{PyObjectCallbackConverter, UnitCallbackConverter};
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
|
@ -19,18 +19,18 @@ use conversion::{IntoPyObject, FromPyObject};
|
|||
|
||||
/// Descriptor interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyDescrProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyDescrProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
|
||||
fn __get__(&'p self, py: Python<'p>, instance: &'p PyObject, owner: Option<&'p PyType>)
|
||||
fn __get__(&'p self, instance: &'p PyInstance, owner: Option<&'p PyType>)
|
||||
-> Self::Result where Self: PyDescrGetProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __set__(&'p self, py: Python<'p>, instance: &'p PyObject, value: &'p PyObject)
|
||||
fn __set__(&'p self, instance: &'p PyInstance, value: &'p PyInstance)
|
||||
-> Self::Result where Self: PyDescrSetProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __delete__(&'p self, py: Python<'p>, instance: &'p PyObject)
|
||||
fn __delete__(&'p self, instance: &'p PyInstance)
|
||||
-> Self::Result where Self: PyDescrDeleteProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __set_name__(&'p self, py: Python<'p>, instance: &'p PyObject)
|
||||
fn __set_name__(&'p self, instance: &'p PyInstance)
|
||||
-> Self::Result where Self: PyDescrSetNameProtocol<'p> { unimplemented!() }
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
//! Python GC support
|
||||
//!
|
||||
|
||||
use std::mem;
|
||||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
use ffi;
|
||||
use callback;
|
||||
use python::{Python, ToPyPointer};
|
||||
use callback::AbortOnDrop;
|
||||
use token::{Py, AsPyRef};
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
pub struct PyTraverseError(c_int);
|
||||
|
@ -18,10 +16,10 @@ pub struct PyTraverseError(c_int);
|
|||
#[allow(unused_variables)]
|
||||
pub trait PyGCProtocol<'p> : PyTypeInfo {
|
||||
|
||||
fn __traverse__(&'p self, py: Python<'p>, visit: PyVisit)
|
||||
fn __traverse__(&'p self, visit: PyVisit)
|
||||
-> Result<(), PyTraverseError> { unimplemented!() }
|
||||
|
||||
fn __clear__(&'p mut self, py: Python<'p>) { unimplemented!() }
|
||||
fn __clear__(&'p mut self) { unimplemented!() }
|
||||
|
||||
}
|
||||
|
||||
|
@ -30,11 +28,10 @@ pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
|
|||
|
||||
|
||||
impl<'p, T> PyGCProtocol<'p> for T where T: PyTypeInfo {
|
||||
default fn __traverse__(&'p self, _py: Python<'p>, _: PyVisit)
|
||||
-> Result<(), PyTraverseError> {
|
||||
default fn __traverse__(&'p self, _: PyVisit) -> Result<(), PyTraverseError> {
|
||||
Ok(())
|
||||
}
|
||||
default fn __clear__(&'p mut self, _py: Python<'p>) {}
|
||||
default fn __clear__(&'p mut self) {}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -97,17 +94,13 @@ impl<T> PyGCTraverseProtocolImpl for T where T: for<'p> PyGCTraverseProtocol<'p>
|
|||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(T), ".__traverse__()");
|
||||
|
||||
let guard = AbortOnDrop(LOCATION);
|
||||
let py = Python::assume_gil_acquired();
|
||||
let visit = PyVisit { visit: visit, arg: arg, _py: py };
|
||||
let slf = Py::<T>::from_borrowed_ptr(slf);
|
||||
|
||||
let ret = match slf.as_ref(py).__traverse__(py, visit) {
|
||||
Ok(()) => 0,
|
||||
Err(PyTraverseError(code)) => code
|
||||
};
|
||||
mem::forget(guard);
|
||||
ret
|
||||
callback::cb_unary_unit::<T, _>(LOCATION, slf, |py, slf| {
|
||||
let visit = PyVisit { visit: visit, arg: arg, _py: py };
|
||||
match slf.__traverse__(visit) {
|
||||
Ok(()) => 0,
|
||||
Err(PyTraverseError(code)) => code
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Some(tp_traverse::<T>)
|
||||
|
@ -136,12 +129,10 @@ impl<T> PyGCClearProtocolImpl for T where T: for<'p> PyGCClearProtocol<'p>
|
|||
{
|
||||
const LOCATION: &'static str = concat!(stringify!(T), ".__clear__()");
|
||||
|
||||
let guard = AbortOnDrop(LOCATION);
|
||||
let py = Python::assume_gil_acquired();
|
||||
let slf = Py::<T>::from_borrowed_ptr(slf);
|
||||
T::__clear__(&mut slf.as_mut(py), py);
|
||||
mem::forget(guard);
|
||||
0
|
||||
callback::cb_unary_unit::<T, _>(LOCATION, slf, |_, slf| {
|
||||
slf.__clear__();
|
||||
0
|
||||
})
|
||||
}
|
||||
Some(tp_clear::<T>)
|
||||
}
|
||||
|
|
|
@ -8,18 +8,18 @@
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use python::PyDowncastFrom;
|
||||
use typeob::PyTypeInfo;
|
||||
use callback::{PyObjectCallbackConverter, IterNextResultConverter};
|
||||
|
||||
|
||||
/// Iterator protocol
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyIterProtocol<'p> : PyTypeInfo {
|
||||
fn __iter__(&'p mut self, py: Python<'p>)
|
||||
pub trait PyIterProtocol<'p> : PyTypeInfo + PyDowncastFrom {
|
||||
fn __iter__(&'p mut self)
|
||||
-> Self::Result where Self: PyIterIterProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __next__(&'p mut self, py: Python<'p>)
|
||||
fn __next__(&'p mut self)
|
||||
-> Self::Result where Self: PyIterNextProtocol<'p> { unimplemented!() }
|
||||
|
||||
}
|
||||
|
|
|
@ -8,19 +8,14 @@ macro_rules! py_unary_func {
|
|||
};
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $ret_type:ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, $res_type>(LOCATION, $conv, |py| {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let result = {
|
||||
let res = slf.as_mut(py).$f(py).into();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
};
|
||||
py.release(slf);
|
||||
result
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let res = slf.$f().into();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -33,19 +28,15 @@ macro_rules! py_unary_func {
|
|||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject)
|
||||
-> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, $res_type>(LOCATION, $conv, |py| {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let result = {
|
||||
let res = slf.as_mut(py).$f(py).into();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
};
|
||||
py.release(slf);
|
||||
result
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let res = slf.$f().into();
|
||||
$crate::callback::cb_convert($conv, py, res)
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -59,11 +50,11 @@ macro_rules! py_len_func {
|
|||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject)
|
||||
-> $crate::ffi::Py_ssize_t
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::callback::cb_unary::<T, _, _, _>(LOCATION, slf, $conv, |py, slf| {
|
||||
slf.$f(py).into()
|
||||
$crate::callback::cb_unary::<T, _, _, _>(LOCATION, slf, $conv, |_, slf| {
|
||||
slf.$f().into()
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -80,27 +71,20 @@ macro_rules! py_binary_func{
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject) -> $return
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, $res_type>(LOCATION, $conv, |py| {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let arg = $crate::PyObject::from_borrowed_ptr(py, arg);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let arg = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg);
|
||||
|
||||
let result = {
|
||||
let result = match arg.extract(py) {
|
||||
Ok(arg) => {
|
||||
slf.as_mut(py).$f(py, arg).into()
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => slf.$f(arg).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(arg);
|
||||
py.release(slf);
|
||||
result
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -114,37 +98,29 @@ macro_rules! py_binary_self_func{
|
|||
#[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>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_meth(LOCATION, |py| {
|
||||
let slf1 = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let arg = $crate::PyObject::from_borrowed_ptr(py, arg);
|
||||
let slf1 = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let arg = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg);
|
||||
|
||||
let result = {
|
||||
let result = match arg.extract(py) {
|
||||
Ok(arg) => {
|
||||
slf1.as_mut(py).$f(py, arg).into()
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
ffi::Py_INCREF(slf);
|
||||
slf
|
||||
}
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
let result = match arg.extract() {
|
||||
Ok(arg) => slf1.$f(arg).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(arg);
|
||||
py.release(slf1);
|
||||
result
|
||||
match result {
|
||||
Ok(_) => {
|
||||
ffi::Py_INCREF(slf);
|
||||
slf
|
||||
}
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -159,19 +135,14 @@ macro_rules! py_ssizearg_func {
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: $crate::Py_ssize_t) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_meth(LOCATION, |py| {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let result = {
|
||||
let result = slf.as_mut(py).$f(py, arg as isize).into();
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
};
|
||||
py.release(slf);
|
||||
result
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let result = slf.$f(arg as isize).into();
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
})
|
||||
}
|
||||
Some(wrap::<$class>)
|
||||
|
@ -188,30 +159,24 @@ macro_rules! py_ternary_func{
|
|||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject) -> $return_type
|
||||
where T: for<'p> $trait<'p>
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, $res_type>(LOCATION, $conv, |py| {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let arg1 = $crate::PyObject::from_borrowed_ptr(py, arg1);
|
||||
let arg2 = $crate::PyObject::from_borrowed_ptr(py, arg2);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let arg1 = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg1);
|
||||
let arg2 = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg2);
|
||||
|
||||
let result = {
|
||||
let result = match arg1.extract(py) {
|
||||
Ok(arg1) => match arg2.extract(py) {
|
||||
Ok(arg2) => slf.as_mut(py).$f(py, arg1, arg2).into(),
|
||||
Err(e) => Err(e.into())
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
let result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf.$f(arg1, arg2).into(),
|
||||
Err(e) => Err(e.into())
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(arg2);
|
||||
py.release(arg1);
|
||||
py.release(slf);
|
||||
result
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -229,35 +194,29 @@ macro_rules! py_ternary_self_func{
|
|||
-> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_meth(LOCATION, |py| {
|
||||
let slf1 = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let arg1 = $crate::PyObject::from_borrowed_ptr(py, arg1);
|
||||
let arg2 = $crate::PyObject::from_borrowed_ptr(py, arg2);
|
||||
let slf1 = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let arg1 = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg1);
|
||||
let arg2 = py.cast_from_borrowed_ptr::<$crate::PyInstance>(arg2);
|
||||
|
||||
let result = {
|
||||
let result = match arg1.extract(py) {
|
||||
Ok(arg1) => match arg2.extract(py) {
|
||||
Ok(arg2) => slf1.as_mut(py).$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 result = match arg1.extract() {
|
||||
Ok(arg1) => match arg2.extract() {
|
||||
Ok(arg2) => slf1.$f(arg1, arg2).into(),
|
||||
Err(e) => Err(e.into())
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(arg2);
|
||||
py.release(arg1);
|
||||
py.release(slf1);
|
||||
result
|
||||
|
||||
match result {
|
||||
Ok(_) => slf,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
$crate::std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
|
@ -274,6 +233,7 @@ macro_rules! py_func_set{
|
|||
value: *mut $crate::ffi::PyObject) -> $crate::c_int
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
$crate::callback::cb_unary_unit::<T, _>(LOCATION, slf, |py, slf| {
|
||||
if value.is_null() {
|
||||
|
@ -282,20 +242,16 @@ macro_rules! py_func_set{
|
|||
e.restore(py);
|
||||
-1
|
||||
} else {
|
||||
let name = $crate::PyObject::from_borrowed_ptr(py, name);
|
||||
let value = $crate::PyObject::from_borrowed_ptr(py, value);
|
||||
let result = match name.extract(py) {
|
||||
Ok(name) => match value.extract(py) {
|
||||
Ok(value) => {
|
||||
slf.$f(py, name, value).into()
|
||||
},
|
||||
let name = py.mut_cast_from_borrowed_ptr::<$crate::PyInstance>(name);
|
||||
let value = py.cast_from_borrowed_ptr::<$crate::PyInstance>(value);
|
||||
let result = match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
Ok(value) =>
|
||||
slf.$f(name, value).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(value);
|
||||
py.release(name);
|
||||
|
||||
match result {
|
||||
Ok(_) =>
|
||||
0,
|
||||
|
@ -323,40 +279,33 @@ macro_rules! py_func_del{
|
|||
value: *mut $crate::ffi::PyObject) -> $crate::c_int
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, ()>(
|
||||
LOCATION, $crate::callback::UnitCallbackConverter, |py|
|
||||
{
|
||||
if value.is_null() {
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let name = PyObject::from_borrowed_ptr(py, name);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let name = py.cast_from_borrowed_ptr::<$crate::PyInstance>(name);
|
||||
|
||||
let result = {
|
||||
let result = match name.extract(py) {
|
||||
Ok(name) =>
|
||||
slf.as_mut(py).$f(py, name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
}
|
||||
let result = match name.extract() {
|
||||
Ok(name) => slf.$f(name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
py.release(name);
|
||||
py.release(slf);
|
||||
result
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let e = PyErr::new::<exc::NotImplementedError, _>(
|
||||
py, format!("Subscript assignment not supported by {:?}",
|
||||
stringify!(T)));
|
||||
e.restore(py);
|
||||
-1
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -373,59 +322,48 @@ macro_rules! py_func_set_del{
|
|||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject) -> $crate::c_int
|
||||
where T: for<'p> $trait<'p> + for<'p> $trait2<'p>
|
||||
where T: for<'p> $trait<'p> + for<'p> $trait2<'p> + $crate::PyDowncastFrom
|
||||
{
|
||||
use token::AsPyRef;
|
||||
use $crate::ObjectProtocol;
|
||||
const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()");
|
||||
|
||||
$crate::callback::cb_pyfunc::<_, _, ()>(
|
||||
LOCATION, $crate::callback::UnitCallbackConverter, |py|
|
||||
{
|
||||
let slf = $crate::Py::<T>::from_borrowed_ptr(slf);
|
||||
let name = PyObject::from_borrowed_ptr(py, name);
|
||||
let slf = py.mut_cast_from_borrowed_ptr::<T>(slf);
|
||||
let name = py.cast_from_borrowed_ptr::<$crate::PyInstance>(name);
|
||||
|
||||
let result = {
|
||||
if value.is_null() {
|
||||
let result = match name.extract(py) {
|
||||
Ok(name) =>
|
||||
slf.as_mut(py).$f2(py, name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
if value.is_null() {
|
||||
let result = match name.extract() {
|
||||
Ok(name) => slf.$f2(name).into(),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
} else {
|
||||
let value = ::PyObject::from_borrowed_ptr(py, value);
|
||||
let result = {
|
||||
let result = match name.extract(py) {
|
||||
Ok(name) => match value.extract(py) {
|
||||
Ok(value) => {
|
||||
slf.as_mut(py).$f(py, name, value).into()
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
}
|
||||
};
|
||||
py.release(value);
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
py.release(name);
|
||||
py.release(slf);
|
||||
result
|
||||
} else {
|
||||
let value = py.cast_from_borrowed_ptr::<$crate::PyInstance>(value);
|
||||
let result = match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
Ok(value) => {
|
||||
slf.$f(name, value).into()
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::Python;
|
||||
use objects::{exc, PyObject};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use objects::exc;
|
||||
use callback::{PyObjectCallbackConverter, LenResultConverter};
|
||||
use conversion::{IntoPyObject, FromPyObject};
|
||||
use typeob::PyTypeInfo;
|
||||
|
@ -15,27 +15,27 @@ use class::methods::PyMethodDef;
|
|||
|
||||
/// Mapping interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyMappingProtocol<'p>: PyTypeInfo + Sized + 'static {
|
||||
pub trait PyMappingProtocol<'p>: PyTypeInfo + PyDowncastFrom + Sized + 'static {
|
||||
|
||||
fn __len__(&'p self, py: Python<'p>)
|
||||
fn __len__(&'p self)
|
||||
-> Self::Result where Self: PyMappingLenProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __getitem__(&'p self, py: Python<'p>, key: Self::Key)
|
||||
fn __getitem__(&'p self, key: Self::Key)
|
||||
-> Self::Result where Self: PyMappingGetItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __setitem__(&'p mut self, py: Python<'p>, key: Self::Key, value: Self::Value)
|
||||
fn __setitem__(&'p mut self, key: Self::Key, value: Self::Value)
|
||||
-> Self::Result where Self: PyMappingSetItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __delitem__(&'p mut self, py: Python<'p>, key: Self::Key)
|
||||
fn __delitem__(&'p mut self, key: Self::Key)
|
||||
-> Self::Result where Self: PyMappingDelItemProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __iter__(&'p self, py: Python<'p>)
|
||||
-> Self::Result where Self: PyMappingIterProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __contains__(&'p self, py: Python<'p>, value: Self::Value)
|
||||
fn __contains__(&'p self, value: Self::Value)
|
||||
-> Self::Result where Self: PyMappingContainsProtocol<'p> {unimplemented!()}
|
||||
|
||||
fn __reversed__(&'p self, py: Python<'p>)
|
||||
fn __reversed__(&'p self)
|
||||
-> Self::Result where Self: PyMappingReversedProtocol<'p> {unimplemented!()}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,120 +5,119 @@
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use callback::PyObjectCallbackConverter;
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
use class::basic::PyObjectProtocolImpl;
|
||||
use ::{IntoPyObject, FromPyObject};
|
||||
use {IntoPyObject, FromPyObject, PyDowncastFrom};
|
||||
|
||||
/// Number interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyNumberProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyNumberProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
|
||||
fn __add__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __add__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberAddProtocol<'p> { unimplemented!() }
|
||||
fn __sub__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __sub__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberSubProtocol<'p> { unimplemented!() }
|
||||
fn __mul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __mul__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberMulProtocol<'p> { unimplemented!() }
|
||||
fn __matmul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __matmul__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberMatmulProtocol<'p> { unimplemented!() }
|
||||
fn __truediv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __truediv__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberTruedivProtocol<'p> { unimplemented!() }
|
||||
fn __floordiv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __floordiv__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberFloordivProtocol<'p> { unimplemented!() }
|
||||
fn __mod__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __mod__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberModProtocol<'p> { unimplemented!() }
|
||||
fn __divmod__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __divmod__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberDivmodProtocol<'p> { unimplemented!() }
|
||||
fn __pow__(&'p self, py: Python<'p>, other: Self::Other, modulo: Self::Modulo)
|
||||
fn __pow__(&'p self, other: Self::Other, modulo: Self::Modulo)
|
||||
-> Self::Result where Self: PyNumberPowProtocol<'p> { unimplemented!() }
|
||||
fn __lshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __lshift__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberLShiftProtocol<'p> { unimplemented!() }
|
||||
fn __rshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rshift__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRShiftProtocol<'p> { unimplemented!() }
|
||||
fn __and__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __and__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberAndProtocol<'p> { unimplemented!() }
|
||||
fn __xor__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __xor__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberXorProtocol<'p> { unimplemented!() }
|
||||
fn __or__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __or__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberOrProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __radd__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __radd__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRAddProtocol<'p> { unimplemented!() }
|
||||
fn __rsub__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rsub__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRSubProtocol<'p> { unimplemented!() }
|
||||
fn __rmul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rmul__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRMulProtocol<'p> { unimplemented!() }
|
||||
fn __rmatmul__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rmatmul__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRMatmulProtocol<'p> { unimplemented!() }
|
||||
fn __rtruediv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rtruediv__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRTruedivProtocol<'p> { unimplemented!() }
|
||||
fn __rfloordiv__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rfloordiv__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRFloordivProtocol<'p> { unimplemented!() }
|
||||
fn __rmod__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rmod__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRModProtocol<'p> { unimplemented!() }
|
||||
fn __rdivmod__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rdivmod__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRDivmodProtocol<'p> { unimplemented!() }
|
||||
fn __rpow__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rpow__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRPowProtocol<'p> { unimplemented!() }
|
||||
fn __rlshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rlshift__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRLShiftProtocol<'p> { unimplemented!() }
|
||||
fn __rrshift__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rrshift__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRRShiftProtocol<'p> { unimplemented!() }
|
||||
fn __rand__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rand__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRAndProtocol<'p> { unimplemented!() }
|
||||
fn __rxor__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __rxor__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberRXorProtocol<'p> { unimplemented!() }
|
||||
fn __ror__(&'p self, py: Python<'p>, other: Self::Other)
|
||||
fn __ror__(&'p self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberROrProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __iadd__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __iadd__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIAddProtocol<'p> { unimplemented!() }
|
||||
fn __isub__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __isub__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberISubProtocol<'p> { unimplemented!() }
|
||||
fn __imul__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __imul__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIMulProtocol<'p> { unimplemented!() }
|
||||
fn __imatmul__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __imatmul__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIMatmulProtocol<'p> { unimplemented!() }
|
||||
fn __itruediv__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __itruediv__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberITruedivProtocol<'p> {unimplemented!()}
|
||||
fn __ifloordiv__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __ifloordiv__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIFloordivProtocol<'p> {unimplemented!() }
|
||||
fn __imod__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __imod__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIModProtocol<'p> { unimplemented!() }
|
||||
fn __ipow__(&'p mut self, py: Python<'p>, other: Self::Other, modulo: Self::Modulo)
|
||||
fn __ipow__(&'p mut self, other: Self::Other, modulo: Self::Modulo)
|
||||
-> Self::Result where Self: PyNumberIPowProtocol<'p> { unimplemented!() }
|
||||
fn __ilshift__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __ilshift__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberILShiftProtocol<'p> { unimplemented!() }
|
||||
fn __irshift__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __irshift__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIRShiftProtocol<'p> { unimplemented!() }
|
||||
fn __iand__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __iand__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIAndProtocol<'p> { unimplemented!() }
|
||||
fn __ixor__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __ixor__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIXorProtocol<'p> { unimplemented!() }
|
||||
fn __ior__(&'p mut self, py: Python<'p>, other: Self::Other)
|
||||
fn __ior__(&'p mut self, other: Self::Other)
|
||||
-> Self::Result where Self: PyNumberIOrProtocol<'p> { unimplemented!() }
|
||||
|
||||
// Unary arithmetic
|
||||
fn __neg__(&'p self, py: Python<'p>)
|
||||
fn __neg__(&'p self)
|
||||
-> Self::Result where Self: PyNumberNegProtocol<'p> { unimplemented!() }
|
||||
fn __pos__(&'p self, py: Python<'p>)
|
||||
fn __pos__(&'p self)
|
||||
-> Self::Result where Self: PyNumberPosProtocol<'p> { unimplemented!() }
|
||||
fn __abs__(&'p self, py: Python<'p>)
|
||||
fn __abs__(&'p self)
|
||||
-> Self::Result where Self: PyNumberAbsProtocol<'p> { unimplemented!() }
|
||||
fn __invert__(&'p self, py: Python<'p>)
|
||||
fn __invert__(&'p self)
|
||||
-> Self::Result where Self: PyNumberInvertProtocol<'p> { unimplemented!() }
|
||||
fn __complex__(&'p self, py: Python<'p>)
|
||||
fn __complex__(&'p self)
|
||||
-> Self::Result where Self: PyNumberComplexProtocol<'p> { unimplemented!() }
|
||||
fn __int__(&'p self, py: Python<'p>)
|
||||
fn __int__(&'p self)
|
||||
-> Self::Result where Self: PyNumberIntProtocol<'p> { unimplemented!() }
|
||||
fn __float__(&'p self, py: Python<'p>)
|
||||
fn __float__(&'p self)
|
||||
-> Self::Result where Self: PyNumberFloatProtocol<'p> { unimplemented!() }
|
||||
fn __round__(&'p self, py: Python<'p>)
|
||||
fn __round__(&'p self)
|
||||
-> Self::Result where Self: PyNumberRoundProtocol<'p> { unimplemented!() }
|
||||
fn __index__(&'p self, py: Python<'p>)
|
||||
fn __index__(&'p self)
|
||||
-> Self::Result where Self: PyNumberIndexProtocol<'p> { unimplemented!() }
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
use std::os::raw::c_int;
|
||||
|
||||
use ffi;
|
||||
use python::Python;
|
||||
use python::PyDowncastFrom;
|
||||
use err::{PyErr, PyResult};
|
||||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use objects::{exc, PyInstance};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use callback::{PyObjectCallbackConverter, LenResultConverter, BoolCallbackConverter};
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::{IntoPyObject, FromPyObject};
|
||||
|
@ -17,32 +17,33 @@ use conversion::{IntoPyObject, FromPyObject};
|
|||
|
||||
/// Sequece interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PySequenceProtocol<'p>: PyTypeInfo + Sized + 'static {
|
||||
fn __len__(&'p self, py: Python<'p>) -> Self::Result
|
||||
pub trait PySequenceProtocol<'p>: PyTypeInfo + PyDowncastFrom
|
||||
{
|
||||
fn __len__(&'p self) -> Self::Result
|
||||
where Self: PySequenceLenProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __getitem__(&'p self, py: Python<'p>, key: isize) -> Self::Result
|
||||
fn __getitem__(&'p self, key: isize) -> Self::Result
|
||||
where Self: PySequenceGetItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __setitem__(&'p mut self, py: Python<'p>, key: isize, value: Self::Value) -> Self::Result
|
||||
fn __setitem__(&'p mut self, key: isize, value: Self::Value) -> Self::Result
|
||||
where Self: PySequenceSetItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __delitem__(&'p mut self, py: Python<'p>, key: isize) -> Self::Result
|
||||
fn __delitem__(&'p mut self, key: isize) -> Self::Result
|
||||
where Self: PySequenceDelItemProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __contains__(&'p self, py: Python<'p>, item: Self::Item) -> Self::Result
|
||||
fn __contains__(&'p self, item: Self::Item) -> Self::Result
|
||||
where Self: PySequenceContainsProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __concat__(&'p self, py: Python<'p>, other: Self::Other) -> Self::Result
|
||||
fn __concat__(&'p self, other: Self::Other) -> Self::Result
|
||||
where Self: PySequenceConcatProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __repeat__(&'p self, py: Python<'p>, count: isize) -> Self::Result
|
||||
fn __repeat__(&'p self, count: isize) -> Self::Result
|
||||
where Self: PySequenceRepeatProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __inplace_concat__(&'p mut self, py: Python<'p>, other: Self::Other) -> Self::Result
|
||||
fn __inplace_concat__(&'p mut self, other: Self::Other) -> Self::Result
|
||||
where Self: PySequenceInplaceConcatProtocol<'p> { unimplemented!() }
|
||||
|
||||
fn __inplace_repeat__(&'p mut self, py: Python<'p>, count: isize) -> Self::Result
|
||||
fn __inplace_repeat__(&'p mut self, count: isize) -> Self::Result
|
||||
where Self: PySequenceInplaceRepeatProtocol<'p> { unimplemented!() }
|
||||
}
|
||||
|
||||
|
@ -224,10 +225,10 @@ impl<T> PySequenceSetItemProtocolImpl for T
|
|||
e.restore(py);
|
||||
-1
|
||||
} else {
|
||||
let value = PyObject::from_borrowed_ptr(py, value);
|
||||
let result = match value.extract(py) {
|
||||
let value = py.cast_from_borrowed_ptr::<PyInstance>(value);
|
||||
let result = match value.extract() {
|
||||
Ok(value) => {
|
||||
slf.__setitem__(py, key as isize, value).into()
|
||||
slf.__setitem__(key as isize, value).into()
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
@ -269,7 +270,7 @@ impl<T> PySequenceDelItemProtocolImpl for T
|
|||
const LOCATION: &'static str = "T.__detitem__()";
|
||||
::callback::cb_unary_unit::<T, _>(LOCATION, slf, |py, slf| {
|
||||
if value.is_null() {
|
||||
let result = slf.__delitem__(py, key as isize).into();
|
||||
let result = slf.__delitem__(key as isize).into();
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
|
@ -304,7 +305,7 @@ impl<T> PySequenceDelItemProtocolImpl for T
|
|||
const LOCATION: &'static str = "T.__set/del_item__()";
|
||||
::callback::cb_unary_unit::<T, _>(LOCATION, slf, |py, slf| {
|
||||
if value.is_null() {
|
||||
let result = slf.__delitem__(py, key as isize).into();
|
||||
let result = slf.__delitem__(key as isize).into();
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
|
@ -313,10 +314,10 @@ impl<T> PySequenceDelItemProtocolImpl for T
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let value = ::PyObject::from_borrowed_ptr(py, value);
|
||||
let result = match value.extract(py) {
|
||||
let value = py.cast_from_borrowed_ptr::<PyInstance>(value);
|
||||
let result = match value.extract() {
|
||||
Ok(value) => {
|
||||
slf.__setitem__(py, key as isize, value).into()
|
||||
slf.__setitem__(key as isize, value).into()
|
||||
},
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use objects::{PyObject, PyTuple};
|
||||
use pointer::PyObject;
|
||||
use objects::{PyInstance, PyTuple};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use typeob::PyTypeInfo;
|
||||
use instance::Py;
|
||||
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`
|
||||
|
@ -31,7 +34,7 @@ pub trait IntoPyObject {
|
|||
|
||||
/// Converts self into a Python object. (Consumes self)
|
||||
#[inline]
|
||||
fn into_object(self, py: Python) -> ::objects::PyObject
|
||||
fn into_object(self, py: Python) -> PyObject
|
||||
where Self: Sized;
|
||||
}
|
||||
|
||||
|
@ -40,7 +43,7 @@ pub trait IntoPyObject {
|
|||
pub trait IntoPyTuple {
|
||||
|
||||
/// Converts self into a PyTuple object.
|
||||
fn into_tuple(self, py: Python) -> PyTuple;
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple>;
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,41 +70,30 @@ pub trait IntoPyTuple {
|
|||
/// the inherent method `PyObject::extract()` can be used.
|
||||
pub trait FromPyObject<'source> : Sized {
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'source PyObject) -> PyResult<Self>;
|
||||
fn extract(ob: &'source PyInstance) -> PyResult<Self>;
|
||||
}
|
||||
|
||||
pub trait RefFromPyObject<'p> {
|
||||
fn with_extracted<F, R>(py: Python, obj: &'p PyObject, f: F) -> PyResult<R>
|
||||
pub trait RefFromPyObject {
|
||||
fn with_extracted<F, R>(ob: &PyInstance, f: F) -> PyResult<R>
|
||||
where F: FnOnce(&Self) -> R;
|
||||
}
|
||||
|
||||
impl <'p, T: ?Sized> RefFromPyObject<'p> for T
|
||||
where for<'a> &'a T: FromPyObject<'p> + Sized
|
||||
impl <T: ?Sized> RefFromPyObject for T
|
||||
where for<'a> &'a T: FromPyObject<'a> + Sized
|
||||
{
|
||||
#[inline]
|
||||
fn with_extracted<F, R>(py: Python, obj: &'p PyObject, f: F) -> PyResult<R>
|
||||
fn with_extracted<F, R>(obj: &PyInstance, f: F) -> PyResult<R>
|
||||
where F: FnOnce(&Self) -> R
|
||||
{
|
||||
match FromPyObject::extract(py, obj) {
|
||||
match FromPyObject::extract(obj) {
|
||||
Ok(val) => Ok(f(val)),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default IntoPyObject implementation
|
||||
/*impl<T> IntoPyObject for T where T: ToPyObject
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, py: Python) -> ::PyObject
|
||||
{
|
||||
self.to_object(py)
|
||||
}
|
||||
}*/
|
||||
|
||||
/// Identity conversion: allows using existing `PyObject` instances where
|
||||
/// `T: ToPyObject` is expected.
|
||||
// `ToPyObject` for references
|
||||
impl <'a, T: ?Sized> ToPyObject for &'a T where T: ToPyObject {
|
||||
|
||||
#[inline]
|
||||
|
@ -130,7 +122,7 @@ impl <T> ToPyObject for Option<T> where T: ToPyObject {
|
|||
}
|
||||
impl<T> IntoPyObject for Option<T> where T: IntoPyObject {
|
||||
|
||||
fn into_object(self, py: Python) -> ::PyObject {
|
||||
fn into_object(self, py: Python) -> PyObject {
|
||||
match self {
|
||||
Some(val) => val.into_object(py),
|
||||
None => py.None(),
|
||||
|
@ -151,24 +143,24 @@ impl IntoPyObject for () {
|
|||
}
|
||||
|
||||
/// Extract reference to instance from `PyObject`
|
||||
impl<'source, T> FromPyObject<'source> for &'source T
|
||||
impl<'a, T> FromPyObject<'a> for &'a T
|
||||
where T: PyTypeInfo + PyDowncastFrom
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(py: Python, ob: &'source PyObject) -> PyResult<&'source T>
|
||||
default fn extract(ob: &'a PyInstance) -> PyResult<&'a T>
|
||||
{
|
||||
Ok(ob.cast_as(py)?)
|
||||
Ok(ob.cast_as()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl <'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'source>
|
||||
impl<'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'source>
|
||||
{
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self>
|
||||
fn extract(obj: &'source PyInstance) -> PyResult<Self>
|
||||
{
|
||||
if obj.as_ptr() == unsafe { ffi::Py_None() } {
|
||||
Ok(None)
|
||||
} else {
|
||||
match T::extract(py, obj) {
|
||||
match T::extract(obj) {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
|
|
61
src/err.rs
61
src/err.rs
|
@ -6,9 +6,11 @@ use std::error::Error;
|
|||
use libc;
|
||||
|
||||
use ffi;
|
||||
use python::{ToPyPointer, IntoPyPointer, Python, PyDowncastInto, PyClone};
|
||||
use objects::{PyObject, PyType, exc};
|
||||
use typeob::{PyTypeObject};
|
||||
use python::{ToPyPointer, IntoPyPointer, Python, PyClone};
|
||||
use PyObject;
|
||||
use objects::{PyInstance, PyType, exc};
|
||||
use instance::Py;
|
||||
use typeob::PyTypeObject;
|
||||
use conversion::{ToPyObject, IntoPyTuple, IntoPyObject};
|
||||
|
||||
/**
|
||||
|
@ -34,10 +36,10 @@ let gil = Python::acquire_gil();
|
|||
let py = gil.python();
|
||||
let ctx = PyDict::new(py);
|
||||
|
||||
ctx.set_item(py, "CustomError", py.get_type::<CustomError>()).unwrap();
|
||||
ctx.set_item("CustomError", py.get_type::<CustomError>()).unwrap();
|
||||
|
||||
py.run("assert str(CustomError) == \"<class 'mymodule.CustomError'>\"", None, Some(&ctx)).unwrap();
|
||||
py.run("assert CustomError('oops').args == ('oops',)", None, Some(&ctx)).unwrap();
|
||||
py.run("assert CustomError('oops').args == ('oops',)", None, Some(ctx)).unwrap();
|
||||
}
|
||||
```
|
||||
*/
|
||||
|
@ -76,7 +78,7 @@ macro_rules! py_exception {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, $name::type_object(py)) }
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +92,7 @@ macro_rules! py_exception {
|
|||
#[derive(Debug)]
|
||||
pub struct PyErr {
|
||||
/// The type of the exception. This should be either a `PyClass` or a `PyType`.
|
||||
pub ptype: PyType,
|
||||
pub ptype: Py<PyType>,
|
||||
/// The value of the exception.
|
||||
///
|
||||
/// This can be either an instance of `ptype`,
|
||||
|
@ -140,24 +142,25 @@ impl PyErr {
|
|||
///
|
||||
/// `base` can be an existing exception type to subclass, or a tuple of classes
|
||||
/// `dict` specifies an optional dictionary of class variables and methods
|
||||
pub fn new_type(py: Python, name: &str, base: Option<PyType>, dict: Option<PyObject>)
|
||||
-> PyType
|
||||
pub fn new_type<'p>(py: Python<'p>,
|
||||
name: &str, base: Option<&PyType>, dict: Option<PyObject>)
|
||||
-> &'p PyType
|
||||
{
|
||||
let base: *mut ffi::PyObject = match base {
|
||||
None => std::ptr::null_mut(),
|
||||
Some(obj) => obj.into_ptr()
|
||||
Some(obj) => obj.as_ptr()
|
||||
};
|
||||
|
||||
let dict: *mut ffi::PyObject = match dict {
|
||||
None => std::ptr::null_mut(),
|
||||
Some(obj) => obj.into_ptr(),
|
||||
Some(obj) => obj.as_ptr(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let null_terminated_name = CString::new(name).expect("Failed to initialize nul terminated exception name");
|
||||
let ptr = ffi::PyErr_NewException(
|
||||
null_terminated_name.as_ptr() as *mut c_char,
|
||||
base, dict) as *mut ffi::PyTypeObject;
|
||||
null_terminated_name.as_ptr() as *mut c_char, base, dict)
|
||||
as *mut ffi::PyTypeObject;
|
||||
PyType::from_type_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
|
@ -183,19 +186,19 @@ impl PyErr {
|
|||
// and because we mustn't panic in normalize().
|
||||
PyErr {
|
||||
ptype: if ptype.is_null() {
|
||||
py.get_type::<exc::SystemError>()
|
||||
py.get_type::<exc::SystemError>().into()
|
||||
} else {
|
||||
PyObject::from_owned_ptr(py, ptype).unchecked_cast_into::<PyType>()
|
||||
PyType::from_type_ptr(py, ptype as *mut ffi::PyTypeObject).into()
|
||||
},
|
||||
pvalue: PyObject::from_owned_ptr_or_opt(py, pvalue),
|
||||
ptraceback: PyObject::from_owned_ptr_or_opt(py, ptraceback)
|
||||
}
|
||||
}
|
||||
|
||||
fn new_helper(_py: Python, ty: PyType, value: PyObject) -> PyErr {
|
||||
fn new_helper(_py: Python, ty: &PyType, value: PyObject) -> PyErr {
|
||||
assert!(unsafe { ffi::PyExceptionClass_Check(ty.as_ptr()) } != 0);
|
||||
PyErr {
|
||||
ptype: ty,
|
||||
ptype: ty.into(),
|
||||
pvalue: Some(value),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -211,23 +214,23 @@ impl PyErr {
|
|||
}
|
||||
|
||||
fn from_instance_helper<'p>(py: Python, obj: PyObject) -> PyErr {
|
||||
if unsafe { ffi::PyExceptionInstance_Check(obj.as_ptr()) } != 0 {
|
||||
let ptr = obj.as_ptr();
|
||||
|
||||
if unsafe { ffi::PyExceptionInstance_Check(ptr) } != 0 {
|
||||
PyErr {
|
||||
ptype: unsafe { PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyExceptionInstance_Class(obj.as_ptr()))
|
||||
.unchecked_cast_into::<PyType>() },
|
||||
ptype: unsafe { PyType::from_type_ptr(py, ptr as *mut ffi::PyTypeObject).into() },
|
||||
pvalue: Some(obj),
|
||||
ptraceback: None
|
||||
}
|
||||
} else if unsafe { ffi::PyExceptionClass_Check(obj.as_ptr()) } != 0 {
|
||||
PyErr {
|
||||
ptype: PyType::downcast_into(py, obj).expect("Failed to downcast into PyType"),
|
||||
ptype: unsafe { Py::from_borrowed_ptr(ptr) },
|
||||
pvalue: None,
|
||||
ptraceback: None
|
||||
}
|
||||
} else {
|
||||
PyErr {
|
||||
ptype: py.get_type::<exc::TypeError>(),
|
||||
ptype: py.get_type::<exc::TypeError>().into(),
|
||||
pvalue: Some("exceptions must derive from BaseException".into_object(py)),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -238,9 +241,9 @@ impl PyErr {
|
|||
/// `exc` is the exception type; usually one of the standard exceptions like `py.get_type::<exc::RuntimeError>()`.
|
||||
/// `value` is the exception instance, or a tuple of arguments to pass to the exception constructor.
|
||||
#[inline]
|
||||
pub fn new_lazy_init(exc: PyType, value: Option<PyObject>) -> PyErr {
|
||||
pub fn new_lazy_init(exc: &PyType, value: Option<PyObject>) -> PyErr {
|
||||
PyErr {
|
||||
ptype: exc,
|
||||
ptype: exc.into(),
|
||||
pvalue: value,
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -254,7 +257,7 @@ impl PyErr {
|
|||
where A: IntoPyTuple
|
||||
{
|
||||
PyErr {
|
||||
ptype: exc.clone_ref(py),
|
||||
ptype: exc.into(),
|
||||
pvalue: Some(args.into_tuple(py).into()),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -307,7 +310,7 @@ impl PyErr {
|
|||
}
|
||||
|
||||
/// Retrieves the exception type.
|
||||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
pub fn get_type(&self, py: Python) -> Py<PyType> {
|
||||
self.ptype.clone_ref(py)
|
||||
}
|
||||
|
||||
|
@ -317,7 +320,7 @@ impl PyErr {
|
|||
pub fn instance(&mut self, py: Python) -> PyObject {
|
||||
self.normalize(py);
|
||||
match self.pvalue {
|
||||
Some(ref instance) => instance.to_object(py),
|
||||
Some(ref instance) => instance.clone_ref(py),
|
||||
None => py.None(),
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +337,7 @@ impl PyErr {
|
|||
|
||||
/// Issue a warning message.
|
||||
/// May return a PyErr if warnings-as-errors is enabled.
|
||||
pub fn warn(py: Python, category: &PyObject, message: &str, stacklevel: i32) -> PyResult<()> {
|
||||
pub fn warn(py: Python, category: &PyInstance, message: &str, stacklevel: i32) -> PyResult<()> {
|
||||
let message = CString::new(message).map_err(|e| e.to_pyerr(py))?;
|
||||
unsafe {
|
||||
error_on_minusone(py, ffi::PyErr_WarnEx(
|
||||
|
|
|
@ -27,6 +27,12 @@ pub unsafe fn PyString_Check(op : *mut PyObject) -> c_int {
|
|||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_STRING_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyBaseString_Check(op : *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(
|
||||
Py_TYPE(op), Py_TPFLAGS_STRING_SUBCLASS | Py_TPFLAGS_UNICODE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyString_CheckExact(op : *mut PyObject) -> c_int {
|
||||
let u : *mut PyTypeObject = &mut PyString_Type;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::os::raw::{c_void, c_int, c_uint, c_ulong, c_char};
|
|||
use ffi3::pyport::{Py_ssize_t, Py_hash_t};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PyObject {
|
||||
#[cfg(py_sys_config="Py_TRACE_REFS")]
|
||||
_ob_next: *mut PyObject,
|
||||
|
@ -36,6 +36,9 @@ pub struct PyVarObject {
|
|||
|
||||
#[inline(always)]
|
||||
pub unsafe fn Py_REFCNT(ob : *mut PyObject) -> Py_ssize_t {
|
||||
if ob.is_null() {
|
||||
panic!();
|
||||
}
|
||||
(*ob).ob_refcnt
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ pub enum PyThreadState { }
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum PyGILState_STATE {
|
||||
PyGILState_LOCKED,
|
||||
PyGILState_UNLOCKED
|
||||
|
|
35
src/fmt.rs
35
src/fmt.rs
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use pointers::PyPtr;
|
||||
use python::Python;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
impl fmt::Debug for PyPtr {
|
||||
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_object(py);
|
||||
let repr_obj = try!(r.repr(py).map_err(|_| fmt::Error));
|
||||
let result = f.write_str(&repr_obj.to_string_lossy(py));
|
||||
py.release(repr_obj);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PyPtr {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_object(py);
|
||||
let str_obj = try!(r.str(py).map_err(|_| fmt::Error));
|
||||
let result = f.write_str(&str_obj.to_string_lossy(py));
|
||||
py.release(str_obj);
|
||||
result
|
||||
}
|
||||
}
|
|
@ -6,8 +6,10 @@ use std::marker::PhantomData;
|
|||
|
||||
use ffi;
|
||||
use err::{PyResult, PyErr, PyDowncastError};
|
||||
use objects::PyObject;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use pointer::PyObject;
|
||||
use objects::PyInstance;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
use python::{Python, IntoPyPointer, ToPyPointer, PyDowncastInto};
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
@ -15,16 +17,19 @@ use typeob::{PyTypeInfo, PyObjectAlloc};
|
|||
pub struct PyToken(PhantomData<Rc<()>>);
|
||||
|
||||
impl PyToken {
|
||||
pub fn token(&self) -> Python {
|
||||
pub fn py<'p>(&'p self) -> Python<'p> {
|
||||
unsafe { Python::assume_gil_acquired() }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyObjectWithToken : Sized {
|
||||
pub trait PyObjectWithToken: Sized {
|
||||
fn token(&self) -> Python;
|
||||
}
|
||||
|
||||
pub trait AsPyRef<T> : Sized {
|
||||
pub trait PyNativeType: PyObjectWithToken {}
|
||||
|
||||
|
||||
pub trait AsPyRef<T>: Sized {
|
||||
|
||||
fn as_ref(&self, py: Python) -> &T;
|
||||
|
||||
|
@ -70,9 +75,10 @@ pub trait AsPyRef<T> : Sized {
|
|||
}
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
pub struct Py<T>(*mut ffi::PyObject, std::marker::PhantomData<T>);
|
||||
#[derive(Debug)]
|
||||
pub struct Py<T>(pub *mut ffi::PyObject, std::marker::PhantomData<T>);
|
||||
|
||||
// `PyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
// `Py<T>` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl<T> Send for Py<T> {}
|
||||
unsafe impl<T> Sync for Py<T> {}
|
||||
|
||||
|
@ -129,12 +135,6 @@ impl<T> Py<T> {
|
|||
unsafe { ffi::Py_REFCNT(self.0) }
|
||||
}
|
||||
|
||||
/// Get reference to &PyObject.
|
||||
#[inline]
|
||||
pub fn as_object<'p>(&self, _py: Python<'p>) -> &PyObject {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> Py<T> {
|
||||
|
@ -179,7 +179,7 @@ impl<T> Py<T> where T: PyTypeInfo,
|
|||
impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
||||
|
||||
#[inline]
|
||||
fn as_ref(&self, _py: Python) -> &T {
|
||||
default fn as_ref(&self, _py: Python) -> &T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut T;
|
||||
|
@ -187,7 +187,7 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
|||
}
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut(&self, _py: Python) -> &mut T {
|
||||
default fn as_mut(&self, _py: Python) -> &mut T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut T;
|
||||
|
@ -196,9 +196,23 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo + PyNativeType {
|
||||
|
||||
#[inline]
|
||||
fn as_ref(&self, _py: Python) -> &T {
|
||||
unsafe {std::mem::transmute(self)}
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut(&self, _py: Python) -> &mut T {
|
||||
unsafe {std::mem::transmute(self as *const _ as *mut T)}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToPyObject for Py<T> {
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,8 +264,9 @@ impl<T> Drop for Py<T> {
|
|||
|
||||
|
||||
impl<T> std::convert::From<Py<T>> for PyObject {
|
||||
#[inline]
|
||||
fn from(ob: Py<T>) -> Self {
|
||||
unsafe{std::mem::transmute(ob)}
|
||||
unsafe {std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,10 +310,7 @@ impl<T> PyDowncastInto for Py<T> where T: PyTypeInfo
|
|||
{
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
ptr, <T as PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
if T::is_instance(ptr) {
|
||||
Ok(Py::from_owned_ptr(ptr))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
|
@ -307,12 +319,11 @@ impl<T> PyDowncastInto for Py<T> where T: PyTypeInfo
|
|||
}
|
||||
}
|
||||
|
||||
fn downcast_from_ptr<'p>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError<'p>>
|
||||
fn downcast_into_from_ptr<'p>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError<'p>>
|
||||
{
|
||||
unsafe{
|
||||
let checked = ffi::PyObject_TypeCheck(ptr, <T as PyTypeInfo>::type_object()) != 0;
|
||||
if checked {
|
||||
if T::is_instance(ptr) {
|
||||
Ok(Py::from_owned_ptr(ptr))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
|
@ -331,20 +342,13 @@ impl<T> PyDowncastInto for Py<T> where T: PyTypeInfo
|
|||
}
|
||||
|
||||
|
||||
impl<'a, T> ::FromPyObject<'a> for Py<T> where T: PyTypeInfo
|
||||
impl<'a, T> FromPyObject<'a> for Py<T> where T: ToPyPointer + FromPyObject<'a>
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'a PyObject) -> PyResult<Self>
|
||||
fn extract(ob: &'a PyInstance) -> PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
ob.as_ptr(), <T as PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
Ok( Py::from_borrowed_ptr(ob.as_ptr()) )
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None).into())
|
||||
}
|
||||
ob.extract::<T>().map(|val| Py::from_borrowed_ptr(val.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
30
src/lib.rs
30
src/lib.rs
|
@ -34,7 +34,7 @@
|
|||
//! ```rust
|
||||
//! extern crate pyo3;
|
||||
//!
|
||||
//! use pyo3::{Python, PyDict, PyResult};
|
||||
//! use pyo3::{Python, PyDict, PyResult, ObjectProtocol};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let gil = Python::acquire_gil();
|
||||
|
@ -43,11 +43,11 @@
|
|||
//!
|
||||
//! fn hello(py: Python) -> PyResult<()> {
|
||||
//! let sys = py.import("sys")?;
|
||||
//! let version: String = sys.get(py, "version")?.extract(py)?;
|
||||
//! let version: String = sys.get("version")?.extract()?;
|
||||
//!
|
||||
//! let locals = PyDict::new(py);
|
||||
//! locals.set_item(py, "os", py.import("os")?)?;
|
||||
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;
|
||||
//! locals.set_item("os", py.import("os")?)?;
|
||||
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(locals))?.extract()?;
|
||||
//!
|
||||
//! println!("Hello {}, I'm Python {}", user, version);
|
||||
//! Ok(())
|
||||
|
@ -72,7 +72,7 @@
|
|||
//!
|
||||
//! 1. `m`: The module name.
|
||||
//! 2. name of function visible to Python code.
|
||||
//! 3. arguments description string, i.e. "param1, param2=None, *, param3=55"
|
||||
//! 3. comma separated arguments, i.e. param="None", "*", param3="55"
|
||||
//!
|
||||
//!
|
||||
//! # Example
|
||||
|
@ -81,7 +81,7 @@
|
|||
//! #![feature(proc_macro, specialization)]
|
||||
//!
|
||||
//! extern crate pyo3;
|
||||
//! use pyo3::{py, Python, PyResult, PyObject, PyModule, PyString};
|
||||
//! use pyo3::{py, Python, PyResult, PyModule, PyString, ObjectProtocol};
|
||||
//!
|
||||
//! // add bindings to the generated python module
|
||||
//! // N.B: names: "libhello" must be the name of the `.so` or `.pyd` file
|
||||
|
@ -95,9 +95,9 @@
|
|||
//! // Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
||||
//! // Python objects to Rust values; and the Rust return value back into a Python object.
|
||||
//! #[pyfn(m, "run_rust_func")]
|
||||
//! fn run(py: Python, name: PyString) -> PyResult<PyObject> {
|
||||
//! fn run(py: Python, name: &PyString) -> PyResult<()> {
|
||||
//! println!("Rust says: Hello {} of Python!", name);
|
||||
//! Ok(py.None())
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! Ok(())
|
||||
|
@ -152,20 +152,15 @@ pub mod ffi {
|
|||
}
|
||||
|
||||
pub use ffi::{Py_ssize_t, Py_hash_t};
|
||||
|
||||
mod pointers;
|
||||
pub use pointers::PyPtr;
|
||||
|
||||
pub mod token;
|
||||
pub use token::{PyToken, PyObjectWithToken, Py, AsPyRef};
|
||||
|
||||
pub use err::{PyErr, PyResult, PyDowncastError, ToPyErr};
|
||||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use pointer::PyObject;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer, PyClone,
|
||||
PyMutDowncastFrom, PyDowncastFrom, PyDowncastInto};
|
||||
pub use pythonrun::{GILGuard, prepare_freethreaded_python};
|
||||
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, IntoPyTuple};
|
||||
pub use instance::{PyToken, PyObjectWithToken, AsPyRef, Py, PyNativeType};
|
||||
pub use conversion::{FromPyObject, ToPyObject, IntoPyObject, IntoPyTuple};
|
||||
pub mod class;
|
||||
pub use class::*;
|
||||
|
||||
|
@ -190,11 +185,12 @@ macro_rules! cstr(
|
|||
);
|
||||
|
||||
mod python;
|
||||
mod fmt;
|
||||
mod err;
|
||||
mod conversion;
|
||||
mod instance;
|
||||
mod objects;
|
||||
mod objectprotocol;
|
||||
mod pointer;
|
||||
mod pythonrun;
|
||||
pub mod callback;
|
||||
pub mod typeob;
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use libc;
|
||||
use std;
|
||||
use std::cmp::Ordering;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult, self};
|
||||
use python::{Python, PyDowncastInto, ToPyPointer};
|
||||
use objects::{PyObject, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, IntoPyTuple};
|
||||
use err::{PyErr, PyResult, PyDowncastError, self};
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom, PyClone};
|
||||
use pointer::PyObject;
|
||||
use objects::{PyInstance, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, IntoPyTuple, FromPyObject};
|
||||
use instance::PyObjectWithToken;
|
||||
|
||||
|
||||
pub trait ObjectProtocol {
|
||||
|
||||
/// Determines whether this object has the given attribute.
|
||||
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
||||
fn hasattr<N>(&self, py: Python, attr_name: N) -> PyResult<bool> where N: ToPyObject;
|
||||
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> where N: ToPyObject;
|
||||
|
||||
/// Retrieves an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name'.
|
||||
fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject> where N: ToPyObject;
|
||||
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyInstance> where N: ToPyObject;
|
||||
|
||||
/// Sets an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name = value'.
|
||||
fn setattr<N, V>(&self, py: Python, attr_name: N, value: V) -> PyResult<()>
|
||||
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
||||
where N: ToPyObject, V: ToPyObject;
|
||||
|
||||
/// Deletes an attribute.
|
||||
/// This is equivalent to the Python expression 'del self.attr_name'.
|
||||
fn delattr<N>(&self, py: Python, attr_name: N) -> PyResult<()> where N: ToPyObject;
|
||||
fn delattr<N>(&self, attr_name: N) -> PyResult<()> where N: ToPyObject;
|
||||
|
||||
/// Compares two Python objects.
|
||||
///
|
||||
|
@ -46,7 +47,7 @@ pub trait ObjectProtocol {
|
|||
/// else:
|
||||
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
|
||||
/// ```
|
||||
fn compare<O>(&self, py: Python, other: O) -> PyResult<Ordering> where O: ToPyObject;
|
||||
fn compare<O>(&self, other: O) -> PyResult<Ordering> where O: ToPyObject;
|
||||
|
||||
/// Compares two Python objects.
|
||||
///
|
||||
|
@ -57,136 +58,133 @@ pub trait ObjectProtocol {
|
|||
/// * CompareOp::Le: `self <= other`
|
||||
/// * CompareOp::Gt: `self > other`
|
||||
/// * CompareOp::Ge: `self >= other`
|
||||
fn rich_compare<O>(&self, py: Python, other: O, compare_op: ::CompareOp)
|
||||
-> PyResult<PyObject> where O: ToPyObject;
|
||||
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp) -> PyResult<PyObject>
|
||||
where O: ToPyObject;
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'repr(self)'.
|
||||
fn repr(&self, py: Python) -> PyResult<PyString>;
|
||||
fn repr(&self) -> PyResult<&PyString>;
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'str(self)'.
|
||||
fn str(&self, py: Python) -> PyResult<PyString>;
|
||||
fn str(&self) -> PyResult<&PyString>;
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
fn is_callable(&self, py: Python) -> bool;
|
||||
fn is_callable(&self) -> bool;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyInstance>
|
||||
where A: IntoPyTuple;
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
fn call_method<A>(&self, py: Python,
|
||||
name: &str, args: A,
|
||||
kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>)
|
||||
-> PyResult<&PyInstance>
|
||||
where A: IntoPyTuple;
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: 'hash(self)'
|
||||
fn hash(&self, py: Python) -> PyResult<::Py_hash_t>;
|
||||
fn hash(&self) -> PyResult<::Py_hash_t>;
|
||||
|
||||
/// Returns whether the object is considered to be true.
|
||||
/// This is equivalent to the Python expression: 'not not self'
|
||||
fn is_true(&self, py: Python) -> PyResult<bool>;
|
||||
fn is_true(&self) -> PyResult<bool>;
|
||||
|
||||
/// Returns whether the object is considered to be None.
|
||||
/// This is equivalent to the Python expression: 'is None'
|
||||
#[inline]
|
||||
fn is_none(&self, py: Python) -> bool;
|
||||
fn is_none(&self) -> bool;
|
||||
|
||||
/// Returns the length of the sequence or mapping.
|
||||
/// This is equivalent to the Python expression: 'len(self)'
|
||||
fn len(&self, py: Python) -> PyResult<usize>;
|
||||
fn len(&self) -> PyResult<usize>;
|
||||
|
||||
/// This is equivalent to the Python expression: 'self[key]'
|
||||
fn get_item<K>(&self, py: Python, key: K) -> PyResult<PyObject> where K: ToPyObject;
|
||||
fn get_item<K>(&self, key: K) -> PyResult<&PyInstance> where K: ToPyObject;
|
||||
|
||||
/// Sets an item value.
|
||||
/// This is equivalent to the Python expression 'self[key] = value'.
|
||||
fn set_item<K, V>(&self, py: Python, key: K, value: V) -> PyResult<()>
|
||||
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||
where K: ToPyObject, V: ToPyObject;
|
||||
|
||||
/// Deletes an item.
|
||||
/// This is equivalent to the Python expression 'del self[key]'.
|
||||
fn del_item<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject;
|
||||
fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject;
|
||||
|
||||
/// Takes an object and returns an iterator for it.
|
||||
/// This is typically a new iterator but if the argument
|
||||
/// is an iterator, this returns itself.
|
||||
fn iter<'p>(&self, py: Python<'p>) -> PyResult<PyIterator<'p>>;
|
||||
fn iter<'p>(&'p self) -> PyResult<PyIterator<'p>>;
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self, py: Python) -> PyType;
|
||||
fn get_type(&self) -> &PyType;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError<'a>>
|
||||
where D: PyDowncastFrom,
|
||||
&'a PyInstance: std::convert::From<&'a Self>;
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
fn extract<'a, D>(&'a self) -> PyResult<D>
|
||||
where D: FromPyObject<'a>,
|
||||
&'a PyInstance: std::convert::From<&'a Self>;
|
||||
|
||||
/// Returns reference count for python object.
|
||||
fn get_refcnt(&self) -> isize;
|
||||
|
||||
/// Clones PyObject. (utility function)
|
||||
fn clone_ref(&self, ptr: &PyObject) -> PyObject;
|
||||
|
||||
/// Gets the Python builtin value `None`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
fn None(&self) -> PyObject;
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl<T> ObjectProtocol for T where T: ToPyPointer {
|
||||
impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
||||
|
||||
/// Determines whether this object has the given attribute.
|
||||
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
||||
#[inline]
|
||||
fn hasattr<N>(&self, py: Python, attr_name: N) -> PyResult<bool> where N: ToPyObject {
|
||||
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
|
||||
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> where N: ToPyObject {
|
||||
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
|
||||
Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name) != 0)
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieves an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name'.
|
||||
#[inline]
|
||||
fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject> where N: ToPyObject
|
||||
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyInstance> where N: ToPyObject
|
||||
{
|
||||
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
|
||||
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
|
||||
self.token().cast_from_ptr_or_err(
|
||||
ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name = value'.
|
||||
#[inline]
|
||||
fn setattr<N, V>(&self, py: Python, attr_name: N, value: V) -> PyResult<()>
|
||||
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
||||
where N: ToPyObject, V: ToPyObject
|
||||
{
|
||||
attr_name.with_borrowed_ptr(
|
||||
py, move |attr_name|
|
||||
value.with_borrowed_ptr(py, |value| unsafe {
|
||||
self.token(), move |attr_name|
|
||||
value.with_borrowed_ptr(self.token(), |value| unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value))
|
||||
self.token(), ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Deletes an attribute.
|
||||
/// This is equivalent to the Python expression 'del self.attr_name'.
|
||||
#[inline]
|
||||
fn delattr<N>(&self, py: Python, attr_name: N) -> PyResult<()> where N: ToPyObject {
|
||||
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
|
||||
err::error_on_minusone(py,
|
||||
fn delattr<N>(&self, attr_name: N) -> PyResult<()> where N: ToPyObject {
|
||||
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
|
||||
err::error_on_minusone(self.token(),
|
||||
ffi::PyObject_DelAttr(self.as_ptr(), attr_name))
|
||||
})
|
||||
}
|
||||
|
||||
/// Compares two Python objects.
|
||||
///
|
||||
/// On Python 2, this is equivalent to the Python expression 'cmp(self, other)'.
|
||||
///
|
||||
/// On Python 3, this is equivalent to:
|
||||
/// ```
|
||||
/// if self == other:
|
||||
/// return Equal
|
||||
/// elif a < b:
|
||||
/// return Less
|
||||
/// elif a > b:
|
||||
/// return Greater
|
||||
/// else:
|
||||
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
|
||||
/// ```
|
||||
fn compare<O>(&self, py: Python, other: O) -> PyResult<Ordering> where O: ToPyObject {
|
||||
fn compare<O>(&self, other: O) -> PyResult<Ordering> where O: ToPyObject {
|
||||
unsafe fn do_compare(py: Python,
|
||||
a: *mut ffi::PyObject,
|
||||
b: *mut ffi::PyObject) -> PyResult<Ordering> {
|
||||
|
@ -211,183 +209,176 @@ impl<T> ObjectProtocol for T where T: ToPyPointer {
|
|||
Err(PyErr::new::<::exc::TypeError, _>(py, "ObjectProtocol::compare(): All comparisons returned false"))
|
||||
}
|
||||
|
||||
other.with_borrowed_ptr(py, |other| unsafe {
|
||||
do_compare(py, self.as_ptr(), other)
|
||||
other.with_borrowed_ptr(self.token(), |other| unsafe {
|
||||
do_compare(self.token(), self.as_ptr(), other)
|
||||
})
|
||||
}
|
||||
|
||||
/// Compares two Python objects.
|
||||
///
|
||||
/// Depending on the value of `compare_op`, equivalent to one of the following Python expressions:
|
||||
/// * CompareOp::Eq: `self == other`
|
||||
/// * CompareOp::Ne: `self != other`
|
||||
/// * CompareOp::Lt: `self < other`
|
||||
/// * CompareOp::Le: `self <= other`
|
||||
/// * CompareOp::Gt: `self > other`
|
||||
/// * CompareOp::Ge: `self >= other`
|
||||
fn rich_compare<O>(&self, py: Python, other: O, compare_op: ::CompareOp)
|
||||
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp)
|
||||
-> PyResult<PyObject> where O: ToPyObject {
|
||||
unsafe {
|
||||
other.with_borrowed_ptr(py, |other| {
|
||||
other.with_borrowed_ptr(self.token(), |other| {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_RichCompare(
|
||||
self.as_ptr(), other, compare_op as libc::c_int))
|
||||
self.token(), ffi::PyObject_RichCompare(
|
||||
self.as_ptr(), other, compare_op as c_int))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'repr(self)'.
|
||||
#[inline]
|
||||
fn repr(&self, py: Python) -> PyResult<PyString> {
|
||||
Ok(PyString::downcast_from_ptr(
|
||||
py, unsafe{ffi::PyObject_Repr(self.as_ptr())})?)
|
||||
fn repr(&self) -> PyResult<&PyString> {
|
||||
unsafe {
|
||||
self.token().cast_from_ptr_or_err(ffi::PyObject_Repr(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'str(self)'.
|
||||
#[inline]
|
||||
fn str(&self, py: Python) -> PyResult<PyString> {
|
||||
Ok(PyString::downcast_from_ptr(
|
||||
py, unsafe{ffi::PyObject_Str(self.as_ptr())})?)
|
||||
fn str(&self) -> PyResult<&PyString> {
|
||||
unsafe {
|
||||
self.token().cast_from_ptr_or_err(ffi::PyObject_Str(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
#[inline]
|
||||
fn is_callable(&self, _py: Python) -> bool {
|
||||
fn is_callable(&self) -> bool {
|
||||
unsafe {
|
||||
ffi::PyCallable_Check(self.as_ptr()) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
#[inline]
|
||||
fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyInstance>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
let t = args.into_tuple(py);
|
||||
let t = args.into_tuple(self.token());
|
||||
let result = unsafe {
|
||||
PyObject::from_borrowed_ptr_or_err(
|
||||
py, ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
self.token().cast_from_borrowed_ptr_or_err(
|
||||
ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
};
|
||||
py.release(t);
|
||||
self.token().release(t);
|
||||
result
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
#[inline]
|
||||
fn call_method<A>(&self, py: Python,
|
||||
name: &str, args: A,
|
||||
kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>)
|
||||
-> PyResult<&PyInstance>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
name.with_borrowed_ptr(py, |name| unsafe {
|
||||
let t = args.into_tuple(py);
|
||||
name.with_borrowed_ptr(self.token(), |name| unsafe {
|
||||
let t = args.into_tuple(self.token());
|
||||
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
|
||||
let result = PyObject::from_borrowed_ptr_or_err(
|
||||
py, ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()));
|
||||
py.release(t);
|
||||
let result = self.token().cast_from_borrowed_ptr_or_err(
|
||||
ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()));
|
||||
self.token().release(t);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: 'hash(self)'
|
||||
#[inline]
|
||||
fn hash(&self, py: Python) -> PyResult<ffi::Py_hash_t> {
|
||||
fn hash(&self) -> PyResult<ffi::Py_hash_t> {
|
||||
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be true.
|
||||
/// This is equivalent to the Python expression: 'not not self'
|
||||
#[inline]
|
||||
fn is_true(&self, py: Python) -> PyResult<bool> {
|
||||
fn is_true(&self) -> PyResult<bool> {
|
||||
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(v != 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be None.
|
||||
/// This is equivalent to the Python expression: 'is None'
|
||||
#[inline]
|
||||
fn is_none(&self, _py: Python) -> bool {
|
||||
fn is_none(&self) -> bool {
|
||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||
}
|
||||
|
||||
/// Returns the length of the sequence or mapping.
|
||||
/// This is equivalent to the Python expression: 'len(self)'
|
||||
#[inline]
|
||||
fn len(&self, py: Python) -> PyResult<usize> {
|
||||
fn len(&self) -> PyResult<usize> {
|
||||
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(v as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is equivalent to the Python expression: 'self[key]'
|
||||
#[inline]
|
||||
fn get_item<K>(&self, py: Python, key: K) -> PyResult<PyObject> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_GetItem(self.as_ptr(), key))
|
||||
fn get_item<K>(&self, key: K) -> PyResult<&PyInstance> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
self.token().cast_from_ptr_or_err(
|
||||
ffi::PyObject_GetItem(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets an item value.
|
||||
/// This is equivalent to the Python expression 'self[key] = value'.
|
||||
#[inline]
|
||||
fn set_item<K, V>(&self, py: Python, key: K, value: V) -> PyResult<()>
|
||||
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||
where K: ToPyObject, V: ToPyObject
|
||||
{
|
||||
key.with_borrowed_ptr(py, move |key|
|
||||
value.with_borrowed_ptr(py, |value| unsafe {
|
||||
err::error_on_minusone(py,
|
||||
ffi::PyObject_SetItem(self.as_ptr(), key, value))
|
||||
key.with_borrowed_ptr(
|
||||
self.token(), move |key|
|
||||
value.with_borrowed_ptr(self.token(), |value| unsafe {
|
||||
err::error_on_minusone(
|
||||
self.token(), ffi::PyObject_SetItem(self.as_ptr(), key, value))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Deletes an item.
|
||||
/// This is equivalent to the Python expression 'del self[key]'.
|
||||
#[inline]
|
||||
fn del_item<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
err::error_on_minusone(py,
|
||||
ffi::PyObject_DelItem(self.as_ptr(), key))
|
||||
fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
err::error_on_minusone(
|
||||
self.token(), ffi::PyObject_DelItem(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
/// Takes an object and returns an iterator for it.
|
||||
/// This is typically a new iterator but if the argument
|
||||
/// is an iterator, this returns itself.
|
||||
#[inline]
|
||||
fn iter<'p>(&self, py: Python<'p>) -> PyResult<PyIterator<'p>> {
|
||||
fn iter<'p>(&'p self) -> PyResult<PyIterator<'p>> {
|
||||
unsafe {
|
||||
let ptr = PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_GetIter(self.as_ptr()))?;
|
||||
PyIterator::from_object(py, ptr).map_err(|e| e.into())
|
||||
self.token(), ffi::PyObject_GetIter(self.as_ptr()))?;
|
||||
PyIterator::from_object(self.token(), ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self, py: Python) -> PyType {
|
||||
fn get_type(&self) -> &PyType {
|
||||
unsafe {
|
||||
PyType::from_type_ptr(py, (*self.as_ptr()).ob_type)
|
||||
PyType::from_type_ptr(self.token(), (*self.as_ptr()).ob_type)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError<'a>>
|
||||
where D: PyDowncastFrom,
|
||||
&'a PyInstance: std::convert::From<&'a Self>
|
||||
{
|
||||
<D as PyDowncastFrom>::downcast_from(self.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extract<'a, D>(&'a self) -> PyResult<D>
|
||||
where D: FromPyObject<'a>,
|
||||
&'a PyInstance: std::convert::From<&'a T>
|
||||
{
|
||||
FromPyObject::extract(self.into())
|
||||
}
|
||||
|
||||
fn clone_ref(&self, ptr: &PyObject) -> PyObject {
|
||||
ptr.clone_ref(self.token())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
fn None(&self) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(self.token(), ffi::Py_None()) }
|
||||
}
|
||||
|
||||
fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
|
||||
}
|
||||
|
@ -395,17 +386,18 @@ impl<T> ObjectProtocol for T where T: ToPyPointer {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python};
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
//use objects::{PyTuple}; //PyList,
|
||||
use super::ObjectProtocol;
|
||||
use objects::PyString;
|
||||
|
||||
#[test]
|
||||
fn test_debug_string() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
assert_eq!(format!("{:?}", v), "'Hello\\n'");
|
||||
let s = PyString::downcast_from(v.as_ref(py)).unwrap();
|
||||
assert_eq!(format!("{:?}", s), "'Hello\\n'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -413,17 +405,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
assert_eq!(format!("{}", v), "Hello\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compare() {
|
||||
use std::cmp::Ordering;
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let one = 1i32.to_object(py);
|
||||
assert_eq!(one.compare(py, 1).unwrap(), Ordering::Equal);
|
||||
assert_eq!(one.compare(py, 2).unwrap(), Ordering::Less);
|
||||
assert_eq!(one.compare(py, 0).unwrap(), Ordering::Greater);
|
||||
let s = PyString::downcast_from(v.as_ref(py)).unwrap();
|
||||
assert_eq!(format!("{}", s), "Hello\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{ToPyPointer, Python};
|
||||
use objects::PyObject;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `bool`.
|
||||
pub struct PyBool(PyPtr);
|
||||
pub struct PyBool(PyObject);
|
||||
|
||||
pyobject_convert!(PyBool);
|
||||
pyobject_nativetype!(PyBool, PyBool_Type, PyBool_Check);
|
||||
|
@ -14,15 +13,15 @@ pyobject_nativetype!(PyBool, PyBool_Type, PyBool_Check);
|
|||
impl PyBool {
|
||||
/// Depending on `val`, returns `py.True()` or `py.False()`.
|
||||
#[inline]
|
||||
pub fn new(_py: Python, val: bool) -> PyBool {
|
||||
unsafe { PyBool(
|
||||
PyPtr::from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() })
|
||||
)}
|
||||
pub fn new<'p>(py: Python<'p>, val: bool) -> &'p PyBool {
|
||||
unsafe {
|
||||
py.cast_from_ptr(if val { ffi::Py_True() } else { ffi::Py_False() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets whether this boolean is `true`.
|
||||
#[inline]
|
||||
pub fn is_true(&self, _py: Python) -> bool {
|
||||
pub fn is_true(&self) -> bool {
|
||||
self.as_ptr() == unsafe { ::ffi::Py_True() }
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +30,11 @@ impl PyBool {
|
|||
impl ToPyObject for bool {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
PyBool::new(py, *self).into()
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(
|
||||
py,
|
||||
if *self { ffi::Py_True() } else { ffi::Py_False() })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -54,23 +57,24 @@ impl IntoPyObject for bool {
|
|||
///
|
||||
/// Fails with `TypeError` if the input is not a Python `bool`.
|
||||
pyobject_extract!(py, obj to bool => {
|
||||
Ok(try!(obj.cast_as::<PyBool>(py)).is_true(py))
|
||||
Ok(try!(obj.cast_as::<PyBool>()).is_true())
|
||||
});
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python};
|
||||
use objects::PyObject;
|
||||
use python::Python;
|
||||
use objects::PyInstance;
|
||||
use conversion::ToPyObject;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
fn test_true() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(py.True().is_true(py));
|
||||
let t: PyObject = py.True().into();
|
||||
assert_eq!(true, t.extract(py).unwrap());
|
||||
assert!(py.True().is_true());
|
||||
let t: &PyInstance = py.True().into();
|
||||
assert_eq!(true, t.extract().unwrap());
|
||||
assert!(true.to_object(py) == py.True().into());
|
||||
}
|
||||
|
||||
|
@ -78,9 +82,9 @@ mod test {
|
|||
fn test_false() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(!py.False().is_true(py));
|
||||
let t: PyObject = py.False().into();
|
||||
assert_eq!(false, t.extract(py).unwrap());
|
||||
assert!(!py.False().is_true());
|
||||
let t: &PyInstance = py.False().into();
|
||||
assert_eq!(false, t.extract().unwrap());
|
||||
assert!(false.to_object(py) == py.False().into());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
use std::ptr;
|
||||
use std::os::raw::c_char;
|
||||
use ffi;
|
||||
use pointer::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyResult, PyErr};
|
||||
use pointers::PyPtr;
|
||||
|
||||
|
||||
/// Represents a Python bytearray.
|
||||
pub struct PyByteArray(PyPtr);
|
||||
pub struct PyByteArray(PyObject);
|
||||
|
||||
pyobject_convert!(PyByteArray);
|
||||
pyobject_nativetype!(PyByteArray, PyByteArray_Type, PyByteArray_Check);
|
||||
|
@ -21,29 +19,29 @@ impl PyByteArray {
|
|||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(_py: Python, src: &[u8]) -> PyByteArray {
|
||||
pub fn new<'p>(py: Python<'p>, src: &[u8]) -> &'p PyByteArray {
|
||||
let ptr = src.as_ptr() as *const c_char;
|
||||
let len = src.len() as ffi::Py_ssize_t;
|
||||
let ptr = unsafe {ffi::PyByteArray_FromStringAndSize(ptr, len)};
|
||||
PyByteArray(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
unsafe {
|
||||
py.cast_from_ptr::<PyByteArray>(
|
||||
ffi::PyByteArray_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new Python bytearray object
|
||||
/// from other PyObject, that implements the buffer protocol.
|
||||
pub fn from<I>(py: Python, src: I) -> PyResult<PyByteArray>
|
||||
pub fn from<'p, I>(py: Python<'p>, src: I) -> PyResult<&'p PyByteArray>
|
||||
where I: ToPyPointer
|
||||
{
|
||||
let res = unsafe {ffi::PyByteArray_FromObject(src.as_ptr())};
|
||||
if res != ptr::null_mut() {
|
||||
Ok(PyByteArray(PyPtr::from_owned_ptr_or_panic(res)))
|
||||
} else {
|
||||
Err(PyErr::fetch(py))
|
||||
unsafe {
|
||||
py.cast_from_ptr_or_err(
|
||||
ffi::PyByteArray_FromObject(src.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the length of the bytearray.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
// non-negative Py_ssize_t should always fit into Rust usize
|
||||
unsafe {
|
||||
ffi::PyByteArray_Size(self.0.as_ptr()) as usize
|
||||
|
@ -51,7 +49,7 @@ impl PyByteArray {
|
|||
}
|
||||
|
||||
/// Gets the Python bytearray data as byte slice.
|
||||
pub fn data(&self, _py: Python) -> &mut [u8] {
|
||||
pub fn data(&self) -> &mut [u8] {
|
||||
unsafe {
|
||||
let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8;
|
||||
let length = ffi::PyByteArray_Size(self.0.as_ptr()) as usize;
|
||||
|
@ -60,13 +58,13 @@ impl PyByteArray {
|
|||
}
|
||||
|
||||
/// Resize bytearray object.
|
||||
pub fn resize(&self, py: Python, len: usize) -> PyResult<()> {
|
||||
pub fn resize(&self, len: usize) -> PyResult<()> {
|
||||
unsafe {
|
||||
let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t);
|
||||
if result == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,8 @@ impl PyByteArray {
|
|||
mod test {
|
||||
use exc;
|
||||
use python::Python;
|
||||
use objects::{PyObject, PyByteArray};
|
||||
use pointer::PyObject;
|
||||
use objects::PyByteArray;
|
||||
|
||||
#[test]
|
||||
fn test_bytearray() {
|
||||
|
@ -86,20 +85,21 @@ mod test {
|
|||
|
||||
let src = b"Hello Python";
|
||||
let bytearray = PyByteArray::new(py, src);
|
||||
assert_eq!(src.len(), bytearray.len(py));
|
||||
assert_eq!(src, bytearray.data(py));
|
||||
assert_eq!(src.len(), bytearray.len());
|
||||
assert_eq!(src, bytearray.data());
|
||||
|
||||
let ba: PyObject = bytearray.into();
|
||||
let bytearray = PyByteArray::from(py, &ba).unwrap();
|
||||
assert_eq!(src.len(), bytearray.len(py));
|
||||
assert_eq!(src, bytearray.data(py));
|
||||
let bytearray = PyByteArray::from(py, ba).unwrap();
|
||||
|
||||
bytearray.resize(py, 20).unwrap();
|
||||
assert_eq!(20, bytearray.len(py));
|
||||
assert_eq!(src.len(), bytearray.len());
|
||||
assert_eq!(src, bytearray.data());
|
||||
|
||||
bytearray.resize(20).unwrap();
|
||||
assert_eq!(20, bytearray.len());
|
||||
|
||||
let none = py.None();
|
||||
if let Err(mut err) = PyByteArray::from(py, &none) {
|
||||
assert!(py.is_instance::<exc::TypeError>(&err.instance(py)).unwrap())
|
||||
assert!(py.is_instance::<exc::TypeError, _>(&err.instance(py)).unwrap())
|
||||
} else {
|
||||
panic!("error");
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
use std::{mem, collections, hash, cmp};
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use python::{Python, ToPyPointer};
|
||||
use conversion::{ToPyObject};
|
||||
use objects::{PyObject, PyList};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PyInstance, PyList};
|
||||
use err::{self, PyResult, PyErr};
|
||||
|
||||
/// Represents a Python `dict`.
|
||||
pub struct PyDict(PyPtr);
|
||||
pub struct PyDict(PyObject);
|
||||
|
||||
pyobject_convert!(PyDict);
|
||||
pyobject_nativetype!(PyDict, PyDict_Type, PyDict_Check);
|
||||
|
@ -22,103 +23,99 @@ impl PyDict {
|
|||
/// Creates a new empty dictionary.
|
||||
///
|
||||
/// May panic when running out of memory.
|
||||
pub fn new(_py: Python) -> PyDict {
|
||||
unsafe { PyDict(PyPtr::from_owned_ptr_or_panic(ffi::PyDict_New())) }
|
||||
}
|
||||
|
||||
/// Construct a new dict with the given raw pointer
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyDict {
|
||||
PyDict(PyPtr::from_borrowed_ptr(ptr))
|
||||
pub fn new<'p>(py: Python<'p>) -> &'p PyDict {
|
||||
unsafe {
|
||||
py.cast_from_ptr::<PyDict>(ffi::PyDict_New())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a new dictionary that contains the same key-value pairs as self.
|
||||
/// Corresponds to `dict(self)` in Python.
|
||||
pub fn copy(&self, py: Python) -> PyResult<PyDict> {
|
||||
pub fn copy(&self) -> PyResult<&PyDict> {
|
||||
unsafe {
|
||||
Ok(PyDict(
|
||||
PyPtr::from_owned_ptr_or_err(py, ffi::PyDict_Copy(self.0.as_ptr()))?
|
||||
))
|
||||
self.token().cast_from_ptr_or_err::<PyDict>(ffi::PyDict_Copy(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty an existing dictionary of all key-value pairs.
|
||||
#[inline]
|
||||
pub fn clear(&self, _py: Python) {
|
||||
pub fn clear(&self) {
|
||||
unsafe { ffi::PyDict_Clear(self.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Return the number of items in the dictionary.
|
||||
/// This is equivalent to len(p) on a dictionary.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::PyDict_Size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Determine if the dictionary contains the specified key.
|
||||
/// This is equivalent to the Python expression `key in self`.
|
||||
pub fn contains<K>(&self, py: Python, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
pub fn contains<K>(&self, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
match ffi::PyDict_Contains(self.as_ptr(), key) {
|
||||
1 => Ok(true),
|
||||
0 => Ok(false),
|
||||
_ => Err(PyErr::fetch(py))
|
||||
_ => Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets an item from the dictionary.
|
||||
/// Returns None if the item is not present, or if an error occurs.
|
||||
pub fn get_item<K>(&self, py: Python, key: K) -> Option<PyObject> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
PyObject::from_borrowed_ptr_or_opt(
|
||||
py, ffi::PyDict_GetItem(self.as_ptr(), key))
|
||||
pub fn get_item<K>(&self, key: K) -> Option<&PyInstance> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
self.token().cast_from_borrowed_ptr_or_opt(
|
||||
ffi::PyDict_GetItem(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets an item value.
|
||||
/// This is equivalent to the Python expression `self[key] = value`.
|
||||
pub fn set_item<K, V>(&self, py: Python, key: K, value: V)
|
||||
-> PyResult<()> where K: ToPyObject, V: ToPyObject {
|
||||
pub fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||
where K: ToPyObject, V: ToPyObject
|
||||
{
|
||||
key.with_borrowed_ptr(
|
||||
py, move |key|
|
||||
value.with_borrowed_ptr(py, |value| unsafe {
|
||||
self.token(), move |key|
|
||||
value.with_borrowed_ptr(self.token(), |value| unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PyDict_SetItem(self.as_ptr(), key, value))
|
||||
self.token(), ffi::PyDict_SetItem(self.as_ptr(), key, value))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Deletes an item.
|
||||
/// This is equivalent to the Python expression `del self[key]`.
|
||||
pub fn del_item<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
pub fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject
|
||||
{
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PyDict_DelItem(self.as_ptr(), key))
|
||||
self.token(), ffi::PyDict_DelItem(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
/// List of dict items.
|
||||
/// This is equivalent to the python expression `list(dict.items())`.
|
||||
pub fn items_list(&self, py: Python) -> PyList {
|
||||
pub fn items_list(&self) -> &PyList {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr(
|
||||
py, ffi::PyDict_Items(self.as_ptr())).unchecked_cast_into::<PyList>()
|
||||
self.token().cast_from_ptr::<PyList>(
|
||||
ffi::PyDict_Items(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of (key, value) pairs in this dictionary.
|
||||
pub fn items(&self, py: Python) -> Vec<(PyObject, PyObject)> {
|
||||
pub fn items(&self) -> Vec<(PyObject, PyObject)> {
|
||||
// Note that we don't provide an iterator because
|
||||
// PyDict_Next() is unsafe to use when the dictionary might be changed
|
||||
// by other python code.
|
||||
let mut vec = Vec::with_capacity(self.len(py));
|
||||
let mut vec = Vec::with_capacity(self.len());
|
||||
unsafe {
|
||||
let mut pos = 0;
|
||||
let mut key: *mut ffi::PyObject = mem::uninitialized();
|
||||
let mut value: *mut ffi::PyObject = mem::uninitialized();
|
||||
while ffi::PyDict_Next(self.as_ptr(), &mut pos, &mut key, &mut value) != 0 {
|
||||
vec.push((PyObject::from_borrowed_ptr(py, key),
|
||||
PyObject::from_borrowed_ptr(py, value)));
|
||||
vec.push((PyObject::from_borrowed_ptr(self.token(), key),
|
||||
PyObject::from_borrowed_ptr(self.token(), value)));
|
||||
}
|
||||
}
|
||||
vec
|
||||
|
@ -132,7 +129,7 @@ impl <K, V> ToPyObject for collections::HashMap<K, V>
|
|||
fn to_object(&self, py: Python) -> PyObject {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(py, key, value).expect("Failed to set_item on dict");
|
||||
dict.set_item(key, value).expect("Failed to set_item on dict");
|
||||
};
|
||||
dict.into()
|
||||
}
|
||||
|
@ -145,7 +142,7 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
|
|||
fn to_object(&self, py: Python) -> PyObject {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(py, key, value).expect("Failed to set_item on dict");
|
||||
dict.set_item(key, value).expect("Failed to set_item on dict");
|
||||
};
|
||||
dict.into()
|
||||
}
|
||||
|
@ -155,10 +152,32 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
|
|||
mod test {
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use python::Python;
|
||||
use instance::AsPyRef;
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PyDict, PyTuple};
|
||||
use ::PyDowncastFrom;
|
||||
use {PyDowncastFrom, ObjectProtocol};
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let dict = PyDict::new(py);
|
||||
dict.set_item(7, 32).unwrap();
|
||||
assert_eq!(32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(None, dict.get_item(8i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_copy() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let dict = PyDict::new(py);
|
||||
dict.set_item(7, 32).unwrap();
|
||||
|
||||
let ndict = dict.copy().unwrap();
|
||||
assert_eq!(32, ndict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(None, ndict.get_item(8i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
|
@ -166,12 +185,12 @@ mod test {
|
|||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert_eq!(0, dict.len(py));
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(0, dict.len());
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict2 = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert_eq!(1, dict2.len(py));
|
||||
let dict2 = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(1, dict2.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -181,9 +200,9 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert_eq!(true, dict.contains(py, 7i32).unwrap());
|
||||
assert_eq!(false, dict.contains(py, 8i32).unwrap());
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(true, dict.contains(7i32).unwrap());
|
||||
assert_eq!(false, dict.contains(8i32).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -193,9 +212,9 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert_eq!(32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(None, dict.get_item(py, 8i32));
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(None, dict.get_item(8i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -205,11 +224,11 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
|
||||
assert_eq!(42i32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(123i32, dict.get_item(py, 8i32).unwrap().extract::<i32>(py).unwrap());
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.set_item(7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(8i32, 123i32).is_ok()); // insert
|
||||
assert_eq!(42i32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(123i32, dict.get_item(8i32).unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -219,14 +238,13 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.set_item(7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(8i32, 123i32).is_ok()); // insert
|
||||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
assert_eq!(None, v.get(&8i32));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_del_item() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -234,10 +252,10 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert!(dict.del_item(py, 7i32).is_ok());
|
||||
assert_eq!(0, dict.len(py));
|
||||
assert_eq!(None, dict.get_item(py, 7i32));
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.del_item(7i32).is_ok());
|
||||
assert_eq!(0, dict.len());
|
||||
assert_eq!(None, dict.get_item(7i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -247,8 +265,8 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
assert!(dict.del_item(py, 7i32).is_ok()); // change
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.del_item(7i32).is_ok()); // change
|
||||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
}
|
||||
|
||||
|
@ -261,14 +279,14 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for el in dict.items_list(py).iter(py) {
|
||||
let tuple = el.cast_into::<PyTuple>(py).unwrap();
|
||||
key_sum += tuple.get_item(py, 0).extract::<i32>(py).unwrap();
|
||||
value_sum += tuple.get_item(py, 1).extract::<i32>(py).unwrap();
|
||||
for el in dict.items_list().iter() {
|
||||
let tuple = el.cast_as::<PyTuple>().unwrap();
|
||||
key_sum += tuple.get_item(0).extract::<i32>().unwrap();
|
||||
value_sum += tuple.get_item(1).extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(7 + 8 + 9, key_sum);
|
||||
assert_eq!(32 + 42 + 123, value_sum);
|
||||
|
@ -283,11 +301,11 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(py, &ob).unwrap();
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for (key, value) in dict.items(py) {
|
||||
for (key, value) in dict.items() {
|
||||
key_sum += key.extract::<i32>(py).unwrap();
|
||||
value_sum += value.extract::<i32>(py).unwrap();
|
||||
}
|
||||
|
@ -304,10 +322,10 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.to_object(py);
|
||||
let py_map = PyDict::downcast_from(py, &m).unwrap();
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len(py) == 1);
|
||||
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -319,9 +337,9 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.to_object(py);
|
||||
let py_map = PyDict::downcast_from(py, &m).unwrap();
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len(py) == 1);
|
||||
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@ use std::{self, mem, ops};
|
|||
use std::ffi::CStr;
|
||||
|
||||
use ffi;
|
||||
use python::{Python, IntoPyPointer};
|
||||
use pointer::PyObject;
|
||||
use python::{Python, ToPyPointer};
|
||||
use err::PyResult;
|
||||
use super::{PyObject, PyTuple, PyType};
|
||||
use super::{PyTuple, PyType};
|
||||
|
||||
macro_rules! exc_type(
|
||||
($name:ident, $exc_name:ident) => (
|
||||
|
@ -24,7 +25,7 @@ macro_rules! exc_type(
|
|||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::python::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::python::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { PyType::from_type_ptr(py, ffi::$exc_name as *mut ffi::PyTypeObject) }
|
||||
}
|
||||
}
|
||||
|
@ -126,10 +127,10 @@ impl UnicodeDecodeError {
|
|||
|
||||
impl StopIteration {
|
||||
|
||||
pub fn stop_iteration(_py: Python, args: PyTuple) {
|
||||
pub fn stop_iteration(_py: Python, args: &PyTuple) {
|
||||
unsafe {
|
||||
ffi::PyErr_SetObject(
|
||||
ffi::PyExc_StopIteration as *mut ffi::PyObject, args.into_ptr());
|
||||
ffi::PyExc_StopIteration as *mut ffi::PyObject, args.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
use std::os::raw::c_double;
|
||||
|
||||
use ffi;
|
||||
use objects::PyObject;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{ToPyPointer, Python};
|
||||
use err::PyErr;
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `float` object.
|
||||
|
@ -17,7 +17,7 @@ use conversion::{ToPyObject, IntoPyObject};
|
|||
/// by using [`ToPyObject`](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with `f32`/`f64`.
|
||||
pub struct PyFloat(PyPtr);
|
||||
pub struct PyFloat(PyObject);
|
||||
|
||||
pyobject_convert!(PyFloat);
|
||||
pyobject_nativetype!(PyFloat, PyFloat_Type, PyFloat_Check);
|
||||
|
@ -25,14 +25,14 @@ pyobject_nativetype!(PyFloat, PyFloat_Type, PyFloat_Check);
|
|||
|
||||
impl PyFloat {
|
||||
/// Creates a new Python `float` object.
|
||||
pub fn new(_py: Python, val: c_double) -> PyFloat {
|
||||
pub fn new(_py: Python, val: c_double) -> Py<PyFloat> {
|
||||
unsafe {
|
||||
PyFloat(PyPtr::from_owned_ptr_or_panic(ffi::PyFloat_FromDouble(val)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyFloat_FromDouble(val))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the value of this float.
|
||||
pub fn value(&self, _py: Python) -> c_double {
|
||||
pub fn value(&self) -> c_double {
|
||||
unsafe { ffi::PyFloat_AsDouble(self.0.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ impl IntoPyObject for f64 {
|
|||
|
||||
pyobject_extract!(py, obj to f64 => {
|
||||
let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) };
|
||||
if v == -1.0 && PyErr::occurred(py) {
|
||||
Err(PyErr::fetch(py))
|
||||
if v == -1.0 && PyErr::occurred(obj.token()) {
|
||||
Err(PyErr::fetch(obj.token()))
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl IntoPyObject for f32 {
|
|||
}
|
||||
|
||||
pyobject_extract!(py, obj to f32 => {
|
||||
Ok(try!(obj.extract::<f64>(py)) as f32)
|
||||
Ok(try!(obj.extract::<f64>()) as f32)
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use objects::PyInstance;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use objects::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
|
||||
/// A python iterator object.
|
||||
///
|
||||
/// Unlike other python objects, this class includes a `Python<'p>` token
|
||||
/// so that `PyIterator` can implement the rust `Iterator` trait.
|
||||
pub struct PyIterator<'p>(PyPtr, Python<'p>);
|
||||
pub struct PyIterator<'p>(&'p PyInstance);
|
||||
|
||||
|
||||
impl <'p> PyIterator<'p> {
|
||||
|
@ -24,7 +24,7 @@ impl <'p> PyIterator<'p> {
|
|||
unsafe {
|
||||
let ptr = obj.into_ptr();
|
||||
if ffi::PyIter_Check(ptr) != 0 {
|
||||
Ok(PyIterator(PyPtr::from_borrowed_ptr(ptr), py))
|
||||
Ok(PyIterator(py.cast_from_ptr(ptr)))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError(py, None))
|
||||
|
@ -34,20 +34,23 @@ impl <'p> PyIterator<'p> {
|
|||
}
|
||||
|
||||
impl <'p> Iterator for PyIterator<'p> {
|
||||
type Item = PyResult<PyObject>;
|
||||
type Item = PyResult<&'p PyInstance>;
|
||||
|
||||
/// Retrieves the next item from an iterator.
|
||||
/// Returns `None` when the iterator is exhausted.
|
||||
/// If an exception occurs, returns `Some(Err(..))`.
|
||||
/// Further `next()` calls after an exception occurs are likely
|
||||
/// to repeatedly result in the same exception.
|
||||
fn next(&mut self) -> Option<PyResult<PyObject>> {
|
||||
match unsafe { PyObject::from_owned_ptr_or_opt(
|
||||
self.1, ffi::PyIter_Next(self.0.as_ptr())) } {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let py = self.0.token();
|
||||
|
||||
match unsafe {
|
||||
py.cast_from_ptr_or_opt(ffi::PyIter_Next(self.0.as_ptr())) }
|
||||
{
|
||||
Some(obj) => Some(Ok(obj)),
|
||||
None => {
|
||||
if PyErr::occurred(self.1) {
|
||||
Some(Err(PyErr::fetch(self.1)))
|
||||
if PyErr::occurred(py) {
|
||||
Some(Err(PyErr::fetch(py)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -58,8 +61,10 @@ impl <'p> Iterator for PyIterator<'p> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use python::{Python};
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyInstance;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
|
@ -67,9 +72,10 @@ mod tests {
|
|||
let gil_guard = Python::acquire_gil();
|
||||
let py = gil_guard.python();
|
||||
let obj = vec![10, 20].to_object(py);
|
||||
let mut it = obj.iter(py).unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract(py).unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract(py).unwrap());
|
||||
let inst = PyInstance::downcast_from(obj.as_ref(py)).unwrap();
|
||||
let mut it = inst.iter().unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert!(it.next().is_none());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,39 +4,41 @@
|
|||
|
||||
use err::{self, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use pointers::PyPtr;
|
||||
use instance::PyObjectWithToken;
|
||||
use pointer::PyObject;
|
||||
use objects::PyInstance;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use objects::PyObject;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `list`.
|
||||
pub struct PyList(PyPtr);
|
||||
pub struct PyList(PyObject);
|
||||
|
||||
pyobject_convert!(PyList);
|
||||
pyobject_nativetype!(PyList, PyList_Type, PyList_Check);
|
||||
|
||||
impl PyList {
|
||||
/// Construct a new list with the given elements.
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> PyList {
|
||||
pub fn new<'p, T: ToPyObject>(py: Python<'p>, elements: &[T]) -> &'p PyList {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
|
||||
for (i, e) in elements.iter().enumerate() {
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
|
||||
let obj = e.to_object(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
PyList(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
py.cast_from_ptr::<PyList>(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new empty list.
|
||||
pub fn empty(_py: Python) -> PyList {
|
||||
pub fn empty<'p>(py: Python<'p>) -> &'p PyList {
|
||||
unsafe {
|
||||
PyList(PyPtr::from_owned_ptr_or_panic(ffi::PyList_New(0)))
|
||||
py.cast_from_ptr::<PyList>(ffi::PyList_New(0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the length of the list.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
// non-negative Py_ssize_t should always fit into Rust usize
|
||||
unsafe {
|
||||
ffi::PyList_Size(self.as_ptr()) as usize
|
||||
|
@ -46,57 +48,67 @@ impl PyList {
|
|||
/// Gets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_item(&self, py: Python, index: isize) -> PyObject {
|
||||
pub fn get_item(&self, index: isize) -> &PyInstance {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
let ptr = ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t);
|
||||
let ob = PyObject::from_borrowed_ptr(self.token(), ptr);
|
||||
self.token().track_object(ob)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_parked_item(&self, index: isize) -> PyObject {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t);
|
||||
PyObject::from_borrowed_ptr(self.token(), ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn set_item<I>(&self, py: Python, index: isize, item: I) -> PyResult<()>
|
||||
pub fn set_item<I>(&self, index: isize, item: I) -> PyResult<()>
|
||||
where I: ToPyObject
|
||||
{
|
||||
item.with_borrowed_ptr(py, |item| unsafe {
|
||||
item.with_borrowed_ptr(self.token(), |item| unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PyList_SetItem(self.as_ptr(), index, item))
|
||||
self.token(), ffi::PyList_SetItem(self.as_ptr(), index, item))
|
||||
})
|
||||
}
|
||||
|
||||
/// Inserts an item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn insert_item<I>(&self, py: Python, index: isize, item: I) -> PyResult<()>
|
||||
pub fn insert_item<I>(&self, index: isize, item: I) -> PyResult<()>
|
||||
where I: ToPyObject
|
||||
{
|
||||
item.with_borrowed_ptr(py, |item| unsafe {
|
||||
item.with_borrowed_ptr(self.token(), |item| unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PyList_Insert(self.as_ptr(), index, item))
|
||||
self.token(), ffi::PyList_Insert(self.as_ptr(), index, item))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter<'a, 'p>(&'a self, py: Python<'p>) -> PyListIterator<'a, 'p> {
|
||||
PyListIterator { py: py, list: self, index: 0 }
|
||||
pub fn iter(&self) -> PyListIterator {
|
||||
PyListIterator { list: self, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by `PyList::iter()`.
|
||||
pub struct PyListIterator<'a, 'p> {
|
||||
py: Python<'p>,
|
||||
pub struct PyListIterator<'a> {
|
||||
list: &'a PyList,
|
||||
index: isize,
|
||||
}
|
||||
|
||||
impl<'a, 'p> Iterator for PyListIterator<'a, 'p> {
|
||||
type Item = PyObject;
|
||||
impl<'a> Iterator for PyListIterator<'a> {
|
||||
type Item = &'a PyInstance;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<PyObject> {
|
||||
if self.index < self.list.len(self.py) as isize {
|
||||
let item = self.list.get_item(self.py, self.index);
|
||||
fn next(&mut self) -> Option<&'a PyInstance> {
|
||||
if self.index < self.list.len() as isize {
|
||||
let item = self.list.get_item(self.index);
|
||||
self.index += 1;
|
||||
Some(item)
|
||||
} else {
|
||||
|
@ -139,24 +151,39 @@ impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
|||
let obj = e.into_object(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
::PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python, PyDowncastInto};
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyList;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::new(py, &v);
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
|
||||
assert_eq!(5, list.get_item(2).extract::<i32>().unwrap());
|
||||
assert_eq!(7, list.get_item(3).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![1,2,3,4];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
assert_eq!(4, list.len(py));
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(4, list.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -164,11 +191,25 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, list.get_item(py, 1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, list.get_item(py, 2).extract::<i32>(py).unwrap());
|
||||
assert_eq!(7, list.get_item(py, 3).extract::<i32>(py).unwrap());
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
|
||||
assert_eq!(5, list.get_item(2).extract::<i32>().unwrap());
|
||||
assert_eq!(7, list.get_item(3).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_parked_item() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(2, list.get_parked_item(0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, list.get_parked_item(1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, list.get_parked_item(2).extract::<i32>(py).unwrap());
|
||||
assert_eq!(7, list.get_parked_item(3).extract::<i32>(py).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -176,11 +217,12 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let val = 42i32.to_object(py);
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
list.set_item(py, 0, val).unwrap();
|
||||
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
list.set_item(0, val).unwrap();
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -188,14 +230,15 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let val = 42i32.to_object(py);
|
||||
assert_eq!(4, list.len(py));
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
list.insert_item(py, 0, val).unwrap();
|
||||
assert_eq!(5, list.len(py));
|
||||
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, list.get_item(py, 1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(4, list.len());
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
list.insert_item(0, val).unwrap();
|
||||
assert_eq!(5, list.len());
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(2, list.get_item(1).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -203,10 +246,11 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in list.iter(py) {
|
||||
assert_eq!(v[idx], el.extract::<i32>(py).unwrap());
|
||||
for el in list.iter() {
|
||||
assert_eq!(v[idx], el.extract::<i32>().unwrap());
|
||||
idx += 1;
|
||||
}
|
||||
assert_eq!(idx, v.len());
|
||||
|
@ -217,8 +261,9 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let v2 = list.as_ref().extract::<Vec<i32>>(py).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let v2 = list.as_ref().extract::<Vec<i32>>().unwrap();
|
||||
assert_eq!(v, v2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
pub use self::object::PyObject;
|
||||
pub use self::typeobject::PyType;
|
||||
pub use self::module::PyModule;
|
||||
pub use self::iterator::PyIterator;
|
||||
|
@ -29,17 +28,77 @@ pub use self::num3::PyLong as PyInt;
|
|||
#[cfg(not(Py_3))]
|
||||
pub use self::num2::{PyInt, PyLong};
|
||||
|
||||
//#[macro_export]
|
||||
macro_rules! pyobject_nativetype(
|
||||
|
||||
macro_rules! pyobject_downcast(
|
||||
($name: ident, $checkfunction: ident) => (
|
||||
impl $crate::python::PyDowncastFrom for $name
|
||||
{
|
||||
fn downcast_from(ob: &$crate::PyInstance)
|
||||
-> Result<&$name, $crate::PyDowncastError>
|
||||
{
|
||||
use $crate::{ToPyPointer, PyObjectWithToken};
|
||||
|
||||
unsafe {
|
||||
if $crate::ffi::$checkfunction(ob.as_ptr()) > 0 {
|
||||
Ok($crate::std::mem::transmute(ob))
|
||||
} else {
|
||||
Err($crate::PyDowncastError(ob.token(), None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unchecked_downcast_from(ob: &$crate::PyInstance) -> &Self
|
||||
{
|
||||
$crate::std::mem::transmute(ob)
|
||||
}
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &$crate::PyInstance) -> &mut Self
|
||||
{
|
||||
#[allow(mutable_transmutes)]
|
||||
$crate::std::mem::transmute(ob)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for &'a $name
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(ob: &'a $crate::PyInstance) -> $crate::PyResult<Self>
|
||||
{
|
||||
use instance::PyObjectWithToken;
|
||||
unsafe {
|
||||
if $crate::ffi::$checkfunction(ob.as_ptr()) != 0 {
|
||||
Ok($crate::std::mem::transmute(ob))
|
||||
} else {
|
||||
Err($crate::PyDowncastError(ob.token(), None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! pyobject_convert(
|
||||
($name: ident) => (
|
||||
impl $crate::std::convert::AsRef<PyObject> for $name {
|
||||
fn as_ref(&self) -> &$crate::PyObject {
|
||||
impl<'a> $crate::std::convert::From<&'a $name> for &'a $crate::PyInstance {
|
||||
fn from(ob: &'a $name) -> Self {
|
||||
unsafe{$crate::std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pyobject_nativetype(
|
||||
($name: ident) => {
|
||||
impl $crate::PyNativeType for $name {}
|
||||
|
||||
impl $crate::std::convert::AsRef<$crate::PyInstance> for $name {
|
||||
fn as_ref(&self) -> &$crate::PyInstance {
|
||||
unsafe{$crate::std::mem::transmute(self)}
|
||||
}
|
||||
}
|
||||
impl $crate::PyClone for $name {
|
||||
fn clone_ref(&self, _py: $crate::Python) -> Self {
|
||||
$name(unsafe{$crate::PyPtr::from_borrowed_ptr(self.as_ptr())})
|
||||
impl $crate::PyObjectWithToken for $name {
|
||||
#[inline]
|
||||
fn token<'p>(&'p self) -> $crate::Python<'p> {
|
||||
unsafe { $crate::Python::assume_gil_acquired() }
|
||||
}
|
||||
}
|
||||
impl $crate::python::ToPyPointer for $name {
|
||||
|
@ -49,32 +108,33 @@ macro_rules! pyobject_nativetype(
|
|||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
impl<'a> $crate::python::ToPyPointer for &'a $name {
|
||||
impl $crate::python::IntoPyPointer for $name {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::python::IntoPyPointer for $name {
|
||||
/// Gets the underlying FFI pointer, returns a owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut $crate::ffi::PyObject {
|
||||
let ptr = self.0.as_ptr();
|
||||
$crate::std::mem::forget(self);
|
||||
unsafe { $crate::ffi::Py_INCREF(ptr); }
|
||||
ptr
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
($name: ident, $typeobject: ident, $checkfunction: ident) => {
|
||||
pyobject_downcast!($name, $checkfunction);
|
||||
pyobject_nativetype!($name, $typeobject);
|
||||
impl<'a> $crate::python::IntoPyPointer for &'a $name {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn into_ptr(self) -> *mut $crate::ffi::PyObject {
|
||||
let ptr = self.0.as_ptr();
|
||||
unsafe { $crate::ffi::Py_INCREF(ptr); }
|
||||
ptr
|
||||
}
|
||||
}
|
||||
impl PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, o: &$name) -> bool {
|
||||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($name: ident, $typeobject: ident) => (
|
||||
($name: ident, $typeobject: ident, $checkfunction: ident) => {
|
||||
pyobject_nativetype!($name);
|
||||
|
||||
impl $crate::typeob::PyTypeInfo for $name {
|
||||
|
@ -82,7 +142,7 @@ macro_rules! pyobject_nativetype(
|
|||
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
$crate::std::mem::size_of::<ffi::PyObject>()
|
||||
$crate::std::mem::size_of::<$crate::ffi::PyObject>()
|
||||
}
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
|
@ -96,14 +156,19 @@ macro_rules! pyobject_nativetype(
|
|||
fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||
unsafe { &mut $crate::ffi::$typeobject }
|
||||
}
|
||||
#[inline]
|
||||
fn is_instance(ptr: *mut $crate::ffi::PyObject) -> bool {
|
||||
#[allow(unused_unsafe)]
|
||||
unsafe { $crate::ffi::$checkfunction(ptr) > 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::typeob::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
fn init_type(_py: Python) {}
|
||||
fn init_type(_py: $crate::Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, &mut $crate::ffi::$typeobject) }
|
||||
}
|
||||
}
|
||||
|
@ -112,23 +177,22 @@ macro_rules! pyobject_nativetype(
|
|||
{
|
||||
#[inline]
|
||||
fn to_object<'p>(&self, py: $crate::Python<'p>) -> $crate::PyObject {
|
||||
$crate::PyObject::from_borrowed_ptr(py, self.0.as_ptr())
|
||||
unsafe {$crate::PyObject::from_borrowed_ptr(py, self.0.as_ptr())}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_borrowed_ptr<F, R>(&self, _py: $crate::Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
where F: FnOnce(*mut $crate::ffi::PyObject) -> R
|
||||
{
|
||||
f(self.0.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::IntoPyObject for $name
|
||||
impl<'a> $crate::IntoPyObject for &'a $name
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, _py: $crate::Python) -> $crate::PyObject
|
||||
{
|
||||
unsafe { $crate::std::mem::transmute(self) }
|
||||
fn into_object<'p>(self, py: $crate::Python) -> $crate::PyObject {
|
||||
unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,18 +200,9 @@ macro_rules! pyobject_nativetype(
|
|||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
use $crate::python::PyDowncastInto;
|
||||
|
||||
let gil = $crate::Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let s = unsafe { $crate::PyString::downcast_from_ptr(
|
||||
py, $crate::ffi::PyObject_Repr(
|
||||
$crate::python::ToPyPointer::as_ptr(self))) };
|
||||
let repr_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
let result = f.write_str(&repr_obj.to_string_lossy(py));
|
||||
py.release(repr_obj);
|
||||
result
|
||||
use $crate::ObjectProtocol;
|
||||
let s = try!(self.repr().map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,129 +210,25 @@ macro_rules! pyobject_nativetype(
|
|||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let gil = $crate::Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
use $crate::python::PyDowncastInto;
|
||||
|
||||
let s = unsafe { $crate::PyString::downcast_from_ptr(
|
||||
py, $crate::ffi::PyObject_Str(
|
||||
$crate::python::ToPyPointer::as_ptr(self))) };
|
||||
let str_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
let result = f.write_str(&str_obj.to_string_lossy(py));
|
||||
py.release(str_obj);
|
||||
result
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! pyobject_downcast(
|
||||
($name: ident, $checkfunction: ident) => (
|
||||
impl $crate::python::PyDowncastFrom for $name
|
||||
{
|
||||
fn downcast_from<'a, 'p>(py: $crate::Python<'p>, ob: &'a $crate::PyObject)
|
||||
-> Result<&'a $name, $crate::PyDowncastError<'p>>
|
||||
{
|
||||
use $crate::ToPyPointer;
|
||||
|
||||
unsafe {
|
||||
if $crate::ffi::$checkfunction(ob.as_ptr()) > 0 {
|
||||
let ptr = ob as *const _ as *mut u8 as *mut $name;
|
||||
Ok(ptr.as_ref().expect("Failed to call as_ref"))
|
||||
} else {
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl $crate::python::PyDowncastInto for $name
|
||||
{
|
||||
fn downcast_into<'p, I>(py: $crate::Python<'p>, ob: I)
|
||||
-> Result<Self, $crate::PyDowncastError<'p>>
|
||||
where I: $crate::IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($name(PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn downcast_from_ptr<'p>(py: $crate::Python<'p>, ptr: *mut $crate::ffi::PyObject)
|
||||
-> Result<$name, $crate::PyDowncastError<'p>>
|
||||
{
|
||||
unsafe{
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($name(PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unchecked_downcast_into<'p, I>(ob: I) -> Self
|
||||
where I: $crate::IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
$name(PyPtr::from_owned_ptr(ob.into_ptr()))
|
||||
}
|
||||
use $crate::ObjectProtocol;
|
||||
let s = try!(self.str().map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for $name
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'a $crate::PyObject) -> $crate::PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
if ffi::$checkfunction(ob.as_ptr()) != 0 {
|
||||
Ok( $name($crate::pointers::PyPtr::from_borrowed_ptr(ob.as_ptr())) )
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for &'a $name
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'a $crate::PyObject) -> $crate::PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
if ffi::$checkfunction(ob.as_ptr()) != 0 {
|
||||
Ok($crate::std::mem::transmute(ob))
|
||||
} else {
|
||||
Err($crate::PyDowncastError(py, None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! pyobject_convert(
|
||||
($name: ident) => (
|
||||
impl $crate::std::convert::From<$name> for $crate::PyObject {
|
||||
fn from(ob: $name) -> Self {
|
||||
unsafe{$crate::std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
)
|
||||
pyobject_downcast!($name, $checkfunction);
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! pyobject_extract(
|
||||
($py:ident, $obj:ident to $t:ty => $body: block) => {
|
||||
impl<'source> ::conversion::FromPyObject<'source>
|
||||
for $t
|
||||
impl<'source> $crate::FromPyObject<'source> for $t
|
||||
{
|
||||
fn extract($py: Python, $obj: &'source ::PyObject) -> $crate::PyResult<Self>
|
||||
fn extract($obj: &'source $crate::PyInstance) -> $crate::PyResult<Self>
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
@ -285,6 +236,12 @@ macro_rules! pyobject_extract(
|
|||
);
|
||||
|
||||
|
||||
use python::ToPyPointer;
|
||||
|
||||
/// Represents general python instance.
|
||||
pub struct PyInstance(::PyObject);
|
||||
pyobject_nativetype!(PyInstance, PyBaseObject_Type, PyObject_Check);
|
||||
|
||||
mod typeobject;
|
||||
mod module;
|
||||
mod dict;
|
||||
|
@ -299,7 +256,6 @@ mod slice;
|
|||
mod stringdata;
|
||||
mod stringutils;
|
||||
mod set;
|
||||
mod object;
|
||||
pub mod exc;
|
||||
|
||||
#[cfg(Py_3)]
|
||||
|
|
|
@ -8,53 +8,59 @@ use std::os::raw::c_char;
|
|||
use std::ffi::{CStr, CString};
|
||||
|
||||
use conversion::{ToPyObject, IntoPyTuple};
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::{PyObject, PyDict, PyType, exc};
|
||||
use objects::{PyInstance, PyDict, PyType, exc};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use instance::PyObjectWithToken;
|
||||
use err::{PyResult, PyErr, ToPyErr};
|
||||
|
||||
|
||||
/// Represents a Python module object.
|
||||
pub struct PyModule(PyPtr);
|
||||
pub struct PyModule(PyObject);
|
||||
|
||||
pyobject_convert!(PyModule);
|
||||
pyobject_nativetype!(PyModule, PyModule_Type, PyModule_Check);
|
||||
|
||||
|
||||
impl<'p> PyModule {
|
||||
impl PyModule {
|
||||
/// Create a new module object with the `__name__` attribute set to name.
|
||||
pub fn new(py: Python, name: &str) -> PyResult<PyModule> {
|
||||
pub fn new<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
|
||||
let name = CString::new(name).map_err(|e| e.to_pyerr(py))?;
|
||||
Ok(PyModule(PyPtr::from_owned_ptr_or_err(
|
||||
py, unsafe{ffi::PyModule_New(name.as_ptr())} )?))
|
||||
unsafe {
|
||||
py.cast_from_ptr_or_err(
|
||||
ffi::PyModule_New(name.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
pub fn import(py: Python, name: &str) -> PyResult<PyModule> {
|
||||
pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
|
||||
let name = CString::new(name).map_err(|e| e.to_pyerr(py))?;
|
||||
Ok(PyModule(PyPtr::from_owned_ptr_or_err(
|
||||
py, unsafe{ffi::PyImport_ImportModule(name.as_ptr())} )?))
|
||||
unsafe {
|
||||
py.cast_from_ptr_or_err(
|
||||
ffi::PyImport_ImportModule(name.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the dictionary object that implements module's namespace;
|
||||
/// this object is the same as the `__dict__` attribute of the module object.
|
||||
pub fn dict(&self, py: Python) -> PyDict {
|
||||
pub fn dict(&self) -> &PyDict {
|
||||
unsafe {
|
||||
PyDict::from_borrowed_ptr(py, ffi::PyModule_GetDict(self.as_ptr()))
|
||||
self.token().cast_from_ptr::<PyDict>(
|
||||
ffi::PyModule_GetDict(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn str_from_ptr<'a>(&'a self, py: Python, ptr: *const c_char) -> PyResult<&'a str> {
|
||||
unsafe fn str_from_ptr<'a>(&'a self, ptr: *const c_char) -> PyResult<&'a str> {
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
let slice = CStr::from_ptr(ptr).to_bytes();
|
||||
match std::str::from_utf8(slice) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => Err(PyErr::from_instance(
|
||||
py,
|
||||
try!(exc::UnicodeDecodeError::new_utf8(py, slice, e))))
|
||||
self.token(),
|
||||
try!(exc::UnicodeDecodeError::new_utf8(self.token(), slice, e))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,38 +68,37 @@ impl<'p> PyModule {
|
|||
/// Gets the module name.
|
||||
///
|
||||
/// May fail if the module does not have a `__name__` attribute.
|
||||
pub fn name<'a>(&'a self, py: Python) -> PyResult<&'a str> {
|
||||
unsafe { self.str_from_ptr(py, ffi::PyModule_GetName(self.as_ptr())) }
|
||||
pub fn name<'a>(&'a self) -> PyResult<&'a str> {
|
||||
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Gets the module filename.
|
||||
///
|
||||
/// May fail if the module does not have a `__file__` attribute.
|
||||
pub fn filename<'a>(&'a self, py: Python) -> PyResult<&'a str> {
|
||||
unsafe { self.str_from_ptr(py, ffi::PyModule_GetFilename(self.as_ptr())) }
|
||||
pub fn filename<'a>(&'a self) -> PyResult<&'a str> {
|
||||
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Calls a function in the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
|
||||
pub fn call<A>(&self, py: Python, name: &str,
|
||||
args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
pub fn call<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyInstance>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
self.getattr(py, name)?.call(py, args, kwargs)
|
||||
self.getattr(name)?.call(args, kwargs)
|
||||
}
|
||||
|
||||
/// Gets a member from the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)`
|
||||
pub fn get(&self, py: Python, name: &str) -> PyResult<PyObject>
|
||||
pub fn get(&self, name: &str) -> PyResult<&PyInstance>
|
||||
{
|
||||
self.getattr(py, name)
|
||||
self.getattr(name)
|
||||
}
|
||||
|
||||
/// Adds a member to the module.
|
||||
///
|
||||
/// This is a convenience function which can be used from the module's initialization function.
|
||||
pub fn add<V>(&self, py: Python, name: &str, value: V) -> PyResult<()> where V: ToPyObject {
|
||||
self.setattr(py, name, value)
|
||||
pub fn add<V>(&self, name: &str, value: V) -> PyResult<()> where V: ToPyObject {
|
||||
self.setattr(name, value)
|
||||
}
|
||||
|
||||
/// Adds a new extension type to the module.
|
||||
|
@ -101,30 +106,26 @@ impl<'p> PyModule {
|
|||
/// This is a convenience function that initializes the `class`,
|
||||
/// sets `new_type.__module__` to this module's name,
|
||||
/// and adds the type to this module.
|
||||
pub fn add_class<T>(&self, py: Python) -> PyResult<()>
|
||||
pub fn add_class<T>(&self) -> PyResult<()>
|
||||
where T: ::typeob::PyTypeInfo
|
||||
{
|
||||
let mut ty = <T as ::typeob::PyTypeInfo>::type_object();
|
||||
let type_name = <T as ::typeob::PyTypeInfo>::type_name();
|
||||
|
||||
let ty = if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
|
||||
unsafe { PyType::from_type_ptr(py, ty) }
|
||||
unsafe { PyType::from_type_ptr(self.token(), ty) }
|
||||
} else {
|
||||
// automatically initialize the class
|
||||
let name = self.name(py)?;
|
||||
let name = self.name()?;
|
||||
let type_description = <T as ::typeob::PyTypeInfo>::type_description();
|
||||
|
||||
let to = ::typeob::initialize_type::<T>(
|
||||
py, Some(name), type_name, type_description, ty)
|
||||
::typeob::initialize_type::<T>(
|
||||
self.token(), Some(name), type_name, type_description, ty)
|
||||
.expect(format!("An error occurred while initializing class {}",
|
||||
<T as ::typeob::PyTypeInfo>::type_name()).as_ref());
|
||||
py.release(to);
|
||||
unsafe { PyType::from_type_ptr(py, ty) }
|
||||
unsafe { PyType::from_type_ptr(self.token(), ty) }
|
||||
};
|
||||
|
||||
self.setattr(py, type_name, &ty)?;
|
||||
|
||||
py.release(ty);
|
||||
Ok(())
|
||||
self.setattr(type_name, ty)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ extern crate num_traits;
|
|||
use self::num_traits::cast::cast;
|
||||
|
||||
use ffi;
|
||||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{ToPyPointer, IntoPyPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use objects::{exc, PyInstance};
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
|
||||
/// Represents a Python `int` object.
|
||||
|
@ -23,7 +23,7 @@ use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
|||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
pub struct PyInt(PyPtr);
|
||||
pub struct PyInt(PyObject);
|
||||
|
||||
pyobject_convert!(PyInt);
|
||||
pyobject_nativetype!(PyInt, PyInt_Type, PyInt_Check);
|
||||
|
@ -35,7 +35,7 @@ pyobject_nativetype!(PyInt, PyInt_Type, PyInt_Check);
|
|||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong(PyPtr);
|
||||
pub struct PyLong(PyObject);
|
||||
|
||||
pyobject_convert!(PyLong);
|
||||
pyobject_nativetype!(PyLong, PyLong_Type, PyLong_Check);
|
||||
|
@ -46,9 +46,9 @@ impl PyInt {
|
|||
/// Note: you might want to call `val.to_py_object(py)` instead
|
||||
/// to avoid truncation if the value does not fit into a `c_long`,
|
||||
/// and to make your code compatible with Python 3.x.
|
||||
pub fn new(_py: Python, val: c_long) -> PyInt {
|
||||
pub fn new(_py: Python, val: c_long) -> Py<PyInt> {
|
||||
unsafe {
|
||||
PyInt(PyPtr::from_owned_ptr_or_panic(ffi::PyLong_FromLong(val)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyLong_FromLong(val))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl PyInt {
|
|||
/// but not for `long` objects.
|
||||
/// In almost all cases, you can avoid the distinction between these types
|
||||
/// by simply calling `obj.extract::<i32>(py)`.
|
||||
pub fn value(&self, _py: Python) -> c_long {
|
||||
pub fn value(&self) -> c_long {
|
||||
unsafe { ffi::PyInt_AS_LONG(self.0.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
@ -81,12 +81,12 @@ macro_rules! int_fits_c_long(
|
|||
}
|
||||
pyobject_extract!(py, obj to $rust_type => {
|
||||
let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) };
|
||||
if val == -1 && PyErr::occurred(py) {
|
||||
return Err(PyErr::fetch(py));
|
||||
if val == -1 && PyErr::occurred(obj.token()) {
|
||||
return Err(PyErr::fetch(obj.token()));
|
||||
}
|
||||
match cast::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
None => Err(overflow_error(obj.token()))
|
||||
}
|
||||
});
|
||||
)
|
||||
|
@ -107,10 +107,10 @@ macro_rules! int_fits_larger_int(
|
|||
}
|
||||
}
|
||||
pyobject_extract!(py, obj to $rust_type => {
|
||||
let val = try!(obj.extract::<$larger_type>(py));
|
||||
let val = try!(obj.extract::<$larger_type>());
|
||||
match cast::<$larger_type, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
None => Err(overflow_error(obj.token()))
|
||||
}
|
||||
});
|
||||
)
|
||||
|
@ -153,20 +153,22 @@ macro_rules! int_convert_u64_or_i64 (
|
|||
}
|
||||
|
||||
impl <'source> FromPyObject<'source> for $rust_type {
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<$rust_type>
|
||||
fn extract(obj: &'source PyInstance) -> PyResult<$rust_type>
|
||||
{
|
||||
let ptr = obj.as_ptr();
|
||||
unsafe {
|
||||
if ffi::PyLong_Check(ptr) != 0 {
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(ptr))
|
||||
err_if_invalid_value(obj.token(), !0, $pylong_as_ull_or_ull(ptr))
|
||||
} else if ffi::PyInt_Check(ptr) != 0 {
|
||||
match cast::<c_long, $rust_type>(ffi::PyInt_AS_LONG(ptr)) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
None => Err(overflow_error(obj.token()))
|
||||
}
|
||||
} else {
|
||||
let num = PyPtr::from_owned_ptr_or_err(py, ffi::PyNumber_Long(ptr))?;
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(num.into_ptr()))
|
||||
let num = PyObject::from_owned_ptr_or_err(
|
||||
obj.token(), ffi::PyNumber_Long(ptr))?;
|
||||
err_if_invalid_value(
|
||||
obj.token(), !0, $pylong_as_ull_or_ull(num.into_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ extern crate num_traits;
|
|||
use self::num_traits::cast::cast;
|
||||
|
||||
use ffi;
|
||||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{ToPyPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use objects::{exc, PyInstance};
|
||||
use instance::PyObjectWithToken;
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
|
||||
/// Represents a Python `int` object.
|
||||
|
@ -21,11 +21,12 @@ use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
|||
/// by using [`ToPyObject`](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong(PyPtr);
|
||||
pub struct PyLong(PyObject);
|
||||
|
||||
pyobject_convert!(PyLong);
|
||||
pyobject_nativetype!(PyLong, PyLong_Type, PyLong_Check);
|
||||
|
||||
|
||||
macro_rules! int_fits_c_long(
|
||||
($rust_type:ty) => (
|
||||
impl ToPyObject for $rust_type {
|
||||
|
@ -44,12 +45,12 @@ macro_rules! int_fits_c_long(
|
|||
}
|
||||
pyobject_extract!(py, obj to $rust_type => {
|
||||
let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) };
|
||||
if val == -1 && PyErr::occurred(py) {
|
||||
return Err(PyErr::fetch(py));
|
||||
if val == -1 && PyErr::occurred(obj.token()) {
|
||||
return Err(PyErr::fetch(obj.token()));
|
||||
}
|
||||
match cast::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
None => Err(overflow_error(obj.token()))
|
||||
}
|
||||
});
|
||||
)
|
||||
|
@ -70,10 +71,10 @@ macro_rules! int_fits_larger_int(
|
|||
}
|
||||
}
|
||||
pyobject_extract!(py, obj to $rust_type => {
|
||||
let val = try!(obj.extract::<$larger_type>(py));
|
||||
let val = try!(obj.extract::<$larger_type>());
|
||||
match cast::<$larger_type, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
None => Err(overflow_error(obj.token()))
|
||||
}
|
||||
});
|
||||
)
|
||||
|
@ -109,18 +110,18 @@ macro_rules! int_convert_u64_or_i64 (
|
|||
}
|
||||
}
|
||||
impl<'source> FromPyObject<'source> for $rust_type {
|
||||
fn extract(py: Python, ob: &'source PyObject) -> PyResult<$rust_type>
|
||||
fn extract(ob: &'source PyInstance) -> PyResult<$rust_type>
|
||||
{
|
||||
let ptr = ob.as_ptr();
|
||||
unsafe {
|
||||
if ffi::PyLong_Check(ptr) != 0 {
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(ptr))
|
||||
err_if_invalid_value(ob.token(), !0, $pylong_as_ull_or_ull(ptr))
|
||||
} else {
|
||||
let num = ffi::PyNumber_Long(ptr);
|
||||
if num.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(ob.token()))
|
||||
} else {
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(num))
|
||||
err_if_invalid_value(ob.token(), !0, $pylong_as_ull_or_ull(num))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use python::{Python, ToPyPointer};
|
||||
use conversion::FromPyObject;
|
||||
|
||||
pub struct PyObject(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyObject, PyBaseObject_Type, PyObject_Check);
|
||||
|
||||
|
||||
impl PyObject {
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
unsafe { PyObject(PyPtr::from_owned_ptr(ptr)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<PyObject> {
|
||||
Ok(PyObject(PyPtr::from_owned_ptr_or_err(py, ptr)?))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject)
|
||||
-> PyObject {
|
||||
PyObject(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject(unsafe{PyPtr::from_owned_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
unsafe { PyObject(PyPtr::from_borrowed_ptr(ptr)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject(unsafe{PyPtr::from_borrowed_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(PyObject(unsafe{PyPtr::from_borrowed_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Transmutes a slice of owned FFI pointers to `&[Py<'p, PyObject>]`.
|
||||
/// Undefined behavior if any pointer in the slice is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn borrow_from_owned_ptr_slice<'a>(ptr: &'a [*mut ffi::PyObject])
|
||||
-> &'a [PyObject] {
|
||||
std::mem::transmute(ptr)
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_as<'a, 'p, D>(&'a self, py: Python<'p>) -> Result<&'a D, PyDowncastError<'p>>
|
||||
where D: ::PyDowncastFrom
|
||||
{
|
||||
<D as ::PyDowncastFrom>::downcast_from(py, &self)
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_into<'p, D>(self, py: Python<'p>) -> Result<D, PyDowncastError<'p>>
|
||||
where D: ::PyDowncastInto
|
||||
{
|
||||
<D as ::PyDowncastInto>::downcast_into(py, self)
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn unchecked_cast_into<'p, D>(self) -> D where D: ::PyDowncastInto
|
||||
{
|
||||
<D as ::PyDowncastInto>::unchecked_downcast_into(self)
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
pub fn extract<'a, D>(&'a self, py: Python) -> PyResult<D> where D: FromPyObject<'a>
|
||||
{
|
||||
FromPyObject::extract(py, &self)
|
||||
}
|
||||
|
||||
pub fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn drop_ref(&mut self) {
|
||||
self.0.drop_ref();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> PartialEq for PyObject {
|
||||
#[inline]
|
||||
fn eq(&self, other: &PyObject) -> bool {
|
||||
self.as_ptr() == other.as_ptr()
|
||||
}
|
||||
}
|
|
@ -3,10 +3,11 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom, PyDowncastInto};
|
||||
use pointer::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use conversion::{FromPyObject, ToPyObject};
|
||||
use objects::{PyObject, PyList, PyTuple};
|
||||
use objects::{PyInstance, PyList, PyTuple};
|
||||
use ffi::Py_ssize_t;
|
||||
use err;
|
||||
use err::{PyErr, PyResult};
|
||||
|
@ -15,18 +16,19 @@ use objectprotocol::ObjectProtocol;
|
|||
|
||||
|
||||
/// Represents a reference to a python object supporting the sequence protocol.
|
||||
pub struct PySequence(PyPtr);
|
||||
pub struct PySequence(PyObject);
|
||||
|
||||
pyobject_nativetype!(PySequence);
|
||||
pyobject_downcast!(PySequence, PySequence_Check);
|
||||
|
||||
|
||||
impl PySequence {
|
||||
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
||||
#[inline]
|
||||
pub fn len(&self, py: Python) -> PyResult<isize> {
|
||||
let v = unsafe { ffi::PySequence_Size(self.0.as_ptr()) };
|
||||
pub fn len(&self) -> PyResult<isize> {
|
||||
let v = unsafe { ffi::PySequence_Size(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(v as isize)
|
||||
}
|
||||
|
@ -34,10 +36,10 @@ impl PySequence {
|
|||
|
||||
/// Return the concatenation of o1 and o2. Equivalent to python `o1 + o2`
|
||||
#[inline]
|
||||
pub fn concat(&self, py: Python, other: &PySequence) -> PyResult<PySequence> {
|
||||
pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> {
|
||||
unsafe {
|
||||
Ok(PySequence(PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))?))
|
||||
self.token().cast_from_ptr_or_err::<PySequence>(
|
||||
ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,49 +47,57 @@ impl PySequence {
|
|||
/// Equivalent to python `o * count`
|
||||
/// NB: Python accepts negative counts; it returns an empty Sequence.
|
||||
#[inline]
|
||||
pub fn repeat(&self, py: Python, count: isize) -> PyResult<PySequence> {
|
||||
pub fn repeat(&self, count: isize) -> PyResult<&PySequence> {
|
||||
unsafe {
|
||||
Ok(PySequence(PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))?))
|
||||
self.token().cast_from_ptr_or_err::<PySequence>(
|
||||
ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the concatenation of o1 and o2 on success. Equivalent to python `o1 += o2`
|
||||
/// Concatenate of o1 and o2 on success. Equivalent to python `o1 += o2`
|
||||
#[inline]
|
||||
pub fn in_place_concat(&self, py: Python, other: &PySequence) -> PyResult<PySequence> {
|
||||
pub fn in_place_concat(&self, other: &PySequence) -> PyResult<()> {
|
||||
unsafe {
|
||||
Ok(PySequence(PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_InPlaceConcat(self.0.as_ptr(), other.as_ptr()))?))
|
||||
let ptr = ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr());
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the result of repeating sequence object o count times.
|
||||
/// Repeate sequence object o count times and store in self.
|
||||
/// Equivalent to python `o *= count`
|
||||
/// NB: Python accepts negative counts; it empties the Sequence.
|
||||
#[inline]
|
||||
pub fn in_place_repeat(&self, py: Python, count: isize) -> PyResult<PySequence> {
|
||||
pub fn in_place_repeat(&self, count: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
Ok(PySequence(PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t))?))
|
||||
let ptr = ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t);
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the ith element of the Sequence. Equivalent to python `o[index]`
|
||||
#[inline]
|
||||
pub fn get_item(&self, py: Python, index: isize) -> PyResult<PyObject> {
|
||||
pub fn get_item(&self, index: isize) -> PyResult<&PyInstance> {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
self.token().cast_from_ptr_or_err(
|
||||
ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the slice of sequence object o between begin and end.
|
||||
/// This is the equivalent of the Python expression `o[begin:end]`
|
||||
#[inline]
|
||||
pub fn get_slice(&self, py: Python, begin: isize, end: isize) -> PyResult<PyObject> {
|
||||
pub fn get_slice(&self, begin: isize, end: isize) -> PyResult<&PyInstance> {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PySequence_GetSlice(
|
||||
self.token().cast_from_ptr_or_err(
|
||||
ffi::PySequence_GetSlice(
|
||||
self.as_ptr(), begin as Py_ssize_t, end as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +105,10 @@ impl PySequence {
|
|||
/// Assign object v to the ith element of o.
|
||||
/// Equivalent to Python statement `o[i] = v`
|
||||
#[inline]
|
||||
pub fn set_item(&self, py: Python, i: isize, v: &PyObject) -> PyResult<()> {
|
||||
pub fn set_item(&self, i: isize, v: &PyInstance) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
err::error_on_minusone(
|
||||
self.token(),
|
||||
ffi::PySequence_SetItem(self.as_ptr(), i as Py_ssize_t, v.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
@ -105,9 +116,10 @@ impl PySequence {
|
|||
/// Delete the ith element of object o.
|
||||
/// Python statement `del o[i]`
|
||||
#[inline]
|
||||
pub fn del_item(&self, py: Python, i: isize) -> PyResult<()> {
|
||||
pub fn del_item(&self, i: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
err::error_on_minusone(
|
||||
self.token(),
|
||||
ffi::PySequence_DelItem(self.as_ptr(), i as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
@ -115,10 +127,10 @@ impl PySequence {
|
|||
/// Assign the sequence object v to the slice in sequence object o from i1 to i2.
|
||||
/// This is the equivalent of the Python statement `o[i1:i2] = v`
|
||||
#[inline]
|
||||
pub fn set_slice(&self, py: Python, i1: isize, i2: isize, v: &PyObject) -> PyResult<()> {
|
||||
pub fn set_slice(&self, i1: isize, i2: isize, v: &PyInstance) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PySequence_SetSlice(
|
||||
self.token(), ffi::PySequence_SetSlice(
|
||||
self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t, v.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
@ -126,24 +138,24 @@ impl PySequence {
|
|||
/// Delete the slice in sequence object o from i1 to i2.
|
||||
/// equivalent of the Python statement `del o[i1:i2]`
|
||||
#[inline]
|
||||
pub fn del_slice(&self, py: Python, i1: isize, i2: isize) -> PyResult<()> {
|
||||
pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(
|
||||
py, ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t))
|
||||
self.token(),
|
||||
ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of occurrences of value in o, that is, return the number of keys for
|
||||
/// which `o[key] == value`
|
||||
#[inline]
|
||||
pub fn count<V>(&self, py: Python, value: V) -> PyResult<usize>
|
||||
where V: ToPyObject
|
||||
pub fn count<V>(&self, value: V) -> PyResult<usize> where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Count(self.as_ptr(), ptr)
|
||||
});
|
||||
if r == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(r as usize)
|
||||
}
|
||||
|
@ -151,30 +163,28 @@ impl PySequence {
|
|||
|
||||
/// Determine if o contains value. this is equivalent to the Python expression `value in o`
|
||||
#[inline]
|
||||
pub fn contains<V>(&self, py: Python, value: V) -> PyResult<bool>
|
||||
where V: ToPyObject
|
||||
pub fn contains<V>(&self, value: V) -> PyResult<bool> where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Contains(self.as_ptr(), ptr)
|
||||
});
|
||||
match r {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
_ => Err(PyErr::fetch(py))
|
||||
_ => Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the first index i for which o[i] == value.
|
||||
/// This is equivalent to the Python expression `o.index(value)`
|
||||
#[inline]
|
||||
pub fn index<V>(&self, py: Python, value: V) -> PyResult<usize>
|
||||
where V: ToPyObject
|
||||
pub fn index<V>(&self, value: V) -> PyResult<usize> where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Index(self.as_ptr(), ptr)
|
||||
});
|
||||
if r == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else {
|
||||
Ok(r as usize)
|
||||
}
|
||||
|
@ -182,29 +192,26 @@ impl PySequence {
|
|||
|
||||
/// Return a fresh list based on the Sequence.
|
||||
#[inline]
|
||||
pub fn list(&self, py: Python) -> PyResult<PyList> {
|
||||
pub fn list<'p>(&self, py: Python<'p>) -> PyResult<&'p PyList> {
|
||||
unsafe {
|
||||
Ok(PyList::downcast_from_ptr(
|
||||
py, ffi::PySequence_List(self.as_ptr()))?)
|
||||
py.cast_from_ptr_or_err(ffi::PySequence_List(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a fresh tuple based on the Sequence.
|
||||
#[inline]
|
||||
pub fn tuple(&self, py: Python) -> PyResult<PyTuple> {
|
||||
pub fn tuple<'p>(&self, py: Python<'p>) -> PyResult<&'p PyTuple> {
|
||||
unsafe {
|
||||
Ok(PyTuple::downcast_from_ptr(
|
||||
py, ffi::PySequence_Tuple(self.as_ptr()))?)
|
||||
py.cast_from_ptr_or_err(ffi::PySequence_Tuple(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'source, T> FromPyObject<'source> for Vec<T>
|
||||
where for<'a> T: FromPyObject<'a>
|
||||
impl<'a, T> FromPyObject<'a> for Vec<T> where T: FromPyObject<'a>
|
||||
{
|
||||
default fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
extract_sequence(py, obj)
|
||||
default fn extract(obj: &'a PyInstance) -> PyResult<Self> {
|
||||
extract_sequence(obj)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,7 +219,7 @@ impl<'source, T> FromPyObject<'source> for Vec<T>
|
|||
impl <'source, T> FromPyObject<'source> for Vec<T>
|
||||
where for<'a> T: FromPyObject<'a> + buffer::Element + Copy
|
||||
{
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
fn extract(py: Python, obj: &'source PyInstance) -> PyResult<Self> {
|
||||
// first try buffer protocol
|
||||
if let Ok(buf) = buffer::PyBuffer::get(py, obj) {
|
||||
if buf.dimensions() == 1 {
|
||||
|
@ -228,21 +235,21 @@ impl <'source, T> FromPyObject<'source> for Vec<T>
|
|||
}
|
||||
}*/
|
||||
|
||||
fn extract_sequence<T>(py: Python, obj: &PyObject) -> PyResult<Vec<T>>
|
||||
where for<'a> T: FromPyObject<'a>
|
||||
fn extract_sequence<'s, T>(obj: &'s PyInstance) -> PyResult<Vec<T>> where T: FromPyObject<'s>
|
||||
{
|
||||
let seq = PySequence::downcast_from(py, obj)?;
|
||||
let seq = PySequence::downcast_from(obj)?;
|
||||
let mut v = Vec::new();
|
||||
for item in try!(seq.iter(py)) {
|
||||
for item in try!(seq.iter()) {
|
||||
let item = try!(item);
|
||||
v.push(try!(T::extract(py, &item)));
|
||||
v.push(try!(item.extract::<T>()));
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python, PyDowncastInto};
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PySequence};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
@ -252,7 +259,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = 42i32;
|
||||
assert!(v.to_object(py).cast_into::<PySequence>(py).is_err());
|
||||
assert!(v.to_object(py).cast_as::<PySequence>(py).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -260,36 +267,38 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "London Calling";
|
||||
assert!(v.to_object(py).cast_into::<PySequence>(py).is_ok());
|
||||
assert!(v.to_object(py).cast_as::<PySequence>(py).is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn test_seq_empty() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.len(py).unwrap());
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.len().unwrap());
|
||||
|
||||
let needle = 7i32.to_object(py);
|
||||
assert_eq!(false, seq.contains(py, &needle).unwrap());
|
||||
assert_eq!(false, seq.contains(&needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seq_contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, seq.len(py).unwrap());
|
||||
let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, seq.len().unwrap());
|
||||
|
||||
let bad_needle = 7i32.to_object(py);
|
||||
assert_eq!(false, seq.contains(py, &bad_needle).unwrap());
|
||||
assert_eq!(false, seq.contains(&bad_needle).unwrap());
|
||||
|
||||
let good_needle = 8i32.to_object(py);
|
||||
assert_eq!(true, seq.contains(py, &good_needle).unwrap());
|
||||
assert_eq!(true, seq.contains(&good_needle).unwrap());
|
||||
|
||||
let type_coerced_needle = 8f32.to_object(py);
|
||||
assert_eq!(true, seq.contains(py, &type_coerced_needle).unwrap());
|
||||
assert_eq!(true, seq.contains(&type_coerced_needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -297,19 +306,20 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(1, seq.get_item(py, 1).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, seq.get_item(py, 2).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, seq.get_item(py, 3).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, seq.get_item(py, 4).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(8, seq.get_item(py, 5).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(8, seq.get_item(py, -1).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, seq.get_item(py, -2).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, seq.get_item(py, -3).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, seq.get_item(py, -4).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(1, seq.get_item(py, -5).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.get_item(py, 10).is_err());
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(1, seq.get_item(1).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(2, seq.get_item(2).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(3, seq.get_item(3).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(5, seq.get_item(4).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(8, seq.get_item(5).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(8, seq.get_item(-1).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(5, seq.get_item(-2).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(3, seq.get_item(-3).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(2, seq.get_item(-4).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(1, seq.get_item(-5).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.get_item(10).is_err());
|
||||
}
|
||||
|
||||
// fn test_get_slice() {}
|
||||
|
@ -320,62 +330,66 @@ mod test {
|
|||
fn test_seq_del_item() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.del_item(py, 10).is_err());
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(2, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(3, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(5, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(8, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(0, seq.len(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_err());
|
||||
let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert!(seq.del_item(10).is_err());
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(2, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(3, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(5, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(8, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(0, seq.len().unwrap());
|
||||
assert!(seq.del_item(0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seq_index() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.index(py, 1i32).unwrap());
|
||||
assert_eq!(2, seq.index(py, 2i32).unwrap());
|
||||
assert_eq!(3, seq.index(py, 3i32).unwrap());
|
||||
assert_eq!(4, seq.index(py, 5i32).unwrap());
|
||||
assert_eq!(5, seq.index(py, 8i32).unwrap());
|
||||
assert!(seq.index(py, 42i32).is_err());
|
||||
let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.index(1i32).unwrap());
|
||||
assert_eq!(2, seq.index(2i32).unwrap());
|
||||
assert_eq!(3, seq.index(3i32).unwrap());
|
||||
assert_eq!(4, seq.index(5i32).unwrap());
|
||||
assert_eq!(5, seq.index(8i32).unwrap());
|
||||
assert!(seq.index(42i32).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seq_count() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(2, seq.count(py, 1i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 2i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 3i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 5i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 8i32).unwrap());
|
||||
assert_eq!(0, seq.count(py, 42i32).unwrap());
|
||||
let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert_eq!(2, seq.count(1i32).unwrap());
|
||||
assert_eq!(1, seq.count(2i32).unwrap());
|
||||
assert_eq!(1, seq.count(3i32).unwrap());
|
||||
assert_eq!(1, seq.count(5i32).unwrap());
|
||||
assert_eq!(1, seq.count(8i32).unwrap());
|
||||
assert_eq!(0, seq.count(42i32).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seq_iter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in seq.iter(py).unwrap() {
|
||||
assert_eq!(v[idx], el.unwrap().extract::<i32>(py).unwrap());
|
||||
for el in seq.iter().unwrap() {
|
||||
assert_eq!(v[idx], el.unwrap().extract::<i32>().unwrap());
|
||||
idx += 1;
|
||||
}
|
||||
assert_eq!(idx, v.len());
|
||||
|
@ -386,13 +400,14 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["It", "was", "the", "worst", "of", "times"];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
|
||||
let bad_needle = "blurst".to_object(py);
|
||||
assert_eq!(false, seq.contains(py, bad_needle).unwrap());
|
||||
assert_eq!(false, seq.contains(bad_needle).unwrap());
|
||||
|
||||
let good_needle = "worst".to_object(py);
|
||||
assert_eq!(true, seq.contains(py, good_needle).unwrap());
|
||||
assert_eq!(true, seq.contains(good_needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -400,12 +415,13 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 2, 3];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(py, &seq).unwrap();
|
||||
assert_eq!(6, concat_seq.len(py).unwrap());
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(&seq).unwrap();
|
||||
assert_eq!(6, concat_seq.len().unwrap());
|
||||
let concat_v : Vec<i32> = vec![1, 2, 3, 1, 2, 3];
|
||||
for (el, cc) in seq.iter(py).unwrap().zip(concat_v) {
|
||||
assert_eq!(cc, el.unwrap().extract::<i32>(py).unwrap());
|
||||
for (el, cc) in concat_seq.iter().unwrap().zip(concat_v) {
|
||||
assert_eq!(cc, el.unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,9 +430,10 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "string";
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(py, &seq).unwrap();
|
||||
assert_eq!(12, concat_seq.len(py).unwrap());
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(&seq).unwrap();
|
||||
assert_eq!(12, concat_seq.len().unwrap());
|
||||
/*let concat_v = "stringstring".to_owned();
|
||||
for (el, cc) in seq.iter(py).unwrap().zip(concat_v.chars()) {
|
||||
assert_eq!(cc, el.unwrap().extract::<char>(py).unwrap()); //TODO: extract::<char>() is not implemented
|
||||
|
@ -428,12 +445,13 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let repeat_seq = seq.repeat(py, 3).unwrap();
|
||||
assert_eq!(6, repeat_seq.len(py).unwrap());
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
let repeat_seq = seq.repeat(3).unwrap();
|
||||
assert_eq!(6, repeat_seq.len().unwrap());
|
||||
let repeated = vec!["foo", "bar", "foo", "bar", "foo", "bar"];
|
||||
for (el, rpt) in seq.iter(py).unwrap().zip(repeated.iter()) {
|
||||
assert_eq!(*rpt, el.unwrap().extract::<String>(py).unwrap());
|
||||
for (el, rpt) in repeat_seq.iter().unwrap().zip(repeated.iter()) {
|
||||
assert_eq!(*rpt, el.unwrap().extract::<String>().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,7 +460,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert!(seq.list(py).is_ok());
|
||||
}
|
||||
|
||||
|
@ -451,7 +470,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "foo";
|
||||
let seq = PySequence::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let seq = PySequence::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert!(seq.list(py).is_ok());
|
||||
}
|
||||
|
||||
|
@ -460,7 +480,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = ("foo", "bar");
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple(py).is_ok());
|
||||
}
|
||||
|
||||
|
@ -469,7 +490,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let ob = v.to_object(py);
|
||||
let seq = ob.cast_as::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple(py).is_ok());
|
||||
}
|
||||
|
||||
|
@ -477,7 +499,7 @@ mod test {
|
|||
fn test_extract_tuple_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<i32> = py.eval("(1, 2)", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<i32> = py.eval("(1, 2)", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == [1, 2]);
|
||||
}
|
||||
|
||||
|
@ -485,7 +507,7 @@ mod test {
|
|||
fn test_extract_range_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<i32> = py.eval("range(1, 5)", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<i32> = py.eval("range(1, 5)", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == [1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
|
@ -493,7 +515,7 @@ mod test {
|
|||
fn test_extract_bytearray_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<u8> = py.eval("bytearray(b'abc')", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<u8> = py.eval("bytearray(b'abc')", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == b"abc");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,78 +4,77 @@
|
|||
use std::{hash, collections};
|
||||
use ffi;
|
||||
use python::{Python, ToPyPointer};
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyObject;
|
||||
use instance::{AsPyRef, Py, PyObjectWithToken};
|
||||
use err::{self, PyResult, PyErr};
|
||||
|
||||
|
||||
/// Represents a Python `set`
|
||||
pub struct PySet(PyPtr);
|
||||
pub struct PySet(PyObject);
|
||||
|
||||
/// Represents a Python `frozenset`
|
||||
pub struct PyFrozenSet(PyPtr);
|
||||
pub struct PyFrozenSet(PyObject);
|
||||
|
||||
pyobject_convert!(PySet);
|
||||
pyobject_nativetype!(PySet, PySet_Type, PySet_Check);
|
||||
pyobject_convert!(PyFrozenSet);
|
||||
pyobject_nativetype!(PySet, PySet_Type, PySet_Check);
|
||||
pyobject_nativetype!(PyFrozenSet, PyFrozenSet_Type, PyFrozenSet_Check);
|
||||
|
||||
impl PySet {
|
||||
/// Creates a new set.
|
||||
///
|
||||
/// May panic when running out of memory.
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> PySet {
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> Py<PySet> {
|
||||
let list = elements.to_object(py);
|
||||
unsafe {
|
||||
let ptr = ffi::PySet_New(list.as_ptr());
|
||||
PySet(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ffi::PySet_New(list.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all elements from the set.
|
||||
#[inline]
|
||||
pub fn clear(&self, _py: Python) {
|
||||
pub fn clear(&self) {
|
||||
unsafe { ffi::PySet_Clear(self.as_ptr()); }
|
||||
}
|
||||
|
||||
/// Return the number of items in the set.
|
||||
/// This is equivalent to len(p) on a set.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::PySet_Size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Determine if the set contains the specified key.
|
||||
/// This is equivalent to the Python expression `key in self`.
|
||||
pub fn contains<K>(&self, py: Python, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
pub fn contains<K>(&self, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
match ffi::PySet_Contains(self.as_ptr(), key) {
|
||||
1 => Ok(true),
|
||||
0 => Ok(false),
|
||||
_ => Err(PyErr::fetch(py))
|
||||
_ => Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Remove element from the set if it is present.
|
||||
pub fn discard<K>(&self, py: Python, key: K) where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
pub fn discard<K>(&self, key: K) where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
ffi::PySet_Discard(self.as_ptr(), key);
|
||||
})
|
||||
}
|
||||
|
||||
/// Add element to the set.
|
||||
pub fn add<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, move |key| unsafe {
|
||||
err::error_on_minusone(py, ffi::PySet_Add(self.as_ptr(), key))
|
||||
pub fn add<K>(&self, key: K) -> PyResult<()> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), move |key| unsafe {
|
||||
err::error_on_minusone(self.token(), ffi::PySet_Add(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
/// Remove and return an arbitrary element from the set
|
||||
pub fn pop(&self, py: Python) -> Option<PyObject> {
|
||||
pub fn pop(&self) -> Option<PyObject> {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr_or_opt(py, ffi::PySet_Pop(self.as_ptr()))
|
||||
PyObject::from_owned_ptr_or_opt(self.token(), ffi::PySet_Pop(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +84,11 @@ impl<T> ToPyObject for collections::HashSet<T>
|
|||
{
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
let set = PySet::new::<T>(py, &[]);
|
||||
for val in self {
|
||||
set.add(py, val).expect("Failed to add to set");
|
||||
{
|
||||
let s = set.as_ref(py);
|
||||
for val in self {
|
||||
s.add(val).expect("Failed to add to set");
|
||||
}
|
||||
}
|
||||
set.into()
|
||||
}
|
||||
|
@ -97,8 +99,11 @@ impl<T> ToPyObject for collections::BTreeSet<T>
|
|||
{
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
let set = PySet::new::<T>(py, &[]);
|
||||
for val in self {
|
||||
set.add(py, val).expect("Failed to add to set");
|
||||
{
|
||||
let s = set.as_ref(py);
|
||||
for val in self {
|
||||
s.add(val).expect("Failed to add to set");
|
||||
}
|
||||
}
|
||||
set.into()
|
||||
}
|
||||
|
@ -108,29 +113,28 @@ impl PyFrozenSet {
|
|||
/// Creates a new frozenset.
|
||||
///
|
||||
/// May panic when running out of memory.
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> PyFrozenSet {
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> Py<PyFrozenSet> {
|
||||
let list = elements.to_object(py);
|
||||
unsafe {
|
||||
let ptr = ffi::PyFrozenSet_New(list.as_ptr());
|
||||
PyFrozenSet(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyFrozenSet_New(list.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of items in the set.
|
||||
/// This is equivalent to len(p) on a set.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::PySet_Size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Determine if the set contains the specified key.
|
||||
/// This is equivalent to the Python expression `key in self`.
|
||||
pub fn contains<K>(&self, py: Python, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(py, |key| unsafe {
|
||||
pub fn contains<K>(&self, key: K) -> PyResult<bool> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
match ffi::PySet_Contains(self.as_ptr(), key) {
|
||||
1 => Ok(true),
|
||||
0 => Ok(false),
|
||||
_ => Err(PyErr::fetch(py))
|
||||
_ => Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -139,10 +143,11 @@ impl PyFrozenSet {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::{HashSet};
|
||||
use python::{Python, PyDowncastInto};
|
||||
use super::{PySet, PyFrozenSet};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use super::{PySet, PyFrozenSet};
|
||||
use instance::AsPyRef;
|
||||
|
||||
#[test]
|
||||
fn test_set_new() {
|
||||
|
@ -150,7 +155,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
|
||||
let set = PySet::new(py, &[1]);
|
||||
assert_eq!(1, set.len(py));
|
||||
assert_eq!(1, set.as_ref(py).len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -160,22 +165,23 @@ mod test {
|
|||
|
||||
let mut v = HashSet::new();
|
||||
let ob = v.to_object(py);
|
||||
let set = PySet::downcast_into(py, ob).unwrap();
|
||||
assert_eq!(0, set.len(py));
|
||||
let set = PySet::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(0, set.len());
|
||||
v.insert(7);
|
||||
let ob = v.to_object(py);
|
||||
let set2 = PySet::downcast_into(py, ob).unwrap();
|
||||
assert_eq!(1, set2.len(py));
|
||||
let set2 = PySet::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(1, set2.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_clear() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PySet::new(py, &[1]);
|
||||
assert_eq!(1, set.len(py));
|
||||
set.clear(py);
|
||||
assert_eq!(0, set.len(py));
|
||||
let ob = PySet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
assert_eq!(1, set.len());
|
||||
set.clear();
|
||||
assert_eq!(0, set.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -183,37 +189,40 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PySet::new(py, &[1]);
|
||||
assert!(set.contains(py, 1).unwrap());
|
||||
assert!(set.as_ref(py).contains(1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_discard() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PySet::new(py, &[1]);
|
||||
set.discard(py, 2);
|
||||
assert_eq!(1, set.len(py));
|
||||
set.discard(py, 1);
|
||||
assert_eq!(0, set.len(py));
|
||||
let ob = PySet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
set.discard(2);
|
||||
assert_eq!(1, set.len());
|
||||
set.discard(1);
|
||||
assert_eq!(0, set.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_add() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PySet::new(py, &[1, 2]);
|
||||
set.add(py, 1).unwrap(); // Add a dupliated element
|
||||
assert!(set.contains(py, 1).unwrap());
|
||||
let ob = PySet::new(py, &[1, 2]);
|
||||
let set = ob.as_ref(py);
|
||||
set.add(1).unwrap(); // Add a dupliated element
|
||||
assert!(set.contains(1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_pop() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PySet::new(py, &[1]);
|
||||
let val = set.pop(py);
|
||||
let ob = PySet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
let val = set.pop();
|
||||
assert!(val.is_some());
|
||||
let val2 = set.pop(py);
|
||||
let val2 = set.pop();
|
||||
assert!(val2.is_none());
|
||||
}
|
||||
|
||||
|
@ -222,9 +231,10 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let set = PySet::new(py, &[1]);
|
||||
for el in set.iter(py).unwrap() {
|
||||
assert_eq!(1i32, el.unwrap().extract::<i32>(py).unwrap());
|
||||
let ob = PySet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
for el in set.iter().unwrap() {
|
||||
assert_eq!(1i32, el.unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,16 +243,18 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let set = PyFrozenSet::new(py, &[1]);
|
||||
assert_eq!(1, set.len(py));
|
||||
let ob = PyFrozenSet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
assert_eq!(1, set.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_frozenset_contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set = PyFrozenSet::new(py, &[1]);
|
||||
assert!(set.contains(py, 1).unwrap());
|
||||
let ob = PyFrozenSet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
assert!(set.contains(1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -250,9 +262,10 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let set = PyFrozenSet::new(py, &[1]);
|
||||
for el in set.iter(py).unwrap() {
|
||||
assert_eq!(1i32, el.unwrap().extract::<i32>(py).unwrap());
|
||||
let ob = PyFrozenSet::new(py, &[1]);
|
||||
let set = ob.as_ref(py);
|
||||
for el in set.iter().unwrap() {
|
||||
assert_eq!(1i32, el.unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
use std::os::raw::c_long;
|
||||
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{ToPyPointer, Python};
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use objects::PyObject;
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use conversion::ToPyObject;
|
||||
|
||||
/// Represents a Python `slice`. Only `c_long` indeces supprted
|
||||
/// at the moment by `PySlice` object.
|
||||
pub struct PySlice(PyPtr);
|
||||
pub struct PySlice(PyObject);
|
||||
|
||||
pyobject_convert!(PySlice);
|
||||
pyobject_nativetype!(PySlice, PySlice_Type, PySlice_Check);
|
||||
|
@ -40,18 +40,18 @@ impl PySliceIndices {
|
|||
impl PySlice {
|
||||
|
||||
/// Construct a new slice with the given elements.
|
||||
pub fn new(_py: Python, start: isize, stop: isize, step: isize) -> PySlice {
|
||||
pub fn new(_py: Python, start: isize, stop: isize, step: isize) -> Py<PySlice> {
|
||||
unsafe {
|
||||
let ptr = ffi::PySlice_New(ffi::PyLong_FromLong(start as i64),
|
||||
ffi::PyLong_FromLong(stop as i64),
|
||||
ffi::PyLong_FromLong(step as i64));
|
||||
PySlice(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the start, stop, and step indices from the slice object slice assuming a sequence of length length, and store the length of the slice in slicelength.
|
||||
#[inline]
|
||||
pub fn indices(&self, py: Python, length: c_long) -> PyResult<PySliceIndices> {
|
||||
pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> {
|
||||
// non-negative Py_ssize_t should always fit into Rust usize
|
||||
unsafe {
|
||||
let slicelen: isize = 0;
|
||||
|
@ -72,7 +72,7 @@ impl PySlice {
|
|||
slicelength: slicelen,
|
||||
})
|
||||
} else {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,15 @@ use std::borrow::Cow;
|
|||
use std::os::raw::c_char;
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use pointer::PyObject;
|
||||
use objects::PyInstance;
|
||||
use python::{ToPyPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use super::{PyObject, PyStringData};
|
||||
use super::PyStringData;
|
||||
|
||||
/// Represents a Python string.
|
||||
pub struct PyString(PyPtr);
|
||||
pub struct PyString(PyObject);
|
||||
|
||||
pyobject_convert!(PyString);
|
||||
pyobject_nativetype!(PyString, PyUnicode_Type, PyUnicode_Check);
|
||||
|
@ -24,46 +26,45 @@ pyobject_nativetype!(PyString, PyUnicode_Type, PyUnicode_Check);
|
|||
pub use PyString as PyUnicode;
|
||||
|
||||
/// Represents a Python byte string.
|
||||
pub struct PyBytes(PyPtr);
|
||||
pub struct PyBytes(PyObject);
|
||||
|
||||
pyobject_convert!(PyBytes);
|
||||
pyobject_nativetype!(PyBytes, PyBytes_Type, PyBytes_Check);
|
||||
|
||||
|
||||
impl PyString {
|
||||
|
||||
/// Creates a new Python string object.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(_py: Python, s: &str) -> PyString {
|
||||
pub fn new(_py: Python, s: &str) -> Py<PyString> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
PyString(PyPtr::from_owned_ptr_or_panic(
|
||||
ffi::PyUnicode_FromStringAndSize(ptr, len)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_object(py: Python, src: &PyObject, encoding: &str, errors: &str)
|
||||
-> PyResult<PyString> {
|
||||
pub fn from_object(py: Python, src: &PyInstance, encoding: &str, errors: &str)
|
||||
-> PyResult<Py<PyString>> {
|
||||
unsafe {
|
||||
Ok(PyString(
|
||||
PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(),
|
||||
encoding.as_ptr() as *const i8,
|
||||
errors.as_ptr() as *const i8))?))
|
||||
Ok(Py::from_owned_ptr_or_err(
|
||||
py, ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(),
|
||||
encoding.as_ptr() as *const i8,
|
||||
errors.as_ptr() as *const i8))?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the python string data in its underlying representation.
|
||||
pub fn data(&self, py: Python) -> PyStringData {
|
||||
pub fn data(&self) -> PyStringData {
|
||||
// TODO: return the original representation instead
|
||||
// of forcing the UTF-8 representation to be created.
|
||||
unsafe {
|
||||
let mut size : ffi::Py_ssize_t = mem::uninitialized();
|
||||
let data = ffi::PyUnicode_AsUTF8AndSize(self.0.as_ptr(), &mut size) as *const u8;
|
||||
if data.is_null() {
|
||||
PyErr::fetch(py).print(py);
|
||||
PyErr::fetch(self.token()).print(self.token());
|
||||
panic!("PyUnicode_AsUTF8AndSize failed");
|
||||
}
|
||||
PyStringData::Utf8(std::slice::from_raw_parts(data, size as usize))
|
||||
|
@ -74,30 +75,30 @@ impl PyString {
|
|||
///
|
||||
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates).
|
||||
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
|
||||
self.data(py).to_string(py)
|
||||
pub fn to_string(&self) -> PyResult<Cow<str>> {
|
||||
self.data().to_string(self.token())
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
///
|
||||
/// Unpaired surrogates invalid UTF-8 sequences are
|
||||
/// replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self, py: Python) -> Cow<str> {
|
||||
self.data(py).to_string_lossy()
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
self.data().to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PyBytes {
|
||||
/// Creates a new Python byte string object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(_py: Python, s: &[u8]) -> PyBytes {
|
||||
pub fn new(_py: Python, s: &[u8]) -> Py<PyBytes> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
PyBytes(PyPtr::from_owned_ptr_or_panic(
|
||||
ffi::PyBytes_FromStringAndSize(ptr, len)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyBytes_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +116,7 @@ impl PyBytes {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::Python;
|
||||
use instance::AsPyRef;
|
||||
use conversion::{ToPyObject, RefFromPyObject};
|
||||
|
||||
#[test]
|
||||
|
@ -133,7 +135,7 @@ mod test {
|
|||
let s = "Hello Python";
|
||||
let py_string = s.to_object(py);
|
||||
let mut called = false;
|
||||
RefFromPyObject::with_extracted(py, &py_string.into(),
|
||||
RefFromPyObject::with_extracted(py_string.as_ref(py),
|
||||
|s2: &str| {
|
||||
assert_eq!(s, s2);
|
||||
called = true;
|
||||
|
|
|
@ -9,30 +9,32 @@ use std::ascii::AsciiExt;
|
|||
use std::os::raw::c_char;
|
||||
|
||||
use ffi;
|
||||
use conversion::FromPyObject;
|
||||
use err::{PyResult, PyDowncastError};
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer, PyDowncastInto, PyDowncastFrom};
|
||||
use super::{PyObject, PyStringData};
|
||||
use err::PyResult;
|
||||
use pointer::PyObject;
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use python::{Python, ToPyPointer};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use super::{PyInstance, PyStringData};
|
||||
|
||||
/// Represents a Python string.
|
||||
pub struct PyString(PyPtr);
|
||||
pub struct PyString(PyObject);
|
||||
|
||||
pyobject_convert!(PyString);
|
||||
pyobject_nativetype!(PyString, PyBaseString_Type);
|
||||
pyobject_nativetype!(PyString, PyBaseString_Type, PyBaseString_Check);
|
||||
|
||||
/// Represents a Python unicode string.
|
||||
pub struct PyUnicode(PyPtr);
|
||||
pub struct PyUnicode(PyObject);
|
||||
|
||||
pyobject_convert!(PyUnicode);
|
||||
pyobject_nativetype!(PyUnicode, PyUnicode_Type, PyUnicode_Check);
|
||||
|
||||
/// Represents a Python byte string. Corresponds to `str` in Python 2
|
||||
pub struct PyBytes(PyPtr);
|
||||
pub struct PyBytes(PyObject);
|
||||
|
||||
pyobject_convert!(PyBytes);
|
||||
pyobject_nativetype!(PyBytes, PyBaseString_Type, PyString_Check);
|
||||
|
||||
|
||||
impl PyString {
|
||||
/// Creates a new Python string object.
|
||||
///
|
||||
|
@ -41,21 +43,20 @@ impl PyString {
|
|||
/// Use `PyUnicode::new()` to always create a unicode string.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(py: Python, s: &str) -> PyString {
|
||||
pub fn new(py: Python, s: &str) -> Py<PyString> {
|
||||
if s.is_ascii() {
|
||||
PyBytes::new(py, s.as_bytes()).into_basestring()
|
||||
PyBytes::new(py, s.as_bytes()).into()
|
||||
} else {
|
||||
PyUnicode::new(py, s).into_basestring()
|
||||
PyUnicode::new(py, s).into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_object(py: Python, src: &PyObject,
|
||||
encoding: &str, errors: &str) -> PyResult<PyString> {
|
||||
pub fn from_object(src: &PyInstance, encoding: &str, errors: &str) -> PyResult<Py<PyString>> {
|
||||
unsafe {
|
||||
Ok(PyString(PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PyUnicode_FromEncodedObject(
|
||||
Ok(Py::from_owned_ptr_or_err(
|
||||
src.token(), ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(), encoding.as_ptr() as *const i8, errors.as_ptr() as *const i8))?
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,12 +65,11 @@ impl PyString {
|
|||
/// For Python 2 byte strings, this function always returns `PyStringData::Utf8`,
|
||||
/// even if the bytes are not valid UTF-8.
|
||||
/// For unicode strings, returns the underlying representation used by Python.
|
||||
pub fn data(&self, py: Python) -> PyStringData {
|
||||
let ob: &PyObject = self.as_ref();
|
||||
if let Ok(bytes) = ob.cast_as::<PyBytes>(py) {
|
||||
PyStringData::Utf8(bytes.data(py))
|
||||
} else if let Ok(unicode) = ob.cast_as::<PyUnicode>(py) {
|
||||
unicode.data(py)
|
||||
pub fn data(&self) -> PyStringData {
|
||||
if let Ok(bytes) = self.cast_as::<PyBytes>() {
|
||||
PyStringData::Utf8(bytes.data())
|
||||
} else if let Ok(unicode) = self.cast_as::<PyUnicode>() {
|
||||
unicode.data()
|
||||
} else {
|
||||
panic!("PyString is neither `str` nor `unicode`")
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ impl PyString {
|
|||
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates, or a Python 2.7 byte string that is
|
||||
/// not valid UTF-8).
|
||||
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
|
||||
self.data(py).to_string(py)
|
||||
pub fn to_string(&self) -> PyResult<Cow<str>> {
|
||||
self.data().to_string(self.token())
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
|
@ -94,100 +94,8 @@ impl PyString {
|
|||
///
|
||||
/// Unpaired surrogates and (on Python 2.7) invalid UTF-8 sequences are
|
||||
/// replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self, py: Python) -> Cow<str> {
|
||||
self.data(py).to_string_lossy()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_base_string(ptr: *mut ffi::PyObject) -> bool {
|
||||
unsafe {
|
||||
ffi::PyType_FastSubclass(
|
||||
ffi::Py_TYPE(ptr),
|
||||
ffi::Py_TPFLAGS_STRING_SUBCLASS | ffi::Py_TPFLAGS_UNICODE_SUBCLASS) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyDowncastFrom for PyString
|
||||
{
|
||||
fn downcast_from<'a, 'p>(py: Python<'p>, ob: &'a PyObject)
|
||||
-> Result<&'a PyString, PyDowncastError<'p>>
|
||||
{
|
||||
unsafe {
|
||||
if PyString::is_base_string(ob.as_ptr()) {
|
||||
let ptr = ob as *const _ as *mut u8 as *mut PyString;
|
||||
Ok(ptr.as_ref().expect("Failed to call as_ref"))
|
||||
} else {
|
||||
Err(PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyDowncastInto for PyString
|
||||
{
|
||||
fn downcast_into<'p, I>(py: Python<'p>, ob: I) -> Result<Self, PyDowncastError<'p>>
|
||||
where I: IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if PyString::is_base_string(ptr) {
|
||||
Ok(PyString(PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn downcast_from_ptr<'p>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<PyString, PyDowncastError<'p>>
|
||||
{
|
||||
unsafe{
|
||||
if PyString::is_base_string(ptr) {
|
||||
Ok(PyString(PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unchecked_downcast_into<'p, I>(ob: I) -> Self where I: IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
PyString(PyPtr::from_owned_ptr(ob.into_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromPyObject<'a> for PyString
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'a PyObject) -> PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
if PyString::is_base_string(ob.as_ptr()) {
|
||||
Ok( PyString(PyPtr::from_borrowed_ptr(ob.as_ptr())) )
|
||||
} else {
|
||||
Err(PyDowncastError(py, None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromPyObject<'a> for &'a PyString
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: Python, ob: &'a PyObject) -> PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
if PyString::is_base_string(ob.as_ptr()) {
|
||||
Ok(std::mem::transmute(ob))
|
||||
} else {
|
||||
Err(PyDowncastError(py, None).into())
|
||||
}
|
||||
}
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
self.data().to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,23 +104,16 @@ impl PyBytes {
|
|||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(_py: Python, s: &[u8]) -> PyBytes {
|
||||
pub fn new(_py: Python, s: &[u8]) -> Py<PyBytes> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
PyBytes(PyPtr::from_owned_ptr_or_panic(
|
||||
ffi::PyBytes_FromStringAndSize(ptr, len)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyBytes_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyBytes` to `PyString`.
|
||||
#[inline]
|
||||
pub fn into_basestring(self) -> PyString {
|
||||
<PyString as ::PyDowncastInto>::unchecked_downcast_into(self)
|
||||
}
|
||||
|
||||
/// Gets the Python string data as byte slice.
|
||||
pub fn data(&self, _py: Python) -> &[u8] {
|
||||
pub fn data(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8;
|
||||
let length = ffi::PyBytes_Size(self.as_ptr()) as usize;
|
||||
|
@ -226,36 +127,27 @@ impl PyUnicode {
|
|||
/// Creates a new Python unicode string object.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(_py: Python, s: &str) -> PyUnicode {
|
||||
pub fn new(_py: Python, s: &str) -> Py<PyUnicode> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
PyUnicode(PyPtr::from_owned_ptr_or_panic(
|
||||
ffi::PyUnicode_FromStringAndSize(ptr, len)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_object(py: Python, src: &PyObject, encoding: &str, errors: &str)
|
||||
-> PyResult<PyUnicode>
|
||||
pub fn from_object(src: &PyInstance, encoding: &str, errors: &str) -> PyResult<Py<PyUnicode>>
|
||||
{
|
||||
unsafe {
|
||||
Ok(PyUnicode(
|
||||
PyPtr::from_owned_ptr_or_err(
|
||||
py, ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(),
|
||||
encoding.as_ptr() as *const i8,
|
||||
errors.as_ptr() as *const i8))?))
|
||||
Ok(Py::from_owned_ptr_or_err(
|
||||
src.token(), ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(),
|
||||
encoding.as_ptr() as *const i8,
|
||||
errors.as_ptr() as *const i8))?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyUnicode` to `PyString`.
|
||||
#[inline]
|
||||
pub fn into_basestring(self) -> PyString {
|
||||
<PyString as ::PyDowncastInto>::unchecked_downcast_into(self)
|
||||
}
|
||||
|
||||
/// Gets the python string data in its underlying representation.
|
||||
pub fn data(&self, _py: Python) -> PyStringData {
|
||||
pub fn data(&self) -> PyStringData {
|
||||
unsafe {
|
||||
let buffer = ffi::PyUnicode_AS_UNICODE(self.as_ptr());
|
||||
let length = ffi::PyUnicode_GET_SIZE(self.as_ptr()) as usize;
|
||||
|
@ -267,21 +159,39 @@ impl PyUnicode {
|
|||
///
|
||||
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates).
|
||||
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
|
||||
self.data(py).to_string(py)
|
||||
pub fn to_string(&self) -> PyResult<Cow<str>> {
|
||||
self.data().to_string(self.token())
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
///
|
||||
/// Unpaired surrogates are replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self, py: Python) -> Cow<str> {
|
||||
self.data(py).to_string_lossy()
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
self.data().to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyBytes` to `PyString`.
|
||||
impl std::convert::From<Py<PyBytes>> for Py<PyString> {
|
||||
#[inline]
|
||||
fn from(ob: Py<PyBytes>) -> Py<PyString> {
|
||||
<Py<PyString> as ::PyDowncastInto>::unchecked_downcast_into(ob)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyUnicode` to `PyString`.
|
||||
impl std::convert::From<Py<PyUnicode>> for Py<PyString> {
|
||||
#[inline]
|
||||
fn from(ob: Py<PyUnicode>) -> Py<PyString> {
|
||||
<Py<PyString> as ::PyDowncastInto>::unchecked_downcast_into(ob)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::Python;
|
||||
use instance::AsPyRef;
|
||||
use conversion::{ToPyObject, RefFromPyObject};
|
||||
|
||||
#[test]
|
||||
|
@ -300,7 +210,7 @@ mod test {
|
|||
let s = "Hello Python";
|
||||
let py_string = s.to_object(py);
|
||||
let mut called = false;
|
||||
RefFromPyObject::with_extracted(py, &py_string,
|
||||
RefFromPyObject::with_extracted(py_string.as_ref(py),
|
||||
|s2: &str| {
|
||||
assert_eq!(s, s2);
|
||||
called = true;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use err::PyResult;
|
||||
use objects::{PyObject, PyString};
|
||||
use python::{ToPyPointer, Python};
|
||||
use pointer::PyObject;
|
||||
use objects::{PyInstance, PyString};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use python::Python;
|
||||
use conversion::{ToPyObject, IntoPyObject, RefFromPyObject};
|
||||
|
||||
/// Converts Rust `str` to Python object.
|
||||
|
@ -52,25 +54,26 @@ impl<'a> IntoPyObject for &'a String {
|
|||
|
||||
/// Allows extracting strings from Python objects.
|
||||
/// Accepts Python `str` and `unicode` objects.
|
||||
pyobject_extract!(py, obj to Cow<'source, str> => {
|
||||
try!(obj.cast_as::<PyString>(py)).to_string(py)
|
||||
});
|
||||
|
||||
impl<'source> ::FromPyObject<'source> for Cow<'source, str>
|
||||
{
|
||||
fn extract(ob: &'source PyInstance) -> PyResult<Self>
|
||||
{
|
||||
try!(ob.cast_as::<PyString>()).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows extracting strings from Python objects.
|
||||
/// Accepts Python `str` and `unicode` objects.
|
||||
pyobject_extract!(py, obj to String => {
|
||||
let s = try!(obj.cast_as::<PyString>(py));
|
||||
s.to_string(py).map(Cow::into_owned)
|
||||
let s = try!(obj.cast_as::<PyString>());
|
||||
s.to_string().map(Cow::into_owned)
|
||||
});
|
||||
|
||||
|
||||
impl<'p> RefFromPyObject<'p> for str {
|
||||
fn with_extracted<F, R>(py: Python, obj: &'p PyObject, f: F) -> PyResult<R>
|
||||
impl RefFromPyObject for str {
|
||||
fn with_extracted<F, R>(obj: &PyInstance, f: F) -> PyResult<R>
|
||||
where F: FnOnce(&str) -> R
|
||||
{
|
||||
let p = PyObject::from_borrowed_ptr(py, obj.as_ptr());
|
||||
let s = try!(p.extract::<Cow<str>>(py));
|
||||
let s = try!(obj.extract::<Cow<str>>());
|
||||
Ok(f(&s))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,16 @@ use std::slice;
|
|||
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use err::{PyErr, PyResult};
|
||||
use pointers::PyPtr;
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use pointer::PyObject;
|
||||
use objects::PyInstance;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use conversion::{FromPyObject, ToPyObject, IntoPyTuple, IntoPyObject};
|
||||
use objects::PyObject;
|
||||
use super::exc;
|
||||
|
||||
/// Represents a Python tuple object.
|
||||
pub struct PyTuple(PyPtr);
|
||||
pub struct PyTuple(PyObject);
|
||||
|
||||
pyobject_convert!(PyTuple);
|
||||
pyobject_nativetype!(PyTuple, PyTuple_Type, PyTuple_Check);
|
||||
|
@ -22,32 +24,27 @@ pyobject_nativetype!(PyTuple, PyTuple_Type, PyTuple_Check);
|
|||
impl PyTuple {
|
||||
|
||||
/// Construct a new tuple with the given elements.
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> PyTuple {
|
||||
pub fn new<T: ToPyObject>(py: Python, elements: &[T]) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let len = elements.len();
|
||||
let ptr = ffi::PyTuple_New(len as Py_ssize_t);
|
||||
for (i, e) in elements.iter().enumerate() {
|
||||
ffi::PyTuple_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
|
||||
}
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new tuple with the given raw pointer
|
||||
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyTuple {
|
||||
PyTuple(PyPtr::from_borrowed_ptr(ptr))
|
||||
}
|
||||
|
||||
/// Retrieves the empty tuple.
|
||||
pub fn empty(_py: Python) -> PyTuple {
|
||||
pub fn empty(_py: Python) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ffi::PyTuple_New(0)))
|
||||
Py::from_owned_ptr_or_panic(ffi::PyTuple_New(0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the length of the tuple.
|
||||
#[inline]
|
||||
pub fn len(&self, _py: Python) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe {
|
||||
// non-negative Py_ssize_t should always fit into Rust uint
|
||||
ffi::PyTuple_GET_SIZE(self.as_ptr()) as usize
|
||||
|
@ -57,30 +54,18 @@ impl PyTuple {
|
|||
/// Gets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_item(&self, py: Python, index: usize) -> PyObject {
|
||||
pub fn get_item(&self, index: usize) -> &PyInstance {
|
||||
// TODO: reconsider whether we should panic
|
||||
// It's quite inconsistent that this method takes `Python` when `len()` does not.
|
||||
assert!(index < self.len(py));
|
||||
assert!(index < self.len());
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
||||
self.token().cast_from_borrowed_ptr(
|
||||
ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the item at the specified index.
|
||||
/// Panics if the index is out of range.
|
||||
pub fn into_item(self, py: Python, index: usize) -> PyObject {
|
||||
assert!(index < self.len(py));
|
||||
let result = unsafe {
|
||||
PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
||||
};
|
||||
py.release(self);
|
||||
result
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice<'a>(&'a self, py: Python) -> &'a [PyObject] {
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [PyObject] {
|
||||
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
|
||||
// and because tuples are immutable.
|
||||
// (We don't even need a Python token, thanks to immutability)
|
||||
|
@ -88,41 +73,42 @@ impl PyTuple {
|
|||
let ptr = self.as_ptr() as *mut ffi::PyTupleObject;
|
||||
PyObject::borrow_from_owned_ptr_slice(
|
||||
slice::from_raw_parts(
|
||||
(*ptr).ob_item.as_ptr(), self.len(py)
|
||||
(*ptr).ob_item.as_ptr(), self.len()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self, py: Python) -> slice::Iter<PyObject> {
|
||||
self.as_slice(py).iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn drop_ref(&mut self) {
|
||||
self.0.drop_ref();
|
||||
pub fn iter(&self) -> slice::Iter<PyObject> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyTuple for PyTuple {
|
||||
fn into_tuple(self, _py: Python) -> PyTuple {
|
||||
impl<'a> IntoPyTuple for &'a PyTuple {
|
||||
fn into_tuple(self, _py: Python) -> Py<PyTuple> {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyTuple for Py<PyTuple> {
|
||||
fn into_tuple(self, _py: Python) -> Py<PyTuple> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPyTuple for &'a str {
|
||||
fn into_tuple(self, py: Python) -> PyTuple {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyTuple_New(1);
|
||||
ffi::PyTuple_SetItem(ptr, 0, self.into_object(py).into_ptr());
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wrong_tuple_length(py: Python, t: &PyTuple, expected_length: usize) -> PyErr {
|
||||
let msg = format!("Expected tuple of length {}, but got tuple of length {}.",
|
||||
expected_length, t.len(py));
|
||||
expected_length, t.len());
|
||||
PyErr::new_lazy_init(
|
||||
py.get_type::<exc::ValueError>(), Some(msg.into_object(py)))
|
||||
}
|
||||
|
@ -133,7 +119,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.to_object(py).into_ptr());)+;
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ptr)).into()
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,32 +128,32 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_object(py).into_ptr());)+;
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ptr)).into()
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <$($T: IntoPyObject),+> IntoPyTuple for ($($T,)+) {
|
||||
fn into_tuple(self, py: Python) -> PyTuple {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_object(py).into_ptr());)+;
|
||||
PyTuple(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, $($T: FromPyObject<'s>),+> FromPyObject<'s> for ($($T,)+) {
|
||||
fn extract(py: Python, obj: &'s PyObject) -> PyResult<Self>
|
||||
fn extract(obj: &'s PyInstance) -> PyResult<Self>
|
||||
{
|
||||
let t = try!(obj.cast_as::<PyTuple>(py));
|
||||
let slice = t.as_slice(py);
|
||||
if t.len(py) == $length {
|
||||
let t = try!(obj.cast_as::<PyTuple>());
|
||||
let slice = t.as_slice();
|
||||
if t.len() == $length {
|
||||
Ok((
|
||||
$( try!(slice[$n].extract::<$T>(py)), )+
|
||||
$( try!(slice[$n].extract::<$T>(obj.token())), )+
|
||||
))
|
||||
} else {
|
||||
Err(wrong_tuple_length(py, t, $length))
|
||||
Err(wrong_tuple_length(obj.token(), t, $length))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +184,7 @@ tuple_conversion!(9, (ref0, 0, A), (ref1, 1, B), (ref2, 2, C), (ref3, 3, D),
|
|||
/// let gil = pyo3::Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let os = py.import("os").unwrap();
|
||||
/// let pid = os.call(py, "get_pid", pyo3::NoArgs, None);
|
||||
/// let pid = os.call("get_pid", pyo3::NoArgs, None);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct NoArgs;
|
||||
|
@ -221,7 +207,7 @@ impl IntoPyObject for NoArgs
|
|||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl IntoPyTuple for NoArgs {
|
||||
|
||||
fn into_tuple(self, py: Python) -> PyTuple {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +215,7 @@ impl IntoPyTuple for NoArgs {
|
|||
/// Converts `()` to an empty Python tuple.
|
||||
impl IntoPyTuple for () {
|
||||
|
||||
fn into_tuple(self, py: Python) -> PyTuple {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
@ -238,11 +224,11 @@ impl IntoPyTuple for () {
|
|||
/// Returns `Ok(NoArgs)` if the input is an empty Python tuple.
|
||||
/// Otherwise, returns an error.
|
||||
pyobject_extract!(py, obj to NoArgs => {
|
||||
let t = try!(obj.cast_as::<PyTuple>(py));
|
||||
if t.len(py) == 0 {
|
||||
let t = try!(obj.cast_as::<PyTuple>());
|
||||
if t.len() == 0 {
|
||||
Ok(NoArgs)
|
||||
} else {
|
||||
Err(wrong_tuple_length(py, t, 0))
|
||||
Err(wrong_tuple_length(obj.token(), t, 0))
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -250,17 +236,31 @@ pyobject_extract!(py, obj to NoArgs => {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use PyTuple;
|
||||
use python::{Python, PyDowncastInto};
|
||||
use conversion::IntoPyObject;
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyInstance;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let pyob = PyTuple::new(py, &[1, 2, 3]);
|
||||
let ob = pyob.as_ref(py);
|
||||
assert_eq!(3, ob.len());
|
||||
let ob: &PyInstance = ob.into();
|
||||
assert_eq!((1, 2, 3), ob.extract().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let tuple = PyTuple::downcast_into(py, (1, 2, 3).to_object(py)).unwrap();
|
||||
assert_eq!(3, tuple.len(py));
|
||||
assert_eq!((1, 2, 3), tuple.into_object(py).extract(py).unwrap());
|
||||
let ob = (1, 2, 3).to_object(py);
|
||||
let tuple = PyTuple::downcast_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(3, tuple.len());
|
||||
let ob: &PyInstance = tuple.into();
|
||||
assert_eq!((1, 2, 3), ob.extract().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@ use std::ffi::CStr;
|
|||
use std::borrow::Cow;
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use pointer::PyObject;
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyErr, PyResult};
|
||||
use instance::PyObjectWithToken;
|
||||
use typeob::PyTypeObject;
|
||||
|
||||
/// Represents a reference to a Python type object.
|
||||
pub struct PyType(PyPtr);
|
||||
pub struct PyType(PyObject);
|
||||
|
||||
pyobject_convert!(PyType);
|
||||
pyobject_nativetype!(PyType, PyType_Type, PyType_Check);
|
||||
|
@ -30,26 +30,27 @@ impl PyType {
|
|||
/// This increments the reference count on the type object.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_type_ptr(_py: Python, p: *mut ffi::PyTypeObject) -> PyType {
|
||||
PyType(PyPtr::from_borrowed_ptr(p as *mut ffi::PyObject))
|
||||
pub unsafe fn from_type_ptr<'p>(py: Python<'p>, p: *mut ffi::PyTypeObject) -> &'p PyType
|
||||
{
|
||||
py.cast_from_borrowed_ptr::<PyType>(p as *mut ffi::PyObject)
|
||||
}
|
||||
|
||||
/// Gets the name of the PyType.
|
||||
pub fn name<'a>(&'a self, _py: Python) -> Cow<'a, str> {
|
||||
pub fn name<'a>(&'a self) -> Cow<'a, str> {
|
||||
unsafe {
|
||||
CStr::from_ptr((*self.as_type_ptr()).tp_name).to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether `self` is subclass of type `T` like Python `issubclass` function
|
||||
pub fn is_subclass<T>(&self, py: Python) -> PyResult<bool>
|
||||
pub fn is_subclass<T>(&self) -> PyResult<bool>
|
||||
where T: PyTypeObject
|
||||
{
|
||||
let result = unsafe {
|
||||
ffi::PyObject_IsSubclass(self.as_ptr(), T::type_object(py).as_ptr())
|
||||
ffi::PyObject_IsSubclass(self.as_ptr(), T::type_object(self.token()).as_ptr())
|
||||
};
|
||||
if result == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else if result == 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
|
@ -58,12 +59,12 @@ impl PyType {
|
|||
}
|
||||
|
||||
// Check whether `obj` is an instance of `self`
|
||||
pub fn is_instance<T: ToPyPointer>(&self, py: Python, obj: &T) -> PyResult<bool> {
|
||||
pub fn is_instance<T: ToPyPointer>(&self, obj: &T) -> PyResult<bool> {
|
||||
let result = unsafe {
|
||||
ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr())
|
||||
};
|
||||
if result == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else if result == 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
|
@ -71,11 +72,3 @@ impl PyType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PyType {
|
||||
#[inline]
|
||||
fn eq(&self, other: &PyType) -> bool {
|
||||
self.as_type_ptr() == other.as_type_ptr()
|
||||
}
|
||||
}
|
||||
impl Eq for PyType { }
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use instance::{AsPyRef, PyObjectWithToken};
|
||||
use objects::{PyInstance, PyDict};
|
||||
use conversion::{ToPyObject, IntoPyObject, IntoPyTuple, FromPyObject};
|
||||
use python::{Python, PyClone, ToPyPointer, IntoPyPointer};
|
||||
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
#[derive(Debug)]
|
||||
pub struct PyObject(*mut ffi::PyObject);
|
||||
|
||||
// `PyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PyObject {}
|
||||
unsafe impl Sync for PyObject {}
|
||||
|
||||
|
||||
impl PyObject {
|
||||
/// Creates a `PyPtr` instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the `PyPtr`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)));
|
||||
PyObject(ptr)
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_panic(py: Python, ptr: *mut ffi::PyObject) -> PyObject
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
unsafe{
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct `PyPtr` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(unsafe{
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct `PyPtr` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub fn from_owned_ptr_or_opt(py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe{
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PyPtr` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)));
|
||||
ffi::Py_INCREF(ptr);
|
||||
PyObject(ptr)
|
||||
}
|
||||
|
||||
/// Creates a `PyPtr` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_or_err(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(PyObject::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PyPtr` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_or_opt(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Transmutes a slice of owned FFI pointers to `&[PyObject]`.
|
||||
/// Undefined behavior if any pointer in the slice is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn borrow_from_owned_ptr_slice<'a>(ptr: &'a [*mut ffi::PyObject])
|
||||
-> &'a [PyObject] {
|
||||
std::mem::transmute(ptr)
|
||||
}
|
||||
|
||||
/// Gets the reference count of the ffi::PyObject pointer.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.0) }
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be None.
|
||||
/// This is equivalent to the Python expression: 'is None'
|
||||
#[inline]
|
||||
pub fn is_none(&self) -> bool {
|
||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, PyDowncastError>
|
||||
where D: ::PyDowncastFrom
|
||||
{
|
||||
<D as ::PyDowncastFrom>::downcast_from(self.as_ref(py))
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
pub fn extract<'p, D>(&'p self, py: Python) -> PyResult<D> where D: FromPyObject<'p>
|
||||
{
|
||||
FromPyObject::extract(self.as_ref(py))
|
||||
}
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
#[inline]
|
||||
pub fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
let t = args.into_tuple(py);
|
||||
let result = unsafe {
|
||||
PyObject::from_borrowed_ptr_or_err(
|
||||
py, ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
};
|
||||
py.release(t);
|
||||
result
|
||||
}
|
||||
|
||||
/// Retrieves an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name'.
|
||||
#[inline]
|
||||
pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
|
||||
where N: ToPyObject
|
||||
{
|
||||
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
|
||||
})
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
#[inline]
|
||||
pub fn call_method<A>(&self, py: Python,
|
||||
name: &str, args: A,
|
||||
kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
name.with_borrowed_ptr(py, |name| unsafe {
|
||||
let t = args.into_tuple(py);
|
||||
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
|
||||
let result = PyObject::from_borrowed_ptr_or_err(
|
||||
py, ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()));
|
||||
py.release(t);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Calls `ffi::Py_DECREF` and sets ptr to null value.
|
||||
#[inline]
|
||||
pub unsafe fn drop_ref(&mut self) {
|
||||
ffi::Py_DECREF(self.0);
|
||||
self.0 = std::ptr::null_mut();
|
||||
}
|
||||
}
|
||||
|
||||
impl AsPyRef<PyInstance> for PyObject {
|
||||
|
||||
#[inline]
|
||||
fn as_ref(&self, _py: Python) -> &PyInstance {
|
||||
unsafe {std::mem::transmute(self)}
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut(&self, _py: Python) -> &mut PyInstance {
|
||||
unsafe {std::mem::transmute(self as *const _ as *mut PyInstance)}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for PyObject
|
||||
{
|
||||
#[inline]
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyObject {
|
||||
unsafe {PyObject::from_borrowed_ptr(py, self.as_ptr())}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_borrowed_ptr<F, R>(&self, _py: Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
{
|
||||
f(self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyPointer for PyObject {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToPyPointer for &'a PyObject {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyPointer for PyObject {
|
||||
/// Gets the underlying FFI pointer, returns a owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.0;
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PyObject {
|
||||
#[inline]
|
||||
fn eq(&self, o: &PyObject) -> bool {
|
||||
self.0 == o.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PyClone for PyObject {
|
||||
fn clone_ref(&self, py: Python) -> Self {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyObject for PyObject
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, _py: Python) -> PyObject
|
||||
{
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromPyObject<'a> for PyObject
|
||||
{
|
||||
#[inline]
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(ob: &'a PyInstance) -> PyResult<Self>
|
||||
{
|
||||
unsafe {
|
||||
Ok(PyObject::from_borrowed_ptr(ob.token(), ob.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//use backtrace::Backtrace;
|
||||
|
||||
/// Dropping a `PyObject` instance decrements the reference count on the object by 1.
|
||||
impl Drop for PyObject {
|
||||
|
||||
fn drop(&mut self) {
|
||||
if !self.0.is_null() {
|
||||
//unsafe {
|
||||
//debug!("drop PyPtr: {:?} {} {:?} {:?} {:?}",
|
||||
// self.0, ffi::Py_REFCNT(self.0), &self as *const _,
|
||||
// std::ffi::CStr::from_ptr((*(*self.0).ob_type).tp_name).to_string_lossy(),
|
||||
// &self);
|
||||
//let bt = Backtrace::new();
|
||||
//let bt = Backtrace::from(Vec::from(&bt.frames()[0..15]));
|
||||
//println!("{:?}", bt);
|
||||
//}
|
||||
let _gil_guard = Python::acquire_gil();
|
||||
unsafe { ffi::Py_DECREF(self.0); }
|
||||
}
|
||||
}
|
||||
}
|
157
src/pointers.rs
157
src/pointers.rs
|
@ -1,157 +0,0 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use objects::PyObject;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
pub struct PyPtr(*mut ffi::PyObject);
|
||||
|
||||
// `PyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PyPtr {}
|
||||
unsafe impl Sync for PyPtr {}
|
||||
|
||||
|
||||
impl PyPtr {
|
||||
/// Creates a `PyPtr` instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the `PyPtr`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyPtr {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)));
|
||||
PyPtr(ptr)
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> PyPtr
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
unsafe{
|
||||
PyPtr::from_owned_ptr(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct `PyPtr` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyPtr>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(unsafe{
|
||||
PyPtr::from_owned_ptr(ptr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PyPtr` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyPtr {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)));
|
||||
ffi::Py_INCREF(ptr);
|
||||
PyPtr::from_owned_ptr(ptr)
|
||||
}
|
||||
|
||||
/// Gets the reference count of the ffi::PyObject pointer.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.0) }
|
||||
}
|
||||
|
||||
/// Get reference to &PyObject.
|
||||
#[inline]
|
||||
pub fn as_object<'p>(&self, _py: Python<'p>) -> &PyObject {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts `PyPtr` instance -> PyObject.
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_object(self, _py: Python) -> PyObject {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> PyPtr {
|
||||
unsafe { PyPtr::from_borrowed_ptr(self.0) }
|
||||
}
|
||||
|
||||
/// Casts the `PyPtr` imstance to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_into<D>(self, py: Python) -> Result<D, PyDowncastError>
|
||||
where D: ::PyDowncastInto
|
||||
{
|
||||
<D as ::PyDowncastInto>::downcast_into(py, self)
|
||||
}
|
||||
|
||||
/// Calls `ffi::Py_DECREF` and sets ptr to null value.
|
||||
#[inline]
|
||||
pub unsafe fn drop_ref(&mut self) {
|
||||
ffi::Py_DECREF(self.0);
|
||||
self.0 = std::ptr::null_mut();
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyPointer for PyPtr {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyPointer for PyPtr {
|
||||
/// Gets the underlying FFI pointer, returns a owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.0;
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PyPtr {
|
||||
#[inline]
|
||||
fn eq(&self, o: &PyPtr) -> bool {
|
||||
self.0 == o.0
|
||||
}
|
||||
}
|
||||
|
||||
//use backtrace::Backtrace;
|
||||
|
||||
/// Dropping a `PyPtr` instance decrements the reference count on the object by 1.
|
||||
impl Drop for PyPtr {
|
||||
|
||||
fn drop(&mut self) {
|
||||
if !self.0.is_null() {
|
||||
unsafe {
|
||||
debug!("drop PyPtr: {:?} {} {:?} {:?} {:?}",
|
||||
self.0, ffi::Py_REFCNT(self.0), &self as *const _,
|
||||
std::ffi::CStr::from_ptr((*(*self.0).ob_type).tp_name).to_string_lossy(),
|
||||
&self);
|
||||
//let bt = Backtrace::new();
|
||||
//let bt = Backtrace::from(Vec::from(&bt.frames()[0..15]));
|
||||
//println!("{:?}", bt);
|
||||
}
|
||||
let _gil_guard = Python::acquire_gil();
|
||||
unsafe { ffi::Py_DECREF(self.0); }
|
||||
}
|
||||
}
|
||||
}
|
161
src/python.rs
161
src/python.rs
|
@ -9,10 +9,11 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use typeob::{PyTypeInfo, PyTypeObject, PyObjectAlloc};
|
||||
use token::{Py, PyToken};
|
||||
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
|
||||
use instance::{Py, PyToken};
|
||||
use pointer::PyObject;
|
||||
use objects::{PyInstance, PyType, PyBool, PyDict, PyModule};
|
||||
use err::{PyErr, PyResult, PyDowncastError, ToPyErr};
|
||||
use pythonrun::GILGuard;
|
||||
use pythonrun::{self, GILGuard};
|
||||
|
||||
|
||||
/// Marker type that indicates that the GIL is currently held.
|
||||
|
@ -33,15 +34,20 @@ pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
|||
pub trait PyDowncastFrom : Sized {
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn downcast_from<'a, 'p>(Python<'p>, &'a PyObject) -> Result<&'a Self, PyDowncastError<'p>>;
|
||||
fn downcast_from(&PyInstance) -> Result<&Self, PyDowncastError>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
unsafe fn unchecked_downcast_from(&PyInstance) -> &Self;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
unsafe fn unchecked_mut_downcast_from(&PyInstance) -> &mut Self;
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
pub trait PyMutDowncastFrom : Sized {
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn downcast_mut_from<'a, 'p>(Python<'p>, &'a mut PyObject) ->
|
||||
Result<&'a mut Self, PyDowncastError<'p>>;
|
||||
fn downcast_mut_from(&mut PyInstance) -> Result<&mut Self, PyDowncastError>;
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
|
@ -52,8 +58,8 @@ pub trait PyDowncastInto : Sized {
|
|||
where I: ToPyPointer + IntoPyPointer;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn downcast_from_ptr<'p>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError<'p>>;
|
||||
fn downcast_into_from_ptr<'p>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError<'p>>;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn unchecked_downcast_into<'p, I>(I) -> Self where I: IntoPyPointer;
|
||||
|
@ -149,7 +155,7 @@ impl<'p> Python<'p> {
|
|||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
pub fn eval(self, code: &str, globals: Option<&PyDict>,
|
||||
locals: Option<&PyDict>) -> PyResult<PyObject> {
|
||||
locals: Option<&PyDict>) -> PyResult<&'p PyInstance> {
|
||||
self.run_code(code, ffi::Py_eval_input, globals, locals)
|
||||
}
|
||||
|
||||
|
@ -159,8 +165,7 @@ impl<'p> Python<'p> {
|
|||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
pub fn run(self, code: &str, globals: Option<&PyDict>,
|
||||
locals: Option<&PyDict>) -> PyResult<()> {
|
||||
let result = self.run_code(code, ffi::Py_file_input, globals, locals)?;
|
||||
self.release(result);
|
||||
let _ = self.run_code(code, ffi::Py_file_input, globals, locals)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -171,7 +176,7 @@ impl<'p> Python<'p> {
|
|||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
fn run_code(self, code: &str, start: c_int,
|
||||
globals: Option<&PyDict>, locals: Option<&PyDict>) -> PyResult<PyObject> {
|
||||
globals: Option<&PyDict>, locals: Option<&PyDict>) -> PyResult<&'p PyInstance> {
|
||||
let code = CString::new(code).map_err(|e| e.to_pyerr(self))?;
|
||||
|
||||
unsafe {
|
||||
|
@ -187,17 +192,17 @@ impl<'p> Python<'p> {
|
|||
let res_ptr = ffi::PyRun_StringFlags(code.as_ptr(),
|
||||
start, globals, locals, 0 as *mut _);
|
||||
|
||||
PyObject::from_owned_ptr_or_err(self, res_ptr)
|
||||
self.cast_from_ptr_or_err(res_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the Python type object for type T.
|
||||
pub fn get_type<T>(self) -> PyType where T: PyTypeObject {
|
||||
pub fn get_type<T>(self) -> &'p PyType where T: PyTypeObject {
|
||||
T::type_object(self)
|
||||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
pub fn import(self, name : &str) -> PyResult<PyModule> {
|
||||
pub fn import(self, name : &str) -> PyResult<&'p PyModule> {
|
||||
PyModule::import(self, name)
|
||||
}
|
||||
|
||||
|
@ -211,14 +216,14 @@ impl<'p> Python<'p> {
|
|||
/// Gets the Python builtin value `True`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn True(self) -> PyBool {
|
||||
pub fn True(self) -> &'p PyBool {
|
||||
PyBool::new(self, true)
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `False`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn False(self) -> PyBool {
|
||||
pub fn False(self) -> &'p PyBool {
|
||||
PyBool::new(self, false)
|
||||
}
|
||||
|
||||
|
@ -257,8 +262,8 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
/// Check whether `obj` is an instance of type `T` like Python `isinstance` function
|
||||
pub fn is_instance<T: PyTypeObject>(self, obj: &PyObject) -> PyResult<bool> {
|
||||
T::type_object(self).is_instance(self, obj)
|
||||
pub fn is_instance<T: PyTypeObject, V: ToPyPointer>(self, obj: &V) -> PyResult<bool> {
|
||||
T::type_object(self).is_instance(obj)
|
||||
}
|
||||
|
||||
/// Check whether type `T` is subclass of type `U` like Python `issubclass` function
|
||||
|
@ -266,14 +271,109 @@ impl<'p> Python<'p> {
|
|||
where T: PyTypeObject,
|
||||
U: PyTypeObject
|
||||
{
|
||||
T::type_object(self).is_subclass::<U>(self)
|
||||
T::type_object(self).is_subclass::<U>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
|
||||
pub fn checked_cast_as<D>(self, obj: PyObject) -> Result<&'p D, PyDowncastError<'p>>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
unsafe {
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::downcast_from(p)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn cast_as<D>(self, obj: PyObject) -> &'p D
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
}
|
||||
|
||||
pub unsafe fn cast_from_ptr<D>(self, ptr: *mut ffi::PyObject) -> &'p D
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_owned_ptr_or_panic(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
}
|
||||
|
||||
pub fn cast_from_ptr_or_err<D>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p D>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_owned_ptr_or_err(self, ptr)?;
|
||||
unsafe {
|
||||
let p = pythonrun::register(self, obj);
|
||||
Ok(<D as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cast_from_ptr_or_opt<D>(self, ptr: *mut ffi::PyObject) -> Option<&'p D>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let obj = PyObject::from_owned_ptr(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
Some(<D as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn cast_from_borrowed_ptr<D>(self, ptr: *mut ffi::PyObject) -> &'p D
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_borrowed_ptr(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
}
|
||||
|
||||
pub unsafe fn cast_from_borrowed_ptr_or_err<D>(self, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<&'p D>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_borrowed_ptr_or_err(self, ptr)?;
|
||||
let p = pythonrun::register(self, obj);
|
||||
Ok(<D as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
}
|
||||
|
||||
pub unsafe fn cast_from_borrowed_ptr_or_opt<D>(self, ptr: *mut ffi::PyObject)
|
||||
-> Option<&'p D>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
let obj = PyObject::from_borrowed_ptr(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
Some(<D as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn mut_cast_from_borrowed_ptr<D>(self, ptr: *mut ffi::PyObject) -> &'p mut D
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_borrowed_ptr(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::unchecked_mut_downcast_from(p)
|
||||
}
|
||||
|
||||
pub fn track_object(self, obj: PyObject) -> &'p PyInstance
|
||||
{
|
||||
unsafe { pythonrun::register(self, obj) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use {Python, PyDict};
|
||||
use objects::{PyBool, PyList, PyInt};
|
||||
use Python;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use objects::{PyInstance, PyBool, PyList, PyInt, PyDict};
|
||||
|
||||
#[test]
|
||||
fn test_eval() {
|
||||
|
@ -281,22 +381,23 @@ mod test {
|
|||
let py = gil.python();
|
||||
|
||||
// Make sure builtin names are accessible
|
||||
let v: i32 = py.eval("min(1, 2)", None, None).unwrap().extract(py).unwrap();
|
||||
let v: i32 = py.eval("min(1, 2)", None, None)
|
||||
.map_err(|e| e.print(py)).unwrap().extract().unwrap();
|
||||
assert_eq!(v, 1);
|
||||
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "foo", 13).unwrap();
|
||||
d.set_item("foo", 13).unwrap();
|
||||
|
||||
// Inject our own global namespace
|
||||
let v: i32 = py.eval("foo + 29", Some(&d), None).unwrap().extract(py).unwrap();
|
||||
let v: i32 = py.eval("foo + 29", Some(d), None).unwrap().extract().unwrap();
|
||||
assert_eq!(v, 42);
|
||||
|
||||
// Inject our own local namespace
|
||||
let v: i32 = py.eval("foo + 29", None, Some(&d)).unwrap().extract(py).unwrap();
|
||||
let v: i32 = py.eval("foo + 29", None, Some(d)).unwrap().extract().unwrap();
|
||||
assert_eq!(v, 42);
|
||||
|
||||
// Make sure builtin names are still accessible when using a local namespace
|
||||
let v: i32 = py.eval("min(foo, 2)", None, Some(&d)).unwrap().extract(py).unwrap();
|
||||
let v: i32 = py.eval("min(foo, 2)", None, Some(d)).unwrap().extract().unwrap();
|
||||
assert_eq!(v, 2);
|
||||
}
|
||||
|
||||
|
@ -304,10 +405,10 @@ mod test {
|
|||
fn test_is_instance() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(py.is_instance::<PyBool>(py.True().as_ref()).unwrap());
|
||||
assert!(py.is_instance::<PyBool, PyInstance>(py.True().into()).unwrap());
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
assert!(!py.is_instance::<PyBool>(list.as_ref()).unwrap());
|
||||
assert!(py.is_instance::<PyList>(list.as_ref()).unwrap());
|
||||
assert!(!py.is_instance::<PyBool, _>(list.as_ref()).unwrap());
|
||||
assert!(py.is_instance::<PyList, _>(list.as_ref()).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
// 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::{sync, rc, marker};
|
||||
use std::{sync, rc, marker, mem};
|
||||
use ffi;
|
||||
use python::Python;
|
||||
use python::{Python, ToPyPointer};
|
||||
use pointer::PyObject;
|
||||
use objects::PyInstance;
|
||||
|
||||
static START: sync::Once = sync::ONCE_INIT;
|
||||
|
||||
|
@ -71,6 +59,9 @@ pub fn prepare_freethreaded_python() {
|
|||
// Note that the PyThreadState returned by PyEval_SaveThread is also held in TLS by the Python runtime,
|
||||
// and will be restored by PyGILState_Ensure.
|
||||
}
|
||||
|
||||
// initialize release pool
|
||||
POOL = Box::into_raw(Box::new(Vec::with_capacity(250)));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -87,6 +78,7 @@ pub fn prepare_freethreaded_python() {
|
|||
/// ```
|
||||
#[must_use]
|
||||
pub struct GILGuard {
|
||||
pos: usize,
|
||||
gstate: ffi::PyGILState_STATE,
|
||||
// hack to opt out of Send on stable rust, which doesn't
|
||||
// have negative impls
|
||||
|
@ -96,11 +88,61 @@ pub struct GILGuard {
|
|||
/// The Drop implementation for `GILGuard` will release the GIL.
|
||||
impl Drop for GILGuard {
|
||||
fn drop(&mut self) {
|
||||
debug!("RELEASE");
|
||||
unsafe { ffi::PyGILState_Release(self.gstate) }
|
||||
unsafe {
|
||||
drain(self.pos);
|
||||
|
||||
ffi::PyGILState_Release(self.gstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut POOL: *mut Vec<PyObject> = 0 as *mut _;
|
||||
|
||||
pub struct Pool {
|
||||
pos: usize,
|
||||
no_send: marker::PhantomData<rc::Rc<()>>,
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
#[inline]
|
||||
pub unsafe fn new() -> Pool {
|
||||
let pool: &'static mut Vec<PyInstance> = mem::transmute(POOL);
|
||||
Pool{ pos: pool.len(), no_send: marker::PhantomData }
|
||||
}
|
||||
// /// Retrieves the marker type that proves that the GIL was acquired.
|
||||
// #[inline]
|
||||
// pub fn python<'p>(&'p self) -> Python<'p> {
|
||||
// unsafe { Python::assume_gil_acquired() }
|
||||
//}
|
||||
}
|
||||
|
||||
impl Drop for Pool {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
drain(self.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn register<'p>(_py: Python<'p>, obj: PyObject) -> &'p PyInstance {
|
||||
let pool: &'static mut Vec<PyObject> = mem::transmute(POOL);
|
||||
pool.push(obj);
|
||||
mem::transmute(&pool[pool.len()-1])
|
||||
}
|
||||
|
||||
pub unsafe fn drain(pos: usize) {
|
||||
let pool: &'static mut Vec<PyObject> = mem::transmute(POOL);
|
||||
|
||||
let len = pool.len();
|
||||
if pos < len {
|
||||
for ob in &mut pool[pos..len] {
|
||||
ffi::Py_DECREF(ob.as_ptr());
|
||||
}
|
||||
pool.set_len(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl GILGuard {
|
||||
/// Acquires the global interpreter lock, which allows access to the Python runtime.
|
||||
///
|
||||
|
@ -108,9 +150,13 @@ impl GILGuard {
|
|||
/// See [prepare_freethreaded_python()](fn.prepare_freethreaded_python.html) for details.
|
||||
pub fn acquire() -> GILGuard {
|
||||
::pythonrun::prepare_freethreaded_python();
|
||||
debug!("ACQUIRE");
|
||||
let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
|
||||
GILGuard { gstate: gstate, no_send: marker::PhantomData }
|
||||
|
||||
unsafe {
|
||||
let gstate = ffi::PyGILState_Ensure(); // acquire GIL
|
||||
let pool: &'static mut Vec<PyInstance> = mem::transmute(POOL);
|
||||
|
||||
GILGuard { pos: pool.len(), gstate: gstate, no_send: marker::PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the marker type that proves that the GIL was acquired.
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::mem;
|
|||
use std::ffi::{CStr, CString};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use {ffi, class};
|
||||
use {ffi, class, pythonrun};
|
||||
use err::{PyErr, PyResult};
|
||||
use python::Python;
|
||||
use objects::PyType;
|
||||
|
@ -35,6 +35,9 @@ pub trait PyTypeInfo {
|
|||
/// PyTypeObject instance for this type
|
||||
fn type_object() -> &'static mut ffi::PyTypeObject;
|
||||
|
||||
/// Check `*mut ffi::PyObject` if it is the same type
|
||||
fn is_instance(ptr: *mut ffi::PyObject) -> bool;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +63,12 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
|||
default fn type_object() -> &'static mut ffi::PyTypeObject {
|
||||
<T as PyTypeInfo>::type_object()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn is_instance(ptr: *mut ffi::PyObject) -> bool {
|
||||
<T as PyTypeInfo>::is_instance(ptr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub trait PyObjectAlloc<T> {
|
||||
|
@ -121,7 +130,7 @@ pub trait PyTypeObject {
|
|||
fn init_type(py: Python);
|
||||
|
||||
/// Retrieves the type object for this Python object type.
|
||||
fn type_object(py: Python) -> PyType;
|
||||
fn type_object<'p>(py: Python<'p>) -> &'p PyType;
|
||||
|
||||
}
|
||||
|
||||
|
@ -133,17 +142,16 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
|
|||
|
||||
if (ty.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let to = initialize_type::<T>(
|
||||
initialize_type::<T>(
|
||||
py, None, <T as PyTypeInfo>::type_name(),
|
||||
<T as PyTypeInfo>::type_description(), ty).expect(
|
||||
format!("An error occurred while initializing class {}",
|
||||
<T as PyTypeInfo>::type_name()).as_ref());
|
||||
py.release(to);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn type_object(py: Python) -> PyType {
|
||||
default fn type_object<'p>(py: Python<'p>) -> &'p PyType {
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
|
||||
unsafe { PyType::from_type_ptr(py, <T as PyTypeInfo>::type_object()) }
|
||||
|
@ -151,9 +159,11 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
|
|||
}
|
||||
|
||||
|
||||
pub fn initialize_type<T>(py: Python, module_name: Option<&str>, type_name: &str,
|
||||
type_description: &'static str, type_object: &mut ffi::PyTypeObject)
|
||||
-> PyResult<PyType>
|
||||
pub fn initialize_type<'p, T>(py: Python<'p>,
|
||||
module_name: Option<&str>,
|
||||
type_name: &str,
|
||||
type_description: &'static str,
|
||||
type_object: &mut ffi::PyTypeObject) -> PyResult<&'p PyType>
|
||||
where T: PyObjectAlloc<T> + PyTypeInfo
|
||||
{
|
||||
// type name
|
||||
|
@ -267,6 +277,7 @@ unsafe extern "C" fn tp_dealloc_callback<T>(obj: *mut ffi::PyObject)
|
|||
debug!("DEALLOC: {:?} - {:?}", obj,
|
||||
CStr::from_ptr((*(*obj).ob_type).tp_name).to_string_lossy());
|
||||
let guard = AbortOnDrop("Cannot unwind out of tp_dealloc");
|
||||
let _pool = pythonrun::Pool::new();
|
||||
let py = Python::assume_gil_acquired();
|
||||
let r = <T as PyObjectAlloc<T>>::dealloc(py, obj);
|
||||
mem::forget(guard);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
extern crate compiletest_rs as compiletest;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::env::var;
|
||||
//use std::path::PathBuf;
|
||||
//use std::env::var;
|
||||
|
||||
/*
|
||||
fn run_mode(mode: &'static str) {
|
||||
let mut config = compiletest::default_config();
|
||||
let cfg_mode = mode.parse().ok().expect("Invalid mode");
|
||||
|
@ -22,4 +23,4 @@ fn run_mode(mode: &'static str) {
|
|||
fn compile_tests() {
|
||||
run_mode("compile-fail");
|
||||
// run_mode("run-pass");
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -18,9 +18,9 @@ struct TestClass {
|
|||
#[py::proto]
|
||||
impl class::PyBufferProtocol for TestClass {
|
||||
|
||||
fn bf_getbuffer(&self, py: Python, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
||||
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
||||
if view == ptr::null_mut() {
|
||||
return Err(PyErr::new::<exc::BufferError, _>(py, "View is null"))
|
||||
return Err(PyErr::new::<exc::BufferError, _>(self.token(), "View is null"))
|
||||
}
|
||||
|
||||
unsafe {
|
||||
|
@ -28,7 +28,7 @@ impl class::PyBufferProtocol for TestClass {
|
|||
}
|
||||
|
||||
if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE {
|
||||
return Err(PyErr::new::<exc::BufferError, _>(py, "Object is not writable"))
|
||||
return Err(PyErr::new::<exc::BufferError, _>(self.token(), "Object is not writable"))
|
||||
}
|
||||
|
||||
let bytes = &self.vec;
|
||||
|
@ -74,8 +74,8 @@ fn test_buffer() {
|
|||
let t = py.init(|t| TestClass{vec: vec![b' ', b'2', b'3'], token: t}).unwrap();
|
||||
|
||||
let d = PyDict::new(py);
|
||||
let _ = d.set_item(py, "ob", t);
|
||||
py.run("assert bytes(ob) == b' 23'", None, Some(&d)).unwrap();
|
||||
d.set_item("ob", t).unwrap();
|
||||
py.run("assert bytes(ob) == b' 23'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3))]
|
||||
|
@ -87,6 +87,6 @@ fn test_buffer() {
|
|||
let t = py.init(|t| TestClass{vec: vec![b' ', b'2', b'3'], token: t}).unwrap();
|
||||
|
||||
let d = PyDict::new(py);
|
||||
let _ = d.set_item(py, "ob", t);
|
||||
py.run("assert memoryview(ob).tobytes() == ' 23'", None, Some(&d)).unwrap();
|
||||
d.set_item("ob", t).unwrap();
|
||||
py.run("assert memoryview(ob).tobytes() == ' 23'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ use pyo3::ffi;
|
|||
macro_rules! py_run {
|
||||
($py:expr, $val:ident, $code:expr) => {{
|
||||
let d = PyDict::new($py);
|
||||
d.set_item($py, stringify!($val), &$val).unwrap();
|
||||
$py.run($code, None, Some(&d)).expect($code);
|
||||
d.set_item(stringify!($val), &$val).unwrap();
|
||||
$py.run($code, None, Some(d)).expect($code);
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,8 @@ 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();
|
||||
let res = $py.run($code, None, Some(&d));
|
||||
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>()) {
|
||||
panic!(format!("Expected {} but got {:?}", stringify!($err), err))
|
||||
|
@ -45,7 +45,7 @@ fn empty_class() {
|
|||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClass>();
|
||||
// By default, don't allow creating instances from python.
|
||||
assert!(typeobj.call(py, NoArgs, None).is_err());
|
||||
assert!(typeobj.call(NoArgs, None).is_err());
|
||||
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
|
||||
}
|
||||
|
@ -59,10 +59,16 @@ struct ClassWithDocs { }
|
|||
|
||||
#[test]
|
||||
fn class_with_docstr() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<ClassWithDocs>();
|
||||
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
println!("TEST1");
|
||||
let typeobj = py.get_type::<ClassWithDocs>();
|
||||
println!("TEST2");
|
||||
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
||||
println!("TEST3");
|
||||
}
|
||||
println!("TEST4");
|
||||
}
|
||||
|
||||
#[py::class(name=CustomName)]
|
||||
|
@ -84,11 +90,11 @@ fn empty_class_in_module() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let module = PyModule::new(py, "test_module.nested").unwrap();
|
||||
module.add_class::<EmptyClassInModule>(py).unwrap();
|
||||
module.add_class::<EmptyClassInModule>().unwrap();
|
||||
|
||||
let ty = module.getattr(py, "EmptyClassInModule").unwrap();
|
||||
assert_eq!(ty.getattr(py, "__name__").unwrap().extract::<String>(py).unwrap(), "EmptyClassInModule");
|
||||
assert_eq!(ty.getattr(py, "__module__").unwrap().extract::<String>(py).unwrap(), "test_module.nested");
|
||||
let ty = module.getattr("EmptyClassInModule").unwrap();
|
||||
assert_eq!(ty.getattr("__name__").unwrap().extract::<String>().unwrap(), "EmptyClassInModule");
|
||||
assert_eq!(ty.getattr("__module__").unwrap().extract::<String>().unwrap(), "test_module.nested");
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -99,8 +105,8 @@ struct EmptyClassWithNew {
|
|||
#[py::methods]
|
||||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<Py<EmptyClassWithNew>> {
|
||||
Py::new(py, |t| EmptyClassWithNew{token: t})
|
||||
fn __new__(cls: &PyType) -> PyResult<Py<EmptyClassWithNew>> {
|
||||
Py::new(cls.token(), |t| EmptyClassWithNew{token: t})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +115,7 @@ fn empty_class_with_new() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClassWithNew>();
|
||||
assert!(typeobj.call(py, NoArgs, None).unwrap().cast_as::<EmptyClassWithNew>(py).is_ok());
|
||||
assert!(typeobj.call(NoArgs, None).unwrap().cast_as::<EmptyClassWithNew>().is_ok());
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -121,8 +127,8 @@ struct NewWithOneArg {
|
|||
#[py::methods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg: i32) -> PyResult<Py<NewWithOneArg>> {
|
||||
Py::new(py, |t| NewWithOneArg{_data: arg, token: t})
|
||||
fn __new__(cls: &PyType, arg: i32) -> PyResult<Py<NewWithOneArg>> {
|
||||
Py::new(cls.token(), |t| NewWithOneArg{_data: arg, token: t})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +137,8 @@ fn new_with_one_arg() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithOneArg>();
|
||||
let wrp = typeobj.call(py, (42,), None).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithOneArg>(py).unwrap();
|
||||
let wrp = typeobj.call((42,), None).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithOneArg>().unwrap();
|
||||
assert_eq!(obj._data, 42);
|
||||
}
|
||||
|
||||
|
@ -147,9 +153,9 @@ struct NewWithTwoArgs {
|
|||
#[py::methods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg1: i32, arg2: i32) -> PyResult<Py<NewWithTwoArgs>>
|
||||
fn __new__(cls: &PyType, arg1: i32, arg2: i32) -> PyResult<Py<NewWithTwoArgs>>
|
||||
{
|
||||
Py::new(py, |t| NewWithTwoArgs{_data1: arg1, _data2: arg2, token: t})
|
||||
Py::new(cls.token(), |t| NewWithTwoArgs{_data1: arg1, _data2: arg2, token: t})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,8 +164,8 @@ fn new_with_two_args() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithTwoArgs>();
|
||||
let wrp = typeobj.call(py, (10, 20), None).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithTwoArgs>(py).unwrap();
|
||||
let wrp = typeobj.call((10, 20), None).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithTwoArgs>().unwrap();
|
||||
assert_eq!(obj._data1, 10);
|
||||
assert_eq!(obj._data2, 20);
|
||||
}
|
||||
|
@ -226,7 +232,7 @@ struct InstanceMethod {
|
|||
#[py::methods]
|
||||
impl InstanceMethod {
|
||||
/// Test method
|
||||
fn method(&self, py: Python) -> PyResult<i32> {
|
||||
fn method(&self) -> PyResult<i32> {
|
||||
Ok(self.member)
|
||||
}
|
||||
}
|
||||
|
@ -237,11 +243,11 @@ fn instance_method() {
|
|||
let py = gil.python();
|
||||
|
||||
let obj = Py::new(py, |t| InstanceMethod{member: 42, token: t}).unwrap();
|
||||
assert!(obj.as_ref(py).method(py).unwrap() == 42);
|
||||
assert!(obj.as_ref(py).method().unwrap() == 42);
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "obj", obj).unwrap();
|
||||
py.run("assert obj.method() == 42", None, Some(&d)).unwrap();
|
||||
py.run("assert obj.method.__doc__ == 'Test method'", None, Some(&d)).unwrap();
|
||||
d.set_item("obj", obj).unwrap();
|
||||
py.run("assert obj.method() == 42", None, Some(d)).unwrap();
|
||||
py.run("assert obj.method.__doc__ == 'Test method'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -252,22 +258,22 @@ struct InstanceMethodWithArgs {
|
|||
|
||||
#[py::methods]
|
||||
impl InstanceMethodWithArgs {
|
||||
fn method(&self, py: Python, multiplier: i32) -> PyResult<i32> {
|
||||
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
||||
Ok(self.member * multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
//#[test]
|
||||
fn instance_method_with_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = Py::new(py, |t| InstanceMethodWithArgs{member: 7, token: t}).unwrap();
|
||||
assert!(obj.as_ref(py).method(py, 6).unwrap() == 42);
|
||||
assert!(obj.as_ref(py).method(6).unwrap() == 42);
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "obj", obj).unwrap();
|
||||
py.run("assert obj.method(3) == 21", None, Some(&d)).unwrap();
|
||||
py.run("assert obj.method(multiplier=6) == 42", None, Some(&d)).unwrap();
|
||||
d.set_item("obj", obj).unwrap();
|
||||
py.run("assert obj.method(3) == 21", None, Some(d)).unwrap();
|
||||
py.run("assert obj.method(multiplier=6) == 42", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,13 +283,13 @@ struct ClassMethod {token: PyToken}
|
|||
#[py::methods]
|
||||
impl ClassMethod {
|
||||
#[new]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<Py<ClassMethod>> {
|
||||
Py::new(py, |t| ClassMethod{token: t})
|
||||
fn __new__(cls: &PyType) -> PyResult<Py<ClassMethod>> {
|
||||
Py::new(cls.token(), |t| ClassMethod{token: t})
|
||||
}
|
||||
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, py: Python) -> PyResult<String> {
|
||||
Ok(format!("{}.method()!", cls.name(py)))
|
||||
fn method(cls: &PyType) -> PyResult<String> {
|
||||
Ok(format!("{}.method()!", cls.name()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,9 +299,9 @@ fn class_method() {
|
|||
let py = gil.python();
|
||||
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "C", py.get_type::<ClassMethod>()).unwrap();
|
||||
py.run("assert C.method() == 'ClassMethod.method()!'", None, Some(&d)).unwrap();
|
||||
py.run("assert C().method() == 'ClassMethod.method()!'", None, Some(&d)).unwrap();
|
||||
d.set_item("C", py.get_type::<ClassMethod>()).unwrap();
|
||||
py.run("assert C.method() == 'ClassMethod.method()!'", None, Some(d)).unwrap();
|
||||
py.run("assert C().method() == 'ClassMethod.method()!'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
|
||||
|
@ -305,8 +311,8 @@ struct ClassMethodWithArgs{token: PyToken}
|
|||
#[py::methods]
|
||||
impl ClassMethodWithArgs {
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, py: Python, input: PyString) -> PyResult<String> {
|
||||
Ok(format!("{}.method({})", cls.name(py), input))
|
||||
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
|
||||
Ok(format!("{}.method({})", cls.name(), input))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,8 +322,8 @@ fn class_method_with_args() {
|
|||
let py = gil.python();
|
||||
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "C", py.get_type::<ClassMethodWithArgs>()).unwrap();
|
||||
py.run("assert C.method('abc') == 'ClassMethodWithArgs.method(abc)'", None, Some(&d)).unwrap();
|
||||
d.set_item("C", py.get_type::<ClassMethodWithArgs>()).unwrap();
|
||||
py.run("assert C.method('abc') == 'ClassMethodWithArgs.method(abc)'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -328,8 +334,8 @@ struct StaticMethod {
|
|||
#[py::methods]
|
||||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<Py<StaticMethod>> {
|
||||
Py::new(py, |t| StaticMethod{token: t})
|
||||
fn __new__(cls: &PyType) -> PyResult<Py<StaticMethod>> {
|
||||
Py::new(cls.token(), |t| StaticMethod{token: t})
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
|
@ -345,9 +351,9 @@ fn static_method() {
|
|||
|
||||
assert_eq!(StaticMethod::method(py).unwrap(), "StaticMethod.method()!");
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "C", py.get_type::<StaticMethod>()).unwrap();
|
||||
py.run("assert C.method() == 'StaticMethod.method()!'", None, Some(&d)).unwrap();
|
||||
py.run("assert C().method() == 'StaticMethod.method()!'", None, Some(&d)).unwrap();
|
||||
d.set_item("C", py.get_type::<StaticMethod>()).unwrap();
|
||||
py.run("assert C.method() == 'StaticMethod.method()!'", None, Some(d)).unwrap();
|
||||
py.run("assert C().method() == 'StaticMethod.method()!'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -370,8 +376,8 @@ fn static_method_with_args() {
|
|||
assert_eq!(StaticMethodWithArgs::method(py, 1234).unwrap(), "0x4d2");
|
||||
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "C", py.get_type::<StaticMethodWithArgs>()).unwrap();
|
||||
py.run("assert C.method(1337) == '0x539'", None, Some(&d)).unwrap();
|
||||
d.set_item("C", py.get_type::<StaticMethodWithArgs>()).unwrap();
|
||||
py.run("assert C.method(1337) == '0x539'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -383,12 +389,12 @@ struct GCIntegration {
|
|||
|
||||
#[py::proto]
|
||||
impl PyGCProtocol for GCIntegration {
|
||||
fn __traverse__(&self, py: Python, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
visit.call(&*self.self_ref.borrow())
|
||||
}
|
||||
|
||||
fn __clear__(&mut self, py: Python) {
|
||||
*self.self_ref.borrow_mut() = py.None();
|
||||
fn __clear__(&mut self) {
|
||||
*self.self_ref.borrow_mut() = self.token().None();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +405,7 @@ fn gc_integration() {
|
|||
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
let inst = Py::new(py, |t| GCIntegration{
|
||||
self_ref: RefCell::new(py.None()),
|
||||
self_ref: RefCell::new(py.None().into()),
|
||||
dropped: TestDropCall { drop_called: drop_called.clone() },
|
||||
token: t}).unwrap();
|
||||
|
||||
|
@ -418,7 +424,7 @@ pub struct Len {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for Len {
|
||||
fn __len__(&self, py: Python) -> PyResult<usize> {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(self.l)
|
||||
}
|
||||
}
|
||||
|
@ -447,11 +453,11 @@ struct Iterator{
|
|||
|
||||
#[py::proto]
|
||||
impl PyIterProtocol for Iterator {
|
||||
fn __iter__(&mut self, py: Python) -> PyResult<Py<Iterator>> {
|
||||
fn __iter__(&mut self) -> PyResult<Py<Iterator>> {
|
||||
Ok(self.into())
|
||||
}
|
||||
|
||||
fn __next__(&mut self, py: Python) -> PyResult<Option<i32>> {
|
||||
fn __next__(&mut self) -> PyResult<Option<i32>> {
|
||||
Ok(self.iter.next())
|
||||
}
|
||||
}
|
||||
|
@ -471,24 +477,24 @@ struct StringMethods {token: PyToken}
|
|||
|
||||
#[py::proto]
|
||||
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
||||
fn __str__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __str__(&self) -> PyResult<&'static str> {
|
||||
Ok("str")
|
||||
}
|
||||
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("repr")
|
||||
}
|
||||
|
||||
fn __format__(&self, py: Python, format_spec: String) -> PyResult<String> {
|
||||
fn __format__(&self, format_spec: String) -> PyResult<String> {
|
||||
Ok(format!("format({})", format_spec))
|
||||
}
|
||||
|
||||
fn __unicode__(&self, py: Python) -> PyResult<PyString> {
|
||||
Ok(PyString::new(py, "unicode"))
|
||||
fn __unicode__(&self) -> PyResult<PyObject> {
|
||||
Ok(PyString::new(self.token(), "unicode").into())
|
||||
}
|
||||
|
||||
fn __bytes__(&self, py: Python) -> PyResult<PyBytes> {
|
||||
Ok(PyBytes::new(py, b"bytes"))
|
||||
fn __bytes__(&self) -> PyResult<PyObject> {
|
||||
Ok(PyBytes::new(self.token(), b"bytes").into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,10 +533,10 @@ struct Comparisons {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for Comparisons {
|
||||
fn __hash__(&self, py: Python) -> PyResult<usize> {
|
||||
fn __hash__(&self) -> PyResult<usize> {
|
||||
Ok(self.val as usize)
|
||||
}
|
||||
fn __bool__(&self, py: Python) -> PyResult<bool> {
|
||||
fn __bool__(&self) -> PyResult<bool> {
|
||||
Ok(self.val != 0)
|
||||
}
|
||||
}
|
||||
|
@ -561,13 +567,13 @@ struct Sequence {
|
|||
|
||||
#[py::proto]
|
||||
impl PySequenceProtocol for Sequence {
|
||||
fn __len__(&self, py: Python) -> PyResult<usize> {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(5)
|
||||
}
|
||||
|
||||
fn __getitem__(&self, py: Python, key: isize) -> PyResult<isize> {
|
||||
fn __getitem__(&self, key: isize) -> PyResult<isize> {
|
||||
if key == 5 {
|
||||
return Err(PyErr::new::<exc::IndexError, NoArgs>(py, NoArgs));
|
||||
return Err(PyErr::new::<exc::IndexError, NoArgs>(self.token(), NoArgs));
|
||||
}
|
||||
Ok(key)
|
||||
}
|
||||
|
@ -591,7 +597,7 @@ struct Callable {token: PyToken}
|
|||
impl Callable {
|
||||
|
||||
#[__call__]
|
||||
fn __call__(&self, py: Python, arg: i32) -> PyResult<i32> {
|
||||
fn __call__(&self, arg: i32) -> PyResult<i32> {
|
||||
Ok(arg * 6)
|
||||
}
|
||||
}
|
||||
|
@ -618,7 +624,7 @@ struct SetItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol<'a> for SetItem {
|
||||
fn __setitem__(&mut self, py: Python, key: i32, val: i32) -> PyResult<()> {
|
||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
self.val = val;
|
||||
Ok(())
|
||||
|
@ -645,7 +651,7 @@ struct DelItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol<'a> for DelItem {
|
||||
fn __delitem__(&mut self, py: Python, key: i32) -> PyResult<()> {
|
||||
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -670,12 +676,12 @@ struct SetDelItem {
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for SetDelItem {
|
||||
fn __setitem__(&mut self, py: Python, key: i32, val: i32) -> PyResult<()> {
|
||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.val = Some(val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __delitem__(&mut self, py: Python, key: i32) -> PyResult<()> {
|
||||
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
||||
self.val = None;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -698,7 +704,7 @@ struct Reversed {token: PyToken}
|
|||
|
||||
#[py::proto]
|
||||
impl PyMappingProtocol for Reversed{
|
||||
fn __reversed__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __reversed__(&self) -> PyResult<&'static str> {
|
||||
Ok("I am reversed")
|
||||
}
|
||||
}
|
||||
|
@ -717,7 +723,7 @@ struct Contains {token: PyToken}
|
|||
|
||||
#[py::proto]
|
||||
impl PySequenceProtocol for Contains {
|
||||
fn __contains__(&self, py: Python, item: i32) -> PyResult<bool> {
|
||||
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
||||
Ok(item >= 0)
|
||||
}
|
||||
}
|
||||
|
@ -741,19 +747,19 @@ struct UnaryArithmetic {token: PyToken}
|
|||
#[py::proto]
|
||||
impl PyNumberProtocol for UnaryArithmetic {
|
||||
|
||||
fn __neg__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __neg__(&self) -> PyResult<&'static str> {
|
||||
Ok("neg")
|
||||
}
|
||||
|
||||
fn __pos__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __pos__(&self) -> PyResult<&'static str> {
|
||||
Ok("pos")
|
||||
}
|
||||
|
||||
fn __abs__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __abs__(&self) -> PyResult<&'static str> {
|
||||
Ok("abs")
|
||||
}
|
||||
|
||||
fn __invert__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __invert__(&self) -> PyResult<&'static str> {
|
||||
Ok("invert")
|
||||
}
|
||||
}
|
||||
|
@ -778,42 +784,42 @@ struct BinaryArithmetic {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for BinaryArithmetic {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyNumberProtocol for BinaryArithmetic {
|
||||
fn __add__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __add__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __sub__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __sub__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} - {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __mul__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __mul__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} * {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __lshift__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __lshift__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} << {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __rshift__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __rshift__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} >> {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __and__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __and__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} & {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __xor__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __xor__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} ^ {:?}", self, rhs))
|
||||
}
|
||||
|
||||
fn __or__(&self, py: Python, rhs: &PyObject) -> PyResult<String> {
|
||||
fn __or__(&self, rhs: &PyInstance) -> PyResult<String> {
|
||||
Ok(format!("{:?} | {:?}", self, rhs))
|
||||
}
|
||||
}
|
||||
|
@ -852,18 +858,18 @@ struct RichComparisons {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for RichComparisons {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC")
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, py: Python, other: &PyObject, op: CompareOp) -> PyResult<String> {
|
||||
fn __richcmp__(&self, other: &PyInstance, op: CompareOp) -> PyResult<String> {
|
||||
match op {
|
||||
CompareOp::Lt => Ok(format!("{} < {:?}", self.__repr__(py).unwrap(), other)),
|
||||
CompareOp::Le => Ok(format!("{} <= {:?}", self.__repr__(py).unwrap(), other)),
|
||||
CompareOp::Eq => Ok(format!("{} == {:?}", self.__repr__(py).unwrap(), other)),
|
||||
CompareOp::Ne => Ok(format!("{} != {:?}", self.__repr__(py).unwrap(), other)),
|
||||
CompareOp::Gt => Ok(format!("{} > {:?}", self.__repr__(py).unwrap(), other)),
|
||||
CompareOp::Ge => Ok(format!("{} >= {:?}", self.__repr__(py).unwrap(), other))
|
||||
CompareOp::Lt => Ok(format!("{} < {:?}", self.__repr__().unwrap(), other)),
|
||||
CompareOp::Le => Ok(format!("{} <= {:?}", self.__repr__().unwrap(), other)),
|
||||
CompareOp::Eq => Ok(format!("{} == {:?}", self.__repr__().unwrap(), other)),
|
||||
CompareOp::Ne => Ok(format!("{} != {:?}", self.__repr__().unwrap(), other)),
|
||||
CompareOp::Gt => Ok(format!("{} > {:?}", self.__repr__().unwrap(), other)),
|
||||
CompareOp::Ge => Ok(format!("{} >= {:?}", self.__repr__().unwrap(), other))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -875,16 +881,15 @@ struct RichComparisons2 {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for RichComparisons2 {
|
||||
fn __repr__(&self, py: Python) -> PyResult<&'static str> {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC2")
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, py: Python,
|
||||
other: &'p PyObject, op: CompareOp) -> PyResult<PyObject> {
|
||||
fn __richcmp__(&self, other: &'p PyInstance, op: CompareOp) -> PyResult<PyObject> {
|
||||
match op {
|
||||
CompareOp::Eq => Ok(true.to_object(py)),
|
||||
CompareOp::Ne => Ok(false.to_object(py)),
|
||||
_ => Ok(py.NotImplemented())
|
||||
CompareOp::Eq => Ok(true.to_object(self.token())),
|
||||
CompareOp::Ne => Ok(false.to_object(self.token())),
|
||||
_ => Ok(self.token().NotImplemented())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -950,49 +955,49 @@ struct InPlaceOperations {
|
|||
|
||||
#[py::proto]
|
||||
impl PyObjectProtocol for InPlaceOperations {
|
||||
fn __repr__(&self, py: Python) -> PyResult<String> {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("IPO({:?})", self.value))
|
||||
}
|
||||
}
|
||||
|
||||
#[py::proto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __iadd__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value + other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __isub__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __isub__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value - other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __imul__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __imul__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value * other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ilshift__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __ilshift__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value << other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __irshift__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __irshift__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value >> other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __iand__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __iand__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value & other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ixor__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __ixor__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value ^ other;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __ior__(&mut self, py: Python, other: u32) -> PyResult<()> {
|
||||
fn __ior__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value = self.value | other;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1037,16 +1042,16 @@ struct ContextManager {
|
|||
#[py::proto]
|
||||
impl<'p> PyContextProtocol<'p> for ContextManager {
|
||||
|
||||
fn __enter__(&mut self, py: Python) -> PyResult<i32> {
|
||||
fn __enter__(&mut self) -> PyResult<i32> {
|
||||
Ok(42)
|
||||
}
|
||||
|
||||
fn __exit__(&mut self, py: Python,
|
||||
ty: Option<PyType>,
|
||||
value: Option<PyObject>,
|
||||
traceback: Option<PyObject>) -> PyResult<bool> {
|
||||
fn __exit__(&mut self,
|
||||
ty: Option<&'p PyType>,
|
||||
value: Option<&'p PyInstance>,
|
||||
traceback: Option<&'p PyInstance>) -> PyResult<bool> {
|
||||
self.exit_called = true;
|
||||
if ty == Some(py.get_type::<exc::ValueError>()) {
|
||||
if ty == Some(self.token().get_type::<exc::ValueError>()) {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
@ -1083,16 +1088,16 @@ struct ClassWithProperties {
|
|||
#[py::methods]
|
||||
impl ClassWithProperties {
|
||||
|
||||
fn get_num(&self, py: Python) -> PyResult<i32> {
|
||||
fn get_num(&self) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
}
|
||||
|
||||
#[getter(DATA)]
|
||||
fn get_data(&self, py: Python) -> PyResult<i32> {
|
||||
fn get_data(&self) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
}
|
||||
#[setter(DATA)]
|
||||
fn set_data(&mut self, py: Python, value: i32) -> PyResult<()> {
|
||||
fn set_data(&mut self, value: i32) -> PyResult<()> {
|
||||
self.num = value;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ fn test_basics() {
|
|||
let py = gil.python();
|
||||
|
||||
let v = PySlice::new(py, 1, 10, 2);
|
||||
let indices = v.indices(py, 100).unwrap();
|
||||
let indices = v.as_ref(py).indices(100).unwrap();
|
||||
assert_eq!(1, indices.start);
|
||||
assert_eq!(10, indices.stop);
|
||||
assert_eq!(2, indices.step);
|
||||
|
@ -28,19 +28,19 @@ struct Test {
|
|||
#[py::proto]
|
||||
impl<'p> PyMappingProtocol<'p> for Test
|
||||
{
|
||||
fn __getitem__(&self, py: Python, idx: PyObject) -> PyResult<PyObject> {
|
||||
if let Ok(slice) = idx.cast_as::<PySlice>(py) {
|
||||
let indices = slice.indices(py, 1000)?;
|
||||
fn __getitem__(&self, idx: &PyInstance) -> PyResult<PyObject> {
|
||||
if let Ok(slice) = idx.cast_as::<PySlice>() {
|
||||
let indices = slice.indices(1000)?;
|
||||
if indices.start == 100 && indices.stop == 200 && indices.step == 1 {
|
||||
return Ok("slice".into_object(py))
|
||||
return Ok("slice".into_object(self.token()))
|
||||
}
|
||||
}
|
||||
else if let Ok(idx) = idx.extract::<isize>(py) {
|
||||
else if let Ok(idx) = idx.extract::<isize>() {
|
||||
if idx == 1 {
|
||||
return Ok("int".into_object(py))
|
||||
return Ok("int".into_object(self.token()))
|
||||
}
|
||||
}
|
||||
Err(PyErr::new::<exc::ValueError, _>(py, "error"))
|
||||
Err(PyErr::new::<exc::ValueError, _>(self.token(), "error"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ fn test_cls_impl() {
|
|||
|
||||
let ob = py.init(|t| Test{token: t}).unwrap();
|
||||
let d = PyDict::new(py);
|
||||
d.set_item(py, "ob", ob).unwrap();
|
||||
d.set_item("ob", ob).unwrap();
|
||||
|
||||
py.run("assert ob[1] == 'int'", None, Some(&d)).unwrap();
|
||||
py.run("assert ob[100:200:1] == 'slice'", None, Some(&d)).unwrap();
|
||||
py.run("assert ob[1] == 'int'", None, Some(d)).unwrap();
|
||||
py.run("assert ob[100:200:1] == 'slice'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue