diff --git a/.cargo/config b/.cargo/config index 22c67c22..9d7fa21a 100644 --- a/.cargo/config +++ b/.cargo/config @@ -18,4 +18,4 @@ rustflags = [ "-Delided_lifetimes_in_paths", "-Dunused_lifetimes", "-Drust_2021_prelude_collisions" -] \ No newline at end of file +] diff --git a/src/buffer.rs b/src/buffer.rs index 2207aaba..f567176f 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -58,14 +58,23 @@ impl Debug for PyBuffer { /// Represents the type of a Python buffer element. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ElementType { - /// A signed integer type and its width in bytes. - SignedInteger { bytes: usize }, - /// An unsigned integer type and its width in bytes. - UnsignedInteger { bytes: usize }, + /// A signed integer type. + SignedInteger { + /// The width of the signed integer in bytes. + bytes: usize, + }, + /// An unsigned integer type. + UnsignedInteger { + /// The width of the unsigned integer in bytes. + bytes: usize, + }, /// A boolean type. Bool, - /// A float type and its width in bytes. - Float { bytes: usize }, + /// A float type. + Float { + /// The width of the float in bytes. + bytes: usize, + }, /// An unknown type. This may occur when parsing has failed. Unknown, } @@ -607,6 +616,8 @@ impl PyBuffer { } } + /// Release the buffer object, freeing the reference to the Python object + /// which owns the buffer. pub fn release(self, _py: Python<'_>) { // First move self into a ManuallyDrop, so that PyBuffer::drop will // never be called. (It would acquire the GIL and call PyBuffer_Release diff --git a/src/err/mod.rs b/src/err/mod.rs index 0c72918f..4fba4b8c 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -53,6 +53,8 @@ pub struct PyDowncastError<'a> { } impl<'a> PyDowncastError<'a> { + /// Create a new `PyDowncastError` representing a failure to convert the object + /// `from` into the type named in `to`. pub fn new(from: &'a PyAny, to: impl Into>) -> Self { PyDowncastError { from, diff --git a/src/impl_.rs b/src/impl_.rs index d1a51a8e..08ef053b 100644 --- a/src/impl_.rs +++ b/src/impl_.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + //! Internals of PyO3 which are accessed by code expanded from PyO3's procedural macros. //! //! Usage of any of these APIs in downstream code is implicitly acknowledging that these diff --git a/src/impl_/pymethods.rs b/src/impl_/pymethods.rs index 2bf20c65..6234d297 100644 --- a/src/impl_/pymethods.rs +++ b/src/impl_/pymethods.rs @@ -1,8 +1,8 @@ use crate::internal_tricks::{extract_cstr_or_leak_cstring, NulByteInString}; -use crate::{ffi, AsPyPointer, PyAny, PyObject, PyResult, Python}; +use crate::{ffi, PyAny, PyObject, PyResult, PyTraverseError, Python}; use std::ffi::CStr; use std::fmt; -use std::os::raw::{c_int, c_void}; +use std::os::raw::c_int; /// Python 3.8 and up - __ipow__ has modulo argument correctly populated. #[cfg(Py_3_8)] @@ -253,41 +253,6 @@ fn get_doc(doc: &'static str) -> Result<&'static CStr, NulByteInString> { extract_cstr_or_leak_cstring(doc, "Document cannot contain NUL byte.") } -#[repr(transparent)] -pub struct PyTraverseError(pub(crate) c_int); - -/// Object visitor for GC. -#[derive(Clone)] -pub struct PyVisit<'p> { - pub(crate) visit: ffi::visitproc, - pub(crate) arg: *mut c_void, - /// VisitProc contains a Python instance to ensure that - /// 1) it is cannot be moved out of the traverse() call - /// 2) it cannot be sent to other threads - pub(crate) _py: Python<'p>, -} - -impl<'p> PyVisit<'p> { - /// Visit `obj`. - pub fn call(&self, obj: &T) -> Result<(), PyTraverseError> - where - T: AsPyPointer, - { - let r = unsafe { (self.visit)(obj.as_ptr(), self.arg) }; - if r == 0 { - Ok(()) - } else { - Err(PyTraverseError(r)) - } - } - - /// Creates the PyVisit from the arguments to tp_traverse - #[doc(hidden)] - pub unsafe fn from_raw(visit: ffi::visitproc, arg: *mut c_void, _py: Python<'p>) -> Self { - Self { visit, arg, _py } - } -} - /// Unwraps the result of __traverse__ for tp_traverse #[doc(hidden)] #[inline] diff --git a/src/inspect/mod.rs b/src/inspect/mod.rs index 9ba27451..f14f8a2d 100644 --- a/src/inspect/mod.rs +++ b/src/inspect/mod.rs @@ -1,4 +1,4 @@ -/// Runtime inspection of objects exposed to Python. -/// -/// Tracking issue: . +//! Runtime inspection of objects exposed to Python. +//! +//! Tracking issue: . pub mod types; diff --git a/src/inspect/types.rs b/src/inspect/types.rs index aee4682d..d8f8e6a1 100644 --- a/src/inspect/types.rs +++ b/src/inspect/types.rs @@ -1,3 +1,5 @@ +//! Data types used to describe runtime Python types. + use std::borrow::Cow; use std::fmt::{Display, Formatter}; diff --git a/src/lib.rs b/src/lib.rs index 53631aec..618b8d74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![warn(missing_docs)] #![cfg_attr(feature = "nightly", feature(auto_traits, negative_impls))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr( @@ -310,7 +311,13 @@ pub use crate::type_object::PyTypeInfo; pub use crate::types::PyAny; pub use crate::version::PythonVersionInfo; -// Old directory layout, to be rethought? +/// Old module which contained some implementation details of the `#[pyproto]` module. +/// +/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead +/// of `use pyo3::class::basic::CompareOp`. +/// +/// For compatibility reasons this has not yet been removed, however will be done so +/// once is resolved. pub mod class { #[doc(hidden)] pub use crate::impl_::pymethods as methods; @@ -322,20 +329,48 @@ pub mod class { PyClassAttributeDef, PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef, }; + /// Old module which contained some implementation details of the `#[pyproto]` module. + /// + /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead + /// of `use pyo3::class::basic::CompareOp`. + /// + /// For compatibility reasons this has not yet been removed, however will be done so + /// once is resolved. pub mod basic { pub use crate::pyclass::CompareOp; } + /// Old module which contained some implementation details of the `#[pyproto]` module. + /// + /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterANextOutput` instead + /// of `use pyo3::class::pyasync::IterANextOutput`. + /// + /// For compatibility reasons this has not yet been removed, however will be done so + /// once is resolved. pub mod pyasync { pub use crate::pyclass::{IterANextOutput, PyIterANextOutput}; } + /// Old module which contained some implementation details of the `#[pyproto]` module. + /// + /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterNextOutput` instead + /// of `use pyo3::class::pyasync::IterNextOutput`. + /// + /// For compatibility reasons this has not yet been removed, however will be done so + /// once is resolved. pub mod iter { pub use crate::pyclass::{IterNextOutput, PyIterNextOutput}; } + /// Old module which contained some implementation details of the `#[pyproto]` module. + /// + /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead + /// of `use pyo3::class::gc::PyTraverseError`. + /// + /// For compatibility reasons this has not yet been removed, however will be done so + /// once is resolved. pub mod gc { - pub use crate::impl_::pymethods::{PyTraverseError, PyVisit}; + pub use crate::pyclass::{PyTraverseError, PyVisit}; } } diff --git a/src/once_cell.rs b/src/once_cell.rs index e0627e6f..ae966960 100644 --- a/src/once_cell.rs +++ b/src/once_cell.rs @@ -161,10 +161,12 @@ macro_rules! intern { pub struct Interned(&'static str, GILOnceCell>); impl Interned { + /// Creates an empty holder for an interned `str`. pub const fn new(value: &'static str) -> Self { Interned(value, GILOnceCell::new()) } + /// Gets or creates the interned `str` value. #[inline] pub fn get<'py>(&'py self, py: Python<'py>) -> &'py PyString { self.1 diff --git a/src/pycell/impl_.rs b/src/pycell/impl_.rs index 700fc711..958149ef 100644 --- a/src/pycell/impl_.rs +++ b/src/pycell/impl_.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] //! Crate-private implementation of pycell use std::cell::Cell; diff --git a/src/pyclass.rs b/src/pyclass.rs index d2343ea7..ffec5c9a 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -18,6 +18,10 @@ use std::{ ptr, }; +mod gc; + +pub use self::gc::{PyTraverseError, PyVisit}; + /// Types that can be used as Python classes. /// /// The `#[pyclass]` attribute implements this trait for your Rust struct - @@ -502,6 +506,7 @@ pub enum IterNextOutput { Return(U), } +/// Alias of `IterNextOutput` with `PyObject` yield & return values. pub type PyIterNextOutput = IterNextOutput; impl IntoPyCallbackOutput<*mut ffi::PyObject> for PyIterNextOutput { diff --git a/src/pyclass/gc.rs b/src/pyclass/gc.rs new file mode 100644 index 00000000..8203af07 --- /dev/null +++ b/src/pyclass/gc.rs @@ -0,0 +1,39 @@ +use std::os::raw::{c_int, c_void}; + +use crate::{ffi, AsPyPointer, Python}; + +/// Error returned by a `__traverse__` visitor implementation. +#[repr(transparent)] +pub struct PyTraverseError(pub(crate) c_int); + +/// Object visitor for GC. +#[derive(Clone)] +pub struct PyVisit<'p> { + pub(crate) visit: ffi::visitproc, + pub(crate) arg: *mut c_void, + /// VisitProc contains a Python instance to ensure that + /// 1) it is cannot be moved out of the traverse() call + /// 2) it cannot be sent to other threads + pub(crate) _py: Python<'p>, +} + +impl<'p> PyVisit<'p> { + /// Visit `obj`. + pub fn call(&self, obj: &T) -> Result<(), PyTraverseError> + where + T: AsPyPointer, + { + let r = unsafe { (self.visit)(obj.as_ptr(), self.arg) }; + if r == 0 { + Ok(()) + } else { + Err(PyTraverseError(r)) + } + } + + /// Creates the PyVisit from the arguments to tp_traverse + #[doc(hidden)] + pub unsafe fn from_raw(visit: ffi::visitproc, arg: *mut c_void, _py: Python<'p>) -> Self { + Self { visit, arg, _py } + } +} diff --git a/src/type_object.rs b/src/type_object.rs index 570f579c..4949eb87 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -96,6 +96,7 @@ pub struct LazyStaticType { } impl LazyStaticType { + /// Creates an uninitialized `LazyStaticType`. pub const fn new() -> Self { LazyStaticType { value: GILOnceCell::new(), @@ -104,6 +105,7 @@ impl LazyStaticType { } } + /// Gets the type object contained by this `LazyStaticType`, initializing it if needed. pub fn get_or_init(&self, py: Python<'_>) -> *mut ffi::PyTypeObject { fn inner() -> *mut ffi::PyTypeObject { // Safety: `py` is held by the caller of `get_or_init`. diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 79de3c38..4d78b44d 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -234,6 +234,7 @@ pyobject_native_type!( ); impl PyDateTime { + /// Creates a new `datetime.datetime` object. #[allow(clippy::too_many_arguments)] pub fn new<'p>( py: Python<'p>, diff --git a/src/types/dict.rs b/src/types/dict.rs index d87e0351..49eb5f41 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -262,6 +262,7 @@ impl PyDict { } } +/// PyO3 implementation of an iterator for a Python `dict` object. pub struct PyDictIterator<'py> { dict: &'py PyDict, ppos: ffi::Py_ssize_t, diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index cfe6348f..704c2591 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -89,6 +89,7 @@ mod impl_ { } } + /// PyO3 implementation of an iterator for a Python `frozenset` object. pub struct PyFrozenSetIterator<'p> { it: &'p PyIterator, } @@ -116,6 +117,7 @@ mod impl_ { } } + /// PyO3 implementation of an iterator for a Python `frozenset` object. pub struct PyFrozenSetIterator<'py> { set: &'py PyAny, pos: ffi::Py_ssize_t, diff --git a/src/types/set.rs b/src/types/set.rs index 6f425559..0488ee34 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -143,6 +143,7 @@ mod impl_ { } } + /// PyO3 implementation of an iterator for a Python `set` object. pub struct PySetIterator<'p> { it: &'p PyIterator, } @@ -165,6 +166,8 @@ mod impl_ { #[cfg(not(Py_LIMITED_API))] mod impl_ { use super::*; + + /// PyO3 implementation of an iterator for a Python `set` object. pub struct PySetIterator<'py> { set: &'py super::PyAny, pos: ffi::Py_ssize_t, diff --git a/src/types/slice.rs b/src/types/slice.rs index 5e3aa7af..460383b1 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -18,16 +18,21 @@ pyobject_native_type!( #checkfunction=ffi::PySlice_Check ); -/// Represents Python `slice` indices. +/// Return value from [`PySlice::indices`]. #[derive(Debug, Eq, PartialEq)] pub struct PySliceIndices { + /// Start of the slice pub start: isize, + /// End of the slice pub stop: isize, + /// Increment to use when iterating the slice from `start` to `stop`. pub step: isize, + /// The length of the slice calculated from the original input sequence. pub slicelength: isize, } impl PySliceIndices { + /// Creates a new `PySliceIndices`. pub fn new(start: isize, stop: isize, step: isize) -> PySliceIndices { PySliceIndices { start,