Merge pull request #813 from birkenfeld/docstrings
docstrings: fixes, also point to the new guide chapter
This commit is contained in:
commit
da4009507e
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Basic Python Object customization
|
||||
//!
|
||||
//! Check [python c-api information](https://docs.python.org/3/reference/datamodel.html#basic-customization)
|
||||
//! Check [the Python C API information](https://docs.python.org/3/reference/datamodel.html#basic-customization)
|
||||
//! for more information.
|
||||
//!
|
||||
//! Parts of the documentation are copied from the respective methods from the
|
||||
|
@ -27,7 +27,7 @@ pub enum CompareOp {
|
|||
Ge = ffi::Py_GE as isize,
|
||||
}
|
||||
|
||||
/// Basic python class customization
|
||||
/// Basic Python class customization
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyObjectProtocol<'p>: PyClass {
|
||||
fn __getattr__(&'p self, name: Self::Name) -> Self::Result
|
||||
|
@ -246,8 +246,8 @@ where
|
|||
}
|
||||
|
||||
/// An object may support setting attributes (by implementing PyObjectSetAttrProtocol)
|
||||
/// and may support deleting attributes (by implementing PyObjectDelAttrProtocol)
|
||||
/// and we need to generate a single extern c function that supports only setting, only deleting
|
||||
/// and may support deleting attributes (by implementing PyObjectDelAttrProtocol).
|
||||
/// We need to generate a single "extern C" function that supports only setting, only deleting
|
||||
/// or both, and return None in case none of the two is supported.
|
||||
mod tp_setattro_impl {
|
||||
use super::*;
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::ffi;
|
|||
use libc::c_int;
|
||||
use std::ffi::CString;
|
||||
|
||||
/// `PyMethodDefType` represents different types of python callable objects.
|
||||
/// It is used by `#[pymethods]` and `#[pyproto]` annotations.
|
||||
/// `PyMethodDefType` represents different types of Python callable objects.
|
||||
/// It is used by the `#[pymethods]` and `#[pyproto]` annotations.
|
||||
#[derive(Debug)]
|
||||
pub enum PyMethodDefType {
|
||||
/// Represents class `__new__` method
|
||||
|
@ -133,7 +133,7 @@ pub trait PyMethodsInventory: inventory::Collect {
|
|||
fn get_methods(&self) -> &'static [PyMethodDefType];
|
||||
}
|
||||
|
||||
/// The implementation of tis trait defines which methods a python type has.
|
||||
/// The implementation of this trait defines which methods a Python type has.
|
||||
///
|
||||
/// For pyclass derived structs this is implemented by collecting all impl blocks through inventory
|
||||
pub trait PyMethodsProtocol {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Python Async/Await Interface.
|
||||
//!
|
||||
//! Check [python c-api information](
|
||||
//! Check [the Python C API information](
|
||||
//! https://docs.python.org/3/c-api/typeobj.html#async-object-structures)
|
||||
//!
|
||||
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
//! Conversions between various states of rust and python types and their wrappers.
|
||||
//! Conversions between various states of Rust and Python types and their wrappers.
|
||||
use crate::err::{self, PyDowncastError, PyResult};
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::{PyDowncastImpl, PyTypeInfo};
|
||||
|
@ -9,9 +9,10 @@ use crate::types::PyTuple;
|
|||
use crate::{ffi, gil, Py, PyCell, PyClass, PyNativeType, PyRef, PyRefMut, Python};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// This trait represents that, **we can do zero-cost conversion from the object to FFI pointer**.
|
||||
/// This trait represents that **we can do zero-cost conversion from the object
|
||||
/// to a FFI pointer**.
|
||||
///
|
||||
/// This trait is implemented for types that internally wrap a pointer to a python object.
|
||||
/// This trait is implemented for types that internally wrap a pointer to a Python object.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -77,7 +78,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`.
|
||||
pub trait ToPyObject {
|
||||
/// Converts self into a Python object.
|
||||
fn to_object(&self, py: Python) -> PyObject;
|
||||
|
@ -161,23 +162,31 @@ impl<T> FromPy<T> for T {
|
|||
/// `FromPyObject` is implemented by various types that can be extracted from
|
||||
/// a Python object reference.
|
||||
///
|
||||
/// Normal usage is through the `PyObject::extract` helper method:
|
||||
/// Normal usage is through the helper methods `PyObject::extract` or
|
||||
/// `PyAny::extract`:
|
||||
///
|
||||
/// ```let obj: PyObject = ...;
|
||||
/// let value: &TargetType = obj.extract(py)?;
|
||||
///
|
||||
/// let any: &PyAny = ...;
|
||||
/// let value: &TargetType = any.extract()?;
|
||||
/// ```
|
||||
///
|
||||
/// Note: depending on the implementation, the lifetime of the extracted result may
|
||||
/// depend on the lifetime of the `obj` or the `prepared` variable.
|
||||
///
|
||||
/// For example, when extracting `&str` from a python byte string, the resulting string slice will
|
||||
/// For example, when extracting `&str` from a Python byte string, the resulting string slice will
|
||||
/// point to the existing string data (lifetime: `'source`).
|
||||
/// On the other hand, when extracting `&str` from a python unicode string, the preparation step
|
||||
/// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step
|
||||
/// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`.
|
||||
/// Since only which of these cases applies depends on the runtime type of the python object,
|
||||
/// Since which case applies depends on the runtime type of the Python object,
|
||||
/// both the `obj` and `prepared` variables must outlive the resulting string slice.
|
||||
///
|
||||
/// In cases where the result does not depend on the `'prepared` lifetime,
|
||||
/// the inherent method `PyObject::extract()` can be used.
|
||||
///
|
||||
/// The trait's conversion method takes a `&PyAny` argument but is called
|
||||
/// `FromPyObject` for historical reasons.
|
||||
pub trait FromPyObject<'source>: Sized {
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(ob: &'source PyAny) -> PyResult<Self>;
|
||||
|
|
44
src/err.rs
44
src/err.rs
|
@ -16,9 +16,9 @@ use std::io;
|
|||
use std::os::raw::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Represents a `PyErr` value
|
||||
/// Represents a `PyErr` value.
|
||||
///
|
||||
/// **CAUTION**
|
||||
/// **Caution:**
|
||||
///
|
||||
/// When you construct an instance of `PyErrValue`, we highly recommend to use `from_err_args`
|
||||
/// method. If you want to to construct `PyErrValue::ToArgs` directly, please do not forget to
|
||||
|
@ -69,13 +69,22 @@ impl PyErr {
|
|||
/// Creates a new PyErr of type `T`.
|
||||
///
|
||||
/// `value` can be:
|
||||
/// * a tuple: the exception instance will be created using python `T(*tuple)`
|
||||
/// * any other value: the exception instance will be created using python `T(value)`
|
||||
/// * a tuple: the exception instance will be created using Python `T(*tuple)`
|
||||
/// * any other value: the exception instance will be created using Python `T(value)`
|
||||
///
|
||||
/// Panics if `T` is not a python class derived from `BaseException`.
|
||||
/// Panics if `T` is not a Python class derived from `BaseException`.
|
||||
///
|
||||
/// Example:
|
||||
/// `return Err(PyErr::new::<exceptions::TypeError, _>("Error message"));`
|
||||
/// ```ignore
|
||||
/// return Err(PyErr::new::<exceptions::TypeError, _>("Error message"));
|
||||
/// ```
|
||||
///
|
||||
/// In most cases, you can use a concrete exception's constructors instead:
|
||||
/// the example is equivalent to
|
||||
/// ```ignore
|
||||
/// return Err(exceptions::TypeError::py_err("Error message"));
|
||||
/// return exceptions::TypeError::into("Error message");
|
||||
/// ```
|
||||
pub fn new<T, V>(value: V) -> PyErr
|
||||
where
|
||||
T: PyTypeObject,
|
||||
|
@ -91,7 +100,8 @@ impl PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct a new error, with the usual lazy initialization of Python exceptions.
|
||||
/// Constructs a new error, with the usual lazy initialization of Python exceptions.
|
||||
///
|
||||
/// `exc` is the exception type; usually one of the standard exceptions
|
||||
/// like `exceptions::RuntimeError`.
|
||||
/// `args` is the a tuple of arguments to pass to the exception constructor.
|
||||
|
@ -158,6 +168,7 @@ impl PyErr {
|
|||
}
|
||||
|
||||
/// Retrieves the current error from the Python interpreter's global state.
|
||||
///
|
||||
/// The error is cleared from the Python interpreter.
|
||||
/// If no error is set, returns a `SystemError`.
|
||||
pub fn fetch(_: Python) -> PyErr {
|
||||
|
@ -232,19 +243,21 @@ impl PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Print a standard traceback to sys.stderr.
|
||||
/// Prints a standard traceback to `sys.stderr`.
|
||||
pub fn print(self, py: Python) {
|
||||
self.restore(py);
|
||||
unsafe { ffi::PyErr_PrintEx(0) }
|
||||
}
|
||||
|
||||
/// Print a standard traceback to sys.stderr.
|
||||
/// Prints a standard traceback to `sys.stderr`, and sets
|
||||
/// `sys.last_{type,value,traceback}` attributes to this exception's data.
|
||||
pub fn print_and_set_sys_last_vars(self, py: Python) {
|
||||
self.restore(py);
|
||||
unsafe { ffi::PyErr_PrintEx(1) }
|
||||
}
|
||||
|
||||
/// Return true if the current exception matches the exception in `exc`.
|
||||
/// Returns true if the current exception matches the exception in `exc`.
|
||||
///
|
||||
/// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass.
|
||||
/// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
|
||||
pub fn matches<T>(&self, py: Python, exc: T) -> bool
|
||||
|
@ -256,7 +269,7 @@ impl PyErr {
|
|||
})
|
||||
}
|
||||
|
||||
/// Return true if the current exception is instance of `T`
|
||||
/// Returns true if the current exception is instance of `T`.
|
||||
pub fn is_instance<T>(&self, _py: Python) -> bool
|
||||
where
|
||||
T: PyTypeObject,
|
||||
|
@ -277,8 +290,8 @@ impl PyErr {
|
|||
// This is safe as long as normalized() doesn't unwind due to a panic.
|
||||
}
|
||||
|
||||
/// Helper function for normalizing the error by deconstructing and reconstructing the PyErr.
|
||||
/// Must not panic for safety in normalize()
|
||||
/// Helper function for normalizing the error by deconstructing and reconstructing the `PyErr`.
|
||||
/// Must not panic for safety in `normalize()`.
|
||||
fn into_normalized(self, py: Python) -> PyErr {
|
||||
let PyErr {
|
||||
ptype,
|
||||
|
@ -302,6 +315,7 @@ impl PyErr {
|
|||
}
|
||||
|
||||
/// Retrieves the exception instance for this error.
|
||||
///
|
||||
/// This method takes `mut self` because the error might need
|
||||
/// to be normalized in order to create the exception instance.
|
||||
fn instance(mut self, py: Python) -> PyObject {
|
||||
|
@ -345,8 +359,8 @@ impl PyErr {
|
|||
-1
|
||||
}
|
||||
|
||||
/// Issue a warning message.
|
||||
/// May return a PyErr if warnings-as-errors is enabled.
|
||||
/// Issues a warning message.
|
||||
/// May return a `PyErr` if warnings-as-errors is enabled.
|
||||
pub fn warn(py: Python, category: &PyAny, message: &str, stacklevel: i32) -> PyResult<()> {
|
||||
let message = CString::new(message)?;
|
||||
unsafe {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
//! Exception types defined by python.
|
||||
//! Exception types defined by Python.
|
||||
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
|
@ -12,7 +12,7 @@ use std::ffi::CStr;
|
|||
use std::ops;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
/// The boilerplate to convert between a rust type and a python exception
|
||||
/// The boilerplate to convert between a Rust type and a Python exception.
|
||||
#[macro_export]
|
||||
macro_rules! impl_exception_boilerplate {
|
||||
($name: ident) => {
|
||||
|
@ -40,11 +40,11 @@ macro_rules! impl_exception_boilerplate {
|
|||
};
|
||||
}
|
||||
|
||||
/// Defines rust type for exception defined in Python code.
|
||||
/// Defines a Rust type for an exception defined in Python code.
|
||||
///
|
||||
/// # Syntax
|
||||
///
|
||||
/// `import_exception!(module, MyError)`
|
||||
/// ```import_exception!(module, MyError)```
|
||||
///
|
||||
/// * `module` is the name of the containing module.
|
||||
/// * `MyError` is the name of the new exception type.
|
||||
|
@ -83,8 +83,8 @@ macro_rules! import_exception {
|
|||
};
|
||||
}
|
||||
|
||||
/// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an exception defined in python
|
||||
/// code.
|
||||
/// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an
|
||||
/// exception defined in Python code.
|
||||
#[macro_export]
|
||||
macro_rules! import_exception_type_object {
|
||||
($module: expr, $name: ident) => {
|
||||
|
@ -120,11 +120,12 @@ macro_rules! import_exception_type_object {
|
|||
/// Defines a new exception type.
|
||||
///
|
||||
/// # Syntax
|
||||
/// `create_exception!(module, MyError, BaseException)`
|
||||
///
|
||||
/// ```create_exception!(module, MyError, BaseException)```
|
||||
///
|
||||
/// * `module` is the name of the containing module.
|
||||
/// * `MyError` is the name of the new exception type.
|
||||
/// * `BaseException` is the superclass of MyError, usually `pyo3::exceptions::Exception`
|
||||
/// * `BaseException` is the superclass of `MyError`, usually `pyo3::exceptions::Exception`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
|
@ -166,8 +167,8 @@ macro_rules! create_exception {
|
|||
};
|
||||
}
|
||||
|
||||
/// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an exception newly defined in
|
||||
/// rust code.
|
||||
/// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an
|
||||
/// exception newly defined in Rust code.
|
||||
#[macro_export]
|
||||
macro_rules! create_exception_type_object {
|
||||
($module: ident, $name: ident, $base: ty) => {
|
||||
|
|
|
@ -13,19 +13,27 @@ use std::marker::PhantomData;
|
|||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Types that are built into the python interpreter.
|
||||
/// Types that are built into the Python interpreter.
|
||||
///
|
||||
/// pyo3 is designed in a way that that all references to those types are bound to the GIL,
|
||||
/// which is why you can get a token from all references of those types.
|
||||
/// PyO3 is designed in a way that all references to those types are bound
|
||||
/// to the GIL, which is why you can get a token from all references of those
|
||||
/// types.
|
||||
pub unsafe trait PyNativeType: Sized {
|
||||
fn py(&self) -> Python {
|
||||
unsafe { Python::assume_gil_acquired() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer with specified type information.
|
||||
/// A Python object of known type.
|
||||
///
|
||||
/// `Py<T>` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
/// Accessing this object is thread-safe, since any access to its API requires a
|
||||
/// `Python<'py>` GIL token.
|
||||
///
|
||||
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation
|
||||
/// of the different Python object types.
|
||||
///
|
||||
/// Technically, it is a safe wrapper around `NonNull<ffi::PyObject>` with
|
||||
/// specified type information.
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);
|
||||
|
@ -52,6 +60,7 @@ impl<T> Py<T> {
|
|||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given FFI pointer.
|
||||
///
|
||||
/// This moves ownership over the pointer into the `Py<T>`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
|
@ -64,7 +73,8 @@ impl<T> Py<T> {
|
|||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given FFI pointer.
|
||||
/// Panics if the pointer is `null`.
|
||||
///
|
||||
/// Panics if the pointer is NULL.
|
||||
/// Undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
|
@ -77,8 +87,9 @@ impl<T> Py<T> {
|
|||
}
|
||||
|
||||
/// Construct `Py<T>` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
///
|
||||
/// Returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
|
||||
match NonNull::new(ptr) {
|
||||
|
@ -88,7 +99,8 @@ impl<T> Py<T> {
|
|||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
///
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
|
@ -100,21 +112,21 @@ impl<T> Py<T> {
|
|||
Py(NonNull::new_unchecked(ptr), PhantomData)
|
||||
}
|
||||
|
||||
/// Gets the reference count of the ffi::PyObject pointer.
|
||||
/// Gets the reference count of the `ffi::PyObject` pointer.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
/// Clones self by calling `Py_INCREF()` on the ptr.
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> Py<T> {
|
||||
unsafe { Py::from_borrowed_ptr(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Returns the inner pointer without decreasing the refcount
|
||||
/// Returns the inner pointer without decreasing the refcount.
|
||||
///
|
||||
/// This will eventually move into its own trait
|
||||
/// This will eventually move into its own trait.
|
||||
pub(crate) fn into_non_null(self) -> NonNull<ffi::PyObject> {
|
||||
let pointer = self.0;
|
||||
mem::forget(self);
|
||||
|
@ -122,7 +134,7 @@ impl<T> Py<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Retrives `&'py` types from `Py<T>` or `PyObject`.
|
||||
/// Retrieves `&'py` types from `Py<T>` or `PyObject`.
|
||||
///
|
||||
/// # Examples
|
||||
/// `PyObject::as_ref` returns `&PyAny`.
|
||||
|
@ -138,6 +150,7 @@ impl<T> Py<T> {
|
|||
/// let py = gil.python();
|
||||
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0); // PyAny implements ObjectProtocol
|
||||
/// ```
|
||||
///
|
||||
/// `Py<T>::as_ref` returns `&PyDict`, `&PyList` or so for native types, and `&PyCell<T>`
|
||||
/// for `#[pyclass]`.
|
||||
/// ```
|
||||
|
@ -177,8 +190,8 @@ impl<T> ToPyObject for Py<T> {
|
|||
}
|
||||
|
||||
impl<T> IntoPy<PyObject> for Py<T> {
|
||||
/// Converts `Py` instance -> PyObject.
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
/// Converts a `Py` instance to `PyObject`.
|
||||
/// Consumes `self` without calling `Py_DECREF()`.
|
||||
#[inline]
|
||||
fn into_py(self, _py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_not_null(self.into_non_null()) }
|
||||
|
@ -297,12 +310,12 @@ where
|
|||
|
||||
/// Reference to a converted [ToPyObject].
|
||||
///
|
||||
/// Many methods want to take anything that can be converted into a python object. This type
|
||||
/// takes care of both types types that are already python object (i.e. implement
|
||||
/// Many methods want to take anything that can be converted into a Python object. This type
|
||||
/// takes care of both types types that are already Python object (i.e. implement
|
||||
/// [AsPyPointer]) and those that don't (i.e. [ToPyObject] types).
|
||||
/// For the [AsPyPointer] types, we just use the borrowed pointer, which is a lot faster
|
||||
/// and simpler than creating a new extra object. The remaning [ToPyObject] types are
|
||||
/// converted to python objects, the owned pointer is stored and decref'd on drop.
|
||||
/// converted to Python objects, the owned pointer is stored and decref'd on drop.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -326,7 +339,7 @@ pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
|
|||
}
|
||||
|
||||
/// This should eventually be replaced with a generic `IntoPy` trait impl by figuring
|
||||
/// out the correct lifetime annotation to make the compiler happy
|
||||
/// out the correct lifetime annotation to make the compiler happy.
|
||||
impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
|
||||
pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
|
||||
to_pyobject.to_managed_py_ref(py)
|
||||
|
@ -339,16 +352,16 @@ impl<'p, T: ToPyObject> AsPyPointer for ManagedPyRef<'p, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper trait to choose the right implementation for [ManagedPyRef]
|
||||
/// Helper trait to choose the right implementation for [ManagedPyRef].
|
||||
pub trait ManagedPyRefDispatch: ToPyObject {
|
||||
/// Optionally converts into a python object and stores the pointer to the python heap.
|
||||
/// Optionally converts into a Python object and stores the pointer to the python heap.
|
||||
fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self>;
|
||||
|
||||
/// Dispatch over a xdecref and a noop drop impl
|
||||
fn drop_impl(borrowed: &mut ManagedPyRef<Self>);
|
||||
}
|
||||
|
||||
/// Case 1: It's a rust object which still needs to be converted to a python object.
|
||||
/// Case 1: It's a Rust object which still needs to be converted to a Python object.
|
||||
/// This means we're storing the owned pointer that into_ptr() has given us
|
||||
/// and therefore need to xdecref when we're done.
|
||||
///
|
||||
|
@ -370,7 +383,7 @@ impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {
|
|||
}
|
||||
}
|
||||
|
||||
/// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
|
||||
/// Case 2: It's an object on the Python heap, we're just storing a borrowed pointer.
|
||||
/// The object we're getting is an owned pointer, it might have it's own drop impl.
|
||||
impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
|
||||
/// Use AsPyPointer to copy the pointer and store it as borrowed pointer
|
||||
|
|
65
src/lib.rs
65
src/lib.rs
|
@ -7,23 +7,26 @@
|
|||
//!
|
||||
//! # 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 of
|
||||
//! Rust mutability does not apply to Python objects. As a result, PyO3 allows
|
||||
//! mutating Python objects even if they are not stored in a mutable Rust
|
||||
//! variable.
|
||||
//!
|
||||
//! 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
|
||||
//! in a mutable Rust variable.
|
||||
//! In Python, all objects are implicitly reference counted. The Python
|
||||
//! interpreter uses a global interpreter lock (GIL) to ensure thread-safety.
|
||||
//! Thus, we use `struct Python<'py>` as a token to indicate that
|
||||
//! a function can assume that the GIL is held. In Rust, we use different types
|
||||
//! to represent a reference to a Python object, depending on whether we know
|
||||
//! the GIL is held, and depending on whether we know the underlying type. See
|
||||
//! [the guide](https://pyo3.rs/master/types.html) for an explanation of
|
||||
//! the different Python object types.
|
||||
//!
|
||||
//! The Python interpreter uses a global interpreter lock (GIL)
|
||||
//! to ensure thread-safety.
|
||||
//! This API uses a zero-sized `struct Python<'p>` as a token to indicate
|
||||
//! that a function can assume that the GIL is held.
|
||||
//!
|
||||
//! You obtain a `Python` instance by acquiring the GIL,
|
||||
//! and have to pass it into all operations that call into the Python runtime.
|
||||
//! A `Python` instance is either obtained explicitly by acquiring the GIL,
|
||||
//! or implicitly by PyO3 when it generates the wrapper code for Rust functions
|
||||
//! and structs wrapped as Python functions and objects.
|
||||
//!
|
||||
//! # Error Handling
|
||||
//!
|
||||
//! The vast majority of operations in this library will return `PyResult<...>`.
|
||||
//! This is an alias for the type `Result<..., PyErr>`.
|
||||
//!
|
||||
|
@ -32,9 +35,9 @@
|
|||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ## Using rust from python
|
||||
//! ## Using Rust from Python
|
||||
//!
|
||||
//! Pyo3 can be used to generate a native python module.
|
||||
//! PyO3 can be used to generate a native Python module.
|
||||
//!
|
||||
//! **`Cargo.toml`**
|
||||
//!
|
||||
|
@ -60,13 +63,13 @@
|
|||
//! use pyo3::wrap_pyfunction;
|
||||
//!
|
||||
//! #[pyfunction]
|
||||
//! /// Formats the sum of two numbers as string
|
||||
//! /// Formats the sum of two numbers as string.
|
||||
//! fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
|
||||
//! Ok((a + b).to_string())
|
||||
//! }
|
||||
//!
|
||||
//! /// This module is a python module implemented in Rust.
|
||||
//! #[pymodule]
|
||||
//! /// A Python module implemented in Rust.
|
||||
//! fn string_sum(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
//! m.add_wrapped(wrap_pyfunction!(sum_as_string))?;
|
||||
//!
|
||||
|
@ -74,7 +77,11 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! On windows and linux, you can build normally with `cargo build --release`. On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||
//! On Windows and linux, you can build normally with `cargo build
|
||||
//! --release`. On macOS, you need to set additional linker arguments. One
|
||||
//! option is to compile with `cargo rustc --release -- -C link-arg=-undefined
|
||||
//! -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with
|
||||
//! the following content:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [target.x86_64-apple-darwin]
|
||||
|
@ -84,13 +91,21 @@
|
|||
//! ]
|
||||
//! ```
|
||||
//!
|
||||
//! For developing, you can copy and rename the shared library from the target folder: On macOS, rename `libstring_sum.dylib` to `string_sum.so`, on windows `libstring_sum.dll` to `string_sum.pyd` and on linux `libstring_sum.so` to `string_sum.so`. Then open a python shell in the same folder and you'll be able to `import string_sum`.
|
||||
//! While developing, you symlink (or copy) and rename the shared library from
|
||||
//! the target folder: On macOS, rename `libstring_sum.dylib` to
|
||||
//! `string_sum.so`, on Windows `libstring_sum.dll` to `string_sum.pyd` and on
|
||||
//! Linux `libstring_sum.so` to `string_sum.so`. Then open a Python shell in the
|
||||
//! same folder and you'll be able to `import string_sum`.
|
||||
//!
|
||||
//! To build, test and publish your crate as python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while maturin should work on your crate without any configuration.
|
||||
//! To build, test and publish your crate as a Python module, you can use
|
||||
//! [maturin](https://github.com/PyO3/maturin) or
|
||||
//! [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an
|
||||
//! example for setuptools-rust in [examples/word-count](examples/word-count),
|
||||
//! while maturin should work on your crate without any configuration.
|
||||
//!
|
||||
//! ## Using python from rust
|
||||
//! ## Using Python from Rust
|
||||
//!
|
||||
//! Add `pyo3` this to your `Cargo.toml`:
|
||||
//! Add `pyo3` to your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
|
@ -180,14 +195,14 @@ mod python;
|
|||
pub mod type_object;
|
||||
pub mod types;
|
||||
|
||||
/// The proc macros, which are also part of the prelude
|
||||
/// The proc macros, which are also part of the prelude.
|
||||
pub mod proc_macro {
|
||||
pub use pyo3cls::pymodule;
|
||||
/// The proc macro attributes
|
||||
pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto};
|
||||
}
|
||||
|
||||
/// Returns a function that takes a [Python] instance and returns a python function.
|
||||
/// Returns a function that takes a [Python] instance and returns a Python function.
|
||||
///
|
||||
/// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped].
|
||||
#[macro_export]
|
||||
|
@ -197,7 +212,7 @@ macro_rules! wrap_pyfunction {
|
|||
}};
|
||||
}
|
||||
|
||||
/// Returns a function that takes a [Python] instance and returns a python module.
|
||||
/// Returns a function that takes a [Python] instance and returns a Python module.
|
||||
///
|
||||
/// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped].
|
||||
#[macro_export]
|
||||
|
|
|
@ -8,11 +8,11 @@ pub const VERSION: i32 = 4;
|
|||
|
||||
/// Serialize an object to bytes using the Python built-in marshal module.
|
||||
///
|
||||
/// The built-in marshalling only supports a limited range of object.
|
||||
/// The built-in marshalling only supports a limited range of objects.
|
||||
/// The exact types supported depend on the version argument.
|
||||
/// The [`VERSION`] constant holds the highest version currently supported.
|
||||
///
|
||||
/// See the [python documentation](https://docs.python.org/3/library/marshal.html) for more details.
|
||||
/// See the [Python documentation](https://docs.python.org/3/library/marshal.html) for more details.
|
||||
///
|
||||
/// # Example:
|
||||
/// ```
|
||||
|
|
|
@ -9,17 +9,20 @@ use crate::{AsPyPointer, Py, Python};
|
|||
use crate::{FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, ToBorrowedObject, ToPyObject};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// A python object
|
||||
/// A Python object of any type.
|
||||
///
|
||||
/// The python object's lifetime is managed by python's garbage
|
||||
/// collector.
|
||||
/// The Python object's lifetime is managed by Python's garbage collector,
|
||||
/// so to access the object API, a `Python<'py>` GIL token is required.
|
||||
///
|
||||
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation
|
||||
/// of the different Python object types.
|
||||
///
|
||||
/// Technically, it is a safe wrapper around `NonNull<ffi::PyObject>`.
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyObject(NonNull<ffi::PyObject>);
|
||||
|
||||
// `PyObject` is thread-safe, any python related operations require a Python<'p> token.
|
||||
// `PyObject` is thread-safe, any Python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PyObject {}
|
||||
unsafe impl Sync for PyObject {}
|
||||
|
||||
|
@ -48,7 +51,7 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given FFI pointer.
|
||||
/// Panics if the pointer is `null`.
|
||||
/// Panics if the pointer is NULL.
|
||||
/// Undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
|
@ -60,9 +63,9 @@ impl PyObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct `PyObject` from the result of a Python FFI call that
|
||||
/// Constructs a `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.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Ok(PyObject(nonnull_ptr)),
|
||||
|
@ -70,9 +73,9 @@ impl PyObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct `PyObject` from the result of a Python FFI call that
|
||||
/// Constructs a `PyObject` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Some(PyObject(nonnull_ptr)),
|
||||
|
@ -81,7 +84,7 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
|
@ -94,8 +97,8 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
pub unsafe fn from_borrowed_ptr_or_err(
|
||||
py: Python,
|
||||
ptr: *mut ffi::PyObject,
|
||||
|
@ -108,8 +111,8 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
pub unsafe fn from_borrowed_ptr_or_opt(
|
||||
py: Python,
|
||||
ptr: *mut ffi::PyObject,
|
||||
|
@ -126,19 +129,21 @@ impl PyObject {
|
|||
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
/// Clones self by calling `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'
|
||||
///
|
||||
/// This is equivalent to the Python expression `self is None`.
|
||||
pub fn is_none(&self) -> bool {
|
||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be true.
|
||||
/// This is equivalent to the Python expression: 'not not self'
|
||||
///
|
||||
/// This is equivalent to the Python expression `bool(self)`.
|
||||
pub fn is_true(&self, py: Python) -> PyResult<bool> {
|
||||
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
|
@ -149,6 +154,8 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
///
|
||||
/// This can cast only to native Python types, not types implemented in Rust.
|
||||
pub fn cast_as<'p, D>(&'p self, py: Python<'p>) -> Result<&'p D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<'p>,
|
||||
|
@ -157,6 +164,7 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
///
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
pub fn extract<'p, D>(&'p self, py: Python<'p>) -> PyResult<D>
|
||||
where
|
||||
|
@ -166,7 +174,8 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Retrieves an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name'.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.attr_name`.
|
||||
pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
|
||||
where
|
||||
N: ToPyObject,
|
||||
|
@ -177,7 +186,8 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
///
|
||||
/// This is equivalent to the Python expression `self(*args, **kwargs)`.
|
||||
pub fn call(
|
||||
&self,
|
||||
py: Python,
|
||||
|
@ -196,20 +206,23 @@ impl PyObject {
|
|||
result
|
||||
}
|
||||
|
||||
/// Calls the object without arguments.
|
||||
/// This is equivalent to the Python expression: 'self()'
|
||||
pub fn call0(&self, py: Python) -> PyResult<PyObject> {
|
||||
self.call(py, (), None)
|
||||
}
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args)'
|
||||
/// Calls the object with only positional arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self(*args)`.
|
||||
pub fn call1(&self, py: Python, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> {
|
||||
self.call(py, args, None)
|
||||
}
|
||||
|
||||
/// Calls the object without arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self()`.
|
||||
pub fn call0(&self, py: Python) -> PyResult<PyObject> {
|
||||
self.call(py, (), None)
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name(*args, **kwargs)`.
|
||||
pub fn call_method(
|
||||
&self,
|
||||
py: Python,
|
||||
|
@ -232,14 +245,9 @@ impl PyObject {
|
|||
})
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name()'
|
||||
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> {
|
||||
self.call_method(py, name, (), None)
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args)'
|
||||
/// Calls a method on the object with only positional arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name(*args)`.
|
||||
pub fn call_method1(
|
||||
&self,
|
||||
py: Python,
|
||||
|
@ -248,6 +256,13 @@ impl PyObject {
|
|||
) -> PyResult<PyObject> {
|
||||
self.call_method(py, name, args, None)
|
||||
}
|
||||
|
||||
/// Calls a method on the object with no arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name()`.
|
||||
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> {
|
||||
self.call_method(py, name, (), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsPyRef for PyObject {
|
||||
|
@ -284,7 +299,7 @@ impl IntoPyPointer for PyObject {
|
|||
}
|
||||
|
||||
impl PartialEq for PyObject {
|
||||
/// Checks for identity, not python's `__eq__`
|
||||
/// Checks for pointer identity, not equivalent to Python's `__eq__`.
|
||||
#[inline]
|
||||
fn eq(&self, o: &PyObject) -> bool {
|
||||
self.0 == o.0
|
||||
|
|
|
@ -14,18 +14,21 @@ use std::os::raw::c_int;
|
|||
/// Python object model helper methods
|
||||
pub trait ObjectProtocol {
|
||||
/// Determines whether this object has the given attribute.
|
||||
///
|
||||
/// This is equivalent to the Python expression `hasattr(self, attr_name)`.
|
||||
fn hasattr<N>(&self, 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<&PyAny>
|
||||
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
|
||||
|
@ -33,6 +36,7 @@ pub trait ObjectProtocol {
|
|||
V: ToBorrowedObject;
|
||||
|
||||
/// Deletes an attribute.
|
||||
///
|
||||
/// This is equivalent to the Python expression `del self.attr_name`.
|
||||
fn delattr<N>(&self, attr_name: N) -> PyResult<()>
|
||||
where
|
||||
|
@ -57,7 +61,8 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Compares two Python objects.
|
||||
///
|
||||
/// Depending on the value of `compare_op`, equivalent to one of the following Python expressions:
|
||||
/// Depending on the value of `compare_op`, this is equivalent to one of the
|
||||
/// following Python expressions:
|
||||
/// * CompareOp::Eq: `self == other`
|
||||
/// * CompareOp::Ne: `self != other`
|
||||
/// * CompareOp::Lt: `self < other`
|
||||
|
@ -68,11 +73,13 @@ pub trait ObjectProtocol {
|
|||
where
|
||||
O: ToPyObject;
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// Computes the "repr" representation of self.
|
||||
///
|
||||
/// This is equivalent to the Python expression `repr(self)`.
|
||||
fn repr(&self) -> PyResult<&PyString>;
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// Computes the "str" representation of self.
|
||||
///
|
||||
/// This is equivalent to the Python expression `str(self)`.
|
||||
fn str(&self) -> PyResult<&PyString>;
|
||||
|
||||
|
@ -80,19 +87,23 @@ pub trait ObjectProtocol {
|
|||
fn is_callable(&self) -> bool;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self(*args, **kwargs)`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self(*args, **kwargs)`.
|
||||
fn call(&self, args: impl IntoPy<Py<PyTuple>>, kwargs: Option<&PyDict>) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self()`.
|
||||
fn call0(&self) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self(*args)`.
|
||||
/// Calls the object with only positional arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self(*args)`.
|
||||
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls the object without arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self()`.
|
||||
fn call0(&self) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: `self.name(*args, **kwargs)`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name(*args, **kwargs)`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
|
@ -113,77 +124,92 @@ pub trait ObjectProtocol {
|
|||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: `self.name()`.
|
||||
fn call_method0(&self, name: &str) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls a method on the object with positional arguments only.
|
||||
/// This is equivalent to the Python expression: `self.name(*args)`.
|
||||
/// Calls a method on the object with only positional arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name(*args)`.
|
||||
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>;
|
||||
|
||||
/// Calls a method on the object without arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.name()`.
|
||||
fn call_method0(&self, name: &str) -> PyResult<&PyAny>;
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: `hash(self)`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `hash(self)`.
|
||||
fn hash(&self) -> PyResult<isize>;
|
||||
|
||||
/// Returns whether the object is considered to be true.
|
||||
/// This is equivalent to the Python expression: `not not self`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `bool(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`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self is None`.
|
||||
fn is_none(&self) -> bool;
|
||||
|
||||
/// Returns the length of the sequence or mapping.
|
||||
/// This is equivalent to the Python expression: `len(self)`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `len(self)`.
|
||||
fn len(&self) -> PyResult<usize>;
|
||||
|
||||
/// Returns true if the sequence or mapping has a length of 0.
|
||||
/// This is equivalent to the Python expression: `len(self) == 0`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `len(self) == 0`.
|
||||
fn is_empty(&self) -> PyResult<bool>;
|
||||
|
||||
/// This is equivalent to the Python expression: `self[key]`.
|
||||
/// Gets an item from the collections.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self[key]`.
|
||||
fn get_item<K>(&self, key: K) -> PyResult<&PyAny>
|
||||
where
|
||||
K: ToBorrowedObject;
|
||||
|
||||
/// Sets an item value.
|
||||
/// Sets a collection 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: ToBorrowedObject,
|
||||
V: ToBorrowedObject;
|
||||
|
||||
/// Deletes an item.
|
||||
/// Deletes an item from the collection.
|
||||
///
|
||||
/// This is equivalent to the Python expression `del self[key]`.
|
||||
fn del_item<K>(&self, key: K) -> PyResult<()>
|
||||
where
|
||||
K: ToBorrowedObject;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// This is typically a new iterator but if the argument is an iterator,
|
||||
/// this returns itself.
|
||||
fn iter(&self) -> PyResult<PyIterator>;
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
/// Returns the Python type object for this object's type.
|
||||
fn get_type(&self) -> &PyType;
|
||||
|
||||
/// Gets the Python type pointer for this object.
|
||||
/// Returns the Python type pointer for this object.
|
||||
fn get_type_ptr(&self) -> *mut ffi::PyTypeObject;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
///
|
||||
/// This can cast only to native Python types, not types implemented in Rust.
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<'a>,
|
||||
&'a PyAny: std::convert::From<&'a Self>;
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
///
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
fn extract<'a, D>(&'a self) -> PyResult<D>
|
||||
where
|
||||
D: FromPyObject<'a>,
|
||||
&'a PyAny: std::convert::From<&'a Self>;
|
||||
|
||||
/// Returns reference count for python object.
|
||||
/// Returns the reference count for the Python object.
|
||||
fn get_refcnt(&self) -> isize;
|
||||
|
||||
/// Gets the Python builtin value `None`.
|
||||
|
|
103
src/python.rs
103
src/python.rs
|
@ -20,30 +20,31 @@ pub use gil::prepare_freethreaded_python;
|
|||
|
||||
/// 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-sized marker struct that is required for most Python operations.
|
||||
/// 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
|
||||
/// Python global interpreter lock (GIL) is acquired. The lifetime `'p` represents the lifetime of
|
||||
/// the Python interpreter.
|
||||
/// holding the lock.
|
||||
///
|
||||
/// Note that the GIL can be temporarily released by the python interpreter during a function call
|
||||
/// Note that the GIL can be temporarily released by the Python interpreter during a function call
|
||||
/// (e.g. importing a module), even when you're holding a GILGuard. In general, you don't need to
|
||||
/// worry about this becauseas the GIL is reaquired before returning to the rust code:
|
||||
/// worry about this because the GIL is reacquired before returning to the Rust code:
|
||||
///
|
||||
/// ```text
|
||||
/// GILGuard |=====================================|
|
||||
/// `Python` exists |=====================================|
|
||||
/// GIL actually held |==========| |================|
|
||||
/// Rust code running |=======| |==| |======|
|
||||
/// ```
|
||||
///
|
||||
/// This behaviour can cause deadlocks when trying to lock while holding a GILGuard:
|
||||
/// This behaviour can cause deadlocks when trying to lock a Rust mutex while
|
||||
/// holding the GIL:
|
||||
///
|
||||
/// * Thread 1 acquires the GIL
|
||||
/// * Thread 1 locks a mutex
|
||||
/// * Thread 1 makes a call into the python interpreter, which releases the GIL
|
||||
/// * Thread 1 makes a call into the Python interpreter which releases the GIL
|
||||
/// * Thread 2 acquires the GIL
|
||||
/// * Thread 2 tries to locks the mutex, blocks
|
||||
/// * Thread 1's python interpreter call blocks trying to reacquire the GIL held by thread 2
|
||||
/// * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2
|
||||
///
|
||||
/// To avoid deadlocking, you should release the GIL before trying to lock a mutex, e.g. with
|
||||
/// [Python::allow_threads].
|
||||
|
@ -51,8 +52,8 @@ pub use gil::prepare_freethreaded_python;
|
|||
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
|
||||
/// and stays acquired for the lifetime `'p`.
|
||||
/// Retrieves a Python instance under the assumption that the GIL is already
|
||||
/// acquired at this point, and stays acquired for the lifetime `'p`.
|
||||
///
|
||||
/// Because the output lifetime `'p` is not connected to any input parameter,
|
||||
/// care must be taken that the compiler infers an appropriate lifetime for `'p`
|
||||
|
@ -105,8 +106,16 @@ impl<'p> Python<'p> {
|
|||
/// "#, None, Some(locals));
|
||||
/// ```
|
||||
///
|
||||
/// **NOTE**
|
||||
/// You cannot use all `&Py~` types in the closure that `allow_threads` takes.
|
||||
/// **Note:**
|
||||
/// PyO3 types that represent objects with a lifetime tied to holding the GIL
|
||||
/// cannot be used in the closure. This includes `&PyAny` and all the
|
||||
/// concrete-typed siblings, like `&PyString`.
|
||||
///
|
||||
/// You can convert such references to e.g. `PyObject` or `Py<PyString>`,
|
||||
/// which makes them independent of the GIL lifetime. However, you cannot
|
||||
/// do much with those without a `Python<'p>` token, for which you'd need to
|
||||
/// reacquire the GIL.
|
||||
///
|
||||
/// # Example
|
||||
/// ```compile_fail
|
||||
/// # use pyo3::prelude::*;
|
||||
|
@ -114,10 +123,9 @@ impl<'p> Python<'p> {
|
|||
/// fn parallel_print(py: Python<'_>) {
|
||||
/// let s = PyString::new(py, "This object should not be shared >_<");
|
||||
/// py.allow_threads(move || {
|
||||
/// println!("{:?}", s); // This causes compile error.
|
||||
/// println!("{:?}", s); // This causes a compile error.
|
||||
/// });
|
||||
/// }
|
||||
/// # Example
|
||||
/// ```
|
||||
pub fn allow_threads<T, F>(self, f: F) -> T
|
||||
where
|
||||
|
@ -193,8 +201,9 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
/// Runs code in the given context.
|
||||
/// `start` indicates the type of input expected:
|
||||
/// one of `Py_single_input`, `Py_file_input`, or `Py_eval_input`.
|
||||
///
|
||||
/// `start` indicates the type of input expected: one of `Py_single_input`,
|
||||
/// `Py_file_input`, or `Py_eval_input`.
|
||||
///
|
||||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
|
@ -237,17 +246,21 @@ impl<'p> Python<'p> {
|
|||
unsafe { self.from_borrowed_ptr(T::type_object().into_ptr()) }
|
||||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
/// Imports the Python module with the specified name.
|
||||
pub fn import(self, name: &str) -> PyResult<&'p PyModule> {
|
||||
PyModule::import(self, name)
|
||||
}
|
||||
|
||||
/// Check whether `obj` is an instance of type `T` like Python `isinstance` function
|
||||
/// Checks whether `obj` is an instance of type `T`.
|
||||
///
|
||||
/// This is equivalent to the Python `isinstance` function.
|
||||
pub fn is_instance<T: PyTypeObject, V: AsPyPointer>(self, obj: &V) -> PyResult<bool> {
|
||||
T::type_object().as_ref(self).is_instance(obj)
|
||||
}
|
||||
|
||||
/// Check whether type `T` is subclass of type `U` like Python `issubclass` function
|
||||
/// Checks whether type `T` is subclass of type `U`.
|
||||
///
|
||||
/// This is equivalent to the Python `issubclass` function.
|
||||
pub fn is_subclass<T, U>(self) -> PyResult<bool>
|
||||
where
|
||||
T: PyTypeObject,
|
||||
|
@ -272,7 +285,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
/// Register object in release pool, and try to downcast to specific type.
|
||||
/// Registers the object in the release pool, and tries to downcast to specific type.
|
||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
|
||||
where
|
||||
T: PyTryFrom<'p>,
|
||||
|
@ -281,7 +294,8 @@ impl<'p> Python<'p> {
|
|||
<T as PyTryFrom>::try_from(obj)
|
||||
}
|
||||
|
||||
/// Register object in release pool, and do unchecked downcast to specific type.
|
||||
/// Registers the object in the release pool, and does an unchecked downcast
|
||||
/// to the specific type.
|
||||
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'p T
|
||||
where
|
||||
T: PyDowncastImpl + PyTypeInfo,
|
||||
|
@ -290,7 +304,7 @@ impl<'p> Python<'p> {
|
|||
T::unchecked_downcast(obj)
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool
|
||||
/// Registers the object pointer in the release pool.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyAny {
|
||||
match NonNull::new(ptr) {
|
||||
|
@ -299,8 +313,8 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool,
|
||||
/// and do unchecked downcast to specific type.
|
||||
/// Registers the object pointer in the release pool,
|
||||
/// and does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where
|
||||
|
@ -309,9 +323,10 @@ impl<'p> Python<'p> {
|
|||
FromPyPointer::from_owned_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register owned `ffi::PyObject` pointer in release pool.
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
/// Registers the owned object pointer in the release pool.
|
||||
///
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
/// Does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
|
||||
where
|
||||
|
@ -320,9 +335,10 @@ impl<'p> Python<'p> {
|
|||
FromPyPointer::from_owned_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
||||
/// Register owned `ffi::PyObject` pointer in release pool.
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
/// Registers the owned object pointer in release pool.
|
||||
///
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
/// Does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
|
||||
where
|
||||
|
@ -331,9 +347,10 @@ impl<'p> Python<'p> {
|
|||
FromPyPointer::from_owned_ptr_or_opt(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
/// Panics if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
/// Registers the borrowed object pointer in the release pool.
|
||||
///
|
||||
/// Panics if the pointer is NULL.
|
||||
/// Does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where
|
||||
|
@ -342,9 +359,10 @@ impl<'p> Python<'p> {
|
|||
FromPyPointer::from_borrowed_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
/// Registers the borrowed object pointer in the release pool.
|
||||
///
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
/// Does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
|
||||
where
|
||||
|
@ -353,9 +371,10 @@ impl<'p> Python<'p> {
|
|||
FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific `T`.
|
||||
/// Registers the borrowed object pointer in the release pool.
|
||||
///
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
/// Does an unchecked downcast to the specific type.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
|
||||
where
|
||||
|
@ -365,13 +384,13 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Pass value ownership to `Python` object and get reference back.
|
||||
/// Passes value ownership to `Python` object and get reference back.
|
||||
/// Value get cleaned up on the GIL release.
|
||||
pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
|
||||
unsafe { gil::register_any(ob) }
|
||||
}
|
||||
|
||||
/// Release PyObject reference.
|
||||
/// Releases a PyObject reference.
|
||||
#[inline]
|
||||
pub fn release<T>(self, ob: T)
|
||||
where
|
||||
|
@ -385,7 +404,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Release `ffi::PyObject` pointer.
|
||||
/// Releases a `ffi::PyObject` pointer.
|
||||
#[inline]
|
||||
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
|
||||
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };
|
||||
|
|
|
@ -47,10 +47,10 @@ pub unsafe trait PyBorrowFlagLayout<T: PyTypeInfo>: PyLayout<T> + Sized {}
|
|||
/// Our custom type flags
|
||||
#[doc(hidden)]
|
||||
pub mod type_flags {
|
||||
/// type object supports python GC
|
||||
/// Type object supports Python GC
|
||||
pub const GC: usize = 1;
|
||||
|
||||
/// Type object supports python weak references
|
||||
/// Type object supports Python weak references
|
||||
pub const WEAKREF: usize = 1 << 1;
|
||||
|
||||
/// Type object can be used as the base type of another type
|
||||
|
|
|
@ -3,12 +3,18 @@ use crate::err::PyDowncastError;
|
|||
use crate::internal_tricks::Unsendable;
|
||||
use crate::{ffi, PyObject};
|
||||
|
||||
/// Represents a python's [Any](https://docs.python.org/3/library/typing.html#typing.Any) type.
|
||||
/// We can convert all python objects as `PyAny`.
|
||||
/// A Python object with GIL lifetime
|
||||
///
|
||||
/// Represents any Python object. All Python objects can be cast to `PyAny`.
|
||||
/// In addition, if the inner object is an instance of type `T`, we can downcast
|
||||
/// `PyAny` into `T`.
|
||||
///
|
||||
/// `PyAny` is used as a reference with a lifetime that represents that the GIL
|
||||
/// is held, therefore its API does not require a `Python<'py>` token.
|
||||
///
|
||||
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation
|
||||
/// of the different Python object types.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -16,7 +16,7 @@ pub struct PyBool(PyObject, Unsendable);
|
|||
pyobject_native_type!(PyBool, ffi::PyObject, ffi::PyBool_Type, ffi::PyBool_Check);
|
||||
|
||||
impl PyBool {
|
||||
/// Depending on `val`, returns `py.True()` or `py.False()`.
|
||||
/// Depending on `val`, returns `true` or `false`.
|
||||
#[inline]
|
||||
pub fn new(py: Python, val: bool) -> &PyBool {
|
||||
unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) }
|
||||
|
@ -29,7 +29,7 @@ impl PyBool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a rust `bool` to a Python `bool`.
|
||||
/// Converts a Rust `bool` to a Python `bool`.
|
||||
impl ToPyObject for bool {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
|
@ -53,7 +53,7 @@ impl FromPy<bool> for PyObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a Python `bool` to a rust `bool`.
|
||||
/// Converts a Python `bool` to a Rust `bool`.
|
||||
///
|
||||
/// Fails with `TypeError` if the input is not a Python `bool`.
|
||||
impl<'source> FromPyObject<'source> for bool {
|
||||
|
|
|
@ -17,6 +17,7 @@ pyobject_native_var_type!(PyByteArray, ffi::PyByteArray_Type, ffi::PyByteArray_C
|
|||
|
||||
impl PyByteArray {
|
||||
/// Creates a new Python bytearray object.
|
||||
///
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
pub fn new<'p>(py: Python<'p>, src: &[u8]) -> &'p PyByteArray {
|
||||
let ptr = src.as_ptr() as *const c_char;
|
||||
|
@ -24,8 +25,8 @@ impl PyByteArray {
|
|||
unsafe { py.from_owned_ptr::<PyByteArray>(ffi::PyByteArray_FromStringAndSize(ptr, len)) }
|
||||
}
|
||||
|
||||
/// Creates a new Python bytearray object
|
||||
/// from other PyObject, that implements the buffer protocol.
|
||||
/// Creates a new Python bytearray object from another PyObject that
|
||||
/// implements the buffer protocol.
|
||||
pub fn from<'p, I>(py: Python<'p>, src: &'p I) -> PyResult<&'p PyByteArray>
|
||||
where
|
||||
I: AsPyPointer,
|
||||
|
@ -40,12 +41,12 @@ impl PyByteArray {
|
|||
unsafe { ffi::PyByteArray_Size(self.0.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Check if bytearray is empty.
|
||||
/// Checks if the bytearray is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Copies the contents of the bytearray to a rust vector
|
||||
/// Copies the contents of the bytearray to a Rust vector.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -75,7 +76,7 @@ impl PyByteArray {
|
|||
slice.to_vec()
|
||||
}
|
||||
|
||||
/// Resize bytearray object to `len`.
|
||||
/// Resizes the bytearray object to the new length `len`.
|
||||
pub fn resize(&self, len: usize) -> PyResult<()> {
|
||||
unsafe {
|
||||
let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t);
|
||||
|
|
|
@ -12,17 +12,17 @@ use std::os::raw::c_char;
|
|||
use std::slice::SliceIndex;
|
||||
use std::str;
|
||||
|
||||
/// Represents a Python `bytes`.
|
||||
/// Represents a Python `bytes` object.
|
||||
///
|
||||
/// This type is immutable
|
||||
/// This type is immutable.
|
||||
#[repr(transparent)]
|
||||
pub struct PyBytes(PyObject, Unsendable);
|
||||
|
||||
pyobject_native_var_type!(PyBytes, ffi::PyBytes_Type, ffi::PyBytes_Check);
|
||||
|
||||
impl PyBytes {
|
||||
/// Creates a new Python byte string object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
/// Creates a new Python bytestring object.
|
||||
/// The bytestring is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new<'p>(py: Python<'p>, s: &[u8]) -> &'p PyBytes {
|
||||
|
@ -31,7 +31,7 @@ impl PyBytes {
|
|||
unsafe { py.from_owned_ptr(ffi::PyBytes_FromStringAndSize(ptr, len)) }
|
||||
}
|
||||
|
||||
/// Creates a new Python byte string object from raw pointer.
|
||||
/// Creates a new Python byte string object from a raw pointer and length.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub unsafe fn from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> &PyBytes {
|
||||
|
@ -41,7 +41,7 @@ impl PyBytes {
|
|||
))
|
||||
}
|
||||
|
||||
/// Get the Python string as a byte slice.
|
||||
/// Gets the Python string as a byte slice.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
unsafe {
|
||||
|
@ -53,7 +53,7 @@ impl PyBytes {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is the same way [Vec] is indexed
|
||||
/// This is the same way [Vec] is indexed.
|
||||
impl<I: SliceIndex<[u8]>> Index<I> for PyBytes {
|
||||
type Output = I::Output;
|
||||
|
||||
|
|
|
@ -21,18 +21,18 @@ pyobject_native_type!(
|
|||
);
|
||||
|
||||
impl PyComplex {
|
||||
/// Creates a new Python `PyComplex` object, from its real and imaginary values.
|
||||
/// Creates a new Python `complex` object, from its real and imaginary values.
|
||||
pub fn from_doubles(py: Python, real: c_double, imag: c_double) -> &PyComplex {
|
||||
unsafe {
|
||||
let ptr = ffi::PyComplex_FromDoubles(real, imag);
|
||||
py.from_owned_ptr(ptr)
|
||||
}
|
||||
}
|
||||
/// Returns the real value of `PyComplex`.
|
||||
/// Returns the real part of the complex number.
|
||||
pub fn real(&self) -> c_double {
|
||||
unsafe { ffi::PyComplex_RealAsDouble(self.as_ptr()) }
|
||||
}
|
||||
/// Returns the imaginary value of `PyComplex`.
|
||||
/// Returns the imaginary part the complex number.
|
||||
pub fn imag(&self) -> c_double {
|
||||
unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) }
|
||||
}
|
||||
|
|
|
@ -51,8 +51,9 @@ impl PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return a new dictionary that contains the same key-value pairs as self.
|
||||
/// Corresponds to `dict(self)` in Python.
|
||||
/// Returns a new dictionary that contains the same key-value pairs as self.
|
||||
///
|
||||
/// This is equivalent to the Python expression `dict(self)`.
|
||||
pub fn copy(&self) -> PyResult<&PyDict> {
|
||||
unsafe {
|
||||
self.py()
|
||||
|
@ -60,23 +61,25 @@ impl PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
/// Empty an existing dictionary of all key-value pairs.
|
||||
/// Empties an existing dictionary of all key-value pairs.
|
||||
pub fn clear(&self) {
|
||||
unsafe { ffi::PyDict_Clear(self.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Return the number of items in the dictionary.
|
||||
/// This is equivalent to len(p) on a dictionary.
|
||||
///
|
||||
/// This is equivalent to the Python expression `len(self)`.
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::PyDict_Size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Check if dict is empty.
|
||||
/// Checks if the dict is empty, i.e. `len(self) == 0`.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Determine if the dictionary contains the specified key.
|
||||
/// Determines if the dictionary contains the specified key.
|
||||
///
|
||||
/// This is equivalent to the Python expression `key in self`.
|
||||
pub fn contains<K>(&self, key: K) -> PyResult<bool>
|
||||
where
|
||||
|
@ -92,7 +95,10 @@ impl PyDict {
|
|||
}
|
||||
|
||||
/// Gets an item from the dictionary.
|
||||
/// Returns None if the item is not present, or if an error occurs.
|
||||
///
|
||||
/// Returns `None` if the item is not present, or if an error occurs.
|
||||
///
|
||||
/// To get a `KeyError` for non-existing keys, use `ObjectProtocol::get_item`.
|
||||
pub fn get_item<K>(&self, key: K) -> Option<&PyAny>
|
||||
where
|
||||
K: ToBorrowedObject,
|
||||
|
@ -104,7 +110,8 @@ impl PyDict {
|
|||
}
|
||||
|
||||
/// Sets an item value.
|
||||
/// This is equivalent to the Python expression `self[key] = value`.
|
||||
///
|
||||
/// This is equivalent to the Python statement `self[key] = value`.
|
||||
pub fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||
where
|
||||
K: ToPyObject,
|
||||
|
@ -118,7 +125,8 @@ impl PyDict {
|
|||
}
|
||||
|
||||
/// Deletes an item.
|
||||
/// This is equivalent to the Python expression `del self[key]`.
|
||||
///
|
||||
/// This is equivalent to the Python statement `del self[key]`.
|
||||
pub fn del_item<K>(&self, key: K) -> PyResult<()>
|
||||
where
|
||||
K: ToBorrowedObject,
|
||||
|
@ -128,8 +136,9 @@ impl PyDict {
|
|||
})
|
||||
}
|
||||
|
||||
/// List of dict keys.
|
||||
/// This is equivalent to the python expression `list(dict.keys())`.
|
||||
/// Returns a list of dict keys.
|
||||
///
|
||||
/// This is equivalent to the Python expression `list(dict.keys())`.
|
||||
pub fn keys(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py()
|
||||
|
@ -137,8 +146,9 @@ impl PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
/// List of dict values.
|
||||
/// This is equivalent to the python expression `list(dict.values())`.
|
||||
/// Returns a list of dict values.
|
||||
///
|
||||
/// This is equivalent to the Python expression `list(dict.values())`.
|
||||
pub fn values(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py()
|
||||
|
@ -146,8 +156,9 @@ impl PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
/// List of dict items.
|
||||
/// This is equivalent to the python expression `list(dict.items())`.
|
||||
/// Returns a list of dict items.
|
||||
///
|
||||
/// This is equivalent to the Python expression `list(dict.items())`.
|
||||
pub fn items(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py()
|
||||
|
@ -155,9 +166,10 @@ impl PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a iterator of (key, value) pairs in this dictionary.
|
||||
/// Returns an iterator of `(key, value)` pairs in this dictionary.
|
||||
///
|
||||
/// Note that it's unsafe to use when the dictionary might be changed by other code.
|
||||
/// Note that it's unsafe to use when the dictionary might be changed by
|
||||
/// other code.
|
||||
pub fn iter(&self) -> PyDictIterator {
|
||||
PyDictIterator {
|
||||
dict: self.as_ref(),
|
||||
|
|
|
@ -9,10 +9,10 @@ use crate::types::PyAny;
|
|||
use crate::AsPyPointer;
|
||||
use crate::Python;
|
||||
|
||||
/// A python iterator object.
|
||||
/// A Python iterator object.
|
||||
///
|
||||
/// Unlike other python objects, this class includes a `Python<'p>` token
|
||||
/// so that `PyIterator` can implement the rust `Iterator` trait.
|
||||
/// Unlike other Python objects, this class includes a `Python<'p>` token
|
||||
/// so that `PyIterator` can implement the Rust `Iterator` trait.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -60,6 +60,7 @@ impl<'p> Iterator for PyIterator<'p> {
|
|||
type Item = PyResult<&'p PyAny>;
|
||||
|
||||
/// Retrieves the next item from an iterator.
|
||||
///
|
||||
/// Returns `None` when the iterator is exhausted.
|
||||
/// If an exception occurs, returns `Some(Err(..))`.
|
||||
/// Further `next()` calls after an exception occurs are likely
|
||||
|
|
|
@ -20,7 +20,7 @@ pub struct PyList(PyObject, Unsendable);
|
|||
pyobject_native_var_type!(PyList, ffi::PyList_Type, ffi::PyList_Check);
|
||||
|
||||
impl PyList {
|
||||
/// Construct a new list with the given elements.
|
||||
/// Constructs a new list with the given elements.
|
||||
pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
|
||||
where
|
||||
T: ToPyObject,
|
||||
|
@ -38,18 +38,18 @@ impl PyList {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct a new empty list.
|
||||
/// Constructs a new empty list.
|
||||
pub fn empty(py: Python) -> &PyList {
|
||||
unsafe { py.from_owned_ptr::<PyList>(ffi::PyList_New(0)) }
|
||||
}
|
||||
|
||||
/// Gets the length of the list.
|
||||
/// Returns the length of the list.
|
||||
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 }
|
||||
}
|
||||
|
||||
/// Check if list is empty.
|
||||
/// Checks if the list is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ impl PyList {
|
|||
}
|
||||
}
|
||||
|
||||
/// Appends an item at the list.
|
||||
/// Appends an item to the list.
|
||||
pub fn append<I>(&self, item: I) -> PyResult<()>
|
||||
where
|
||||
I: ToBorrowedObject,
|
||||
|
@ -113,7 +113,7 @@ impl PyList {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns an iterator over this list items.
|
||||
/// Returns an iterator over this list's items.
|
||||
pub fn iter(&self) -> PyListIterator {
|
||||
PyListIterator {
|
||||
list: self,
|
||||
|
@ -121,12 +121,12 @@ impl PyList {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sorts the list in-place. Equivalent to python `l.sort()`
|
||||
/// Sorts the list in-place. Equivalent to the Python expression `l.sort()`.
|
||||
pub fn sort(&self) -> PyResult<()> {
|
||||
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Sort(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Reverses the list in-place. Equivalent to python `l.reverse()`
|
||||
/// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`.
|
||||
pub fn reverse(&self) -> PyResult<()> {
|
||||
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Reverse(self.as_ptr())) }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
//! Various types defined by the python interpreter such as `int`, `str` and `tuple`
|
||||
//! Various types defined by the Python interpreter such as `int`, `str` and `tuple`.
|
||||
|
||||
pub use self::any::PyAny;
|
||||
pub use self::boolobject::PyBool;
|
||||
|
|
|
@ -25,23 +25,24 @@ pub struct PyModule(PyObject, Unsendable);
|
|||
pyobject_native_var_type!(PyModule, ffi::PyModule_Type, ffi::PyModule_Check);
|
||||
|
||||
impl PyModule {
|
||||
/// Create a new module object with the `__name__` attribute set to name.
|
||||
/// Creates a new module object with the `__name__` attribute set to name.
|
||||
pub fn new<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
|
||||
let name = CString::new(name)?;
|
||||
unsafe { py.from_owned_ptr_or_err(ffi::PyModule_New(name.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
/// Imports the Python module with the specified name.
|
||||
pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
|
||||
let name = CString::new(name)?;
|
||||
unsafe { py.from_owned_ptr_or_err(ffi::PyImport_ImportModule(name.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Loads the python code specified into a new module
|
||||
/// 'code' is the raw Python you want to load into the module
|
||||
/// 'file_name' is the file name to associate with the module
|
||||
/// (this is used when Python reports errors, for example)
|
||||
/// 'module_name' is the name to give the module
|
||||
/// Loads the Python code specified into a new module.
|
||||
///
|
||||
/// `code` is the raw Python you want to load into the module.
|
||||
/// `file_name` is the file name to associate with the module
|
||||
/// (this is used when Python reports errors, for example).
|
||||
/// `module_name` is the name to give the module.
|
||||
pub fn from_code<'p>(
|
||||
py: Python<'p>,
|
||||
code: &str,
|
||||
|
@ -106,14 +107,14 @@ impl PyModule {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the module name.
|
||||
/// Returns the module's name.
|
||||
///
|
||||
/// May fail if the module does not have a `__name__` attribute.
|
||||
pub fn name(&self) -> PyResult<&str> {
|
||||
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Gets the module filename.
|
||||
/// Returns the module's filename.
|
||||
///
|
||||
/// May fail if the module does not have a `__file__` attribute.
|
||||
pub fn filename(&self) -> PyResult<&str> {
|
||||
|
@ -121,7 +122,8 @@ impl PyModule {
|
|||
}
|
||||
|
||||
/// Calls a function in the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
|
||||
///
|
||||
/// This is equivalent to the Python expression `module.name(*args, **kwargs)`.
|
||||
pub fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
|
@ -131,20 +133,23 @@ impl PyModule {
|
|||
self.getattr(name)?.call(args, kwargs)
|
||||
}
|
||||
|
||||
/// Calls a function in the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)()`
|
||||
pub fn call0(&self, name: &str) -> PyResult<&PyAny> {
|
||||
self.getattr(name)?.call0()
|
||||
}
|
||||
|
||||
/// Calls a function in the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)(*args)`
|
||||
/// Calls a function in the module with only positional arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `module.name(*args)`.
|
||||
pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
|
||||
self.getattr(name)?.call1(args)
|
||||
}
|
||||
|
||||
/// Calls a function in the module without arguments.
|
||||
///
|
||||
/// This is equivalent to the Python expression `module.name()`.
|
||||
pub fn call0(&self, name: &str) -> PyResult<&PyAny> {
|
||||
self.getattr(name)?.call0()
|
||||
}
|
||||
|
||||
/// Gets a member from the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)`
|
||||
///
|
||||
/// This is equivalent to the Python expression `module.name`.
|
||||
pub fn get(&self, name: &str) -> PyResult<&PyAny> {
|
||||
self.getattr(name)
|
||||
}
|
||||
|
|
|
@ -417,7 +417,7 @@ mod bigint_conversion {
|
|||
assert_eq!(zero, BigInt::from(0));
|
||||
}
|
||||
|
||||
/// `OverflowError` on converting python int to BigInt, see issue #629
|
||||
/// `OverflowError` on converting Python int to BigInt, see issue #629
|
||||
#[test]
|
||||
fn check_overflow() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
|
|
@ -12,13 +12,15 @@ use crate::types::{PyAny, PyList, PyTuple};
|
|||
use crate::AsPyPointer;
|
||||
use crate::{FromPyObject, PyTryFrom, ToBorrowedObject};
|
||||
|
||||
/// Represents a reference to a python object supporting the sequence protocol.
|
||||
/// Represents a reference to a Python object supporting the sequence protocol.
|
||||
#[repr(transparent)]
|
||||
pub struct PySequence(PyObject, Unsendable);
|
||||
pyobject_native_type_named!(PySequence);
|
||||
|
||||
impl PySequence {
|
||||
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
||||
/// Returns the number of objects in sequence.
|
||||
///
|
||||
/// This is equivalent to the Python expression `len(self)`.
|
||||
#[inline]
|
||||
pub fn len(&self) -> PyResult<isize> {
|
||||
let v = unsafe { ffi::PySequence_Size(self.as_ptr()) };
|
||||
|
@ -34,7 +36,9 @@ impl PySequence {
|
|||
self.len().map(|l| l == 0)
|
||||
}
|
||||
|
||||
/// Return the concatenation of o1 and o2. Equivalent to python `o1 + o2`
|
||||
/// Returns the concatenation of `self` and `other`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self + other`.
|
||||
#[inline]
|
||||
pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> {
|
||||
unsafe {
|
||||
|
@ -48,8 +52,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the result of repeating sequence object o count times.
|
||||
/// Equivalent to python `o * count`
|
||||
/// Returns the result of repeating a sequence object `count` times.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self * count`.
|
||||
/// NB: Python accepts negative counts; it returns an empty Sequence.
|
||||
#[inline]
|
||||
pub fn repeat(&self, count: isize) -> PyResult<&PySequence> {
|
||||
|
@ -64,7 +69,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Concatenate of o1 and o2 on success. Equivalent to python `o1 += o2`
|
||||
/// Concatenates `self` and `other` in place.
|
||||
///
|
||||
/// This is equivalent to the Python statement `self += other`.
|
||||
#[inline]
|
||||
pub fn in_place_concat(&self, other: &PySequence) -> PyResult<()> {
|
||||
unsafe {
|
||||
|
@ -77,8 +84,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Repeate sequence object o count times and store in self.
|
||||
/// Equivalent to python `o *= count`
|
||||
/// Repeats the sequence object `count` times and updates `self`.
|
||||
///
|
||||
/// This is equivalent to the Python statement `self *= count`.
|
||||
/// NB: Python accepts negative counts; it empties the Sequence.
|
||||
#[inline]
|
||||
pub fn in_place_repeat(&self, count: isize) -> PyResult<()> {
|
||||
|
@ -92,7 +100,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the ith element of the Sequence. Equivalent to python `o[index]`
|
||||
/// Returns the `index`th element of the Sequence.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self[index]`.
|
||||
#[inline]
|
||||
pub fn get_item(&self, index: isize) -> PyResult<&PyAny> {
|
||||
unsafe {
|
||||
|
@ -101,8 +111,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the slice of sequence object o between begin and end.
|
||||
/// This is the equivalent of the Python expression `o[begin:end]`
|
||||
/// Returns the slice of sequence object between `begin` and `end`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self[begin:end]`.
|
||||
#[inline]
|
||||
pub fn get_slice(&self, begin: isize, end: isize) -> PyResult<&PyAny> {
|
||||
unsafe {
|
||||
|
@ -114,8 +125,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assign object v to the ith element of o.
|
||||
/// Equivalent to Python statement `o[i] = v`
|
||||
/// Assigns object `item` to the `i`th element of self.
|
||||
///
|
||||
/// This is equivalent to the Python statement `self[i] = v`.
|
||||
#[inline]
|
||||
pub fn set_item<I>(&self, i: isize, item: I) -> PyResult<()>
|
||||
where
|
||||
|
@ -131,8 +143,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Delete the ith element of object o.
|
||||
/// Python statement `del o[i]`
|
||||
/// Deletes the `i`th element of self.
|
||||
///
|
||||
/// This is equivalent to the Python statement `del self[i]`.
|
||||
#[inline]
|
||||
pub fn del_item(&self, i: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
|
@ -143,8 +156,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assign the sequence object v to the slice in sequence object o from i1 to i2.
|
||||
/// This is the equivalent of the Python statement `o[i1:i2] = v`
|
||||
/// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`.
|
||||
///
|
||||
/// This is equivalent to the Python statement `self[i1:i2] = v`.
|
||||
#[inline]
|
||||
pub fn set_slice(&self, i1: isize, i2: isize, v: &PyAny) -> PyResult<()> {
|
||||
unsafe {
|
||||
|
@ -160,8 +174,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Delete the slice in sequence object o from i1 to i2.
|
||||
/// equivalent of the Python statement `del o[i1:i2]`
|
||||
/// Deletes the slice from `i1` to `i2` from `self`.
|
||||
///
|
||||
/// This is equivalent to the Python statement `del self[i1:i2]`.
|
||||
#[inline]
|
||||
pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
|
@ -172,8 +187,8 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the number of occurrences of value in o, that is, return the number of keys for
|
||||
/// which `o[key] == value`
|
||||
/// Returns the number of occurrences of `value` in self, that is, return the
|
||||
/// number of keys for which `self[key] == value`.
|
||||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
pub fn count<V>(&self, value: V) -> PyResult<usize>
|
||||
|
@ -190,7 +205,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Determine if o contains value. this is equivalent to the Python expression `value in o`
|
||||
/// Determines if self contains `value`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `value in self`.
|
||||
#[inline]
|
||||
pub fn contains<V>(&self, value: V) -> PyResult<bool>
|
||||
where
|
||||
|
@ -206,8 +223,9 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the first index `i` for which `o[i] == value`.
|
||||
/// This is equivalent to the Python expression `o.index(value)`
|
||||
/// Returns the first index `i` for which `self[i] == value`.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self.index(value)`.
|
||||
#[inline]
|
||||
pub fn index<V>(&self, value: V) -> PyResult<usize>
|
||||
where
|
||||
|
@ -223,7 +241,7 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return a fresh list based on the Sequence.
|
||||
/// Returns a fresh list based on the Sequence.
|
||||
#[inline]
|
||||
pub fn list(&self) -> PyResult<&PyList> {
|
||||
unsafe {
|
||||
|
@ -232,7 +250,7 @@ impl PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return a fresh tuple based on the Sequence.
|
||||
/// Returns a fresh tuple based on the Sequence.
|
||||
#[inline]
|
||||
pub fn tuple(&self) -> PyResult<&PyTuple> {
|
||||
unsafe {
|
||||
|
|
|
@ -30,18 +30,20 @@ pyobject_native_type!(
|
|||
);
|
||||
|
||||
impl PySet {
|
||||
/// Creates a new set.
|
||||
/// Creates a new set with elements from the given slice.
|
||||
///
|
||||
/// Returns an error if some element is not hashable.
|
||||
pub fn new<'p, T: ToPyObject>(py: Python<'p>, elements: &[T]) -> PyResult<&'p PySet> {
|
||||
let list = elements.to_object(py);
|
||||
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(list.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Creates a new empty set
|
||||
/// Creates a new empty set.
|
||||
pub fn empty<'p>(py: Python<'p>) -> PyResult<&'p PySet> {
|
||||
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(ptr::null_mut())) }
|
||||
}
|
||||
|
||||
/// Remove all elements from the set.
|
||||
/// Removes all elements from the set.
|
||||
#[inline]
|
||||
pub fn clear(&self) {
|
||||
unsafe {
|
||||
|
@ -49,19 +51,21 @@ impl PySet {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the number of items in the set.
|
||||
/// This is equivalent to len(p) on a set.
|
||||
/// Returns the number of items in the set.
|
||||
///
|
||||
/// This is equivalent to the Python expression `len(self)`.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::PySet_Size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Check if set is empty.
|
||||
/// Checks if set is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Determine if the set contains the specified key.
|
||||
/// Determines if the set contains the specified key.
|
||||
///
|
||||
/// This is equivalent to the Python expression `key in self`.
|
||||
pub fn contains<K>(&self, key: K) -> PyResult<bool>
|
||||
where
|
||||
|
@ -76,7 +80,7 @@ impl PySet {
|
|||
})
|
||||
}
|
||||
|
||||
/// Remove element from the set if it is present.
|
||||
/// Removes the element from the set if it is present.
|
||||
pub fn discard<K>(&self, key: K)
|
||||
where
|
||||
K: ToPyObject,
|
||||
|
@ -86,7 +90,7 @@ impl PySet {
|
|||
})
|
||||
}
|
||||
|
||||
/// Add element to the set.
|
||||
/// Adds an element to the set.
|
||||
pub fn add<K>(&self, key: K) -> PyResult<()>
|
||||
where
|
||||
K: ToPyObject,
|
||||
|
@ -96,7 +100,7 @@ impl PySet {
|
|||
})
|
||||
}
|
||||
|
||||
/// Remove and return an arbitrary element from the set
|
||||
/// Removes and returns an arbitrary element from the set.
|
||||
pub fn pop(&self) -> Option<PyObject> {
|
||||
let element =
|
||||
unsafe { PyObject::from_owned_ptr_or_err(self.py(), ffi::PySet_Pop(self.as_ptr())) };
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::os::raw::c_long;
|
|||
|
||||
/// Represents a Python `slice`.
|
||||
///
|
||||
/// Only `c_long` indices supported at the moment by `PySlice` object.
|
||||
/// Only `c_long` indices supported at the moment by the `PySlice` object.
|
||||
#[repr(transparent)]
|
||||
pub struct PySlice(PyObject, Unsendable);
|
||||
|
||||
|
@ -22,7 +22,7 @@ pyobject_native_type!(
|
|||
ffi::PySlice_Check
|
||||
);
|
||||
|
||||
/// Represents a Python `slice` indices
|
||||
/// Represents Python `slice` indices.
|
||||
pub struct PySliceIndices {
|
||||
pub start: isize,
|
||||
pub stop: isize,
|
||||
|
@ -42,7 +42,7 @@ impl PySliceIndices {
|
|||
}
|
||||
|
||||
impl PySlice {
|
||||
/// Construct a new slice with the given elements.
|
||||
/// Constructs a new slice with the given elements.
|
||||
pub fn new(py: Python, start: isize, stop: isize, step: isize) -> &PySlice {
|
||||
unsafe {
|
||||
let ptr = ffi::PySlice_New(
|
||||
|
@ -54,7 +54,9 @@ impl PySlice {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Retrieves the start, stop, and step indices from the slice object,
|
||||
/// assuming a sequence of length `length`, and stores the length of the
|
||||
/// slice in its `slicelength` member.
|
||||
#[inline]
|
||||
pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> {
|
||||
// non-negative Py_ssize_t should always fit into Rust usize
|
||||
|
|
|
@ -14,9 +14,9 @@ use std::os::raw::c_char;
|
|||
use std::ptr::NonNull;
|
||||
use std::str;
|
||||
|
||||
/// Represents a Python `string`.
|
||||
/// Represents a Python `string` (a Unicode string object).
|
||||
///
|
||||
/// This type is immutable
|
||||
/// This type is immutable.
|
||||
#[repr(transparent)]
|
||||
pub struct PyString(PyObject, Unsendable);
|
||||
|
||||
|
@ -43,7 +43,7 @@ impl PyString {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the Python string as a byte slice.
|
||||
/// Gets the Python string as a byte slice.
|
||||
///
|
||||
/// Returns a `UnicodeEncodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates).
|
||||
|
@ -60,17 +60,17 @@ impl PyString {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
/// Converts the `PyString` into a Rust string.
|
||||
pub fn to_string(&self) -> PyResult<Cow<str>> {
|
||||
let bytes = self.as_bytes()?;
|
||||
let string = std::str::from_utf8(bytes)?;
|
||||
Ok(Cow::Borrowed(string))
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
/// Converts the `PyString` into a Rust string.
|
||||
///
|
||||
/// Unpaired surrogates invalid UTF-8 sequences are
|
||||
/// replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
/// replaced with `U+FFFD REPLACEMENT CHARACTER`.
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
match self.to_string() {
|
||||
Ok(s) => s,
|
||||
|
@ -98,7 +98,7 @@ impl PyString {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts Rust `str` to Python object.
|
||||
/// Converts a Rust `str` to a Python object.
|
||||
/// See `PyString::new` for details on the conversion.
|
||||
impl ToPyObject for str {
|
||||
#[inline]
|
||||
|
@ -114,7 +114,7 @@ impl<'a> IntoPy<PyObject> for &'a str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts Rust `Cow<str>` to Python object.
|
||||
/// Converts a Rust `Cow<str>` to a Python object.
|
||||
/// See `PyString::new` for details on the conversion.
|
||||
impl<'a> ToPyObject for Cow<'a, str> {
|
||||
#[inline]
|
||||
|
@ -123,7 +123,7 @@ impl<'a> ToPyObject for Cow<'a, str> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts Rust `String` to Python object.
|
||||
/// Converts a Rust `String` to a Python object.
|
||||
/// See `PyString::new` for details on the conversion.
|
||||
impl ToPyObject for String {
|
||||
#[inline]
|
||||
|
|
|
@ -15,13 +15,15 @@ use crate::{FromPyObject, IntoPy, PyTryFrom, ToPyObject};
|
|||
use std::slice;
|
||||
|
||||
/// Represents a Python `tuple` object.
|
||||
///
|
||||
/// This type is immutable.
|
||||
#[repr(transparent)]
|
||||
pub struct PyTuple(PyObject, Unsendable);
|
||||
|
||||
pyobject_native_var_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check);
|
||||
|
||||
impl PyTuple {
|
||||
/// Construct a new tuple with the given elements.
|
||||
/// Constructs a new tuple with the given elements.
|
||||
pub fn new<T, U>(py: Python, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyTuple
|
||||
where
|
||||
T: ToPyObject,
|
||||
|
@ -38,7 +40,7 @@ impl PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
/// Retrieves the empty tuple.
|
||||
/// Constructs an empty tuple (on the Python side, a singleton object).
|
||||
pub fn empty(py: Python) -> &PyTuple {
|
||||
unsafe { py.from_owned_ptr(ffi::PyTuple_New(0)) }
|
||||
}
|
||||
|
@ -51,17 +53,17 @@ impl PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if tuple is empty.
|
||||
/// Checks if the tuple is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Take a slice of the tuple pointed to by p from low to high and return it as a new tuple.
|
||||
/// Takes a slice of the tuple pointed from `low` to `high` and returns it as a new tuple.
|
||||
pub fn slice(&self, low: isize, high: isize) -> Py<PyTuple> {
|
||||
unsafe { Py::from_owned_ptr_or_panic(ffi::PyTuple_GetSlice(self.as_ptr(), low, high)) }
|
||||
}
|
||||
|
||||
/// Take a slice of the tuple pointed to by p from low and return it as a new tuple.
|
||||
/// Takes a slice of the tuple from `low` to the end and returns it as a new tuple.
|
||||
pub fn split_from(&self, low: isize) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let ptr =
|
||||
|
@ -70,7 +72,7 @@ impl PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the item at the specified index.
|
||||
/// Gets the tuple item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_item(&self, index: usize) -> &PyAny {
|
||||
|
@ -83,6 +85,7 @@ impl PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `self` as a slice of objects.
|
||||
pub fn as_slice(&self) -> &[PyObject] {
|
||||
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
|
||||
// and because tuples are immutable.
|
||||
|
|
|
@ -20,6 +20,7 @@ pub struct PyType(PyObject, Unsendable);
|
|||
pyobject_native_var_type!(PyType, ffi::PyType_Type, ffi::PyType_Check);
|
||||
|
||||
impl PyType {
|
||||
/// Creates a new type object.
|
||||
#[inline]
|
||||
pub fn new<T: PyTypeObject>() -> Py<PyType> {
|
||||
T::type_object()
|
||||
|
@ -31,7 +32,7 @@ impl PyType {
|
|||
self.as_ptr() as *mut ffi::PyTypeObject
|
||||
}
|
||||
|
||||
/// Retrieves the PyType instance for the given FFI pointer.
|
||||
/// Retrieves the `PyType` instance for the given FFI pointer.
|
||||
/// This increments the reference count on the type object.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
|
@ -39,12 +40,14 @@ impl PyType {
|
|||
py.from_borrowed_ptr(p as *mut ffi::PyObject)
|
||||
}
|
||||
|
||||
/// Gets the name of the PyType.
|
||||
/// Gets the name of the `PyType`.
|
||||
pub fn name(&self) -> Cow<str> {
|
||||
unsafe { CStr::from_ptr((*self.as_type_ptr()).tp_name).to_string_lossy() }
|
||||
}
|
||||
|
||||
/// Check whether `self` is subclass of type `T` like Python `issubclass` function
|
||||
/// Checks whether `self` is subclass of type `T`.
|
||||
///
|
||||
/// Equivalent to Python's `issubclass` function.
|
||||
pub fn is_subclass<T>(&self) -> PyResult<bool>
|
||||
where
|
||||
T: PyTypeObject,
|
||||
|
@ -59,7 +62,9 @@ impl PyType {
|
|||
}
|
||||
}
|
||||
|
||||
// Check whether `obj` is an instance of `self`
|
||||
/// Check whether `obj` is an instance of `self`.
|
||||
///
|
||||
/// Equivalent to Python's `isinstance` function.
|
||||
pub fn is_instance<T: AsPyPointer>(&self, obj: &T) -> PyResult<bool> {
|
||||
let result = unsafe { ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr()) };
|
||||
if result == -1 {
|
||||
|
|
Loading…
Reference in New Issue