Skip to main content

pyo3/types/
mod.rs

1//! Various types defined by the Python interpreter such as `int`, `str` and `tuple`.
2
3pub use self::any::{PyAny, PyAnyMethods};
4pub use self::boolobject::{PyBool, PyBoolMethods};
5pub use self::bytearray::{PyByteArray, PyByteArrayMethods};
6pub use self::bytes::{PyBytes, PyBytesMethods};
7pub use self::capsule::{CapsuleName, PyCapsule, PyCapsuleMethods};
8pub use self::code::{PyCode, PyCodeInput, PyCodeMethods};
9pub use self::complex::{PyComplex, PyComplexMethods};
10pub use self::datetime::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess};
11#[cfg(not(Py_LIMITED_API))]
12pub use self::datetime::{PyDateAccess, PyDeltaAccess, PyTimeAccess};
13pub use self::dict::{IntoPyDict, PyDict, PyDictMethods};
14#[cfg(not(any(PyPy, GraalPy)))]
15pub use self::dict::{PyDictItems, PyDictKeys, PyDictValues};
16pub use self::ellipsis::PyEllipsis;
17pub use self::float::{PyFloat, PyFloatMethods};
18#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
19pub use self::frame::PyFrame;
20pub use self::frozenset::{PyFrozenSet, PyFrozenSetBuilder, PyFrozenSetMethods};
21pub use self::function::PyCFunction;
22#[cfg(not(Py_LIMITED_API))]
23pub use self::function::PyFunction;
24#[cfg(Py_3_9)]
25pub use self::genericalias::PyGenericAlias;
26pub use self::iterator::PyIterator;
27#[cfg(all(not(PyPy), Py_3_10))]
28pub use self::iterator::PySendResult;
29pub use self::list::{PyList, PyListMethods};
30pub use self::mapping::{PyMapping, PyMappingMethods};
31pub use self::mappingproxy::PyMappingProxy;
32pub use self::memoryview::PyMemoryView;
33pub use self::module::{PyModule, PyModuleMethods};
34#[cfg(all(not(Py_LIMITED_API), Py_3_13))]
35pub use self::mutex::{PyMutex, PyMutexGuard};
36pub use self::none::PyNone;
37pub use self::notimplemented::PyNotImplemented;
38pub use self::num::PyInt;
39pub use self::pysuper::PySuper;
40pub use self::range::{PyRange, PyRangeMethods};
41pub use self::sequence::{PySequence, PySequenceMethods};
42pub use self::set::{PySet, PySetMethods};
43pub use self::slice::{PySlice, PySliceIndices, PySliceMethods};
44#[cfg(not(Py_LIMITED_API))]
45pub use self::string::PyStringData;
46pub use self::string::{PyString, PyStringMethods};
47pub use self::traceback::{PyTraceback, PyTracebackMethods};
48pub use self::tuple::{PyTuple, PyTupleMethods};
49pub use self::typeobject::{PyType, PyTypeMethods};
50pub use self::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference};
51
52/// Iteration over Python collections.
53///
54/// When working with a Python collection, one approach is to convert it to a Rust collection such
55/// as `Vec` or `HashMap`. However this is a relatively expensive operation. If you just want to
56/// visit all their items, consider iterating over the collections directly:
57///
58/// # Examples
59///
60/// ```rust
61/// use pyo3::prelude::*;
62/// use pyo3::types::PyDict;
63/// use pyo3::ffi::c_str;
64///
65/// # pub fn main() -> PyResult<()> {
66/// Python::attach(|py| {
67///     let dict = py.eval(c"{'a':'b', 'c':'d'}", None, None)?.cast_into::<PyDict>()?;
68///
69///     for (key, value) in &dict {
70///         println!("key: {}, value: {}", key, value);
71///     }
72///
73///     Ok(())
74/// })
75/// # }
76///  ```
77///
78/// If PyO3 detects that the collection is mutated during iteration, it will panic.
79///
80/// These iterators use Python's C-API directly. However in certain cases, like when compiling for
81/// the Limited API and PyPy, the underlying structures are opaque and that may not be possible.
82/// In these cases the iterators are implemented by forwarding to [`PyIterator`].
83pub mod iter {
84    pub use super::dict::BoundDictIterator;
85    pub use super::frozenset::BoundFrozenSetIterator;
86    pub use super::list::BoundListIterator;
87    pub use super::set::BoundSetIterator;
88    pub use super::tuple::{BorrowedTupleIterator, BoundTupleIterator};
89}
90
91/// Python objects that have a base type.
92///
93/// This marks types that can be upcast into a [`PyAny`] and used in its place.
94/// This essentially includes every Python object except [`PyAny`] itself.
95///
96/// This is used to provide the [`Deref<Target = Bound<'_, PyAny>>`](std::ops::Deref)
97/// implementations for [`Bound<'_, T>`](crate::Bound).
98///
99/// Users should not need to implement this trait directly. It's implementation
100/// is provided by the [`#[pyclass]`](macro@crate::pyclass) attribute.
101///
102/// ## Note
103/// This is needed because the compiler currently tries to figure out all the
104/// types in a deref-chain before starting to look for applicable method calls.
105/// So we need to prevent [`Bound<'_, PyAny`](crate::Bound) dereferencing to
106/// itself in order to avoid running into the recursion limit. This trait is
107/// used to exclude this from our blanket implementation. See [this Rust
108/// issue][1] for more details. If the compiler limitation gets resolved, this
109/// trait will be removed.
110///
111/// [1]: https://github.com/rust-lang/rust/issues/19509
112pub trait DerefToPyAny {
113    // Empty.
114}
115
116// Implementations core to all native types except for PyAny (because they don't
117// make sense on PyAny / have different implementations).
118#[doc(hidden)]
119#[macro_export]
120macro_rules! pyobject_native_type_named (
121    ($name:ty $(;$generics:ident)*) => {
122        impl $crate::types::DerefToPyAny for $name {}
123    };
124);
125
126/// Helper for defining the `$typeobject` argument for other macros in this module.
127///
128/// # Safety
129///
130/// - `$typeobject` must be a known `static mut PyTypeObject`
131#[doc(hidden)]
132#[macro_export]
133macro_rules! pyobject_native_static_type_object(
134    ($typeobject:expr) => {
135        |_py| ::std::ptr::addr_of_mut!($typeobject)
136    };
137);
138
139/// Adds a TYPE_HINT constant if the `experimental-inspect`  feature is enabled.
140#[cfg(not(feature = "experimental-inspect"))]
141#[doc(hidden)]
142#[macro_export]
143macro_rules! pyobject_type_info_type_hint(
144    ($module:expr, $name:expr) => {};
145);
146
147#[cfg(feature = "experimental-inspect")]
148#[doc(hidden)]
149#[macro_export]
150macro_rules! pyobject_type_info_type_hint(
151    ($module:expr, $name:expr) => {
152        const TYPE_HINT: $crate::inspect::PyStaticExpr = $crate::type_hint_identifier!($module, $name);
153    };
154);
155
156/// Implements the `PyTypeInfo` trait for a native Python type.
157///
158/// # Safety
159///
160/// - `$typeobject` must be a function that produces a valid `*mut PyTypeObject`
161/// - `$checkfunction` must be a function that accepts arbitrary `*mut PyObject` and returns true /
162///   false according to whether the object is an instance of the type from `$typeobject`
163#[doc(hidden)]
164#[macro_export]
165macro_rules! pyobject_native_type_info(
166    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, $module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
167        // SAFETY: macro caller has upheld the safety contracts
168        unsafe impl<$($generics,)*> $crate::type_object::PyTypeInfo for $name {
169            const NAME: &'static str = stringify!($name);
170            const MODULE: ::std::option::Option<&'static str> = $module;
171            $crate::pyobject_type_info_type_hint!($type_hint_module, $type_hint_name);
172
173            #[inline]
174            #[allow(clippy::redundant_closure_call)]
175            fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {
176                $typeobject(py)
177            }
178
179            $(
180                #[inline]
181                fn is_type_of(obj: &$crate::Bound<'_, $crate::PyAny>) -> bool {
182                    #[allow(unused_unsafe, reason = "not all `$checkfunction` are unsafe fn")]
183                    // SAFETY: `$checkfunction` is being called with a valid `PyObject` pointer
184                    unsafe { $checkfunction(obj.as_ptr()) > 0 }
185                }
186            )?
187        }
188
189        impl $name {
190            #[doc(hidden)]
191            pub const _PYO3_DEF: $crate::impl_::pymodule::AddTypeToModule<Self> = $crate::impl_::pymodule::AddTypeToModule::new();
192
193            #[allow(dead_code)]
194            #[doc(hidden)]
195            pub const _PYO3_INTROSPECTION_ID: &'static str = concat!(stringify!($module), stringify!($name));
196        }
197    };
198);
199
200/// Declares all of the boilerplate for Python types.
201#[doc(hidden)]
202#[macro_export]
203macro_rules! pyobject_native_type_core {
204    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
205        $crate::pyobject_native_type_named!($name $(;$generics)*);
206        $crate::pyobject_native_type_info!($name, $typeobject, $type_hint_module, $type_hint_name, $module $(, #checkfunction=$checkfunction)? $(;$generics)*);
207    };
208    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
209        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name, #module=$module $(, #checkfunction=$checkfunction)? $(;$generics)*);
210    };
211    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
212        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name, #module=::std::option::Option::Some("builtins") $(, #checkfunction=$checkfunction)? $(;$generics)*);
213    };
214}
215
216#[doc(hidden)]
217#[macro_export]
218macro_rules! pyobject_subclassable_native_type {
219    ($name:ty, $layout:path $(;$generics:ident)*) => {
220        #[cfg(not(Py_LIMITED_API))]
221        impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name {
222            type LayoutAsBase = $crate::impl_::pycell::PyClassObjectBase<$layout>;
223            type BaseNativeType = $name;
224            type Initializer = $crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;
225            type PyClassMutability = $crate::pycell::impl_::ImmutableClass;
226            type Layout<T: $crate::impl_::pyclass::PyClassImpl> = $crate::impl_::pycell::PyStaticClassObject<T>;
227        }
228
229        #[cfg(all(Py_3_12, Py_LIMITED_API))]
230        impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name {
231            type LayoutAsBase = $crate::impl_::pycell::PyVariableClassObjectBase;
232            type BaseNativeType = Self;
233            type Initializer = $crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;
234            type PyClassMutability = $crate::pycell::impl_::ImmutableClass;
235            type Layout<T: $crate::impl_::pyclass::PyClassImpl> = $crate::impl_::pycell::PyVariableClassObject<T>;
236        }
237    }
238}
239
240#[doc(hidden)]
241#[macro_export]
242macro_rules! pyobject_native_type_sized {
243    ($name:ty, $layout:path $(;$generics:ident)*) => {
244        unsafe impl $crate::type_object::PyLayout<$name> for $layout {}
245        impl $crate::type_object::PySizedLayout<$name> for $layout {}
246    };
247}
248
249/// Declares all of the boilerplate for Python types which can be inherited from (because the exact
250/// Python layout is known).
251#[doc(hidden)]
252#[macro_export]
253macro_rules! pyobject_native_type {
254    ($name:ty, $layout:path, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr $(, #module=$module:expr)? $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
255        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name $(, #module=$module)? $(, #checkfunction=$checkfunction)? $(;$generics)*);
256        // To prevent inheriting native types with ABI3
257        #[cfg(not(Py_LIMITED_API))]
258        $crate::pyobject_native_type_sized!($name, $layout $(;$generics)*);
259    };
260}
261
262pub(crate) mod any;
263pub(crate) mod boolobject;
264pub(crate) mod bytearray;
265pub(crate) mod bytes;
266pub(crate) mod capsule;
267mod code;
268pub(crate) mod complex;
269pub(crate) mod datetime;
270pub(crate) mod dict;
271mod ellipsis;
272pub(crate) mod float;
273#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
274mod frame;
275pub(crate) mod frozenset;
276mod function;
277#[cfg(Py_3_9)]
278pub(crate) mod genericalias;
279pub(crate) mod iterator;
280pub(crate) mod list;
281pub(crate) mod mapping;
282pub(crate) mod mappingproxy;
283mod memoryview;
284pub(crate) mod module;
285#[cfg(all(not(Py_LIMITED_API), Py_3_13))]
286mod mutex;
287mod none;
288mod notimplemented;
289mod num;
290mod pysuper;
291pub(crate) mod range;
292pub(crate) mod sequence;
293pub(crate) mod set;
294pub(crate) mod slice;
295pub(crate) mod string;
296pub(crate) mod traceback;
297pub(crate) mod tuple;
298pub(crate) mod typeobject;
299pub(crate) mod weakref;