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