lib: overhaul docstrings

This commit is contained in:
Georg Brandl 2020-03-17 15:16:15 +01:00
parent a7a2ccb5ff
commit 77b1ae3137
29 changed files with 435 additions and 298 deletions

View File

@ -2,7 +2,7 @@
//! Basic Python Object customization //! 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. //! for more information.
//! //!
//! Parts of the documentation are copied from the respective methods from the //! 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, Ge = ffi::Py_GE as isize,
} }
/// Basic python class customization /// Basic Python class customization
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait PyObjectProtocol<'p>: PyClass { pub trait PyObjectProtocol<'p>: PyClass {
fn __getattr__(&'p self, name: Self::Name) -> Self::Result fn __getattr__(&'p self, name: Self::Name) -> Self::Result
@ -246,8 +246,8 @@ where
} }
/// An object may support setting attributes (by implementing PyObjectSetAttrProtocol) /// An object may support setting attributes (by implementing PyObjectSetAttrProtocol)
/// and may support deleting attributes (by implementing PyObjectDelAttrProtocol) /// and may support deleting attributes (by implementing PyObjectDelAttrProtocol).
/// and we need to generate a single extern c function that supports only setting, only deleting /// 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. /// or both, and return None in case none of the two is supported.
mod tp_setattro_impl { mod tp_setattro_impl {
use super::*; use super::*;

View File

@ -4,8 +4,8 @@ use crate::ffi;
use libc::c_int; use libc::c_int;
use std::ffi::CString; use std::ffi::CString;
/// `PyMethodDefType` represents different types of python callable objects. /// `PyMethodDefType` represents different types of Python callable objects.
/// It is used by `#[pymethods]` and `#[pyproto]` annotations. /// It is used by the `#[pymethods]` and `#[pyproto]` annotations.
#[derive(Debug)] #[derive(Debug)]
pub enum PyMethodDefType { pub enum PyMethodDefType {
/// Represents class `__new__` method /// Represents class `__new__` method
@ -133,7 +133,7 @@ pub trait PyMethodsInventory: inventory::Collect {
fn get_methods(&self) -> &'static [PyMethodDefType]; fn get_methods(&self) -> &'static [PyMethodDefType];
} }
/// The implementation of tis trait defines which methods a python type has. /// The implementation of tis trait defines which methods a Python type has.
/// ///
/// For pyclass derived structs this is implemented by collecting all impl blocks through inventory /// For pyclass derived structs this is implemented by collecting all impl blocks through inventory
pub trait PyMethodsProtocol { pub trait PyMethodsProtocol {

View File

@ -2,7 +2,7 @@
//! Python Async/Await Interface. //! 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) //! https://docs.python.org/3/c-api/typeobj.html#async-object-structures)
//! //!
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/) //! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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::err::{self, PyDowncastError, PyResult};
use crate::object::PyObject; use crate::object::PyObject;
use crate::type_object::{PyDowncastImpl, PyTypeInfo}; 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 crate::{ffi, gil, Py, PyCell, PyClass, PyNativeType, PyRef, PyRefMut, Python};
use std::ptr::NonNull; 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 /// # 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 { pub trait ToPyObject {
/// Converts self into a Python object. /// Converts self into a Python object.
fn to_object(&self, py: Python) -> PyObject; 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 /// `FromPyObject` is implemented by various types that can be extracted from
/// a Python object reference. /// 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 obj: PyObject = ...;
/// let value: &TargetType = obj.extract(py)?; /// 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 /// Note: depending on the implementation, the lifetime of the extracted result may
/// depend on the lifetime of the `obj` or the `prepared` variable. /// 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`). /// 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`. /// 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. /// both the `obj` and `prepared` variables must outlive the resulting string slice.
/// ///
/// In cases where the result does not depend on the `'prepared` lifetime, /// In cases where the result does not depend on the `'prepared` lifetime,
/// the inherent method `PyObject::extract()` can be used. /// 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 { pub trait FromPyObject<'source>: Sized {
/// Extracts `Self` from the source `PyObject`. /// Extracts `Self` from the source `PyObject`.
fn extract(ob: &'source PyAny) -> PyResult<Self>; fn extract(ob: &'source PyAny) -> PyResult<Self>;

View File

@ -16,9 +16,9 @@ use std::io;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::ptr::NonNull; 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` /// 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 /// 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`. /// Creates a new PyErr of type `T`.
/// ///
/// `value` can be: /// `value` can be:
/// * a tuple: the exception instance will be created using python `T(*tuple)` /// * 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)` /// * 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: /// Example:
/// `return Err(PyErr::new::<exceptions::TypeError, _>("Error message"));` /// ```
/// 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
/// ```
/// return Err(exceptions::TypeError::py_err("Error message"));
/// return exceptions::TypeError::into("Error message");
/// ```
pub fn new<T, V>(value: V) -> PyErr pub fn new<T, V>(value: V) -> PyErr
where where
T: PyTypeObject, 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 /// `exc` is the exception type; usually one of the standard exceptions
/// like `exceptions::RuntimeError`. /// like `exceptions::RuntimeError`.
/// `args` is the a tuple of arguments to pass to the exception constructor. /// `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. /// Retrieves the current error from the Python interpreter's global state.
///
/// The error is cleared from the Python interpreter. /// The error is cleared from the Python interpreter.
/// If no error is set, returns a `SystemError`. /// If no error is set, returns a `SystemError`.
pub fn fetch(_: Python) -> PyErr { 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) { pub fn print(self, py: Python) {
self.restore(py); self.restore(py);
unsafe { ffi::PyErr_PrintEx(0) } 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) { pub fn print_and_set_sys_last_vars(self, py: Python) {
self.restore(py); self.restore(py);
unsafe { ffi::PyErr_PrintEx(1) } 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 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. /// 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 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 pub fn is_instance<T>(&self, _py: Python) -> bool
where where
T: PyTypeObject, T: PyTypeObject,
@ -277,8 +290,8 @@ impl PyErr {
// This is safe as long as normalized() doesn't unwind due to a panic. // 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. /// Helper function for normalizing the error by deconstructing and reconstructing the `PyErr`.
/// Must not panic for safety in normalize() /// Must not panic for safety in `normalize()`.
fn into_normalized(self, py: Python) -> PyErr { fn into_normalized(self, py: Python) -> PyErr {
let PyErr { let PyErr {
ptype, ptype,
@ -302,6 +315,7 @@ impl PyErr {
} }
/// Retrieves the exception instance for this error. /// Retrieves the exception instance for this error.
///
/// This method takes `mut self` because the error might need /// This method takes `mut self` because the error might need
/// to be normalized in order to create the exception instance. /// to be normalized in order to create the exception instance.
fn instance(mut self, py: Python) -> PyObject { fn instance(mut self, py: Python) -> PyObject {
@ -345,8 +359,8 @@ impl PyErr {
-1 -1
} }
/// Issue a warning message. /// Issues a warning message.
/// May return a PyErr if warnings-as-errors is enabled. /// May return a `PyErr` if warnings-as-errors is enabled.
pub fn warn(py: Python, category: &PyAny, message: &str, stacklevel: i32) -> PyResult<()> { pub fn warn(py: Python, category: &PyAny, message: &str, stacklevel: i32) -> PyResult<()> {
let message = CString::new(message)?; let message = CString::new(message)?;
unsafe { unsafe {

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
@ -12,7 +12,7 @@ use std::ffi::CStr;
use std::ops; use std::ops;
use std::os::raw::c_char; 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_export]
macro_rules! impl_exception_boilerplate { macro_rules! impl_exception_boilerplate {
($name: ident) => { ($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 /// # Syntax
/// ///
/// `import_exception!(module, MyError)` /// ```import_exception!(module, MyError)```
/// ///
/// * `module` is the name of the containing module. /// * `module` is the name of the containing module.
/// * `MyError` is the name of the new exception type. /// * `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 /// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an
/// code. /// exception defined in Python code.
#[macro_export] #[macro_export]
macro_rules! import_exception_type_object { macro_rules! import_exception_type_object {
($module: expr, $name: ident) => { ($module: expr, $name: ident) => {
@ -120,11 +120,12 @@ macro_rules! import_exception_type_object {
/// Defines a new exception type. /// Defines a new exception type.
/// ///
/// # Syntax /// # Syntax
/// `create_exception!(module, MyError, BaseException)` ///
/// ```create_exception!(module, MyError, BaseException)```
/// ///
/// * `module` is the name of the containing module. /// * `module` is the name of the containing module.
/// * `MyError` is the name of the new exception type. /// * `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 /// # Example
/// ``` /// ```
@ -166,8 +167,8 @@ macro_rules! create_exception {
}; };
} }
/// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an exception newly defined in /// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an
/// rust code. /// exception newly defined in Rust code.
#[macro_export] #[macro_export]
macro_rules! create_exception_type_object { macro_rules! create_exception_type_object {
($module: ident, $name: ident, $base: ty) => { ($module: ident, $name: ident, $base: ty) => {

View File

@ -60,6 +60,7 @@ impl<T> Py<T> {
} }
/// Creates a `Py<T>` instance for the given FFI pointer. /// Creates a `Py<T>` instance for the given FFI pointer.
///
/// This moves ownership over the pointer into the `Py<T>`. /// This moves ownership over the pointer into the `Py<T>`.
/// Undefined behavior if the pointer is NULL or invalid. /// Undefined behavior if the pointer is NULL or invalid.
#[inline] #[inline]
@ -72,7 +73,8 @@ impl<T> Py<T> {
} }
/// Creates a `Py<T>` instance for the given FFI pointer. /// 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. /// Undefined behavior if the pointer is invalid.
#[inline] #[inline]
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> { pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> {
@ -85,8 +87,9 @@ impl<T> Py<T> {
} }
/// Construct `Py<T>` from the result of a Python FFI call that /// 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. /// Unsafe because the pointer might be invalid.
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> { pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
match NonNull::new(ptr) { match NonNull::new(ptr) {
@ -96,7 +99,8 @@ impl<T> Py<T> {
} }
/// Creates a `Py<T>` instance for the given Python FFI pointer. /// 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. /// Undefined behavior if the pointer is NULL or invalid.
#[inline] #[inline]
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> Py<T> { pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> Py<T> {
@ -108,21 +112,21 @@ impl<T> Py<T> {
Py(NonNull::new_unchecked(ptr), PhantomData) 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] #[inline]
pub fn get_refcnt(&self) -> isize { pub fn get_refcnt(&self) -> isize {
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } 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] #[inline]
pub fn clone_ref(&self, _py: Python) -> Py<T> { pub fn clone_ref(&self, _py: Python) -> Py<T> {
unsafe { Py::from_borrowed_ptr(self.0.as_ptr()) } 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> { pub(crate) fn into_non_null(self) -> NonNull<ffi::PyObject> {
let pointer = self.0; let pointer = self.0;
mem::forget(self); mem::forget(self);
@ -146,6 +150,7 @@ impl<T> Py<T> {
/// let py = gil.python(); /// let py = gil.python();
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0); // PyAny implements ObjectProtocol /// 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>` /// `Py<T>::as_ref` returns `&PyDict`, `&PyList` or so for native types, and `&PyCell<T>`
/// for `#[pyclass]`. /// for `#[pyclass]`.
/// ``` /// ```
@ -185,8 +190,8 @@ impl<T> ToPyObject for Py<T> {
} }
impl<T> IntoPy<PyObject> for Py<T> { impl<T> IntoPy<PyObject> for Py<T> {
/// Converts `Py` instance -> PyObject. /// Converts a `Py` instance to `PyObject`.
/// Consumes `self` without calling `Py_DECREF()` /// Consumes `self` without calling `Py_DECREF()`.
#[inline] #[inline]
fn into_py(self, _py: Python) -> PyObject { fn into_py(self, _py: Python) -> PyObject {
unsafe { PyObject::from_not_null(self.into_non_null()) } unsafe { PyObject::from_not_null(self.into_non_null()) }
@ -305,12 +310,12 @@ where
/// Reference to a converted [ToPyObject]. /// Reference to a converted [ToPyObject].
/// ///
/// Many methods want to take anything that can be converted into a python object. This type /// 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 /// takes care of both types types that are already Python object (i.e. implement
/// [AsPyPointer]) and those that don't (i.e. [ToPyObject] types). /// [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 /// 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 /// 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 /// # Example
/// ///
@ -334,7 +339,7 @@ pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
} }
/// This should eventually be replaced with a generic `IntoPy` trait impl by figuring /// 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> { impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self { pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
to_pyobject.to_managed_py_ref(py) to_pyobject.to_managed_py_ref(py)
@ -347,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 { 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>; fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self>;
/// Dispatch over a xdecref and a noop drop impl /// Dispatch over a xdecref and a noop drop impl
fn drop_impl(borrowed: &mut ManagedPyRef<Self>); 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 /// This means we're storing the owned pointer that into_ptr() has given us
/// and therefore need to xdecref when we're done. /// and therefore need to xdecref when we're done.
/// ///
@ -378,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. /// 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 { impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
/// Use AsPyPointer to copy the pointer and store it as borrowed pointer /// Use AsPyPointer to copy the pointer and store it as borrowed pointer

View File

@ -195,14 +195,14 @@ mod python;
pub mod type_object; pub mod type_object;
pub mod types; 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 mod proc_macro {
pub use pyo3cls::pymodule; pub use pyo3cls::pymodule;
/// The proc macro attributes /// The proc macro attributes
pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; 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]. /// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped].
#[macro_export] #[macro_export]
@ -212,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]. /// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped].
#[macro_export] #[macro_export]

View File

@ -8,11 +8,11 @@ pub const VERSION: i32 = 4;
/// Serialize an object to bytes using the Python built-in marshal module. /// 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 exact types supported depend on the version argument.
/// The [`VERSION`] constant holds the highest version currently supported. /// 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: /// # Example:
/// ``` /// ```

View File

@ -22,7 +22,7 @@ use std::ptr::NonNull;
#[repr(transparent)] #[repr(transparent)]
pub struct PyObject(NonNull<ffi::PyObject>); 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 Send for PyObject {}
unsafe impl Sync for PyObject {} unsafe impl Sync for PyObject {}
@ -51,7 +51,7 @@ impl PyObject {
} }
/// Creates a `PyObject` instance for the given FFI pointer. /// 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. /// Undefined behavior if the pointer is invalid.
#[inline] #[inline]
pub unsafe fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject) -> PyObject { pub unsafe fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
@ -63,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 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> { pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject> {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(nonnull_ptr) => Ok(PyObject(nonnull_ptr)), Some(nonnull_ptr) => Ok(PyObject(nonnull_ptr)),
@ -73,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 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> { pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject> {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(nonnull_ptr) => Some(PyObject(nonnull_ptr)), Some(nonnull_ptr) => Some(PyObject(nonnull_ptr)),
@ -84,7 +84,7 @@ impl PyObject {
} }
/// Creates a `PyObject` instance for the given Python FFI pointer. /// 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. /// Undefined behavior if the pointer is NULL or invalid.
#[inline] #[inline]
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject { pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
@ -97,8 +97,8 @@ impl PyObject {
} }
/// Creates a `PyObject` instance for the given Python FFI pointer. /// Creates a `PyObject` instance for the given Python FFI pointer.
/// Calls Py_INCREF() on the ptr. /// Calls `Py_INCREF()` on the ptr.
/// Returns `Err(PyErr)` if the pointer is `null`. /// Returns `Err(PyErr)` if the pointer is NULL.
pub unsafe fn from_borrowed_ptr_or_err( pub unsafe fn from_borrowed_ptr_or_err(
py: Python, py: Python,
ptr: *mut ffi::PyObject, ptr: *mut ffi::PyObject,
@ -111,8 +111,8 @@ impl PyObject {
} }
/// Creates a `PyObject` instance for the given Python FFI pointer. /// Creates a `PyObject` instance for the given Python FFI pointer.
/// Calls Py_INCREF() on the ptr. /// Calls `Py_INCREF()` on the ptr.
/// Returns `None` if the pointer is `null`. /// Returns `None` if the pointer is NULL.
pub unsafe fn from_borrowed_ptr_or_opt( pub unsafe fn from_borrowed_ptr_or_opt(
py: Python, py: Python,
ptr: *mut ffi::PyObject, ptr: *mut ffi::PyObject,
@ -129,19 +129,21 @@ impl PyObject {
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } 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 { pub fn clone_ref(&self, py: Python) -> Self {
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) } unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
} }
/// Returns whether the object is considered to be None. /// 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 { pub fn is_none(&self) -> bool {
unsafe { ffi::Py_None() == self.as_ptr() } unsafe { ffi::Py_None() == self.as_ptr() }
} }
/// Returns whether the object is considered to be true. /// 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> { pub fn is_true(&self, py: Python) -> PyResult<bool> {
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
if v == -1 { if v == -1 {
@ -152,6 +154,8 @@ impl PyObject {
} }
/// Casts the PyObject to a concrete Python object type. /// 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> pub fn cast_as<'p, D>(&'p self, py: Python<'p>) -> Result<&'p D, PyDowncastError>
where where
D: PyTryFrom<'p>, D: PyTryFrom<'p>,
@ -160,6 +164,7 @@ impl PyObject {
} }
/// Extracts some type from the Python object. /// Extracts some type from the Python object.
///
/// This is a wrapper function around `FromPyObject::extract()`. /// This is a wrapper function around `FromPyObject::extract()`.
pub fn extract<'p, D>(&'p self, py: Python<'p>) -> PyResult<D> pub fn extract<'p, D>(&'p self, py: Python<'p>) -> PyResult<D>
where where
@ -169,7 +174,8 @@ impl PyObject {
} }
/// Retrieves an attribute value. /// 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> pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
where where
N: ToPyObject, N: ToPyObject,
@ -180,7 +186,8 @@ impl PyObject {
} }
/// Calls the object. /// 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( pub fn call(
&self, &self,
py: Python, py: Python,
@ -199,20 +206,23 @@ impl PyObject {
result result
} }
/// Calls the object without arguments. /// Calls the object with only positional arguments.
/// This is equivalent to the Python expression: 'self()' ///
pub fn call0(&self, py: Python) -> PyResult<PyObject> { /// This is equivalent to the Python expression `self(*args)`.
self.call(py, (), None)
}
/// Calls the object.
/// This is equivalent to the Python expression: 'self(*args)'
pub fn call1(&self, py: Python, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> { pub fn call1(&self, py: Python, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> {
self.call(py, args, None) 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. /// 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( pub fn call_method(
&self, &self,
py: Python, py: Python,
@ -235,14 +245,9 @@ impl PyObject {
}) })
} }
/// Calls a method on the object. /// Calls a method on the object with only positional arguments.
/// This is equivalent to the Python expression: 'self.name()' ///
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> { /// This is equivalent to the Python expression `self.name(*args)`.
self.call_method(py, name, (), None)
}
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name(*args)'
pub fn call_method1( pub fn call_method1(
&self, &self,
py: Python, py: Python,
@ -251,6 +256,13 @@ impl PyObject {
) -> PyResult<PyObject> { ) -> PyResult<PyObject> {
self.call_method(py, name, args, None) 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 { impl AsPyRef for PyObject {
@ -287,7 +299,7 @@ impl IntoPyPointer for PyObject {
} }
impl PartialEq for PyObject { impl PartialEq for PyObject {
/// Checks for identity, not python's `__eq__` /// Checks for pointer identity, not equivalent to Python's `__eq__`.
#[inline] #[inline]
fn eq(&self, o: &PyObject) -> bool { fn eq(&self, o: &PyObject) -> bool {
self.0 == o.0 self.0 == o.0

View File

@ -14,18 +14,21 @@ use std::os::raw::c_int;
/// Python object model helper methods /// Python object model helper methods
pub trait ObjectProtocol { pub trait ObjectProtocol {
/// Determines whether this object has the given attribute. /// Determines whether this object has the given attribute.
///
/// This is equivalent to the Python expression `hasattr(self, attr_name)`. /// This is equivalent to the Python expression `hasattr(self, attr_name)`.
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>
where where
N: ToPyObject; N: ToPyObject;
/// Retrieves an attribute value. /// Retrieves an attribute value.
///
/// This is equivalent to the Python expression `self.attr_name`. /// This is equivalent to the Python expression `self.attr_name`.
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyAny> fn getattr<N>(&self, attr_name: N) -> PyResult<&PyAny>
where where
N: ToPyObject; N: ToPyObject;
/// Sets an attribute value. /// Sets an attribute value.
///
/// This is equivalent to the Python expression `self.attr_name = value`. /// This is equivalent to the Python expression `self.attr_name = value`.
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()> fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
where where
@ -33,6 +36,7 @@ pub trait ObjectProtocol {
V: ToBorrowedObject; V: ToBorrowedObject;
/// Deletes an attribute. /// Deletes an attribute.
///
/// This is equivalent to the Python expression `del self.attr_name`. /// This is equivalent to the Python expression `del self.attr_name`.
fn delattr<N>(&self, attr_name: N) -> PyResult<()> fn delattr<N>(&self, attr_name: N) -> PyResult<()>
where where
@ -57,7 +61,8 @@ pub trait ObjectProtocol {
/// Compares two Python objects. /// 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::Eq: `self == other`
/// * CompareOp::Ne: `self != other` /// * CompareOp::Ne: `self != other`
/// * CompareOp::Lt: `self < other` /// * CompareOp::Lt: `self < other`
@ -68,11 +73,13 @@ pub trait ObjectProtocol {
where where
O: ToPyObject; O: ToPyObject;
/// Compute the string representation of self. /// Computes the "repr" representation of self.
///
/// This is equivalent to the Python expression `repr(self)`. /// This is equivalent to the Python expression `repr(self)`.
fn repr(&self) -> PyResult<&PyString>; 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)`. /// This is equivalent to the Python expression `str(self)`.
fn str(&self) -> PyResult<&PyString>; fn str(&self) -> PyResult<&PyString>;
@ -80,19 +87,23 @@ pub trait ObjectProtocol {
fn is_callable(&self) -> bool; fn is_callable(&self) -> bool;
/// Calls the object. /// 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>; fn call(&self, args: impl IntoPy<Py<PyTuple>>, kwargs: Option<&PyDict>) -> PyResult<&PyAny>;
/// Calls the object. /// Calls the object with only positional arguments.
/// This is equivalent to the Python expression: `self()`. ///
fn call0(&self) -> PyResult<&PyAny>; /// This is equivalent to the Python expression `self(*args)`.
/// Calls the object.
/// This is equivalent to the Python expression: `self(*args)`.
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>; 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. /// 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 /// # Example
/// ```rust /// ```rust
@ -113,77 +124,92 @@ pub trait ObjectProtocol {
kwargs: Option<&PyDict>, kwargs: Option<&PyDict>,
) -> PyResult<&PyAny>; ) -> PyResult<&PyAny>;
/// Calls a method on the object. /// Calls a method on the object with only positional arguments.
/// This is equivalent to the Python expression: `self.name()`. ///
fn call_method0(&self, name: &str) -> PyResult<&PyAny>; /// This is equivalent to the Python expression `self.name(*args)`.
/// Calls a method on the object with positional arguments only.
/// This is equivalent to the Python expression: `self.name(*args)`.
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>; 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. /// 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>; fn hash(&self) -> PyResult<isize>;
/// Returns whether the object is considered to be true. /// 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>; fn is_true(&self) -> PyResult<bool>;
/// Returns whether the object is considered to be None. /// 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; fn is_none(&self) -> bool;
/// Returns the length of the sequence or mapping. /// 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>; fn len(&self) -> PyResult<usize>;
/// Returns true if the sequence or mapping has a length of 0. /// 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>; 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> fn get_item<K>(&self, key: K) -> PyResult<&PyAny>
where where
K: ToBorrowedObject; K: ToBorrowedObject;
/// Sets an item value. /// Sets a collection item value.
///
/// This is equivalent to the Python expression `self[key] = value`. /// This is equivalent to the Python expression `self[key] = value`.
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()> fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
where where
K: ToBorrowedObject, K: ToBorrowedObject,
V: ToBorrowedObject; V: ToBorrowedObject;
/// Deletes an item. /// Deletes an item from the collection.
///
/// This is equivalent to the Python expression `del self[key]`. /// This is equivalent to the Python expression `del self[key]`.
fn del_item<K>(&self, key: K) -> PyResult<()> fn del_item<K>(&self, key: K) -> PyResult<()>
where where
K: ToBorrowedObject; K: ToBorrowedObject;
/// Takes an object and returns an iterator for it. /// 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>; 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; 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; fn get_type_ptr(&self) -> *mut ffi::PyTypeObject;
/// Casts the PyObject to a concrete Python object type. /// 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> fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
where where
D: PyTryFrom<'a>, D: PyTryFrom<'a>,
&'a PyAny: std::convert::From<&'a Self>; &'a PyAny: std::convert::From<&'a Self>;
/// Extracts some type from the Python object. /// Extracts some type from the Python object.
///
/// This is a wrapper function around `FromPyObject::extract()`. /// This is a wrapper function around `FromPyObject::extract()`.
fn extract<'a, D>(&'a self) -> PyResult<D> fn extract<'a, D>(&'a self) -> PyResult<D>
where where
D: FromPyObject<'a>, D: FromPyObject<'a>,
&'a PyAny: std::convert::From<&'a Self>; &'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; fn get_refcnt(&self) -> isize;
/// Gets the Python builtin value `None`. /// Gets the Python builtin value `None`.

View File

@ -20,30 +20,31 @@ pub use gil::prepare_freethreaded_python;
/// Marker type that indicates that the GIL is currently held. /// 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, /// 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 /// 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 /// 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 /// (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 /// ```text
/// GILGuard |=====================================| /// `Python` exists |=====================================|
/// GIL actually held |==========| |================| /// GIL actually held |==========| |================|
/// Rust code running |=======| |==| |======| /// 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 acquires the GIL
/// * Thread 1 locks a mutex /// * 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 acquires the GIL
/// * Thread 2 tries to locks the mutex, blocks /// * 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 /// To avoid deadlocking, you should release the GIL before trying to lock a mutex, e.g. with
/// [Python::allow_threads]. /// [Python::allow_threads].
@ -51,8 +52,8 @@ pub use gil::prepare_freethreaded_python;
pub struct Python<'p>(PhantomData<&'p GILGuard>); pub struct Python<'p>(PhantomData<&'p GILGuard>);
impl<'p> Python<'p> { impl<'p> Python<'p> {
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point, /// Retrieves a Python instance under the assumption that the GIL is already
/// and stays acquired for the lifetime `'p`. /// acquired at this point, and stays acquired for the lifetime `'p`.
/// ///
/// Because the output lifetime `'p` is not connected to any input parameter, /// 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` /// care must be taken that the compiler infers an appropriate lifetime for `'p`
@ -105,8 +106,16 @@ impl<'p> Python<'p> {
/// "#, None, Some(locals)); /// "#, None, Some(locals));
/// ``` /// ```
/// ///
/// **NOTE** /// **Note:**
/// You cannot use all `&Py~` types in the closure that `allow_threads` takes. /// 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 /// # Example
/// ```compile_fail /// ```compile_fail
/// # use pyo3::prelude::*; /// # use pyo3::prelude::*;
@ -114,10 +123,9 @@ impl<'p> Python<'p> {
/// fn parallel_print(py: Python<'_>) { /// fn parallel_print(py: Python<'_>) {
/// let s = PyString::new(py, "This object should not be shared >_<"); /// let s = PyString::new(py, "This object should not be shared >_<");
/// py.allow_threads(move || { /// 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 pub fn allow_threads<T, F>(self, f: F) -> T
where where
@ -193,8 +201,9 @@ impl<'p> Python<'p> {
} }
/// Runs code in the given context. /// 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 `globals` is `None`, it defaults to Python module `__main__`.
/// If `locals` is `None`, it defaults to the value of `globals`. /// 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()) } 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> { pub fn import(self, name: &str) -> PyResult<&'p PyModule> {
PyModule::import(self, name) 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> { pub fn is_instance<T: PyTypeObject, V: AsPyPointer>(self, obj: &V) -> PyResult<bool> {
T::type_object().as_ref(self).is_instance(obj) 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> pub fn is_subclass<T, U>(self) -> PyResult<bool>
where where
T: PyTypeObject, T: PyTypeObject,
@ -272,7 +285,7 @@ impl<'p> Python<'p> {
} }
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> pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
where where
T: PyTryFrom<'p>, T: PyTryFrom<'p>,
@ -281,7 +294,8 @@ impl<'p> Python<'p> {
<T as PyTryFrom>::try_from(obj) <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 pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'p T
where where
T: PyDowncastImpl + PyTypeInfo, T: PyDowncastImpl + PyTypeInfo,
@ -290,7 +304,7 @@ impl<'p> Python<'p> {
T::unchecked_downcast(obj) T::unchecked_downcast(obj)
} }
/// Register `ffi::PyObject` pointer in release pool /// Registers the object pointer in the release pool.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyAny { pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyAny {
match NonNull::new(ptr) { match NonNull::new(ptr) {
@ -299,8 +313,8 @@ impl<'p> Python<'p> {
} }
} }
/// Register `ffi::PyObject` pointer in release pool, /// Registers the object pointer in the release pool,
/// and do unchecked downcast to specific type. /// and does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
where where
@ -309,9 +323,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr(self, ptr) FromPyPointer::from_owned_ptr(self, ptr)
} }
/// Register owned `ffi::PyObject` pointer in release pool. /// Registers the owned object pointer in the release pool.
/// Returns `Err(PyErr)` if the pointer is `null`. ///
/// do unchecked downcast to specific type. /// Returns `Err(PyErr)` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T> pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where where
@ -320,9 +335,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr_or_err(self, ptr) FromPyPointer::from_owned_ptr_or_err(self, ptr)
} }
/// Register owned `ffi::PyObject` pointer in release pool. /// Registers the owned object pointer in release pool.
/// Returns `None` if the pointer is `null`. ///
/// do unchecked downcast to specific type. /// Returns `None` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T> pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where where
@ -331,9 +347,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr_or_opt(self, ptr) FromPyPointer::from_owned_ptr_or_opt(self, ptr)
} }
/// Register borrowed `ffi::PyObject` pointer in release pool. /// Registers the borrowed object pointer in the release pool.
/// Panics if the pointer is `null`. ///
/// do unchecked downcast to specific type. /// Panics if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
where where
@ -342,9 +359,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_borrowed_ptr(self, ptr) FromPyPointer::from_borrowed_ptr(self, ptr)
} }
/// Register borrowed `ffi::PyObject` pointer in release pool. /// Registers the borrowed object pointer in the release pool.
/// Returns `Err(PyErr)` if the pointer is `null`. ///
/// do unchecked downcast to specific type. /// Returns `Err(PyErr)` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T> pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where where
@ -353,9 +371,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_borrowed_ptr_or_err(self, ptr) FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
} }
/// Register borrowed `ffi::PyObject` pointer in release pool. /// Registers the borrowed object pointer in the release pool.
/// Returns `None` if the pointer is `null`. ///
/// do unchecked downcast to specific `T`. /// Returns `None` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T> pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where where
@ -365,13 +384,13 @@ impl<'p> Python<'p> {
} }
#[doc(hidden)] #[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. /// Value get cleaned up on the GIL release.
pub fn register_any<T: 'static>(self, ob: T) -> &'p T { pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
unsafe { gil::register_any(ob) } unsafe { gil::register_any(ob) }
} }
/// Release PyObject reference. /// Releases a PyObject reference.
#[inline] #[inline]
pub fn release<T>(self, ob: T) pub fn release<T>(self, ob: T)
where where
@ -385,7 +404,7 @@ impl<'p> Python<'p> {
} }
} }
/// Release `ffi::PyObject` pointer. /// Releases a `ffi::PyObject` pointer.
#[inline] #[inline]
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) { pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) }; unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };

View File

@ -47,10 +47,10 @@ pub unsafe trait PyBorrowFlagLayout<T: PyTypeInfo>: PyLayout<T> + Sized {}
/// Our custom type flags /// Our custom type flags
#[doc(hidden)] #[doc(hidden)]
pub mod type_flags { pub mod type_flags {
/// type object supports python GC /// Type object supports Python GC
pub const GC: usize = 1; pub const GC: usize = 1;
/// Type object supports python weak references /// Type object supports Python weak references
pub const WEAKREF: usize = 1 << 1; pub const WEAKREF: usize = 1 << 1;
/// Type object can be used as the base type of another type /// Type object can be used as the base type of another type

View File

@ -16,7 +16,7 @@ pub struct PyBool(PyObject, Unsendable);
pyobject_native_type!(PyBool, ffi::PyObject, ffi::PyBool_Type, ffi::PyBool_Check); pyobject_native_type!(PyBool, ffi::PyObject, ffi::PyBool_Type, ffi::PyBool_Check);
impl PyBool { impl PyBool {
/// Depending on `val`, returns `py.True()` or `py.False()`. /// Depending on `val`, returns `true` or `false`.
#[inline] #[inline]
pub fn new(py: Python, val: bool) -> &PyBool { pub fn new(py: Python, val: bool) -> &PyBool {
unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) } 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 { impl ToPyObject for bool {
#[inline] #[inline]
fn to_object(&self, py: Python) -> PyObject { 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`. /// Fails with `TypeError` if the input is not a Python `bool`.
impl<'source> FromPyObject<'source> for bool { impl<'source> FromPyObject<'source> for bool {

View File

@ -17,6 +17,7 @@ pyobject_native_var_type!(PyByteArray, ffi::PyByteArray_Type, ffi::PyByteArray_C
impl PyByteArray { impl PyByteArray {
/// Creates a new Python bytearray object. /// Creates a new Python bytearray object.
///
/// The byte string is initialized by copying the data from the `&[u8]`. /// The byte string is initialized by copying the data from the `&[u8]`.
pub fn new<'p>(py: Python<'p>, src: &[u8]) -> &'p PyByteArray { pub fn new<'p>(py: Python<'p>, src: &[u8]) -> &'p PyByteArray {
let ptr = src.as_ptr() as *const c_char; 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)) } unsafe { py.from_owned_ptr::<PyByteArray>(ffi::PyByteArray_FromStringAndSize(ptr, len)) }
} }
/// Creates a new Python bytearray object /// Creates a new Python bytearray object from another PyObject that
/// from other PyObject, that implements the buffer protocol. /// implements the buffer protocol.
pub fn from<'p, I>(py: Python<'p>, src: &'p I) -> PyResult<&'p PyByteArray> pub fn from<'p, I>(py: Python<'p>, src: &'p I) -> PyResult<&'p PyByteArray>
where where
I: AsPyPointer, I: AsPyPointer,
@ -40,12 +41,12 @@ impl PyByteArray {
unsafe { ffi::PyByteArray_Size(self.0.as_ptr()) as usize } 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 self.len() == 0
} }
/// Copies the contents of the bytearray to a rust vector /// Copies the contents of the bytearray to a Rust vector.
/// ///
/// # Example /// # Example
/// ///
@ -75,7 +76,7 @@ impl PyByteArray {
slice.to_vec() slice.to_vec()
} }
/// Resize bytearray object to `len`. /// Resizes the bytearray object to the new length `len`.
pub fn resize(&self, len: usize) -> PyResult<()> { pub fn resize(&self, len: usize) -> PyResult<()> {
unsafe { unsafe {
let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t); let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t);

View File

@ -12,17 +12,17 @@ use std::os::raw::c_char;
use std::slice::SliceIndex; use std::slice::SliceIndex;
use std::str; use std::str;
/// Represents a Python `bytes`. /// Represents a Python `bytes` object.
/// ///
/// This type is immutable /// This type is immutable.
#[repr(transparent)] #[repr(transparent)]
pub struct PyBytes(PyObject, Unsendable); pub struct PyBytes(PyObject, Unsendable);
pyobject_native_var_type!(PyBytes, ffi::PyBytes_Type, ffi::PyBytes_Check); pyobject_native_var_type!(PyBytes, ffi::PyBytes_Type, ffi::PyBytes_Check);
impl PyBytes { impl PyBytes {
/// Creates a new Python byte string object. /// Creates a new Python bytestring object.
/// The byte string is initialized by copying the data from the `&[u8]`. /// The bytestring is initialized by copying the data from the `&[u8]`.
/// ///
/// Panics if out of memory. /// Panics if out of memory.
pub fn new<'p>(py: Python<'p>, s: &[u8]) -> &'p PyBytes { 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)) } 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. /// Panics if out of memory.
pub unsafe fn from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> &PyBytes { 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] #[inline]
pub fn as_bytes(&self) -> &[u8] { pub fn as_bytes(&self) -> &[u8] {
unsafe { 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 { impl<I: SliceIndex<[u8]>> Index<I> for PyBytes {
type Output = I::Output; type Output = I::Output;

View File

@ -21,18 +21,18 @@ pyobject_native_type!(
); );
impl PyComplex { 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 { pub fn from_doubles(py: Python, real: c_double, imag: c_double) -> &PyComplex {
unsafe { unsafe {
let ptr = ffi::PyComplex_FromDoubles(real, imag); let ptr = ffi::PyComplex_FromDoubles(real, imag);
py.from_owned_ptr(ptr) 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 { pub fn real(&self) -> c_double {
unsafe { ffi::PyComplex_RealAsDouble(self.as_ptr()) } 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 { pub fn imag(&self) -> c_double {
unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) } unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) }
} }

View File

@ -51,8 +51,9 @@ impl PyDict {
} }
} }
/// Return a new dictionary that contains the same key-value pairs as self. /// Returns a new dictionary that contains the same key-value pairs as self.
/// Corresponds to `dict(self)` in Python. ///
/// This is equivalent to the Python expression `dict(self)`.
pub fn copy(&self) -> PyResult<&PyDict> { pub fn copy(&self) -> PyResult<&PyDict> {
unsafe { unsafe {
self.py() 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) { pub fn clear(&self) {
unsafe { ffi::PyDict_Clear(self.as_ptr()) } unsafe { ffi::PyDict_Clear(self.as_ptr()) }
} }
/// Return the number of items in the dictionary. /// 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 { pub fn len(&self) -> usize {
unsafe { ffi::PyDict_Size(self.as_ptr()) as 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 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`. /// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K) -> PyResult<bool> pub fn contains<K>(&self, key: K) -> PyResult<bool>
where where
@ -92,7 +95,10 @@ impl PyDict {
} }
/// Gets an item from the dictionary. /// 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> pub fn get_item<K>(&self, key: K) -> Option<&PyAny>
where where
K: ToBorrowedObject, K: ToBorrowedObject,
@ -104,7 +110,8 @@ impl PyDict {
} }
/// Sets an item value. /// 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<()> pub fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
where where
K: ToPyObject, K: ToPyObject,
@ -118,7 +125,8 @@ impl PyDict {
} }
/// Deletes an item. /// 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<()> pub fn del_item<K>(&self, key: K) -> PyResult<()>
where where
K: ToBorrowedObject, K: ToBorrowedObject,
@ -128,8 +136,9 @@ impl PyDict {
}) })
} }
/// List of dict keys. /// Returns a list of dict keys.
/// This is equivalent to the python expression `list(dict.keys())`. ///
/// This is equivalent to the Python expression `list(dict.keys())`.
pub fn keys(&self) -> &PyList { pub fn keys(&self) -> &PyList {
unsafe { unsafe {
self.py() self.py()
@ -137,8 +146,9 @@ impl PyDict {
} }
} }
/// List of dict values. /// Returns a list of dict values.
/// This is equivalent to the python expression `list(dict.values())`. ///
/// This is equivalent to the Python expression `list(dict.values())`.
pub fn values(&self) -> &PyList { pub fn values(&self) -> &PyList {
unsafe { unsafe {
self.py() self.py()
@ -146,8 +156,9 @@ impl PyDict {
} }
} }
/// List of dict items. /// Returns a list of dict items.
/// This is equivalent to the python expression `list(dict.items())`. ///
/// This is equivalent to the Python expression `list(dict.items())`.
pub fn items(&self) -> &PyList { pub fn items(&self) -> &PyList {
unsafe { unsafe {
self.py() 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 { pub fn iter(&self) -> PyDictIterator {
PyDictIterator { PyDictIterator {
dict: self.as_ref(), dict: self.as_ref(),

View File

@ -9,10 +9,10 @@ use crate::types::PyAny;
use crate::AsPyPointer; use crate::AsPyPointer;
use crate::Python; use crate::Python;
/// A python iterator object. /// A Python iterator object.
/// ///
/// Unlike other python objects, this class includes a `Python<'p>` token /// Unlike other Python objects, this class includes a `Python<'p>` token
/// so that `PyIterator` can implement the rust `Iterator` trait. /// so that `PyIterator` can implement the Rust `Iterator` trait.
/// ///
/// # Example /// # Example
/// ///
@ -60,6 +60,7 @@ impl<'p> Iterator for PyIterator<'p> {
type Item = PyResult<&'p PyAny>; type Item = PyResult<&'p PyAny>;
/// Retrieves the next item from an iterator. /// Retrieves the next item from an iterator.
///
/// Returns `None` when the iterator is exhausted. /// Returns `None` when the iterator is exhausted.
/// If an exception occurs, returns `Some(Err(..))`. /// If an exception occurs, returns `Some(Err(..))`.
/// Further `next()` calls after an exception occurs are likely /// Further `next()` calls after an exception occurs are likely

View File

@ -20,7 +20,7 @@ pub struct PyList(PyObject, Unsendable);
pyobject_native_var_type!(PyList, ffi::PyList_Type, ffi::PyList_Check); pyobject_native_var_type!(PyList, ffi::PyList_Type, ffi::PyList_Check);
impl PyList { 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 pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
where where
T: ToPyObject, T: ToPyObject,
@ -38,18 +38,18 @@ impl PyList {
} }
} }
/// Construct a new empty list. /// Constructs a new empty list.
pub fn empty(py: Python) -> &PyList { pub fn empty(py: Python) -> &PyList {
unsafe { py.from_owned_ptr::<PyList>(ffi::PyList_New(0)) } 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 { pub fn len(&self) -> usize {
// non-negative Py_ssize_t should always fit into Rust usize // non-negative Py_ssize_t should always fit into Rust usize
unsafe { ffi::PyList_Size(self.as_ptr()) as 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 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<()> pub fn append<I>(&self, item: I) -> PyResult<()>
where where
I: ToBorrowedObject, 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 { pub fn iter(&self) -> PyListIterator {
PyListIterator { PyListIterator {
list: self, 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<()> { pub fn sort(&self) -> PyResult<()> {
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Sort(self.as_ptr())) } 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<()> { pub fn reverse(&self) -> PyResult<()> {
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Reverse(self.as_ptr())) } unsafe { err::error_on_minusone(self.py(), ffi::PyList_Reverse(self.as_ptr())) }
} }

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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::any::PyAny;
pub use self::boolobject::PyBool; pub use self::boolobject::PyBool;

View File

@ -25,23 +25,24 @@ pub struct PyModule(PyObject, Unsendable);
pyobject_native_var_type!(PyModule, ffi::PyModule_Type, ffi::PyModule_Check); pyobject_native_var_type!(PyModule, ffi::PyModule_Type, ffi::PyModule_Check);
impl PyModule { 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> { pub fn new<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
let name = CString::new(name)?; let name = CString::new(name)?;
unsafe { py.from_owned_ptr_or_err(ffi::PyModule_New(name.as_ptr())) } 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> { pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
let name = CString::new(name)?; let name = CString::new(name)?;
unsafe { py.from_owned_ptr_or_err(ffi::PyImport_ImportModule(name.as_ptr())) } unsafe { py.from_owned_ptr_or_err(ffi::PyImport_ImportModule(name.as_ptr())) }
} }
/// Loads the python code specified into a new 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 /// `code` is the raw Python you want to load into the module.
/// (this is used when Python reports errors, for example) /// `file_name` is the file name to associate with the module
/// 'module_name' is the name to give 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>( pub fn from_code<'p>(
py: Python<'p>, py: Python<'p>,
code: &str, 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. /// May fail if the module does not have a `__name__` attribute.
pub fn name(&self) -> PyResult<&str> { pub fn name(&self) -> PyResult<&str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) } unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) }
} }
/// Gets the module filename. /// Returns the module's filename.
/// ///
/// May fail if the module does not have a `__file__` attribute. /// May fail if the module does not have a `__file__` attribute.
pub fn filename(&self) -> PyResult<&str> { pub fn filename(&self) -> PyResult<&str> {
@ -121,7 +122,8 @@ impl PyModule {
} }
/// Calls a function in the module. /// 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( pub fn call(
&self, &self,
name: &str, name: &str,
@ -131,20 +133,23 @@ impl PyModule {
self.getattr(name)?.call(args, kwargs) self.getattr(name)?.call(args, kwargs)
} }
/// Calls a function in the module. /// Calls a function in the module with only positional arguments.
/// This is equivalent to the Python expression: `getattr(module, name)()` ///
pub fn call0(&self, name: &str) -> PyResult<&PyAny> { /// This is equivalent to the Python expression `module.name(*args)`.
self.getattr(name)?.call0()
}
/// Calls a function in the module.
/// This is equivalent to the Python expression: `getattr(module, name)(*args)`
pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> { pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
self.getattr(name)?.call1(args) 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. /// 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> { pub fn get(&self, name: &str) -> PyResult<&PyAny> {
self.getattr(name) self.getattr(name)
} }

View File

@ -417,7 +417,7 @@ mod bigint_conversion {
assert_eq!(zero, BigInt::from(0)); 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] #[test]
fn check_overflow() { fn check_overflow() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();

View File

@ -12,13 +12,15 @@ use crate::types::{PyAny, PyList, PyTuple};
use crate::AsPyPointer; use crate::AsPyPointer;
use crate::{FromPyObject, PyTryFrom, ToBorrowedObject}; 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)] #[repr(transparent)]
pub struct PySequence(PyObject, Unsendable); pub struct PySequence(PyObject, Unsendable);
pyobject_native_type_named!(PySequence); pyobject_native_type_named!(PySequence);
impl 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] #[inline]
pub fn len(&self) -> PyResult<isize> { pub fn len(&self) -> PyResult<isize> {
let v = unsafe { ffi::PySequence_Size(self.as_ptr()) }; let v = unsafe { ffi::PySequence_Size(self.as_ptr()) };
@ -34,7 +36,9 @@ impl PySequence {
self.len().map(|l| l == 0) 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] #[inline]
pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> { pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> {
unsafe { unsafe {
@ -48,8 +52,9 @@ impl PySequence {
} }
} }
/// Return the result of repeating sequence object o count times. /// Returns the result of repeating a sequence object `count` times.
/// Equivalent to python `o * count` ///
/// This is equivalent to the Python expression `self * count`.
/// NB: Python accepts negative counts; it returns an empty Sequence. /// NB: Python accepts negative counts; it returns an empty Sequence.
#[inline] #[inline]
pub fn repeat(&self, count: isize) -> PyResult<&PySequence> { 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] #[inline]
pub fn in_place_concat(&self, other: &PySequence) -> PyResult<()> { pub fn in_place_concat(&self, other: &PySequence) -> PyResult<()> {
unsafe { unsafe {
@ -77,8 +84,9 @@ impl PySequence {
} }
} }
/// Repeate sequence object o count times and store in self. /// Repeats the sequence object `count` times and updates `self`.
/// Equivalent to python `o *= count` ///
/// This is equivalent to the Python statement `self *= count`.
/// NB: Python accepts negative counts; it empties the Sequence. /// NB: Python accepts negative counts; it empties the Sequence.
#[inline] #[inline]
pub fn in_place_repeat(&self, count: isize) -> PyResult<()> { 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] #[inline]
pub fn get_item(&self, index: isize) -> PyResult<&PyAny> { pub fn get_item(&self, index: isize) -> PyResult<&PyAny> {
unsafe { unsafe {
@ -101,8 +111,9 @@ impl PySequence {
} }
} }
/// Return the slice of sequence object o between begin and end. /// Returns the slice of sequence object between `begin` and `end`.
/// This is the equivalent of the Python expression `o[begin:end]` ///
/// This is equivalent to the Python expression `self[begin:end]`.
#[inline] #[inline]
pub fn get_slice(&self, begin: isize, end: isize) -> PyResult<&PyAny> { pub fn get_slice(&self, begin: isize, end: isize) -> PyResult<&PyAny> {
unsafe { unsafe {
@ -114,8 +125,9 @@ impl PySequence {
} }
} }
/// Assign object v to the ith element of o. /// Assigns object `item` to the `i`th element of self.
/// Equivalent to Python statement `o[i] = v` ///
/// This is equivalent to the Python statement `self[i] = v`.
#[inline] #[inline]
pub fn set_item<I>(&self, i: isize, item: I) -> PyResult<()> pub fn set_item<I>(&self, i: isize, item: I) -> PyResult<()>
where where
@ -131,8 +143,9 @@ impl PySequence {
} }
} }
/// Delete the ith element of object o. /// Deletes the `i`th element of self.
/// Python statement `del o[i]` ///
/// This is equivalent to the Python statement `del self[i]`.
#[inline] #[inline]
pub fn del_item(&self, i: isize) -> PyResult<()> { pub fn del_item(&self, i: isize) -> PyResult<()> {
unsafe { unsafe {
@ -143,8 +156,9 @@ impl PySequence {
} }
} }
/// Assign the sequence object v to the slice in sequence object o from i1 to i2. /// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`.
/// This is the equivalent of the Python statement `o[i1:i2] = v` ///
/// This is equivalent to the Python statement `self[i1:i2] = v`.
#[inline] #[inline]
pub fn set_slice(&self, i1: isize, i2: isize, v: &PyAny) -> PyResult<()> { pub fn set_slice(&self, i1: isize, i2: isize, v: &PyAny) -> PyResult<()> {
unsafe { unsafe {
@ -160,8 +174,9 @@ impl PySequence {
} }
} }
/// Delete the slice in sequence object o from i1 to i2. /// Deletes the slice from `i1` to `i2` from `self`.
/// equivalent of the Python statement `del o[i1:i2]` ///
/// This is equivalent to the Python statement `del self[i1:i2]`.
#[inline] #[inline]
pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<()> { pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<()> {
unsafe { unsafe {
@ -172,8 +187,8 @@ impl PySequence {
} }
} }
/// Return the number of occurrences of value in o, that is, return the number of keys for /// Returns the number of occurrences of `value` in self, that is, return the
/// which `o[key] == value` /// number of keys for which `self[key] == value`.
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub fn count<V>(&self, value: V) -> PyResult<usize> 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] #[inline]
pub fn contains<V>(&self, value: V) -> PyResult<bool> pub fn contains<V>(&self, value: V) -> PyResult<bool>
where where
@ -206,8 +223,9 @@ impl PySequence {
} }
} }
/// Return the first index `i` for which `o[i] == value`. /// Returns the first index `i` for which `self[i] == value`.
/// This is equivalent to the Python expression `o.index(value)` ///
/// This is equivalent to the Python expression `self.index(value)`.
#[inline] #[inline]
pub fn index<V>(&self, value: V) -> PyResult<usize> pub fn index<V>(&self, value: V) -> PyResult<usize>
where where
@ -223,7 +241,7 @@ impl PySequence {
} }
} }
/// Return a fresh list based on the Sequence. /// Returns a fresh list based on the Sequence.
#[inline] #[inline]
pub fn list(&self) -> PyResult<&PyList> { pub fn list(&self) -> PyResult<&PyList> {
unsafe { unsafe {
@ -232,7 +250,7 @@ impl PySequence {
} }
} }
/// Return a fresh tuple based on the Sequence. /// Returns a fresh tuple based on the Sequence.
#[inline] #[inline]
pub fn tuple(&self) -> PyResult<&PyTuple> { pub fn tuple(&self) -> PyResult<&PyTuple> {
unsafe { unsafe {

View File

@ -30,18 +30,20 @@ pyobject_native_type!(
); );
impl PySet { 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> { pub fn new<'p, T: ToPyObject>(py: Python<'p>, elements: &[T]) -> PyResult<&'p PySet> {
let list = elements.to_object(py); let list = elements.to_object(py);
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(list.as_ptr())) } 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> { pub fn empty<'p>(py: Python<'p>) -> PyResult<&'p PySet> {
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(ptr::null_mut())) } 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] #[inline]
pub fn clear(&self) { pub fn clear(&self) {
unsafe { unsafe {
@ -49,19 +51,21 @@ impl PySet {
} }
} }
/// Return the number of items in the set. /// Returns the number of items in the set.
/// This is equivalent to len(p) on a set. ///
/// This is equivalent to the Python expression `len(self)`.
#[inline] #[inline]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
unsafe { ffi::PySet_Size(self.as_ptr()) as 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 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`. /// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K) -> PyResult<bool> pub fn contains<K>(&self, key: K) -> PyResult<bool>
where 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) pub fn discard<K>(&self, key: K)
where where
K: ToPyObject, 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<()> pub fn add<K>(&self, key: K) -> PyResult<()>
where where
K: ToPyObject, 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> { pub fn pop(&self) -> Option<PyObject> {
let element = let element =
unsafe { PyObject::from_owned_ptr_or_err(self.py(), ffi::PySet_Pop(self.as_ptr())) }; unsafe { PyObject::from_owned_ptr_or_err(self.py(), ffi::PySet_Pop(self.as_ptr())) };

View File

@ -11,7 +11,7 @@ use std::os::raw::c_long;
/// Represents a Python `slice`. /// 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)] #[repr(transparent)]
pub struct PySlice(PyObject, Unsendable); pub struct PySlice(PyObject, Unsendable);
@ -22,7 +22,7 @@ pyobject_native_type!(
ffi::PySlice_Check ffi::PySlice_Check
); );
/// Represents a Python `slice` indices /// Represents Python `slice` indices.
pub struct PySliceIndices { pub struct PySliceIndices {
pub start: isize, pub start: isize,
pub stop: isize, pub stop: isize,
@ -42,7 +42,7 @@ impl PySliceIndices {
} }
impl PySlice { 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 { pub fn new(py: Python, start: isize, stop: isize, step: isize) -> &PySlice {
unsafe { unsafe {
let ptr = ffi::PySlice_New( 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] #[inline]
pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> { pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> {
// non-negative Py_ssize_t should always fit into Rust usize // non-negative Py_ssize_t should always fit into Rust usize

View File

@ -14,9 +14,9 @@ use std::os::raw::c_char;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::str; 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)] #[repr(transparent)]
pub struct PyString(PyObject, Unsendable); 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 /// Returns a `UnicodeEncodeError` if the input is not valid unicode
/// (containing unpaired surrogates). /// (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>> { pub fn to_string(&self) -> PyResult<Cow<str>> {
let bytes = self.as_bytes()?; let bytes = self.as_bytes()?;
let string = std::str::from_utf8(bytes)?; let string = std::str::from_utf8(bytes)?;
Ok(Cow::Borrowed(string)) 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 /// 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> { pub fn to_string_lossy(&self) -> Cow<str> {
match self.to_string() { match self.to_string() {
Ok(s) => s, 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. /// See `PyString::new` for details on the conversion.
impl ToPyObject for str { impl ToPyObject for str {
#[inline] #[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. /// See `PyString::new` for details on the conversion.
impl<'a> ToPyObject for Cow<'a, str> { impl<'a> ToPyObject for Cow<'a, str> {
#[inline] #[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. /// See `PyString::new` for details on the conversion.
impl ToPyObject for String { impl ToPyObject for String {
#[inline] #[inline]

View File

@ -15,13 +15,15 @@ use crate::{FromPyObject, IntoPy, PyTryFrom, ToPyObject};
use std::slice; use std::slice;
/// Represents a Python `tuple` object. /// Represents a Python `tuple` object.
///
/// This type is immutable.
#[repr(transparent)] #[repr(transparent)]
pub struct PyTuple(PyObject, Unsendable); pub struct PyTuple(PyObject, Unsendable);
pyobject_native_var_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check); pyobject_native_var_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check);
impl PyTuple { 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 pub fn new<T, U>(py: Python, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyTuple
where where
T: ToPyObject, 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 { pub fn empty(py: Python) -> &PyTuple {
unsafe { py.from_owned_ptr(ffi::PyTuple_New(0)) } 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 { pub fn is_empty(&self) -> bool {
self.len() == 0 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> { 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)) } 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> { pub fn split_from(&self, low: isize) -> Py<PyTuple> {
unsafe { unsafe {
let ptr = 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. /// Panics if the index is out of range.
pub fn get_item(&self, index: usize) -> &PyAny { 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] { pub fn as_slice(&self) -> &[PyObject] {
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject, // This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
// and because tuples are immutable. // and because tuples are immutable.

View File

@ -20,6 +20,7 @@ pub struct PyType(PyObject, Unsendable);
pyobject_native_var_type!(PyType, ffi::PyType_Type, ffi::PyType_Check); pyobject_native_var_type!(PyType, ffi::PyType_Type, ffi::PyType_Check);
impl PyType { impl PyType {
/// Creates a new type object.
#[inline] #[inline]
pub fn new<T: PyTypeObject>() -> Py<PyType> { pub fn new<T: PyTypeObject>() -> Py<PyType> {
T::type_object() T::type_object()
@ -31,7 +32,7 @@ impl PyType {
self.as_ptr() as *mut ffi::PyTypeObject 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. /// This increments the reference count on the type object.
/// Undefined behavior if the pointer is NULL or invalid. /// Undefined behavior if the pointer is NULL or invalid.
#[inline] #[inline]
@ -39,12 +40,14 @@ impl PyType {
py.from_borrowed_ptr(p as *mut ffi::PyObject) 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> { pub fn name(&self) -> Cow<str> {
unsafe { CStr::from_ptr((*self.as_type_ptr()).tp_name).to_string_lossy() } 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> pub fn is_subclass<T>(&self) -> PyResult<bool>
where where
T: PyTypeObject, 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> { pub fn is_instance<T: AsPyPointer>(&self, obj: &T) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr()) }; let result = unsafe { ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr()) };
if result == -1 { if result == -1 {