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::{PyCapsule, PyCapsuleMethods};
8#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
9pub use self::code::PyCode;
10pub use self::complex::{PyComplex, PyComplexMethods};
11#[allow(deprecated)]
12#[cfg(all(not(Py_LIMITED_API), feature = "gil-refs"))]
13pub use self::datetime::timezone_utc;
14#[cfg(not(Py_LIMITED_API))]
15pub use self::datetime::{
16    timezone_utc_bound, PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime,
17    PyTimeAccess, PyTzInfo, PyTzInfoAccess,
18};
19pub use self::dict::{IntoPyDict, PyDict, PyDictMethods};
20#[cfg(not(any(PyPy, GraalPy)))]
21pub use self::dict::{PyDictItems, PyDictKeys, PyDictValues};
22pub use self::ellipsis::PyEllipsis;
23pub use self::float::{PyFloat, PyFloatMethods};
24#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
25pub use self::frame::PyFrame;
26pub use self::frozenset::{PyFrozenSet, PyFrozenSetBuilder, PyFrozenSetMethods};
27pub use self::function::PyCFunction;
28#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
29pub use self::function::PyFunction;
30pub use self::iterator::PyIterator;
31pub use self::list::{PyList, PyListMethods};
32pub use self::mapping::{PyMapping, PyMappingMethods};
33pub use self::memoryview::PyMemoryView;
34pub use self::module::{PyModule, PyModuleMethods};
35pub use self::none::PyNone;
36pub use self::notimplemented::PyNotImplemented;
37pub use self::num::PyLong;
38pub use self::num::PyLong as PyInt;
39#[cfg(not(any(PyPy, GraalPy)))]
40pub use self::pysuper::PySuper;
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, PyString as PyUnicode, 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///
64/// # pub fn main() -> PyResult<()> {
65/// Python::with_gil(|py| {
66///     let dict = py.eval_bound("{'a':'b', 'c':'d'}", None, None)?.downcast_into::<PyDict>()?;
67///
68///     for (key, value) in &dict {
69///         println!("key: {}, value: {}", key, value);
70///     }
71///
72///     Ok(())
73/// })
74/// # }
75///  ```
76///
77/// If PyO3 detects that the collection is mutated during iteration, it will panic.
78///
79/// These iterators use Python's C-API directly. However in certain cases, like when compiling for
80/// the Limited API and PyPy, the underlying structures are opaque and that may not be possible.
81/// In these cases the iterators are implemented by forwarding to [`PyIterator`].
82pub mod iter {
83    pub use super::dict::BoundDictIterator;
84    pub use super::frozenset::BoundFrozenSetIterator;
85    pub use super::list::BoundListIterator;
86    pub use super::set::BoundSetIterator;
87    pub use super::tuple::{BorrowedTupleIterator, BoundTupleIterator};
88
89    #[cfg(feature = "gil-refs")]
90    pub use super::{
91        dict::PyDictIterator, frozenset::PyFrozenSetIterator, list::PyListIterator,
92        set::PySetIterator, tuple::PyTupleIterator,
93    };
94}
95
96/// Python objects that have a base type.
97///
98/// This marks types that can be upcast into a [`PyAny`] and used in its place.
99/// This essentially includes every Python object except [`PyAny`] itself.
100///
101/// This is used to provide the [`Deref<Target = Bound<'_, PyAny>>`](std::ops::Deref)
102/// implementations for [`Bound<'_, T>`](crate::Bound).
103///
104/// Users should not need to implement this trait directly. It's implementation
105/// is provided by the [`#[pyclass]`](macro@crate::pyclass) attribute.
106///
107/// ## Note
108/// This is needed because the compiler currently tries to figure out all the
109/// types in a deref-chain before starting to look for applicable method calls.
110/// So we need to prevent [`Bound<'_, PyAny`](crate::Bound) dereferencing to
111/// itself in order to avoid running into the recursion limit. This trait is
112/// used to exclude this from our blanket implementation. See [this Rust
113/// issue][1] for more details. If the compiler limitation gets resolved, this
114/// trait will be removed.
115///
116/// [1]: https://github.com/rust-lang/rust/issues/19509
117pub trait DerefToPyAny {
118    // Empty.
119}
120
121// Implementations core to all native types
122#[doc(hidden)]
123#[macro_export]
124#[cfg_attr(docsrs, doc(cfg(all())))]
125#[cfg(not(feature = "gil-refs"))]
126macro_rules! pyobject_native_type_base(
127    // empty implementation on non-gil-refs
128    ($name:ty $(;$generics:ident)* ) => {};
129);
130
131// Implementations core to all native types
132#[doc(hidden)]
133#[macro_export]
134#[cfg_attr(docsrs, doc(cfg(all())))]
135#[cfg(feature = "gil-refs")]
136macro_rules! pyobject_native_type_base(
137    ($name:ty $(;$generics:ident)* ) => {
138        unsafe impl<$($generics,)*> $crate::PyNativeType for $name {
139            type AsRefSource = Self;
140        }
141
142        impl<$($generics,)*> ::std::fmt::Debug for $name {
143            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>)
144                   -> ::std::result::Result<(), ::std::fmt::Error>
145            {
146                use $crate::{PyNativeType, types::{PyAnyMethods, PyStringMethods}};
147                let s = self.as_borrowed().repr().or(::std::result::Result::Err(::std::fmt::Error))?;
148                f.write_str(&s.to_string_lossy())
149            }
150        }
151
152        impl<$($generics,)*> ::std::fmt::Display for $name {
153            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>)
154                   -> ::std::result::Result<(), ::std::fmt::Error>
155            {
156                use $crate::{PyNativeType, types::{PyAnyMethods, PyStringMethods, PyTypeMethods}};
157                match self.as_borrowed().str() {
158                    ::std::result::Result::Ok(s) => return f.write_str(&s.to_string_lossy()),
159                    ::std::result::Result::Err(err) => err.write_unraisable_bound(self.py(), ::std::option::Option::Some(&self.as_borrowed())),
160                }
161
162                match self.as_borrowed().get_type().name() {
163                    ::std::result::Result::Ok(name) => ::std::write!(f, "<unprintable {} object>", name),
164                    ::std::result::Result::Err(_err) => f.write_str("<unprintable object>"),
165                }
166            }
167        }
168
169        impl<$($generics,)*> $crate::ToPyObject for $name
170        {
171            #[inline]
172            fn to_object(&self, py: $crate::Python<'_>) -> $crate::PyObject {
173                unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
174            }
175        }
176    };
177);
178
179// Implementations core to all native types except for PyAny (because they don't
180// make sense on PyAny / have different implementations).
181#[doc(hidden)]
182#[macro_export]
183#[cfg_attr(docsrs, doc(cfg(all())))]
184#[cfg(not(feature = "gil-refs"))]
185macro_rules! pyobject_native_type_named (
186    ($name:ty $(;$generics:ident)*) => {
187
188        impl<$($generics,)*> ::std::convert::AsRef<$crate::PyAny> for $name {
189            #[inline]
190            fn as_ref(&self) -> &$crate::PyAny {
191                &self.0
192            }
193        }
194
195        impl<$($generics,)*> ::std::ops::Deref for $name {
196            type Target = $crate::PyAny;
197
198            #[inline]
199            fn deref(&self) -> &$crate::PyAny {
200                &self.0
201            }
202        }
203
204        impl $crate::types::DerefToPyAny for $name {}
205    };
206);
207
208#[doc(hidden)]
209#[macro_export]
210#[cfg_attr(docsrs, doc(cfg(all())))]
211#[cfg(feature = "gil-refs")]
212macro_rules! pyobject_native_type_named (
213    ($name:ty $(;$generics:ident)*) => {
214        $crate::pyobject_native_type_base!($name $(;$generics)*);
215
216        impl<$($generics,)*> ::std::convert::AsRef<$crate::PyAny> for $name {
217            #[inline]
218            fn as_ref(&self) -> &$crate::PyAny {
219                &self.0
220            }
221        }
222
223        impl<$($generics,)*> ::std::ops::Deref for $name {
224            type Target = $crate::PyAny;
225
226            #[inline]
227            fn deref(&self) -> &$crate::PyAny {
228                &self.0
229            }
230        }
231
232        unsafe impl<$($generics,)*> $crate::AsPyPointer for $name {
233            /// Gets the underlying FFI pointer, returns a borrowed pointer.
234            #[inline]
235            fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
236                self.0.as_ptr()
237            }
238        }
239
240        // FIXME https://github.com/PyO3/pyo3/issues/3903
241        #[allow(unknown_lints, non_local_definitions)]
242        impl<$($generics,)*> $crate::IntoPy<$crate::Py<$name>> for &'_ $name {
243            #[inline]
244            fn into_py(self, py: $crate::Python<'_>) -> $crate::Py<$name> {
245                unsafe { $crate::Py::from_borrowed_ptr(py, self.as_ptr()) }
246            }
247        }
248
249        // FIXME https://github.com/PyO3/pyo3/issues/3903
250        #[allow(unknown_lints, non_local_definitions)]
251        impl<$($generics,)*> ::std::convert::From<&'_ $name> for $crate::Py<$name> {
252            #[inline]
253            fn from(other: &$name) -> Self {
254                use $crate::PyNativeType;
255                unsafe { $crate::Py::from_borrowed_ptr(other.py(), other.as_ptr()) }
256            }
257        }
258
259        // FIXME https://github.com/PyO3/pyo3/issues/3903
260        #[allow(unknown_lints, non_local_definitions)]
261        impl<'a, $($generics,)*> ::std::convert::From<&'a $name> for &'a $crate::PyAny {
262            fn from(ob: &'a $name) -> Self {
263                unsafe{&*(ob as *const $name as *const $crate::PyAny)}
264            }
265        }
266
267        impl $crate::types::DerefToPyAny for $name {}
268    };
269);
270
271#[doc(hidden)]
272#[macro_export]
273macro_rules! pyobject_native_static_type_object(
274    ($typeobject:expr) => {
275        |_py| {
276            #[allow(unused_unsafe)] // https://github.com/rust-lang/rust/pull/125834
277            unsafe { ::std::ptr::addr_of_mut!($typeobject) }
278        }
279    };
280);
281
282#[doc(hidden)]
283#[macro_export]
284macro_rules! pyobject_native_type_info(
285    ($name:ty, $typeobject:expr, $module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
286        unsafe impl<$($generics,)*> $crate::type_object::PyTypeInfo for $name {
287            const NAME: &'static str = stringify!($name);
288            const MODULE: ::std::option::Option<&'static str> = $module;
289
290            #[inline]
291            #[allow(clippy::redundant_closure_call)]
292            fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {
293                $typeobject(py)
294            }
295
296            $(
297                #[inline]
298                fn is_type_of_bound(obj: &$crate::Bound<'_, $crate::PyAny>) -> bool {
299                    #[allow(unused_unsafe)]
300                    unsafe { $checkfunction(obj.as_ptr()) > 0 }
301                }
302            )?
303        }
304
305        impl $name {
306            #[doc(hidden)]
307            pub const _PYO3_DEF: $crate::impl_::pymodule::AddTypeToModule<Self> = $crate::impl_::pymodule::AddTypeToModule::new();
308        }
309    };
310);
311
312// NOTE: This macro is not included in pyobject_native_type_base!
313// because rust-numpy has a special implementation.
314#[doc(hidden)]
315#[macro_export]
316#[cfg_attr(docsrs, doc(cfg(all())))]
317#[cfg(not(feature = "gil-refs"))]
318macro_rules! pyobject_native_type_extract {
319    // no body for non-gil-refs
320    ($name:ty $(;$generics:ident)*) => {};
321}
322
323// NOTE: This macro is not included in pyobject_native_type_base!
324// because rust-numpy has a special implementation.
325#[doc(hidden)]
326#[macro_export]
327#[cfg_attr(docsrs, doc(cfg(all())))]
328#[cfg(feature = "gil-refs")]
329macro_rules! pyobject_native_type_extract {
330    ($name:ty $(;$generics:ident)*) => {
331        // FIXME https://github.com/PyO3/pyo3/issues/3903
332        #[allow(unknown_lints, non_local_definitions)]
333        impl<'py, $($generics,)*> $crate::FromPyObject<'py> for &'py $name {
334            #[inline]
335            fn extract_bound(obj: &$crate::Bound<'py, $crate::PyAny>) -> $crate::PyResult<Self> {
336                ::std::clone::Clone::clone(obj).into_gil_ref().downcast().map_err(::std::convert::Into::into)
337            }
338        }
339    }
340}
341
342/// Declares all of the boilerplate for Python types.
343#[doc(hidden)]
344#[macro_export]
345macro_rules! pyobject_native_type_core {
346    ($name:ty, $typeobject:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
347        $crate::pyobject_native_type_named!($name $(;$generics)*);
348        $crate::pyobject_native_type_info!($name, $typeobject, $module $(, #checkfunction=$checkfunction)? $(;$generics)*);
349        $crate::pyobject_native_type_extract!($name $(;$generics)*);
350    };
351    ($name:ty, $typeobject:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
352        $crate::pyobject_native_type_core!($name, $typeobject, #module=::std::option::Option::Some("builtins") $(, #checkfunction=$checkfunction)? $(;$generics)*);
353    };
354}
355
356#[doc(hidden)]
357#[macro_export]
358macro_rules! pyobject_native_type_sized {
359    ($name:ty, $layout:path $(;$generics:ident)*) => {
360        unsafe impl $crate::type_object::PyLayout<$name> for $layout {}
361        impl $crate::type_object::PySizedLayout<$name> for $layout {}
362        impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name {
363            type LayoutAsBase = $crate::impl_::pycell::PyClassObjectBase<$layout>;
364            type BaseNativeType = $name;
365            type Initializer = $crate::pyclass_init::PyNativeTypeInitializer<Self>;
366            type PyClassMutability = $crate::pycell::impl_::ImmutableClass;
367        }
368    }
369}
370
371/// Declares all of the boilerplate for Python types which can be inherited from (because the exact
372/// Python layout is known).
373#[doc(hidden)]
374#[macro_export]
375macro_rules! pyobject_native_type {
376    ($name:ty, $layout:path, $typeobject:expr $(, #module=$module:expr)? $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {
377        $crate::pyobject_native_type_core!($name, $typeobject $(, #module=$module)? $(, #checkfunction=$checkfunction)? $(;$generics)*);
378        // To prevent inheriting native types with ABI3
379        #[cfg(not(Py_LIMITED_API))]
380        $crate::pyobject_native_type_sized!($name, $layout $(;$generics)*);
381    };
382}
383
384pub(crate) mod any;
385pub(crate) mod boolobject;
386pub(crate) mod bytearray;
387pub(crate) mod bytes;
388pub(crate) mod capsule;
389#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
390mod code;
391pub(crate) mod complex;
392#[cfg(not(Py_LIMITED_API))]
393pub(crate) mod datetime;
394pub(crate) mod dict;
395mod ellipsis;
396pub(crate) mod float;
397#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]
398mod frame;
399pub(crate) mod frozenset;
400mod function;
401pub(crate) mod iterator;
402pub(crate) mod list;
403pub(crate) mod mapping;
404mod memoryview;
405pub(crate) mod module;
406mod none;
407mod notimplemented;
408mod num;
409#[cfg(not(any(PyPy, GraalPy)))]
410mod pysuper;
411pub(crate) mod sequence;
412pub(crate) mod set;
413pub(crate) mod slice;
414pub(crate) mod string;
415pub(crate) mod traceback;
416pub(crate) mod tuple;
417pub(crate) mod typeobject;
418pub(crate) mod weakref;