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

View File

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

View File

@ -2,7 +2,7 @@
//! Python Async/Await Interface.
//!
//! Check [python c-api information](
//! Check [the Python C API information](
//! https://docs.python.org/3/c-api/typeobj.html#async-object-structures)
//!
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! Conversions between various states of rust and python types and their wrappers.
//! Conversions between various states of Rust and Python types and their wrappers.
use crate::err::{self, PyDowncastError, PyResult};
use crate::object::PyObject;
use crate::type_object::{PyDowncastImpl, PyTypeInfo};
@ -9,9 +9,10 @@ use crate::types::PyTuple;
use crate::{ffi, gil, Py, PyCell, PyClass, PyNativeType, PyRef, PyRefMut, Python};
use std::ptr::NonNull;
/// This trait represents that, **we can do zero-cost conversion from the object to FFI pointer**.
/// This trait represents that **we can do zero-cost conversion from the object
/// to a FFI pointer**.
///
/// This trait is implemented for types that internally wrap a pointer to a python object.
/// This trait is implemented for types that internally wrap a pointer to a Python object.
///
/// # Example
///
@ -77,7 +78,7 @@ where
}
}
/// Conversion trait that allows various objects to be converted into `PyObject`
/// Conversion trait that allows various objects to be converted into `PyObject`.
pub trait ToPyObject {
/// Converts self into a Python object.
fn to_object(&self, py: Python) -> PyObject;
@ -161,23 +162,31 @@ impl<T> FromPy<T> for T {
/// `FromPyObject` is implemented by various types that can be extracted from
/// a Python object reference.
///
/// Normal usage is through the `PyObject::extract` helper method:
/// Normal usage is through the helper methods `PyObject::extract` or
/// `PyAny::extract`:
///
/// ```let obj: PyObject = ...;
/// let value: &TargetType = obj.extract(py)?;
///
/// let any: &PyAny = ...;
/// let value: &TargetType = any.extract()?;
/// ```
///
/// Note: depending on the implementation, the lifetime of the extracted result may
/// depend on the lifetime of the `obj` or the `prepared` variable.
///
/// For example, when extracting `&str` from a python byte string, the resulting string slice will
/// For example, when extracting `&str` from a Python byte string, the resulting string slice will
/// point to the existing string data (lifetime: `'source`).
/// On the other hand, when extracting `&str` from a python unicode string, the preparation step
/// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step
/// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`.
/// Since only which of these cases applies depends on the runtime type of the python object,
/// Since which case applies depends on the runtime type of the Python object,
/// both the `obj` and `prepared` variables must outlive the resulting string slice.
///
/// In cases where the result does not depend on the `'prepared` lifetime,
/// the inherent method `PyObject::extract()` can be used.
///
/// The trait's conversion method takes a `&PyAny` argument but is called
/// `FromPyObject` for historical reasons.
pub trait FromPyObject<'source>: Sized {
/// Extracts `Self` from the source `PyObject`.
fn extract(ob: &'source PyAny) -> PyResult<Self>;

View File

@ -16,9 +16,9 @@ use std::io;
use std::os::raw::c_char;
use std::ptr::NonNull;
/// Represents a `PyErr` value
/// Represents a `PyErr` value.
///
/// **CAUTION**
/// **Caution:**
///
/// When you construct an instance of `PyErrValue`, we highly recommend to use `from_err_args`
/// method. If you want to to construct `PyErrValue::ToArgs` directly, please do not forget to
@ -69,13 +69,22 @@ impl PyErr {
/// Creates a new PyErr of type `T`.
///
/// `value` can be:
/// * a tuple: the exception instance will be created using python `T(*tuple)`
/// * any other value: the exception instance will be created using python `T(value)`
/// * a tuple: the exception instance will be created using Python `T(*tuple)`
/// * any other value: the exception instance will be created using Python `T(value)`
///
/// Panics if `T` is not a python class derived from `BaseException`.
/// Panics if `T` is not a Python class derived from `BaseException`.
///
/// Example:
/// `return Err(PyErr::new::<exceptions::TypeError, _>("Error message"));`
/// ```
/// 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
where
T: PyTypeObject,
@ -91,7 +100,8 @@ impl PyErr {
}
}
/// Construct a new error, with the usual lazy initialization of Python exceptions.
/// Constructs a new error, with the usual lazy initialization of Python exceptions.
///
/// `exc` is the exception type; usually one of the standard exceptions
/// like `exceptions::RuntimeError`.
/// `args` is the a tuple of arguments to pass to the exception constructor.
@ -158,6 +168,7 @@ impl PyErr {
}
/// Retrieves the current error from the Python interpreter's global state.
///
/// The error is cleared from the Python interpreter.
/// If no error is set, returns a `SystemError`.
pub fn fetch(_: Python) -> PyErr {
@ -232,19 +243,21 @@ impl PyErr {
}
}
/// Print a standard traceback to sys.stderr.
/// Prints a standard traceback to `sys.stderr`.
pub fn print(self, py: Python) {
self.restore(py);
unsafe { ffi::PyErr_PrintEx(0) }
}
/// Print a standard traceback to sys.stderr.
/// Prints a standard traceback to `sys.stderr`, and sets
/// `sys.last_{type,value,traceback}` attributes to this exception's data.
pub fn print_and_set_sys_last_vars(self, py: Python) {
self.restore(py);
unsafe { ffi::PyErr_PrintEx(1) }
}
/// Return true if the current exception matches the exception in `exc`.
/// Returns true if the current exception matches the exception in `exc`.
///
/// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass.
/// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
pub fn matches<T>(&self, py: Python, exc: T) -> bool
@ -256,7 +269,7 @@ impl PyErr {
})
}
/// Return true if the current exception is instance of `T`
/// Returns true if the current exception is instance of `T`.
pub fn is_instance<T>(&self, _py: Python) -> bool
where
T: PyTypeObject,
@ -277,8 +290,8 @@ impl PyErr {
// This is safe as long as normalized() doesn't unwind due to a panic.
}
/// Helper function for normalizing the error by deconstructing and reconstructing the PyErr.
/// Must not panic for safety in normalize()
/// Helper function for normalizing the error by deconstructing and reconstructing the `PyErr`.
/// Must not panic for safety in `normalize()`.
fn into_normalized(self, py: Python) -> PyErr {
let PyErr {
ptype,
@ -302,6 +315,7 @@ impl PyErr {
}
/// Retrieves the exception instance for this error.
///
/// This method takes `mut self` because the error might need
/// to be normalized in order to create the exception instance.
fn instance(mut self, py: Python) -> PyObject {
@ -345,8 +359,8 @@ impl PyErr {
-1
}
/// Issue a warning message.
/// May return a PyErr if warnings-as-errors is enabled.
/// Issues a warning message.
/// May return a `PyErr` if warnings-as-errors is enabled.
pub fn warn(py: Python, category: &PyAny, message: &str, stacklevel: i32) -> PyResult<()> {
let message = CString::new(message)?;
unsafe {

View File

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

View File

@ -60,6 +60,7 @@ impl<T> Py<T> {
}
/// Creates a `Py<T>` instance for the given FFI pointer.
///
/// This moves ownership over the pointer into the `Py<T>`.
/// Undefined behavior if the pointer is NULL or invalid.
#[inline]
@ -72,7 +73,8 @@ impl<T> Py<T> {
}
/// Creates a `Py<T>` instance for the given FFI pointer.
/// Panics if the pointer is `null`.
///
/// Panics if the pointer is NULL.
/// Undefined behavior if the pointer is invalid.
#[inline]
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> {
@ -85,8 +87,9 @@ impl<T> Py<T> {
}
/// Construct `Py<T>` from the result of a Python FFI call that
/// returns a new reference (owned pointer).
/// Returns `Err(PyErr)` if the pointer is `null`.
///
/// Returns a new reference (owned pointer).
/// Returns `Err(PyErr)` if the pointer is NULL.
/// Unsafe because the pointer might be invalid.
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
match NonNull::new(ptr) {
@ -96,7 +99,8 @@ impl<T> Py<T> {
}
/// Creates a `Py<T>` instance for the given Python FFI pointer.
/// Calls Py_INCREF() on the ptr.
///
/// Calls `Py_INCREF()` on the ptr.
/// Undefined behavior if the pointer is NULL or invalid.
#[inline]
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> Py<T> {
@ -108,21 +112,21 @@ impl<T> Py<T> {
Py(NonNull::new_unchecked(ptr), PhantomData)
}
/// Gets the reference count of the ffi::PyObject pointer.
/// Gets the reference count of the `ffi::PyObject` pointer.
#[inline]
pub fn get_refcnt(&self) -> isize {
unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }
}
/// Clone self, Calls Py_INCREF() on the ptr.
/// Clones self by calling `Py_INCREF()` on the ptr.
#[inline]
pub fn clone_ref(&self, _py: Python) -> Py<T> {
unsafe { Py::from_borrowed_ptr(self.0.as_ptr()) }
}
/// Returns the inner pointer without decreasing the refcount
/// Returns the inner pointer without decreasing the refcount.
///
/// This will eventually move into its own trait
/// This will eventually move into its own trait.
pub(crate) fn into_non_null(self) -> NonNull<ffi::PyObject> {
let pointer = self.0;
mem::forget(self);
@ -146,6 +150,7 @@ impl<T> Py<T> {
/// let py = gil.python();
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0); // PyAny implements ObjectProtocol
/// ```
///
/// `Py<T>::as_ref` returns `&PyDict`, `&PyList` or so for native types, and `&PyCell<T>`
/// for `#[pyclass]`.
/// ```
@ -185,8 +190,8 @@ impl<T> ToPyObject for Py<T> {
}
impl<T> IntoPy<PyObject> for Py<T> {
/// Converts `Py` instance -> PyObject.
/// Consumes `self` without calling `Py_DECREF()`
/// Converts a `Py` instance to `PyObject`.
/// Consumes `self` without calling `Py_DECREF()`.
#[inline]
fn into_py(self, _py: Python) -> PyObject {
unsafe { PyObject::from_not_null(self.into_non_null()) }
@ -305,12 +310,12 @@ where
/// Reference to a converted [ToPyObject].
///
/// Many methods want to take anything that can be converted into a python object. This type
/// takes care of both types types that are already python object (i.e. implement
/// Many methods want to take anything that can be converted into a Python object. This type
/// takes care of both types types that are already Python object (i.e. implement
/// [AsPyPointer]) and those that don't (i.e. [ToPyObject] types).
/// For the [AsPyPointer] types, we just use the borrowed pointer, which is a lot faster
/// and simpler than creating a new extra object. The remaning [ToPyObject] types are
/// converted to python objects, the owned pointer is stored and decref'd on drop.
/// converted to Python objects, the owned pointer is stored and decref'd on drop.
///
/// # Example
///
@ -334,7 +339,7 @@ pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
}
/// This should eventually be replaced with a generic `IntoPy` trait impl by figuring
/// out the correct lifetime annotation to make the compiler happy
/// out the correct lifetime annotation to make the compiler happy.
impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
to_pyobject.to_managed_py_ref(py)
@ -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 {
/// Optionally converts into a python object and stores the pointer to the python heap.
/// Optionally converts into a Python object and stores the pointer to the python heap.
fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self>;
/// Dispatch over a xdecref and a noop drop impl
fn drop_impl(borrowed: &mut ManagedPyRef<Self>);
}
/// Case 1: It's a rust object which still needs to be converted to a python object.
/// Case 1: It's a Rust object which still needs to be converted to a Python object.
/// This means we're storing the owned pointer that into_ptr() has given us
/// and therefore need to xdecref when we're done.
///
@ -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.
impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
/// 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 types;
/// The proc macros, which are also part of the prelude
/// The proc macros, which are also part of the prelude.
pub mod proc_macro {
pub use pyo3cls::pymodule;
/// The proc macro attributes
pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto};
}
/// Returns a function that takes a [Python] instance and returns a python function.
/// Returns a function that takes a [Python] instance and returns a Python function.
///
/// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped].
#[macro_export]
@ -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].
#[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.
///
/// The built-in marshalling only supports a limited range of object.
/// The built-in marshalling only supports a limited range of objects.
/// The exact types supported depend on the version argument.
/// The [`VERSION`] constant holds the highest version currently supported.
///
/// See the [python documentation](https://docs.python.org/3/library/marshal.html) for more details.
/// See the [Python documentation](https://docs.python.org/3/library/marshal.html) for more details.
///
/// # Example:
/// ```

View File

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

View File

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

View File

@ -20,30 +20,31 @@ pub use gil::prepare_freethreaded_python;
/// Marker type that indicates that the GIL is currently held.
///
/// The 'Python' struct is a zero-size marker struct that is required for most Python operations.
/// The `Python` struct is a zero-sized marker struct that is required for most Python operations.
/// This is used to indicate that the operation accesses/modifies the Python interpreter state,
/// and thus can only be called if the Python interpreter is initialized and the
/// Python global interpreter lock (GIL) is acquired. The lifetime `'p` represents the lifetime of
/// the Python interpreter.
/// holding the lock.
///
/// Note that the GIL can be temporarily released by the python interpreter during a function call
/// Note that the GIL can be temporarily released by the Python interpreter during a function call
/// (e.g. importing a module), even when you're holding a GILGuard. In general, you don't need to
/// worry about this becauseas the GIL is reaquired before returning to the rust code:
/// worry about this because the GIL is reacquired before returning to the Rust code:
///
/// ```text
/// GILGuard |=====================================|
/// `Python` exists |=====================================|
/// GIL actually held |==========| |================|
/// Rust code running |=======| |==| |======|
/// ```
///
/// This behaviour can cause deadlocks when trying to lock while holding a GILGuard:
/// This behaviour can cause deadlocks when trying to lock a Rust mutex while
/// holding the GIL:
///
/// * Thread 1 acquires the GIL
/// * Thread 1 locks a mutex
/// * Thread 1 makes a call into the python interpreter, which releases the GIL
/// * Thread 1 makes a call into the Python interpreter which releases the GIL
/// * Thread 2 acquires the GIL
/// * Thread 2 tries to locks the mutex, blocks
/// * Thread 1's python interpreter call blocks trying to reacquire the GIL held by thread 2
/// * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2
///
/// To avoid deadlocking, you should release the GIL before trying to lock a mutex, e.g. with
/// [Python::allow_threads].
@ -51,8 +52,8 @@ pub use gil::prepare_freethreaded_python;
pub struct Python<'p>(PhantomData<&'p GILGuard>);
impl<'p> Python<'p> {
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
/// and stays acquired for the lifetime `'p`.
/// Retrieves a Python instance under the assumption that the GIL is already
/// acquired at this point, and stays acquired for the lifetime `'p`.
///
/// Because the output lifetime `'p` is not connected to any input parameter,
/// care must be taken that the compiler infers an appropriate lifetime for `'p`
@ -105,8 +106,16 @@ impl<'p> Python<'p> {
/// "#, None, Some(locals));
/// ```
///
/// **NOTE**
/// You cannot use all `&Py~` types in the closure that `allow_threads` takes.
/// **Note:**
/// PyO3 types that represent objects with a lifetime tied to holding the GIL
/// cannot be used in the closure. This includes `&PyAny` and all the
/// concrete-typed siblings, like `&PyString`.
///
/// You can convert such references to e.g. `PyObject` or `Py<PyString>`,
/// which makes them independent of the GIL lifetime. However, you cannot
/// do much with those without a `Python<'p>` token, for which you'd need to
/// reacquire the GIL.
///
/// # Example
/// ```compile_fail
/// # use pyo3::prelude::*;
@ -114,10 +123,9 @@ impl<'p> Python<'p> {
/// fn parallel_print(py: Python<'_>) {
/// let s = PyString::new(py, "This object should not be shared >_<");
/// py.allow_threads(move || {
/// println!("{:?}", s); // This causes compile error.
/// println!("{:?}", s); // This causes a compile error.
/// });
/// }
/// # Example
/// ```
pub fn allow_threads<T, F>(self, f: F) -> T
where
@ -193,8 +201,9 @@ impl<'p> Python<'p> {
}
/// Runs code in the given context.
/// `start` indicates the type of input expected:
/// one of `Py_single_input`, `Py_file_input`, or `Py_eval_input`.
///
/// `start` indicates the type of input expected: one of `Py_single_input`,
/// `Py_file_input`, or `Py_eval_input`.
///
/// If `globals` is `None`, it defaults to Python module `__main__`.
/// If `locals` is `None`, it defaults to the value of `globals`.
@ -237,17 +246,21 @@ impl<'p> Python<'p> {
unsafe { self.from_borrowed_ptr(T::type_object().into_ptr()) }
}
/// Import the Python module with the specified name.
/// Imports the Python module with the specified name.
pub fn import(self, name: &str) -> PyResult<&'p PyModule> {
PyModule::import(self, name)
}
/// Check whether `obj` is an instance of type `T` like Python `isinstance` function
/// Checks whether `obj` is an instance of type `T`.
///
/// This is equivalent to the Python `isinstance` function.
pub fn is_instance<T: PyTypeObject, V: AsPyPointer>(self, obj: &V) -> PyResult<bool> {
T::type_object().as_ref(self).is_instance(obj)
}
/// Check whether type `T` is subclass of type `U` like Python `issubclass` function
/// Checks whether type `T` is subclass of type `U`.
///
/// This is equivalent to the Python `issubclass` function.
pub fn is_subclass<T, U>(self) -> PyResult<bool>
where
T: PyTypeObject,
@ -272,7 +285,7 @@ impl<'p> Python<'p> {
}
impl<'p> Python<'p> {
/// Register object in release pool, and try to downcast to specific type.
/// Registers the object in the release pool, and tries to downcast to specific type.
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
where
T: PyTryFrom<'p>,
@ -281,7 +294,8 @@ impl<'p> Python<'p> {
<T as PyTryFrom>::try_from(obj)
}
/// Register object in release pool, and do unchecked downcast to specific type.
/// Registers the object in the release pool, and does an unchecked downcast
/// to the specific type.
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'p T
where
T: PyDowncastImpl + PyTypeInfo,
@ -290,7 +304,7 @@ impl<'p> Python<'p> {
T::unchecked_downcast(obj)
}
/// Register `ffi::PyObject` pointer in release pool
/// Registers the object pointer in the release pool.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyAny {
match NonNull::new(ptr) {
@ -299,8 +313,8 @@ impl<'p> Python<'p> {
}
}
/// Register `ffi::PyObject` pointer in release pool,
/// and do unchecked downcast to specific type.
/// Registers the object pointer in the release pool,
/// and does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
where
@ -309,9 +323,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr(self, ptr)
}
/// Register owned `ffi::PyObject` pointer in release pool.
/// Returns `Err(PyErr)` if the pointer is `null`.
/// do unchecked downcast to specific type.
/// Registers the owned object pointer in the release pool.
///
/// Returns `Err(PyErr)` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where
@ -320,9 +335,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr_or_err(self, ptr)
}
/// Register owned `ffi::PyObject` pointer in release pool.
/// Returns `None` if the pointer is `null`.
/// do unchecked downcast to specific type.
/// Registers the owned object pointer in release pool.
///
/// Returns `None` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where
@ -331,9 +347,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_owned_ptr_or_opt(self, ptr)
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Panics if the pointer is `null`.
/// do unchecked downcast to specific type.
/// Registers the borrowed object pointer in the release pool.
///
/// Panics if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
where
@ -342,9 +359,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_borrowed_ptr(self, ptr)
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Returns `Err(PyErr)` if the pointer is `null`.
/// do unchecked downcast to specific type.
/// Registers the borrowed object pointer in the release pool.
///
/// Returns `Err(PyErr)` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where
@ -353,9 +371,10 @@ impl<'p> Python<'p> {
FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Returns `None` if the pointer is `null`.
/// do unchecked downcast to specific `T`.
/// Registers the borrowed object pointer in the release pool.
///
/// Returns `None` if the pointer is NULL.
/// Does an unchecked downcast to the specific type.
#[allow(clippy::wrong_self_convention)]
pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where
@ -365,13 +384,13 @@ impl<'p> Python<'p> {
}
#[doc(hidden)]
/// Pass value ownership to `Python` object and get reference back.
/// Passes value ownership to `Python` object and get reference back.
/// Value get cleaned up on the GIL release.
pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
unsafe { gil::register_any(ob) }
}
/// Release PyObject reference.
/// Releases a PyObject reference.
#[inline]
pub fn release<T>(self, ob: T)
where
@ -385,7 +404,7 @@ impl<'p> Python<'p> {
}
}
/// Release `ffi::PyObject` pointer.
/// Releases a `ffi::PyObject` pointer.
#[inline]
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };

View File

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

View File

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

View File

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

View File

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

View File

@ -21,18 +21,18 @@ pyobject_native_type!(
);
impl PyComplex {
/// Creates a new Python `PyComplex` object, from its real and imaginary values.
/// Creates a new Python `complex` object, from its real and imaginary values.
pub fn from_doubles(py: Python, real: c_double, imag: c_double) -> &PyComplex {
unsafe {
let ptr = ffi::PyComplex_FromDoubles(real, imag);
py.from_owned_ptr(ptr)
}
}
/// Returns the real value of `PyComplex`.
/// Returns the real part of the complex number.
pub fn real(&self) -> c_double {
unsafe { ffi::PyComplex_RealAsDouble(self.as_ptr()) }
}
/// Returns the imaginary value of `PyComplex`.
/// Returns the imaginary part the complex number.
pub fn imag(&self) -> c_double {
unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) }
}

View File

@ -51,8 +51,9 @@ impl PyDict {
}
}
/// Return a new dictionary that contains the same key-value pairs as self.
/// Corresponds to `dict(self)` in Python.
/// Returns a new dictionary that contains the same key-value pairs as self.
///
/// This is equivalent to the Python expression `dict(self)`.
pub fn copy(&self) -> PyResult<&PyDict> {
unsafe {
self.py()
@ -60,23 +61,25 @@ impl PyDict {
}
}
/// Empty an existing dictionary of all key-value pairs.
/// Empties an existing dictionary of all key-value pairs.
pub fn clear(&self) {
unsafe { ffi::PyDict_Clear(self.as_ptr()) }
}
/// Return the number of items in the dictionary.
/// This is equivalent to len(p) on a dictionary.
///
/// This is equivalent to the Python expression `len(self)`.
pub fn len(&self) -> usize {
unsafe { ffi::PyDict_Size(self.as_ptr()) as usize }
}
/// Check if dict is empty.
/// Checks if the dict is empty, i.e. `len(self) == 0`.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Determine if the dictionary contains the specified key.
/// Determines if the dictionary contains the specified key.
///
/// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K) -> PyResult<bool>
where
@ -92,7 +95,10 @@ impl PyDict {
}
/// Gets an item from the dictionary.
/// Returns None if the item is not present, or if an error occurs.
///
/// Returns `None` if the item is not present, or if an error occurs.
///
/// To get a `KeyError` for non-existing keys, use `ObjectProtocol::get_item`.
pub fn get_item<K>(&self, key: K) -> Option<&PyAny>
where
K: ToBorrowedObject,
@ -104,7 +110,8 @@ impl PyDict {
}
/// Sets an item value.
/// This is equivalent to the Python expression `self[key] = value`.
///
/// This is equivalent to the Python statement `self[key] = value`.
pub fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
where
K: ToPyObject,
@ -118,7 +125,8 @@ impl PyDict {
}
/// Deletes an item.
/// This is equivalent to the Python expression `del self[key]`.
///
/// This is equivalent to the Python statement `del self[key]`.
pub fn del_item<K>(&self, key: K) -> PyResult<()>
where
K: ToBorrowedObject,
@ -128,8 +136,9 @@ impl PyDict {
})
}
/// List of dict keys.
/// This is equivalent to the python expression `list(dict.keys())`.
/// Returns a list of dict keys.
///
/// This is equivalent to the Python expression `list(dict.keys())`.
pub fn keys(&self) -> &PyList {
unsafe {
self.py()
@ -137,8 +146,9 @@ impl PyDict {
}
}
/// List of dict values.
/// This is equivalent to the python expression `list(dict.values())`.
/// Returns a list of dict values.
///
/// This is equivalent to the Python expression `list(dict.values())`.
pub fn values(&self) -> &PyList {
unsafe {
self.py()
@ -146,8 +156,9 @@ impl PyDict {
}
}
/// List of dict items.
/// This is equivalent to the python expression `list(dict.items())`.
/// Returns a list of dict items.
///
/// This is equivalent to the Python expression `list(dict.items())`.
pub fn items(&self) -> &PyList {
unsafe {
self.py()
@ -155,9 +166,10 @@ impl PyDict {
}
}
/// Returns a iterator of (key, value) pairs in this dictionary.
/// Returns an iterator of `(key, value)` pairs in this dictionary.
///
/// Note that it's unsafe to use when the dictionary might be changed by other code.
/// Note that it's unsafe to use when the dictionary might be changed by
/// other code.
pub fn iter(&self) -> PyDictIterator {
PyDictIterator {
dict: self.as_ref(),

View File

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

View File

@ -20,7 +20,7 @@ pub struct PyList(PyObject, Unsendable);
pyobject_native_var_type!(PyList, ffi::PyList_Type, ffi::PyList_Check);
impl PyList {
/// Construct a new list with the given elements.
/// Constructs a new list with the given elements.
pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
where
T: ToPyObject,
@ -38,18 +38,18 @@ impl PyList {
}
}
/// Construct a new empty list.
/// Constructs a new empty list.
pub fn empty(py: Python) -> &PyList {
unsafe { py.from_owned_ptr::<PyList>(ffi::PyList_New(0)) }
}
/// Gets the length of the list.
/// Returns the length of the list.
pub fn len(&self) -> usize {
// non-negative Py_ssize_t should always fit into Rust usize
unsafe { ffi::PyList_Size(self.as_ptr()) as usize }
}
/// Check if list is empty.
/// Checks if the list is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
@ -91,7 +91,7 @@ impl PyList {
}
}
/// Appends an item at the list.
/// Appends an item to the list.
pub fn append<I>(&self, item: I) -> PyResult<()>
where
I: ToBorrowedObject,
@ -113,7 +113,7 @@ impl PyList {
})
}
/// Returns an iterator over this list items.
/// Returns an iterator over this list's items.
pub fn iter(&self) -> PyListIterator {
PyListIterator {
list: self,
@ -121,12 +121,12 @@ impl PyList {
}
}
/// Sorts the list in-place. Equivalent to python `l.sort()`
/// Sorts the list in-place. Equivalent to the Python expression `l.sort()`.
pub fn sort(&self) -> PyResult<()> {
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Sort(self.as_ptr())) }
}
/// Reverses the list in-place. Equivalent to python `l.reverse()`
/// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`.
pub fn reverse(&self) -> PyResult<()> {
unsafe { err::error_on_minusone(self.py(), ffi::PyList_Reverse(self.as_ptr())) }
}

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! Various types defined by the python interpreter such as `int`, `str` and `tuple`
//! Various types defined by the Python interpreter such as `int`, `str` and `tuple`.
pub use self::any::PyAny;
pub use self::boolobject::PyBool;

View File

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

View File

@ -417,7 +417,7 @@ mod bigint_conversion {
assert_eq!(zero, BigInt::from(0));
}
/// `OverflowError` on converting python int to BigInt, see issue #629
/// `OverflowError` on converting Python int to BigInt, see issue #629
#[test]
fn check_overflow() {
let gil = Python::acquire_gil();

View File

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

View File

@ -30,18 +30,20 @@ pyobject_native_type!(
);
impl PySet {
/// Creates a new set.
/// Creates a new set with elements from the given slice.
///
/// Returns an error if some element is not hashable.
pub fn new<'p, T: ToPyObject>(py: Python<'p>, elements: &[T]) -> PyResult<&'p PySet> {
let list = elements.to_object(py);
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(list.as_ptr())) }
}
/// Creates a new empty set
/// Creates a new empty set.
pub fn empty<'p>(py: Python<'p>) -> PyResult<&'p PySet> {
unsafe { py.from_owned_ptr_or_err(ffi::PySet_New(ptr::null_mut())) }
}
/// Remove all elements from the set.
/// Removes all elements from the set.
#[inline]
pub fn clear(&self) {
unsafe {
@ -49,19 +51,21 @@ impl PySet {
}
}
/// Return the number of items in the set.
/// This is equivalent to len(p) on a set.
/// Returns the number of items in the set.
///
/// This is equivalent to the Python expression `len(self)`.
#[inline]
pub fn len(&self) -> usize {
unsafe { ffi::PySet_Size(self.as_ptr()) as usize }
}
/// Check if set is empty.
/// Checks if set is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Determine if the set contains the specified key.
/// Determines if the set contains the specified key.
///
/// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K) -> PyResult<bool>
where
@ -76,7 +80,7 @@ impl PySet {
})
}
/// Remove element from the set if it is present.
/// Removes the element from the set if it is present.
pub fn discard<K>(&self, key: K)
where
K: ToPyObject,
@ -86,7 +90,7 @@ impl PySet {
})
}
/// Add element to the set.
/// Adds an element to the set.
pub fn add<K>(&self, key: K) -> PyResult<()>
where
K: ToPyObject,
@ -96,7 +100,7 @@ impl PySet {
})
}
/// Remove and return an arbitrary element from the set
/// Removes and returns an arbitrary element from the set.
pub fn pop(&self) -> Option<PyObject> {
let element =
unsafe { PyObject::from_owned_ptr_or_err(self.py(), ffi::PySet_Pop(self.as_ptr())) };

View File

@ -11,7 +11,7 @@ use std::os::raw::c_long;
/// Represents a Python `slice`.
///
/// Only `c_long` indices supported at the moment by `PySlice` object.
/// Only `c_long` indices supported at the moment by the `PySlice` object.
#[repr(transparent)]
pub struct PySlice(PyObject, Unsendable);
@ -22,7 +22,7 @@ pyobject_native_type!(
ffi::PySlice_Check
);
/// Represents a Python `slice` indices
/// Represents Python `slice` indices.
pub struct PySliceIndices {
pub start: isize,
pub stop: isize,
@ -42,7 +42,7 @@ impl PySliceIndices {
}
impl PySlice {
/// Construct a new slice with the given elements.
/// Constructs a new slice with the given elements.
pub fn new(py: Python, start: isize, stop: isize, step: isize) -> &PySlice {
unsafe {
let ptr = ffi::PySlice_New(
@ -54,7 +54,9 @@ impl PySlice {
}
}
/// Retrieve the start, stop, and step indices from the slice object slice assuming a sequence of length length, and store the length of the slice in slicelength.
/// Retrieves the start, stop, and step indices from the slice object,
/// assuming a sequence of length `length`, and stores the length of the
/// slice in its `slicelength` member.
#[inline]
pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> {
// non-negative Py_ssize_t should always fit into Rust usize

View File

@ -14,9 +14,9 @@ use std::os::raw::c_char;
use std::ptr::NonNull;
use std::str;
/// Represents a Python `string`.
/// Represents a Python `string` (a Unicode string object).
///
/// This type is immutable
/// This type is immutable.
#[repr(transparent)]
pub struct PyString(PyObject, Unsendable);
@ -43,7 +43,7 @@ impl PyString {
}
}
/// Get the Python string as a byte slice.
/// Gets the Python string as a byte slice.
///
/// Returns a `UnicodeEncodeError` if the input is not valid unicode
/// (containing unpaired surrogates).
@ -60,17 +60,17 @@ impl PyString {
}
}
/// Convert the `PyString` into a Rust string.
/// Converts the `PyString` into a Rust string.
pub fn to_string(&self) -> PyResult<Cow<str>> {
let bytes = self.as_bytes()?;
let string = std::str::from_utf8(bytes)?;
Ok(Cow::Borrowed(string))
}
/// Convert the `PyString` into a Rust string.
/// Converts the `PyString` into a Rust string.
///
/// Unpaired surrogates invalid UTF-8 sequences are
/// replaced with U+FFFD REPLACEMENT CHARACTER.
/// replaced with `U+FFFD REPLACEMENT CHARACTER`.
pub fn to_string_lossy(&self) -> Cow<str> {
match self.to_string() {
Ok(s) => s,
@ -98,7 +98,7 @@ impl PyString {
}
}
/// Converts Rust `str` to Python object.
/// Converts a Rust `str` to a Python object.
/// See `PyString::new` for details on the conversion.
impl ToPyObject for str {
#[inline]
@ -114,7 +114,7 @@ impl<'a> IntoPy<PyObject> for &'a str {
}
}
/// Converts Rust `Cow<str>` to Python object.
/// Converts a Rust `Cow<str>` to a Python object.
/// See `PyString::new` for details on the conversion.
impl<'a> ToPyObject for Cow<'a, str> {
#[inline]
@ -123,7 +123,7 @@ impl<'a> ToPyObject for Cow<'a, str> {
}
}
/// Converts Rust `String` to Python object.
/// Converts a Rust `String` to a Python object.
/// See `PyString::new` for details on the conversion.
impl ToPyObject for String {
#[inline]

View File

@ -15,13 +15,15 @@ use crate::{FromPyObject, IntoPy, PyTryFrom, ToPyObject};
use std::slice;
/// Represents a Python `tuple` object.
///
/// This type is immutable.
#[repr(transparent)]
pub struct PyTuple(PyObject, Unsendable);
pyobject_native_var_type!(PyTuple, ffi::PyTuple_Type, ffi::PyTuple_Check);
impl PyTuple {
/// Construct a new tuple with the given elements.
/// Constructs a new tuple with the given elements.
pub fn new<T, U>(py: Python, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyTuple
where
T: ToPyObject,
@ -38,7 +40,7 @@ impl PyTuple {
}
}
/// Retrieves the empty tuple.
/// Constructs an empty tuple (on the Python side, a singleton object).
pub fn empty(py: Python) -> &PyTuple {
unsafe { py.from_owned_ptr(ffi::PyTuple_New(0)) }
}
@ -51,17 +53,17 @@ impl PyTuple {
}
}
/// Check if tuple is empty.
/// Checks if the tuple is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Take a slice of the tuple pointed to by p from low to high and return it as a new tuple.
/// Takes a slice of the tuple pointed from `low` to `high` and returns it as a new tuple.
pub fn slice(&self, low: isize, high: isize) -> Py<PyTuple> {
unsafe { Py::from_owned_ptr_or_panic(ffi::PyTuple_GetSlice(self.as_ptr(), low, high)) }
}
/// Take a slice of the tuple pointed to by p from low and return it as a new tuple.
/// Takes a slice of the tuple from `low` to the end and returns it as a new tuple.
pub fn split_from(&self, low: isize) -> Py<PyTuple> {
unsafe {
let ptr =
@ -70,7 +72,7 @@ impl PyTuple {
}
}
/// Gets the item at the specified index.
/// Gets the tuple item at the specified index.
///
/// Panics if the index is out of range.
pub fn get_item(&self, index: usize) -> &PyAny {
@ -83,6 +85,7 @@ impl PyTuple {
}
}
/// Returns `self` as a slice of objects.
pub fn as_slice(&self) -> &[PyObject] {
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
// and because tuples are immutable.

View File

@ -20,6 +20,7 @@ pub struct PyType(PyObject, Unsendable);
pyobject_native_var_type!(PyType, ffi::PyType_Type, ffi::PyType_Check);
impl PyType {
/// Creates a new type object.
#[inline]
pub fn new<T: PyTypeObject>() -> Py<PyType> {
T::type_object()
@ -31,7 +32,7 @@ impl PyType {
self.as_ptr() as *mut ffi::PyTypeObject
}
/// Retrieves the PyType instance for the given FFI pointer.
/// Retrieves the `PyType` instance for the given FFI pointer.
/// This increments the reference count on the type object.
/// Undefined behavior if the pointer is NULL or invalid.
#[inline]
@ -39,12 +40,14 @@ impl PyType {
py.from_borrowed_ptr(p as *mut ffi::PyObject)
}
/// Gets the name of the PyType.
/// Gets the name of the `PyType`.
pub fn name(&self) -> Cow<str> {
unsafe { CStr::from_ptr((*self.as_type_ptr()).tp_name).to_string_lossy() }
}
/// Check whether `self` is subclass of type `T` like Python `issubclass` function
/// Checks whether `self` is subclass of type `T`.
///
/// Equivalent to Python's `issubclass` function.
pub fn is_subclass<T>(&self) -> PyResult<bool>
where
T: PyTypeObject,
@ -59,7 +62,9 @@ impl PyType {
}
}
// Check whether `obj` is an instance of `self`
/// Check whether `obj` is an instance of `self`.
///
/// Equivalent to Python's `isinstance` function.
pub fn is_instance<T: AsPyPointer>(&self, obj: &T) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr()) };
if result == -1 {