drop PyClone trait; doc cleanups
This commit is contained in:
parent
dd29dbce80
commit
fc1df289bd
|
@ -12,8 +12,8 @@ Supported Python versions:
|
|||
|
||||
Supported Rust version:
|
||||
|
||||
* Rust 1.17.0-nightly or later
|
||||
* On Windows, we require rustc 1.17.0-nightly
|
||||
* Rust 1.20.0-nightly or later
|
||||
* On Windows, we require rustc 1.20.0-nightly
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -109,9 +109,6 @@ In Python, all objects are implicitly reference counted.
|
|||
In Rust, we will use the [`PyObject`](https://pyo3.github.io/PyO3/pyo3/struct.PyObject.html) type
|
||||
to represent a reference to a Python object.
|
||||
|
||||
The method [`clone_ref()`](https://pyo3.github.io/PyO3/pyo3/trait.PyClone.html#tymethod.clone_ref) (from trait [`PyClone`](https://pyo3.github.io/PyO3/pyo3/trait.PyClone.html)) can be used to create additional
|
||||
references to the same Python object.
|
||||
|
||||
Because all Python objects potentially have multiple owners, the
|
||||
concept of Rust mutability does not apply to Python objects.
|
||||
As a result, this API will **allow mutating Python objects even if they are not stored
|
||||
|
|
|
@ -33,6 +33,8 @@ pub trait ToPyObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`
|
||||
/// by consuming original object.
|
||||
pub trait IntoPyObject {
|
||||
|
||||
/// Converts self into a Python object. (Consumes self)
|
||||
|
@ -51,14 +53,14 @@ pub trait IntoPyTuple {
|
|||
}
|
||||
|
||||
|
||||
/// `FromPyObject` is implemented by various types that can be extracted from a Python object.
|
||||
/// `FromPyObject` is implemented by various types that can be extracted from
|
||||
/// a Python object reference.
|
||||
///
|
||||
/// Normal usage is through the `PyObject::extract` helper method:
|
||||
/// ```let obj: PyObject = ...;
|
||||
/// let value = try!(obj.extract::<TargetType>(py));
|
||||
/// let value: &TargetType = obj.extract(py)?;
|
||||
/// ```
|
||||
///
|
||||
/// TODO: update this documentation
|
||||
/// Note: depending on the implementation, the lifetime of the extracted result may
|
||||
/// depend on the lifetime of the `obj` or the `prepared` variable.
|
||||
///
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::error::Error;
|
|||
use libc;
|
||||
|
||||
use ffi;
|
||||
use python::{ToPyPointer, IntoPyPointer, Python, PyClone};
|
||||
use python::{ToPyPointer, IntoPyPointer, Python};
|
||||
use PyObject;
|
||||
use objects::{PyObjectRef, PyType, exc};
|
||||
use instance::Py;
|
||||
|
@ -347,10 +347,12 @@ impl PyErr {
|
|||
}
|
||||
|
||||
pub fn clone_ref(&self, py: Python) -> PyErr {
|
||||
let v = if let Some(ref val) = self.pvalue { Some(val.clone_ref(py))} else { None };
|
||||
let t = if let Some(ref val) = self.ptraceback { Some(val.clone_ref(py))} else { None };
|
||||
PyErr {
|
||||
ptype: self.ptype.clone_ref(py),
|
||||
pvalue: self.pvalue.clone_ref(py),
|
||||
ptraceback: self.ptraceback.clone_ref(py),
|
||||
pvalue: v,
|
||||
ptraceback: t,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,19 +24,25 @@ impl PyToken {
|
|||
}
|
||||
}
|
||||
|
||||
/// Any instance that is managed Python can have access to `gil`.
|
||||
pub trait PyObjectWithToken: Sized {
|
||||
fn py(&self) -> Python;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNativeType: PyObjectWithToken {}
|
||||
|
||||
|
||||
/// Trait implements objet reference extraction from python managed pointer.
|
||||
pub trait AsPyRef<T>: Sized {
|
||||
|
||||
/// Return reference to object.
|
||||
fn as_ref(&self, py: Python) -> &T;
|
||||
|
||||
/// Return mutable reference to object.
|
||||
fn as_mut(&self, py: Python) -> &mut T;
|
||||
|
||||
/// Acquire python gil and call closure with object reference.
|
||||
fn with<F, R>(&self, f: F) -> R where F: FnOnce(Python, &T) -> R
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -45,6 +51,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
f(py, self.as_ref(py))
|
||||
}
|
||||
|
||||
/// Acquire python gil and call closure with mutable object reference.
|
||||
fn with_mut<F, R>(&self, f: F) -> R where F: FnOnce(Python, &mut T) -> R
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -76,7 +83,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer with specified type information.
|
||||
#[derive(Debug)]
|
||||
pub struct Py<T>(pub *mut ffi::PyObject, std::marker::PhantomData<T>);
|
||||
|
||||
|
@ -96,7 +103,9 @@ impl<T> Py<T> {
|
|||
Py(ptr, std::marker::PhantomData)
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
/// Creates a `Py<T>` instance for the given FFI pointer.
|
||||
/// Panics if the pointer is `null`.
|
||||
/// Undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T>
|
||||
{
|
||||
|
@ -142,25 +151,16 @@ impl<T> Py<T> {
|
|||
pub fn clone_ref(&self, _py: Python) -> Py<T> {
|
||||
unsafe { Py::from_borrowed_ptr(self.0) }
|
||||
}
|
||||
|
||||
/// Casts the `Py<T>` 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> Py<T> where T: PyTypeInfo,
|
||||
{
|
||||
/// Create new instance of T and move under python management
|
||||
/// Create new instance of T and move it under python management
|
||||
/// Returns `Py<T>`.
|
||||
pub fn new<F>(py: Python, f: F) -> PyResult<Py<T>>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
T: PyObjectAlloc<T>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
T: PyObjectAlloc<T>
|
||||
{
|
||||
let ob = f(PyToken(PhantomData));
|
||||
|
||||
|
@ -171,7 +171,7 @@ impl<T> Py<T> where T: PyTypeInfo,
|
|||
Ok(ob)
|
||||
}
|
||||
|
||||
/// Create new instance of `T` and move under python management.
|
||||
/// Create new instance of `T` and move it under python management.
|
||||
/// Returns references to `T`
|
||||
pub fn new_ref<F>(py: Python, f: F) -> PyResult<&T>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
|
@ -185,7 +185,7 @@ impl<T> Py<T> where T: PyTypeInfo,
|
|||
}
|
||||
}
|
||||
|
||||
/// Create new instance of `T` and move under python management.
|
||||
/// Create new instance of `T` and move it under python management.
|
||||
/// Returns mutable references to `T`
|
||||
pub fn new_mut<F>(py: Python, f: F) -> PyResult<&mut T>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
|
@ -234,6 +234,7 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo + PyNativeType {
|
|||
}
|
||||
|
||||
impl<T> ToPyObject for Py<T> {
|
||||
/// Converts `Py` instance -> PyObject.
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
//! In Python, all objects are implicitly reference counted.
|
||||
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
|
||||
//!
|
||||
//! The method `clone_ref()` (from trait `PyClone`) can be used to create additional
|
||||
//! references to the same Python object.
|
||||
//!
|
||||
//! Because all Python objects potentially have multiple owners, the
|
||||
//! concept of Rust mutability does not apply to Python objects.
|
||||
//! As a result, this API will allow mutating Python objects even if they are not stored
|
||||
|
@ -157,7 +154,7 @@ pub use err::{PyErr, PyResult, PyDowncastError, ToPyErr};
|
|||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use object::PyObject;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer, PyClone,
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer,
|
||||
PyMutDowncastFrom, PyDowncastFrom, PyDowncastInto};
|
||||
pub use pythonrun::{GILGuard, prepare_freethreaded_python, prepare_pyo3_library};
|
||||
pub use instance::{PyToken, PyObjectWithToken, AsPyRef, Py, PyNativeType};
|
||||
|
@ -167,7 +164,7 @@ pub use class::*;
|
|||
|
||||
/// Procedural macros
|
||||
pub mod py {
|
||||
pub use pyo3cls::*;
|
||||
pub use pyo3cls::{proto, class, methods};
|
||||
|
||||
#[cfg(Py_3)]
|
||||
pub use pyo3cls::mod3init as modinit;
|
||||
|
@ -194,6 +191,7 @@ mod object;
|
|||
mod objects;
|
||||
mod objectprotocol;
|
||||
mod pythonrun;
|
||||
#[doc(hidden)]
|
||||
pub mod callback;
|
||||
pub mod typeob;
|
||||
#[doc(hidden)]
|
||||
|
|
|
@ -8,10 +8,10 @@ use err::{PyErr, PyResult, PyDowncastError};
|
|||
use instance::{AsPyRef, PyObjectWithToken};
|
||||
use objects::{PyObjectRef, PyDict};
|
||||
use conversion::{ToPyObject, IntoPyObject, IntoPyTuple, FromPyObject};
|
||||
use python::{Python, PyClone, ToPyPointer, IntoPyPointer};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
|
||||
|
||||
/// Wrapper around unsafe `*mut ffi::PyObject` pointer. Decrement ref counter on `Drop`
|
||||
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
|
||||
#[derive(Debug)]
|
||||
pub struct PyObject(*mut ffi::PyObject);
|
||||
|
||||
|
@ -123,6 +123,13 @@ impl PyObject {
|
|||
unsafe { ffi::Py_REFCNT(self.0) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
pub fn clone_ref(&self, py: Python) -> Self {
|
||||
unsafe {
|
||||
PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be None.
|
||||
/// This is equivalent to the Python expression: 'is None'
|
||||
#[inline]
|
||||
|
@ -266,14 +273,6 @@ impl PartialEq for PyObject {
|
|||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
|
|
@ -6,13 +6,14 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult, PyDowncastError, self};
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom, PyClone};
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, IntoPyTuple, FromPyObject};
|
||||
use instance::PyObjectWithToken;
|
||||
|
||||
|
||||
/// Python object model helper methods
|
||||
pub trait ObjectProtocol {
|
||||
|
||||
/// Determines whether this object has the given attribute.
|
||||
|
@ -136,9 +137,6 @@ pub trait ObjectProtocol {
|
|||
/// 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;
|
||||
|
@ -369,10 +367,6 @@ impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
|||
FromPyObject::extract(self.into())
|
||||
}
|
||||
|
||||
fn clone_ref(&self, ptr: &PyObject) -> PyObject {
|
||||
ptr.clone_ref(self.py())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
fn None(&self) -> PyObject {
|
||||
|
|
|
@ -8,7 +8,7 @@ use instance::PyObjectWithToken;
|
|||
use python::{Python, ToPyPointer};
|
||||
use err::{PyResult, PyErr};
|
||||
|
||||
/// Represents a Python bytearray.
|
||||
/// Represents a Python `bytearray`.
|
||||
pub struct PyByteArray(PyObject);
|
||||
|
||||
pyobject_convert!(PyByteArray);
|
||||
|
|
|
@ -16,7 +16,7 @@ use instance::PyObjectWithToken;
|
|||
use err::{PyResult, PyErr, ToPyErr};
|
||||
|
||||
|
||||
/// Represents a Python module object.
|
||||
/// Represents a Python `module` object.
|
||||
pub struct PyModule(PyObject);
|
||||
|
||||
pyobject_convert!(PyModule);
|
||||
|
|
|
@ -9,8 +9,9 @@ use ffi::{self, Py_ssize_t};
|
|||
use instance::PyObjectWithToken;
|
||||
use conversion::ToPyObject;
|
||||
|
||||
/// Represents a Python `slice`. Only `c_long` indeces supprted
|
||||
/// at the moment by `PySlice` object.
|
||||
/// Represents a Python `slice`.
|
||||
///
|
||||
/// Only `c_long` indeces supprted at the moment by `PySlice` object.
|
||||
pub struct PySlice(PyObject);
|
||||
|
||||
pyobject_convert!(PySlice);
|
||||
|
|
|
@ -15,17 +15,17 @@ use python::{ToPyPointer, Python};
|
|||
use err::{PyResult, PyErr};
|
||||
use super::PyStringData;
|
||||
|
||||
/// Represents a Python string.
|
||||
/// Represents a Python `string`.
|
||||
pub struct PyString(PyObject);
|
||||
|
||||
pyobject_convert!(PyString);
|
||||
pyobject_nativetype!(PyString, PyUnicode_Type, PyUnicode_Check);
|
||||
|
||||
/// Represents a Python unicode string.
|
||||
/// Represents a Python `unicode string`.
|
||||
/// Corresponds to `unicode` in Python 2, and `str` in Python 3.
|
||||
pub use PyString as PyUnicode;
|
||||
|
||||
/// Represents a Python byte string.
|
||||
/// Represents a Python `byte` string.
|
||||
pub struct PyBytes(PyObject);
|
||||
|
||||
pyobject_convert!(PyBytes);
|
||||
|
|
|
@ -16,19 +16,19 @@ use python::{Python, ToPyPointer};
|
|||
use objectprotocol::ObjectProtocol;
|
||||
use super::{PyObjectRef, PyStringData};
|
||||
|
||||
/// Represents a Python string.
|
||||
/// Represents a Python `string`.
|
||||
pub struct PyString(PyObject);
|
||||
|
||||
pyobject_convert!(PyString);
|
||||
pyobject_nativetype!(PyString, PyBaseString_Type, PyBaseString_Check);
|
||||
|
||||
/// Represents a Python unicode string.
|
||||
/// Represents a Python `unicode string`.
|
||||
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
|
||||
/// Represents a Python `byte` string. Corresponds to `str` in Python 2
|
||||
pub struct PyBytes(PyObject);
|
||||
|
||||
pyobject_convert!(PyBytes);
|
||||
|
|
|
@ -14,7 +14,7 @@ use python::{Python, ToPyPointer, IntoPyPointer};
|
|||
use conversion::{FromPyObject, ToPyObject, IntoPyTuple, IntoPyObject};
|
||||
use super::exc;
|
||||
|
||||
/// Represents a Python tuple object.
|
||||
/// Represents a Python `tuple` object.
|
||||
pub struct PyTuple(PyObject);
|
||||
|
||||
pyobject_convert!(PyTuple);
|
||||
|
|
|
@ -12,7 +12,7 @@ use err::{PyErr, PyResult};
|
|||
use instance::PyObjectWithToken;
|
||||
use typeob::PyTypeObject;
|
||||
|
||||
/// Represents a reference to a Python type object.
|
||||
/// Represents a reference to a Python `type object`.
|
||||
pub struct PyType(PyObject);
|
||||
|
||||
pyobject_convert!(PyType);
|
||||
|
|
|
@ -101,21 +101,6 @@ impl <T> IntoPyPointer for Option<T> where T: IntoPyPointer {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait PyClone {
|
||||
|
||||
fn clone_ref(&self, py: Python) -> Self;
|
||||
|
||||
}
|
||||
|
||||
impl<T> PyClone for Option<T> where T: PyClone {
|
||||
fn clone_ref(&self, py: Python) -> Option<T> {
|
||||
match *self {
|
||||
Some(ref p) => Some(p.clone_ref(py)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
|
||||
|
|
|
@ -15,9 +15,7 @@ use callback::AbortOnDrop;
|
|||
use class::methods::PyMethodDefType;
|
||||
|
||||
|
||||
/// Basic python type information
|
||||
/// Implementing this trait for custom struct is enough to make it compatible with
|
||||
/// python object system
|
||||
/// Python type information.
|
||||
pub trait PyTypeInfo {
|
||||
/// Type of objects to store in PyObject struct
|
||||
type Type;
|
||||
|
@ -67,6 +65,7 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
|||
|
||||
}
|
||||
|
||||
/// A Python object allocator that is usable as a base type for #[class]
|
||||
pub trait PyObjectAlloc<T> {
|
||||
|
||||
/// Allocates a new object (usually by calling ty->tp_alloc),
|
||||
|
@ -79,11 +78,8 @@ pub trait PyObjectAlloc<T> {
|
|||
unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject);
|
||||
}
|
||||
|
||||
/// A Python object allocator that is usable as a base type for #[class]
|
||||
impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
||||
|
||||
/// Allocates a new object (usually by calling ty->tp_alloc),
|
||||
/// and initializes it using value.
|
||||
default unsafe fn alloc(py: Python, value: T) -> PyResult<*mut ffi::PyObject> {
|
||||
// TODO: remove this
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
|
@ -98,9 +94,6 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
|||
Ok(obj)
|
||||
}
|
||||
|
||||
/// Calls the rust destructor for the object and frees the memory
|
||||
/// (usually by calling ptr->ob_type->tp_free).
|
||||
/// This function is used as tp_dealloc implementation.
|
||||
default unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
||||
let ptr = (obj as *mut u8).offset(<Self as PyTypeInfo>::offset()) as *mut T;
|
||||
std::ptr::drop_in_place(ptr);
|
||||
|
@ -152,6 +145,7 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
|
|||
}
|
||||
|
||||
|
||||
/// Register new type in python object system.
|
||||
pub fn initialize_type<'p, T>(py: Python<'p>,
|
||||
module_name: Option<&str>,
|
||||
type_object: &mut ffi::PyTypeObject) -> PyResult<&'p PyType>
|
||||
|
|
Loading…
Reference in a new issue