Update documentation
This commit is contained in:
parent
5d3d03bcac
commit
1e5605036e
|
@ -1,12 +1,12 @@
|
||||||
#[macro_use] extern crate cpython;
|
extern crate cpython;
|
||||||
|
|
||||||
use cpython::{PythonObject, ObjectProtocol, PyModule, Python};
|
use cpython::{PythonObject, Python};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let sys = PyModule::import(py, "sys").unwrap();
|
let sys = py.import("sys").unwrap();
|
||||||
let path: String = sys.as_object().getattr("version").unwrap().extract().unwrap();
|
let version: String = sys.get("version").unwrap().extract().unwrap();
|
||||||
println!("Hello Python {}", path);
|
println!("Hello Python {}", version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,35 +4,28 @@ use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, ToPythonPoin
|
||||||
use objects::{exc, PyObject, PyBool, PyTuple};
|
use objects::{exc, PyObject, PyBool, PyTuple};
|
||||||
use err::{self, PyErr, PyResult};
|
use err::{self, PyErr, PyResult};
|
||||||
|
|
||||||
/// ToPyObject is implemented for types that can be converted into a python object.
|
/// Conversion trait that allows various objects to be converted into python objects.
|
||||||
/// The goal is to allow methods that take a python object to take anything that
|
|
||||||
/// can be converted into a python object.
|
|
||||||
/// For example, compare calling the following method signatures:
|
|
||||||
/// fn m1(o: &PyObject) {}
|
|
||||||
/// fn m2<O>(o: &O) where O : ToPyObject {}
|
|
||||||
///
|
|
||||||
/// let o: &PyObject = ...;
|
|
||||||
/// m1(o);
|
|
||||||
/// m2(o);
|
|
||||||
///
|
|
||||||
/// let p: PyPtr<PyObject> = ...;
|
|
||||||
/// m1(*p)
|
|
||||||
/// m2(p)
|
|
||||||
///
|
|
||||||
/// let i: i32 = ...;
|
|
||||||
/// m1(*try!(i.to_py_object(py)))
|
|
||||||
/// m2(i)
|
|
||||||
pub trait ToPyObject<'p> {
|
pub trait ToPyObject<'p> {
|
||||||
type ObjectType : PythonObject<'p> = PyObject<'p>;
|
type ObjectType : PythonObject<'p> = PyObject<'p>;
|
||||||
|
|
||||||
|
/// Converts self into a python object.
|
||||||
fn to_py_object(&self, py: Python<'p>) -> PyResult<'p, Self::ObjectType>;
|
fn to_py_object(&self, py: Python<'p>) -> PyResult<'p, Self::ObjectType>;
|
||||||
|
|
||||||
|
/// Converts self into a python object.
|
||||||
|
///
|
||||||
|
/// May be more efficient than `to_py_object` in some cases because
|
||||||
|
/// it can move out of the input object.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_py_object(self, py: Python<'p>) -> PyResult<'p, Self::ObjectType>
|
fn into_py_object(self, py: Python<'p>) -> PyResult<'p, Self::ObjectType>
|
||||||
where Self: Sized {
|
where Self: Sized {
|
||||||
self.to_py_object(py)
|
self.to_py_object(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts self into a python object and calls the specified closure
|
||||||
|
/// on the native FFI pointer underlying the python object.
|
||||||
|
///
|
||||||
|
/// May be more efficient than `to_py_object` because it does not need
|
||||||
|
/// to touch any reference counts when the input object already is a python object.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_borrowed_ptr<F, R>(&self, py: Python<'p>, f: F) -> PyResult<'p, R>
|
fn with_borrowed_ptr<F, R>(&self, py: Python<'p>, f: F) -> PyResult<'p, R>
|
||||||
where F: FnOnce(*mut ffi::PyObject) -> PyResult<'p, R> {
|
where F: FnOnce(*mut ffi::PyObject) -> PyResult<'p, R> {
|
||||||
|
@ -47,7 +40,7 @@ pub trait ToPyObject<'p> {
|
||||||
// 2) input is PyObject
|
// 2) input is PyObject
|
||||||
// -> with_borrowed_ptr() just forwards to the closure
|
// -> with_borrowed_ptr() just forwards to the closure
|
||||||
// 3) input is &str, int, ...
|
// 3) input is &str, int, ...
|
||||||
// -> to_py_object() allocates new python object; FFI call happens; PyPtr::drop() calls Py_DECREF()
|
// -> to_py_object() allocates new python object; FFI call happens; PyObject::drop() calls Py_DECREF()
|
||||||
|
|
||||||
// FFI functions that steal a reference will use:
|
// FFI functions that steal a reference will use:
|
||||||
// let input = try!(input.into_py_object()); ffi::Call(input.steal_ptr())
|
// let input = try!(input.into_py_object()); ffi::Call(input.steal_ptr())
|
||||||
|
|
60
src/err.rs
60
src/err.rs
|
@ -5,20 +5,22 @@ use objects::oldstyle::PyClass;
|
||||||
use ffi;
|
use ffi;
|
||||||
use libc;
|
use libc;
|
||||||
use conversion::ToPyObject;
|
use conversion::ToPyObject;
|
||||||
use std::ffi::CStr;
|
use std::ffi::{CString, CStr};
|
||||||
|
|
||||||
/// Represents a python exception that was raised.
|
/// Represents a python exception that was raised.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PyErr<'p> {
|
pub struct PyErr<'p> {
|
||||||
/// Gets the type of the exception. This should be either a PyClass or a PyType.
|
/// The type of the exception. This should be either a `PyClass` or a `PyType`.
|
||||||
pub ptype : PyObject<'p>,
|
pub ptype : PyObject<'p>,
|
||||||
/// Gets the value of the exception.
|
/// The value of the exception.
|
||||||
/// This can be either an instance of ptype,
|
///
|
||||||
/// a tuple of arguments to be passed to ptype's constructor,
|
/// This can be either an instance of `ptype`,
|
||||||
/// or a single argument to be passed to ptype's constructor.
|
/// a tuple of arguments to be passed to `ptype`'s constructor,
|
||||||
/// Call PyErr::instance() to get the exception instance in all cases.
|
/// or a single argument to be passed to `ptype`'s constructor.
|
||||||
|
/// Call `PyErr::instance()` to get the exception instance in all cases.
|
||||||
pub pvalue : Option<PyObject<'p>>,
|
pub pvalue : Option<PyObject<'p>>,
|
||||||
pub ptraceback : Option<PyObject<'p>> // is actually a PyTraceBack
|
/// The `PyTraceBack` object associated with the error.
|
||||||
|
pub ptraceback : Option<PyObject<'p>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ impl <'p> PyErr<'p> {
|
||||||
|
|
||||||
/// Retrieves the current error from the python interpreter's global state.
|
/// Retrieves the current error from the python interpreter's global state.
|
||||||
/// The error is cleared from the python interpreter.
|
/// The error is cleared from the python interpreter.
|
||||||
/// If no error is set, returns a SystemError.
|
/// If no error is set, returns a `SystemError`.
|
||||||
pub fn fetch(py : Python<'p>) -> PyErr<'p> {
|
pub fn fetch(py : Python<'p>) -> PyErr<'p> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ptype : *mut ffi::PyObject = std::mem::uninitialized();
|
let mut ptype : *mut ffi::PyObject = std::mem::uninitialized();
|
||||||
|
@ -60,9 +62,10 @@ impl <'p> PyErr<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new PyErr.
|
/// Creates a new PyErr.
|
||||||
/// If obj is a python exception instance, the PyErr will use that instance.
|
///
|
||||||
/// If obj is a python exception type, the PyErr will (lazily) create a new instance of that type
|
/// If `obj` is a python exception instance, the PyErr will use that instance.
|
||||||
/// Otherwise, a TypeError is returned instead.
|
/// If `obj` is a python exception type, the PyErr will (lazily) create a new instance of that type
|
||||||
|
/// Otherwise, a `TypeError` is returned instead.
|
||||||
pub fn new<O>(obj: O) -> PyErr<'p> where O: PythonObject<'p> {
|
pub fn new<O>(obj: O) -> PyErr<'p> where O: PythonObject<'p> {
|
||||||
PyErr::new_from_object(obj.into_object())
|
PyErr::new_from_object(obj.into_object())
|
||||||
}
|
}
|
||||||
|
@ -147,7 +150,7 @@ impl <'p> PyErr<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the exception type.
|
/// Retrieves the exception type.
|
||||||
/// If the exception type is an old-style class, returns oldstyle::PyClass.
|
/// If the exception type is an old-style class, returns `oldstyle::PyClass`.
|
||||||
pub fn get_type(&self) -> PyType<'p> {
|
pub fn get_type(&self) -> PyType<'p> {
|
||||||
let py = self.ptype.python();
|
let py = self.ptype.python();
|
||||||
match self.ptype.clone().cast_into::<PyType>() {
|
match self.ptype.clone().cast_into::<PyType>() {
|
||||||
|
@ -161,7 +164,7 @@ impl <'p> PyErr<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the exception instance for this error.
|
/// Retrieves the exception instance for this error.
|
||||||
/// This method takes &mut self because the error might need
|
/// This method takes `&mut self` because the error might need
|
||||||
/// to be normalized in order to create the exception instance.
|
/// to be normalized in order to create the exception instance.
|
||||||
pub fn instance(&mut self) -> PyObject<'p> {
|
pub fn instance(&mut self) -> PyObject<'p> {
|
||||||
self.normalize();
|
self.normalize();
|
||||||
|
@ -171,7 +174,8 @@ impl <'p> PyErr<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restores the error by writing it to the python interpreter's global state.
|
/// Writes the error back to the python interpreter's global state.
|
||||||
|
/// This is the opposite of `PyErr::fetch()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn restore(self) {
|
pub fn restore(self) {
|
||||||
let PyErr { ptype, pvalue, ptraceback } = self;
|
let PyErr { ptype, pvalue, ptraceback } = self;
|
||||||
|
@ -182,13 +186,15 @@ impl <'p> PyErr<'p> {
|
||||||
|
|
||||||
/// Issue a warning message.
|
/// Issue a warning message.
|
||||||
/// May return a PyErr if warnings-as-errors is enabled.
|
/// May return a PyErr if warnings-as-errors is enabled.
|
||||||
pub fn warn(py: Python<'p>, category: &PyObject, message: &CStr, stacklevel: i32) -> PyResult<'p, ()> {
|
pub fn warn(py: Python<'p>, category: &PyObject, message: &str, stacklevel: i32) -> PyResult<'p, ()> {
|
||||||
|
let message = CString::new(message).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
error_on_minusone(py, ffi::PyErr_WarnEx(category.as_ptr(), message.as_ptr(), stacklevel as ffi::Py_ssize_t))
|
error_on_minusone(py, ffi::PyErr_WarnEx(category.as_ptr(), message.as_ptr(), stacklevel as ffi::Py_ssize_t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts `PythonObjectDowncastError` to python `TypeError`.
|
||||||
impl <'p> std::convert::From<PythonObjectDowncastError<'p>> for PyErr<'p> {
|
impl <'p> std::convert::From<PythonObjectDowncastError<'p>> for PyErr<'p> {
|
||||||
fn from(err: PythonObjectDowncastError<'p>) -> PyErr<'p> {
|
fn from(err: PythonObjectDowncastError<'p>) -> PyErr<'p> {
|
||||||
PyErr::new_lazy_init(err.0.get_type::<exc::TypeError>(), None)
|
PyErr::new_lazy_init(err.0.get_type::<exc::TypeError>(), None)
|
||||||
|
@ -196,7 +202,7 @@ impl <'p> std::convert::From<PythonObjectDowncastError<'p>> for PyErr<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct PyObject from the result of a python FFI call that returns a new reference (owned pointer).
|
/// Construct PyObject from the result of a python FFI call that returns a new reference (owned pointer).
|
||||||
/// Returns Err(PyErr) if the pointer is null.
|
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||||
/// Unsafe because the pointer might be invalid.
|
/// Unsafe because the pointer might be invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn result_from_owned_ptr(py : Python, p : *mut ffi::PyObject) -> PyResult<PyObject> {
|
pub unsafe fn result_from_owned_ptr(py : Python, p : *mut ffi::PyObject) -> PyResult<PyObject> {
|
||||||
|
@ -207,18 +213,22 @@ pub unsafe fn result_from_owned_ptr(py : Python, p : *mut ffi::PyObject) -> PyRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn panic_after_error(py: Python) -> ! {
|
||||||
|
unsafe { ffi::PyErr_Print(); }
|
||||||
|
panic!("Python API called failed");
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn from_owned_ptr_or_panic(py : Python, p : *mut ffi::PyObject) -> PyObject {
|
pub unsafe fn from_owned_ptr_or_panic(py : Python, p : *mut ffi::PyObject) -> PyObject {
|
||||||
if p.is_null() {
|
if p.is_null() {
|
||||||
ffi::PyErr_Print();
|
panic_after_error(py);
|
||||||
panic!("Python API called failed");
|
|
||||||
} else {
|
} else {
|
||||||
PyObject::from_owned_ptr(py, p)
|
PyObject::from_owned_ptr(py, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct PyObject from the result of a python FFI call that returns a borrowed reference.
|
/// Construct PyObject from the result of a python FFI call that returns a borrowed reference.
|
||||||
/// Returns Err(PyErr) if the pointer is null.
|
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||||
/// Unsafe because the pointer might be invalid.
|
/// Unsafe because the pointer might be invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn result_from_borrowed_ptr(py : Python, p : *mut ffi::PyObject) -> PyResult<PyObject> {
|
pub unsafe fn result_from_borrowed_ptr(py : Python, p : *mut ffi::PyObject) -> PyResult<PyObject> {
|
||||||
|
@ -239,6 +249,16 @@ pub unsafe fn result_cast_from_owned_ptr<'p, T>(py : Python<'p>, p : *mut ffi::P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn cast_from_owned_ptr_or_panic<'p, T>(py : Python<'p>, p : *mut ffi::PyObject) -> T
|
||||||
|
where T: ::python::PythonObjectWithCheckedDowncast<'p>
|
||||||
|
{
|
||||||
|
if p.is_null() {
|
||||||
|
panic_after_error(py);
|
||||||
|
} else {
|
||||||
|
PyObject::from_owned_ptr(py, p).cast_into().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns Ok if the error code is not -1.
|
/// Returns Ok if the error code is not -1.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn error_on_minusone(py : Python, result : libc::c_int) -> PyResult<()> {
|
pub fn error_on_minusone(py : Python, result : libc::c_int) -> PyResult<()> {
|
||||||
|
|
58
src/lib.rs
58
src/lib.rs
|
@ -8,17 +8,47 @@
|
||||||
|
|
||||||
//! Rust bindings to the python interpreter.
|
//! Rust bindings to the python interpreter.
|
||||||
//!
|
//!
|
||||||
|
//! # Ownership and Lifetimes
|
||||||
|
//! In python, all objects are implicitly reference counted.
|
||||||
|
//! In rust, we will use the `PyObject` type to represent a reference to a python object.
|
||||||
|
//!
|
||||||
|
//! Because all python objects potentially have multiple owners, the concept
|
||||||
|
//! 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
|
||||||
|
//! in a mutable rust variable.
|
||||||
|
//!
|
||||||
|
//! The python interpreter uses a global interpreter lock (GIL)
|
||||||
|
//! to ensure thread-safety.
|
||||||
|
//! This API uses the lifetime parameter `PyObject<'p>` to ensure that python objects cannot
|
||||||
|
//! be accessed without holding the GIL.
|
||||||
|
//! Throughout this library, the lifetime `'p` always refers to the lifetime of the python interpreter.
|
||||||
|
//!
|
||||||
|
//! When accessing existing objects, the lifetime on `PyObject<'p>` is sufficient to ensure that the GIL
|
||||||
|
//! is held by the current code. But we also need to ensure that the GIL is held when creating new objects.
|
||||||
|
//! For this purpose, this library uses the marker type `Python<'p>`,
|
||||||
|
//! which acts like a reference to the whole python interpreter.
|
||||||
|
//!
|
||||||
|
//! You can obtain a `Python<'p>` instance by acquiring the GIL, or by calling `python()`
|
||||||
|
//! on any existing python object.
|
||||||
|
//!
|
||||||
|
//! # Error Handling
|
||||||
|
//! The vast majority of operations in this library will return `PyResult<'p, ...>`.
|
||||||
|
//! This is an alias for the type `Result<..., PyErr<'p>>`.
|
||||||
|
//!
|
||||||
|
//! A `PyErr` represents a python exception. Errors within the rust-cpython library are
|
||||||
|
//! also exposed as python exceptions.
|
||||||
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//! ```
|
//! ```
|
||||||
//! #[macro_use] extern crate cpython;
|
//! extern crate cpython;
|
||||||
//!
|
//!
|
||||||
//! use cpython::{PythonObject, ObjectProtocol, PyModule, Python};
|
//! use cpython::{PythonObject, Python};
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let gil = Python::acquire_gil();
|
//! let gil_guard = Python::acquire_gil();
|
||||||
//! let py = gil.python();
|
//! let py = gil_guard.python();
|
||||||
//! let sys = py.import("sys").unwrap();
|
//! let sys = py.import("sys").unwrap();
|
||||||
//! let version: String = sys.get("version").unwrap().extract().unwrap();
|
//! let version = sys.get("version").unwrap().extract::<String>().unwrap();
|
||||||
//! println!("Hello Python {}", version);
|
//! println!("Hello Python {}", version);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -51,6 +81,7 @@ mod objectprotocol;
|
||||||
mod pythonrun;
|
mod pythonrun;
|
||||||
|
|
||||||
/// Private re-exports for macros. Do not use.
|
/// Private re-exports for macros. Do not use.
|
||||||
|
#[doc(hidden)]
|
||||||
pub mod _detail {
|
pub mod _detail {
|
||||||
pub use ffi;
|
pub use ffi;
|
||||||
pub use libc;
|
pub use libc;
|
||||||
|
@ -117,6 +148,18 @@ macro_rules! py_module_initializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a python callable object that invokes a Rust function.
|
||||||
|
///
|
||||||
|
/// Arguments:
|
||||||
|
///
|
||||||
|
/// 1. The `Python<'p>` marker, to ensure this macro is only used while holding the GIL.
|
||||||
|
/// 2. A Rust function with the signature `<'p>(Python<'p>, &PyTuple<'p>) -> PyResult<'p, T>`
|
||||||
|
/// for some `T` that implements `ToPyObject`.
|
||||||
|
///
|
||||||
|
/// See `py_module_initializer!` for example usage.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
/// May panic when python runs out of memory.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! py_func {
|
macro_rules! py_func {
|
||||||
($py: expr, $f: expr) => ({
|
($py: expr, $f: expr) => ({
|
||||||
|
@ -132,7 +175,10 @@ macro_rules! py_func {
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Ok(val) => $crate::ToPythonPointer::steal_ptr(val),
|
Ok(val) => $crate::ToPythonPointer::steal_ptr(val),
|
||||||
Err(e) => { e.restore(); ::std::ptr::null_mut() }
|
Err(e) => {
|
||||||
|
e.restore();
|
||||||
|
::std::ptr::null_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static mut method_def: $crate::_detail::ffi::PyMethodDef = $crate::_detail::ffi::PyMethodDef {
|
static mut method_def: $crate::_detail::ffi::PyMethodDef = $crate::_detail::ffi::PyMethodDef {
|
||||||
|
|
|
@ -9,6 +9,7 @@ use objects::{PyObject, PyTuple, PyDict};
|
||||||
use conversion::ToPyObject;
|
use conversion::ToPyObject;
|
||||||
use err::{PyErr, PyResult, result_from_owned_ptr, error_on_minusone};
|
use err::{PyErr, PyResult, result_from_owned_ptr, error_on_minusone};
|
||||||
|
|
||||||
|
/// Trait that contains methods
|
||||||
pub trait ObjectProtocol<'p> : PythonObject<'p> {
|
pub trait ObjectProtocol<'p> : PythonObject<'p> {
|
||||||
/// Determines whether this object has the given attribute.
|
/// Determines whether this object has the given attribute.
|
||||||
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
||||||
|
|
|
@ -7,6 +7,7 @@ use conversion::{FromPyObject, ToPyObject};
|
||||||
pyobject_newtype!(PyBool, PyBool_Check, PyBool_Type);
|
pyobject_newtype!(PyBool, PyBool_Check, PyBool_Type);
|
||||||
|
|
||||||
impl <'p> PyBool<'p> {
|
impl <'p> PyBool<'p> {
|
||||||
|
/// Depending on `val`, returns `py.True()` or `py.False()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(py: Python<'p>, val: bool) -> PyBool<'p> {
|
pub fn get(py: Python<'p>, val: bool) -> PyBool<'p> {
|
||||||
if val { py.True() } else { py.False() }
|
if val { py.True() } else { py.False() }
|
||||||
|
|
|
@ -7,8 +7,14 @@ use err::{self, PyResult};
|
||||||
pyobject_newtype!(PyDict, PyDict_Check, PyDict_Type);
|
pyobject_newtype!(PyDict, PyDict_Check, PyDict_Type);
|
||||||
|
|
||||||
impl <'p> PyDict<'p> {
|
impl <'p> PyDict<'p> {
|
||||||
|
/// Creates a new empty dictionary.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
/// May panic when running out of memory.
|
||||||
pub fn new(py: Python<'p>) -> PyDict<'p> {
|
pub fn new(py: Python<'p>) -> PyDict<'p> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
err::cast_from_owned_ptr_or_panic(py, ffi::PyDict_New())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! This module contains the python exception types.
|
||||||
|
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
|
|
|
@ -7,8 +7,7 @@ pyobject_newtype!(PyIterator, PyIter_Check);
|
||||||
|
|
||||||
impl <'p> PyIterator<'p> {
|
impl <'p> PyIterator<'p> {
|
||||||
/// Retrieves the next item from an iterator.
|
/// Retrieves the next item from an iterator.
|
||||||
/// Returns None when the iterator is exhausted.
|
/// Returns `None` when the iterator is exhausted.
|
||||||
#[inline]
|
|
||||||
pub fn iter_next(&self) -> PyResult<'p, Option<PyObject<'p>>> {
|
pub fn iter_next(&self) -> PyResult<'p, Option<PyObject<'p>>> {
|
||||||
let py = self.python();
|
let py = self.python();
|
||||||
match unsafe { PyObject::from_owned_ptr_opt(py, ffi::PyIter_Next(self.as_ptr())) } {
|
match unsafe { PyObject::from_owned_ptr_opt(py, ffi::PyIter_Next(self.as_ptr())) } {
|
||||||
|
@ -24,4 +23,3 @@ impl <'p> PyIterator<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use conversion::{ToPyObject, FromPyObject};
|
||||||
pyobject_newtype!(PyList, PyList_Check, PyList_Type);
|
pyobject_newtype!(PyList, PyList_Check, PyList_Type);
|
||||||
|
|
||||||
impl <'p> PyList<'p> {
|
impl <'p> PyList<'p> {
|
||||||
|
/// Construct a new list with the given elements.
|
||||||
pub fn new(py: Python<'p>, elements: &[PyObject<'p>]) -> PyList<'p> {
|
pub fn new(py: Python<'p>, elements: &[PyObject<'p>]) -> PyList<'p> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
|
let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
|
||||||
|
@ -20,6 +21,7 @@ impl <'p> PyList<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the length of the list.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
// non-negative Py_ssize_t should always fit into Rust uint
|
// non-negative Py_ssize_t should always fit into Rust uint
|
||||||
|
@ -28,6 +30,9 @@ impl <'p> PyList<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the item at the specified index.
|
||||||
|
///
|
||||||
|
/// Panics if the index is out of range.
|
||||||
pub fn get_item(&self, index: usize) -> PyObject<'p> {
|
pub fn get_item(&self, index: usize) -> PyObject<'p> {
|
||||||
assert!(index < self.len());
|
assert!(index < self.len());
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -35,21 +40,21 @@ impl <'p> PyList<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the item at the specified index.
|
||||||
|
///
|
||||||
|
/// Panics if the index is out of range.
|
||||||
pub fn set_item(&self, index: usize, item: PyObject<'p>) {
|
pub fn set_item(&self, index: usize, item: PyObject<'p>) {
|
||||||
let r = unsafe { ffi::PyList_SetItem(self.as_ptr(), index as Py_ssize_t, item.steal_ptr()) };
|
let r = unsafe { ffi::PyList_SetItem(self.as_ptr(), index as Py_ssize_t, item.steal_ptr()) };
|
||||||
assert!(r == 0);
|
assert!(r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts an item at the specified index.
|
||||||
|
///
|
||||||
|
/// Panics if the index is out of range.
|
||||||
pub fn insert_item(&self, index: usize, item: PyObject<'p>) {
|
pub fn insert_item(&self, index: usize, item: PyObject<'p>) {
|
||||||
let r = unsafe { ffi::PyList_Insert(self.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
|
let r = unsafe { ffi::PyList_Insert(self.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
|
||||||
assert!(r == 0);
|
assert!(r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#[inline]
|
|
||||||
pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, PyObject<'p>> {
|
|
||||||
self.as_slice().iter()
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'p, T> ToPyObject<'p> for [T] where T: ToPyObject<'p> {
|
impl <'p, T> ToPyObject<'p> for [T] where T: ToPyObject<'p> {
|
||||||
|
|
|
@ -27,6 +27,7 @@ impl <'p> PyModule<'p> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method for module_initializer!() macro, do not use directly!
|
// Helper method for module_initializer!() macro, do not use directly!
|
||||||
|
#[doc(hidden)]
|
||||||
pub fn _init<F, R>(py: Python<'p>, name: &CStr, init: F) -> PyResult<'p, R>
|
pub fn _init<F, R>(py: Python<'p>, name: &CStr, init: F) -> PyResult<'p, R>
|
||||||
where F: FnOnce(Python<'p>, PyModule<'p>) -> PyResult<'p, R> {
|
where F: FnOnce(Python<'p>, PyModule<'p>) -> PyResult<'p, R> {
|
||||||
let module = try!(unsafe {
|
let module = try!(unsafe {
|
||||||
|
@ -60,21 +61,28 @@ impl <'p> PyModule<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the module name.
|
||||||
|
///
|
||||||
|
/// May fail if the module does not have a __name__ attribute.
|
||||||
pub fn name<'a>(&'a self) -> PyResult<'p, &'a str> {
|
pub fn name<'a>(&'a self) -> PyResult<'p, &'a str> {
|
||||||
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) }
|
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) -> PyResult<'p, &'a str> {
|
pub fn filename<'a>(&'a self) -> PyResult<'p, &'a str> {
|
||||||
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.as_ptr())) }
|
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.as_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function for retrieving a member from the module.
|
/// Gets a member from the module.
|
||||||
pub fn get(&self, name: &str) -> PyResult<'p, PyObject<'p>> {
|
pub fn get(&self, name: &str) -> PyResult<'p, PyObject<'p>> {
|
||||||
use objectprotocol::ObjectProtocol;
|
use objectprotocol::ObjectProtocol;
|
||||||
self.as_object().getattr(name)
|
self.as_object().getattr(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a member to the module.
|
/// Adds a member to the module.
|
||||||
|
///
|
||||||
/// This is a convenience function which can be used from the module's initialization function.
|
/// 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<'p, ()> where V: ToPyObject<'p> {
|
pub fn add<V>(&self, name: &str, value: V) -> PyResult<'p, ()> where V: ToPyObject<'p> {
|
||||||
let py = self.python();
|
let py = self.python();
|
||||||
|
|
|
@ -12,12 +12,14 @@ pyobject_newtype!(PyLong, PyLong_Check, PyLong_Type);
|
||||||
pyobject_newtype!(PyFloat, PyFloat_Check, PyFloat_Type);
|
pyobject_newtype!(PyFloat, PyFloat_Check, PyFloat_Type);
|
||||||
|
|
||||||
impl <'p> PyInt<'p> {
|
impl <'p> PyInt<'p> {
|
||||||
|
/// Creates a new python `int` object.
|
||||||
pub fn new(py: Python<'p>, val: c_long) -> PyInt<'p> {
|
pub fn new(py: Python<'p>, val: c_long) -> PyInt<'p> {
|
||||||
unsafe {
|
unsafe {
|
||||||
err::result_from_owned_ptr(py, ffi::PyInt_FromLong(val)).unwrap().unchecked_cast_into::<PyInt>()
|
err::cast_from_owned_ptr_or_panic(py, ffi::PyInt_FromLong(val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the value of this integer.
|
||||||
pub fn value(&self) -> c_long {
|
pub fn value(&self) -> c_long {
|
||||||
unsafe { ffi::PyInt_AS_LONG(self.as_ptr()) }
|
unsafe { ffi::PyInt_AS_LONG(self.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
@ -25,12 +27,14 @@ impl <'p> PyInt<'p> {
|
||||||
|
|
||||||
|
|
||||||
impl <'p> PyFloat<'p> {
|
impl <'p> PyFloat<'p> {
|
||||||
|
/// Creates a new python `float` object.
|
||||||
pub fn new(py: Python<'p>, val: c_double) -> PyFloat<'p> {
|
pub fn new(py: Python<'p>, val: c_double) -> PyFloat<'p> {
|
||||||
unsafe {
|
unsafe {
|
||||||
err::result_from_owned_ptr(py, ffi::PyFloat_FromDouble(val)).unwrap().unchecked_cast_into::<PyFloat>()
|
err::cast_from_owned_ptr_or_panic(py, ffi::PyFloat_FromDouble(val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the value of this float.
|
||||||
pub fn value(&self) -> c_double {
|
pub fn value(&self) -> c_double {
|
||||||
unsafe { ffi::PyFloat_AS_DOUBLE(self.as_ptr()) }
|
unsafe { ffi::PyFloat_AS_DOUBLE(self.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub struct PyObject<'p> {
|
||||||
py : Python<'p>
|
py : Python<'p>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dropping a `PyObject` decrements the reference count on the object by 1.
|
||||||
impl <'p> Drop for PyObject<'p> {
|
impl <'p> Drop for PyObject<'p> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
@ -24,6 +25,7 @@ impl <'p> Drop for PyObject<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cloning a `PyObject` increments the reference count on the object by 1.
|
||||||
impl <'p> Clone for PyObject<'p> {
|
impl <'p> Clone for PyObject<'p> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> PyObject<'p> {
|
fn clone(&self) -> PyObject<'p> {
|
||||||
|
@ -135,7 +137,7 @@ impl <'p> PyObject<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transmutes an owned FFI pointer to &PyObject.
|
/// Transmutes an owned FFI pointer to `&PyObject`.
|
||||||
/// Undefined behavior if the pointer is NULL or invalid.
|
/// Undefined behavior if the pointer is NULL or invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn borrow_from_owned_ptr<'a>(py : Python<'p>, ptr : &'a *mut ffi::PyObject) -> &'a PyObject<'p> {
|
pub unsafe fn borrow_from_owned_ptr<'a>(py : Python<'p>, ptr : &'a *mut ffi::PyObject) -> &'a PyObject<'p> {
|
||||||
|
@ -143,19 +145,20 @@ impl <'p> PyObject<'p> {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transmutes a slice of owned FFI pointers to &[PyObject].
|
/// Transmutes a slice of owned FFI pointers to `&[PyObject]`.
|
||||||
/// Undefined behavior if the pointer is NULL or invalid.
|
/// Undefined behavior if the pointer is NULL or invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn borrow_from_owned_ptr_slice<'a>(py : Python<'p>, ptr : &'a [*mut ffi::PyObject]) -> &'a [PyObject<'p>] {
|
pub unsafe fn borrow_from_owned_ptr_slice<'a>(py : Python<'p>, ptr : &'a [*mut ffi::PyObject]) -> &'a [PyObject<'p>] {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the reference count of this python object.
|
/// Gets the reference count of this python object.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_refcnt(&self) -> usize {
|
pub fn get_refcnt(&self) -> usize {
|
||||||
unsafe { ffi::Py_REFCNT(self.as_ptr()) as usize }
|
unsafe { ffi::Py_REFCNT(self.as_ptr()) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the python type object for this object's type.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_type(&self) -> &PyType<'p> {
|
pub fn get_type(&self) -> &PyType<'p> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -166,15 +169,15 @@ impl <'p> PyObject<'p> {
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete python object type.
|
/// Casts the PyObject to a concrete python object type.
|
||||||
/// Causes undefined behavior if the object is not of the expected type.
|
/// Causes undefined behavior if the object is not of the expected type.
|
||||||
/// This is a wrapper function around PythonObject::unchecked_downcast_from().
|
/// This is a wrapper function around `PythonObject::unchecked_downcast_from()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn unchecked_cast_into<T>(self) -> T where T: PythonObject<'p> {
|
pub unsafe fn unchecked_cast_into<T>(self) -> T where T: PythonObject<'p> {
|
||||||
PythonObject::unchecked_downcast_from(self)
|
PythonObject::unchecked_downcast_from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete python object type.
|
/// Casts the PyObject to a concrete python object type.
|
||||||
/// Returns a python TypeError if the object is not of the expected type.
|
/// Returns a python `TypeError` if the object is not of the expected type.
|
||||||
/// This is a wrapper function around PythonObjectWithCheckedDowncast::downcast_from().
|
/// This is a wrapper function around `PythonObjectWithCheckedDowncast::downcast_from()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cast_into<T>(self) -> Result<T, PythonObjectDowncastError<'p>> where T: PythonObjectWithCheckedDowncast<'p> {
|
pub fn cast_into<T>(self) -> Result<T, PythonObjectDowncastError<'p>> where T: PythonObjectWithCheckedDowncast<'p> {
|
||||||
PythonObjectWithCheckedDowncast::downcast_from(self)
|
PythonObjectWithCheckedDowncast::downcast_from(self)
|
||||||
|
@ -182,34 +185,39 @@ impl <'p> PyObject<'p> {
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete python object type.
|
/// Casts the PyObject to a concrete python object type.
|
||||||
/// Causes undefined behavior if the object is not of the expected type.
|
/// Causes undefined behavior if the object is not of the expected type.
|
||||||
/// This is a wrapper function around PythonObject::unchecked_downcast_borrow_from().
|
/// This is a wrapper function around `PythonObject::unchecked_downcast_borrow_from()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn unchecked_cast_as<'s, T>(&'s self) -> &'s T where T: PythonObject<'p> {
|
pub unsafe fn unchecked_cast_as<'s, T>(&'s self) -> &'s T where T: PythonObject<'p> {
|
||||||
PythonObject::unchecked_downcast_borrow_from(self)
|
PythonObject::unchecked_downcast_borrow_from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete python object type.
|
/// Casts the PyObject to a concrete python object type.
|
||||||
/// Returns a python TypeError if the object is not of the expected type.
|
/// Returns a python `TypeError` if the object is not of the expected type.
|
||||||
/// This is a wrapper function around PythonObjectWithCheckedDowncast::downcast_borrow_from().
|
/// This is a wrapper function around `PythonObjectWithCheckedDowncast::downcast_borrow_from()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cast_as<'s, T>(&'s self) -> Result<&'s T, PythonObjectDowncastError<'p>> where T: PythonObjectWithCheckedDowncast<'p> {
|
pub fn cast_as<'s, T>(&'s self) -> Result<&'s T, PythonObjectDowncastError<'p>> where T: PythonObjectWithCheckedDowncast<'p> {
|
||||||
PythonObjectWithCheckedDowncast::downcast_borrow_from(self)
|
PythonObjectWithCheckedDowncast::downcast_borrow_from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts some type from the python object.
|
/// Extracts some type from the python object.
|
||||||
/// This is a wrapper function around FromPyObject::from_py_object().
|
/// This is a wrapper function around `FromPyObject::from_py_object()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extract<'s, T>(&'s self) -> Result<T, PyErr<'p>> where T: ::conversion::FromPyObject<'p, 's> {
|
pub fn extract<'s, T>(&'s self) -> Result<T, PyErr<'p>> where T: ::conversion::FromPyObject<'p, 's> {
|
||||||
::conversion::FromPyObject::from_py_object(self)
|
::conversion::FromPyObject::from_py_object(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PyObject implements the `==` operator using reference equality:
|
||||||
|
/// `obj1 == obj2` in rust is equivalent to `obj1 is obj2` in python.
|
||||||
impl <'p> PartialEq for PyObject<'p> {
|
impl <'p> PartialEq for PyObject<'p> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, o : &PyObject<'p>) -> bool {
|
fn eq(&self, o : &PyObject<'p>) -> bool {
|
||||||
self.ptr == o.ptr
|
self.ptr == o.ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PyObject implements the `==` operator using reference equality:
|
||||||
|
/// `obj1 == obj2` in rust is equivalent to `obj1 is obj2` in python.
|
||||||
impl <'p> Eq for PyObject<'p> { }
|
impl <'p> Eq for PyObject<'p> { }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! This module contains support for old-style classes. Only available in Python 2.x.
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use python::{Python, PythonObject, ToPythonPointer};
|
use python::{Python, PythonObject, ToPythonPointer};
|
||||||
use err::{self, PyResult};
|
use err::{self, PyResult};
|
||||||
|
|
|
@ -16,6 +16,21 @@ pyobject_newtype!(PyString, PyString_Check, PyString_Type);
|
||||||
pyobject_newtype!(PyUnicode, PyUnicode_Check, PyUnicode_Type);
|
pyobject_newtype!(PyUnicode, PyUnicode_Check, PyUnicode_Type);
|
||||||
|
|
||||||
impl <'p> PyString<'p> {
|
impl <'p> PyString<'p> {
|
||||||
|
/// Creates a new python string object from the Rust string.
|
||||||
|
///
|
||||||
|
/// Note: on Python 2, this function always creates a `str` object,
|
||||||
|
/// never a `unicode` object.
|
||||||
|
/// Use `str::to_py_object()` instead to create `unicode` objects for non-ascii strings.
|
||||||
|
pub fn new(py: Python<'p>, s: &str) -> PyString<'p> {
|
||||||
|
let ptr = s.as_ptr() as *const c_char;
|
||||||
|
let len = s.len() as ffi::Py_ssize_t;
|
||||||
|
unsafe {
|
||||||
|
err::cast_from_owned_ptr_or_panic(py,
|
||||||
|
ffi::PyString_FromStringAndSize(ptr, len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the python string data as byte slice.
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
let buffer = ffi::PyString_AS_STRING(self.as_ptr()) as *const u8;
|
let buffer = ffi::PyString_AS_STRING(self.as_ptr()) as *const u8;
|
||||||
|
@ -24,12 +39,23 @@ impl <'p> PyString<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the python string data as `&str`.
|
||||||
pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
|
pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
|
||||||
str::from_utf8(self.as_slice())
|
str::from_utf8(self.as_slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'p> PyUnicode<'p> {
|
impl <'p> PyUnicode<'p> {
|
||||||
|
/// Creates a new unicode string object from the Rust string.
|
||||||
|
pub fn new(py: Python<'p>, s: &str) -> PyUnicode<'p> {
|
||||||
|
let ptr = s.as_ptr() as *const c_char;
|
||||||
|
let len = s.len() as ffi::Py_ssize_t;
|
||||||
|
unsafe {
|
||||||
|
err::cast_from_owned_ptr_or_panic(py,
|
||||||
|
ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_slice(&self) -> &[ffi::Py_UNICODE] {
|
pub fn as_slice(&self) -> &[ffi::Py_UNICODE] {
|
||||||
unsafe {
|
unsafe {
|
||||||
let buffer = ffi::PyUnicode_AS_UNICODE(self.as_ptr()) as *const _;
|
let buffer = ffi::PyUnicode_AS_UNICODE(self.as_ptr()) as *const _;
|
||||||
|
@ -41,6 +67,10 @@ impl <'p> PyUnicode<'p> {
|
||||||
|
|
||||||
// When converting strings to/from python, we need to copy the string data.
|
// When converting strings to/from python, we need to copy the string data.
|
||||||
// This means we can implement ToPyObject for str, but FromPyObject only for (Cow)String.
|
// This means we can implement ToPyObject for str, but FromPyObject only for (Cow)String.
|
||||||
|
|
||||||
|
/// Converts rust `str` to python object:
|
||||||
|
/// ASCII-only strings are converted to python `str` objects;
|
||||||
|
/// other strings are converted to python `unicode` objects.
|
||||||
impl <'p> ToPyObject<'p> for str {
|
impl <'p> ToPyObject<'p> for str {
|
||||||
type ObjectType = PyObject<'p>;
|
type ObjectType = PyObject<'p>;
|
||||||
|
|
||||||
|
@ -58,6 +88,9 @@ impl <'p> ToPyObject<'p> for str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts rust `&str` to python object:
|
||||||
|
/// ASCII-only strings are converted to python `str` objects;
|
||||||
|
/// other strings are converted to python `unicode` objects.
|
||||||
impl <'p, 'a> ToPyObject<'p> for &'a str {
|
impl <'p, 'a> ToPyObject<'p> for &'a str {
|
||||||
type ObjectType = PyObject<'p>;
|
type ObjectType = PyObject<'p>;
|
||||||
|
|
||||||
|
|
|
@ -9,22 +9,25 @@ use pythonrun::GILGuard;
|
||||||
struct PythonInterpreterState;
|
struct PythonInterpreterState;
|
||||||
impl !Sync for PythonInterpreterState {}
|
impl !Sync for PythonInterpreterState {}
|
||||||
|
|
||||||
|
/// Marker type that indicates that the GIL is currently held.
|
||||||
|
///
|
||||||
/// The 'Python' struct is a zero-size marker struct that is required for most python operations.
|
/// The 'Python' struct is a zero-size marker struct that is required for most python operations.
|
||||||
/// This is used to indicate that the operation accesses/modifies the python interpreter state,
|
/// This is used to indicate that the operation accesses/modifies the python interpreter state,
|
||||||
/// and thus can only be called if the python interpreter is initialized and the GIL is acquired.
|
/// and thus can only be called if the python interpreter is initialized and the
|
||||||
/// The lifetime 'p represents the lifetime of the python interpreter.
|
/// python global interpreter lock (GIL) is acquired.
|
||||||
/// For example, python constants like None have the type "&'p PyObject<'p>".
|
/// The lifetime `'p` represents the lifetime of the python interpreter.
|
||||||
/// You can imagine the GIL to be a giant "Mutex<AllPythonState>". This makes 'p the lifetime of the
|
///
|
||||||
/// python state protected by that mutex.
|
/// You can imagine the GIL to be a giant `Mutex<PythonInterpreterState>`.
|
||||||
|
/// The type `Python<'p>` then acts like a reference `&'p PythonInterpreterState`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Python<'p>(PhantomData<&'p PythonInterpreterState>);
|
pub struct Python<'p>(PhantomData<&'p PythonInterpreterState>);
|
||||||
|
|
||||||
// Trait for converting from Self to *mut ffi::PyObject
|
/// This trait allows retrieving the underlying FFI pointer from python objects.
|
||||||
pub trait ToPythonPointer {
|
pub trait ToPythonPointer {
|
||||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||||
fn as_ptr(&self) -> *mut ffi::PyObject;
|
fn as_ptr(&self) -> *mut ffi::PyObject;
|
||||||
|
|
||||||
/// Destructures the input object, moving out the ownership of the underlying FFI pointer.
|
/// Retrieves the underlying FFI pointer as a "stolen pointer".
|
||||||
fn steal_ptr(self) -> *mut ffi::PyObject;
|
fn steal_ptr(self) -> *mut ffi::PyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,3 +165,9 @@ impl<'p> Python<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'p> std::fmt::Debug for PythonObjectDowncastError<'p> {
|
||||||
|
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
|
f.write_str("PythonObjectDowncastError")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue