fix ptr borrowing PyTuple::get_item

This commit is contained in:
Nikolay Kim 2017-05-29 18:36:44 -07:00
parent 4232caf3a3
commit 61b8bd0695
12 changed files with 68 additions and 35 deletions

View File

@ -449,7 +449,7 @@ pub fn with_extracted_or_default<'p, P: ?Sized, R, F>(
#[cfg(test)]
mod test {
mod test {
use python::{Python};
use objects::PyTuple;
use conversion::{ToPyTuple};

View File

@ -47,7 +47,7 @@ macro_rules! py_exception {
($module: ident, $name: ident, $base: ty) => {
pub struct $name;
pyobject_nativetype!($name);
// pyobject_nativetype!($name);
impl $name {
pub fn new<'p, T: $crate::ToPyObject>(py: $crate::Python<'p>, args: T) -> $crate::PyErr {
@ -59,13 +59,14 @@ macro_rules! py_exception {
#[inline]
fn type_object<'p>(py: $crate::Python<'p>) -> $crate::PyType<'p> {
unsafe {
#[allow(non_upper_case_globals)]
static mut type_object: *mut $crate::ffi::PyTypeObject = 0 as *mut $crate::ffi::PyTypeObject;
if type_object.is_null() {
type_object = $crate::PyErr::new_type(
py,
concat!(stringify!($module), ".", stringify!($name)),
Some(py.get_type::<$base>()), None);
Some(py.get_type::<$base>()), None).as_type_ptr();
}
$crate::PyType::from_type_ptr(py, type_object)
@ -133,7 +134,7 @@ 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<'p>(py: Python<'p>, name: &str,
base: Option<PyObject<'p>>, dict: Option<PyObject<'p>>) -> PyType<'p> {
base: Option<PyType<'p>>, dict: Option<PyObject<'p>>) -> PyType<'p> {
let base: *mut ffi::PyObject = match base {
None => std::ptr::null_mut(),
Some(obj) => obj.into_ptr()
@ -334,17 +335,6 @@ impl PyErr {
}
}
/*impl PyClone for PyErr {
fn clone_ref(&self, py: Python) -> PyErr {
PyErr {
ptype: self.ptype.clone_ref(py),
pvalue: self.pvalue.clone_ref(py),
ptraceback: self.ptraceback.clone_ref(py)
}
}
}*/
/// Converts `PyDowncastError` to Python `TypeError`.
impl <'p> std::convert::From<PyDowncastError<'p>> for PyErr {
fn from(err: PyDowncastError<'p>) -> PyErr {

View File

@ -90,7 +90,7 @@ macro_rules! py_method_def {
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// let dict = PyDict::new(py);
/// dict.set_item(py, "multiply", py_fn!(py, multiply(lhs: i32, rhs: i32))).unwrap();
/// dict.set_item("multiply", py_fn!(py, multiply(lhs: i32, rhs: i32))).unwrap();
/// py.run("print(multiply(6, 7))", None, Some(&dict)).unwrap();
/// }
/// ```

View File

@ -42,11 +42,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("os", py.import("os")?)?;
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract()?;
//!
//! println!("Hello {}, I'm Python {}", user, version);
//! Ok(())
@ -145,14 +145,14 @@ pub use std::os::raw::*;
/// use pyo3::{Python, PyResult, PyObject};
///
/// py_module_init!(hello, PyInit_hello, |py, m| {
/// m.add(py, "__doc__", "Module documentation string")?;
/// m.add(py, "run", py_fn!(py, run()))?;
/// m.add("__doc__", "Module documentation string")?;
/// m.add("run", py_fn!(py, run()))?;
/// Ok(())
/// });
///
/// fn run(py: Python) -> PyResult<PyObject> {
/// println!("Rust says: Hello Python!");
/// Ok(py.None())
/// Ok(py.None().into_object(py))
/// }
/// # fn main() {}
/// ```

View File

@ -119,6 +119,8 @@ pub trait ObjectProtocol<'p> {
// /// This is typically a new iterator but if the argument
// /// is an iterator, this returns itself.
// fn iter<'a>(&'a self) -> PyResult<Py<'p, ::objects::PyIterator<'a>>>;
fn get_refcnt(&self) -> isize;
}
@ -371,6 +373,10 @@ impl<'p, T> ObjectProtocol<'p> for T where T: PythonObjectWithGilToken<'p> + ToP
//pub fn iter<'a>(&'a self) -> PyResult<Py<'p, ::objects::PyIterator<'a>>> {
// Py::from_owned_ptr_or_err(self.py(), ffi::PyObject_GetIter(self.as_ptr()))
//}
fn get_refcnt(&self) -> isize {
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
}
}

View File

@ -32,6 +32,7 @@ impl<'p> PyByteArray<'p> {
/// Creates a new Python bytearray object
/// from other PyObject, that implements the buffer protocol.
pub fn from(src: &'p PyObject<'p>) -> PyResult<PyByteArray<'p>> {
println!("FROM: {:?} {}", src.as_ptr(), src.get_refcnt());
let res = unsafe {ffi::PyByteArray_FromObject(src.as_ptr())};
if res != ptr::null_mut() {
Ok(unsafe{ PyByteArray(
@ -77,7 +78,7 @@ impl<'p> PyByteArray<'p> {
mod test {
use ::ToPyObject;
use exc;
use python::Python;
use python::{Python, ToPythonPointer};
use typeob::PyTypeObject;
use objects::PyByteArray;
@ -100,6 +101,7 @@ mod test {
assert_eq!(20, bytearray.len());
let none = py.None();
println!("NONE: {:?} {}", none.as_ptr(), none.get_refcnt());
if let Err(mut err) = PyByteArray::from(none.as_object(py)) {
assert!(exc::TypeError::type_object(py).is_instance(&err.instance(py)))
} else {

View File

@ -8,7 +8,7 @@ use std::os::raw::c_char;
use std::ffi::{CStr, CString};
use ::pptr;
use conversion::ToPyTuple;
use conversion::{ToPyObject, ToPyTuple};
use pyptr::PyPtr;
use python::{ToPythonPointer, Python};
use token::PythonObjectWithGilToken;
@ -89,6 +89,19 @@ impl<'p> PyModule<'p> {
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, name: &str) -> PyResult<PyObject> {
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, name: &str, value: V) -> PyResult<()> where V: ToPyObject {
self.setattr(name, value)
}
/// Adds a new extension type to the module.
///
/// This is a convenience function that initializes the `class`,

View File

@ -88,6 +88,11 @@ impl<'p> PyObject<'p> {
{
::conversion::FromPyObject::extract(&self)
}
pub fn get_refcnt(&self) -> isize {
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }
}
}
impl<'p> PartialEq for PyObject<'p> {

View File

@ -62,7 +62,7 @@ impl<'p> PyTuple<'p> {
// It's quite inconsistent that this method takes `Python` when `len()` does not.
assert!(index < self.len());
unsafe {
PyObject::from_owned_ptr(
PyObject::from_borrowed_ptr(
self.gil(), ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
}
}
@ -89,7 +89,7 @@ impl<'p> PyTuple<'p> {
impl<'a> ToPyTuple for PyTuple<'a> {
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
unsafe { PyTuple(pptr::from_owned_ptr_or_panic(py, self.0.as_ptr())) }
unsafe { PyTuple(pptr::from_borrowed_ptr(py, self.0.as_ptr())) }
}
}

View File

@ -1,8 +1,10 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use ffi;
use err::{PyErr, PyResult};
use python::{Python, ToPythonPointer};
use python::{Python, PyDowncastInto, ToPythonPointer};
use typeob::{PyTypeInfo, PyObjectAlloc};
#[allow(non_camel_case_types)]
@ -176,3 +178,21 @@ impl<'p> Drop for pptr<'p> {
unsafe { ffi::Py_DECREF(self.1); }
}
}
impl<'p> std::fmt::Debug for pptr<'p> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let repr = unsafe { ::PyString::downcast_from_owned_ptr(
self.0, ffi::PyObject_Repr(self.1)) };
let repr = repr.map_err(|_| std::fmt::Error)?;
f.write_str(&repr.to_string_lossy())
}
}
impl<'p> std::fmt::Display for pptr<'p> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let ob = unsafe { ::PyString::downcast_from_owned_ptr(
self.0, ffi::PyObject_Str(self.1)) };
let ob = ob.map_err(|_| std::fmt::Error)?;
f.write_str(&ob.to_string_lossy())
}
}

View File

@ -113,6 +113,7 @@ impl<T> PyPtr<T> {
/// Converts PyPtr<T> -> &PyObject<'p>.
#[inline]
pub fn as_object<'p>(&self, _py: Python<'p>) -> &PyObject<'p> {
unsafe {ffi::Py_INCREF(self.inner)};
unsafe { std::mem::transmute(self) }
}

View File

@ -443,6 +443,7 @@ fn string_methods() {
#[py::class]
struct Comparisons {
val: i32,
#[token]
token: PythonToken<Comparisons>,
}
@ -451,7 +452,6 @@ impl PyObjectProtocol for Comparisons {
fn __hash__(&self, py: Python) -> PyResult<usize> {
Ok(self.val as usize)
}
fn __bool__(&self, py: Python) -> PyResult<bool> {
Ok(self.val != 0)
}
@ -994,16 +994,12 @@ fn context_manager() {
assert!(c.exit_called);
c.exit_called = false;
//TODO: re-enable
//py_expect_exception!(
// py, c, "with c as x:\n raise NotImplementedError",
// NotImplementedError);
//assert!(c.exit_called);
py_expect_exception!(
py, c, "with c as x:\n raise NotImplementedError",
NotImplementedError);
assert!(c.exit_called);
}
#[py::class]
struct ClassWithProperties {
num: i32,