other types
This commit is contained in:
parent
bc0f9b014f
commit
08ddb3f14f
|
@ -4,7 +4,7 @@ use std::fmt;
|
|||
|
||||
use pointers::PyPtr;
|
||||
use python::Python;
|
||||
use token::InstancePtr;
|
||||
use token::AsPyRef;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
impl fmt::Debug for PyPtr {
|
||||
|
|
|
@ -157,11 +157,12 @@ mod pointers;
|
|||
pub use pointers::PyPtr;
|
||||
|
||||
pub mod token;
|
||||
pub use token::{PyToken, PyObjectWithToken, Py, AsPyRef};
|
||||
pub use token::{PyToken, PyObjectWithToken, AsPyRef, Py};
|
||||
|
||||
pub use err::{PyErr, PyResult, PyDowncastError, ToPyErr};
|
||||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use objectprotocol2::ObjectProtocol2;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer, PyClone,
|
||||
PyMutDowncastFrom, PyDowncastFrom, PyDowncastInto};
|
||||
pub use pythonrun::{GILGuard, prepare_freethreaded_python};
|
||||
|
@ -195,6 +196,7 @@ mod err;
|
|||
mod conversion;
|
||||
mod objects;
|
||||
mod objectprotocol;
|
||||
mod objectprotocol2;
|
||||
mod pythonrun;
|
||||
pub mod callback;
|
||||
pub mod typeob;
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
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 token::{Py, PyObjectWithToken};
|
||||
|
||||
|
||||
pub trait ObjectProtocol2 {
|
||||
|
||||
/// Determines whether this object has the given attribute.
|
||||
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
||||
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, attr_name: N) -> PyResult<PyObject> where N: ToPyObject;
|
||||
|
||||
/// Sets an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name = value'.
|
||||
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, attr_name: N) -> PyResult<()> where N: ToPyObject;
|
||||
|
||||
/// 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, other: O) -> PyResult<Ordering> where O: ToPyObject;
|
||||
|
||||
/// 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, 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) -> PyResult<Py<PyString>>;
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'str(self)'.
|
||||
fn str(&self) -> PyResult<Py<PyString>>;
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
fn is_callable(&self) -> bool;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
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, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple;
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: 'hash(self)'
|
||||
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) -> 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) -> bool;
|
||||
|
||||
/// Returns the length of the sequence or mapping.
|
||||
/// This is equivalent to the Python expression: 'len(self)'
|
||||
fn len(&self) -> PyResult<usize>;
|
||||
|
||||
/// This is equivalent to the Python expression: 'self[key]'
|
||||
fn get_item<K>(&self, key: K) -> PyResult<PyObject> where K: ToPyObject;
|
||||
|
||||
/// Sets an item value.
|
||||
/// This is equivalent to the Python expression 'self[key] = value'.
|
||||
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, 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>(&'p self) -> PyResult<PyIterator<'p>>;
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self) -> PyType;
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl<'a, T> ObjectProtocol2 for &'a 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, 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, attr_name: N) -> PyResult<PyObject> where N: ToPyObject
|
||||
{
|
||||
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
self.token(), 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, attr_name: N, value: V) -> PyResult<()>
|
||||
where N: ToPyObject, V: ToPyObject
|
||||
{
|
||||
attr_name.with_borrowed_ptr(
|
||||
self.token(), move |attr_name|
|
||||
value.with_borrowed_ptr(self.token(), |value| unsafe {
|
||||
err::error_on_minusone(
|
||||
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, 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, other: O) -> PyResult<Ordering> where O: ToPyObject {
|
||||
unsafe fn do_compare(py: Python,
|
||||
a: *mut ffi::PyObject,
|
||||
b: *mut ffi::PyObject) -> PyResult<Ordering> {
|
||||
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_EQ);
|
||||
if result == 1 {
|
||||
return Ok(Ordering::Equal);
|
||||
} else if result < 0 {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_LT);
|
||||
if result == 1 {
|
||||
return Ok(Ordering::Less);
|
||||
} else if result < 0 {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_GT);
|
||||
if result == 1 {
|
||||
return Ok(Ordering::Greater);
|
||||
} else if result < 0 {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
Err(PyErr::new::<::exc::TypeError, _>(py, "ObjectProtocol::compare(): All comparisons returned false"))
|
||||
}
|
||||
|
||||
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, other: O, compare_op: ::CompareOp)
|
||||
-> PyResult<PyObject> where O: ToPyObject {
|
||||
unsafe {
|
||||
other.with_borrowed_ptr(self.token(), |other| {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
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) -> PyResult<Py<PyString>> {
|
||||
Ok(Py::downcast_from_ptr(
|
||||
self.token(), unsafe{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) -> PyResult<Py<PyString>> {
|
||||
Ok(Py::downcast_from_ptr(
|
||||
self.token(), unsafe{ffi::PyObject_Str(self.as_ptr())})?)
|
||||
}
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
#[inline]
|
||||
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, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
let t = args.into_tuple(self.token());
|
||||
let result = unsafe {
|
||||
PyObject::from_borrowed_ptr_or_err(
|
||||
self.token(), ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
};
|
||||
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, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
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(
|
||||
self.token(), 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) -> PyResult<ffi::Py_hash_t> {
|
||||
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
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) -> PyResult<bool> {
|
||||
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
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) -> 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) -> PyResult<usize> {
|
||||
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
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, key: K) -> PyResult<PyObject> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
self.token(), 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, key: K, value: V) -> PyResult<()>
|
||||
where K: ToPyObject, V: ToPyObject
|
||||
{
|
||||
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, 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>(&'p self) -> PyResult<PyIterator<'p>> {
|
||||
unsafe {
|
||||
let ptr = PyObject::from_owned_ptr_or_err(
|
||||
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) -> PyType {
|
||||
unsafe {
|
||||
PyType::from_type_ptr(self.token(), (*self.as_ptr()).ob_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyString;
|
||||
|
||||
#[test]
|
||||
fn test_debug_string() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
let s = PyString::downcast_from(py, &v).unwrap();
|
||||
assert_eq!(format!("{:?}", s), "'Hello\\n'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_string() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
let s = PyString::downcast_from(py, &v).unwrap();
|
||||
assert_eq!(format!("{}", s), "Hello\n");
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
use ffi;
|
||||
use token::Py;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPyPointer, Python};
|
||||
use objects::PyObject;
|
||||
|
@ -7,22 +8,21 @@ use conversion::{ToPyObject, IntoPyObject};
|
|||
/// Represents a Python `bool`.
|
||||
pub struct PyBool(PyPtr);
|
||||
|
||||
pyobject_convert!(PyBool);
|
||||
pyobject_nativetype!(PyBool, PyBool_Type, PyBool_Check);
|
||||
pyobject_nativetype2!(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(_py: Python, val: bool) -> Py<PyBool> {
|
||||
unsafe {
|
||||
Py::from_borrowed_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() }
|
||||
}
|
||||
}
|
||||
|
@ -54,12 +54,13 @@ 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>(py)).is_true())
|
||||
});
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use token::AsPyRef;
|
||||
use python::{Python};
|
||||
use objects::PyObject;
|
||||
use conversion::ToPyObject;
|
||||
|
@ -68,7 +69,7 @@ mod test {
|
|||
fn test_true() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(py.True().is_true(py));
|
||||
assert!(py.True().as_ref(py).is_true());
|
||||
let t: PyObject = py.True().into();
|
||||
assert_eq!(true, t.extract(py).unwrap());
|
||||
assert!(true.to_object(py) == py.True().into());
|
||||
|
@ -78,7 +79,7 @@ mod test {
|
|||
fn test_false() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(!py.False().is_true(py));
|
||||
assert!(!py.False().as_ref(py).is_true());
|
||||
let t: PyObject = py.False().into();
|
||||
assert_eq!(false, t.extract(py).unwrap());
|
||||
assert!(false.to_object(py) == py.False().into());
|
||||
|
|
|
@ -4,38 +4,39 @@ use std;
|
|||
use std::ptr;
|
||||
use std::os::raw::c_char;
|
||||
use ffi;
|
||||
use token::{Py, PyObjectWithToken};
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyResult, PyErr};
|
||||
use pointers::PyPtr;
|
||||
|
||||
|
||||
/// Represents a Python bytearray.
|
||||
pub struct PyByteArray(PyPtr);
|
||||
|
||||
pyobject_convert!(PyByteArray);
|
||||
pyobject_nativetype!(PyByteArray, PyByteArray_Type, PyByteArray_Check);
|
||||
pyobject_nativetype2!(PyByteArray, PyByteArray_Type, PyByteArray_Check);
|
||||
|
||||
impl PyByteArray {
|
||||
/// Creates a new Python bytearray object.
|
||||
/// 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(_py: Python, src: &[u8]) -> Py<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::from_owned_ptr_or_panic(
|
||||
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<I>(py: Python, src: I) -> PyResult<Py<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)))
|
||||
Ok(Py::from_owned_ptr_or_panic(res))
|
||||
} else {
|
||||
Err(PyErr::fetch(py))
|
||||
}
|
||||
|
@ -43,7 +44,7 @@ impl PyByteArray {
|
|||
|
||||
/// 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 +52,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 +61,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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +77,7 @@ impl PyByteArray {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use exc;
|
||||
use AsPyRef;
|
||||
use python::Python;
|
||||
use objects::{PyObject, PyByteArray};
|
||||
|
||||
|
@ -85,17 +87,22 @@ mod test {
|
|||
let py = gil.python();
|
||||
|
||||
let src = b"Hello Python";
|
||||
let bytearray = PyByteArray::new(py, src);
|
||||
assert_eq!(src.len(), bytearray.len(py));
|
||||
assert_eq!(src, bytearray.data(py));
|
||||
let ba = PyByteArray::new(py, src);
|
||||
{
|
||||
let bytearray = ba.as_ref(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 ba: PyObject = ba.into();
|
||||
let ba = PyByteArray::from(py, &ba).unwrap();
|
||||
|
||||
bytearray.resize(py, 20).unwrap();
|
||||
assert_eq!(20, bytearray.len(py));
|
||||
let bytearray = ba.as_ref(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) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use std::{mem, collections, hash, cmp};
|
||||
|
||||
use ffi;
|
||||
use token::Py;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer};
|
||||
use conversion::{ToPyObject};
|
||||
|
@ -99,10 +100,10 @@ impl PyDict {
|
|||
|
||||
/// 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, py: Python) -> Py<PyList> {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr(
|
||||
py, ffi::PyDict_Items(self.as_ptr())).unchecked_cast_into::<PyList>()
|
||||
py, ffi::PyDict_Items(self.as_ptr())).unchecked_cast_into::<Py<PyList>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +266,7 @@ mod test {
|
|||
// 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) {
|
||||
for el in dict.items_list().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();
|
||||
|
|
|
@ -9,6 +9,7 @@ use objects::PyObject;
|
|||
use pointers::PyPtr;
|
||||
use python::{ToPyPointer, Python};
|
||||
use err::PyErr;
|
||||
use token::Py;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `float` object.
|
||||
|
@ -19,20 +20,19 @@ use conversion::{ToPyObject, IntoPyObject};
|
|||
/// with `f32`/`f64`.
|
||||
pub struct PyFloat(PyPtr);
|
||||
|
||||
pyobject_convert!(PyFloat);
|
||||
pyobject_nativetype!(PyFloat, PyFloat_Type, PyFloat_Check);
|
||||
pyobject_nativetype2!(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()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use err::{self, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use token::{Py, PyObjectWithToken};
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use objects::PyObject;
|
||||
|
@ -12,31 +13,30 @@ use conversion::{ToPyObject, IntoPyObject};
|
|||
/// Represents a Python `list`.
|
||||
pub struct PyList(PyPtr);
|
||||
|
||||
pyobject_convert!(PyList);
|
||||
pyobject_nativetype!(PyList, PyList_Type, PyList_Check);
|
||||
pyobject_nativetype2!(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<T: ToPyObject>(py: Python, elements: &[T]) -> Py<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());
|
||||
}
|
||||
PyList(PyPtr::from_owned_ptr_or_panic(ptr))
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new empty list.
|
||||
pub fn empty(_py: Python) -> PyList {
|
||||
pub fn empty(_py: Python) -> Py<PyList> {
|
||||
unsafe {
|
||||
PyList(PyPtr::from_owned_ptr_or_panic(ffi::PyList_New(0)))
|
||||
Py::from_owned_ptr_or_panic(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 +46,56 @@ 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) -> PyObject {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
self.token(), ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
impl<'a> Iterator for PyListIterator<'a> {
|
||||
type Item = PyObject;
|
||||
|
||||
#[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);
|
||||
if self.index < self.list.len() as isize {
|
||||
let item = self.list.get_item(self.index);
|
||||
self.index += 1;
|
||||
Some(item)
|
||||
} else {
|
||||
|
@ -146,7 +145,7 @@ impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python, PyDowncastInto};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyList;
|
||||
|
||||
|
@ -155,8 +154,9 @@ mod test {
|
|||
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(py, &ob).unwrap();
|
||||
assert_eq!(4, list.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -164,11 +164,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();
|
||||
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(py, &ob).unwrap();
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, list.get_item(2).extract::<i32>(py).unwrap());
|
||||
assert_eq!(7, list.get_item(3).extract::<i32>(py).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -176,11 +177,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(py, &ob).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>(py).unwrap());
|
||||
list.set_item(0, val).unwrap();
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>(py).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -188,14 +190,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(py, &ob).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>(py).unwrap());
|
||||
list.insert_item(0, val).unwrap();
|
||||
assert_eq!(5, list.len());
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, list.get_item(1).extract::<i32>(py).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -203,9 +206,10 @@ 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(py, &ob).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in list.iter(py) {
|
||||
for el in list.iter() {
|
||||
assert_eq!(v[idx], el.extract::<i32>(py).unwrap());
|
||||
idx += 1;
|
||||
}
|
||||
|
@ -217,7 +221,8 @@ 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(py, &ob).unwrap();
|
||||
let v2 = list.as_ref().extract::<Vec<i32>>(py).unwrap();
|
||||
assert_eq!(v, v2);
|
||||
}
|
||||
|
|
|
@ -399,6 +399,7 @@ macro_rules! pyobject_nativetype2(
|
|||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
use $crate::PyObjectWithToken;
|
||||
use $crate::python::PyDowncastFrom;
|
||||
|
||||
let py = self.token();
|
||||
|
@ -423,6 +424,7 @@ macro_rules! pyobject_nativetype2(
|
|||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
use $crate::PyObjectWithToken;
|
||||
use $crate::python::PyDowncastFrom;
|
||||
let py = self.token();
|
||||
|
||||
|
|
|
@ -11,50 +11,50 @@ use conversion::{ToPyObject, IntoPyTuple};
|
|||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer};
|
||||
use objects::{PyObject, PyDict, PyType, exc};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use objectprotocol2::ObjectProtocol2;
|
||||
use token::{Py, PyObjectWithToken};
|
||||
use err::{PyResult, PyErr, ToPyErr};
|
||||
|
||||
|
||||
/// Represents a Python module object.
|
||||
pub struct PyModule(PyPtr);
|
||||
|
||||
pyobject_convert!(PyModule);
|
||||
pyobject_nativetype!(PyModule, PyModule_Type, PyModule_Check);
|
||||
pyobject_nativetype2!(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(py: Python, name: &str) -> PyResult<Py<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())} )?))
|
||||
Ok(Py::from_owned_ptr_or_err(
|
||||
py, unsafe{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(py: Python, name: &str) -> PyResult<Py<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())} )?))
|
||||
Ok(Py::from_owned_ptr_or_err(
|
||||
py, unsafe{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()))
|
||||
PyDict::from_borrowed_ptr(self.token(), 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 +62,39 @@ 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<PyObject>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
self.getattr(py, name)?.call(py, args, kwargs)
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
ObjectProtocol2::getattr(&self, name)?.call(self.token(), 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<PyObject>
|
||||
{
|
||||
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.
|
||||
|
@ -111,7 +112,7 @@ impl<'p> PyModule {
|
|||
unsafe { PyType::from_type_ptr(py, 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>(
|
||||
|
@ -122,7 +123,7 @@ impl<'p> PyModule {
|
|||
unsafe { PyType::from_type_ptr(py, ty) }
|
||||
};
|
||||
|
||||
self.setattr(py, type_name, &ty)?;
|
||||
self.setattr(type_name, &ty)?;
|
||||
|
||||
py.release(ty);
|
||||
Ok(())
|
||||
|
|
|
@ -13,6 +13,7 @@ use objects::PyObject;
|
|||
use pointers::PyPtr;
|
||||
use python::{ToPyPointer, IntoPyPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use token::Py;
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
|
||||
/// Represents a Python `int` object.
|
||||
|
@ -25,8 +26,7 @@ use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
|||
/// with the primitive Rust integer types.
|
||||
pub struct PyInt(PyPtr);
|
||||
|
||||
pyobject_convert!(PyInt);
|
||||
pyobject_nativetype!(PyInt, PyInt_Type, PyInt_Check);
|
||||
pyobject_nativetype2!(PyInt, PyInt_Type, PyInt_Check);
|
||||
|
||||
/// In Python 2.x, represents a Python `long` object.
|
||||
/// Both `PyInt` and `PyLong` refer to the same type on Python 3.x.
|
||||
|
@ -37,8 +37,7 @@ pyobject_nativetype!(PyInt, PyInt_Type, PyInt_Check);
|
|||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong(PyPtr);
|
||||
|
||||
pyobject_convert!(PyLong);
|
||||
pyobject_nativetype!(PyLong, PyLong_Type, PyLong_Check);
|
||||
pyobject_nativetype2!(PyLong, PyLong_Type, PyLong_Check);
|
||||
|
||||
impl PyInt {
|
||||
/// Creates a new Python 2.7 `int` object.
|
||||
|
@ -46,9 +45,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 +57,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()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
|||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong(PyPtr);
|
||||
|
||||
pyobject_convert!(PyLong);
|
||||
pyobject_nativetype!(PyLong, PyLong_Type, PyLong_Check);
|
||||
pyobject_nativetype2!(PyLong, PyLong_Type, PyLong_Check);
|
||||
|
||||
macro_rules! int_fits_c_long(
|
||||
($rust_type:ty) => (
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ffi;
|
||||
use token::Py;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom, PyDowncastInto};
|
||||
use conversion::{FromPyObject, ToPyObject};
|
||||
|
@ -182,9 +183,9 @@ impl PySequence {
|
|||
|
||||
/// Return a fresh list based on the Sequence.
|
||||
#[inline]
|
||||
pub fn list(&self, py: Python) -> PyResult<PyList> {
|
||||
pub fn list(&self, py: Python) -> PyResult<Py<PyList>> {
|
||||
unsafe {
|
||||
Ok(PyList::downcast_from_ptr(
|
||||
Ok(Py::downcast_from_ptr(
|
||||
py, ffi::PySequence_List(self.as_ptr()))?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use python::{Python, ToPyPointer};
|
|||
use pointers::PyPtr;
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyObject;
|
||||
use token::{AsPyRef, Py, PyObjectWithToken};
|
||||
use err::{self, PyResult, PyErr};
|
||||
|
||||
|
||||
|
@ -16,66 +17,63 @@ pub struct PySet(PyPtr);
|
|||
/// Represents a Python `frozenset`
|
||||
pub struct PyFrozenSet(PyPtr);
|
||||
|
||||
pyobject_convert!(PySet);
|
||||
pyobject_nativetype!(PySet, PySet_Type, PySet_Check);
|
||||
pyobject_convert!(PyFrozenSet);
|
||||
pyobject_nativetype!(PyFrozenSet, PyFrozenSet_Type, PyFrozenSet_Check);
|
||||
pyobject_nativetype2!(PySet, PySet_Type, PySet_Check);
|
||||
pyobject_nativetype2!(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_borrowed_ptr_or_opt(self.token(), ffi::PySet_Pop(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +83,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 +98,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 +112,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 +142,11 @@ impl PyFrozenSet {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::{HashSet};
|
||||
use python::{Python, PyDowncastInto};
|
||||
use conversion::ToPyObject;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use super::{PySet, PyFrozenSet};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objectprotocol2::ObjectProtocol2;
|
||||
use token::AsPyRef;
|
||||
|
||||
#[test]
|
||||
fn test_set_new() {
|
||||
|
@ -150,7 +154,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 +164,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(py, &ob).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(py, &ob).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 +188,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,8 +230,9 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let set = PySet::new(py, &[1]);
|
||||
for el in set.iter(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>(py).unwrap());
|
||||
}
|
||||
}
|
||||
|
@ -233,16 +242,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,8 +261,9 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let set = PyFrozenSet::new(py, &[1]);
|
||||
for el in set.iter(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>(py).unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use pointers::PyPtr;
|
|||
use python::{ToPyPointer, Python};
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use token::{Py, PyObjectWithToken};
|
||||
use objects::PyObject;
|
||||
use conversion::ToPyObject;
|
||||
|
||||
|
@ -13,8 +14,7 @@ use conversion::ToPyObject;
|
|||
/// at the moment by `PySlice` object.
|
||||
pub struct PySlice(PyPtr);
|
||||
|
||||
pyobject_convert!(PySlice);
|
||||
pyobject_nativetype!(PySlice, PySlice_Type, PySlice_Check);
|
||||
pyobject_nativetype2!(PySlice, PySlice_Type, PySlice_Check);
|
||||
|
||||
|
||||
/// Represents a Python `slice` indices
|
||||
|
@ -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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use err::{PyResult, PyErr};
|
|||
use super::{PyObject, PyStringData};
|
||||
|
||||
/// Represents a Python string.
|
||||
pub struct PyString(PyPtr);
|
||||
pub struct PyString(pub PyPtr);
|
||||
|
||||
pyobject_nativetype2!(PyString, PyUnicode_Type, PyUnicode_Check);
|
||||
|
||||
|
@ -83,6 +83,7 @@ impl PyString {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl PyBytes {
|
||||
/// Creates a new Python byte string object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
|
|
|
@ -9,7 +9,7 @@ use python::{Python, ToPyPointer, IntoPyPointer};
|
|||
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
pub struct PyPtr(*mut ffi::PyObject);
|
||||
pub struct PyPtr(pub *mut ffi::PyObject);
|
||||
|
||||
// `PyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PyPtr {}
|
||||
|
|
|
@ -197,7 +197,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
pub fn import(self, name : &str) -> PyResult<PyModule> {
|
||||
pub fn import(self, name : &str) -> PyResult<Py<PyModule>> {
|
||||
PyModule::import(self, name)
|
||||
}
|
||||
|
||||
|
@ -211,14 +211,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) -> Py<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) -> Py<PyBool> {
|
||||
PyBool::new(self, false)
|
||||
}
|
||||
|
||||
|
@ -272,8 +272,8 @@ impl<'p> Python<'p> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use {Python, PyDict};
|
||||
use objects::{PyBool, PyList, PyInt};
|
||||
use {AsPyRef, Python};
|
||||
use objects::{PyBool, PyList, PyInt, PyDict};
|
||||
|
||||
#[test]
|
||||
fn test_eval() {
|
||||
|
@ -304,7 +304,7 @@ 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>(py.True().as_ob_ref(py)).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());
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
// Copyright (c) 2015 Daniel Grunwald
|
||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use std::{sync, rc, marker};
|
||||
use ffi;
|
||||
|
|
19
src/token.rs
19
src/token.rs
|
@ -12,8 +12,6 @@ use python::{Python, IntoPyPointer, ToPyPointer, PyDowncastInto};
|
|||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
||||
pub trait PyNativeType {}
|
||||
|
||||
pub struct PyToken(PhantomData<Rc<()>>);
|
||||
|
||||
impl PyToken {
|
||||
|
@ -22,16 +20,21 @@ impl PyToken {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
fn as_mut(&self, py: Python) -> &mut T;
|
||||
|
||||
fn as_ob_ref(&self, py: Python) -> &PyObject;
|
||||
|
||||
fn with<F, R>(&self, f: F) -> R where F: FnOnce(Python, &T) -> R
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -197,9 +200,14 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
|||
ptr.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn as_ob_ref(&self, _py: Python) -> &PyObject {
|
||||
unsafe {std::mem::transmute(self)}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InstancePtr<T> for Py<T> where T: PyTypeInfo + PyNativeType {
|
||||
impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo + PyNativeType {
|
||||
|
||||
#[inline]
|
||||
fn as_ref(&self, _py: Python) -> &T {
|
||||
|
@ -310,6 +318,7 @@ impl<T> PyDowncastInto for Py<T> where T: PyTypeInfo
|
|||
where I: IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if T::is_instance(ptr) {
|
||||
Ok(Py::from_owned_ptr(ptr))
|
||||
} else {
|
||||
|
|
|
@ -84,7 +84,7 @@ 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.as_ref(py).add_class::<EmptyClassInModule>(py).unwrap();
|
||||
|
||||
let ty = module.getattr(py, "EmptyClassInModule").unwrap();
|
||||
assert_eq!(ty.getattr(py, "__name__").unwrap().extract::<String>(py).unwrap(), "EmptyClassInModule");
|
||||
|
|
|
@ -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);
|
||||
|
@ -30,7 +30,7 @@ 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)?;
|
||||
let indices = slice.indices(1000)?;
|
||||
if indices.start == 100 && indices.stop == 200 && indices.step == 1 {
|
||||
return Ok("slice".into_object(py))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue