pyo3/
lib.rs

1#![warn(missing_docs)]
2#![cfg_attr(
3    feature = "nightly",
4    feature(auto_traits, negative_impls, try_trait_v2, iter_advance_by)
5)]
6#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
7// Deny some lints in doctests.
8// Use `#[allow(...)]` locally to override.
9#![doc(test(attr(
10    deny(
11        rust_2018_idioms,
12        unused_lifetimes,
13        rust_2021_prelude_collisions,
14        warnings
15    ),
16    allow(
17        unused_variables,
18        unused_assignments,
19        unused_extern_crates,
20        // FIXME https://github.com/rust-lang/rust/issues/121621#issuecomment-1965156376
21        unknown_lints,
22        non_local_definitions,
23    )
24)))]
25
26//! Rust bindings to the Python interpreter.
27//!
28//! PyO3 can be used to write native Python modules or run Python code and modules from Rust.
29//!
30//! See [the guide] for a detailed introduction.
31//!
32//! # PyO3's object types
33//!
34//! PyO3 has several core types that you should familiarize yourself with:
35//!
36//! ## The `Python<'py>` object, and the `'py` lifetime
37//!
38//! Holding the [global interpreter lock] (GIL) is modeled with the [`Python<'py>`](Python) token. Many
39//! Python APIs require that the GIL is held, and PyO3 uses this token as proof that these APIs
40//! can be called safely. It can be explicitly acquired and is also implicitly acquired by PyO3
41//! as it wraps Rust functions and structs into Python functions and objects.
42//!
43//! The [`Python<'py>`](Python) token's lifetime `'py` is common to many PyO3 APIs:
44//! - Types that also have the `'py` lifetime, such as the [`Bound<'py, T>`](Bound) smart pointer, are
45//!   bound to the Python GIL and rely on this to offer their functionality. These types often
46//!   have a [`.py()`](Bound::py) method to get the associated [`Python<'py>`](Python) token.
47//! - Functions which depend on the `'py` lifetime, such as [`PyList::new`](types::PyList::new),
48//!   require a [`Python<'py>`](Python) token as an input. Sometimes the token is passed implicitly by
49//!   taking a [`Bound<'py, T>`](Bound) or other type which is bound to the `'py` lifetime.
50//! - Traits which depend on the `'py` lifetime, such as [`FromPyObject<'py>`](FromPyObject), usually have
51//!   inputs or outputs which depend on the lifetime. Adding the lifetime to the trait allows
52//!   these inputs and outputs to express their binding to the GIL in the Rust type system.
53//!
54//! ## Python object smart pointers
55//!
56//! PyO3 has two core smart pointers to refer to Python objects, [`Py<T>`](Py) and its GIL-bound
57//! form [`Bound<'py, T>`](Bound) which carries the `'py` lifetime. (There is also
58//! [`Borrowed<'a, 'py, T>`](instance::Borrowed), but it is used much more rarely).
59//!
60//! The type parameter `T` in these smart pointers can be filled by:
61//!   - [`PyAny`], e.g. `Py<PyAny>` or `Bound<'py, PyAny>`, where the Python object type is not
62//!     known. `Py<PyAny>` is so common it has a type alias [`PyObject`].
63//!   - Concrete Python types like [`PyList`](types::PyList) or [`PyTuple`](types::PyTuple).
64//!   - Rust types which are exposed to Python using the [`#[pyclass]`](macro@pyclass) macro.
65//!
66//! See the [guide][types] for an explanation of the different Python object types.
67//!
68//! ## PyErr
69//!
70//! The vast majority of operations in this library will return [`PyResult<...>`](PyResult).
71//! This is an alias for the type `Result<..., PyErr>`.
72//!
73//! A `PyErr` represents a Python exception. A `PyErr` returned to Python code will be raised as a
74//! Python exception. Errors from `PyO3` itself are also exposed as Python exceptions.
75//!
76//! # Feature flags
77//!
78//! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed
79//! description, see the [Features chapter of the guide].
80//!
81//! ## Default feature flags
82//!
83//! The following features are turned on by default:
84//! - `macros`: Enables various macros, including all the attribute macros.
85//!
86//! ## Optional feature flags
87//!
88//! The following features customize PyO3's behavior:
89//!
90//! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by
91//! [PEP 384] to be forward-compatible with future Python versions.
92//! - `auto-initialize`: Changes [`Python::with_gil`] to automatically initialize the Python
93//! interpreter if needed.
94//! - `extension-module`: This will tell the linker to keep the Python symbols unresolved, so that
95//! your module can also be used with statically linked Python interpreters. Use this feature when
96//! building an extension module.
97//! - `multiple-pymethods`: Enables the use of multiple [`#[pymethods]`](macro@crate::pymethods)
98//! blocks per [`#[pyclass]`](macro@crate::pyclass). This adds a dependency on the [inventory]
99//! crate, which is not supported on all platforms.
100//!
101//! The following features enable interactions with other crates in the Rust ecosystem:
102//! - [`anyhow`]: Enables a conversion from [anyhow]’s [`Error`][anyhow_error] type to [`PyErr`].
103//! - [`chrono`]: Enables a conversion from [chrono]'s structures to the equivalent Python ones.
104//! - [`chrono-tz`]: Enables a conversion from [chrono-tz]'s `Tz` enum. Requires Python 3.9+.
105//! - [`either`]: Enables conversions between Python objects and [either]'s [`Either`] type.
106//! - [`eyre`]: Enables a conversion from [eyre]’s [`Report`] type to [`PyErr`].
107//! - [`hashbrown`]: Enables conversions between Python objects and [hashbrown]'s [`HashMap`] and
108//! [`HashSet`] types.
109//! - [`indexmap`][indexmap_feature]: Enables conversions between Python dictionary and [indexmap]'s [`IndexMap`].
110//! - [`num-bigint`]: Enables conversions between Python objects and [num-bigint]'s [`BigInt`] and
111//! [`BigUint`] types.
112//! - [`num-complex`]: Enables conversions between Python objects and [num-complex]'s [`Complex`]
113//!  type.
114//! - [`num-rational`]: Enables conversions between Python's fractions.Fraction and [num-rational]'s types
115//! - [`rust_decimal`]: Enables conversions between Python's decimal.Decimal and [rust_decimal]'s
116//! [`Decimal`] type.
117//! - [`serde`]: Allows implementing [serde]'s [`Serialize`] and [`Deserialize`] traits for
118//! [`Py`]`<T>` for all `T` that implement [`Serialize`] and [`Deserialize`].
119//! - [`smallvec`][smallvec]: Enables conversions between Python list and [smallvec]'s [`SmallVec`].
120//!
121//! ## Unstable features
122//!
123//! - `nightly`: Uses  `#![feature(auto_traits, negative_impls)]` to define [`Ungil`] as an auto trait.
124//
125//! ## `rustc` environment flags
126//! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`, `Py_3_11`, `Py_3_12`, `Py_3_13`: Marks code that is
127//!    only enabled when compiling for a given minimum Python version.
128//! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled.
129//! - `Py_GIL_DISABLED`: Marks code that runs only in the free-threaded build of CPython.
130//! - `PyPy` - Marks code enabled when compiling for PyPy.
131//! - `GraalPy` - Marks code enabled when compiling for GraalPy.
132//!
133//! Additionally, you can query for the values `Py_DEBUG`, `Py_REF_DEBUG`,
134//! `Py_TRACE_REFS`, and `COUNT_ALLOCS` from `py_sys_config` to query for the
135//! corresponding C build-time defines. For example, to conditionally define
136//! debug code using `Py_DEBUG`, you could do:
137//!
138//! ```rust,ignore
139//! #[cfg(py_sys_config = "Py_DEBUG")]
140//! println!("only runs if python was compiled with Py_DEBUG")
141//! ```
142//! To use these attributes, add [`pyo3-build-config`] as a build dependency in
143//! your `Cargo.toml` and call `pyo3_build_config::use_pyo3_cfgs()` in a
144//! `build.rs` file.
145//!
146//! # Minimum supported Rust and Python versions
147//!
148//! Requires Rust 1.63 or greater.
149//!
150//! PyO3 supports the following Python distributions:
151//!   - CPython 3.7 or greater
152//!   - PyPy 7.3 (Python 3.9+)
153//!   - GraalPy 24.0 or greater (Python 3.10+)
154//!
155//! # Example: Building a native Python module
156//!
157//! PyO3 can be used to generate a native Python module. The easiest way to try this out for the
158//! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based
159//! Python packages with minimal configuration. The following steps set up some files for an example
160//! Python module, install `maturin`, and then show how to build and import the Python module.
161//!
162//! First, create a new folder (let's call it `string_sum`) containing the following two files:
163//!
164//! **`Cargo.toml`**
165//!
166//! ```toml
167//! [package]
168//! name = "string-sum"
169//! version = "0.1.0"
170//! edition = "2021"
171//!
172//! [lib]
173//! name = "string_sum"
174//! # "cdylib" is necessary to produce a shared library for Python to import from.
175//! #
176//! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
177//! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
178//! # crate-type = ["cdylib", "rlib"]
179//! crate-type = ["cdylib"]
180//!
181//! [dependencies.pyo3]
182#![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"),  "\"")]
183//! features = ["extension-module"]
184//! ```
185//!
186//! **`src/lib.rs`**
187//! ```rust
188//! use pyo3::prelude::*;
189//!
190//! /// Formats the sum of two numbers as string.
191//! #[pyfunction]
192//! fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
193//!     Ok((a + b).to_string())
194//! }
195//!
196//! /// A Python module implemented in Rust.
197//! #[pymodule]
198//! fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> {
199//!     m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
200//!
201//!     Ok(())
202//! }
203//! ```
204//!
205//! With those two files in place, now `maturin` needs to be installed. This can be done using
206//! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin`
207//! into it:
208//! ```bash
209//! $ cd string_sum
210//! $ python -m venv .env
211//! $ source .env/bin/activate
212//! $ pip install maturin
213//! ```
214//!
215//! Now build and execute the module:
216//! ```bash
217//! $ maturin develop
218//! # lots of progress output as maturin runs the compilation...
219//! $ python
220//! >>> import string_sum
221//! >>> string_sum.sum_as_string(5, 20)
222//! '25'
223//! ```
224//!
225//! As well as with `maturin`, it is possible to build using [setuptools-rust] or
226//! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further
227//! configuration.
228//!
229//! # Example: Using Python from Rust
230//!
231//! To embed Python into a Rust binary, you need to ensure that your Python installation contains a
232//! shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give
233//! some example code which runs an embedded Python interpreter.
234//!
235//! To install the Python shared library on Ubuntu:
236//! ```bash
237//! sudo apt install python3-dev
238//! ```
239//!
240//! Start a new project with `cargo new` and add  `pyo3` to the `Cargo.toml` like this:
241//! ```toml
242//! [dependencies.pyo3]
243#![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"),  "\"")]
244//! # this is necessary to automatically initialize the Python interpreter
245//! features = ["auto-initialize"]
246//! ```
247//!
248//! Example program displaying the value of `sys.version` and the current user name:
249//! ```rust
250//! use pyo3::prelude::*;
251//! use pyo3::types::IntoPyDict;
252//! use pyo3::ffi::c_str;
253//!
254//! fn main() -> PyResult<()> {
255//!     Python::with_gil(|py| {
256//!         let sys = py.import("sys")?;
257//!         let version: String = sys.getattr("version")?.extract()?;
258//!
259//!         let locals = [("os", py.import("os")?)].into_py_dict(py)?;
260//!         let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'");
261//!         let user: String = py.eval(code, None, Some(&locals))?.extract()?;
262//!
263//!         println!("Hello {}, I'm Python {}", user, version);
264//!         Ok(())
265//!     })
266//! }
267//! ```
268//!
269//! The guide has [a section][calling_rust] with lots of examples about this topic.
270//!
271//! # Other Examples
272//!
273//! The PyO3 [README](https://github.com/PyO3/pyo3#readme) contains quick-start examples for both
274//! using [Rust from Python] and [Python from Rust].
275//!
276//! The PyO3 repository's [examples subdirectory]
277//! contains some basic packages to demonstrate usage of PyO3.
278//!
279//! There are many projects using PyO3 - see a list of some at
280//! <https://github.com/PyO3/pyo3#examples>.
281//!
282//! [anyhow]: https://docs.rs/anyhow/ "A trait object based error system for easy idiomatic error handling in Rust applications."
283//! [anyhow_error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html "Anyhows `Error` type, a wrapper around a dynamic error type"
284//! [`anyhow`]: ./anyhow/index.html "Documentation about the `anyhow` feature."
285//! [inventory]: https://docs.rs/inventory
286//! [`HashMap`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html
287//! [`HashSet`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html
288//! [`SmallVec`]: https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html
289//! [`Uuid`]: https://docs.rs/uuid/latest/uuid/struct.Uuid.html
290//! [`IndexMap`]: https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html
291//! [`BigInt`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html
292//! [`BigUint`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html
293//! [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html
294//! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html
295//! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html
296//! [chrono]: https://docs.rs/chrono/ "Date and Time for Rust."
297//! [chrono-tz]: https://docs.rs/chrono-tz/ "TimeZone implementations for chrono from the IANA database."
298//! [`chrono`]: ./chrono/index.html "Documentation about the `chrono` feature."
299//! [`chrono-tz`]: ./chrono-tz/index.html "Documentation about the `chrono-tz` feature."
300//! [either]: https://docs.rs/either/ "A type that represents one of two alternatives."
301//! [`either`]: ./either/index.html "Documentation about the `either` feature."
302//! [`Either`]: https://docs.rs/either/latest/either/enum.Either.html
303//! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications."
304//! [`Report`]: https://docs.rs/eyre/latest/eyre/struct.Report.html
305//! [`eyre`]: ./eyre/index.html "Documentation about the `eyre` feature."
306//! [`hashbrown`]: ./hashbrown/index.html "Documentation about the `hashbrown` feature."
307//! [indexmap_feature]: ./indexmap/index.html "Documentation about the `indexmap` feature."
308//! [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages"
309//! [`num-bigint`]: ./num_bigint/index.html "Documentation about the `num-bigint` feature."
310//! [`num-complex`]: ./num_complex/index.html "Documentation about the `num-complex` feature."
311//! [`num-rational`]: ./num_rational/index.html "Documentation about the `num-rational` feature."
312//! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config
313//! [rust_decimal]: https://docs.rs/rust_decimal
314//! [`rust_decimal`]: ./rust_decimal/index.html "Documenation about the `rust_decimal` feature."
315//! [`Decimal`]: https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html
316//! [`serde`]: <./serde/index.html> "Documentation about the `serde` feature."
317#![doc = concat!("[calling_rust]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/python-from-rust.html \"Calling Python from Rust - PyO3 user guide\"")]
318//! [examples subdirectory]: https://github.com/PyO3/pyo3/tree/main/examples
319//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book"
320//! [global interpreter lock]: https://docs.python.org/3/glossary.html#term-global-interpreter-lock
321//! [hashbrown]: https://docs.rs/hashbrown
322//! [smallvec]: https://docs.rs/smallvec
323//! [uuid]: https://docs.rs/uuid
324//! [indexmap]: https://docs.rs/indexmap
325#![doc = concat!("[manual_builds]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"")]
326//! [num-bigint]: https://docs.rs/num-bigint
327//! [num-complex]: https://docs.rs/num-complex
328//! [num-rational]: https://docs.rs/num-rational
329//! [serde]: https://docs.rs/serde
330//! [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions"
331//! [the guide]: https://pyo3.rs "PyO3 user guide"
332#![doc = concat!("[types]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html \"GIL lifetimes, mutability and Python object types\"")]
333//! [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI"
334//! [Python from Rust]: https://github.com/PyO3/pyo3#using-python-from-rust
335//! [Rust from Python]: https://github.com/PyO3/pyo3#using-rust-from-python
336#![doc = concat!("[Features chapter of the guide]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#features-reference \"Features Reference - PyO3 user guide\"")]
337//! [`Ungil`]: crate::marker::Ungil
338pub use crate::class::*;
339pub use crate::conversion::{AsPyPointer, FromPyObject, IntoPyObject, IntoPyObjectExt};
340#[allow(deprecated)]
341pub use crate::conversion::{IntoPy, ToPyObject};
342pub use crate::err::{DowncastError, DowncastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr};
343#[cfg(not(any(PyPy, GraalPy)))]
344pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter};
345pub use crate::instance::{Borrowed, Bound, BoundObject, Py, PyObject};
346pub use crate::marker::Python;
347pub use crate::pycell::{PyRef, PyRefMut};
348pub use crate::pyclass::PyClass;
349pub use crate::pyclass_init::PyClassInitializer;
350pub use crate::type_object::{PyTypeCheck, PyTypeInfo};
351pub use crate::types::PyAny;
352pub use crate::version::PythonVersionInfo;
353
354pub(crate) mod ffi_ptr_ext;
355pub(crate) mod py_result_ext;
356pub(crate) mod sealed;
357
358/// Old module which contained some implementation details of the `#[pyproto]` module.
359///
360/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead
361/// of `use pyo3::class::basic::CompareOp`.
362///
363/// For compatibility reasons this has not yet been removed, however will be done so
364/// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
365pub mod class {
366    pub use self::gc::{PyTraverseError, PyVisit};
367
368    pub use self::methods::*;
369
370    #[doc(hidden)]
371    pub mod methods {
372        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
373        pub type IPowModulo = crate::impl_::pymethods::IPowModulo;
374        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
375        pub type PyClassAttributeDef = crate::impl_::pymethods::PyClassAttributeDef;
376        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
377        pub type PyGetterDef = crate::impl_::pymethods::PyGetterDef;
378        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
379        pub type PyMethodDef = crate::impl_::pymethods::PyMethodDef;
380        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
381        pub type PyMethodDefType = crate::impl_::pymethods::PyMethodDefType;
382        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
383        pub type PyMethodType = crate::impl_::pymethods::PyMethodType;
384        #[deprecated(since = "0.23.0", note = "PyO3 implementation detail")]
385        pub type PySetterDef = crate::impl_::pymethods::PySetterDef;
386    }
387
388    /// Old module which contained some implementation details of the `#[pyproto]` module.
389    ///
390    /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead
391    /// of `use pyo3::class::basic::CompareOp`.
392    ///
393    /// For compatibility reasons this has not yet been removed, however will be done so
394    /// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
395    pub mod basic {
396        pub use crate::pyclass::CompareOp;
397    }
398
399    /// Old module which contained some implementation details of the `#[pyproto]` module.
400    ///
401    /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead
402    /// of `use pyo3::class::gc::PyTraverseError`.
403    ///
404    /// For compatibility reasons this has not yet been removed, however will be done so
405    /// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
406    pub mod gc {
407        pub use crate::pyclass::{PyTraverseError, PyVisit};
408    }
409}
410
411#[cfg(feature = "macros")]
412#[doc(hidden)]
413pub use {
414    indoc,    // Re-exported for py_run
415    unindent, // Re-exported for py_run
416};
417
418#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
419#[doc(hidden)]
420pub use inventory; // Re-exported for `#[pyclass]` and `#[pymethods]` with `multiple-pymethods`.
421
422/// Tests and helpers which reside inside PyO3's main library. Declared first so that macros
423/// are available in unit tests.
424#[cfg(test)]
425#[macro_use]
426mod tests;
427
428#[macro_use]
429mod internal_tricks;
430mod internal;
431
432pub mod buffer;
433pub mod call;
434pub mod conversion;
435mod conversions;
436#[cfg(feature = "experimental-async")]
437pub mod coroutine;
438mod err;
439pub mod exceptions;
440pub mod ffi;
441mod gil;
442#[doc(hidden)]
443pub mod impl_;
444mod instance;
445pub mod marker;
446pub mod marshal;
447#[macro_use]
448pub mod sync;
449pub mod panic;
450pub mod pybacked;
451pub mod pycell;
452pub mod pyclass;
453pub mod pyclass_init;
454
455pub mod type_object;
456pub mod types;
457mod version;
458
459#[allow(unused_imports)] // with no features enabled this module has no public exports
460pub use crate::conversions::*;
461
462#[cfg(feature = "macros")]
463pub use pyo3_macros::{
464    pyfunction, pymethods, pymodule, FromPyObject, IntoPyObject, IntoPyObjectRef,
465};
466
467/// A proc macro used to expose Rust structs and fieldless enums as Python objects.
468///
469#[doc = include_str!("../guide/pyclass-parameters.md")]
470///
471/// For more on creating Python classes,
472/// see the [class section of the guide][1].
473///
474#[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html")]
475#[cfg(feature = "macros")]
476pub use pyo3_macros::pyclass;
477
478#[cfg(feature = "macros")]
479#[macro_use]
480mod macros;
481
482#[cfg(feature = "experimental-inspect")]
483pub mod inspect;
484
485// Putting the declaration of prelude at the end seems to help encourage rustc and rustdoc to prefer using
486// other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`).
487pub mod prelude;
488
489/// Test readme and user guide
490#[cfg(doctest)]
491pub mod doc_test {
492    macro_rules! doctests {
493        ($($path:expr => $mod:ident),* $(,)?) => {
494            $(
495                #[doc = include_str!(concat!("../", $path))]
496                mod $mod{}
497            )*
498        };
499    }
500
501    doctests! {
502        "README.md" => readme_md,
503        "guide/src/advanced.md" => guide_advanced_md,
504        "guide/src/async-await.md" => guide_async_await_md,
505        "guide/src/building-and-distribution.md" => guide_building_and_distribution_md,
506        "guide/src/building-and-distribution/multiple-python-versions.md" => guide_bnd_multiple_python_versions_md,
507        "guide/src/class.md" => guide_class_md,
508        "guide/src/class/call.md" => guide_class_call,
509        "guide/src/class/object.md" => guide_class_object,
510        "guide/src/class/numeric.md" => guide_class_numeric,
511        "guide/src/class/protocols.md" => guide_class_protocols_md,
512        "guide/src/class/thread-safety.md" => guide_class_thread_safety_md,
513        "guide/src/conversions.md" => guide_conversions_md,
514        "guide/src/conversions/tables.md" => guide_conversions_tables_md,
515        "guide/src/conversions/traits.md" => guide_conversions_traits_md,
516        "guide/src/debugging.md" => guide_debugging_md,
517
518        // deliberate choice not to test guide/ecosystem because those pages depend on external
519        // crates such as pyo3_asyncio.
520
521        "guide/src/exception.md" => guide_exception_md,
522        "guide/src/faq.md" => guide_faq_md,
523        "guide/src/features.md" => guide_features_md,
524        "guide/src/free-threading.md" => guide_free_threading_md,
525        "guide/src/function.md" => guide_function_md,
526        "guide/src/function/error-handling.md" => guide_function_error_handling_md,
527        "guide/src/function/signature.md" => guide_function_signature_md,
528        "guide/src/migration.md" => guide_migration_md,
529        "guide/src/module.md" => guide_module_md,
530        "guide/src/parallelism.md" => guide_parallelism_md,
531        "guide/src/performance.md" => guide_performance_md,
532        "guide/src/python-from-rust.md" => guide_python_from_rust_md,
533        "guide/src/python-from-rust/calling-existing-code.md" => guide_pfr_calling_existing_code_md,
534        "guide/src/python-from-rust/function-calls.md" => guide_pfr_function_calls_md,
535        "guide/src/python-typing-hints.md" => guide_python_typing_hints_md,
536        "guide/src/rust-from-python.md" => guide_rust_from_python_md,
537        "guide/src/trait-bounds.md" => guide_trait_bounds_md,
538        "guide/src/types.md" => guide_types_md,
539    }
540}