pyo3-0.27.2/.cargo_vcs_info.json0000644000000001360000000000100120160ustar { "git": { "sha1": "117102d832d7bd7e66e75501e5722976b28b1a88" }, "path_in_vcs": "" }pyo3-0.27.2/.netlify/internal_banner.html000064400000000000000000000026211046102023000163660ustar 00000000000000
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here
pyo3-0.27.2/.netlify/redirect.sh000064400000000000000000000045421046102023000145000ustar 00000000000000# Add redirect for each documented version set +x # these loops get very spammy and fill the deploy log for d in netlify_build/v*; do version="${d/netlify_build\/v/}" echo "/v$version/doc/* https://docs.rs/pyo3/$version/:splat" >> netlify_build/_redirects if [ $version != $PYO3_VERSION ]; then # for old versions, mark the files in the latest version as the canonical URL for file in $(find $d -type f); do file_path="${file/$d\//}" # remove index.html and/or .html suffix to match the page URL on the # final netlfiy site url_path="$file_path" if [[ $file_path == index.html ]]; then url_path="" elif [[ $file_path == *.html ]]; then url_path="${file_path%.html}" fi echo "/v$version/$url_path" >> netlify_build/_headers if test -f "netlify_build/v$PYO3_VERSION/$file_path"; then echo " Link: ; rel=\"canonical\"" >> netlify_build/_headers else # this file doesn't exist in the latest guide, don't index it echo " X-Robots-Tag: noindex" >> netlify_build/_headers fi done fi done # Add latest redirect echo "/latest/* /v${PYO3_VERSION}/:splat 302" >> netlify_build/_redirects # some backwards compatbiility redirects echo "/latest/building_and_distribution/* /latest/building-and-distribution/:splat 302" >> netlify_build/_redirects echo "/latest/building-and-distribution/multiple_python_versions/* /latest/building-and-distribution/multiple-python-versions:splat 302" >> netlify_build/_redirects echo "/latest/function/error_handling/* /latest/function/error-handling/:splat 302" >> netlify_build/_redirects echo "/latest/getting_started/* /latest/getting-started/:splat 302" >> netlify_build/_redirects echo "/latest/python_from_rust/* /latest/python-from-rust/:splat 302" >> netlify_build/_redirects echo "/latest/python_typing_hints/* /latest/python-typing-hints/:splat 302" >> netlify_build/_redirects echo "/latest/trait_bounds/* /latest/trait-bounds/:splat 302" >> netlify_build/_redirects ## Add landing page redirect if [ "${CONTEXT}" == "deploy-preview" ]; then echo "/ /main/" >> netlify_build/_redirects else echo "/ /v${PYO3_VERSION}/ 302" >> netlify_build/_redirects fi set -xpyo3-0.27.2/.towncrier.template.md000064400000000000000000000010471046102023000150360ustar 00000000000000{% for section_text, section in sections.items() %}{%- if section %}{{section_text}}{% endif -%} {% if section %} {% for category in ['packaging', 'added', 'changed', 'removed', 'fixed' ] if category in section %} ### {{ definitions[category]['name'] }} {% if definitions[category]['showcontent'] %} {% for text, pull_requests in section[category].items() %} - {{ text }} {{ pull_requests|join(', ') }} {% endfor %} {% else %} - {{ section[category]['']|join(', ') }} {% endif %} {% endfor %}{% else %}No significant changes.{% endif %}{% endfor %} pyo3-0.27.2/Architecture.md000064400000000000000000000240311046102023000135520ustar 00000000000000 # PyO3: Architecture This document roughly describes the high-level architecture of PyO3. If you want to become familiar with the codebase you are in the right place! ## Overview PyO3 provides a bridge between Rust and Python, based on the [Python/C API]. Thus, PyO3 has low-level bindings of these API as its core. On top of that, we have higher-level bindings to operate Python objects safely. Also, to define Python classes and functions in Rust code, we have `trait PyClass` and a set of protocol traits (e.g., `PyIterProtocol`) for supporting object protocols (i.e., `__dunder__` methods). Since implementing `PyClass` requires lots of boilerplate, we have a proc-macro `#[pyclass]`. To summarize, there are six main parts to the PyO3 codebase. 1. [Low-level bindings of Python/C API.](#1-low-level-bindings-of-python-capi) - [`pyo3-ffi`] and [`src/ffi`] 2. [Bindings to Python objects.](#2-bindings-to-python-objects) - [`src/instance.rs`] and [`src/types`] 3. [`PyClass` and related functionalities.](#3-pyclass-and-related-functionalities) - [`src/pycell.rs`], [`src/pyclass.rs`], and more 4. [Procedural macros to simplify usage for users.](#4-procedural-macros-to-simplify-usage-for-users) - [`src/impl_`], [`pyo3-macros`] and [`pyo3-macros-backend`] 5. [`build.rs` and `pyo3-build-config`](#5-buildrs-and-pyo3-build-config) - [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs) - [`pyo3-build-config`] ## 1. Low-level bindings of Python/C API [`pyo3-ffi`] contains wrappers of the [Python/C API]. This is currently done by hand rather than automated tooling because: - it gives us best control about how to adapt C conventions to Rust, and - there are many Python interpreter versions we support in a single set of files. We aim to provide straight-forward Rust wrappers resembling the file structure of [`cpython/Include`](https://github.com/python/cpython/tree/main/Include). We are continuously updating the module to match the latest CPython version which PyO3 supports (i.e. as of time of writing Python 3.13). The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome. In the [`pyo3-ffi`] crate, there is lots of conditional compilation such as `#[cfg(Py_LIMITED_API)]`, `#[cfg(Py_3_7)]`, and `#[cfg(PyPy)]`. `Py_LIMITED_API` corresponds to `#define Py_LIMITED_API` macro in Python/C API. With `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an [abi3 wheel](https://pyo3.rs/latest/building-and-distribution.html#py_limited_apiabi3). `Py_3_7` means that the API is available from Python >= 3.7. There are also `Py_3_8`, `Py_3_9`, and so on. `PyPy` means that the API definition is for PyPy. Those flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config). ## 2. Bindings to Python objects [`src/types`] contains bindings to [built-in types](https://docs.python.org/3/library/stdtypes.html) of Python, such as `dict` and `list`. For historical reasons, Python's `object` is called `PyAny` in PyO3 and located in [`src/types/any.rs`]. Currently, `PyAny` is a straightforward wrapper of `ffi::PyObject`, defined as: ```rust #[repr(transparent)] pub struct PyAny(UnsafeCell); ``` Concrete Python objects are implemented by wrapping `PyAny`, e.g.,: ```rust #[repr(transparent)] pub struct PyDict(PyAny); ``` These types are not intended to be accessed directly, and instead are used through the `Py` and `Bound` smart pointers. We have some macros in [`src/types/mod.rs`] which make it easier to implement APIs for concrete Python types. ## 3. `PyClass` and related functionalities [`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contain types and traits to make `#[pyclass]` work. Also, [`src/pyclass_init.rs`] and [`src/impl_/pyclass.rs`] have related functionalities. To realize object-oriented programming in C, all Python objects have `ob_base: PyObject` as their first field in their structure definition. Thanks to this guarantee, casting `*mut A` to `*mut PyObject` is valid if `A` is a Python object. To ensure this guarantee, we have a wrapper struct `PyClassObject` in [`src/pycell/impl_.rs`] which is roughly: ```rust #[repr(C)] pub struct PyClassObject { ob_base: crate::ffi::PyObject, inner: T, } ``` Thus, when copying a Rust struct to a Python object, we first allocate `PyClassObject` on the Python heap and then move `T` into it. The primary way to interact with Python objects implemented in Rust is through the `Bound<'py, T>` smart pointer. By having the `'py` lifetime of the `Python<'py>` token, this ties the lifetime of the `Bound<'py, T>` smart pointer to the lifetime for which the thread is attached to the Python interpreter and allows PyO3 to call Python APIs at maximum efficiency. `Bound<'py, T>` requires that `T` implements `PyClass`. This trait is somewhat complex and derives many traits, but the most important one is `PyTypeInfo` in [`src/type_object.rs`]. `PyTypeInfo` is also implemented for built-in types. In Python, all objects have their types, and types are also objects of `type`. For example, you can see `type({})` shows `dict` and `type(type({}))` shows `type` in Python REPL. `T: PyTypeInfo` implies that `T` has a corresponding type object. ### Protocol methods Python has some built-in special methods called dunder methods, such as `__iter__`. They are called "slots" in the [abstract objects layer](https://docs.python.org/3/c-api/abstract.html) in Python/C API. We provide a way to implement those protocols similarly, by recognizing special names in `#[pymethods]`, with a few new ones for slots that can not be implemented in Python, such as GC support. ## 4. Procedural macros to simplify usage for users. [`pyo3-macros`] provides five proc-macro APIs: `pymodule`, `pyfunction`, `pyclass`, `pymethods`, and `#[derive(FromPyObject)]`. [`pyo3-macros-backend`] has the actual implementations of these APIs. [`src/impl_`] contains `#[doc(hidden)]` functionality used in code generated by these proc-macros, such as parsing function arguments. ## 5. `build.rs` and `pyo3-build-config` PyO3 supports a wide range of OSes, interpreters and use cases. The correct environment must be detected at build time in order to set up relevant conditional compilation correctly. This logic is captured in the [`pyo3-build-config`] crate, which is a `build-dependency` of `pyo3` and `pyo3-macros`, and can also be used by downstream users in the same way. In [`pyo3-build-config`]'s `build.rs` the build environment is detected and inlined into the crate as a "config file". This works in all cases except for cross-compiling, where it is necessary to capture this from the `pyo3` `build.rs` to get some extra environment variables that Cargo doesn't set for build dependencies. The `pyo3` `build.rs` also runs some safety checks such as ensuring the Python version detected is actually supported. Some of the functionality of `pyo3-build-config`: - Find the interpreter for build and detect the Python version. - We have to set some version flags like `#[cfg(Py_3_7)]`. - If the interpreter is PyPy, we set `#[cfg(PyPy)`. - If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used instead of any detected configuration. - If the `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed entirely and only abi3 extensions can be built. - Check if we are building a Python extension. - If we are building an extension (e.g., Python library installable by `pip`), we don't link `libpython`. Currently we use the `extension-module` feature for this purpose. This may change in the future. See [#1123](https://github.com/PyO3/pyo3/pull/1123). - Cross-compiling configuration - If `TARGET` architecture and `HOST` architecture differ, we can find cross compile information from environment variables (`PYO3_CROSS_LIB_DIR`, `PYO3_CROSS_PYTHON_VERSION` and `PYO3_CROSS_PYTHON_IMPLEMENTATION`) or system files. When cross compiling extension modules it is often possible to make it work without any additional user input. - When an experimental feature `generate-import-lib` is enabled, the `pyo3-ffi` build script can generate `python3.dll` import libraries for Windows targets automatically via an external [`python3-dll-a`] crate. This enables the users to cross compile Python extensions for Windows without having to install any Windows Python libraries. [python/c api]: https://docs.python.org/3/c-api/ [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ [`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros [`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`pyo3-ffi`]: https://github.com/PyO3/pyo3/tree/main/pyo3-ffi [`src/class`]: https://github.com/PyO3/pyo3/tree/main/src/class [`src/ffi`]: https://github.com/PyO3/pyo3/tree/main/src/ffi [`src/types`]: https://github.com/PyO3/pyo3/tree/main/src/types [`src/impl_`]: https://github.com/PyO3/pyo3/blob/main/src/impl_ [`src/instance.rs`]: https://github.com/PyO3/pyo3/tree/main/src/instance.rs [`src/pycell.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pycell.rs [`src/pyclass.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass.rs [`src/pyclass_init.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_init.rs [`src/pyclass_slot.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_slot.rs [`src/type_object.rs`]: https://github.com/PyO3/pyo3/tree/main/src/type_object.rs [`src/class/methods.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/methods.rs [`src/class/impl_.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/impl_.rs [`src/types/any.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/any.rs [`src/types/mod.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/mod.rs pyo3-0.27.2/CHANGELOG.md000064400000000000000000005643451046102023000124400ustar 00000000000000# Changelog All notable changes to this project will be documented in this file. For help with updating to new PyO3 versions, please see the [migration guide](https://pyo3.rs/latest/migration.html). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). To see unreleased changes, please see the [CHANGELOG on the main branch guide](https://pyo3.rs/main/changelog.html). ## [0.27.2] - 2025-11-30 ### Changed - Disable subclassing `PyDict` on GraalPy (unsupported for now, may crash at runtime). [#5653](https://github.com/PyO3/pyo3/pull/5653) ### Fixed - Fix crash when compiling on Rust 1.92+ with both debug assertions and optimizations enabled. [#5638](https://github.com/PyO3/pyo3/pull/5638) - Fix FFI definition of `PyDictObject` on PyPy. [#5653](https://github.com/PyO3/pyo3/pull/5653) ## [0.27.1] - 2025-10-21 ### Fixed - Fix `clippy:declare_interior_mutable_const` warning from `#[pyfunction]`. [#5538](https://github.com/PyO3/pyo3/pull/5538) - Expose `pyo3::types::PySendResult` in public API. [#5539](https://github.com/PyO3/pyo3/pull/5539) ## [0.27.0] - 2025-10-19 ### Packaging - Extend range of supported versions of `hashbrown` optional dependency to include version 0.16. [#5428](https://github.com/PyO3/pyo3/pull/5428) - Bump optional `num-bigint` dependency minimum version to 0.4.4. [#5471](https://github.com/PyO3/pyo3/pull/5471) - Test against Python 3.14 final release. [#5499](https://github.com/PyO3/pyo3/pull/5499) - Drop support for PyPy 3.9 and 3.10. [#5516](https://github.com/PyO3/pyo3/pull/5516) - Provide a better error message when building an outdated PyO3 for a too-new Python version. [#5519](https://github.com/PyO3/pyo3/pull/5519) ### Added - Add `FromPyObjectOwned` as convenient trait bound for `FromPyObject` when the data is not borrowed from Python. [#4390](https://github.com/PyO3/pyo3/pull/4390) - Add `Borrowed::extract`, same as `PyAnyMethods::extract`, but does not restrict the lifetime by deref. [#4390](https://github.com/PyO3/pyo3/pull/4390) - `experimental-inspect`: basic support for `#[derive(IntoPyObject)]` (no struct fields support yet). [#5365](https://github.com/PyO3/pyo3/pull/5365) - `experimental-inspect`: support `#[pyo3(get, set)]` and `#[pyclass(get_all, set_all)]`. [#5370](https://github.com/PyO3/pyo3/pull/5370) - Add `PyTypeCheck::classinfo_object` that returns an object that can be used as parameter in `isinstance` or `issubclass`. [#5387](https://github.com/PyO3/pyo3/pull/5387) - Implement `PyTypeInfo` on `datetime.*` types even when the limited API is enabled. [#5388](https://github.com/PyO3/pyo3/pull/5388) - Implement `PyTypeInfo` on `PyIterator`, `PyMapping` and `PySequence`. [#5402](https://github.com/PyO3/pyo3/pull/5402) - Implement `PyTypeInfo` on `PyCode` when using the stable ABI. [#5403](https://github.com/PyO3/pyo3/pull/5403) - Implement `PyTypeInfo` on `PyWeakrefReference` when using the stable ABI. [#5404](https://github.com/PyO3/pyo3/pull/5404) - Add `pyo3::sync::RwLockExt` trait, analogous to `pyo3::sync::MutexExt` for readwrite locks. [#5435](https://github.com/PyO3/pyo3/pull/5435) - Add `PyString::from_bytes`. [#5437](https://github.com/PyO3/pyo3/pull/5437) - Implement `AsRef<[u8]>` for `PyBytes`. [#5445](https://github.com/PyO3/pyo3/pull/5445) - Add `CastError` and `CastIntoError`. [#5468](https://github.com/PyO3/pyo3/pull/5468) - Add `PyCapsuleMethods::pointer_checked` and `PyCapsuleMethods::is_valid_checked`. [#5474](https://github.com/PyO3/pyo3/pull/5474) - Add `Borrowed::cast`, `Borrowed::cast_exact` and `Borrowed::cast_unchecked`. [#5475](https://github.com/PyO3/pyo3/pull/5475) - Add conversions for `jiff::civil::ISOWeekDate`. [#5478](https://github.com/PyO3/pyo3/pull/5478) - Add conversions for `&Cstr`, `Cstring` and `Cow`. [#5482](https://github.com/PyO3/pyo3/pull/5482) - add `#[pyclass(skip_from_py_object)]` option, to opt-out of the `FromPyObject: PyClass + Clone` blanket impl. [#5488](https://github.com/PyO3/pyo3/pull/5488) - Add `PyErr::add_note`. [#5489](https://github.com/PyO3/pyo3/pull/5489) - Add `FromPyObject` impl for `Cow` & `Cow`. [#5497](https://github.com/PyO3/pyo3/pull/5497) - Add `#[pyclass(from_py_object)]` pyclass option, to opt-in to the extraction of pyclasses by value (requires `Clone`). [#5506](https://github.com/PyO3/pyo3/pull/5506) ### Changed - Rework `FromPyObject` trait for flexibility and performance: [#4390](https://github.com/PyO3/pyo3/pull/4390) - Add a second lifetime to `FromPyObject`, to allow borrowing data from Python objects (e.g. `&str` from Python `str`). - Replace `extract_bound` with `extract`, which takes `Borrowed<'a, 'py, PyAny>`. - Optimize `FromPyObject` implementations for `Vec` and `[u8; N]` from `bytes` and `bytearray`. [#5244](https://github.com/PyO3/pyo3/pull/5244) - Deprecate `#[pyfn]` attribute. [#5384](https://github.com/PyO3/pyo3/pull/5384) - Fetch type name dynamically on cast errors instead of using `PyTypeCheck::NAME`. [#5387](https://github.com/PyO3/pyo3/pull/5387) - Deprecate `PyTypeCheck::NAME` in favour of `PyTypeCheck::classinfo_object` which provides the type information at runtime. [#5387](https://github.com/PyO3/pyo3/pull/5387) - `PyClassGuard(Mut)` and `PyRef(Mut)` extraction now returns an opaque Rust error [#5413](https://github.com/PyO3/pyo3/pull/5413) - Fetch type name dynamically when exporting types implementing `PyTypeInfo` with `#[pymodule_use]`. [#5414](https://github.com/PyO3/pyo3/pull/5414) - Improve `Debug` representation of `PyBuffer`. [#5442](https://github.com/PyO3/pyo3/pull/5442) - `experimental-inspect`: change the way introspection data is emitted in the binaries to avoid a pointer indirection and simplify parsing. [#5450](https://github.com/PyO3/pyo3/pull/5450) - Optimize `Py::drop` for the case when attached to the Python interpreter. [#5454](https://github.com/PyO3/pyo3/pull/5454) - Replace `DowncastError` and `DowncastIntoError` with `CastError` and `CastIntoError`. [#5468](https://github.com/PyO3/pyo3/pull/5468) - Enable fast-path for 128-bit integer conversions on `GraalPy`. [#5471](https://github.com/PyO3/pyo3/pull/5471) - Deprecate `PyAnyMethods::downcast` functions in favour of `Bound::cast` functions. [#5472](https://github.com/PyO3/pyo3/pull/5472) - Make `PyTypeCheck` an `unsafe trait`. [#5473](https://github.com/PyO3/pyo3/pull/5473) - Deprecate unchecked `PyCapsuleMethods`: `pointer()`, `reference()`, and `is_valid()`. [#5474](https://github.com/PyO3/pyo3/pull/5474) - Reduce lifetime of return value in `PyCapsuleMethods::reference`. [#5474](https://github.com/PyO3/pyo3/pull/5474) - `PyCapsuleMethods::name` now returns `CapsuleName` wrapper instead of `&CStr`. [#5474](https://github.com/PyO3/pyo3/pull/5474) - Deprecate `import_exception_bound` in favour of `import_exception`. [#5480](https://github.com/PyO3/pyo3/pull/5480) - `PyList::get_item_unchecked`, `PyTuple::get_item_unchecked`, and `PyTuple::get_borrowed_item_unchecked` no longer check for null values at the provided index. [#5494](https://github.com/PyO3/pyo3/pull/5494) - Allow converting naive datetime into chrono `DateTime`. [#5507](https://github.com/PyO3/pyo3/pull/5507) ### Removed - Removed `FromPyObjectBound` trait. [#4390](https://github.com/PyO3/pyo3/pull/4390) ### Fixed - Fix compilation failure on `wasm32-wasip2`. [#5368](https://github.com/PyO3/pyo3/pull/5368) - Fix `OsStr` conversion for non-utf8 strings on Windows. [#5444](https://github.com/PyO3/pyo3/pull/5444) - Fix issue with `cargo vendor` caused by gitignored build artifact `emscripten/pybuilddir.txt`. [#5456](https://github.com/PyO3/pyo3/pull/5456) - Stop leaking `PyMethodDef` instances inside `#[pyfunction]` macro generated code. [#5459](https://github.com/PyO3/pyo3/pull/5459) - Don't export definition of FFI struct `PyObjectObFlagsAndRefcnt` on 32-bit Python 3.14 (doesn't exist). [#5499](https://github.com/PyO3/pyo3/pull/5499) - Fix failure to build for `abi3` interpreters on Windows using maturin's built-in sysconfig in combination with the `generate-import-lib` feature. [#5503](https://github.com/PyO3/pyo3/pull/5503) - Fix FFI definitions `PyModule_ExecDef` and `PyModule_FromDefAndSpec2` on PyPy. [#5529](https://github.com/PyO3/pyo3/pull/5529) ## [0.26.0] - 2025-08-29 ### Packaging - Bump hashbrown dependency to 0.15. [#5152](https://github.com/PyO3/pyo3/pull/5152) - Update MSRV to 1.74. [#5171](https://github.com/PyO3/pyo3/pull/5171) - Set the same maximum supported version for alternative interpreters as for CPython. [#5192](https://github.com/PyO3/pyo3/pull/5192) - Add optional `bytes` dependency to add conversions for `bytes::Bytes`. [#5252](https://github.com/PyO3/pyo3/pull/5252) - Publish new crate `pyo3-introspection` to pair with the `experimental-inspect` feature. [#5300](https://github.com/PyO3/pyo3/pull/5300) - The `PYO3_BUILD_EXTENSION_MODULE` now causes the same effect as the `extension-module` feature. Eventually we expect maturin and setuptools-rust to set this environment variable automatically. Users with their own build systems will need to do the same. [#5343](https://github.com/PyO3/pyo3/pull/5343) ### Added - Add `#[pyo3(warn(message = "...", category = ...))]` attribute for automatic warnings generation for `#[pyfunction]` and `#[pymethods]`. [#4364](https://github.com/PyO3/pyo3/pull/4364) - Add `PyMutex`, available on Python 3.13 and newer. [#4523](https://github.com/PyO3/pyo3/pull/4523) - Add FFI definition `PyMutex_IsLocked`, available on Python 3.14 and newer. [#4523](https://github.com/PyO3/pyo3/pull/4523) - Add `PyString::from_encoded_object`. [#5017](https://github.com/PyO3/pyo3/pull/5017) - `experimental-inspect`: add basic input type annotations. [#5089](https://github.com/PyO3/pyo3/pull/5089) - Add FFI function definitions for `PyFrameObject` from CPython 3.13. [#5154](https://github.com/PyO3/pyo3/pull/5154) - `experimental-inspect`: tag modules created using `#[pymodule]` or `#[pymodule_init]` functions as incomplete. [#5207](https://github.com/PyO3/pyo3/pull/5207) - `experimental-inspect`: add basic return type support. [#5208](https://github.com/PyO3/pyo3/pull/5208) - Add `PyCode::compile` and `PyCodeMethods::run` to create and execute code objects. [#5217](https://github.com/PyO3/pyo3/pull/5217) - Add `PyOnceLock` type for thread-safe single-initialization. [#5223](https://github.com/PyO3/pyo3/pull/5223) - Add `PyClassGuard(Mut)` pyclass holders. In the future they will replace `PyRef(Mut)`. [#5233](https://github.com/PyO3/pyo3/pull/5233) - `experimental-inspect`: allow annotations in `#[pyo3(signature)]` signature attribute. [#5241](https://github.com/PyO3/pyo3/pull/5241) - Implement `MutexExt` for parking_lot's/lock_api `ReentrantMutex`. [#5258](https://github.com/PyO3/pyo3/pull/5258) - `experimental-inspect`: support class associated constants. [#5272](https://github.com/PyO3/pyo3/pull/5272) - Add `Bound::cast` family of functions superseding the `PyAnyMethods::downcast` family. [#5289](https://github.com/PyO3/pyo3/pull/5289) - Add FFI definitions `Py_Version` and `Py_IsFinalizing`. [#5317](https://github.com/PyO3/pyo3/pull/5317) - `experimental-inspect`: add output type annotation for `#[pyclass]`. [#5320](https://github.com/PyO3/pyo3/pull/5320) - `experimental-inspect`: support `#[pyclass(eq, eq_int, ord, hash, str)]`. [#5338](https://github.com/PyO3/pyo3/pull/5338) - `experimental-inspect`: add basic support for `#[derive(FromPyObject)]` (no struct fields support yet). [#5339](https://github.com/PyO3/pyo3/pull/5339) - Add `Python::try_attach`. [#5342](https://github.com/PyO3/pyo3/pull/5342) ### Changed - Use `Py_TPFLAGS_DISALLOW_INSTANTIATION` instead of a `__new__` which always fails for a `#[pyclass]` without a `#[new]` on Python 3.10 and up. [#4568](https://github.com/PyO3/pyo3/pull/4568) - `PyModule::from_code` now defaults `file_name` to `` if empty. [#4777](https://github.com/PyO3/pyo3/pull/4777) - Deprecate `PyString::from_object` in favour of `PyString::from_encoded_object`. [#5017](https://github.com/PyO3/pyo3/pull/5017) - When building with `abi3` for a Python version newer than pyo3 supports, automatically fall back to an abi3 build for the latest supported version. [#5144](https://github.com/PyO3/pyo3/pull/5144) - Change `is_instance_of` trait bound from `PyTypeInfo` to `PyTypeCheck`. [#5146](https://github.com/PyO3/pyo3/pull/5146) - Many PyO3 proc macros now report multiple errors instead of only the first one. [#5159](https://github.com/PyO3/pyo3/pull/5159) - Change `MutexExt` return type to be an associated type. [#5201](https://github.com/PyO3/pyo3/pull/5201) - Use `PyCallArgs` for `Py::call` and friends so they're equivalent to their `Bound` counterpart. [#5206](https://github.com/PyO3/pyo3/pull/5206) - Rename `Python::with_gil` to `Python::attach`. [#5209](https://github.com/PyO3/pyo3/pull/5209) - Rename `Python::allow_threads` to `Python::detach` [#5221](https://github.com/PyO3/pyo3/pull/5221) - Deprecate `GILOnceCell` type in favour of `PyOnceLock`. [#5223](https://github.com/PyO3/pyo3/pull/5223) - Rename `pyo3::prepare_freethreaded_python` to `Python::initialize`. [#5247](https://github.com/PyO3/pyo3/pull/5247) - Convert `PyMemoryError` into/from `io::ErrorKind::OutOfMemory`. [#5256](https://github.com/PyO3/pyo3/pull/5256) - Deprecate `GILProtected`. [#5285](https://github.com/PyO3/pyo3/pull/5285) - Move `#[pyclass]` docstring formatting from import time to compile time. [#5286](https://github.com/PyO3/pyo3/pull/5286) - `Python::attach` will now panic if the Python interpreter is in the process of shutting down. [#5317](https://github.com/PyO3/pyo3/pull/5317) - Add fast-path to `PyTypeInfo::type_object` for `#[pyclass]` types. [#5324](https://github.com/PyO3/pyo3/pull/5324) - Deprecate `PyObject` type alias for `Py`. [#5325](https://github.com/PyO3/pyo3/pull/5325) - Rename `Python::with_gil_unchecked` to `Python::attach_unchecked`. [#5340](https://github.com/PyO3/pyo3/pull/5340) - Rename `Python::assume_gil_acquired` to `Python::assume_attached`. [#5354](https://github.com/PyO3/pyo3/pull/5354) ### Removed - Remove FFI definition of internals of `PyFrameObject`. [#5154](https://github.com/PyO3/pyo3/pull/5154) - Remove `Eq` and `PartialEq` implementations on `PyGetSetDef` FFI definition. [#5196](https://github.com/PyO3/pyo3/pull/5196) - Remove private FFI definitions `_Py_IsCoreInitialized` and `_Py_InitializeMain`. [#5317](https://github.com/PyO3/pyo3/pull/5317) ### Fixed - Use critical section in `PyByteArray::to_vec` on freethreaded build to replicate GIL-enabled "soundness". [#4742](https://github.com/PyO3/pyo3/pull/4742) - Fix precision loss when converting `bigdecimal` into Python. [#5198](https://github.com/PyO3/pyo3/pull/5198) - Don't treat win7 target as a cross-compilation. [#5210](https://github.com/PyO3/pyo3/pull/5210) - WASM targets no longer require exception handling support for Python < 3.14. [#5239](https://github.com/PyO3/pyo3/pull/5239) - Fix segfault when dropping `PyBuffer` after the Python interpreter has been finalized. [#5242](https://github.com/PyO3/pyo3/pull/5242) - `experimental-inspect`: better automated imports generation. [#5251](https://github.com/PyO3/pyo3/pull/5251) - `experimental-inspect`: fix introspection of `__richcmp__`, `__concat__`, `__repeat__`, `__inplace_concat__` and `__inplace_repeat__`. [#5273](https://github.com/PyO3/pyo3/pull/5273) - fixed a leaked borrow, when converting a mutable sub class into a frozen base class using `PyRef::into_super` [#5281](https://github.com/PyO3/pyo3/pull/5281) - Fix FFI definition `Py_Exit` (never returns, was `()` return value, now `!`). [#5317](https://github.com/PyO3/pyo3/pull/5317) - `experimental-inspect`: fix handling of module members gated behind `#[cfg(...)]` attributes. [#5318](https://github.com/PyO3/pyo3/pull/5318) ## [0.25.1] - 2025-06-12 ### Packaging - Add support for Windows on ARM64. [#5145](https://github.com/PyO3/pyo3/pull/5145) - Add `chrono-local` feature for optional conversions for chrono's `Local` timezone & `DateTime` instances. [#5174](https://github.com/PyO3/pyo3/pull/5174) ### Added - Add FFI definition `PyBytes_AS_STRING`. [#5121](https://github.com/PyO3/pyo3/pull/5121) - Add support for module associated consts introspection. [#5150](https://github.com/PyO3/pyo3/pull/5150) ### Changed - Enable "vectorcall" FFI definitions on GraalPy. [#5121](https://github.com/PyO3/pyo3/pull/5121) - Use `Py_Is` function on GraalPy [#5121](https://github.com/PyO3/pyo3/pull/5121) ### Fixed - Report a better compile error for `async` declarations when not using `experimental-async` feature. [#5156](https://github.com/PyO3/pyo3/pull/5156) - Fix implementation of `FromPyObject` for `uuid::Uuid` on big-endian architectures. [#5161](https://github.com/PyO3/pyo3/pull/5161) - Fix segmentation faults on 32-bit x86 with Python 3.14. [#5180](https://github.com/PyO3/pyo3/pull/5180) ## [0.25.0] - 2025-05-14 ### Packaging - Support Python 3.14.0b1. [#4811](https://github.com/PyO3/pyo3/pull/4811) - Bump supported GraalPy version to 24.2. [#5116](https://github.com/PyO3/pyo3/pull/5116) - Add optional `bigdecimal` dependency to add conversions for `bigdecimal::BigDecimal`. [#5011](https://github.com/PyO3/pyo3/pull/5011) - Add optional `time` dependency to add conversions for `time` types. [#5057](https://github.com/PyO3/pyo3/pull/5057) - Remove `cfg-if` dependency. [#5110](https://github.com/PyO3/pyo3/pull/5110) - Add optional `ordered_float` dependency to add conversions for `ordered_float::NotNan` and `ordered_float::OrderedFloat`. [#5114](https://github.com/PyO3/pyo3/pull/5114) ### Added - Add initial type stub generation to the `experimental-inspect` feature. [#3977](https://github.com/PyO3/pyo3/pull/3977) - Add `#[pyclass(generic)]` option to support runtime generic typing. [#4926](https://github.com/PyO3/pyo3/pull/4926) - Implement `OnceExt` & `MutexExt` for `parking_lot` & `lock_api`. Use the new extension traits by enabling the `arc_lock`, `lock_api`, or `parking_lot` cargo features. [#5044](https://github.com/PyO3/pyo3/pull/5044) - Implement `From`/`Into` for `Borrowed` -> `Py`. [#5054](https://github.com/PyO3/pyo3/pull/5054) - Add `PyTzInfo` constructors. [#5055](https://github.com/PyO3/pyo3/pull/5055) - Add FFI definition `PY_INVALID_STACK_EFFECT`. [#5064](https://github.com/PyO3/pyo3/pull/5064) - Implement `AsRef>` for `Py`, `Bound` and `Borrowed`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Add FFI definition `PyModule_Add` and `compat::PyModule_Add`. [#5085](https://github.com/PyO3/pyo3/pull/5085) - Add FFI definitions `Py_HashBuffer`, `Py_HashPointer`, and `PyObject_GenericHash`. [#5086](https://github.com/PyO3/pyo3/pull/5086) - Support `#[pymodule_export]` on `const` items in declarative modules. [#5096](https://github.com/PyO3/pyo3/pull/5096) - Add `#[pyclass(immutable_type)]` option (on Python 3.14+ with `abi3`, or 3.10+ otherwise) for immutable type objects. [#5101](https://github.com/PyO3/pyo3/pull/5101) - Support `#[pyo3(rename_all)]` support on `#[derive(IntoPyObject)]`. [#5112](https://github.com/PyO3/pyo3/pull/5112) - Add `PyRange` wrapper. [#5117](https://github.com/PyO3/pyo3/pull/5117) ### Changed - Enable use of `datetime` types with `abi3` feature enabled. [#4970](https://github.com/PyO3/pyo3/pull/4970) - Deprecate `timezone_utc` in favor of `PyTzInfo::utc`. [#5055](https://github.com/PyO3/pyo3/pull/5055) - Reduce visibility of some CPython implementation details: [#5064](https://github.com/PyO3/pyo3/pull/5064) - The FFI definition `PyCodeObject` is now an opaque struct on all Python versions. - The FFI definition `PyFutureFeatures` is now only defined up until Python 3.10 (it was present in CPython headers but unused in 3.11 and 3.12). - Change `PyAnyMethods::is` to take `other: &Bound`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Change `Py::is` to take `other: &Py`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Change `PyVisit::call` to take `T: Into>>`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Expose `PyDateTime_DATE_GET_TZINFO` and `PyDateTime_TIME_GET_TZINFO` on PyPy 3.10 and later. [#5079](https://github.com/PyO3/pyo3/pull/5079) - Add `#[track_caller]` to `with_gil` and `with_gil_unchecked`. [#5109](https://github.com/PyO3/pyo3/pull/5109) - Use `std::thread::park()` instead of `libc::pause()` or `sleep(9999999)`. [#5115](https://github.com/PyO3/pyo3/pull/5115) ### Removed - Remove all functionality deprecated in PyO3 0.23. [#4982](https://github.com/PyO3/pyo3/pull/4982) - Remove deprecated `IntoPy` and `ToPyObject` traits. [#5010](https://github.com/PyO3/pyo3/pull/5010) - Remove private types from `pyo3-ffi` (i.e. starting with `_Py`) which are not referenced by public APIs: `_PyLocalMonitors`, `_Py_GlobalMonitors`, `_PyCoCached`, `_PyCoLineInstrumentationData`, `_PyCoMonitoringData`, `_PyCompilerSrcLocation`, `_PyErr_StackItem`. [#5064](https://github.com/PyO3/pyo3/pull/5064) - Remove FFI definition `PyCode_GetNumFree` (PyO3 cannot support it due to knowledge of the code object). [#5064](https://github.com/PyO3/pyo3/pull/5064) - Remove `AsPyPointer` trait. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Remove support for the deprecated string form of `from_py_with`. [#5097](https://github.com/PyO3/pyo3/pull/5097) - Remove FFI definitions of private static variables: `_PyMethodWrapper_Type`, `_PyCoroWrapper_Type`, `_PyImport_FrozenBootstrap`, `_PyImport_FrozenStdlib`, `_PyImport_FrozenTest`, `_PyManagedBuffer_Type`, `_PySet_Dummy`, `_PyWeakref_ProxyType`, and `_PyWeakref_CallableProxyType`. [#5105](https://github.com/PyO3/pyo3/pull/5105) - Remove FFI definitions `PyASCIIObjectState`, `PyUnicode_IS_ASCII`, `PyUnicode_IS_COMPACT`, and `PyUnicode_IS_COMPACT_ASCII` on Python 3.14 and newer. [#5133](https://github.com/PyO3/pyo3/pull/5133) ### Fixed - Correctly pick up the shared state for conda-based Python installation when reading information from sysconfigdata. [#5037](https://github.com/PyO3/pyo3/pull/5037) - Fix compile failure with `#[derive(IntoPyObject, FromPyObject)]` when using `#[pyo3()]` options recognised by only one of the two derives. [#5070](https://github.com/PyO3/pyo3/pull/5070) - Fix various compile errors from missing FFI definitions using certain feature combinations on PyPy and GraalPy. [#5091](https://github.com/PyO3/pyo3/pull/5091) - Fallback on `backports.zoneinfo` for python <3.9 when converting timezones into python. [#5120](https://github.com/PyO3/pyo3/pull/5120) ## [0.24.2] - 2025-04-21 ### Fixed - Fix `unused_imports` lint of `#[pyfunction]` and `#[pymethods]` expanded in `macro_rules` context. [#5030](https://github.com/PyO3/pyo3/pull/5030) - Fix size of `PyCodeObject::_co_instrumentation_version` ffi struct member on Python 3.13 for systems where `uintptr_t` is not 64 bits. [#5048](https://github.com/PyO3/pyo3/pull/5048) - Fix struct-type complex enum variant fields incorrectly exposing raw identifiers as `r#ident` in Python bindings. [#5050](https://github.com/PyO3/pyo3/pull/5050) ## [0.24.1] - 2025-03-31 ### Added - Add `abi3-py313` feature. [#4969](https://github.com/PyO3/pyo3/pull/4969) - Add `PyAnyMethods::getattr_opt`. [#4978](https://github.com/PyO3/pyo3/pull/4978) - Add `PyInt::new` constructor for all supported number types (i32, u32, i64, u64, isize, usize). [#4984](https://github.com/PyO3/pyo3/pull/4984) - Add `pyo3::sync::with_critical_section2`. [#4992](https://github.com/PyO3/pyo3/pull/4992) - Implement `PyCallArgs` for `Borrowed<'_, 'py, PyTuple>`, `&Bound<'py, PyTuple>`, and `&Py`. [#5013](https://github.com/PyO3/pyo3/pull/5013) ### Fixed - Fix `is_type_of` for native types not using same specialized check as `is_type_of_bound`. [#4981](https://github.com/PyO3/pyo3/pull/4981) - Fix `Probe` class naming issue with `#[pymethods]`. [#4988](https://github.com/PyO3/pyo3/pull/4988) - Fix compile failure with required `#[pyfunction]` arguments taking `Option<&str>` and `Option<&T>` (for `#[pyclass]` types). [#5002](https://github.com/PyO3/pyo3/pull/5002) - Fix `PyString::from_object` causing of bounds reads with `encoding` and `errors` parameters which are not nul-terminated. [#5008](https://github.com/PyO3/pyo3/pull/5008) - Fix compile error when additional options follow after `crate` for `#[pyfunction]`. [#5015](https://github.com/PyO3/pyo3/pull/5015) ## [0.24.0] - 2025-03-09 ### Packaging - Add supported CPython/PyPy versions to cargo package metadata. [#4756](https://github.com/PyO3/pyo3/pull/4756) - Bump `target-lexicon` dependency to 0.13. [#4822](https://github.com/PyO3/pyo3/pull/4822) - Add optional `jiff` dependency to add conversions for `jiff` datetime types. [#4823](https://github.com/PyO3/pyo3/pull/4823) - Add optional `uuid` dependency to add conversions for `uuid::Uuid`. [#4864](https://github.com/PyO3/pyo3/pull/4864) - Bump minimum supported `inventory` version to 0.3.5. [#4954](https://github.com/PyO3/pyo3/pull/4954) ### Added - Add `PyIterator::send` method to allow sending values into a python generator. [#4746](https://github.com/PyO3/pyo3/pull/4746) - Add `PyCallArgs` trait for passing arguments into the Python calling protocol. This enabled using a faster calling convention for certain types, improving performance. [#4768](https://github.com/PyO3/pyo3/pull/4768) - Add `#[pyo3(default = ...']` option for `#[derive(FromPyObject)]` to set a default value for extracted fields of named structs. [#4829](https://github.com/PyO3/pyo3/pull/4829) - Add `#[pyo3(into_py_with = ...)]` option for `#[derive(IntoPyObject, IntoPyObjectRef)]`. [#4850](https://github.com/PyO3/pyo3/pull/4850) - Add FFI definitions `PyThreadState_GetFrame` and `PyFrame_GetBack`. [#4866](https://github.com/PyO3/pyo3/pull/4866) - Optimize `last` for `BoundListIterator`, `BoundTupleIterator` and `BorrowedTupleIterator`. [#4878](https://github.com/PyO3/pyo3/pull/4878) - Optimize `Iterator::count()` for `PyDict`, `PyList`, `PyTuple` & `PySet`. [#4878](https://github.com/PyO3/pyo3/pull/4878) - Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundTupleIterator` [#4897](https://github.com/PyO3/pyo3/pull/4897) - Add support for `types.GenericAlias` as `pyo3::types::PyGenericAlias`. [#4917](https://github.com/PyO3/pyo3/pull/4917) - Add `MutextExt` trait to help avoid deadlocks with the GIL while locking a `std::sync::Mutex`. [#4934](https://github.com/PyO3/pyo3/pull/4934) - Add `#[pyo3(rename_all = "...")]` option for `#[derive(FromPyObject)]`. [#4941](https://github.com/PyO3/pyo3/pull/4941) ### Changed - Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundListIterator`. [#4810](https://github.com/PyO3/pyo3/pull/4810) - Use `DerefToPyAny` in blanket implementations of `From>` and `From>` for `PyObject`. [#4593](https://github.com/PyO3/pyo3/pull/4593) - Map `io::ErrorKind::IsADirectory`/`NotADirectory` to the corresponding Python exception on Rust 1.83+. [#4747](https://github.com/PyO3/pyo3/pull/4747) - `PyAnyMethods::call` and friends now require `PyCallArgs` for their positional arguments. [#4768](https://github.com/PyO3/pyo3/pull/4768) - Expose FFI definitions for `PyObject_Vectorcall(Method)` on the stable abi on 3.12+. [#4853](https://github.com/PyO3/pyo3/pull/4853) - `#[pyo3(from_py_with = ...)]` now take a path rather than a string literal [#4860](https://github.com/PyO3/pyo3/pull/4860) - Format Python traceback in impl Debug for PyErr. [#4900](https://github.com/PyO3/pyo3/pull/4900) - Convert `PathBuf` & `Path` into Python `pathlib.Path` instead of `PyString`. [#4925](https://github.com/PyO3/pyo3/pull/4925) - Relax parsing of exotic Python versions. [#4949](https://github.com/PyO3/pyo3/pull/4949) - PyO3 threads now hang instead of `pthread_exit` trying to acquire the GIL when the interpreter is shutting down. This mimics the [Python 3.14](https://github.com/python/cpython/issues/87135) behavior and avoids undefined behavior and crashes. [#4874](https://github.com/PyO3/pyo3/pull/4874) ### Removed - Remove implementations of `Deref` for `PyAny` and other "native" types. [#4593](https://github.com/PyO3/pyo3/pull/4593) - Remove implicit default of trailing optional arguments (see #2935) [#4729](https://github.com/PyO3/pyo3/pull/4729) - Remove the deprecated implicit eq fallback for simple enums. [#4730](https://github.com/PyO3/pyo3/pull/4730) ### Fixed - Correct FFI definition of `PyIter_Send` to return a `PySendResult`. [#4746](https://github.com/PyO3/pyo3/pull/4746) - Fix a thread safety issue in the runtime borrow checker used by mutable pyclass instances on the free-threaded build. [#4948](https://github.com/PyO3/pyo3/pull/4948) ## [0.23.5] - 2025-02-22 ### Packaging - Add support for PyPy3.11 [#4760](https://github.com/PyO3/pyo3/pull/4760) ### Fixed - Fix thread-unsafe implementation of freelist pyclasses on the free-threaded build. [#4902](https://github.com/PyO3/pyo3/pull/4902) - Re-enable a workaround for situations where CPython incorrectly does not add `__builtins__` to `__globals__` in code executed by `Python::py_run` (was removed in PyO3 0.23.0). [#4921](https://github.com/PyO3/pyo3/pull/4921) ## [0.23.4] - 2025-01-10 ### Added - Add `PyList::locked_for_each`, which uses a critical section to lock the list on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) - Add `pyo3_build_config::add_python_framework_link_args` build script API to set rpath when using macOS system Python. [#4833](https://github.com/PyO3/pyo3/pull/4833) ### Changed - Use `datetime.fold` to distinguish ambiguous datetimes when converting to and from `chrono::DateTime` (rather than erroring). [#4791](https://github.com/PyO3/pyo3/pull/4791) - Optimize PyList iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) ### Fixed - Fix unnecessary internal `py.allow_threads` GIL-switch when attempting to access contents of a `PyErr` which originated from Python (could lead to unintended deadlocks). [#4766](https://github.com/PyO3/pyo3/pull/4766) - Fix thread-unsafe access of dict internals in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788) * Fix unnecessary critical sections in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788) - Fix time-of-check to time-of-use issues with list iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) - Fix `chrono::DateTime` to-Python conversion when `Tz` is `chrono_tz::Tz`. [#4790](https://github.com/PyO3/pyo3/pull/4790) - Fix `#[pyclass]` not being able to be named `Probe`. [#4794](https://github.com/PyO3/pyo3/pull/4794) - Fix not treating cross-compilation from x64 to aarch64 on Windows as a cross-compile. [#4800](https://github.com/PyO3/pyo3/pull/4800) - Fix missing struct fields on GraalPy when subclassing builtin classes. [#4802](https://github.com/PyO3/pyo3/pull/4802) - Fix generating import lib for PyPy when `abi3` feature is enabled. [#4806](https://github.com/PyO3/pyo3/pull/4806) - Fix generating import lib for python3.13t when `abi3` feature is enabled. [#4808](https://github.com/PyO3/pyo3/pull/4808) - Fix compile failure for raw identifiers like `r#box` in `derive(FromPyObject)`. [#4814](https://github.com/PyO3/pyo3/pull/4814) - Fix compile failure for `#[pyclass]` enum variants with more than 12 fields. [#4832](https://github.com/PyO3/pyo3/pull/4832) ## [0.23.3] - 2024-12-03 ### Packaging - Bump optional `python3-dll-a` dependency to 0.2.11. [#4749](https://github.com/PyO3/pyo3/pull/4749) ### Fixed - Fix unresolved symbol link failures on Windows when compiling for Python 3.13t with `abi3` features enabled. [#4733](https://github.com/PyO3/pyo3/pull/4733) - Fix unresolved symbol link failures on Windows when compiling for Python 3.13t using the `generate-import-lib` feature. [#4749](https://github.com/PyO3/pyo3/pull/4749) - Fix compile-time regression in PyO3 0.23.0 where changing `PYO3_CONFIG_FILE` would not reconfigure PyO3 for the new interpreter. [#4758](https://github.com/PyO3/pyo3/pull/4758) ## [0.23.2] - 2024-11-25 ### Added - Add `IntoPyObjectExt` trait. [#4708](https://github.com/PyO3/pyo3/pull/4708) ### Fixed - Fix compile failures when building for free-threaded Python when the `abi3` or `abi3-pyxx` features are enabled. [#4719](https://github.com/PyO3/pyo3/pull/4719) - Fix `ambiguous_associated_items` lint error in `#[pyclass]` and `#[derive(IntoPyObject)]` macros. [#4725](https://github.com/PyO3/pyo3/pull/4725) ## [0.23.1] - 2024-11-16 Re-release of 0.23.0 with fixes to docs.rs build. ## [0.23.0] - 2024-11-15 ### Packaging - Drop support for PyPy 3.7 and 3.8. [#4582](https://github.com/PyO3/pyo3/pull/4582) - Extend range of supported versions of `hashbrown` optional dependency to include version 0.15. [#4604](https://github.com/PyO3/pyo3/pull/4604) - Bump minimum version of `eyre` optional dependency to 0.6.8. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `hashbrown` optional dependency to 0.14.5. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `indexmap` optional dependency to 2.5.0. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `num-complex` optional dependency to 0.4.6. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `chrono-tz` optional dependency to 0.10. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Support free-threaded Python 3.13t. [#4588](https://github.com/PyO3/pyo3/pull/4588) ### Added - Add `IntoPyObject` (fallible) conversion trait to convert from Rust to Python values. [#4060](https://github.com/PyO3/pyo3/pull/4060) - Add `#[pyclass(str="")]` option to generate `__str__` based on a `Display` implementation or format string. [#4233](https://github.com/PyO3/pyo3/pull/4233) - Implement `PartialEq` for `Bound<'py, PyInt>` with `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128` and `isize`. [#4317](https://github.com/PyO3/pyo3/pull/4317) - Implement `PartialEq` and `PartialEq` for `Bound<'py, PyFloat>`. [#4348](https://github.com/PyO3/pyo3/pull/4348) - Add `as_super` and `into_super` methods for `Bound`. [#4351](https://github.com/PyO3/pyo3/pull/4351) - Add FFI definitions `PyCFunctionFast` and `PyCFunctionFastWithKeywords` [#4415](https://github.com/PyO3/pyo3/pull/4415) - Add FFI definitions for `PyMutex` on Python 3.13 and newer. [#4421](https://github.com/PyO3/pyo3/pull/4421) - Add `PyDict::locked_for_each` to iterate efficiently on freethreaded Python. [#4439](https://github.com/PyO3/pyo3/pull/4439) - Add FFI definitions `PyObject_GetOptionalAttr`, `PyObject_GetOptionalAttrString`, `PyObject_HasAttrWithError`, `PyObject_HasAttrStringWithError`, `Py_CONSTANT_*` constants, `Py_GetConstant`, `Py_GetConstantBorrowed`, and `PyType_GetModuleByDef` on Python 3.13 and newer. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Add FFI definitions for the Python critical section API available on Python 3.13 and newer. [#4477](https://github.com/PyO3/pyo3/pull/4477) - Add derive macro for `IntoPyObject`. [#4495](https://github.com/PyO3/pyo3/pull/4495) - Add `Borrowed::as_ptr`. [#4520](https://github.com/PyO3/pyo3/pull/4520) - Add FFI definition for `PyImport_AddModuleRef`. [#4529](https://github.com/PyO3/pyo3/pull/4529) - Add `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553) - Add `pyo3::sync::with_critical_section`, a wrapper around the Python Critical Section API added in Python 3.13. [#4587](https://github.com/PyO3/pyo3/pull/4587) - Add `#[pymodule(gil_used = false)]` option to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588) - Add `PyModule::gil_used` method to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588) - Add FFI definition `PyDateTime_CAPSULE_NAME`. [#4634](https://github.com/PyO3/pyo3/pull/4634) - Add `PyMappingProxy` type to represent the `mappingproxy` Python class. [#4644](https://github.com/PyO3/pyo3/pull/4644) - Add FFI definitions `PyList_Extend` and `PyList_Clear`. [#4667](https://github.com/PyO3/pyo3/pull/4667) - Add derive macro for `IntoPyObjectRef`. [#4674](https://github.com/PyO3/pyo3/pull/4674) - Add `pyo3::sync::OnceExt` and `pyo3::sync::OnceLockExt` traits. [#4676](https://github.com/PyO3/pyo3/pull/4676) ### Changed - Prefer `IntoPyObject` over `IntoPy>>` for `#[pyfunction]` and `#[pymethods]` return types. [#4060](https://github.com/PyO3/pyo3/pull/4060) - Report multiple errors from `#[pyclass]` and `#[pyo3(..)]` attributes. [#4243](https://github.com/PyO3/pyo3/pull/4243) - Nested declarative `#[pymodule]` are automatically treated as submodules (no `PyInit_` entrypoint is created). [#4308](https://github.com/PyO3/pyo3/pull/4308) - Deprecate `PyAnyMethods::is_ellipsis` (`Py::is_ellipsis` was deprecated in PyO3 0.20). [#4322](https://github.com/PyO3/pyo3/pull/4322) - Deprecate `PyLong` in favor of `PyInt`. [#4347](https://github.com/PyO3/pyo3/pull/4347) - Rename `IntoPyDict::into_py_dict_bound` to `IntoPyDict::into_py_dict`. [#4388](https://github.com/PyO3/pyo3/pull/4388) - `PyModule::from_code` now expects `&CStr` as arguments instead of `&str`. [#4404](https://github.com/PyO3/pyo3/pull/4404) - Use "fastcall" Python calling convention for `#[pyfunction]`s when compiling on abi3 for Python 3.10 and up. [#4415](https://github.com/PyO3/pyo3/pull/4415) - Remove `Copy` and `Clone` from `PyObject` struct FFI definition. [#4434](https://github.com/PyO3/pyo3/pull/4434) - `Python::eval` and `Python::run` now take a `&CStr` instead of `&str`. [#4435](https://github.com/PyO3/pyo3/pull/4435) - Deprecate `IPowModulo`, `PyClassAttributeDef`, `PyGetterDef`, `PyMethodDef`, `PyMethodDefType`, and `PySetterDef` from PyO3's public API. [#4441](https://github.com/PyO3/pyo3/pull/4441) - `IntoPyObject` impls for `Vec`, `&[u8]`, `[u8; N]`, `Cow<[u8]>` and `SmallVec<[u8; N]>` now convert into Python `bytes` rather than a `list` of integers. [#4442](https://github.com/PyO3/pyo3/pull/4442) - Emit a compile-time error when attempting to subclass a class that doesn't allow subclassing. [#4453](https://github.com/PyO3/pyo3/pull/4453) - `IntoPyDict::into_py_dict` is now fallible due to `IntoPyObject` migration. [#4493](https://github.com/PyO3/pyo3/pull/4493) - The `abi3` feature will now override config files provided via `PYO3_BUILD_CONFIG`. [#4497](https://github.com/PyO3/pyo3/pull/4497) - Disable the `GILProtected` struct on free-threaded Python. [#4504](https://github.com/PyO3/pyo3/pull/4504) - Updated FFI definitions for functions and struct fields that have been deprecated or removed from CPython. [#4534](https://github.com/PyO3/pyo3/pull/4534) - Disable `PyListMethods::get_item_unchecked` on free-threaded Python. [#4539](https://github.com/PyO3/pyo3/pull/4539) - Add `GILOnceCell::import`. [#4542](https://github.com/PyO3/pyo3/pull/4542) - Deprecate `PyAnyMethods::iter` in favour of `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553) - The `#[pyclass]` macro now requires a types to be `Sync`. (Except for `#[pyclass(unsendable)]` types). [#4566](https://github.com/PyO3/pyo3/pull/4566) - `PyList::new` and `PyTuple::new` are now fallible due to `IntoPyObject` migration. [#4580](https://github.com/PyO3/pyo3/pull/4580) - `PyErr::matches` is now fallible due to `IntoPyObject` migration. [#4595](https://github.com/PyO3/pyo3/pull/4595) - Deprecate `ToPyObject` in favour of `IntoPyObject` [#4595](https://github.com/PyO3/pyo3/pull/4595) - Deprecate `PyWeakrefMethods::get_option`. [#4597](https://github.com/PyO3/pyo3/pull/4597) - Seal `PyWeakrefMethods` trait. [#4598](https://github.com/PyO3/pyo3/pull/4598) - Remove `PyNativeTypeInitializer` and `PyObjectInit` from the PyO3 public API. [#4611](https://github.com/PyO3/pyo3/pull/4611) - Deprecate `IntoPy` in favor of `IntoPyObject` [#4618](https://github.com/PyO3/pyo3/pull/4618) - Eagerly normalize exceptions in `PyErr::take()` and `PyErr::fetch()` on Python 3.11 and older. [#4655](https://github.com/PyO3/pyo3/pull/4655) - Move `IntoPy::type_output` to `IntoPyObject::type_output`. [#4657](https://github.com/PyO3/pyo3/pull/4657) - Change return type of `PyMapping::keys`, `PyMapping::values` and `PyMapping::items` to `Bound<'py, PyList>` instead of `Bound<'py, PySequence>`. [#4661](https://github.com/PyO3/pyo3/pull/4661) - Complex enums now allow field types that either implement `IntoPyObject` by reference or by value together with `Clone`. This makes `Py` available as field type. [#4694](https://github.com/PyO3/pyo3/pull/4694) ### Removed - Remove all functionality deprecated in PyO3 0.20. [#4322](https://github.com/PyO3/pyo3/pull/4322) - Remove all functionality deprecated in PyO3 0.21. [#4323](https://github.com/PyO3/pyo3/pull/4323) - Deprecate `PyUnicode` in favour of `PyString`. [#4370](https://github.com/PyO3/pyo3/pull/4370) - Remove deprecated `gil-refs` feature. [#4378](https://github.com/PyO3/pyo3/pull/4378) - Remove private FFI definitions `_Py_IMMORTAL_REFCNT`, `_Py_IsImmortal`, `_Py_TPFLAGS_STATIC_BUILTIN`, `_Py_Dealloc`, `_Py_IncRef`, `_Py_DecRef`. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Remove private FFI definitions `_Py_c_sum`, `_Py_c_diff`, `_Py_c_neg`, `_Py_c_prod`, `_Py_c_quot`, `_Py_c_pow`, `_Py_c_abs`. [#4521](https://github.com/PyO3/pyo3/pull/4521) - Remove `_borrowed` methods of `PyWeakRef` and `PyWeakRefProxy`. [#4528](https://github.com/PyO3/pyo3/pull/4528) - Removed private FFI definition `_PyErr_ChainExceptions`. [#4534](https://github.com/PyO3/pyo3/pull/4534) ### Fixed - Fix invalid library search path `lib_dir` when cross-compiling. [#4389](https://github.com/PyO3/pyo3/pull/4389) - Fix FFI definition `Py_Is` for PyPy on 3.10 to call the function defined by PyPy. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Fix compile failure when using `#[cfg]` attributes for simple enum variants. [#4509](https://github.com/PyO3/pyo3/pull/4509) - Fix compiler warning for `non_snake_case` method names inside `#[pymethods]` generated code. [#4567](https://github.com/PyO3/pyo3/pull/4567) - Fix compile error with `#[derive(FromPyObject)]` generic struct with trait bounds. [#4645](https://github.com/PyO3/pyo3/pull/4645) - Fix compile error for `#[classmethod]` and `#[staticmethod]` on magic methods. [#4654](https://github.com/PyO3/pyo3/pull/4654) - Fix compile warning for `unsafe_op_in_unsafe_fn` in generated macro code. [#4674](https://github.com/PyO3/pyo3/pull/4674) - Fix incorrect deprecation warning for `#[pyclass] enum`s with custom `__eq__` implementation. [#4692](https://github.com/PyO3/pyo3/pull/4692) - Fix `non_upper_case_globals` lint firing for generated `__match_args__` on complex enums. [#4705](https://github.com/PyO3/pyo3/pull/4705) ## [0.22.5] - 2024-10-15 ### Fixed - Fix regression in 0.22.4 of naming collision in `__clear__` slot and `clear` method generated code. [#4619](https://github.com/PyO3/pyo3/pull/4619) ## [0.22.4] - 2024-10-12 ### Added - Add FFI definition `PyWeakref_GetRef` and `compat::PyWeakref_GetRef`. [#4528](https://github.com/PyO3/pyo3/pull/4528) ### Changed - Deprecate `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` (just use the owning forms). [#4590](https://github.com/PyO3/pyo3/pull/4590) ### Fixed - Revert removal of private FFI function `_PyLong_NumBits` on Python 3.13 and later. [#4450](https://github.com/PyO3/pyo3/pull/4450) - Fix `__traverse__` functions for base classes not being called by subclasses created with `#[pyclass(extends = ...)]`. [#4563](https://github.com/PyO3/pyo3/pull/4563) - Fix regression in 0.22.3 failing compiles under `#![forbid(unsafe_code)]`. [#4574](https://github.com/PyO3/pyo3/pull/4574) - Fix `create_exception` macro triggering lint and compile errors due to interaction with `gil-refs` feature. [#4589](https://github.com/PyO3/pyo3/pull/4589) - Workaround possible use-after-free in `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` by leaking their contents. [#4590](https://github.com/PyO3/pyo3/pull/4590) - Fix crash calling `PyType_GetSlot` on static types before Python 3.10. [#4599](https://github.com/PyO3/pyo3/pull/4599) ## [0.22.3] - 2024-09-15 ### Added - Add `pyo3::ffi::compat` namespace with compatibility shims for C API functions added in recent versions of Python. - Add FFI definition `PyDict_GetItemRef` on Python 3.13 and newer, and `compat::PyDict_GetItemRef` for all versions. [#4355](https://github.com/PyO3/pyo3/pull/4355) - Add FFI definition `PyList_GetItemRef` on Python 3.13 and newer, and `pyo3_ffi::compat::PyList_GetItemRef` for all versions. [#4410](https://github.com/PyO3/pyo3/pull/4410) - Add FFI definitions `compat::Py_NewRef` and `compat::Py_XNewRef`. [#4445](https://github.com/PyO3/pyo3/pull/4445) - Add FFI definitions `compat::PyObject_CallNoArgs` and `compat::PyObject_CallMethodNoArgs`. [#4461](https://github.com/PyO3/pyo3/pull/4461) - Add `GilOnceCell>::clone_ref`. [#4511](https://github.com/PyO3/pyo3/pull/4511) ### Changed - Improve error messages for `#[pyfunction]` defined inside `#[pymethods]`. [#4349](https://github.com/PyO3/pyo3/pull/4349) - Improve performance of calls to Python by using the vectorcall calling convention where possible. [#4456](https://github.com/PyO3/pyo3/pull/4456) - Mention the type name in the exception message when trying to instantiate a class with no constructor defined. [#4481](https://github.com/PyO3/pyo3/pull/4481) ### Removed - Remove private FFI definition `_Py_PackageContext`. [#4420](https://github.com/PyO3/pyo3/pull/4420) ### Fixed - Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328) - Fix use of borrowed reference in `PyDict::get_item` (unsafe in free-threaded Python). [#4355](https://github.com/PyO3/pyo3/pull/4355) - Fix `#[pyclass(eq)]` macro hygiene issues for structs and enums. [#4359](https://github.com/PyO3/pyo3/pull/4359) - Fix hygiene/span issues of `#[pyfunction]` and `#[pymethods]` generated code which affected expansion in `macro_rules` context. [#4382](https://github.com/PyO3/pyo3/pull/4382) - Fix `unsafe_code` lint error in `#[pyclass]` generated code. [#4396](https://github.com/PyO3/pyo3/pull/4396) - Fix async functions returning a tuple only returning the first element to Python. [#4407](https://github.com/PyO3/pyo3/pull/4407) - Fix use of borrowed reference in `PyList::get_item` (unsafe in free-threaded Python). [#4410](https://github.com/PyO3/pyo3/pull/4410) - Correct FFI definition `PyArg_ParseTupleAndKeywords` to take `*const *const c_char` instead of `*mut *mut c_char` on Python 3.13 and up. [#4420](https://github.com/PyO3/pyo3/pull/4420) - Fix a soundness bug with `PyClassInitializer`: panic if adding subclass to existing instance via `PyClassInitializer::from(Py).add_subclass(SubClass)`. [#4454](https://github.com/PyO3/pyo3/pull/4454) - Fix illegal reference counting op inside implementation of `__traverse__` handlers. [#4479](https://github.com/PyO3/pyo3/pull/4479) ## [0.22.2] - 2024-07-17 ### Packaging - Require opt-in to freethreaded Python using the `UNSAFE_PYO3_BUILD_FREE_THREADED=1` environment variable (it is not yet supported by PyO3). [#4327](https://github.com/PyO3/pyo3/pull/4327) ### Changed - Use FFI function calls for reference counting on all abi3 versions. [#4324](https://github.com/PyO3/pyo3/pull/4324) - `#[pymodule(...)]` now directly accepts all relevant `#[pyo3(...)]` options. [#4330](https://github.com/PyO3/pyo3/pull/4330) ### Fixed - Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328) - Fix compile failure due to c-string literals on Rust < 1.79. [#4353](https://github.com/PyO3/pyo3/pull/4353) ## [0.22.1] - 2024-07-06 ### Added - Add `#[pyo3(submodule)]` option for declarative `#[pymodule]`s. [#4301](https://github.com/PyO3/pyo3/pull/4301) - Implement `PartialEq` for `Bound<'py, PyBool>`. [#4305](https://github.com/PyO3/pyo3/pull/4305) ### Fixed - Return `NotImplemented` instead of raising `TypeError` from generated equality method when comparing different types. [#4287](https://github.com/PyO3/pyo3/pull/4287) - Handle full-path `#[pyo3::prelude::pymodule]` and similar for `#[pyclass]` and `#[pyfunction]` in declarative modules. [#4288](https://github.com/PyO3/pyo3/pull/4288) - Fix 128-bit int regression on big-endian platforms with Python <3.13. [#4291](https://github.com/PyO3/pyo3/pull/4291) - Stop generating code that will never be covered with declarative modules. [#4297](https://github.com/PyO3/pyo3/pull/4297) - Fix invalid deprecation warning for trailing optional on `#[setter]` function. [#4304](https://github.com/PyO3/pyo3/pull/4304) ## [0.22.0] - 2024-06-24 ### Packaging - Update `heck` dependency to 0.5. [#3966](https://github.com/PyO3/pyo3/pull/3966) - Extend range of supported versions of `chrono-tz` optional dependency to include version 0.10. [#4061](https://github.com/PyO3/pyo3/pull/4061) - Update MSRV to 1.63. [#4129](https://github.com/PyO3/pyo3/pull/4129) - Add optional `num-rational` feature to add conversions with Python's `fractions.Fraction`. [#4148](https://github.com/PyO3/pyo3/pull/4148) - Support Python 3.13. [#4184](https://github.com/PyO3/pyo3/pull/4184) ### Added - Add `PyWeakref`, `PyWeakrefReference` and `PyWeakrefProxy`. [#3835](https://github.com/PyO3/pyo3/pull/3835) - Support `#[pyclass]` on enums that have tuple variants. [#4072](https://github.com/PyO3/pyo3/pull/4072) - Add support for scientific notation in `Decimal` conversion. [#4079](https://github.com/PyO3/pyo3/pull/4079) - Add `pyo3_disable_reference_pool` conditional compilation flag to avoid the overhead of the global reference pool at the cost of known limitations as explained in the performance section of the guide. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[pyo3(constructor = (...))]` to customize the generated constructors for complex enum variants. [#4158](https://github.com/PyO3/pyo3/pull/4158) - Add `PyType::module`, which always matches Python `__module__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyType::fully_qualified_name` which matches the "fully qualified name" defined in [PEP 737](https://peps.python.org/pep-0737). [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyTypeMethods::mro` and `PyTypeMethods::bases`. [#4197](https://github.com/PyO3/pyo3/pull/4197) - Add `#[pyclass(ord)]` to implement ordering based on `PartialOrd`. [#4202](https://github.com/PyO3/pyo3/pull/4202) - Implement `ToPyObject` and `IntoPy` for `PyBackedStr` and `PyBackedBytes`. [#4205](https://github.com/PyO3/pyo3/pull/4205) - Add `#[pyclass(hash)]` option to implement `__hash__` in terms of the `Hash` implementation [#4206](https://github.com/PyO3/pyo3/pull/4206) - Add `#[pyclass(eq)]` option to generate `__eq__` based on `PartialEq`, and `#[pyclass(eq_int)]` for simple enums to implement equality based on their discriminants. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Implement `From>` for `PyClassInitializer`. [#4214](https://github.com/PyO3/pyo3/pull/4214) - Add `as_super` methods to `PyRef` and `PyRefMut` for accessing the base class by reference. [#4219](https://github.com/PyO3/pyo3/pull/4219) - Implement `PartialEq` for `Bound<'py, PyString>`. [#4245](https://github.com/PyO3/pyo3/pull/4245) - Implement `PyModuleMethods::filename` on PyPy. [#4249](https://github.com/PyO3/pyo3/pull/4249) - Implement `PartialEq<[u8]>` for `Bound<'py, PyBytes>`. [#4250](https://github.com/PyO3/pyo3/pull/4250) - Add `pyo3_ffi::c_str` macro to create `&'static CStr` on Rust versions which don't have 1.77's `c""` literals. [#4255](https://github.com/PyO3/pyo3/pull/4255) - Support `bool` conversion with `numpy` 2.0's `numpy.bool` type [#4258](https://github.com/PyO3/pyo3/pull/4258) - Add `PyAnyMethods::{bitnot, matmul, floor_div, rem, divmod}`. [#4264](https://github.com/PyO3/pyo3/pull/4264) ### Changed - Change the type of `PySliceIndices::slicelength` and the `length` parameter of `PySlice::indices()`. [#3761](https://github.com/PyO3/pyo3/pull/3761) - Deprecate implicit default for trailing optional arguments [#4078](https://github.com/PyO3/pyo3/pull/4078) - `Clone`ing pointers into the Python heap has been moved behind the `py-clone` feature, as it must panic without the GIL being held as a soundness fix. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[track_caller]` to all `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>` methods which can panic. [#4098](https://github.com/PyO3/pyo3/pull/4098) - Change `PyAnyMethods::dir` to be fallible and return `PyResult>` (and similar for `PyAny::dir`). [#4100](https://github.com/PyO3/pyo3/pull/4100) - The global reference pool (to track pending reference count decrements) is now initialized lazily to avoid the overhead of taking a mutex upon function entry when the functionality is not actually used. [#4178](https://github.com/PyO3/pyo3/pull/4178) - Emit error messages when using `weakref` or `dict` when compiling for `abi3` for Python older than 3.9. [#4194](https://github.com/PyO3/pyo3/pull/4194) - Change `PyType::name` to always match Python `__name__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Remove CPython internal ffi call for complex number including: add, sub, mul, div, neg, abs, pow. Added PyAnyMethods::{abs, pos, neg} [#4201](https://github.com/PyO3/pyo3/pull/4201) - Deprecate implicit integer comparison for simple enums in favor of `#[pyclass(eq_int)]`. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Set the `module=` attribute of declarative modules' child `#[pymodule]`s and `#[pyclass]`es. [#4213](https://github.com/PyO3/pyo3/pull/4213) - Set the `module` option for complex enum variants from the value set on the complex enum `module`. [#4228](https://github.com/PyO3/pyo3/pull/4228) - Respect the Python "limited API" when building for the `abi3` feature on PyPy or GraalPy. [#4237](https://github.com/PyO3/pyo3/pull/4237) - Optimize code generated by `#[pyo3(get)]` on `#[pyclass]` fields. [#4254](https://github.com/PyO3/pyo3/pull/4254) - `PyCFunction::new`, `PyCFunction::new_with_keywords` and `PyCFunction::new_closure` now take `&'static CStr` name and doc arguments (previously was `&'static str`). [#4255](https://github.com/PyO3/pyo3/pull/4255) - The `experimental-declarative-modules` feature is now stabilized and available by default. [#4257](https://github.com/PyO3/pyo3/pull/4257) ### Fixed - Fix panic when `PYO3_CROSS_LIB_DIR` is set to a missing path. [#4043](https://github.com/PyO3/pyo3/pull/4043) - Fix a compile error when exporting an exception created with `create_exception!` living in a different Rust module using the `declarative-module` feature. [#4086](https://github.com/PyO3/pyo3/pull/4086) - Fix FFI definitions of `PY_VECTORCALL_ARGUMENTS_OFFSET` and `PyVectorcall_NARGS` to fix a false-positive assertion. [#4104](https://github.com/PyO3/pyo3/pull/4104) - Disable `PyUnicode_DATA` on PyPy: not exposed by PyPy. [#4116](https://github.com/PyO3/pyo3/pull/4116) - Correctly handle `#[pyo3(from_py_with = ...)]` attribute on dunder (`__magic__`) method arguments instead of silently ignoring it. [#4117](https://github.com/PyO3/pyo3/pull/4117) - Fix a compile error when declaring a standalone function or class method with a Python name that is a Rust keyword. [#4226](https://github.com/PyO3/pyo3/pull/4226) - Fix declarative modules discarding doc comments on the `mod` node. [#4236](https://github.com/PyO3/pyo3/pull/4236) - Fix `__dict__` attribute missing for `#[pyclass(dict)]` instances when building for `abi3` on Python 3.9. [#4251](https://github.com/PyO3/pyo3/pull/4251) ## [0.21.2] - 2024-04-16 ### Changed - Deprecate the `PySet::empty()` gil-ref constructor. [#4082](https://github.com/PyO3/pyo3/pull/4082) ### Fixed - Fix compile error for `async fn` in `#[pymethods]` with a `&self` receiver and more than one additional argument. [#4035](https://github.com/PyO3/pyo3/pull/4035) - Improve error message for wrong receiver type in `__traverse__`. [#4045](https://github.com/PyO3/pyo3/pull/4045) - Fix compile error when exporting a `#[pyclass]` living in a different Rust module using the `experimental-declarative-modules` feature. [#4054](https://github.com/PyO3/pyo3/pull/4054) - Fix `missing_docs` lint triggering on documented `#[pymodule]` functions. [#4067](https://github.com/PyO3/pyo3/pull/4067) - Fix undefined symbol errors for extension modules on AIX (by linking `libpython`). [#4073](https://github.com/PyO3/pyo3/pull/4073) ## [0.21.1] - 2024-04-01 ### Added - Implement `Send` and `Sync` for `PyBackedStr` and `PyBackedBytes`. [#4007](https://github.com/PyO3/pyo3/pull/4007) - Implement `Clone`, `Debug`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` implementation for `PyBackedBytes` and `PyBackedStr`, and `Display` for `PyBackedStr`. [#4020](https://github.com/PyO3/pyo3/pull/4020) - Add `import_exception_bound!` macro to import exception types without generating GIL Ref functionality for them. [#4027](https://github.com/PyO3/pyo3/pull/4027) ### Changed - Emit deprecation warning for uses of GIL Refs as `#[setter]` function arguments. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Add `#[inline]` hints on many `Bound` and `Borrowed` methods. [#4024](https://github.com/PyO3/pyo3/pull/4024) ### Fixed - Handle `#[pyo3(from_py_with = "")]` in `#[setter]` methods [#3995](https://github.com/PyO3/pyo3/pull/3995) - Allow extraction of `&Bound` in `#[setter]` methods. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Fix some uncovered code blocks emitted by `#[pymodule]`, `#[pyfunction]` and `#[pyclass]` macros. [#4009](https://github.com/PyO3/pyo3/pull/4009) - Fix typo in the panic message when a class referenced in `pyo3::import_exception!` does not exist. [#4012](https://github.com/PyO3/pyo3/pull/4012) - Fix compile error when using an async `#[pymethod]` with a receiver and additional arguments. [#4015](https://github.com/PyO3/pyo3/pull/4015) ## [0.21.0] - 2024-03-25 ### Added - Add support for GraalPy (24.0 and up). [#3247](https://github.com/PyO3/pyo3/pull/3247) - Add `PyMemoryView` type. [#3514](https://github.com/PyO3/pyo3/pull/3514) - Allow `async fn` in for `#[pyfunction]` and `#[pymethods]`, with the `experimental-async` feature. [#3540](https://github.com/PyO3/pyo3/pull/3540) [#3588](https://github.com/PyO3/pyo3/pull/3588) [#3599](https://github.com/PyO3/pyo3/pull/3599) [#3931](https://github.com/PyO3/pyo3/pull/3931) - Implement `PyTypeInfo` for `PyEllipsis`, `PyNone` and `PyNotImplemented`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Support `#[pyclass]` on enums that have non-unit variants. [#3582](https://github.com/PyO3/pyo3/pull/3582) - Support `chrono` feature with `abi3` feature. [#3664](https://github.com/PyO3/pyo3/pull/3664) - `FromPyObject`, `IntoPy` and `ToPyObject` are implemented on `std::duration::Duration` [#3670](https://github.com/PyO3/pyo3/pull/3670) - Add `PyString::to_cow`. Add `Py::to_str`, `Py::to_cow`, and `Py::to_string_lossy`, as ways to access Python string data safely beyond the GIL lifetime. [#3677](https://github.com/PyO3/pyo3/pull/3677) - Add `Bound` and `Borrowed` smart pointers as a new API for accessing Python objects. [#3686](https://github.com/PyO3/pyo3/pull/3686) - Add `PyNativeType::as_borrowed` to convert "GIL refs" to the new `Bound` smart pointer. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Add `FromPyObject::extract_bound` method, to migrate `FromPyObject` implementations to the Bound API. [#3706](https://github.com/PyO3/pyo3/pull/3706) - Add `gil-refs` feature to allow continued use of the deprecated GIL Refs APIs. [#3707](https://github.com/PyO3/pyo3/pull/3707) - Add methods to `PyAnyMethods` for binary operators (`add`, `sub`, etc.) [#3712](https://github.com/PyO3/pyo3/pull/3712) - Add `chrono-tz` feature allowing conversion between `chrono_tz::Tz` and `zoneinfo.ZoneInfo` [#3730](https://github.com/PyO3/pyo3/pull/3730) - Add FFI definition `PyType_GetModuleByDef`. [#3734](https://github.com/PyO3/pyo3/pull/3734) - Conversion between `std::time::SystemTime` and `datetime.datetime` [#3736](https://github.com/PyO3/pyo3/pull/3736) - Add `Py::as_any` and `Py::into_any`. [#3785](https://github.com/PyO3/pyo3/pull/3785) - Add `PyStringMethods::encode_utf8`. [#3801](https://github.com/PyO3/pyo3/pull/3801) - Add `PyBackedStr` and `PyBackedBytes`, as alternatives to `&str` and `&bytes` where a Python object owns the data. [#3802](https://github.com/PyO3/pyo3/pull/3802) [#3991](https://github.com/PyO3/pyo3/pull/3991) - Allow `#[pymodule]` macro on Rust `mod` blocks, with the `experimental-declarative-modules` feature. [#3815](https://github.com/PyO3/pyo3/pull/3815) - Implement `ExactSizeIterator` for `set` and `frozenset` iterators on `abi3` feature. [#3849](https://github.com/PyO3/pyo3/pull/3849) - Add `Py::drop_ref` to explicitly drop a `Py`` and immediately decrease the Python reference count if the GIL is already held. [#3871](https://github.com/PyO3/pyo3/pull/3871) - Allow `#[pymodule]` macro on single argument functions that take `&Bound<'_, PyModule>`. [#3905](https://github.com/PyO3/pyo3/pull/3905) - Implement `FromPyObject` for `Cow`. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Implement `Default` for `GILOnceCell`. [#3971](https://github.com/PyO3/pyo3/pull/3971) - Add `PyDictMethods::into_mapping`, `PyListMethods::into_sequence` and `PyTupleMethods::into_sequence`. [#3982](https://github.com/PyO3/pyo3/pull/3982) ### Changed - `PyDict::from_sequence` now takes a single argument of type `&PyAny` (previously took two arguments `Python` and `PyObject`). [#3532](https://github.com/PyO3/pyo3/pull/3532) - Deprecate `Py::is_ellipsis` and `PyAny::is_ellipsis` in favour of `any.is(py.Ellipsis())`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Split some `PyTypeInfo` functionality into new traits `HasPyGilRef` and `PyTypeCheck`. [#3600](https://github.com/PyO3/pyo3/pull/3600) - Deprecate `PyTryFrom` and `PyTryInto` traits in favor of `any.downcast()` via the `PyTypeCheck` and `PyTypeInfo` traits. [#3601](https://github.com/PyO3/pyo3/pull/3601) - Allow async methods to accept `&self`/`&mut self` [#3609](https://github.com/PyO3/pyo3/pull/3609) - `FromPyObject` for set types now also accept `frozenset` objects as input. [#3632](https://github.com/PyO3/pyo3/pull/3632) - `FromPyObject` for `bool` now also accepts NumPy's `bool_` as input. [#3638](https://github.com/PyO3/pyo3/pull/3638) - Add `AsRefSource` associated type to `PyNativeType`. [#3653](https://github.com/PyO3/pyo3/pull/3653) - Rename `.is_true` to `.is_truthy` on `PyAny` and `Py` to clarify that the test is not based on identity with or equality to the True singleton. [#3657](https://github.com/PyO3/pyo3/pull/3657) - `PyType::name` is now `PyType::qualname` whereas `PyType::name` efficiently accesses the full name which includes the module name. [#3660](https://github.com/PyO3/pyo3/pull/3660) - The `Iter(A)NextOutput` types are now deprecated and `__(a)next__` can directly return anything which can be converted into Python objects, i.e. awaitables do not need to be wrapped into `IterANextOutput` or `Option` any more. `Option` can still be used as well and returning `None` will trigger the fast path for `__next__`, stopping iteration without having to raise a `StopIteration` exception. [#3661](https://github.com/PyO3/pyo3/pull/3661) - Implement `FromPyObject` on `chrono::DateTime` for all `Tz`, not just `FixedOffset` and `Utc`. [#3663](https://github.com/PyO3/pyo3/pull/3663) - Add lifetime parameter to `PyTzInfoAccess` trait. For the deprecated gil-ref API, the trait is now implemented for `&'py PyTime` and `&'py PyDateTime` instead of `PyTime` and `PyDate`. [#3679](https://github.com/PyO3/pyo3/pull/3679) - Calls to `__traverse__` become no-ops for unsendable pyclasses if on the wrong thread, thereby avoiding hard aborts at the cost of potential leakage. [#3689](https://github.com/PyO3/pyo3/pull/3689) - Include `PyNativeType` in `pyo3::prelude`. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Improve performance of `extract::` (and other integer types) by avoiding call to `__index__()` converting the value to an integer for 3.10+. Gives performance improvement of around 30% for successful extraction. [#3742](https://github.com/PyO3/pyo3/pull/3742) - Relax bound of `FromPyObject` for `Py` to just `T: PyTypeCheck`. [#3776](https://github.com/PyO3/pyo3/pull/3776) - `PySet` and `PyFrozenSet` iterators now always iterate the equivalent of `iter(set)`. (A "fast path" with no noticeable performance benefit was removed.) [#3849](https://github.com/PyO3/pyo3/pull/3849) - Move implementations of `FromPyObject` for `&str`, `Cow`, `&[u8]` and `Cow<[u8]>` onto a temporary trait `FromPyObjectBound` when `gil-refs` feature is deactivated. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Deprecate `GILPool`, `Python::with_pool`, and `Python::new_pool`. [#3947](https://github.com/PyO3/pyo3/pull/3947) ### Removed - Remove all functionality deprecated in PyO3 0.19. [#3603](https://github.com/PyO3/pyo3/pull/3603) ### Fixed - Match PyPy 7.3.14 in removing PyPy-only symbol `Py_MAX_NDIMS` in favour of `PyBUF_MAX_NDIM`. [#3757](https://github.com/PyO3/pyo3/pull/3757) - Fix segmentation fault using `datetime` types when an invalid `datetime` module is on sys.path. [#3818](https://github.com/PyO3/pyo3/pull/3818) - Fix `non_local_definitions` lint warning triggered by many PyO3 macros. [#3901](https://github.com/PyO3/pyo3/pull/3901) - Disable `PyCode` and `PyCode_Type` on PyPy: `PyCode_Type` is not exposed by PyPy. [#3934](https://github.com/PyO3/pyo3/pull/3934) ## [0.21.0-beta.0] - 2024-03-10 Prerelease of PyO3 0.21. See [the GitHub diff](https://github.com/pyo3/pyo3/compare/v0.21.0-beta.0...v0.21.0) for what changed between 0.21.0-beta.0 and the final release. ## [0.20.3] - 2024-02-23 ### Packaging - Add `portable-atomic` dependency. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Check maximum version of Python at build time and for versions not yet supported require opt-in to the `abi3` stable ABI by the environment variable `PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1`. [#3821](https://github.com/PyO3/pyo3/pull/3821) ### Fixed - Use `portable-atomic` to support platforms without 64-bit atomics. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Fix compilation failure with `either` feature enabled without `experimental-inspect` enabled. [#3834](https://github.com/PyO3/pyo3/pull/3834) ## [0.20.2] - 2024-01-04 ### Packaging - Pin `pyo3` and `pyo3-ffi` dependencies on `pyo3-build-config` to require the same patch version, i.e. `pyo3` 0.20.2 requires _exactly_ `pyo3-build-config` 0.20.2. [#3721](https://github.com/PyO3/pyo3/pull/3721) ### Fixed - Fix compile failure when building `pyo3` 0.20.0 with latest `pyo3-build-config` 0.20.X. [#3724](https://github.com/PyO3/pyo3/pull/3724) - Fix docs.rs build. [#3722](https://github.com/PyO3/pyo3/pull/3722) ## [0.20.1] - 2023-12-30 ### Added - Add optional `either` feature to add conversions for `either::Either` sum type. [#3456](https://github.com/PyO3/pyo3/pull/3456) - Add optional `smallvec` feature to add conversions for `smallvec::SmallVec`. [#3507](https://github.com/PyO3/pyo3/pull/3507) - Add `take` and `into_inner` methods to `GILOnceCell` [#3556](https://github.com/PyO3/pyo3/pull/3556) - `#[classmethod]` methods can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - `#[pyfunction(pass_module)]` can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - Add `traverse` method to `GILProtected`. [#3616](https://github.com/PyO3/pyo3/pull/3616) - Added `abi3-py312` feature [#3687](https://github.com/PyO3/pyo3/pull/3687) ### Fixed - Fix minimum version specification for optional `chrono` dependency. [#3512](https://github.com/PyO3/pyo3/pull/3512) - Silenced new `clippy::unnecessary_fallible_conversions` warning when using a `Py` `self` receiver. [#3564](https://github.com/PyO3/pyo3/pull/3564) ## [0.20.0] - 2023-10-11 ### Packaging - Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#3108](https://github.com/PyO3/pyo3/pull/3108) - Update MSRV to Rust 1.56. [#3208](https://github.com/PyO3/pyo3/pull/3208) - Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#3237](https://github.com/PyO3/pyo3/pull/3237) - Bump `syn` dependency to 2.0. [#3239](https://github.com/PyO3/pyo3/pull/3239) - Drop support for debug builds of Python 3.7. [#3387](https://github.com/PyO3/pyo3/pull/3387) - Bump `chrono` optional dependency to require 0.4.25 or newer. [#3427](https://github.com/PyO3/pyo3/pull/3427) - Support Python 3.12. [#3488](https://github.com/PyO3/pyo3/pull/3488) ### Added - Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#3203](https://github.com/PyO3/pyo3/pull/3203) - Add FFI definition `Py_GETENV`. [#3336](https://github.com/PyO3/pyo3/pull/3336) - Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#3359](https://github.com/PyO3/pyo3/pull/3359) - Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Add `#[pyclass(rename_all = "...")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `"camelCase"`, `"kebab-case"`, `"lowercase"`, `"PascalCase"`, `"SCREAMING-KEBAB-CASE"`, `"SCREAMING_SNAKE_CASE"`, `"snake_case"`, `"UPPERCASE"`. [#3384](https://github.com/PyO3/pyo3/pull/3384) - Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#3403](https://github.com/PyO3/pyo3/pull/3403) - Add types for `None`, `Ellipsis`, and `NotImplemented`. [#3408](https://github.com/PyO3/pyo3/pull/3408) - Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#3494](https://github.com/PyO3/pyo3/pull/3494) - Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#3502](https://github.com/PyO3/pyo3/pull/3502) ### Changed - Change `PySet::discard` to return `PyResult` (previously returned nothing). [#3281](https://github.com/PyO3/pyo3/pull/3281) - Optimize implementation of `IntoPy` for Rust tuples to Python tuples. [#3321](https://github.com/PyO3/pyo3/pull/3321) - Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#3330](https://github.com/PyO3/pyo3/pull/3330) - Deprecate FFI definitions which are deprecated in Python 3.12. [#3336](https://github.com/PyO3/pyo3/pull/3336) - `AsPyPointer` is now an `unsafe trait`. [#3358](https://github.com/PyO3/pyo3/pull/3358) - Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#3378](https://github.com/PyO3/pyo3/pull/3378) - Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#3379](https://github.com/PyO3/pyo3/pull/3379) - `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#3389](https://github.com/PyO3/pyo3/pull/3389) - Replace `AsPyPointer` with `AsRef` as a bound in the blanket implementation of `From<&T> for PyObject`. [#3391](https://github.com/PyO3/pyo3/pull/3391) - Replace blanket `impl IntoPy for &T where T: AsPyPointer` with implementations of `impl IntoPy` for `&PyAny`, `&T where T: AsRef`, and `&Py`. [#3393](https://github.com/PyO3/pyo3/pull/3393) - Preserve `std::io::Error` kind in implementation of `From` for `PyErr` [#3396](https://github.com/PyO3/pyo3/pull/3396) - Try to select a relevant `ErrorKind` in implementation of `From` for `OSError` subclass. [#3397](https://github.com/PyO3/pyo3/pull/3397) - Retrieve the original `PyErr` in implementation of `From` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#3402](https://github.com/PyO3/pyo3/pull/3402) - `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#3446](https://github.com/PyO3/pyo3/pull/3446) - Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#3458](https://github.com/PyO3/pyo3/pull/3458) - `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#3455](https://github.com/PyO3/pyo3/pull/3455) - Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#3505](https://github.com/PyO3/pyo3/pull/3505) ### Removed - Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#3232](https://github.com/PyO3/pyo3/pull/3232) - Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#3385](https://github.com/PyO3/pyo3/pull/3385) ### Fixed - Handle exceptions properly in `PySet::discard`. [#3281](https://github.com/PyO3/pyo3/pull/3281) - The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Linking of `PyOS_FSPath` on PyPy. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Fix memory leak in `PyTypeBuilder::build`. [#3401](https://github.com/PyO3/pyo3/pull/3401) - Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#3403](https://github.com/PyO3/pyo3/pull/3403) - Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#3404](https://github.com/PyO3/pyo3/pull/3404) - Some-wrapping of `Option` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#3461](https://github.com/PyO3/pyo3/pull/3461) - Fix `IterNextOutput::Return` not returning a value on PyPy. [#3471](https://github.com/PyO3/pyo3/pull/3471) - Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#3491](https://github.com/PyO3/pyo3/pull/3491) - Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#3484](https://github.com/PyO3/pyo3/pull/3484) - Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#3490](https://github.com/PyO3/pyo3/pull/3490) - Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#3500](https://github.com/PyO3/pyo3/pull/3500) ## [0.19.2] - 2023-08-01 ### Added - Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#3295](https://github.com/PyO3/pyo3/pull/3295) - Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Add a "performance" section to the guide collecting performance-related tricks and problems. [#3304](https://github.com/PyO3/pyo3/pull/3304) - Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#3334](https://github.com/PyO3/pyo3/pull/3334) - Add FFI definition `PyType_GetDict()` for Python 3.12. [#3339](https://github.com/PyO3/pyo3/pull/3339) - Add `PyAny::downcast_exact`. [#3346](https://github.com/PyO3/pyo3/pull/3346) - Add `PySlice::full()` to construct a full slice (`::`). [#3353](https://github.com/PyO3/pyo3/pull/3353) ### Changed - Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#3306](https://github.com/PyO3/pyo3/pull/3306) - Update FFI definitions of `object.h` for Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) - Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#3342](https://github.com/PyO3/pyo3/pull/3342) - Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#3345](https://github.com/PyO3/pyo3/pull/3345) ### Fixed - Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#3269](https://github.com/PyO3/pyo3/pull/3269) - Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#3300](https://github.com/PyO3/pyo3/pull/3300) - Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#3313](https://github.com/PyO3/pyo3/pull/3313) - Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". [#3326](https://github.com/PyO3/pyo3/pull/3326) - Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#3328](https://github.com/PyO3/pyo3/pull/3328) - Fix reference counting of immortal objects on Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) ## [0.19.1] - 2023-07-03 ### Packaging - Extend range of supported versions of `hashbrown` optional dependency to include version 0.14 [#3258](https://github.com/PyO3/pyo3/pull/3258) - Extend range of supported versions of `indexmap` optional dependency to include version 2. [#3277](https://github.com/PyO3/pyo3/pull/3277) - Support PyPy 3.10. [#3289](https://github.com/PyO3/pyo3/pull/3289) ### Added - Add `pyo3::types::PyFrozenSetBuilder` to allow building a `PyFrozenSet` item by item. [#3156](https://github.com/PyO3/pyo3/pull/3156) - Add support for converting to and from Python's `ipaddress.IPv4Address`/`ipaddress.IPv6Address` and `std::net::IpAddr`. [#3197](https://github.com/PyO3/pyo3/pull/3197) - Add support for `num-bigint` feature in combination with `abi3`. [#3198](https://github.com/PyO3/pyo3/pull/3198) - Add `PyErr_GetRaisedException()`, `PyErr_SetRaisedException()` to FFI definitions for Python 3.12 and later. [#3248](https://github.com/PyO3/pyo3/pull/3248) - Add `Python::with_pool` which is a safer but more limited alternative to `Python::new_pool`. [#3263](https://github.com/PyO3/pyo3/pull/3263) - Add `PyDict::get_item_with_error` on PyPy. [#3270](https://github.com/PyO3/pyo3/pull/3270) - Allow `#[new]` methods may to return `Py` in order to return existing instances. [#3287](https://github.com/PyO3/pyo3/pull/3287) ### Fixed - Fix conversion of classes implementing `__complex__` to `Complex` when using `abi3` or PyPy. [#3185](https://github.com/PyO3/pyo3/pull/3185) - Stop suppressing unrelated exceptions in `PyAny::hasattr`. [#3271](https://github.com/PyO3/pyo3/pull/3271) - Fix memory leak when creating `PySet` or `PyFrozenSet` or returning types converted into these internally, e.g. `HashSet` or `BTreeSet`. [#3286](https://github.com/PyO3/pyo3/pull/3286) ## [0.19.0] - 2023-05-31 ### Packaging - Correct dependency on syn to version 1.0.85 instead of the incorrect version 1.0.56. [#3152](https://github.com/PyO3/pyo3/pull/3152) ### Added - Accept `text_signature` option (and automatically generate signature) for `#[new]` in `#[pymethods]`. [#2980](https://github.com/PyO3/pyo3/pull/2980) - Add support for converting to and from Python's `decimal.Decimal` and `rust_decimal::Decimal`. [#3016](https://github.com/PyO3/pyo3/pull/3016) - Add `#[pyo3(from_item_all)]` when deriving `FromPyObject` to specify `get_item` as getter for all fields. [#3120](https://github.com/PyO3/pyo3/pull/3120) - Add `pyo3::exceptions::PyBaseExceptionGroup` for Python 3.11, and corresponding FFI definition `PyExc_BaseExceptionGroup`. [#3141](https://github.com/PyO3/pyo3/pull/3141) - Accept `#[new]` with `#[classmethod]` to create a constructor which receives a (subtype's) class/`PyType` as its first argument. [#3157](https://github.com/PyO3/pyo3/pull/3157) - Add `PyClass::get` and `Py::get` for GIL-independent access to classes with `#[pyclass(frozen)]`. [#3158](https://github.com/PyO3/pyo3/pull/3158) - Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`. [#3161](https://github.com/PyO3/pyo3/pull/3161) ### Changed - `PyAny::is_instance_of::(obj)` is now equivalent to `T::is_type_of(obj)`, and now returns `bool` instead of `PyResult`. [#2881](https://github.com/PyO3/pyo3/pull/2881) - Deprecate `text_signature` option on `#[pyclass]` structs. [#2980](https://github.com/PyO3/pyo3/pull/2980) - No longer wrap `anyhow::Error`/`eyre::Report` containing a basic `PyErr` without a chain in a `PyRuntimeError`. [#3004](https://github.com/PyO3/pyo3/pull/3004) - - Change `#[getter]` and `#[setter]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#3029](https://github.com/PyO3/pyo3/pull/3029) - Improve default values for str, numbers and bool in automatically-generated `text_signature`. [#3050](https://github.com/PyO3/pyo3/pull/3050) - Improve default value for `None` in automatically-generated `text_signature`. [#3066](https://github.com/PyO3/pyo3/pull/3066) - Rename `PySequence::list` and `PySequence::tuple` to `PySequence::to_list` and `PySequence::to_tuple`. (The old names continue to exist as deprecated forms.) [#3111](https://github.com/PyO3/pyo3/pull/3111) - Extend the lifetime of the GIL token returned by `PyRef::py` and `PyRefMut::py` to match the underlying borrow. [#3131](https://github.com/PyO3/pyo3/pull/3131) - Safe access to the GIL, for example via `Python::with_gil`, is now locked inside of implementations of the `__traverse__` slot. [#3168](https://github.com/PyO3/pyo3/pull/3168) ### Removed - Remove all functionality deprecated in PyO3 0.17, most prominently `Python::acquire_gil` is replaced by `Python::with_gil`. [#2981](https://github.com/PyO3/pyo3/pull/2981) ### Fixed - Correct FFI definitions `PyGetSetDef`, `PyMemberDef`, `PyStructSequence_Field` and `PyStructSequence_Desc` to have `*const c_char` members for `name` and `doc` (not `*mut c_char`). [#3036](https://github.com/PyO3/pyo3/pull/3036) - Fix panic on `fmt::Display`, instead return `""` string and report error via `sys.unraisablehook()` [#3062](https://github.com/PyO3/pyo3/pull/3062) - Fix a compile error of "temporary value dropped while borrowed" when `#[pyfunction]`s take references into `#[pyclass]`es [#3142](https://github.com/PyO3/pyo3/pull/3142) - Fix crashes caused by PyO3 applying deferred reference count updates when entering a `__traverse__` implementation. [#3168](https://github.com/PyO3/pyo3/pull/3168) - Forbid running the `Drop` implementations of unsendable classes on other threads. [#3176](https://github.com/PyO3/pyo3/pull/3176) - Fix a compile error when `#[pymethods]` items come from somewhere else (for example, as a macro argument) and a custom receiver like `Py` is used. [#3178](https://github.com/PyO3/pyo3/pull/3178) ## [0.18.3] - 2023-04-13 ### Added - Add `GILProtected` to mediate concurrent access to a value using Python's global interpreter lock (GIL). [#2975](https://github.com/PyO3/pyo3/pull/2975) - Support `PyASCIIObject` / `PyUnicode` and associated methods on big-endian architectures. [#3015](https://github.com/PyO3/pyo3/pull/3015) - Add FFI definition `_PyDict_Contains_KnownHash()` for CPython 3.10 and up. [#3088](https://github.com/PyO3/pyo3/pull/3088) ### Fixed - Fix compile error for `#[pymethods]` and `#[pyfunction]` called "output". [#3022](https://github.com/PyO3/pyo3/pull/3022) - Fix compile error in generated code for magic methods implemented as a `#[staticmethod]`. [#3055](https://github.com/PyO3/pyo3/pull/3055) - Fix `is_instance` for `PyDateTime` (would incorrectly check for a `PyDate`). [#3071](https://github.com/PyO3/pyo3/pull/3071) - Fix upstream deprecation of `PyUnicode_InternImmortal` since Python 3.10. [#3071](https://github.com/PyO3/pyo3/pull/3087) ## [0.18.2] - 2023-03-24 ### Packaging - Disable default features of `chrono` to avoid depending on `time` v0.1.x. [#2939](https://github.com/PyO3/pyo3/pull/2939) ### Added - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cow<[u8]>` to efficiently handle both `bytes` and `bytearray` objects. [#2899](https://github.com/PyO3/pyo3/pull/2899) - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cell`. [#3014](https://github.com/PyO3/pyo3/pull/3014) - Add `PyList::to_tuple()`, as a convenient and efficient conversion from lists to tuples. [#3042](https://github.com/PyO3/pyo3/pull/3042) - Add `PyTuple::to_list()`, as a convenient and efficient conversion from tuples to lists. [#3044](https://github.com/PyO3/pyo3/pull/3044) ### Changed - Optimize `PySequence` conversion for `list` and `tuple` inputs. [#2944](https://github.com/PyO3/pyo3/pull/2944) - Improve exception raised when creating `#[pyclass]` type object fails during module import. [#2947](https://github.com/PyO3/pyo3/pull/2947) - Optimize `PyMapping` conversion for `dict` inputs. [#2954](https://github.com/PyO3/pyo3/pull/2954) - Allow `create_exception!` to take a `dotted.module` to place the exception in a submodule. [#2979](https://github.com/PyO3/pyo3/pull/2979) ### Fixed - Fix a reference counting race condition affecting `PyObject`s cloned in `allow_threads` blocks. [#2952](https://github.com/PyO3/pyo3/pull/2952) - Fix `clippy::redundant_closure` lint on default arguments in `#[pyo3(signature = (...))]` annotations. [#2990](https://github.com/PyO3/pyo3/pull/2990) - Fix `non_snake_case` lint on generated code in `#[pyfunction]` macro. [#2993](https://github.com/PyO3/pyo3/pull/2993) - Fix some FFI definitions for the upcoming PyPy 3.10 release. [#3031](https://github.com/PyO3/pyo3/pull/3031) ## [0.18.1] - 2023-02-07 ### Added - Add `PyErr::write_unraisable()`. [#2889](https://github.com/PyO3/pyo3/pull/2889) - Add `Python::Ellipsis()` and `PyAny::is_ellipsis()` methods. [#2911](https://github.com/PyO3/pyo3/pull/2911) - Add `PyDict::update()` and `PyDict::update_if_missing()` methods. [#2912](https://github.com/PyO3/pyo3/pull/2912) ### Changed - FFI definition `PyIter_Check` on CPython 3.7 is now implemented as `hasattr(type(obj), "__next__")`, which works correctly on all platforms and adds support for `abi3`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Warn about unknown config keys in `PYO3_CONFIG_FILE` instead of denying. [#2926](https://github.com/PyO3/pyo3/pull/2926) ### Fixed - Send errors returned by `__releasebuffer__` to `sys.unraisablehook` rather than causing `SystemError`. [#2886](https://github.com/PyO3/pyo3/pull/2886) - Fix downcast to `PyIterator` succeeding for Python classes which did not implement `__next__`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Fix segfault in `__traverse__` when visiting `None` fields of `Option`. [#2921](https://github.com/PyO3/pyo3/pull/2921) - Fix `#[pymethods(crate = "...")]` option being ignored. [#2923](https://github.com/PyO3/pyo3/pull/2923) - Link against `pythonXY_d.dll` for debug Python builds on Windows. [#2937](https://github.com/PyO3/pyo3/pull/2937) ## [0.18.0] - 2023-01-17 ### Packaging - Relax `indexmap` optional depecency to allow `>= 1.6, < 2`. [#2849](https://github.com/PyO3/pyo3/pull/2849) - Relax `hashbrown` optional dependency to allow `>= 0.9, < 0.14`. [#2875](https://github.com/PyO3/pyo3/pull/2875) - Update `memoffset` dependency to 0.8. [#2875](https://github.com/PyO3/pyo3/pull/2875) ### Added - Add `GILOnceCell::get_or_try_init` for fallible `GILOnceCell` initialization. [#2398](https://github.com/PyO3/pyo3/pull/2398) - Add experimental feature `experimental-inspect` with `type_input()` and `type_output()` helpers to get the Python type of any Python-compatible object. [#2490](https://github.com/PyO3/pyo3/pull/2490) [#2882](https://github.com/PyO3/pyo3/pull/2882) - The `#[pyclass]` macro can now take `get_all` and `set_all` to create getters and setters for every field. [#2692](https://github.com/PyO3/pyo3/pull/2692) - Add `#[pyo3(signature = (...))]` option for `#[pyfunction]` and `#[pymethods]`. [#2702](https://github.com/PyO3/pyo3/pull/2702) - `pyo3-build-config`: rebuild when `PYO3_ENVIRONMENT_SIGNATURE` environment variable value changes. [#2727](https://github.com/PyO3/pyo3/pull/2727) - Add conversions between non-zero int types in `std::num` and Python `int`. [#2730](https://github.com/PyO3/pyo3/pull/2730) - Add `Py::downcast()` as a companion to `PyAny::downcast()`, as well as `downcast_unchecked()` for both types. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Add types for all built-in `Warning` classes as well as `PyErr::warn_explicit`. [#2742](https://github.com/PyO3/pyo3/pull/2742) - Add `abi3-py311` feature. [#2776](https://github.com/PyO3/pyo3/pull/2776) - Add FFI definition `_PyErr_ChainExceptions()` for CPython. [#2788](https://github.com/PyO3/pyo3/pull/2788) - Add FFI definitions `PyVectorcall_NARGS` and `PY_VECTORCALL_ARGUMENTS_OFFSET` for PyPy 3.8 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Add `PyList::get_item_unchecked` for PyPy. [#2827](https://github.com/PyO3/pyo3/pull/2827) ### Changed - PyO3's macros now emit a much nicer error message if function return values don't implement the required trait(s). [#2664](https://github.com/PyO3/pyo3/pull/2664) - Use a TypeError, rather than a ValueError, when refusing to treat a str as a Vec. [#2685](https://github.com/PyO3/pyo3/pull/2685) - Change `PyCFunction::new_closure` to take `name` and `doc` arguments. [#2686](https://github.com/PyO3/pyo3/pull/2686) - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now take `&PyAny` instead of `&PyType` arguments, so that they work with objects that pretend to be types using `__subclasscheck__` and `__instancecheck__`. [#2695](https://github.com/PyO3/pyo3/pull/2695) - Deprecate `#[args]` attribute and passing "args" specification directly to `#[pyfunction]` in favor of the new `#[pyo3(signature = (...))]` option. [#2702](https://github.com/PyO3/pyo3/pull/2702) - Deprecate required arguments after `Option` arguments to `#[pyfunction]` and `#[pymethods]` without also using `#[pyo3(signature)]` to specify whether the arguments should be required or have defaults. [#2703](https://github.com/PyO3/pyo3/pull/2703) - Change `#[pyfunction]` and `#[pymethods]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#2705](https://github.com/PyO3/pyo3/pull/2705) - `PyAny::cast_as()` and `Py::cast_as()` are now deprecated in favor of `PyAny::downcast()` and the new `Py::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Relax lifetime bounds on `PyAny::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Automatically generate `__text_signature__` for all Python functions created using `#[pyfunction]` and `#[pymethods]`. [#2784](https://github.com/PyO3/pyo3/pull/2784) - Accept any iterator in `PySet::new` and `PyFrozenSet::new`. [#2795](https://github.com/PyO3/pyo3/pull/2795) - Mixing `#[cfg(...)]` and `#[pyo3(...)]` attributes on `#[pyclass]` struct fields will now work. [#2796](https://github.com/PyO3/pyo3/pull/2796) - Re-enable `PyFunction` on when building for abi3 or PyPy. [#2838](https://github.com/PyO3/pyo3/pull/2838) - Improve `derive(FromPyObject)` to use `intern!` when applicable for `#[pyo3(item)]`. [#2879](https://github.com/PyO3/pyo3/pull/2879) ### Removed - Remove the deprecated `pyproto` feature, `#[pyproto]` macro, and all accompanying APIs. [#2587](https://github.com/PyO3/pyo3/pull/2587) - Remove all functionality deprecated in PyO3 0.16. [#2843](https://github.com/PyO3/pyo3/pull/2843) ### Fixed - Disable `PyModule::filename` on PyPy. [#2715](https://github.com/PyO3/pyo3/pull/2715) - `PyCodeObject` is now once again defined with fields on Python 3.7. [#2726](https://github.com/PyO3/pyo3/pull/2726) - Raise a `TypeError` if `#[new]` pymethods with no arguments receive arguments when called from Python. [#2749](https://github.com/PyO3/pyo3/pull/2749) - Use the `NOARGS` argument calling convention for methods that have a single `py: Python` argument (as a performance optimization). [#2760](https://github.com/PyO3/pyo3/pull/2760) - Fix truncation of `isize` values to `c_long` in `PySlice::new`. [#2769](https://github.com/PyO3/pyo3/pull/2769) - Fix soundness issue with FFI definition `PyUnicodeDecodeError_Create` on PyPy leading to indeterminate behavior (typically a `TypeError`). [#2772](https://github.com/PyO3/pyo3/pull/2772) - Allow functions taking `**kwargs` to accept keyword arguments which share a name with a positional-only argument (as permitted by PEP 570). [#2800](https://github.com/PyO3/pyo3/pull/2800) - Fix unresolved symbol for `PyObject_Vectorcall` on PyPy 3.9 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Fix memory leak in `PyCFunction::new_closure`. [#2842](https://github.com/PyO3/pyo3/pull/2842) ## [0.17.3] - 2022-11-01 ### Packaging - Support Python 3.11. (Previous versions of PyO3 0.17 have been tested against Python 3.11 release candidates and are expected to be compatible, this is the first version tested against Python 3.11.0.) [#2708](https://github.com/PyO3/pyo3/pull/2708) ### Added - Implemented `ExactSizeIterator` for `PyListIterator`, `PyDictIterator`, `PySetIterator` and `PyFrozenSetIterator`. [#2676](https://github.com/PyO3/pyo3/pull/2676) ### Fixed - Fix regression of `impl FromPyObject for [T; N]` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since version 0.17.0. This the same fix that was applied `impl FromPyObject for Vec` in version 0.17.1 extended to fixed-size arrays. [#2675](https://github.com/PyO3/pyo3/pull/2675) - Fix UB in `FunctionDescription::extract_arguments_fastcall` due to creating slices from a null pointer. [#2687](https://github.com/PyO3/pyo3/pull/2687) ## [0.17.2] - 2022-10-04 ### Packaging - Added optional `chrono` feature to convert `chrono` types into types in the `datetime` module. [#2612](https://github.com/PyO3/pyo3/pull/2612) ### Added - Add support for `num-bigint` feature on `PyPy`. [#2626](https://github.com/PyO3/pyo3/pull/2626) ### Fixed - Correctly implement `__richcmp__` for enums, fixing `__ne__` returning always returning `True`. [#2622](https://github.com/PyO3/pyo3/pull/2622) - Fix compile error since 0.17.0 with `Option<&SomePyClass>` argument with a default. [#2630](https://github.com/PyO3/pyo3/pull/2630) - Fix regression of `impl FromPyObject for Vec` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since 0.17.0. [#2631](https://github.com/PyO3/pyo3/pull/2631) ## [0.17.1] - 2022-08-28 ### Fixed - Fix visibility of `PyDictItems`, `PyDictKeys`, and `PyDictValues` types added in PyO3 0.17.0. - Fix compile failure when using `#[pyo3(from_py_with = "...")]` attribute on an argument of type `Option`. [#2592](https://github.com/PyO3/pyo3/pull/2592) - Fix clippy `redundant-closure` lint on `**kwargs` arguments for `#[pyfunction]` and `#[pymethods]`. [#2595](https://github.com/PyO3/pyo3/pull/2595) ## [0.17.0] - 2022-08-23 ### Packaging - Update inventory dependency to `0.3` (the `multiple-pymethods` feature now requires Rust 1.62 for correctness). [#2492](https://github.com/PyO3/pyo3/pull/2492) ### Added - Add `timezone_utc`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Implement `ToPyObject` for `[T; N]`. [#2313](https://github.com/PyO3/pyo3/pull/2313) - Add `PyDictKeys`, `PyDictValues` and `PyDictItems` Rust types. [#2358](https://github.com/PyO3/pyo3/pull/2358) - Add `append_to_inittab`. [#2377](https://github.com/PyO3/pyo3/pull/2377) - Add FFI definition `PyFrame_GetCode`. [#2406](https://github.com/PyO3/pyo3/pull/2406) - Add `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408) - Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, and `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Add `#[pyclass(frozen)]`. [#2448](https://github.com/PyO3/pyo3/pull/2448) - Accept `#[pyo3(name)]` on enum variants. [#2457](https://github.com/PyO3/pyo3/pull/2457) - Add `CompareOp::matches` to implement `__richcmp__` as the result of a Rust `std::cmp::Ordering` comparison. [#2460](https://github.com/PyO3/pyo3/pull/2460) - Add `PySuper` type. [#2486](https://github.com/PyO3/pyo3/pull/2486) - Support PyPy on Windows with the `generate-import-lib` feature. [#2506](https://github.com/PyO3/pyo3/pull/2506) - Add FFI definitions `Py_EnterRecursiveCall` and `Py_LeaveRecursiveCall`. [#2511](https://github.com/PyO3/pyo3/pull/2511) - Add `PyDict::get_item_with_error`. [#2536](https://github.com/PyO3/pyo3/pull/2536) - Add `#[pyclass(sequence)]` option. [#2567](https://github.com/PyO3/pyo3/pull/2567) ### Changed - Change datetime constructors taking a `tzinfo` to take `Option<&PyTzInfo>` instead of `Option<&PyObject>`: `PyDateTime::new`, `PyDateTime::new_with_fold`, `PyTime::new`, and `PyTime::new_with_fold`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Move `PyTypeObject::type_object` method to the `PyTypeInfo` trait, and deprecate the `PyTypeObject` trait. [#2287](https://github.com/PyO3/pyo3/pull/2287) - Methods of `Py` and `PyAny` now accept `impl IntoPy>` rather than just `&str` to allow use of the `intern!` macro. [#2312](https://github.com/PyO3/pyo3/pull/2312) - Change the deprecated `pyproto` feature to be opt-in instead of opt-out. [#2322](https://github.com/PyO3/pyo3/pull/2322) - Emit better error messages when `#[pyfunction]` return types do not implement `IntoPy`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Require `T: IntoPy` for `impl IntoPy for [T; N]` instead of `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Deprecate the `ToBorrowedObject` trait. [#2333](https://github.com/PyO3/pyo3/pull/2333) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Allow `#[classattr]` methods to be fallible. [#2385](https://github.com/PyO3/pyo3/pull/2385) - Prevent multiple `#[pymethods]` with the same name for a single `#[pyclass]`. [#2399](https://github.com/PyO3/pyo3/pull/2399) - Fixup `lib_name` when using `PYO3_CONFIG_FILE`. [#2404](https://github.com/PyO3/pyo3/pull/2404) - Add a message to the `ValueError` raised by the `#[derive(FromPyObject)]` implementation for a tuple struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Allow `#[classattr]` methods to take `Python` argument. [#2456](https://github.com/PyO3/pyo3/pull/2456) - Rework `PyCapsule` type to resolve soundness issues: [#2485](https://github.com/PyO3/pyo3/pull/2485) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take `name: Option` instead of `&CStr`. - The destructor `F` in `PyCapsule::new_with_destructor` must now be `Send`. - `PyCapsule::get_context` deprecated in favor of `PyCapsule::context` which doesn't take a `py: Python<'_>` argument. - `PyCapsule::set_context` no longer takes a `py: Python<'_>` argument. - `PyCapsule::name` now returns `PyResult>` instead of `&CStr`. - `FromPyObject::extract` for `Vec` no longer accepts Python `str` inputs. [#2500](https://github.com/PyO3/pyo3/pull/2500) - Ensure each `#[pymodule]` is only initialized once. [#2523](https://github.com/PyO3/pyo3/pull/2523) - `pyo3_build_config::add_extension_module_link_args` now also emits linker arguments for `wasm32-unknown-emscripten`. [#2538](https://github.com/PyO3/pyo3/pull/2538) - Type checks for `PySequence` and `PyMapping` now require inputs to inherit from (or register with) `collections.abc.Sequence` and `collections.abc.Mapping` respectively. [#2477](https://github.com/PyO3/pyo3/pull/2477) - Disable `PyFunction` on when building for abi3 or PyPy. [#2542](https://github.com/PyO3/pyo3/pull/2542) - Deprecate `Python::acquire_gil`. [#2549](https://github.com/PyO3/pyo3/pull/2549) ### Removed - Remove all functionality deprecated in PyO3 0.15. [#2283](https://github.com/PyO3/pyo3/pull/2283) - Make the `Dict`, `WeakRef` and `BaseNativeType` members of the `PyClass` private implementation details. [#2572](https://github.com/PyO3/pyo3/pull/2572) ### Fixed - Enable incorrectly disabled FFI definition `PyThreadState_DeleteCurrent`. [#2357](https://github.com/PyO3/pyo3/pull/2357) - Fix `wrap_pymodule` interactions with name resolution rules: it no longer "sees through" glob imports of `use submodule::*` when `submodule::submodule` is a `#[pymodule]`. [#2363](https://github.com/PyO3/pyo3/pull/2363) - Correct FFI definition `PyEval_EvalCodeEx` to take `*const *mut PyObject` array arguments instead of `*mut *mut PyObject`. [#2368](https://github.com/PyO3/pyo3/pull/2368) - Fix "raw-ident" structs (e.g. `#[pyclass] struct r#RawName`) incorrectly having `r#` at the start of the class name created in Python. [#2395](https://github.com/PyO3/pyo3/pull/2395) - Correct FFI definition `Py_tracefunc` to be `unsafe extern "C" fn` (was previously safe). [#2407](https://github.com/PyO3/pyo3/pull/2407) - Fix compile failure with `#[pyo3(from_py_with = "...")]` annotations on a field in a `#[derive(FromPyObject)]` struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` lacking leading underscores in their names. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Remove FFI definition `PyArena` on Python 3.10 and up. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Fix FFI definition `PyCompilerFlags` missing member `cf_feature_version` on Python 3.8 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyAsyncMethods` missing member `am_send` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyGenObject` having multiple incorrect members on various Python versions. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PySyntaxErrorObject` missing members `end_lineno` and `end_offset` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyHeapTypeObject` missing member `ht_module` on Python 3.9 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyFrameObject` having multiple incorrect members on various Python versions. [#2424](https://github.com/PyO3/pyo3/pull/2424) [#2434](https://github.com/PyO3/pyo3/pull/2434) - Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definitions `PyDateTime_CAPI`. `PyDateTime_Date`, `PyASCIIObject`, `PyBaseExceptionObject`, `PyListObject`, and `PyTypeObject` on PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definition `_inittab` field `initfunc` typo'd as `initfun`. [#2431](https://github.com/PyO3/pyo3/pull/2431) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` incorrectly having `fold` member. [#2432](https://github.com/PyO3/pyo3/pull/2432) - Fix FFI definitions `PyTypeObject`. `PyHeapTypeObject`, and `PyCFunctionObject` having incorrect members on PyPy 3.9. [#2433](https://github.com/PyO3/pyo3/pull/2433) - Fix FFI definition `PyGetSetDef` to have `*const c_char` for `doc` member (not `*mut c_char`). [#2439](https://github.com/PyO3/pyo3/pull/2439) - Fix `#[pyo3(from_py_with = "...")]` being ignored for 1-element tuple structs and transparent structs. [#2440](https://github.com/PyO3/pyo3/pull/2440) - Use `memoffset` to avoid UB when computing `PyCell` layout. [#2450](https://github.com/PyO3/pyo3/pull/2450) - Fix incorrect enum names being returned by the generated `repr` for enums renamed by `#[pyclass(name = "...")]` [#2457](https://github.com/PyO3/pyo3/pull/2457) - Fix `PyObject_CallNoArgs` incorrectly being available when building for abi3 on Python 3.9. [#2476](https://github.com/PyO3/pyo3/pull/2476) - Fix several clippy warnings generated by `#[pyfunction]` arguments. [#2503](https://github.com/PyO3/pyo3/pull/2503) ## [0.16.6] - 2022-08-23 ### Changed - Fix soundness issues with `PyCapsule` type with select workarounds. Users are encourage to upgrade to PyO3 0.17 at their earliest convenience which contains API breakages which fix the issues in a long-term fashion. [#2522](https://github.com/PyO3/pyo3/pull/2522) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take ownership of a copy of the `name` to resolve a possible use-after-free. - `PyCapsule::name` now returns an empty `CStr` instead of dereferencing a null pointer if the capsule has no name. - The destructor `F` in `PyCapsule::new_with_destructor` will never be called if the capsule is deleted from a thread other than the one which the capsule was created in (a warning will be emitted). - Panics during drop of panic payload caught by PyO3 will now abort. [#2544](https://github.com/PyO3/pyo3/pull/2544) ## [0.16.5] - 2022-05-15 ### Added - Add an experimental `generate-import-lib` feature to support auto-generating non-abi3 python import libraries for Windows targets. [#2364](https://github.com/PyO3/pyo3/pull/2364) - Add FFI definition `Py_ExitStatusException`. [#2374](https://github.com/PyO3/pyo3/pull/2374) ### Changed - Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364) ### Fixed - Added missing `warn_default_encoding` field to `PyConfig` on 3.10+. The previously missing field could result in incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) - Fixed order of `pathconfig_warnings` and `program_name` fields of `PyConfig` on 3.10+. Previously, the order of the fields was swapped and this could lead to incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) ## [0.16.4] - 2022-04-14 ### Added - Add `PyTzInfoAccess` trait for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) ### Changed - Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279) - Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) - Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) ### Fixed - Crates depending on PyO3 can collect code coverage via LLVM instrumentation using stable Rust. [#2286](https://github.com/PyO3/pyo3/pull/2286) - Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289) - Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299) ## [0.16.3] - 2022-04-05 ### Packaging - Extend `parking_lot` dependency supported versions to include 0.12. [#2239](https://github.com/PyO3/pyo3/pull/2239) ### Added - Add methods to `pyo3_build_config::InterpreterConfig` to run Python scripts using the configured executable. [#2092](https://github.com/PyO3/pyo3/pull/2092) - Add `as_bytes` method to `Py`. [#2235](https://github.com/PyO3/pyo3/pull/2235) - Add FFI definitions for `PyType_FromModuleAndSpec`, `PyType_GetModule`, `PyType_GetModuleState` and `PyModule_AddType`. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Add `pyo3_build_config::cross_compiling_from_to` as a helper to detect when PyO3 is cross-compiling. [#2253](https://github.com/PyO3/pyo3/pull/2253) - Add `#[pyclass(mapping)]` option to leave sequence slots empty in container implementations. [#2265](https://github.com/PyO3/pyo3/pull/2265) - Add `PyString::intern` to enable usage of the Python's built-in string interning. [#2268](https://github.com/PyO3/pyo3/pull/2268) - Add `intern!` macro which can be used to amortize the cost of creating Python strings by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269) - Add `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable for selecting the default cross Python implementation. [#2272](https://github.com/PyO3/pyo3/pull/2272) ### Changed - Allow `#[pyo3(crate = "...", text_signature = "...")]` options to be used directly in `#[pyclass(crate = "...", text_signature = "...")]`. [#2234](https://github.com/PyO3/pyo3/pull/2234) - Make `PYO3_CROSS_LIB_DIR` environment variable optional when cross compiling. [#2241](https://github.com/PyO3/pyo3/pull/2241) - Mark `METH_FASTCALL` calling convention as limited API on Python 3.10. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Deprecate `pyo3_build_config::cross_compiling` in favor of `pyo3_build_config::cross_compiling_from_to`. [#2253](https://github.com/PyO3/pyo3/pull/2253) ### Fixed - Fix `abi3-py310` feature: use Python 3.10 ABI when available instead of silently falling back to the 3.9 ABI. [#2242](https://github.com/PyO3/pyo3/pull/2242) - Use shared linking mode when cross compiling against a [Framework bundle](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html) for macOS. [#2233](https://github.com/PyO3/pyo3/pull/2233) - Fix panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232) - Correct dependency version for `syn` to require minimal patch version 1.0.56. [#2240](https://github.com/PyO3/pyo3/pull/2240) ## [0.16.2] - 2022-03-15 ### Packaging - Warn when modules are imported on PyPy 3.7 versions older than PyPy 7.3.8, as they are known to have binary compatibility issues. [#2217](https://github.com/PyO3/pyo3/pull/2217) - Ensure build script of `pyo3-ffi` runs before that of `pyo3` to fix cross compilation. [#2224](https://github.com/PyO3/pyo3/pull/2224) ## [0.16.1] - 2022-03-05 ### Packaging - Extend `hashbrown` optional dependency supported versions to include 0.12. [#2197](https://github.com/PyO3/pyo3/pull/2197) ### Fixed - Fix incorrect platform detection for Windows in `pyo3-build-config`. [#2198](https://github.com/PyO3/pyo3/pull/2198) - Fix regression from 0.16 preventing cross compiling to aarch64 macOS. [#2201](https://github.com/PyO3/pyo3/pull/2201) ## [0.16.0] - 2022-02-27 ### Packaging - Update MSRV to Rust 1.48. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Update `indoc` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006) - `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008) - Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019) - Drop `paste` dependency. [#2081](https://github.com/PyO3/pyo3/pull/2081) - The bindings found in `pyo3::ffi` are now a re-export of a separate `pyo3-ffi` crate. [#2126](https://github.com/PyO3/pyo3/pull/2126) - Support PyPy 3.9. [#2143](https://github.com/PyO3/pyo3/pull/2143) ### Added - Add `PyCapsule` type exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980) - Add `pyo3_build_config::Sysconfigdata` and supporting APIs. [#1996](https://github.com/PyO3/pyo3/pull/1996) - Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009) - Add `#[pyo3(crate = "some::path")]` option to all attribute macros (except the deprecated `#[pyproto]`). [#2022](https://github.com/PyO3/pyo3/pull/2022) - Enable `create_exception!` macro to take an optional docstring. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Enable `#[pyclass]` for fieldless (aka C-like) enums. [#2034](https://github.com/PyO3/pyo3/pull/2034) - Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067) - Add support for paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Enable `wrap_pyfunction!` to wrap a `#[pyfunction]` implemented in a different Rust module or crate. [#2091](https://github.com/PyO3/pyo3/pull/2091) - Add `PyAny::contains` method (`in` operator for `PyAny`). [#2115](https://github.com/PyO3/pyo3/pull/2115) - Add `PyMapping::contains` method (`in` operator for `PyMapping`). [#2133](https://github.com/PyO3/pyo3/pull/2133) - Add garbage collection magic magic methods `__traverse__` and `__clear__` to `#[pymethods]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - Add support for `from_py_with` on struct tuples and enums to override the default from-Python conversion. [#2181](https://github.com/PyO3/pyo3/pull/2181) - Add `eq`, `ne`, `lt`, `le`, `gt`, `ge` methods to `PyAny` that wrap `rich_compare`. [#2175](https://github.com/PyO3/pyo3/pull/2175) - Add `Py::is` and `PyAny::is` methods to check for object identity. [#2183](https://github.com/PyO3/pyo3/pull/2183) - Add support for the `__getattribute__` magic method. [#2187](https://github.com/PyO3/pyo3/pull/2187) ### Changed - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now operate run-time type object instead of a type known at compile-time. The old behavior is still available as `PyType::is_subclass_of`, `PyErr::is_instance_of` and `PyAny::is_instance_of`. [#1985](https://github.com/PyO3/pyo3/pull/1985) - Rename some methods on `PyErr` (the old names are just marked deprecated for now): [#2026](https://github.com/PyO3/pyo3/pull/2026) - `pytype` -> `get_type` - `pvalue` -> `value` (and deprecate equivalent `instance`) - `ptraceback` -> `traceback` - `from_instance` -> `from_value` - `into_instance` -> `into_value` - `PyErr::new_type` now takes an optional docstring and now returns `PyResult>` rather than a `ffi::PyTypeObject` pointer. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Deprecate `PyType::is_instance`; it is inconsistent with other `is_instance` methods in PyO3. Instead of `typ.is_instance(obj)`, use `obj.is_instance(typ)`. [#2031](https://github.com/PyO3/pyo3/pull/2031) - `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` now implement both a Python mapping and sequence by default. [#2065](https://github.com/PyO3/pyo3/pull/2065) - Improve performance and error messages for `#[derive(FromPyObject)]` for enums. [#2068](https://github.com/PyO3/pyo3/pull/2068) - Reduce generated LLVM code size (to improve compile times) for: - internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074) [#2158](https://github.com/PyO3/pyo3/pull/2158) - `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085) - `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081) [#2157](https://github.com/PyO3/pyo3/pull/2157) - Respect Rust privacy rules for items wrapped with `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Add modulo argument to `__ipow__` magic method. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix FFI definition for `_PyCFunctionFast`. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` and `PyDateTime_TimeZone_UTC` are now unsafe functions instead of statics. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` does not implicitly call `PyDateTime_IMPORT` anymore to reflect the original Python API more closely. Before the first call to `PyDateTime_IMPORT` a null pointer is returned. Therefore before calling any of the following FFI functions `PyDateTime_IMPORT` must be called to avoid undefined behavior: [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTime_TimeZone_UTC` - `PyDate_Check` - `PyDate_CheckExact` - `PyDateTime_Check` - `PyDateTime_CheckExact` - `PyTime_Check` - `PyTime_CheckExact` - `PyDelta_Check` - `PyDelta_CheckExact` - `PyTZInfo_Check` - `PyTZInfo_CheckExact` - `PyDateTime_FromTimestamp` - `PyDate_FromTimestamp` - Deprecate the `gc` option for `pyclass` (e.g. `#[pyclass(gc)]`). Just implement a `__traverse__` `#[pymethod]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - The `ml_meth` field of `PyMethodDef` is now represented by the `PyMethodDefPointer` union. [2166](https://github.com/PyO3/pyo3/pull/2166) - Deprecate the `#[pyproto]` traits. [#2173](https://github.com/PyO3/pyo3/pull/2173) ### Removed - Remove all functionality deprecated in PyO3 0.14. [#2007](https://github.com/PyO3/pyo3/pull/2007) - Remove `Default` impl for `PyMethodDef`. [#2166](https://github.com/PyO3/pyo3/pull/2166) - Remove `PartialEq` impl for `Py` and `PyAny` (use the new `is` instead). [#2183](https://github.com/PyO3/pyo3/pull/2183) ### Fixed - Fix undefined symbol for `PyObject_HasAttr` on PyPy. [#2025](https://github.com/PyO3/pyo3/pull/2025) - Fix memory leak in `PyErr::into_value`. [#2026](https://github.com/PyO3/pyo3/pull/2026) - Fix clippy warning `needless-option-as-deref` in code generated by `#[pyfunction]` and `#[pymethods]`. [#2040](https://github.com/PyO3/pyo3/pull/2040) - Fix undefined behavior in `PySlice::indices`. [#2061](https://github.com/PyO3/pyo3/pull/2061) - Fix the `wrap_pymodule!` macro using the wrong name for a `#[pymodule]` with a `#[pyo3(name = "..")]` attribute. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Fix magic methods in `#[pymethods]` accepting implementations with the wrong number of arguments. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix panic in `#[pyfunction]` generated code when a required argument following an `Option` was not provided. [#2093](https://github.com/PyO3/pyo3/pull/2093) - Fixed undefined behavior caused by incorrect `ExactSizeIterator` implementations. [#2124](https://github.com/PyO3/pyo3/pull/2124) - Fix missing FFI definition `PyCMethod_New` on Python 3.9 and up. [#2143](https://github.com/PyO3/pyo3/pull/2143) - Add missing FFI definitions `_PyLong_NumBits` and `_PyLong_AsByteArray` on PyPy. [#2146](https://github.com/PyO3/pyo3/pull/2146) - Fix memory leak in implementation of `AsPyPointer` for `Option`. [#2160](https://github.com/PyO3/pyo3/pull/2160) - Fix FFI definition of `_PyLong_NumBits` to return `size_t` instead of `c_int`. [#2161](https://github.com/PyO3/pyo3/pull/2161) - Fix `TypeError` thrown when argument parsing failed missing the originating causes. [2177](https://github.com/PyO3/pyo3/pull/2178) ## [0.15.2] - 2022-04-14 ### Packaging - Backport of PyPy 3.9 support from PyO3 0.16. [#2262](https://github.com/PyO3/pyo3/pull/2262) ## [0.15.1] - 2021-11-19 ### Added - Add implementations for `Py::as_ref` and `Py::into_ref` for `Py`, `Py` and `Py`. [#1682](https://github.com/PyO3/pyo3/pull/1682) - Add `PyTraceback` type to represent and format Python tracebacks. [#1977](https://github.com/PyO3/pyo3/pull/1977) ### Changed - `#[classattr]` constants with a known magic method name (which is lowercase) no longer trigger lint warnings expecting constants to be uppercase. [#1969](https://github.com/PyO3/pyo3/pull/1969) ### Fixed - Fix creating `#[classattr]` by functions with the name of a known magic method. [#1969](https://github.com/PyO3/pyo3/pull/1969) - Fix use of `catch_unwind` in `allow_threads` which can cause fatal crashes. [#1989](https://github.com/PyO3/pyo3/pull/1989) - Fix build failure on PyPy when abi3 features are activated. [#1991](https://github.com/PyO3/pyo3/pull/1991) - Fix mingw platform detection. [#1993](https://github.com/PyO3/pyo3/pull/1993) - Fix panic in `__get__` implementation when accessing descriptor on type object. [#1997](https://github.com/PyO3/pyo3/pull/1997) ## [0.15.0] - 2021-11-03 ### Packaging - `pyo3`'s `Cargo.toml` now advertises `links = "python"` to inform Cargo that it links against *libpython*. [#1819](https://github.com/PyO3/pyo3/pull/1819) - Added optional `anyhow` feature to convert `anyhow::Error` into `PyErr`. [#1822](https://github.com/PyO3/pyo3/pull/1822) - Support Python 3.10. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Added optional `eyre` feature to convert `eyre::Report` into `PyErr`. [#1893](https://github.com/PyO3/pyo3/pull/1893) - Support PyPy 3.8. [#1948](https://github.com/PyO3/pyo3/pull/1948) ### Added - Add `PyList::get_item_unchecked` and `PyTuple::get_item_unchecked` to get items without bounds checks. [#1733](https://github.com/PyO3/pyo3/pull/1733) - Support `#[doc = include_str!(...)]` attributes on Rust 1.54 and up. [#1746](https://github.com/PyO3/pyo3/issues/1746) - Add `PyAny::py` as a convenience for `PyNativeType::py`. [#1751](https://github.com/PyO3/pyo3/pull/1751) - Add implementation of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1825](https://github.com/PyO3/pyo3/pull/1825) - Add range indexing implementations of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Add `PyMapping` type to represent the Python mapping protocol. [#1844](https://github.com/PyO3/pyo3/pull/1844) - Add commonly-used sequence methods to `PyList` and `PyTuple`. [#1849](https://github.com/PyO3/pyo3/pull/1849) - Add `as_sequence` methods to `PyList` and `PyTuple`. [#1860](https://github.com/PyO3/pyo3/pull/1860) - Add support for magic methods in `#[pymethods]`, intended as a replacement for `#[pyproto]`. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Add `abi3-py310` feature. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Add `PyCFunction::new_closure` to create a Python function from a Rust closure. [#1901](https://github.com/PyO3/pyo3/pull/1901) - Add support for positional-only arguments in `#[pyfunction]`. [#1925](https://github.com/PyO3/pyo3/pull/1925) - Add `PyErr::take` to attempt to fetch a Python exception if present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Changed - `PyList`, `PyTuple` and `PySequence`'s APIs now accepts only `usize` indices instead of `isize`. [#1733](https://github.com/PyO3/pyo3/pull/1733), [#1802](https://github.com/PyO3/pyo3/pull/1802), [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PyList::get_item` and `PyTuple::get_item` now return `PyResult<&PyAny>` instead of panicking. [#1733](https://github.com/PyO3/pyo3/pull/1733) - `PySequence::in_place_repeat` and `PySequence::in_place_concat` now return `PyResult<&PySequence>` instead of `PyResult<()>`, which is needed in case of immutable sequences such as tuples. [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PySequence::get_slice` now returns `PyResult<&PySequence>` instead of `PyResult<&PyAny>`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Deprecate `PyTuple::split_from`. [#1804](https://github.com/PyO3/pyo3/pull/1804) - Deprecate `PyTuple::slice`, new method `PyTuple::get_slice` added with `usize` indices. [#1828](https://github.com/PyO3/pyo3/pull/1828) - Deprecate FFI definitions `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags` when building for Python 3.9. [#1830](https://github.com/PyO3/pyo3/pull/1830) - Mark FFI definitions removed in Python 3.10 `PyParser_ASTFromString`, `PyParser_ASTFromStringObject`, `PyParser_ASTFromFile`, `PyParser_ASTFromFileObject`, `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags`, `PyParser_SimpleParseString`, `PyParser_SimpleParseFile`, `Py_SymtableString`, and `Py_SymtableStringObject`. [#1830](https://github.com/PyO3/pyo3/pull/1830) - `#[pymethods]` now handles magic methods similarly to `#[pyproto]`. In the future, `#[pyproto]` may be deprecated. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Deprecate FFI definitions `PySys_AddWarnOption`, `PySys_AddWarnOptionUnicode` and `PySys_HasWarnOptions`. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Deprecate `#[call]` attribute in favor of using `fn __call__`. [#1929](https://github.com/PyO3/pyo3/pull/1929) - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) - Change `PyErr::fetch` to panic in debug mode if no exception is present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Fixed - Fix building with a conda environment on Windows. [#1873](https://github.com/PyO3/pyo3/pull/1873) - Fix panic on Python 3.6 when calling `Python::with_gil` with Python initialized but threading not initialized. [#1874](https://github.com/PyO3/pyo3/pull/1874) - Fix incorrect linking to version-specific DLL instead of `python3.dll` when cross-compiling to Windows with `abi3`. [#1880](https://github.com/PyO3/pyo3/pull/1880) - Fix FFI definition for `PyTuple_ClearFreeList` incorrectly being present for Python 3.9 and up. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Fix panic in generated `#[derive(FromPyObject)]` for enums. [#1888](https://github.com/PyO3/pyo3/pull/1888) - Fix cross-compiling to Python 3.7 builds with the "m" abi flag. [#1908](https://github.com/PyO3/pyo3/pull/1908) - Fix `__mod__` magic method fallback to `__rmod__`. [#1934](https://github.com/PyO3/pyo3/pull/1934). - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) ## [0.14.5] - 2021-09-05 ### Added - Make `pyo3_build_config::InterpreterConfig` and subfields public. [#1848](https://github.com/PyO3/pyo3/pull/1848) - Add `resolve-config` feature to the `pyo3-build-config` to control whether its build script does anything. [#1856](https://github.com/PyO3/pyo3/pull/1856) ### Fixed - Fix 0.14.4 compile regression on `s390x-unknown-linux-gnu` target. [#1850](https://github.com/PyO3/pyo3/pull/1850) ## [0.14.4] - 2021-08-29 ### Changed - Mark `PyString::data` as `unsafe` and disable it and some supporting PyUnicode FFI APIs (which depend on a C bitfield) on big-endian targets. [#1834](https://github.com/PyO3/pyo3/pull/1834) ## [0.14.3] - 2021-08-22 ### Added - Add `PyString::data` to access the raw bytes stored in a Python string. [#1794](https://github.com/PyO3/pyo3/pull/1794) ### Fixed - Raise `AttributeError` to avoid panic when calling `del` on a `#[setter]` defined class property. [#1779](https://github.com/PyO3/pyo3/pull/1779) - Restrict FFI definitions `PyGILState_Check` and `Py_tracefunc` to the unlimited API. [#1787](https://github.com/PyO3/pyo3/pull/1787) - Add missing `_type` field to `PyStatus` struct definition. [#1791](https://github.com/PyO3/pyo3/pull/1791) - Reduce lower bound `num-complex` optional dependency to support interop with `rust-numpy` and `ndarray` when building with the MSRV of 1.41 [#1799](https://github.com/PyO3/pyo3/pull/1799) - Fix memory leak in `Python::run_code`. [#1806](https://github.com/PyO3/pyo3/pull/1806) - Fix memory leak in `PyModule::from_code`. [#1810](https://github.com/PyO3/pyo3/pull/1810) - Remove use of `pyo3::` in `pyo3::types::datetime` which broke builds using `-Z avoid-dev-deps` [#1811](https://github.com/PyO3/pyo3/pull/1811) ## [0.14.2] - 2021-08-09 ### Added - Add `indexmap` feature to add `ToPyObject`, `IntoPy` and `FromPyObject` implementations for `indexmap::IndexMap`. [#1728](https://github.com/PyO3/pyo3/pull/1728) - Add `pyo3_build_config::add_extension_module_link_args` to use in build scripts to set linker arguments (for macOS). [#1755](https://github.com/PyO3/pyo3/pull/1755) - Add `Python::with_gil_unchecked` unsafe variation of `Python::with_gil` to allow obtaining a `Python` in scenarios where `Python::with_gil` would fail. [#1769](https://github.com/PyO3/pyo3/pull/1769) ### Changed - `PyErr::new` no longer acquires the Python GIL internally. [#1724](https://github.com/PyO3/pyo3/pull/1724) - Reverted PyO3 0.14.0's use of `cargo:rustc-cdylib-link-arg` in its build script, as Cargo unintentionally allowed crates to pass linker args to downstream crates in this way. Projects supporting macOS may need to restore `.cargo/config.toml` files. [#1755](https://github.com/PyO3/pyo3/pull/1755) ### Fixed - Fix regression in 0.14.0 rejecting usage of `#[doc(hidden)]` on structs and functions annotated with PyO3 macros. [#1722](https://github.com/PyO3/pyo3/pull/1722) - Fix regression in 0.14.0 leading to incorrect code coverage being computed for `#[pyfunction]`s. [#1726](https://github.com/PyO3/pyo3/pull/1726) - Fix incorrect FFI definition of `Py_Buffer` on PyPy. [#1737](https://github.com/PyO3/pyo3/pull/1737) - Fix incorrect calculation of `dictoffset` on 32-bit Windows. [#1475](https://github.com/PyO3/pyo3/pull/1475) - Fix regression in 0.13.2 leading to linking to incorrect Python library on Windows "gnu" targets. [#1759](https://github.com/PyO3/pyo3/pull/1759) - Fix compiler warning: deny trailing semicolons in expression macro. [#1762](https://github.com/PyO3/pyo3/pull/1762) - Fix incorrect FFI definition of `Py_DecodeLocale`. The 2nd argument is now `*mut Py_ssize_t` instead of `Py_ssize_t`. [#1766](https://github.com/PyO3/pyo3/pull/1766) ## [0.14.1] - 2021-07-04 ### Added - Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1712](https://github.com/PyO3/pyo3/pull/1712) ### Fixed - Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713) ## [0.14.0] - 2021-07-03 ### Packaging - Update `num-bigint` optional dependency to 0.4. [#1481](https://github.com/PyO3/pyo3/pull/1481) - Update `num-complex` optional dependency to 0.4. [#1482](https://github.com/PyO3/pyo3/pull/1482) - Extend `hashbrown` optional dependency supported versions to include 0.11. [#1496](https://github.com/PyO3/pyo3/pull/1496) - Support PyPy 3.7. [#1538](https://github.com/PyO3/pyo3/pull/1538) ### Added - Extend conversions for `[T; N]` to all `N` using const generics (on Rust 1.51 and up). [#1128](https://github.com/PyO3/pyo3/pull/1128) - Add conversions between `OsStr`/ `OsString` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379) - Add conversions between `Path`/ `PathBuf` and Python strings (and `pathlib.Path` objects). [#1379](https://github.com/PyO3/pyo3/pull/1379) [#1654](https://github.com/PyO3/pyo3/pull/1654) - Add a new set of `#[pyo3(...)]` attributes to control various PyO3 macro functionality: - `#[pyo3(from_py_with = "...")]` function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411) - `#[pyo3(name = "...")]` for setting Python names. [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyo3(text_signature = "...")]` for setting text signature. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473) - Add FFI definitions from `cpython/import.h`.[#1475](https://github.com/PyO3/pyo3/pull/1475) - Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504) - Add FFI definition `PyDateTime_TimeZone_UTC`. [#1572](https://github.com/PyO3/pyo3/pull/1572) - Add support for `#[pyclass(extends=Exception)]`. [#1591](https://github.com/PyO3/pyo3/pull/1591) - Add `PyErr::cause` and `PyErr::set_cause`. [#1679](https://github.com/PyO3/pyo3/pull/1679) - Add FFI definitions from `cpython/pystate.h`. [#1687](https://github.com/PyO3/pyo3/pull/1687/) - Add `wrap_pyfunction!` macro to `pyo3::prelude`. [#1695](https://github.com/PyO3/pyo3/pull/1695) ### Changed - Allow only one `#[pymethods]` block per `#[pyclass]` by default, to remove the dependency on `inventory`. Add a `multiple-pymethods` feature to opt-in the original behavior and dependency on `inventory`. [#1457](https://github.com/PyO3/pyo3/pull/1457) - Change `PyTimeAccess::get_fold` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397) - Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and up. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Deprecate FFI definition `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425) - The `auto-initialize` feature is no longer enabled by default. [#1443](https://github.com/PyO3/pyo3/pull/1443) - Change `PyCFunction::new` and `PyCFunction::new_with_keywords` to take `&'static str` arguments rather than implicitly copying (and leaking) them. [#1450](https://github.com/PyO3/pyo3/pull/1450) - Deprecate `PyModule::call`, `PyModule::call0`, `PyModule::call1` and `PyModule::get`. [#1492](https://github.com/PyO3/pyo3/pull/1492) - Add length information to `PyBufferError`s raised from `PyBuffer::copy_to_slice` and `PyBuffer::copy_from_slice`. [#1534](https://github.com/PyO3/pyo3/pull/1534) - Automatically set `-undefined` and `dynamic_lookup` linker arguments on macOS with the `extension-module` feature. [#1539](https://github.com/PyO3/pyo3/pull/1539) - Deprecate `#[pyproto]` methods which are easier to implement as `#[pymethods]`: [#1560](https://github.com/PyO3/pyo3/pull/1560) - `PyBasicProtocol::__bytes__` and `PyBasicProtocol::__format__` - `PyContextProtocol::__enter__` and `PyContextProtocol::__exit__` - `PyDescrProtocol::__delete__` and `PyDescrProtocol::__set_name__` - `PyMappingProtocol::__reversed__` - `PyNumberProtocol::__complex__` and `PyNumberProtocol::__round__` - `PyAsyncProtocol::__aenter__` and `PyAsyncProtocol::__aexit__` - Deprecate several attributes in favor of the new `#[pyo3(...)]` options: - `#[name = "..."]`, replaced by `#[pyo3(name = "...")]` [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyfn(m, "name")]`, replaced by `#[pyfn(m)] #[pyo3(name = "...")]`. [#1610](https://github.com/PyO3/pyo3/pull/1610) - `#[pymodule(name)]`, replaced by `#[pymodule] #[pyo3(name = "...")]` [#1650](https://github.com/PyO3/pyo3/pull/1650) - `#[text_signature = "..."]`, replaced by `#[pyo3(text_signature = "...")]`. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Reduce LLVM line counts to improve compilation times. [#1604](https://github.com/PyO3/pyo3/pull/1604) - No longer call `PyEval_InitThreads` in `#[pymodule]` init code. [#1630](https://github.com/PyO3/pyo3/pull/1630) - Use `METH_FASTCALL` argument passing convention, when possible, to improve `#[pyfunction]` and method performance. [#1619](https://github.com/PyO3/pyo3/pull/1619), [#1660](https://github.com/PyO3/pyo3/pull/1660) - Filter sysconfigdata candidates by architecture when cross-compiling. [#1626](https://github.com/PyO3/pyo3/pull/1626) ### Removed - Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove deprecated methods `Python::is_instance`, `Python::is_subclass`, `Python::release`, `Python::xdecref`, and `Py::from_owned_ptr_or_panic`. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove many FFI definitions which never existed in the Python C-API: - (previously deprecated) `PyGetSetDef_INIT`, `PyGetSetDef_DICT`, `PyCoro_Check`, `PyCoroWrapper_Check`, and `PyAsyncGen_Check` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyMethodDef_INIT` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyTypeObject_INIT` [#1429](https://github.com/PyO3/pyo3/pull/1429) - `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438) - `PyModuleDef_INIT` [#1630](https://github.com/PyO3/pyo3/pull/1630) - Remove pyclass implementation details from `PyTypeInfo`: - `Type`, `DESCRIPTION`, and `FLAGS` [#1456](https://github.com/PyO3/pyo3/pull/1456) - `BaseType`, `BaseLayout`, `Layout`, `Initializer` [#1596](https://github.com/PyO3/pyo3/pull/1596) - Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality. [#1521](https://github.com/PyO3/pyo3/pull/1521) - Remove `raw_pycfunction!` macro. [#1619](https://github.com/PyO3/pyo3/pull/1619) - Remove `PyClassAlloc` trait. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Remove `PyList::get_parked_item`. [#1664](https://github.com/PyO3/pyo3/pull/1664) ### Fixed - Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - `PYO3_CROSS_LIB_DIR` environment variable no long required when compiling for x86-64 Python from macOS arm64 and reverse. [#1428](https://github.com/PyO3/pyo3/pull/1428) - Fix FFI definition `_PyEval_RequestCodeExtraIndex`, which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Fix FFI definition `PyIndex_Check` missing with the `abi3` feature. [#1436](https://github.com/PyO3/pyo3/pull/1436) - Fix incorrect `TypeError` raised when keyword-only argument passed along with a positional argument in `*args`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix inability to use a named lifetime for `&PyTuple` of `*args` in `#[pyfunction]`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix use of Python argument for `#[pymethods]` inside macro expansions. [#1505](https://github.com/PyO3/pyo3/pull/1505) - No longer include `__doc__` in `__all__` generated for `#[pymodule]`. [#1509](https://github.com/PyO3/pyo3/pull/1509) - Always use cross-compiling configuration if any of the `PYO3_CROSS` family of environment variables are set. [#1514](https://github.com/PyO3/pyo3/pull/1514) - Support `EnvironmentError`, `IOError`, and `WindowsError` on PyPy. [#1533](https://github.com/PyO3/pyo3/pull/1533) - Fix unnecessary rebuilds when cycling between `cargo check` and `cargo clippy` in a Python virtualenv. [#1557](https://github.com/PyO3/pyo3/pull/1557) - Fix segfault when dereferencing `ffi::PyDateTimeAPI` without the GIL. [#1563](https://github.com/PyO3/pyo3/pull/1563) - Fix memory leak in `FromPyObject` implementations for `u128` and `i128`. [#1638](https://github.com/PyO3/pyo3/pull/1638) - Fix `#[pyclass(extends=PyDict)]` leaking the dict contents on drop. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Fix segfault when calling `PyList::get_item` with negative indices. [#1668](https://github.com/PyO3/pyo3/pull/1668) - Fix FFI definitions of `PyEval_SetProfile`/`PyEval_SetTrace` to take `Option` parameters. [#1692](https://github.com/PyO3/pyo3/pull/1692) - Fix `ToPyObject` impl for `HashSet` to accept non-default hashers. [#1702](https://github.com/PyO3/pyo3/pull/1702) ## [0.13.2] - 2021-02-12 ### Packaging - Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421) ### Added - Add unsafe API `with_embedded_python_interpreter` to initialize a Python interpreter, execute a closure, and finalize the interpreter. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Add `serde` feature which provides implementations of `Serialize` and `Deserialize` for `Py`. [#1366](https://github.com/PyO3/pyo3/pull/1366) - Add FFI definition `_PyCFunctionFastWithKeywords` on Python 3.7 and up. [#1384](https://github.com/PyO3/pyo3/pull/1384) - Add `PyDateTime::new_with_fold` method. [#1398](https://github.com/PyO3/pyo3/pull/1398) - Add `size_hint` impls for `{PyDict,PyList,PySet,PyTuple}Iterator`s. [#1699](https://github.com/PyO3/pyo3/pull/1699) ### Changed - `prepare_freethreaded_python` will no longer register an `atexit` handler to call `Py_Finalize`. This resolves a number of issues with incompatible C extensions causing crashes at finalization. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Mark `PyLayout::py_init`, `PyClassDict::clear_dict`, and `opt_to_pyobj` safe, as they do not perform any unsafe operations. [#1404](https://github.com/PyO3/pyo3/pull/1404) ### Fixed - Fix support for using `r#raw_idents` as argument names in pyfunctions. [#1383](https://github.com/PyO3/pyo3/pull/1383) - Fix typo in FFI definition for `PyFunction_GetCode` (was incorrectly `PyFunction_Code`). [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyMarshal_WriteObjectToString` and `PyMarshal_ReadObjectFromString` as available in limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyListObject` and those from `funcobject.h` as requiring non-limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix unqualified `Result` usage in `pyobject_native_type_base`. [#1402](https://github.com/PyO3/pyo3/pull/1402) - Fix build on systems where the default Python encoding is not UTF-8. [#1405](https://github.com/PyO3/pyo3/pull/1405) - Fix build on mingw / MSYS2. [#1423](https://github.com/PyO3/pyo3/pull/1423) ## [0.13.1] - 2021-01-10 ### Added - Add support for `#[pyclass(dict)]` and `#[pyclass(weakref)]` with the `abi3` feature on Python 3.9 and up. [#1342](https://github.com/PyO3/pyo3/pull/1342) - Add FFI definitions `PyOS_BeforeFork`, `PyOS_AfterFork_Parent`, `PyOS_AfterFork_Child` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Add an `auto-initialize` feature to control whether PyO3 should automatically initialize an embedded Python interpreter. For compatibility this feature is enabled by default in PyO3 0.13.1, but is planned to become opt-in from PyO3 0.14.0. [#1347](https://github.com/PyO3/pyo3/pull/1347) - Add support for cross-compiling to Windows without needing `PYO3_CROSS_INCLUDE_DIR`. [#1350](https://github.com/PyO3/pyo3/pull/1350) ### Deprecated - Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338) - Deprecate FFI definitions `PyGetSetDef_DICT` and `PyGetSetDef_INIT` which have never been in the Python API. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Deprecate FFI definitions `PyGen_NeedsFinalizing`, `PyImport_Cleanup` (removed in 3.9), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definition `PyOS_AfterFork` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions `PyCoro_Check`, `PyAsyncGen_Check`, and `PyCoroWrapper_Check`, which have never been in the Python API (for the first two, it is possible to use `PyCoro_CheckExact` and `PyAsyncGen_CheckExact` instead; these are the actual functions provided by the Python API). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions for `PyUnicode_FromUnicode`, `PyUnicode_AsUnicode` and `PyUnicode_AsUnicodeAndSize`, which will be removed from 3.12 and up due to [PEP 623](https://www.python.org/dev/peps/pep-0623/). [#1370](https://github.com/PyO3/pyo3/pull/1370) ### Removed - Remove FFI definition `PyFrame_ClearFreeList` when building for Python 3.9. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definition `_PyDict_Contains` when building for Python 3.10. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definitions `PyGen_NeedsFinalizing` and `PyImport_Cleanup` (for 3.9 and up), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) ### Fixed - Stop including `Py_TRACE_REFS` config setting automatically if `Py_DEBUG` is set on Python 3.8 and up. [#1334](https://github.com/PyO3/pyo3/pull/1334) - Remove `#[deny(warnings)]` attribute (and instead refuse warnings only in CI). [#1340](https://github.com/PyO3/pyo3/pull/1340) - Fix deprecation warning for missing `__module__` with `#[pyclass]`. [#1343](https://github.com/PyO3/pyo3/pull/1343) - Correct return type of `PyFrozenSet::empty` to `&PyFrozenSet` (was incorrectly `&PySet`). [#1351](https://github.com/PyO3/pyo3/pull/1351) - Fix missing `Py_INCREF` on heap type objects on Python versions before 3.8. [#1365](https://github.com/PyO3/pyo3/pull/1365) ## [0.13.0] - 2020-12-22 ### Packaging - Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250) - Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Rename internal crates `pyo3cls` and `pyo3-derive-backend` to `pyo3-macros` and `pyo3-macros-backend` respectively. [#1317](https://github.com/PyO3/pyo3/pull/1317) ### Added - Add support for building for CPython limited API. Opting-in to the limited API enables a single extension wheel built with PyO3 to be installable on multiple Python versions. This required a few minor changes to runtime behavior of of PyO3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152) - Add feature flags `abi3-py36`, `abi3-py37`, `abi3-py38` etc. to set the minimum Python version when using the limited API. [#1263](https://github.com/PyO3/pyo3/pull/1263) - Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Add FFI definitions for PEP 587 "Python Initialization Configuration". [#1247](https://github.com/PyO3/pyo3/pull/1247) - Add FFI definitions for `PyEval_SetProfile` and `PyEval_SetTrace`. [#1255](https://github.com/PyO3/pyo3/pull/1255) - Add FFI definitions for context.h functions (`PyContext_New`, etc). [#1259](https://github.com/PyO3/pyo3/pull/1259) - Add `PyAny::is_instance` method. [#1276](https://github.com/PyO3/pyo3/pull/1276) - Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282) - Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287) - Add conversions between `u128`/`i128` and `PyLong` for PyPy. [#1310](https://github.com/PyO3/pyo3/pull/1310) - Add `Python::version` and `Python::version_info` to get the running interpreter version. [#1322](https://github.com/PyO3/pyo3/pull/1322) - Add conversions for tuples of length 10, 11, and 12. [#1454](https://github.com/PyO3/pyo3/pull/1454) ### Changed - Change return type of `PyType::name` from `Cow` to `PyResult<&str>`. [#1152](https://github.com/PyO3/pyo3/pull/1152) - `#[pyclass(subclass)]` is now required for subclassing from Rust (was previously just required for subclassing from Python). [#1152](https://github.com/PyO3/pyo3/pull/1152) - Change `PyIterator` to be consistent with other native types: it is now used as `&PyIterator` instead of `PyIterator<'a>`. [#1176](https://github.com/PyO3/pyo3/pull/1176) - Change formatting of `PyDowncastError` messages to be closer to Python's builtin error messages. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275) - Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275) - Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278) - Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Require double-quotes for pyclass name argument e.g `#[pyclass(name = "MyClass")]`. [#1303](https://github.com/PyO3/pyo3/pull/1303) ### Deprecated - Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292) ### Removed - Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217) - Remove unused `python3` feature. [#1235](https://github.com/PyO3/pyo3/pull/1235) ### Fixed - Fix missing field in `PyCodeObject` struct (`co_posonlyargcount`) - caused invalid access to other fields in Python >3.7. [#1260](https://github.com/PyO3/pyo3/pull/1260) - Fix building for `x86_64-unknown-linux-musl` target from `x86_64-unknown-linux-gnu` host. [#1267](https://github.com/PyO3/pyo3/pull/1267) - Fix `#[text_signature]` interacting badly with rust `r#raw_identifiers`. [#1286](https://github.com/PyO3/pyo3/pull/1286) - Fix FFI definitions for `PyObject_Vectorcall` and `PyVectorcall_Call`. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Fix building with Anaconda python inside a virtualenv. [#1290](https://github.com/PyO3/pyo3/pull/1290) - Fix definition of opaque FFI types. [#1312](https://github.com/PyO3/pyo3/pull/1312) - Fix using custom error type in pyclass `#[new]` methods. [#1319](https://github.com/PyO3/pyo3/pull/1319) ## [0.12.4] - 2020-11-28 ### Fixed - Fix reference count bug in implementation of `From>` for `PyObject`, a regression introduced in PyO3 0.12. [#1297](https://github.com/PyO3/pyo3/pull/1297) ## [0.12.3] - 2020-10-12 ### Fixed - Fix support for Rust versions 1.39 to 1.44, broken by an incorrect internal update to paste 1.0 which was done in PyO3 0.12.2. [#1234](https://github.com/PyO3/pyo3/pull/1234) ## [0.12.2] - 2020-10-12 ### Added - Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209) - Add `Python::check_signals` as a safe a wrapper for `PyErr_CheckSignals`. [#1214](https://github.com/PyO3/pyo3/pull/1214) ### Fixed - Fix invalid document for protocol methods. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Hide docs of PyO3 private implementation details in `pyo3::class::methods`. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Fix unnecessary rebuild on PATH changes when the python interpreter is provided by PYO3_PYTHON. [#1231](https://github.com/PyO3/pyo3/pull/1231) ## [0.12.1] - 2020-09-16 ### Fixed - Fix building for a 32-bit Python on 64-bit Windows with a 64-bit Rust toolchain. [#1179](https://github.com/PyO3/pyo3/pull/1179) - Fix building on platforms where `c_char` is `u8`. [#1182](https://github.com/PyO3/pyo3/pull/1182) ## [0.12.0] - 2020-09-12 ### Added - Add FFI definitions `Py_FinalizeEx`, `PyOS_getsig`, and `PyOS_setsig`. [#1021](https://github.com/PyO3/pyo3/pull/1021) - Add `PyString::to_str` for accessing `PyString` as `&str`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Add `Python::with_gil` for executing a closure with the Python GIL. [#1037](https://github.com/PyO3/pyo3/pull/1037) - Add type information to failures in `PyAny::downcast`. [#1050](https://github.com/PyO3/pyo3/pull/1050) - Implement `Debug` for `PyIterator`. [#1051](https://github.com/PyO3/pyo3/pull/1051) - Add `PyBytes::new_with` and `PyByteArray::new_with` for initialising `bytes` and `bytearray` objects using a closure. [#1074](https://github.com/PyO3/pyo3/pull/1074) - Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065) - Add `Py::as_ref` and `Py::into_ref` for converting `Py` to `&T`. [#1098](https://github.com/PyO3/pyo3/pull/1098) - Add ability to return `Result` types other than `PyResult` from `#[pyfunction]`, `#[pymethod]` and `#[pyproto]` functions. [#1106](https://github.com/PyO3/pyo3/pull/1118). - Implement `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types (requires the `hashbrown` feature). [#1114](https://github.com/PyO3/pyo3/pull/1114) - Add `#[pyfunction(pass_module)]` and `#[pyfn(pass_module)]` to pass the module object as the first function argument. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add `PyModule::add_function` and `PyModule::add_submodule` as typed alternatives to `PyModule::add_wrapped`. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add native `PyCFunction` and `PyFunction` types. [#1163](https://github.com/PyO3/pyo3/pull/1163) ### Changed - Rework exception types: [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Rename exception types from e.g. `RuntimeError` to `PyRuntimeError`. The old names continue to exist but are deprecated. - Exception objects are now accessible as `&T` or `Py`, just like other Python-native types. - Rename `PyException::py_err` to `PyException::new_err`. - Rename `PyUnicodeDecodeErr::new_err` to `PyUnicodeDecodeErr::new`. - Remove `PyStopIteration::stop_iteration`. - Require `T: Send` for the return value `T` of `Python::allow_threads`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Rename `PYTHON_SYS_EXECUTABLE` to `PYO3_PYTHON`. The old name will continue to work (undocumented) but will be removed in a future release. [#1039](https://github.com/PyO3/pyo3/pull/1039) - Remove `unsafe` from signature of `PyType::as_type_ptr`. [#1047](https://github.com/PyO3/pyo3/pull/1047) - Change return type of `PyIterator::from_object` to `PyResult` (was `Result`). [#1051](https://github.com/PyO3/pyo3/pull/1051) - `IntoPy` is no longer implied by `FromPy`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Change `PyObject` to be a type alias for `Py`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Rework `PyErr` to be compatible with the `std::error::Error` trait: [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Implement `Display`, `Error`, `Send` and `Sync` for `PyErr` and `PyErrArguments`. - Add `PyErr::instance` for accessing `PyErr` as `&PyBaseException`. - `PyErr`'s fields are now an implementation detail. The equivalent values can be accessed with `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`. - Change receiver of `PyErr::print` and `PyErr::print_and_set_sys_last_vars` to `&self` (was `self`). - Remove `PyErrValue`, `PyErr::from_value`, `PyErr::into_normalized`, and `PyErr::normalize`. - Remove `PyException::into`. - Remove `Into>` for `PyErr` and `PyException`. - Change methods generated by `#[pyproto]` to return `NotImplemented` if Python should try a reversed operation. #[1072](https://github.com/PyO3/pyo3/pull/1072) - Change argument to `PyModule::add` to `impl IntoPy` (was `impl ToPyObject`). #[1124](https://github.com/PyO3/pyo3/pull/1124) ### Removed - Remove many exception and `PyErr` APIs; see the "changed" section above. [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Remove `PyString::to_string` (use new `PyString::to_str`). [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `PyString::as_bytes`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `Python::register_any`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `GILGuard::acquire` from the public API. Use `Python::acquire_gil` or `Python::with_gil`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Remove the `FromPy` trait. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Remove the `AsPyRef` trait. [#1098](https://github.com/PyO3/pyo3/pull/1098) ### Fixed - Correct FFI definitions `Py_SetProgramName` and `Py_SetPythonHome` to take `*const` arguments (was `*mut`). [#1021](https://github.com/PyO3/pyo3/pull/1021) - Fix `FromPyObject` for `num_bigint::BigInt` for Python objects with an `__index__` method. [#1027](https://github.com/PyO3/pyo3/pull/1027) - Correct FFI definition `_PyLong_AsByteArray` to take `*mut c_uchar` argument (was `*const c_uchar`). [#1029](https://github.com/PyO3/pyo3/pull/1029) - Fix segfault with `#[pyclass(dict, unsendable)]`. [#1058](https://github.com/PyO3/pyo3/pull/1058) [#1059](https://github.com/PyO3/pyo3/pull/1059) - Fix using `&Self` as an argument type for functions in a `#[pymethods]` block. [#1071](https://github.com/PyO3/pyo3/pull/1071) - Fix best-effort build against PyPy 3.6. [#1092](https://github.com/PyO3/pyo3/pull/1092) - Fix many cases of lifetime elision in `#[pyproto]` implementations. [#1093](https://github.com/PyO3/pyo3/pull/1093) - Fix detection of Python build configuration when cross-compiling. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Always link against libpython on android with the `extension-module` feature. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Fix the `+` operator not trying `__radd__` when both `__add__` and `__radd__` are defined in `PyNumberProtocol` (and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107) - Fix building with Anaconda python. [#1175](https://github.com/PyO3/pyo3/pull/1175) ## [0.11.1] - 2020-06-30 ### Added - `#[pyclass(unsendable)]`. [#1009](https://github.com/PyO3/pyo3/pull/1009) ### Changed - Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010) ## [0.11.0] - 2020-06-28 ### Added - Support stable versions of Rust (>=1.39). [#969](https://github.com/PyO3/pyo3/pull/969) - Add FFI definition `PyObject_AsFileDescriptor`. [#938](https://github.com/PyO3/pyo3/pull/938) - Add `PyByteArray::data`, `PyByteArray::as_bytes`, and `PyByteArray::as_bytes_mut`. [#967](https://github.com/PyO3/pyo3/pull/967) - Add `GILOnceCell` to use in situations where `lazy_static` or `once_cell` can deadlock. [#975](https://github.com/PyO3/pyo3/pull/975) - Add `Py::borrow`, `Py::borrow_mut`, `Py::try_borrow`, and `Py::try_borrow_mut` for accessing `#[pyclass]` values. [#976](https://github.com/PyO3/pyo3/pull/976) - Add `IterNextOutput` and `IterANextOutput` for returning from `__next__` / `__anext__`. [#997](https://github.com/PyO3/pyo3/pull/997) ### Changed - Simplify internals of `#[pyo3(get)]` attribute. (Remove the hidden API `GetPropertyValue`.) [#934](https://github.com/PyO3/pyo3/pull/934) - Call `Py_Finalize` at exit to flush buffers, etc. [#943](https://github.com/PyO3/pyo3/pull/943) - Add type parameter to PyBuffer. #[951](https://github.com/PyO3/pyo3/pull/951) - Require `Send` bound for `#[pyclass]`. [#966](https://github.com/PyO3/pyo3/pull/966) - Add `Python` argument to most methods on `PyObject` and `Py` to ensure GIL safety. [#970](https://github.com/PyO3/pyo3/pull/970) - Change signature of `PyTypeObject::type_object` - now takes `Python` argument and returns `&PyType`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::slice` and `PyTuple::split_from` from `Py` to `&PyTuple`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::as_slice` to `&[&PyAny]`. [#971](https://github.com/PyO3/pyo3/pull/971) - Rename `PyTypeInfo::type_object` to `type_object_raw`, and add `Python` argument. [#975](https://github.com/PyO3/pyo3/pull/975) - Update `num-complex` optional dependency from `0.2` to `0.3`. [#977](https://github.com/PyO3/pyo3/pull/977) - Update `num-bigint` optional dependency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978) - `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961) - `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990) - `#[pyproto]` methods can now have return value `T` or `PyResult` (previously only `PyResult` was supported). [#996](https://github.com/PyO3/pyo3/pull/996) - `#[pyproto]` methods can now skip annotating the return type if it is `()`. [#998](https://github.com/PyO3/pyo3/pull/998) ### Removed - Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930) ### Fixed - Fix passing explicit `None` to `Option` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936) - Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990) - Fix returning `Option` from `#[pyproto]` methods. [#996](https://github.com/PyO3/pyo3/pull/996) - Fix accepting `PyRef` and `PyRefMut` to `#[getter]` and `#[setter]` methods. [#999](https://github.com/PyO3/pyo3/pull/999) ## [0.10.1] - 2020-05-14 ### Fixed - Fix deadlock in `Python::acquire_gil` after dropping a `PyObject` or `Py`. [#924](https://github.com/PyO3/pyo3/pull/924) ## [0.10.0] - 2020-05-13 ### Added - Add FFI definition `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849) - Implement `IntoPy` for `HashSet` and `BTreeSet`. [#864](https://github.com/PyO3/pyo3/pull/864) - Add `PyAny::dir` method. [#886](https://github.com/PyO3/pyo3/pull/886) - Gate macros behind a `macros` feature (enabled by default). [#897](https://github.com/PyO3/pyo3/pull/897) - Add ability to define class attributes using `#[classattr]` on functions in `#[pymethods]`. [#905](https://github.com/PyO3/pyo3/pull/905) - Implement `Clone` for `PyObject` and `Py`. [#908](https://github.com/PyO3/pyo3/pull/908) - Implement `Deref` for all builtin types. (`PyList`, `PyTuple`, `PyDict` etc.) [#911](https://github.com/PyO3/pyo3/pull/911) - Implement `Deref` for `PyCell`. [#911](https://github.com/PyO3/pyo3/pull/911) - Add `#[classattr]` support for associated constants in `#[pymethods]`. [#914](https://github.com/PyO3/pyo3/pull/914) ### Changed - Panics will now be raised as a Python `PanicException`. [#797](https://github.com/PyO3/pyo3/pull/797) - Change `PyObject` and `Py` reference counts to decrement immediately upon drop when the GIL is held. [#851](https://github.com/PyO3/pyo3/pull/851) - Allow `PyIterProtocol` methods to use either `PyRef` or `PyRefMut` as the receiver type. [#856](https://github.com/PyO3/pyo3/pull/856) - Change the implementation of `FromPyObject` for `Py` to apply to a wider range of `T`, including all `T: PyClass`. [#880](https://github.com/PyO3/pyo3/pull/880) - Move all methods from the `ObjectProtocol` trait to the `PyAny` struct. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove need for `#![feature(specialization)]` in crates depending on PyO3. [#917](https://github.com/PyO3/pyo3/pull/917) ### Removed - Remove `PyMethodsProtocol` trait. [#889](https://github.com/PyO3/pyo3/pull/889) - Remove `num-traits` dependency. [#895](https://github.com/PyO3/pyo3/pull/895) - Remove `ObjectProtocol` trait. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove `PyAny::None`. Users should use `Python::None` instead. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove all `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917) ### Fixed - Fix support for `__radd__` and other `__r*__` methods as implementations for Python mathematical operators. [#839](https://github.com/PyO3/pyo3/pull/839) - Fix panics during garbage collection when traversing objects that were already mutably borrowed. [#855](https://github.com/PyO3/pyo3/pull/855) - Prevent `&'static` references to Python objects as arguments to `#[pyfunction]` and `#[pymethods]`. [#869](https://github.com/PyO3/pyo3/pull/869) - Fix lifetime safety bug with `AsPyRef::as_ref`. [#876](https://github.com/PyO3/pyo3/pull/876) - Fix `#[pyo3(get)]` attribute on `Py` fields. [#880](https://github.com/PyO3/pyo3/pull/880) - Fix segmentation faults caused by functions such as `PyList::get_item` returning borrowed objects when it was not safe to do so. [#890](https://github.com/PyO3/pyo3/pull/890) - Fix segmentation faults caused by nested `Python::acquire_gil` calls creating dangling references. [#893](https://github.com/PyO3/pyo3/pull/893) - Fix segmentatation faults when a panic occurs during a call to `Python::allow_threads`. [#912](https://github.com/PyO3/pyo3/pull/912) ## [0.9.2] - 2020-04-09 ### Added - `FromPyObject` implementations for `HashSet` and `BTreeSet`. [#842](https://github.com/PyO3/pyo3/pull/842) ### Fixed - Correctly detect 32bit architecture. [#830](https://github.com/PyO3/pyo3/pull/830) ## [0.9.1] - 2020-03-23 ### Fixed - Error messages for `#[pyclass]`. [#826](https://github.com/PyO3/pyo3/pull/826) - `FromPyObject` implementation for `PySequence`. [#827](https://github.com/PyO3/pyo3/pull/827) ## [0.9.0] - 2020-03-19 ### Added - `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyClass`, `PyLayout`, `PyClassInitializer`. [#683](https://github.com/PyO3/pyo3/pull/683) - Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716) - `FromPyObject` is now automatically implemented for `T: Clone` pyclasses. [#730](https://github.com/PyO3/pyo3/pull/730) - `#[pyo3(get)]` and `#[pyo3(set)]` will now use the Rust doc-comment from the field for the Python property. [#755](https://github.com/PyO3/pyo3/pull/755) - `#[setter]` functions may now take an argument of `Pyo3::Python`. [#760](https://github.com/PyO3/pyo3/pull/760) - `PyTypeInfo::BaseLayout` and `PyClass::BaseNativeType`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyDowncastImpl`. [#770](https://github.com/PyO3/pyo3/pull/770) - Implement `FromPyObject` and `IntoPy` traits for arrays (up to 32). [#778](https://github.com/PyO3/pyo3/pull/778) - `migration.md` and `types.md` in the guide. [#795](https://github.com/PyO3/pyo3/pull/795), #[802](https://github.com/PyO3/pyo3/pull/802) - `ffi::{_PyBytes_Resize, _PyDict_Next, _PyDict_Contains, _PyDict_GetDictPtr}`. #[820](https://github.com/PyO3/pyo3/pull/820) ### Changed - `#[new]` does not take `PyRawObject` and can return `Self`. [#683](https://github.com/PyO3/pyo3/pull/683) - The blanket implementations for `FromPyObject` for `&T` and `&mut T` are no longer specializable. Implement `PyTryFrom` for your type to control the behavior of `FromPyObject::extract` for your types. [#713](https://github.com/PyO3/pyo3/pull/713) - The implementation for `IntoPy for T` where `U: FromPy` is no longer specializable. Control the behavior of this via the implementation of `FromPy`. [#713](https://github.com/PyO3/pyo3/pull/713) - Use `parking_lot::Mutex` instead of `spin::Mutex`. [#734](https://github.com/PyO3/pyo3/pull/734) - Bumped minimum Rust version to `1.42.0-nightly 2020-01-21`. [#761](https://github.com/PyO3/pyo3/pull/761) - `PyRef` and `PyRefMut` are renewed for `PyCell`. [#770](https://github.com/PyO3/pyo3/pull/770) - Some new FFI functions for Python 3.8. [#784](https://github.com/PyO3/pyo3/pull/784) - `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816) ### Removed - `PyRawObject`. [#683](https://github.com/PyO3/pyo3/pull/683) - `PyNoArgsFunction`. [#741](https://github.com/PyO3/pyo3/pull/741) - `initialize_type`. To set the module name for a `#[pyclass]`, use the `module` argument to the macro. #[751](https://github.com/PyO3/pyo3/pull/751) - `AsPyRef::as_mut/with/with_mut/into_py/into_mut_py`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyTryFrom::try_from_mut/try_from_mut_exact/try_from_mut_unchecked`. [#770](https://github.com/PyO3/pyo3/pull/770) - `Python::mut_from_owned_ptr/mut_from_borrowed_ptr`. [#770](https://github.com/PyO3/pyo3/pull/770) - `ObjectProtocol::get_base/get_mut_base`. [#770](https://github.com/PyO3/pyo3/pull/770) ### Fixed - Fixed unsoundness of subclassing. [#683](https://github.com/PyO3/pyo3/pull/683). - Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719) - Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745) - Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760) - `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769) - `"*"` in a `#[pyfunction()]` argument list incorrectly accepting any number of positional arguments (use `args = "*"` when this behavior is desired). #[792](https://github.com/PyO3/pyo3/pull/792) - `PyModule::dict`. #[809](https://github.com/PyO3/pyo3/pull/809) - Fix the case where `DESCRIPTION` is not null-terminated. #[822](https://github.com/PyO3/pyo3/pull/822) ## [0.8.5] - 2020-01-05 ### Added - Implemented `FromPyObject` for `HashMap` and `BTreeMap` - Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692) ## [0.8.4] - 2019-12-14 ### Added - Support for `#[text_signature]` attribute. [#675](https://github.com/PyO3/pyo3/pull/675) ## [0.8.3] - 2019-11-23 ### Removed - `#[init]` is removed. [#658](https://github.com/PyO3/pyo3/pull/658) ### Fixed - Now all `&Py~` types have `!Send` bound. [#655](https://github.com/PyO3/pyo3/pull/655) - Fix a compile error raised by the stabilization of `!` type. [#672](https://github.com/PyO3/pyo3/issues/672). ## [0.8.2] - 2019-10-27 ### Added - FFI compatibility for PEP 590 Vectorcall. [#641](https://github.com/PyO3/pyo3/pull/641) ### Fixed - Fix PySequenceProtocol::set_item. [#624](https://github.com/PyO3/pyo3/pull/624) - Fix a corner case of BigInt::FromPyObject. [#630](https://github.com/PyO3/pyo3/pull/630) - Fix index errors in parameter conversion. [#631](https://github.com/PyO3/pyo3/pull/631) - Fix handling of invalid utf-8 sequences in `PyString::as_bytes`. [#639](https://github.com/PyO3/pyo3/pull/639) and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642). - Remove `__contains__` and `__iter__` from PyMappingProtocol. [#644](https://github.com/PyO3/pyo3/pull/644) - Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645) ## [0.8.1] - 2019-10-08 ### Added - Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608) ### Fixed - Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604) - Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614) - Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597) ## [0.8.0] - 2019-09-16 ### Added - `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499) - `py_run!` macro [#512](https://github.com/PyO3/pyo3/pull/512) - Use existing fields and methods before calling custom **getattr**. [#505](https://github.com/PyO3/pyo3/pull/505) - `PyBytes` can now be indexed just like `Vec` - Implement `IntoPy` for `PyRef` and `PyRefMut`. ### Changed - Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532) - `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound) - Replace `mashup` with `paste`. - `GILPool` gained a `Python` marker to prevent it from being misused to release Python objects without the GIL held. ### Removed - `IntoPyObject` was replaced with `IntoPy` - `#[pyclass(subclass)]` is hidden a `unsound-subclass` feature because it's causing segmentation faults. ### Fixed - More readable error message for generics in pyclass [#503](https://github.com/PyO3/pyo3/pull/503) ## [0.7.0] - 2019-05-26 ### Added - PyPy support by omerbenamram in [#393](https://github.com/PyO3/pyo3/pull/393) - Have `PyModule` generate an index of its members (`__all__` list). - Allow `slf: PyRef` for pyclass(#419) - Allow to use lifetime specifiers in `pymethods` - Add `marshal` module. [#460](https://github.com/PyO3/pyo3/pull/460) ### Changed - `Python::run` returns `PyResult<()>` instead of `PyResult<&PyAny>`. - Methods decorated with `#[getter]` and `#[setter]` can now omit wrapping the result type in `PyResult` if they don't raise exceptions. ### Fixed - `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB. - Fixed automatic derive of `PySequenceProtocol` implementation in [#423](https://github.com/PyO3/pyo3/pull/423). - Capitalization & better wording to README.md. - Docstrings of properties is now properly set using the doc of the `#[getter]` method. - Fixed issues with `pymethods` crashing on doc comments containing double quotes. - `PySet::new` and `PyFrozenSet::new` now return `PyResult<&Py[Frozen]Set>`; exceptions are raised if the items are not hashable. - Fixed building using `venv` on Windows. - `PyTuple::new` now returns `&PyTuple` instead of `Py`. - Fixed several issues with argument parsing; notable, the `*args` and `**kwargs` tuple/dict now doesn't contain arguments that are otherwise assigned to parameters. ## [0.6.0] - 2019-03-28 ### Regressions - Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` to fail with weird linking errors when the `extension-module` feature is activated. For now you can work around this by making the `extension-module` feature optional and running the tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] version = "0.6.0" [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` ### Added - Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3 - Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details. - The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335) - Added `FromPy` and `IntoPy` which are equivalent to `From` and `Into` except that they require a gil token. - Added `ManagedPyRef`, which should eventually replace `ToBorrowedObject`. ### Changed - Renamed `PyObjectRef` to `PyAny` in #388 - Renamed `add_function` to `add_wrapped` as it now also supports modules. - Renamed `#[pymodinit]` to `#[pymodule]` - `py.init(|| value)` becomes `Py::new(value)` - `py.init_ref(|| value)` becomes `PyRef::new(value)` - `py.init_mut(|| value)` becomes `PyRefMut::new(value)`. - `PyRawObject::init` is now infallible, e.g. it returns `()` instead of `PyResult<()>`. - Renamed `py_exception!` to `create_exception!` and refactored the error macros. - Renamed `wrap_function!` to `wrap_pyfunction!` - Renamed `#[prop(get, set)]` to `#[pyo3(get, set)]` - `#[pyfunction]` now supports the same arguments as `#[pyfn()]` - Some macros now emit proper spanned errors instead of panics. - Migrated to the 2018 edition - `crate::types::exceptions` moved to `crate::exceptions` - Replace `IntoPyTuple` with `IntoPy>`. - `IntoPyPointer` and `ToPyPointer` moved into the crate root. - `class::CompareOp` moved into `class::basic::CompareOp` - PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350) - Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358) - Renamed the `typeob` module to `type_object` ### Removed - `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)). - Removed the unnecessary type parameter from `PyObjectAlloc` - `NoArgs`. Just use an empty tuple - `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed. ### Fixed - A soudness hole where every instances of a `#[pyclass]` struct was considered to be part of a python object, even though you can create instances that are not part of the python heap. This was fixed through `PyRef` and `PyRefMut`. - Fix kwargs support in [#328](https://github.com/PyO3/pyo3/pull/328). - Add full support for `__dict__` in [#403](https://github.com/PyO3/pyo3/pull/403). ## [0.5.3] - 2019-01-04 ### Fixed - Fix memory leak in ArrayList by kngwyu [#316](https://github.com/PyO3/pyo3/pull/316) ## [0.5.2] - 2018-11-25 ### Fixed - Fix undeterministic segfaults when creating many objects by kngwyu in [#281](https://github.com/PyO3/pyo3/pull/281) ## [0.5.1] - 2018-11-24 Yanked ## [0.5.0] - 2018-11-11 ### Added - `#[pyclass]` objects can now be returned from rust functions - `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226) - `PyDict::from_sequence`, equivalent to `dict([(key, val), ...])` - Bindings for the `datetime` standard library types: `PyDate`, `PyTime`, `PyDateTime`, `PyTzInfo`, `PyDelta` with associated `ffi` types, by pganssle [#200](https://github.com/PyO3/pyo3/pull/200). - `PyString`, `PyUnicode`, and `PyBytes` now have an `as_bytes` method that returns `&[u8]`. - `PyObjectProtocol::get_type_ptr` by ijl in [#242](https://github.com/PyO3/pyo3/pull/242) ### Changed - Removes the types from the root module and the prelude. They now live in `pyo3::types` instead. - All exceptions are constructed with `py_err` instead of `new`, as they return `PyErr` and not `Self`. - `as_mut` and friends take and `&mut self` instead of `&self` - `ObjectProtocol::call` now takes an `Option<&PyDict>` for the kwargs instead of an `IntoPyDictPointer`. - `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`. - `PyTuple::new` now takes an `IntoIterator` instead of a slice - Updated to syn 0.15 - Split `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc + PyTypeInfo + Sized`. - Ran `cargo edition --fix` which prefixed path with `crate::` for rust 2018 - Renamed `async` to `pyasync` as async will be a keyword in the 2018 edition. - Starting to use `NonNull<*mut PyObject>` for Py and PyObject by ijl [#260](https://github.com/PyO3/pyo3/pull/260) ### Removed - Removed most entries from the prelude. The new prelude is small and clear. - Slowly removing specialization uses - `PyString`, `PyUnicode`, and `PyBytes` no longer have a `data` method (replaced by `as_bytes`) and `PyStringData` has been removed. - The pyobject_extract macro ### Fixed - Added an explanation that the GIL can temporarily be released even while holding a GILGuard. - Lots of clippy errors - Fix segfault on calling an unknown method on a PyObject - Work around a [bug](https://github.com/rust-lang/rust/issues/55380) in the rust compiler by kngwyu [#252](https://github.com/PyO3/pyo3/pull/252) - Fixed a segfault with subclassing pyo3 create classes and using `__class__` by kngwyu [#263](https://github.com/PyO3/pyo3/pull/263) ## [0.4.1] - 2018-08-20 ### Changed - PyTryFrom's error is always to `PyDowncastError` ### Fixed - Fixed compilation on nightly since `use_extern_macros` was stabilized ### Removed - The pyobject_downcast macro ## [0.4.0] - 2018-07-30 ### Changed - Merged both examples into one - Rustfmt all the things :heavy_check_mark: - Switched to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Removed - Conversions from tuples to PyDict due to [rust-lang/rust#52050](https://github.com/rust-lang/rust/issues/52050) ## [0.3.2] - 2018-07-22 ### Changed - Replaced `concat_idents` with mashup ## [0.3.1] - 2018-07-18 ### Fixed - Fixed scoping bug in pyobject_native_type that would break rust-numpy ## [0.3.0] - 2018-07-18 ### Added - A few internal macros became part of the public api ([#155](https://github.com/PyO3/pyo3/pull/155), [#186](https://github.com/PyO3/pyo3/pull/186)) - Always clone in getters. This allows using the get-annotation on all Clone-Types ### Changed - Upgraded to syn 0.14 which means much better error messages :tada: - 128 bit integer support by [kngwyu](https://github.com/kngwyu) ([#137](https://github.com/PyO3/pyo3/pull/173)) - `proc_macro` has been stabilized on nightly ([rust-lang/rust#52081](https://github.com/rust-lang/rust/pull/52081)). This means that we can remove the `proc_macro` feature, but now we need the `use_extern_macros` from the 2018 edition instead. - All proc macro are now prefixed with `py` and live in the prelude. This means you can use `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]` directly, at least after a `use pyo3::prelude::*`. They were also moved into a module called `proc_macro`. You shouldn't use `#[pyo3::proc_macro::pyclass]` or other longer paths in attributes because `proc_macro_path_invoc` isn't going to be stabilized soon. - Renamed the `base` option in the `pyclass` macro to `extends`. - `#[pymodinit]` uses the function name as module name, unless the name is overridden with `#[pymodinit(name)]` - The guide is now properly versioned. ## [0.2.7] - 2018-05-18 ### Fixed - Fix nightly breakage with proc_macro_path ## [0.2.6] - 2018-04-03 ### Fixed - Fix compatibility with TryFrom trait #137 ## [0.2.5] - 2018-02-21 ### Added - CPython 3.7 support ### Fixed - Embedded CPython 3.7b1 crashes on initialization #110 - Generated extension functions are weakly typed #108 - call_method\* crashes when the method does not exist #113 - Allow importing exceptions from nested modules #116 ## [0.2.4] - 2018-01-19 ### Added - Allow to get mutable ref from PyObject #106 - Drop `RefFromPyObject` trait - Add Python::register_any method ### Fixed - Fix impl `FromPyObject` for `Py` - Mark method that work with raw pointers as unsafe #95 ## [0.2.3] - 11-27-2017 ### Changed - Rustup to 1.23.0-nightly 2017-11-07 ### Fixed - Proper `c_char` usage #93 ### Removed - Remove use of now unneeded 'AsciiExt' trait ## [0.2.2] - 09-26-2017 ### Changed - Rustup to 1.22.0-nightly 2017-09-30 ## [0.2.1] - 09-26-2017 ### Fixed - Fix rustc const_fn nightly breakage ## [0.2.0] - 08-12-2017 ### Added - Added inheritance support #15 - Added weakref support #56 - Added subclass support #64 - Added `self.__dict__` support #68 - Added `pyo3::prelude` module #70 - Better `Iterator` support for PyTuple, PyList, PyDict #75 - Introduce IntoPyDictPointer similar to IntoPyTuple #69 ### Changed - Allow to add gc support without implementing PyGCProtocol #57 - Refactor `PyErr` implementation. Drop `py` parameter from constructor. ## [0.1.0] - 07-23-2017 ### Added - Initial release [Unreleased]: https://github.com/pyo3/pyo3/compare/v0.27.1...HEAD [0.27.1]: https://github.com/pyo3/pyo3/compare/v0.27.0...v0.27.1 [0.27.0]: https://github.com/pyo3/pyo3/compare/v0.26.0...v0.27.0 [0.26.0]: https://github.com/pyo3/pyo3/compare/v0.25.1...v0.26.0 [0.25.1]: https://github.com/pyo3/pyo3/compare/v0.25.0...v0.25.1 [0.25.0]: https://github.com/pyo3/pyo3/compare/v0.24.2...v0.25.0 [0.24.2]: https://github.com/pyo3/pyo3/compare/v0.24.1...v0.24.2 [0.24.1]: https://github.com/pyo3/pyo3/compare/v0.24.0...v0.24.1 [0.24.0]: https://github.com/pyo3/pyo3/compare/v0.23.5...v0.24.0 [0.23.5]: https://github.com/pyo3/pyo3/compare/v0.23.4...v0.23.5 [0.23.4]: https://github.com/pyo3/pyo3/compare/v0.23.3...v0.23.4 [0.23.3]: https://github.com/pyo3/pyo3/compare/v0.23.2...v0.23.3 [0.23.2]: https://github.com/pyo3/pyo3/compare/v0.23.1...v0.23.2 [0.23.1]: https://github.com/pyo3/pyo3/compare/v0.23.0...v0.23.1 [0.23.0]: https://github.com/pyo3/pyo3/compare/v0.22.5...v0.23.0 [0.22.5]: https://github.com/pyo3/pyo3/compare/v0.22.4...v0.22.5 [0.22.4]: https://github.com/pyo3/pyo3/compare/v0.22.3...v0.22.4 [0.22.3]: https://github.com/pyo3/pyo3/compare/v0.22.2...v0.22.3 [0.22.2]: https://github.com/pyo3/pyo3/compare/v0.22.1...v0.22.2 [0.22.1]: https://github.com/pyo3/pyo3/compare/v0.22.0...v0.22.1 [0.22.0]: https://github.com/pyo3/pyo3/compare/v0.21.2...v0.22.0 [0.21.2]: https://github.com/pyo3/pyo3/compare/v0.21.1...v0.21.2 [0.21.1]: https://github.com/pyo3/pyo3/compare/v0.21.0...v0.21.1 [0.21.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0 [0.21.0-beta.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0-beta.0 [0.20.3]: https://github.com/pyo3/pyo3/compare/v0.20.2...v0.20.3 [0.20.2]: https://github.com/pyo3/pyo3/compare/v0.20.1...v0.20.2 [0.20.1]: https://github.com/pyo3/pyo3/compare/v0.20.0...v0.20.1 [0.20.0]: https://github.com/pyo3/pyo3/compare/v0.19.2...v0.20.0 [0.19.2]: https://github.com/pyo3/pyo3/compare/v0.19.1...v0.19.2 [0.19.1]: https://github.com/pyo3/pyo3/compare/v0.19.0...v0.19.1 [0.19.0]: https://github.com/pyo3/pyo3/compare/v0.18.3...v0.19.0 [0.18.3]: https://github.com/pyo3/pyo3/compare/v0.18.2...v0.18.3 [0.18.2]: https://github.com/pyo3/pyo3/compare/v0.18.1...v0.18.2 [0.18.1]: https://github.com/pyo3/pyo3/compare/v0.18.0...v0.18.1 [0.18.0]: https://github.com/pyo3/pyo3/compare/v0.17.3...v0.18.0 [0.17.3]: https://github.com/pyo3/pyo3/compare/v0.17.2...v0.17.3 [0.17.2]: https://github.com/pyo3/pyo3/compare/v0.17.1...v0.17.2 [0.17.1]: https://github.com/pyo3/pyo3/compare/v0.17.0...v0.17.1 [0.17.0]: https://github.com/pyo3/pyo3/compare/v0.16.6...v0.17.0 [0.16.6]: https://github.com/pyo3/pyo3/compare/v0.16.5...v0.16.6 [0.16.5]: https://github.com/pyo3/pyo3/compare/v0.16.4...v0.16.5 [0.16.4]: https://github.com/pyo3/pyo3/compare/v0.16.3...v0.16.4 [0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.2...v0.16.3 [0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2 [0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1 [0.16.0]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.16.0 [0.15.2]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.15.2 [0.15.1]: https://github.com/pyo3/pyo3/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/pyo3/pyo3/compare/v0.14.5...v0.15.0 [0.14.5]: https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5 [0.14.4]: https://github.com/pyo3/pyo3/compare/v0.14.3...v0.14.4 [0.14.3]: https://github.com/pyo3/pyo3/compare/v0.14.2...v0.14.3 [0.14.2]: https://github.com/pyo3/pyo3/compare/v0.14.1...v0.14.2 [0.14.1]: https://github.com/pyo3/pyo3/compare/v0.14.0...v0.14.1 [0.14.0]: https://github.com/pyo3/pyo3/compare/v0.13.2...v0.14.0 [0.13.2]: https://github.com/pyo3/pyo3/compare/v0.13.1...v0.13.2 [0.13.1]: https://github.com/pyo3/pyo3/compare/v0.13.0...v0.13.1 [0.13.0]: https://github.com/pyo3/pyo3/compare/v0.12.4...v0.13.0 [0.12.4]: https://github.com/pyo3/pyo3/compare/v0.12.3...v0.12.4 [0.12.3]: https://github.com/pyo3/pyo3/compare/v0.12.2...v0.12.3 [0.12.2]: https://github.com/pyo3/pyo3/compare/v0.12.1...v0.12.2 [0.12.1]: https://github.com/pyo3/pyo3/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/pyo3/pyo3/compare/v0.11.1...v0.12.0 [0.11.1]: https://github.com/pyo3/pyo3/compare/v0.11.0...v0.11.1 [0.11.0]: https://github.com/pyo3/pyo3/compare/v0.10.1...v0.11.0 [0.10.1]: https://github.com/pyo3/pyo3/compare/v0.10.0...v0.10.1 [0.10.0]: https://github.com/pyo3/pyo3/compare/v0.9.2...v0.10.0 [0.9.2]: https://github.com/pyo3/pyo3/compare/v0.9.1...v0.9.2 [0.9.1]: https://github.com/pyo3/pyo3/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/pyo3/pyo3/compare/v0.8.5...v0.9.0 [0.8.5]: https://github.com/pyo3/pyo3/compare/v0.8.4...v0.8.5 [0.8.4]: https://github.com/pyo3/pyo3/compare/v0.8.3...v0.8.4 [0.8.3]: https://github.com/pyo3/pyo3/compare/v0.8.2...v0.8.3 [0.8.2]: https://github.com/pyo3/pyo3/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/pyo3/pyo3/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/pyo3/pyo3/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/pyo3/pyo3/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/pyo3/pyo3/compare/v0.5.3...v0.6.0 [0.5.3]: https://github.com/pyo3/pyo3/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/pyo3/pyo3/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/pyo3/pyo3/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/pyo3/pyo3/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/pyo3/pyo3/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/pyo3/pyo3/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/pyo3/pyo3/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/pyo3/pyo3/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/pyo3/pyo3/compare/v0.2.7...v0.3.0 [0.2.7]: https://github.com/pyo3/pyo3/compare/v0.2.6...v0.2.7 [0.2.6]: https://github.com/pyo3/pyo3/compare/v0.2.5...v0.2.6 [0.2.5]: https://github.com/pyo3/pyo3/compare/v0.2.4...v0.2.5 [0.2.4]: https://github.com/pyo3/pyo3/compare/v0.2.3...v0.2.4 [0.2.3]: https://github.com/pyo3/pyo3/compare/v0.2.2...v0.2.3 [0.2.2]: https://github.com/pyo3/pyo3/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/pyo3/pyo3/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/pyo3/pyo3/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/PyO3/pyo3/tree/0.1.0 pyo3-0.27.2/CITATION.cff000064400000000000000000000004431046102023000125010ustar 00000000000000cff-version: 1.2.0 title: PyO3 message: >- If you use this software as part of a publication and wish to cite it, please use the metadata from this file. type: software authors: - name: PyO3 Project and Contributors website: https://github.com/PyO3 license: - Apache-2.0 - MIT pyo3-0.27.2/Cargo.lock0000644000001001250000000000100077700ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anyhow" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert_approx_eq" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c07dab4369547dbe5114677b33fbbf724971019f3818172d59a97a61c774ffd" [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bigdecimal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "560f42649de9fa436b73517378a147ec21f6c997a546581df4b4b31677828934" dependencies = [ "autocfg", "libm", "num-bigint", "num-integer", "num-traits", ] [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "chrono-tz" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" dependencies = [ "chrono", "phf", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "deranged" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", ] [[package]] name = "eyre" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "getrandom" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", "wasip2", ] [[package]] name = "glob" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "indenter" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "indoc" version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" dependencies = [ "rustversion", ] [[package]] name = "inventory" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" dependencies = [ "rustversion", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", "windows-sys", ] [[package]] name = "jiff-static" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "jiff-tzdb" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] [[package]] name = "js-sys" version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "lock_api" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "num-bigint" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", ] [[package]] name = "num-complex" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-rational" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ "num-bigint", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "ordered-float" version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" dependencies = [ "num-traits", ] [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-link", ] [[package]] name = "phf" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" dependencies = [ "phf_shared", ] [[package]] name = "phf_shared" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "proc-macro2" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bitflags", "num-traits", "rand", "rand_chacha", "rand_xorshift", "regex-syntax", "unarray", ] [[package]] name = "pyo3" version = "0.27.2" dependencies = [ "anyhow", "assert_approx_eq", "bigdecimal", "bytes", "chrono", "chrono-tz", "either", "eyre", "futures", "hashbrown", "iana-time-zone", "indexmap", "indoc", "inventory", "jiff", "libc", "lock_api", "memoffset", "num-bigint", "num-complex", "num-rational", "num-traits", "once_cell", "ordered-float", "parking_lot", "portable-atomic", "proptest", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "rayon", "rust_decimal", "send_wrapper", "serde", "serde_json", "smallvec", "static_assertions", "tempfile", "time", "trybuild", "unindent", "uuid", ] [[package]] name = "pyo3-build-config" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6" dependencies = [ "python3-dll-a", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn", ] [[package]] name = "pyo3-macros-backend" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9" dependencies = [ "heck", "proc-macro2", "pyo3-build-config", "quote", "syn", ] [[package]] name = "python3-dll-a" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d381ef313ae70b4da5f95f8a4de773c6aa5cd28f73adec4b4a31df70b66780d8" dependencies = [ "cc", ] [[package]] name = "quote" version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom", ] [[package]] name = "rand_xorshift" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ "rand_core", ] [[package]] name = "rayon" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex-syntax" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rust_decimal" version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "num-traits", ] [[package]] name = "rustix" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "send_wrapper" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", "serde_core", ] [[package]] name = "serde_spanned" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" dependencies = [ "serde_core", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" [[package]] name = "target-triple" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" [[package]] name = "tempfile" version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", "getrandom", "once_cell", "rustix", "windows-sys", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "time" version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "num-conv", "powerfmt", "time-core", ] [[package]] name = "time-core" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "toml" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ "indexmap", "serde_core", "serde_spanned", "toml_datetime", "toml_parser", "toml_writer", "winnow", ] [[package]] name = "toml_datetime" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ "serde_core", ] [[package]] name = "toml_parser" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] [[package]] name = "toml_writer" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" [[package]] name = "trybuild" version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335" dependencies = [ "glob", "serde", "serde_derive", "serde_json", "target-triple", "termcolor", "toml", ] [[package]] name = "unarray" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unindent" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "uuid" version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom", "js-sys", "wasm-bindgen", ] [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ "windows-sys", ] [[package]] name = "windows-core" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "winnow" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] name = "wit-bindgen" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "zerocopy" version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" dependencies = [ "proc-macro2", "quote", "syn", ] pyo3-0.27.2/Cargo.toml0000644000000243270000000000100100240ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.74" name = "pyo3" version = "0.27.2" authors = ["PyO3 Project and Contributors "] build = "build.rs" exclude = [ "/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Bindings to Python interpreter" homepage = "https://github.com/pyo3/pyo3" documentation = "https://docs.rs/crate/pyo3/" readme = "README.md" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [package.metadata.docs.rs] no-default-features = true features = ["full"] rustdoc-args = [ "--cfg", "docsrs", ] [features] abi3 = [ "pyo3-build-config/abi3", "pyo3-ffi/abi3", ] abi3-py310 = [ "abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310", ] abi3-py311 = [ "abi3-py312", "pyo3-build-config/abi3-py311", "pyo3-ffi/abi3-py311", ] abi3-py312 = [ "abi3-py313", "pyo3-build-config/abi3-py312", "pyo3-ffi/abi3-py312", ] abi3-py313 = [ "abi3-py314", "pyo3-build-config/abi3-py313", "pyo3-ffi/abi3-py313", ] abi3-py314 = [ "abi3", "pyo3-build-config/abi3-py314", "pyo3-ffi/abi3-py314", ] abi3-py37 = [ "abi3-py38", "pyo3-build-config/abi3-py37", "pyo3-ffi/abi3-py37", ] abi3-py38 = [ "abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38", ] abi3-py39 = [ "abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39", ] arc_lock = [ "lock_api", "lock_api/arc_lock", "parking_lot?/arc_lock", ] auto-initialize = [] bigdecimal = [ "dep:bigdecimal", "num-bigint", ] chrono-local = [ "chrono/clock", "dep:iana-time-zone", ] default = ["macros"] experimental-async = [ "macros", "pyo3-macros/experimental-async", ] experimental-inspect = ["pyo3-macros/experimental-inspect"] extension-module = ["pyo3-ffi/extension-module"] full = [ "macros", "anyhow", "arc_lock", "bigdecimal", "bytes", "chrono", "chrono-local", "chrono-tz", "either", "experimental-async", "experimental-inspect", "eyre", "hashbrown", "indexmap", "jiff-02", "lock_api", "num-bigint", "num-complex", "num-rational", "ordered-float", "parking_lot", "py-clone", "rust_decimal", "serde", "smallvec", "time", "uuid", ] generate-import-lib = ["pyo3-ffi/generate-import-lib"] macros = [ "pyo3-macros", "indoc", "unindent", ] multiple-pymethods = [ "inventory", "pyo3-macros/multiple-pymethods", ] nightly = [] num-bigint = [ "dep:num-bigint", "dep:num-traits", ] parking_lot = [ "dep:parking_lot", "lock_api", ] py-clone = [] [lib] name = "pyo3" path = "src/lib.rs" [[test]] name = "test_anyhow" path = "tests/test_anyhow.rs" [[test]] name = "test_append_to_inittab" path = "tests/test_append_to_inittab.rs" [[test]] name = "test_arithmetics" path = "tests/test_arithmetics.rs" [[test]] name = "test_buffer" path = "tests/test_buffer.rs" [[test]] name = "test_buffer_protocol" path = "tests/test_buffer_protocol.rs" [[test]] name = "test_bytes" path = "tests/test_bytes.rs" [[test]] name = "test_class_attributes" path = "tests/test_class_attributes.rs" [[test]] name = "test_class_basics" path = "tests/test_class_basics.rs" [[test]] name = "test_class_comparisons" path = "tests/test_class_comparisons.rs" [[test]] name = "test_class_conversion" path = "tests/test_class_conversion.rs" [[test]] name = "test_class_formatting" path = "tests/test_class_formatting.rs" [[test]] name = "test_class_new" path = "tests/test_class_new.rs" [[test]] name = "test_coroutine" path = "tests/test_coroutine.rs" [[test]] name = "test_datetime" path = "tests/test_datetime.rs" [[test]] name = "test_datetime_import" path = "tests/test_datetime_import.rs" [[test]] name = "test_declarative_module" path = "tests/test_declarative_module.rs" [[test]] name = "test_default_impls" path = "tests/test_default_impls.rs" [[test]] name = "test_enum" path = "tests/test_enum.rs" [[test]] name = "test_exceptions" path = "tests/test_exceptions.rs" [[test]] name = "test_field_cfg" path = "tests/test_field_cfg.rs" [[test]] name = "test_frompy_intopy_roundtrip" path = "tests/test_frompy_intopy_roundtrip.rs" [[test]] name = "test_frompyobject" path = "tests/test_frompyobject.rs" [[test]] name = "test_gc" path = "tests/test_gc.rs" [[test]] name = "test_getter_setter" path = "tests/test_getter_setter.rs" [[test]] name = "test_inheritance" path = "tests/test_inheritance.rs" [[test]] name = "test_intopyobject" path = "tests/test_intopyobject.rs" [[test]] name = "test_macro_docs" path = "tests/test_macro_docs.rs" [[test]] name = "test_macros" path = "tests/test_macros.rs" [[test]] name = "test_mapping" path = "tests/test_mapping.rs" [[test]] name = "test_methods" path = "tests/test_methods.rs" [[test]] name = "test_module" path = "tests/test_module.rs" [[test]] name = "test_multiple_pymethods" path = "tests/test_multiple_pymethods.rs" [[test]] name = "test_proto_methods" path = "tests/test_proto_methods.rs" [[test]] name = "test_pybuffer_drop_without_interpreter" path = "tests/test_pybuffer_drop_without_interpreter.rs" [[test]] name = "test_pyerr_debug_unformattable" path = "tests/test_pyerr_debug_unformattable.rs" [[test]] name = "test_pyfunction" path = "tests/test_pyfunction.rs" [[test]] name = "test_pyself" path = "tests/test_pyself.rs" [[test]] name = "test_sequence" path = "tests/test_sequence.rs" [[test]] name = "test_serde" path = "tests/test_serde.rs" [[test]] name = "test_static_slots" path = "tests/test_static_slots.rs" [[test]] name = "test_string" path = "tests/test_string.rs" [[test]] name = "test_super" path = "tests/test_super.rs" [[test]] name = "test_text_signature" path = "tests/test_text_signature.rs" [[test]] name = "test_variable_arguments" path = "tests/test_variable_arguments.rs" [[test]] name = "test_various" path = "tests/test_various.rs" [dependencies.anyhow] version = "1.0.1" optional = true [dependencies.bigdecimal] version = "0.4.7" optional = true [dependencies.bytes] version = "1.10" optional = true [dependencies.chrono] version = "0.4.25" optional = true default-features = false [dependencies.chrono-tz] version = ">= 0.10, < 0.11" optional = true default-features = false [dependencies.either] version = "1.9" optional = true [dependencies.eyre] version = ">= 0.6.8, < 0.7" optional = true [dependencies.hashbrown] version = ">= 0.15.0, < 0.17" optional = true default-features = false [dependencies.iana-time-zone] version = "0.1" features = ["fallback"] optional = true [dependencies.indexmap] version = ">= 2.5.0, < 3" optional = true [dependencies.indoc] version = "2.0.1" optional = true [dependencies.inventory] version = "0.3.5" optional = true [dependencies.jiff-02] version = "0.2" optional = true package = "jiff" [dependencies.libc] version = "0.2.62" [dependencies.lock_api] version = "0.4" optional = true [dependencies.memoffset] version = "0.9" [dependencies.num-bigint] version = "0.4.4" optional = true [dependencies.num-complex] version = ">= 0.4.6, < 0.5" optional = true [dependencies.num-rational] version = "0.4.1" optional = true [dependencies.num-traits] version = "0.2.16" optional = true [dependencies.once_cell] version = "1.21" [dependencies.ordered-float] version = "5.0.0" optional = true default-features = false [dependencies.parking_lot] version = "0.12" optional = true [dependencies.pyo3-ffi] version = "=0.27.2" [dependencies.pyo3-macros] version = "=0.27.2" optional = true [dependencies.rust_decimal] version = "1.15" optional = true default-features = false [dependencies.serde] version = "1.0" optional = true [dependencies.smallvec] version = "1.0" optional = true [dependencies.time] version = "0.3.38" optional = true default-features = false [dependencies.unindent] version = "0.2.1" optional = true [dependencies.uuid] version = "1.11.0" optional = true [dev-dependencies.assert_approx_eq] version = "1.1.0" [dev-dependencies.chrono] version = "0.4.25" [dev-dependencies.chrono-tz] version = ">= 0.10, < 0.11" [dev-dependencies.futures] version = "0.3.28" [dev-dependencies.parking_lot] version = "0.12.3" features = ["arc_lock"] [dev-dependencies.proptest] version = "1.0" features = ["std"] default-features = false [dev-dependencies.rayon] version = "1.6.1" [dev-dependencies.send_wrapper] version = "0.6" [dev-dependencies.serde] version = "1.0" features = ["derive"] [dev-dependencies.serde_json] version = "1.0.61" [dev-dependencies.static_assertions] version = "1.1.0" [dev-dependencies.tempfile] version = "3.12.0" [dev-dependencies.trybuild] version = ">=1.0.70" [dev-dependencies.uuid] version = "1.10.0" features = ["v4"] [build-dependencies.pyo3-build-config] version = "=0.27.2" features = ["resolve-config"] [target.'cfg(not(target_has_atomic = "64"))'.dependencies.portable-atomic] version = "1.0" [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" undocumented_unsafe_blocks = "allow" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3-0.27.2/Cargo.toml.orig000064400000000000000000000167531046102023000135110ustar 00000000000000[package] name = "pyo3" version = "0.27.2" description = "Bindings to Python interpreter" authors = ["PyO3 Project and Contributors "] readme = "README.md" keywords = ["pyo3", "python", "cpython", "ffi"] homepage = "https://github.com/pyo3/pyo3" repository = "https://github.com/pyo3/pyo3" documentation = "https://docs.rs/crate/pyo3/" categories = ["api-bindings", "development-tools::ffi"] license = "MIT OR Apache-2.0" exclude = [ "/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui", ] edition = "2021" rust-version.workspace = true [dependencies] libc = "0.2.62" memoffset = "0.9" once_cell = "1.21" # ffi bindings to the python interpreter, split into a separate crate so they can be used independently pyo3-ffi = { path = "pyo3-ffi", version = "=0.27.2" } # support crates for macros feature pyo3-macros = { path = "pyo3-macros", version = "=0.27.2", optional = true } indoc = { version = "2.0.1", optional = true } unindent = { version = "0.2.1", optional = true } # support crate for multiple-pymethods feature inventory = { version = "0.3.5", optional = true } # crate integrations that can be added using the eponymous features anyhow = { version = "1.0.1", optional = true } bigdecimal = { version = "0.4.7", optional = true } bytes = { version = "1.10", optional = true } chrono = { version = "0.4.25", default-features = false, optional = true } chrono-tz = { version = ">= 0.10, < 0.11", default-features = false, optional = true } either = { version = "1.9", optional = true } eyre = { version = ">= 0.6.8, < 0.7", optional = true } hashbrown = { version = ">= 0.15.0, < 0.17", optional = true, default-features = false } indexmap = { version = ">= 2.5.0, < 3", optional = true } jiff-02 = { package = "jiff", version = "0.2", optional = true } num-bigint = { version = "0.4.4", optional = true } num-complex = { version = ">= 0.4.6, < 0.5", optional = true } num-rational = { version = "0.4.1", optional = true } num-traits = { version = "0.2.16", optional = true } ordered-float = { version = "5.0.0", default-features = false, optional = true } rust_decimal = { version = "1.15", default-features = false, optional = true } time = { version = "0.3.38", default-features = false, optional = true } serde = { version = "1.0", optional = true } smallvec = { version = "1.0", optional = true } uuid = { version = "1.11.0", optional = true } lock_api = { version = "0.4", optional = true } parking_lot = { version = "0.12", optional = true } iana-time-zone = { version = "0.1", optional = true, features = ["fallback"]} [target.'cfg(not(target_has_atomic = "64"))'.dependencies] portable-atomic = "1.0" [dev-dependencies] assert_approx_eq = "1.1.0" chrono = "0.4.25" chrono-tz = ">= 0.10, < 0.11" # Required for "and $N others" normalization trybuild = ">=1.0.70" proptest = { version = "1.0", default-features = false, features = ["std"] } send_wrapper = "0.6" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.61" rayon = "1.6.1" futures = "0.3.28" tempfile = "3.12.0" static_assertions = "1.1.0" uuid = { version = "1.10.0", features = ["v4"] } parking_lot = { version = "0.12.3", features = ["arc_lock"] } [build-dependencies] pyo3-build-config = { path = "pyo3-build-config", version = "=0.27.2", features = ["resolve-config"] } [features] default = ["macros"] # Enables support for `async fn` for `#[pyfunction]` and `#[pymethods]`. experimental-async = ["macros", "pyo3-macros/experimental-async"] # Enables pyo3::inspect module and additional type information on FromPyObject # and IntoPy traits experimental-inspect = ["pyo3-macros/experimental-inspect"] # Enables macros: #[pyclass], #[pymodule], #[pyfunction] etc. macros = ["pyo3-macros", "indoc", "unindent"] # Enables multiple #[pymethods] per #[pyclass] multiple-pymethods = ["inventory", "pyo3-macros/multiple-pymethods"] # Use this feature when building an extension module. # It tells the linker to keep the python symbols unresolved, # so that the module can also be used with statically linked python interpreters. extension-module = ["pyo3-ffi/extension-module"] # Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more. abi3 = ["pyo3-build-config/abi3", "pyo3-ffi/abi3"] # With abi3, we can manually set the minimum Python version. abi3-py37 = ["abi3-py38", "pyo3-build-config/abi3-py37", "pyo3-ffi/abi3-py37"] abi3-py38 = ["abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38"] abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39"] abi3-py310 = ["abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310"] abi3-py311 = ["abi3-py312", "pyo3-build-config/abi3-py311", "pyo3-ffi/abi3-py311"] abi3-py312 = ["abi3-py313", "pyo3-build-config/abi3-py312", "pyo3-ffi/abi3-py312"] abi3-py313 = ["abi3-py314", "pyo3-build-config/abi3-py313", "pyo3-ffi/abi3-py313"] abi3-py314 = ["abi3", "pyo3-build-config/abi3-py314", "pyo3-ffi/abi3-py314"] # Automatically generates `python3.dll` import libraries for Windows targets. generate-import-lib = ["pyo3-ffi/generate-import-lib"] # Changes `Python::attach` to automatically initialize the Python interpreter if needed. auto-initialize = [] # Enables `Clone`ing references to Python objects `Py` which panics if the # thread is not attached to the Python interpreter. py-clone = [] # Adds `OnceExt` and `MutexExt` implementations to the `parking_lot` types parking_lot = ["dep:parking_lot", "lock_api"] arc_lock = ["lock_api", "lock_api/arc_lock", "parking_lot?/arc_lock"] num-bigint = ["dep:num-bigint", "dep:num-traits"] bigdecimal = ["dep:bigdecimal", "num-bigint"] chrono-local = ["chrono/clock", "dep:iana-time-zone"] # Optimizes PyObject to Vec conversion and so on. nightly = [] # Activates all additional features # This is mostly intended for testing purposes - activating *all* of these isn't particularly useful. full = [ "macros", # "multiple-pymethods", # Not supported by wasm "anyhow", "arc_lock", "bigdecimal", "bytes", "chrono", "chrono-local", "chrono-tz", "either", "experimental-async", "experimental-inspect", "eyre", "hashbrown", "indexmap", "jiff-02", "lock_api", "num-bigint", "num-complex", "num-rational", "ordered-float", "parking_lot", "py-clone", "rust_decimal", "serde", "smallvec", "time", "uuid", ] [workspace] members = [ "pyo3-ffi", "pyo3-build-config", "pyo3-macros", "pyo3-macros-backend", "pyo3-introspection", "pytests", "examples", ] package.rust-version = "1.74" [package.metadata.docs.rs] no-default-features = true features = ["full"] rustdoc-args = ["--cfg", "docsrs"] [workspace.lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" # TODO: make this "warn" # https://github.com/PyO3/pyo3/issues/5487 undocumented_unsafe_blocks = "allow" unnecessary_wraps = "warn" useless_transmute = "warn" used_underscore_binding = "warn" [workspace.lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2018_idioms = { level = "warn", priority = -1 } rust_2021_prelude_collisions = "warn" unused_lifetimes = "warn" unsafe_op_in_unsafe_fn = "warn" [workspace.lints.rustdoc] broken_intra_doc_links = "warn" bare_urls = "warn" [lints] workspace = true pyo3-0.27.2/Code-of-Conduct.md000064400000000000000000000064041046102023000140050ustar 00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq pyo3-0.27.2/Contributing.md000064400000000000000000000341141046102023000136020ustar 00000000000000# Contributing Thank you for your interest in contributing to PyO3! All are welcome - please consider reading our [Code of Conduct](https://github.com/PyO3/pyo3/blob/main/Code-of-Conduct.md) to keep our community positive and inclusive. If you are searching for ideas how to contribute, proceed to the ["Getting started contributing"](#getting-started-contributing) section. If you have found a specific issue to contribute to and need information about the development process, you may find the section ["Writing pull requests"](#writing-pull-requests) helpful. If you want to become familiar with the codebase, see [Architecture.md](https://github.com/PyO3/pyo3/blob/main/Architecture.md). ## Getting started contributing Please join in with any part of PyO3 which interests you. We use GitHub issues to record all bugs and ideas. Feel free to request an issue to be assigned to you if you want to work on it. You can browse the API of the non-public parts of PyO3 [here](https://pyo3.netlify.app/internal/doc/pyo3/index.html). The following sections also contain specific ideas on where to start contributing to PyO3. ## Setting up a development environment To work and develop PyO3, you need Python & Rust installed on your system. * We encourage the use of [rustup](https://rustup.rs/) to be able to select and choose specific toolchains based on the project. * [Pyenv](https://github.com/pyenv/pyenv) is also highly recommended for being able to choose a specific Python version. * [virtualenv](https://virtualenv.pypa.io/en/latest/) can also be used with or without Pyenv to use specific installed Python versions. * [`nox`][nox] is used to automate many of our CI tasks. ### Testing, linting, etc. with nox [`Nox`][nox] is used to automate many of our CI tasks and can be used locally to handle verfication tasks as you code. We recommend running these actions via nox to make use of our prefered configuration options. You can install nox into your global python with pip: `pip install nox` or (recommended) with [`pipx`][pipx] `pip install pipx`, `pipx install nox` The main nox commands we have implemented are: * `nox -s test` will run the full suite of recommended rust and python tests (>10 minutes) * `nox -s test-rust -- skip-full` will run a short suite of rust tests (2-3 minutes) * `nox -s ruff` will check python linting and apply standard formatting rules * `nox -s rustfmt` will check basic rust linting and apply standard formatting rules * `nox -s rumdl` will check the markdown in the guide * `nox -s clippy` will run clippy to make recommendations on rust style * `nox -s bench` will benchmark your rust code * `nox -s codspeed` will run our suite of rust and python performance tests * `nox -s coverage` will analyse test coverage and output `coverage.json` (alternatively: `nox -s coverage lcov` outputs `lcov.info`) * `nox -s check-guide` will use [`lychee`][lychee] to check all the links in the guide and doc comments. Use `nox -l` to list the full set of subcommands you can run. #### UI Tests PyO3 uses [`trybuild`][trybuild] to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality. Because there are several feature combinations for these UI tests, when updating them all (e.g. for a new Rust compiler version) it may be helpful to use the `update-ui-tests` nox session: ```bash nox -s update-ui-tests ``` ## Ways to help ### Help users identify bugs The [PyO3 Discord server](https://discord.gg/33kcChzH7f) is very active with users who are new to PyO3, and often completely new to Rust. Helping them debug is a great way to get experience with the PyO3 codebase. Helping others often reveals bugs, documentation weaknesses, and missing APIs. It's a good idea to open GitHub issues for these immediately so the resolution can be designed and implemented! ### Implement issues ready for development Issues where the solution is clear and work is not in progress use the [needs-implementer](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-implementer) label. Don't be afraid if the solution is not clear to you! The core PyO3 contributors will be happy to mentor you through any questions you have to help you write the solution. ### Help write great docs PyO3 has a user guide (using mdbook) as well as the usual Rust API docs. The aim is for both of these to be detailed, easy to understand, and up-to-date. Pull requests are always welcome to fix typos, change wording, add examples, etc. There are some specific areas of focus where help is currently needed for the documentation: - Issues requesting documentation improvements are tracked with the [documentation](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) label. - Not all APIs had docs or examples when they were made. The goal is to have documentation on all PyO3 APIs ([#306](https://github.com/PyO3/pyo3/issues/306)). If you see an API lacking a doc, please write one and open a PR! To build the docs (including all features), install [`nox`][nox] and then run ```shell nox -s docs -- open ``` #### Doctests We use lots of code blocks in our docs. Run `cargo test --doc` when making changes to check that the doctests still work, or `cargo test` to run all the Rust tests including doctests. See https://doc.rust-lang.org/rustdoc/documentation-tests.html for a guide on doctests. #### Building the guide You can preview the user guide by building it locally with `mdbook`. First, install [`mdbook`][mdbook], the [`mdbook-tabs`][mdbook-tabs] plugin and [`nox`][nox]. Then, run ```shell nox -s build-guide -- --open ``` To check all links in the guide are valid, also install [`lychee`][lychee] and use the `check-guide` session instead: ```shell nox -s check-guide ``` ### Help design the next PyO3 Issues which don't yet have a clear solution use the [needs-design](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-design) label. If any of these issues interest you, please join in with the conversation on the issue! All opinions are valued, and if you're interested in going further with e.g. draft PRs to experiment with API designs, even better! ### Review pull requests Everybody is welcome to submit comments on open PRs. Please help ensure new PyO3 APIs are safe, performant, tidy, and easy to use! ## Writing pull requests Here are a few things to note when you are writing PRs. ### Testing and Continuous Integration The PyO3 repo uses GitHub Actions. PRs are blocked from merging if CI is not successful. Formatting, linting and tests are checked for all Rust and Python code (the pipeline will abort early if formatting fails to save resources). In addition, all warnings in Rust code are disallowed (using `RUSTFLAGS="-D warnings"`). Tests run with all supported Python versions with the latest stable Rust compiler, as well as for Python 3.9 with the minimum supported Rust version. If you are adding a new feature, you should add it to the `full` feature in our *Cargo.toml** so that it is tested in CI. You can run the CI pipeline components yourself with `nox`, see [the testing section above](#testing-linting-etc-with-nox). ### Documenting changes We use [towncrier](https://towncrier.readthedocs.io/en/stable/index.html) to generate a CHANGELOG for each release. To include your changes in the release notes, you should create one (or more) news items in the `newsfragments` directory. Valid news items should be saved as `..md` where `` is the pull request number and `` is one of the following: - `packaging` - for dependency changes and Python / Rust version compatibility changes - `added` - for new features - `changed` - for features which already existed but have been altered or deprecated - `removed` - for features which have been removed - `fixed` - for "changed" features which were classed as a bugfix Docs-only PRs do not need news items; start your PR title with `docs:` to skip the check. ### Style guide #### Generic code PyO3 has a lot of generic APIs to increase usability. These can come at the cost of generic code bloat. Where reasonable, try to implement a concrete sub-portion of generic functions. There are two forms of this: - If the concrete sub-portion doesn't benefit from re-use by other functions, name it `inner` and keep it as a local to the function. - If the concrete sub-portion is re-used by other functions, preferably name it `_foo` and place it directly below `foo` in the source code (where `foo` is the original generic function). #### FFI calls PyO3 makes a lot of FFI calls to Python's C API using raw pointers. Where possible try to avoid using pointers-to-temporaries in expressions: ```rust // dangerous pyo3::ffi::Something(name.to_object(py).as_ptr()); // because the following refactoring is a use-after-free error: let name = name.to_object(py).as_ptr(); pyo3::ffi::Something(name) ``` Instead, prefer to bind the safe owned `PyObject` wrapper before passing to ffi functions: ```rust let name: PyObject = name.to_object(py); pyo3::ffi::Something(name.as_ptr()) // name will automatically be freed when it falls out of scope ``` ## Python and Rust version support policy PyO3 aims to keep sufficient compatibility to make packaging Python extensions built with PyO3 feasible on most common package managers. To keep package maintainers' lives simpler, PyO3 will commit, wherever possible, to only adjust minimum supported Rust and Python versions at the same time. This bump will only come in an `0.x` release, roughly once per year, after the oldest supported Python version reaches its end-of-life. (Check https://endoflife.date/python for a clear timetable on these.) Below are guidelines on what compatibility all PRs are expected to deliver for each language. ### Python PyO3 supports all officially supported Python versions, as well as the latest PyPy3 release. All of these versions are tested in CI. #### Adding support for new CPython versions If you plan to add support for a pre-release version of CPython, here's a (non-exhaustive) checklist: - [ ] Wait until the last alpha release (usually alpha7), since ABI is not guaranteed until the first beta release - [ ] Add prerelease_ver-dev (e.g. `3.14-dev`) to `.github/workflows/ci.yml`, and bump version in `noxfile.py`, `pyo3-ffi/Cargo.toml` under `max-version` within `[package.metadata.cpython]`, and `max` within `pyo3-ffi/build.rs` - [ ] Add a new abi3-prerelease feature for the version (e.g. `abi3-py314`) - In `pyo3-build-config/Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease"] and abi3-prerelease to ["abi3"] - In `pyo3-ffi/Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease", "pyo3-build-config/abi3-most_current_stable"] and abi3-prerelease to ["abi3", "pyo3-build-config/abi3-prerelease"] - In `Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease", "pyo3-ffi/abi3-most_current_stable"] and abi3-prerelease to ["abi3", "pyo3-ffi/abi3-prerelease"] - [ ] Use `#[cfg(Py_prerelease])` (e.g. `#[cfg(Py_3_14)]`) and `#[cfg(not(Py_prerelease]))` to indicate changes between the stable branches of CPython and the pre-release - [ ] Do not add a Rust binding to any function, struct, or global variable prefixed with `_` in CPython's headers - [ ] Ping @ngoldbaum and @davidhewitt for assistance ### Rust PyO3 aims to make use of up-to-date Rust language features to keep the implementation as efficient as possible. The minimum Rust version supported will be decided when the release which bumps Python and Rust versions is made. At the time, the minimum Rust version will be set no higher than the lowest Rust version shipped in the current Debian, RHEL and Alpine Linux distributions. CI tests both the most recent stable Rust version and the minimum supported Rust version. Because of Rust's stability guarantees this is sufficient to confirm support for all Rust versions in between. ## Benchmarking PyO3 has two sets of benchmarks for evaluating some aspects of its performance. The benchmark suite is currently very small - please open PRs with new benchmarks if you're interested in helping to expand it! First, there are Rust-based benchmarks located in the `pyo3-benches` subdirectory. You can run these benchmarks with: nox -s bench Second, there is a Python-based benchmark contained in the `pytests` subdirectory. You can read more about it [here](https://github.com/PyO3/pyo3/tree/main/pytests). ## Code coverage You can view what code is and isn't covered by PyO3's tests. We aim to have 100% coverage - please check coverage and add tests if you notice a lack of coverage! - First, ensure the llvm-cov cargo plugin is installed. You may need to run the plugin through cargo once before using it with `nox`. ```shell cargo install cargo-llvm-cov cargo llvm-cov ``` - Then, generate an `lcov.info` file with ```shell nox -s coverage -- lcov ``` You can install an IDE plugin to view the coverage. For example, if you use VSCode: - Add the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) plugin. - Add these settings to VSCode's `settings.json`: ```json { "coverage-gutters.coverageFileNames": [ "lcov.info", "cov.xml", "coverage.xml", ], "coverage-gutters.showLineCoverage": true } ``` - You should now be able to see green highlights for code that is tested, and red highlights for code that is not tested. ## Sponsor this project At the moment there is no official organisation that accepts sponsorship on PyO3's behalf. If you're seeking to provide significant funding to the PyO3 ecosystem, please reach out to us on [GitHub](https://github.com/PyO3/pyo3/issues/new) or [Discord](https://discord.gg/33kcChzH7f) and we can discuss. In the meanwhile, some of our maintainers have personal GitHub sponsorship pages and would be grateful for your support: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) [mdbook]: https://rust-lang.github.io/mdBook/cli/index.html [mdbook-tabs]: https://mdbook-plugins.rustforweb.org/tabs.html [lychee]: https://github.com/lycheeverse/lychee [nox]: https://github.com/theacodes/nox [pipx]: https://pipx.pypa.io/stable/ [trybuild]: https://github.com/dtolnay/trybuild pyo3-0.27.2/LICENSE-APACHE000064400000000000000000000231171046102023000125360ustar 00000000000000Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS pyo3-0.27.2/LICENSE-MIT000064400000000000000000000021231046102023000122400ustar 00000000000000Copyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-0.27.2/README.md000064400000000000000000000451621046102023000120750ustar 00000000000000# PyO3 [![actions status](https://img.shields.io/github/actions/workflow/status/PyO3/pyo3/ci.yml?branch=main&logo=github&style=)](https://github.com/PyO3/pyo3/actions) [![benchmark](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/PyO3/pyo3) [![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3) [![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3) [![minimum rustc 1.74](https://img.shields.io/badge/rustc-1.74+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f) [![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md) [Rust](https://www.rust-lang.org/) bindings for [Python](https://www.python.org/), including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported. - User Guide: [stable](https://pyo3.rs) | [main](https://pyo3.rs/main) - API Documentation: [stable](https://docs.rs/pyo3/) | [main](https://pyo3.rs/main/doc) ## Usage Requires Rust 1.74 or greater. PyO3 supports the following Python distributions: - CPython 3.7 or greater - PyPy 7.3 (Python 3.11+) - GraalPy 24.2 or greater (Python 3.11+) You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn. ### Using Rust from Python PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`](https://github.com/PyO3/maturin). `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps install `maturin`, use it to generate and build a new Python package, and then launch Python to import and execute a function from the package. First, follow the commands below to create a new directory containing a new Python `virtualenv`, and install `maturin` into the virtualenv using Python's package manager, `pip`: ```bash # (replace string_sum with the desired package name) $ mkdir string_sum $ cd string_sum $ python -m venv .env $ source .env/bin/activate $ pip install maturin ``` Still inside this `string_sum` directory, now run `maturin init`. This will generate the new package source. When given the choice of bindings to use, select pyo3 bindings: ```bash $ maturin init ✔ 🤷 What kind of bindings to use? · pyo3 ✨ Done! New project created string_sum ``` The most important files generated by this command are `Cargo.toml` and `lib.rs`, which will look roughly like the following: **`Cargo.toml`** ```toml [package] name = "string_sum" version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "string_sum" # "cdylib" is necessary to produce a shared library for Python to import from. # # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.27.2", features = ["extension-module"] } ``` **`src/lib.rs`** ```rust /// A Python module implemented in Rust. The name of this module must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pyo3::pymodule] mod string_sum { use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } } ``` Finally, run `maturin develop`. This will build the package and install it into the Python virtualenv previously created and activated. The package is then ready to be used from `python`: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25' ``` To make changes to the package, just edit the Rust source code and then re-run `maturin develop` to recompile. To run this all as a single copy-and-paste, use the bash script below (replace `string_sum` in the first command with the desired package name): ```bash mkdir string_sum && cd "$_" python -m venv .env source .env/bin/activate pip install maturin maturin init --bindings pyo3 maturin develop ``` If you want to be able to run `cargo test` or use this project in a Cargo workspace and are running into linker issues, there are some workarounds in [the FAQ](https://pyo3.rs/latest/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror). As well as with `maturin`, it is possible to build using [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](https://pyo3.rs/latest/building-and-distribution.html#manual-builds). Both offer more flexibility than `maturin` but require more configuration to get started. ### Using Python from Rust To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter. To install the Python shared library on Ubuntu: ```bash sudo apt install python3-dev ``` To install the Python shared library on RPM based distributions (e.g. Fedora, Red Hat, SuSE), install the `python3-devel` package. Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like this: ```toml [dependencies.pyo3] version = "0.27.2" features = ["auto-initialize"] ``` Example program displaying the value of `sys.version` and the current user name: ```rust use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::ffi::c_str; fn main() -> PyResult<()> { Python::attach(|py| { let sys = py.import("sys")?; let version: String = sys.getattr("version")?.extract()?; let locals = [("os", py.import("os")?)].into_py_dict(py)?; let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"); let user: String = py.eval(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) }) } ``` The guide has [a section](https://pyo3.rs/latest/python-from-rust.html) with lots of examples about this topic. ## Tools and libraries - [maturin](https://github.com/PyO3/maturin) _Build and publish crates with pyo3, rust-cpython or cffi bindings as well as rust binaries as python packages_ - [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_. - [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://docs.rs/pyo3/*/pyo3/types/struct.PyDict.html)_ - [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_ - [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_ - [pyo3-log](https://github.com/vorner/pyo3-log) _Bridge from Rust to Python logging_ - [pythonize](https://github.com/davidhewitt/pythonize) _Serde serializer for converting Rust objects to JSON-compatible Python objects_ - [pyo3-async-runtimes](https://github.com/PyO3/pyo3-async-runtimes) _Utilities for interoperability with Python's Asyncio library and Rust's async runtimes._ - [rustimport](https://github.com/mityax/rustimport) _Directly import Rust files or crates from Python, without manual compilation step. Provides pyo3 integration by default and generates pyo3 binding code automatically._ - [pyo3-arrow](https://crates.io/crates/pyo3-arrow) _Lightweight [Apache Arrow](https://arrow.apache.org/) integration for pyo3._ - [pyo3-bytes](https://crates.io/crates/pyo3-bytes) _Integration between [`bytes`](https://crates.io/crates/bytes) and pyo3._ - [pyo3-object_store](https://github.com/developmentseed/obstore/tree/main/pyo3-object_store) _Integration between [`object_store`](https://docs.rs/object_store) and [`pyo3`](https://github.com/PyO3/pyo3)._ ## Examples - [arro3](https://github.com/kylebarron/arro3) _A minimal Python library for Apache Arrow, connecting to the Rust arrow crate._ - [arro3-compute](https://github.com/kylebarron/arro3/tree/main/arro3-compute) _`arro3-compute`_ - [arro3-core](https://github.com/kylebarron/arro3/tree/main/arro3-core) _`arro3-core`_ - [arro3-io](https://github.com/kylebarron/arro3/tree/main/arro3-io) _`arro3-io`_ - [bed-reader](https://github.com/fastlmm/bed-reader) _Read and write the PLINK BED format, simply and efficiently._ - Shows Rayon/ndarray::parallel (including capturing errors, controlling thread num), Python types to Rust generics, Github Actions - [blake3-py](https://github.com/oconnor663/blake3-py) _Python bindings for the [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) cryptographic hash function._ - Parallelized [builds](https://github.com/oconnor663/blake3-py/blob/master/.github/workflows/dists.yml) on GitHub Actions for MacOS, Linux, Windows, including free-threaded 3.13t wheels. - [cellular_raza](https://cellular-raza.com) _A cellular agent-based simulation framework for building complex models from a clean slate._ - [connector-x](https://github.com/sfu-db/connector-x/tree/main/connectorx-python) _Fastest library to load data from DB to DataFrames in Rust and Python._ - [cryptography](https://github.com/pyca/cryptography/tree/main/src/rust) _Python cryptography library with some functionality in Rust._ - [css-inline](https://github.com/Stranger6667/css-inline/tree/master/bindings/python) _CSS inlining for Python implemented in Rust._ - [datafusion-python](https://github.com/apache/arrow-datafusion-python) _A Python library that binds to Apache Arrow in-memory query engine DataFusion._ - [deltalake-python](https://github.com/delta-io/delta-rs/tree/main/python) _Native Delta Lake Python binding based on delta-rs with Pandas integration._ - [fastbloom](https://github.com/yankun1992/fastbloom) _A fast [bloom filter](https://github.com/yankun1992/fastbloom#BloomFilter) | [counting bloom filter](https://github.com/yankun1992/fastbloom#countingbloomfilter) implemented by Rust for Rust and Python!_ - [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library._ - [feos](https://github.com/feos-org/feos) _Lightning fast thermodynamic modeling in Rust with fully developed Python interface._ - [finalytics](https://github.com/Nnamdi-sys/finalytics) _Investment Analysis library in Rust | Python._ - [forust](https://github.com/jinlow/forust) _A lightweight gradient boosted decision tree library written in Rust._ - [geo-index](https://github.com/kylebarron/geo-index) _A Rust crate and [Python library](https://github.com/kylebarron/geo-index/tree/main/python) for packed, immutable, zero-copy spatial indexes._ - [granian](https://github.com/emmett-framework/granian) _A Rust HTTP server for Python applications._ - [haem](https://github.com/BooleanCat/haem) _A Python library for working on Bioinformatics problems._ - [html2text-rs](https://github.com/deedy5/html2text_rs) _Python library for converting HTML to markup or plain text._ - [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/main/examples/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._ - [hudi-rs](https://github.com/apache/hudi-rs) _The native Rust implementation for Apache Hudi, with C++ & Python API bindings._ - [inline-python](https://github.com/m-ou-se/inline-python) _Inline Python code directly in your Rust code._ - [johnnycanencrypt](https://github.com/kushaldas/johnnycanencrypt) OpenPGP library with Yubikey support. - [jsonschema](https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-py) _A high-performance JSON Schema validator for Python._ - [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere._ - [obstore](https://github.com/developmentseed/obstore) _The simplest, highest-throughput Python interface to Amazon S3, Google Cloud Storage, Azure Storage, & other S3-compliant APIs, powered by Rust._ - [opendal](https://github.com/apache/opendal/tree/main/bindings/python) _A data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way._ - [orjson](https://github.com/ijl/orjson) _Fast Python JSON library._ - [ormsgpack](https://github.com/aviramha/ormsgpack) _Fast Python msgpack library._ - [polars](https://github.com/pola-rs/polars) _Fast multi-threaded DataFrame library in Rust | Python | Node.js._ - [pycrdt](https://github.com/jupyter-server/pycrdt) _Python bindings for the Rust CRDT implementation [Yrs](https://github.com/y-crdt/y-crdt)._ - [pydantic-core](https://github.com/pydantic/pydantic-core) _Core validation logic for pydantic written in Rust._ - [primp](https://github.com/deedy5/primp) _The fastest python HTTP client that can impersonate web browsers by mimicking their headers and TLS/JA3/JA4/HTTP2 fingerprints._ - [radiate](https://github.com/pkalivas/radiate): _A high-performance evolution engine for genetic programming and evolutionary algorithms._ - [rateslib](https://github.com/attack68/rateslib) _A fixed income library for Python using Rust extensions._ - [river](https://github.com/online-ml/river) _Online machine learning in python, the computationally heavy statistics algorithms are implemented in Rust._ - [robyn](https://github.com/sparckles/Robyn) A Super Fast Async Python Web Framework with a Rust runtime. - [rust-python-coverage](https://github.com/cjermain/rust-python-coverage) _Example PyO3 project with automated test coverage for Rust and Python._ - [rnet](https://github.com/0x676e67/rnet) Asynchronous Python HTTP Client with Black Magic - [sail](https://github.com/lakehq/sail) _Unifying stream, batch, and AI workloads with Apache Spark compatibility._ - [tiktoken](https://github.com/openai/tiktoken) _A fast BPE tokeniser for use with OpenAI's models._ - [tokenizers](https://github.com/huggingface/tokenizers/tree/main/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust._ - [tzfpy](http://github.com/ringsaturn/tzfpy) _A fast package to convert longitude/latitude to timezone name._ - [utiles](https://github.com/jessekrubin/utiles) _Fast Python web-map tile utilities_ ## Articles and other media - [(Video) Using Rust in Free-Threaded vs Regular Python 3.13](https://www.youtube.com/watch?v=J7phN_M4GLM) - Jun 4, 2025 - [(Video) Techniques learned from five years finding the way for Rust in Python](https://www.youtube.com/watch?v=KTQn_PTHNCw) - Feb 26, 2025 - [(Podcast) Bridging Python and Rust: An Interview with PyO3 Maintainer David Hewitt](https://www.youtube.com/watch?v=P47JUMSQagU) - Aug 30, 2024 - [(Video) PyO3: From Python to Rust and Back Again](https://www.youtube.com/watch?v=UmL_CA-v3O8) - Jul 3, 2024 - [Parsing Python ASTs 20x Faster with Rust](https://www.gauge.sh/blog/parsing-python-asts-20x-faster-with-rust) - Jun 17, 2024 - [(Video) How Python Harnesses Rust through PyO3](https://www.youtube.com/watch?v=UilujdubqVU) - May 18, 2024 - [(Video) Combining Rust and Python: The Best of Both Worlds?](https://www.youtube.com/watch?v=lyG6AKzu4ew) - Mar 1, 2024 - [(Video) Extending Python with Rust using PyO3](https://www.youtube.com/watch?v=T45ZEmSR1-s) - Dec 16, 2023 - [A Week of PyO3 + rust-numpy (How to Speed Up Your Data Pipeline X Times)](https://terencezl.github.io/blog/2023/06/06/a-week-of-pyo3-rust-numpy/) - Jun 6, 2023 - [(Podcast) PyO3 with David Hewitt](https://rustacean-station.org/episode/david-hewitt/) - May 19, 2023 - [Making Python 100x faster with less than 100 lines of Rust](https://ohadravid.github.io/posts/2023-03-rusty-python/) - Mar 28, 2023 - [How Pydantic V2 leverages Rust's Superpowers](https://fosdem.org/2023/schedule/event/rust_how_pydantic_v2_leverages_rusts_superpowers/) - Feb 4, 2023 - [How we extended the River stats module with Rust using PyO3](https://boring-guy.sh/posts/river-rust/) - Dec 23, 2022 - [Nine Rules for Writing Python Extensions in Rust](https://towardsdatascience.com/nine-rules-for-writing-python-extensions-in-rust-d35ea3a4ec29?sk=f8d808d5f414154fdb811e4137011437) - Dec 31, 2021 - [Calling Rust from Python using PyO3](https://saidvandeklundert.net/learn/2021-11-18-calling-rust-from-python-using-pyo3/) - Nov 18, 2021 - [davidhewitt's 2021 talk at Rust Manchester meetup](https://www.youtube.com/watch?v=-XyWG_klSAw&t=320s) - Aug 19, 2021 - [Incrementally porting a small Python project to Rust](https://blog.waleedkhan.name/port-python-to-rust/) - Apr 29, 2021 - [Vortexa - Integrating Rust into Python](https://www.vortexa.com/blog/integrating-rust-into-python) - Apr 12, 2021 - [Writing and publishing a Python module in Rust](https://blog.yossarian.net/2020/08/02/Writing-and-publishing-a-python-module-in-rust) - Aug 2, 2020 ## Contributing Everyone is welcomed to contribute to PyO3! There are many ways to support the project, such as: - help PyO3 users with issues on GitHub and [Discord](https://discord.gg/33kcChzH7f) - improve documentation - write features and bugfixes - publish blogs and examples of how to use PyO3 Our [contributing notes](https://github.com/PyO3/pyo3/blob/main/Contributing.md) and [architecture guide](https://github.com/PyO3/pyo3/blob/main/Architecture.md) have more resources if you wish to volunteer time for PyO3 and are searching where to start. If you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have GitHub sponsorship pages: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) ## License PyO3 is licensed under the [Apache-2.0 license](LICENSE-APACHE) or the [MIT license](LICENSE-MIT), at your option. Python is licensed under the [Python License](https://docs.python.org/3/license.html). Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in PyO3 by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions. Deploys by Netlify pyo3-0.27.2/Releasing.md000064400000000000000000000066121046102023000130460ustar 00000000000000# Releasing This is notes for the current process of releasing a new PyO3 version. Replace `` in all instructions below with the new version. ## 1. Prepare the release commit Follow the process below to update all required pieces to bump the version. All these changes are done in a single commit because it makes it clear to git readers what happened to bump the version. It also makes it easy to cherry-pick the version bump onto the `main` branch when tidying up branch history at the end of the release process. 1. Replace all instances of the PyO3 current version and the with the new version to be released. Places to check: - `Cargo.toml` for all PyO3 crates in the repository. - Examples in `README.md` - PyO3 version embedded into documentation like the README. - `pre-script.rhai` templates for the examples. - `[towncrier]` section in `pyproject.toml`. Some of the above locations may already have the new version with a `-dev` suffix, which needs to be removed. **Make sure not to modify the CHANGELOG during this step!** 2. Run `towncrier build` to generate the CHANGELOG. The version used by `towncrier` should automatically be correct because of the update to `pyproject.toml` in step 1. 3. Manually edit the CHANGELOG for final notes. Steps to do: - Adjust wording of any release lines to make them clearer for users / fix typos. - Add a new link at the bottom for the new version, and update the `Unreleased` link. 4. Create the commit containing all the above changes, with a message of `release: `. Push to `release-` branch on the main PyO3 repository, where `` depends on whether this is a major or minor release: - for O.X.0 minor releases, just use `0.X`, e.g. `release-0.17`. This will become the maintenance branch after release. - for 0.X.Y patch releases, use the full `0.X.Y`, e.g. `release-0.17.1`. This will be deleted after merge. ## 2. Create the release PR and draft release notes Open a PR for the branch, and confirm that it passes CI. For `0.X.0` minor releases, the PR should be merging into `main`, for `0.X.Y` patch releases, the PR should be merging the `release-0.X` maintenance branch. On https://github.com/PyO3/pyo3/releases, click "Draft a new release". The tag will be a new tag of `v` (note preceding `v`) and target should be the `release-` branch you just pushed. Write release notes which match the style of previous releases. You can get the list of contributors by running `nox -s contributors -- v release-` to get contributors from the previous version tag through to the branch tip you just pushed. (This uses the GitHub API, so you'll need to push the branch first.) Save as a draft and wait for now. ## 3. Leave for a cooling off period Wait a couple of days in case anyone wants to hold up the release to add bugfixes etc. ## 4. Put live To put live: - 1. merge the release PR - 2. publish a release on GitHub targeting the release branch CI will automatically push to `crates.io`. ## 5. Tidy the main branch If the release PR targeted a branch other than main, you will need to cherry-pick the version bumps, CHANGELOG modifications and removal of towncrier `newsfragments` and open another PR to land these on main. ## 6. Delete the release branch (patch releases only) For 0.X.Y patch releases, the release branch is no longer needed, so it should be deleted. pyo3-0.27.2/assets/script.py000064400000000000000000000000641046102023000137660ustar 00000000000000# Used in PyModule examples. class Blah: pass pyo3-0.27.2/branding/favicon/pyo3_16x16.png000064400000000000000000000007101046102023000162620ustar 00000000000000PNG  IHDRasRGBDeXIfMM*i4Uq2IDAT8uR1n@\# .M)"< ҤNy@|* .PHYJgf.+K}aku[!*g. E0pqȻoLRܛ $+[F @E|L (qÙ ģ&5b%J –? 3J!ro&@:fЀgE#_UνxHP oA46@Vݯ>ݺ߯_]'$%v'MSf('7,3JyTS oiKJD0(* &4q7?oE3N8c^S<988.7GQ%DT-ŭ8pC5s$ˋ$֋w40f?4л!3i݁Y`*l$4c/뛻*Ey;C |k<:U$/ bd0 x FN$ iKU"\A)H+ Aas|R: ɘ{hced ĤpXPbdaRZnJ OyhGSS$yR/`[IENDB`pyo3-0.27.2/branding/pyo3logo.png000064400000000000000000012477631046102023000146770ustar 00000000000000PNG  IHDR팥 pHYs.#.#x?v IDATx 02޿Ġ4)<3.OCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8z1 G"o..] ^Ce R(RdxK%("EJtT@u:9K* E^;% {j~sm$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBPKG IDAT A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$֬Wbf؟onwcm}?e8sZgj87mto{^|õ[#/K'qT=X4+?d/Vnbm}~6 TL$"8w7ڍLx24ժƱ՘=z%fk_/+wv7nXLD{v؆nk;}t?>/ARhύhύ>utbnލ;c3Z]z | SXLıV؏nmcs׳aXLqV8^+={Yz^|_z D H7mtG2-̏hWJOy"[;ݸ潸`Fcd7= ˼祧ؙåg\㕸g3Z3¹͘ @ߝ;݌hEkUR hr+g }լWb31hvHsz% -gN֣=7Q-zOPzh{L8{^zIc {X }3ժƙ"*~HLJπXJXhύ@B2QreՊHg˞-'jܚ+n=uZ-: Cc{s*u#Ơ VKkKYl,g3Dcm=)2rՊȕz[Ȯ^nx?#<|dꄡq?x ͩ3(fE2􌓨UgldBϤ΀ciJqiLꌡV3&@O8@_=\M0tJq[OGR ^{Z)d FA(R:c(/eώޜRꌑVZc|NI4fc:a]٩Ge,j-uȨV  92֚:ܟf:~G-+N=uY_<82rՊNZ)ˍe,ɗz>gR'0Ĝ:/&S'RLI5,RtY(ћ>W_ oqu r`;{G#nJ!ug{`]8Vk3~:n;+OUPFo~~;=o7_E|}cM 2rWv3;=$nݾ:!ҝ3y'{:*dt'2\77ߏa6ANƋb~:_7Ww~o0u Cḱ 7ן+uMgۛSY('{ߺx^KJexdr\~&uon_ۻ:!su38?ݼw=H=zH淽ֵŷv8?VGr5u|w"7Rg0D63c2Cn=uL-+սF\~&7c2J!֌b~<^VRG0|b\1hgrܽ nݾ:k6ˍ8Uz,u Gl7>NYNL̷JS>S-+r5lw: >W!uic:#xts|I|[jf{s*un=^k Dvr\q"ZNB\kD- nkèP6lPeX_R[Rt ל6V|4,fŸHA[%C`:*ō\)uʉ\<umju/uA-+}T4(~&B/u&n=SbLfSȑ'bQL ԲBܽ nݾ:PUyn'?GsW;{-vrtNGbϕkyaĭ7>}Zȗb9??:Go^y7u996ϤΠ{y'u|OdBꔞћ;?wrà cc;+OUb;?z~|wsAOݐ7X_Rgya|u'q)$nΥΠ^i|o΀O5c20*@`5Ÿ6O/g7Ƿx.2rbk{b=GZV/F1u ={ؼqMØ'~Xzǩ3 V{#ڭRŅߋ+;/S{קn%J}wFdt˩38ZVr|wS7+|:u=vXܿN_X?}/R}'/|?u cΠ #(sz:ݿgn*=ŲaFn=jY!u=l]zCrRg'OR;o Y\٩v0?|:1fPVROedqރIH6XΠڭRܽ nݾ:e|(;Uz,ʥB~:17c2Oīo|w=Hzٳ~4C(ƕztʩSon_+~a83C8x/ب׈݉ nމ;,Hdd>qރXcH`t'Ƌj|w"^֌4CUs?Gl;aLfl?3:1eL6@N0j^#vwRZ-u dZ)L `8Y_ʢ(`lՌ 5#$xZKu[33N+<ėNT 3㞏F'R ė?QyoOSq|'ucf~d+c`KYꌞY_Ƌ碖=::Y_bcyt_ZEg:w'=7j{m~s22VJq?V)u ˕lc{s*u O{^X` 047FªQhc9F1uv?GFT+;B9:(c2G7(``(t'}WιpJnl,WS'@RT(#⹋өAdokm2ucj:>OQ'T)ҭdx~:1n{3H>x_o:cjJ3ȉqރu~F@-+ RI2tSǫo|w=H0(@~k&fG_>ėć?J V)u [x罇_)_Qzs=nB[k5P10 8)@.moNNȭ+;8ح`m,WS'SKYlRg[Vdl/Vbku2uC*kךdZ)D2(@tY(ȵ,D-~z*y΢e#c˥3lSgcV)gZ>_oN;[Bg3.S[k|5nLik5Gw }Up&6 p2["sxtꌱlc{s*uCl_?c2Y,N`9 @l,WS' jWv8DRy'+uRfЂ尉1[VR'0œ 7bϕRg Kg`:!l:!tiLt'RgZt prXdR8>r", KYx\2pt z[*޳ө3_clc9+;S2@8I@ntONs9IU΂A]Rݺ!85@omoNN c2T%u#ʉNràEo6q?E| R'ͩ3Fouʱ`䇿/eȅZVF1uȩV qLK>݉ޜJ1:帴y&u#v|ɗF1-CaArESSgC[16Jw"uHe80A61ZVR'0 ݅өFޅZ\kD-Āp[7CۛS1(`moNy0vqiL >SF=ȅb9uX8ߝƉ_B=@gVk3blNΠv뱾d@.J~ s\xUJ06JڵfjF\)5Rg ZV3djF1`\^s 䚍bT+e=HJ!gbcqn2Y(ө3N#Ubku2u=bLfxt+1N\UJ0B\٩Z-u l `0.֌W=DN` mբ( ?zˠ uONk{Nn=uT .3P]6v F2T+~f*u!Sbň=dP e>:[3J!5<ѕzT+Hg})f:ce8ܟB9u &"ɹrYlW3roku{\S IDAT\~f*uɘqj;:bP\ɨ̈XbQL,nb{ӈEgѸ00&3fE2$dT+xsN6sVk_>n=ϘhqGF vT>Õ#*EgEe{A߲9e,c"ɌA꺤k6n=jFdjW[>nSU׮5ɌFz)r 6֗8ܟquղB/e3Wf8ܟI\-+n=u|B9V35V)gZly NLg:#+ōEehXmNN1?W1)jө1ѷҭN`8a@2O'*bJw"u `c9Kj})ۯb9.Rgmq'dC&=ɴ[R'pLJ!^kT>d6mSggSղBSgmoNNkdGRQNI#,(9`°XN/t?l|><ةzb6FeYN3+JF$Q .,5jb5EM j33b;3ضj^lc9d̊Nȉ#hJ݉8ܟq~f*u\)v3F#Z)dꌱŕhQ1(@݅өRx񜑠eXN΀cY_bc9K7WQᵵVZkߌɰp<:HhV q?3#pCN}$_'jY(΀V #͘ 绕 1'HBV qe[k)|dxd3lSgLQͩKH=>Ę ,9qk6Q{v:v]Nm;.3ĪB\Wv^)HVRN,0pV)u}ōύ06:Nl~]NqbۛSY(΀Z_ʼ롃z\X gS'0`ڭSRϸl@Q4^X_bkmxGڭR\<: >n=֗Jw"uCʠ Y4t1.>|J=>S'@tC c2|j1#1(=*N`B\~&6]ZVD 5(8c~km{ӈ٣2&Qt+BevՊoO+;|q:u{z9c$U+zl8;帰ZK}Y(2{d8b9uCh8N[02ڭRZ B oJ SղBSg;ZV/3&Ñϕ(`8 @[R'R3Fe`;.3֗Z\ۛSF16 |ZV3<5:!6n@K\)^c&S'@=;rOҝ ~ޜJkd8 2 Tg! ^ˋ+݉)#(z|1V(U-+n=u$1(֚1OcL:ߝZG Y4voV ^#6)Co 0P/[t`J~z`ж7rc2Jp $dEZ>ݕzSg ZVD Rcc9j[3r(gVN`S0>ڭSȱ,f޽x݇sYT+~|w"u}j|_ۭRx}gp={/R rGoޏ}^ܹ uk͘m9w~v|󅟦HƘ |q c2\)nx.-_/Gҝ0&@\XEsL_O 'b9uCZ)+/,uJ]XLc gL~;G]8:!teۛw!bt\, ֗h63Ƙ 0?WI&*N`H]<ʘ~o,gd΢1AL ANb})/Z棍OԲBt'Rgg,G~bc9+;uc2 J:!D}W 1(`ϕ }uro{s*uB|2&tޠ G1}](N`D6q?E_SV'S',Guۘ ) ڭS!J!??YdV1(#9c2T%u9gP,S'0`w2ݓRFRWQ#f1Cg{s*u‰֍ɐ b 1>H(FDόͨ3!3(r:c}ix=+Jrl`8U+ZLq,dȫR4UUJV qe[k)}qa.oZE- dȻb9u95Zg`:V1(V ZV0&PXVR'Sev:1eqȅ|_y&:e8ܟ1&P8ߝH@N1AR,p&[q9(Fg!Q\~&""~u~q_|w=Hɘ D|Ax:u\)g;?QgR'@_ϕ~5r)DD;=ˡ[?;īc2 i2Ξ=QFӍϹK[WMq,]kFRHIqĭ[><ט 'wRg3eS'ގoGVgSg@.ݽ {Aܺaܺ}?{p_oLQ|qH1uXNj-&B~o0u::rkQF1: ߾#3V)vdzŲA~AɖRV)\lb8jDD֣Z)ʄXƷv r䱳g~:su3sݽ w/nݾ:%ڭR[.vsF8/J`HK2A6q?_x}b[|<Y(`t'{:xٳ`ԲB0u˟՗KV) .Z)`|k{Rgv:N=ϿuOUx82sWw:1(@uNNGERoHX,V)B+7U+XN7O@ڭRxdq?_潸sofr[X9_CgA""ⱳg~:_QRgoEb[Pن~'wRgN=SFј #Z)K{p$b4ŸsAsjJS2Tu*uX:߭N  SrY(G-s`9A@Ou ҝH@b0jY!ڭgW_`55 @uO^y7u ,p:ڭR4(G7^}ヸ{Aܺa|u~Kd ҝH@bejY!^΢p:Ο"WgKYDDxq_7ߏ}x^vTVXW_ u  7D!&J):xc{wSϡOЛ:;8~pt b2U)8ҶhSϡ4S> Ap<J=#Bc .LOV| LM|02ӓ8ЩZb6׈DQ"_nzrc |]rpùJr8oO'Wcc!vSϡ>3o6 qxr)7ccŸJ):x}~9d!x=sػzkl֭[o5xmzF8}/]gsl7ǛSO` R^0p },8~h4|9$Ԛ)=j5by@ 0|QN=/Q/ݺV-{8'7}:Щ1Xq7 *\⍹F)3h' 'Zb|i[j*ٰu֛G@*r.G)o_|8}z wnO=UㅹKgr@JYN=!s& 1d,揎EO=54=YH=UtScQ-;RϜ`۽9j5\#?"ZFg'Zb|q(@s5=Yz>۷o5b3z lzrc z>^9:CpeXڥFZ>p-Cz쪔rػz h֭[o)|i[LMbpl7^tSO'~xr)ˑwS.RTdi51d,F=z5SL=ugG9jQ#~I 7Q/mΰKi}IA&AgG9^9:;@pnnJ=UJ8Щsػzw{`LMDe Ɩ| |AcGKۢ5SL=1=YH=& qm>0Ax]PWMMbXT-| z>^9:&*УeHOZb6׈DQf/qaJ)'*У` UJ}\#f;évsS Q *\Fj3Z32GP||p=揎$K| @oNY#cqh4sJJɣe>OTw8=ˊ=;qm1N\ ˈ7,8.5eKZ1׈;˩d^kfS 0QeLrqh|i[fd |QeL(?:z>i5zzR.^>\j$If1^kG\^[%~<bW\Μ2mj1׈p)}OP{55QW0Pe̫rqS=zNߚܘz}hj00e1^cXfgܧ=;1N=` ,8~h4|9}cjz}@Cgd 0(ɗlg8eKJkzphLO %7$V)@o5br9= XR.vXCNfĭ mɗEkzNϙܘz15QI= e>cjGbX4szF)ٳ{wS$A;h5\#?`?Js1.*1W50ط ƾxcS,@UJx~H#(5*\FjM'QO5SL= Sex=;\cumzz6N= SeQY#cqh4s֜ k,T` ܧ=;qm1j9[|@4vK'dF6o8J):xc{wSYu{wVRO`LORO A.(*\;8'_b9ZųOWFRA>XoC'aS?2v/o/t|>3CQ)K IDAT~uǘVk,ks_.'}L1f;jSO`@ '1оr|G2drv] ɥuR.tj\#vns1_8vpTL`U8Nz>ۍ.3u{F= Ǟu{O[J}OP`Ř?2?</KkzY5Sp5{w$gG9v?qyƪ};1F=SȀ\RŁN-ޘkޝZr.f;?WSO z@cG٧7_~>ӽQ3ñ=8 2A25Q#cql7ȻʗӓxͱgGyhlq `58ЃZb6׈xaR\^c3f1BX]uGVS=lj|{g9x15QH= Q2=RŁN- XSL!z A'Tˎ3<('00=YH= d %z Ax]PRO{2!(2@O,eP-;A'4 e @F=Zv A8}B }MP #e2BPOLROk2@ϨJ= d 3eG@Ϙ,e2BPjSO5!('& '5AgTJ4</2BP)ղcM LORO[2!(2@Oybz@zJP }KP #e2BP)b }KP #e2BP)ˎ5/'/25QH=o d @F0P' 'p| }IPR-{$Ʒg2BP #eӨSOK2@iN=/ d @F=%z@_zx]P~d @F=QϧЗe3.(p_e2BP #eT-;pzd!#(2 %.g(ӓSO5#(vsS }GP #e2BP #e4=YH==Zv ^9q2O=NhLݱxﭟe4e!rr(ַGv䋥uŸ?ĥ|෿\X+2v٧Q)咼2t텕${4TIP|64S~OD_ذaC\+^+:.]Z]wKP]x~H{'q/^'~vM\X7>YdnS56?ط⡇7ƆX~,n\yWon(@kqhSD!?7"""W,GXb}{鿉|7ίo~+ݥkA!(ޝrq,w#""Vl~[cCD,_y??x7෿L;Ȥ [nzCgG9U%.W?:f1 8ㇿ|,5{(6l+/^xﭟ9APr.^9:SS֔ _$(_o3zƺq󣕸ίo~+ݥԳ>!(hPb2_$.C @Ġ̝<Wޏk ?߸۩g=HP̠dH\fp A/3ѽKsgS֏̧& q8Hu~9NZ8u5/n=AȨp}Oq+WoĉSϮƉS.<6屉ۿ_^nGfϟR…Mn@F=t5>V)bώrQVXfԶ7o]\gc۱@YJ)zw .b[;nxsѽn !AȠp q;XZ~8+"RX}ͨmox{wDDtnf dLku |o>3HXGVGo~m§q{i!B-n@|{g%'& go­#30e cvRO`ˬj9طz zkx/|Y<6VK  iRʥS\ԙĩkqyFy=kz/xݣ0$ͨmo23ѽph CM'N>9?9u-N*.8ЩD&b˓;""b{V\Xp&.KV dHkz<C2k(*xld1~񏣩g1b)y<޾ⅳ@?ڰu֛GwnO=3q;#Q)RO`Nf:{([g,L[xV`Jw)$Z1=YH=T{(jű~\ZT{(X7>ZI=!cQ..#3K h}e9.Ӛ)1XCZ=<#<#"> ,]<s d#Yv@z0> D ̬t3x  ~4xzLMRO|<ގGoGħnGf`mغu#7t,Zbdɩqg텕s>gW{(J)z G??K='?SO-^`S7h5qxr+2r.$(' jۛQތ[` & qqB?4Su{O&0j`u\^z|B~n$""YX^o[]8~h4*\Pc˓;b˓;"V`潷N ̜?+ݥ X 2o/\O=g~B<ۭIN{]!N5Z,$a4S `aa&96e0}9 N 5{X\fm첲 l":EC2JW8A<$.σg6W_W_ fUH\>fK1[Zvtv0NgfL囚Y33F::0"nR'Xn~9r1wr zYF֢wJ2(#ݏs 'RgCn ^9y*u#(RL/bqJ:2x 20Bv2HZq:ul.b9 rDDttvYe`l6nYatv֣R520B6wS'c&RL/bqJ:2ƊA!~`es(Q(#"h׫o$}e`15S3 1wr zYvR20bnnr6ud1TRDDtF 05S3 1[ZV5:ZA+qdPF^^#8݉^RL/bqJ:h׫Yv: 0(#V[zO1[ZjDDވZZA17{xIӝ L/bz+WiE^ziCŠ fnєcՈhoUdFߠ 06J1Tŕ+ߎz쬧Nx,ǻWSgtS3 15˴^8206wS'$NR)J"ZvF<  F?uZ|:S3 15s/GӊF֢^7u0(#h5Hp^:1\> r刈hoUZAQ77zqa9:X^*R)WDw;:;ѬUHT l Ϡ [~3TRDDtz5eiP`NkS3 15s/Gӊvh׫1fPFk b6`Td:l.՘-Ơwȸ̠M'`FI2(Q(#.EވZZD뽸M&OK̦J1Tŕ+ߎf7R#Ƞ |B,\^z5qN1|̖VcahoE^Mce`m6xd(e:;ѮWc20nnr6uO2q)Uvj\x"e`xK^*E\l<ZA+u0 l܍?)O#7+WZŸ 20n5xfbqqZ7R iPѼ3:`(M,B]N+j4k20 ݽ{A=2(|̖Vcj\Ɛd0v %20~$1ps3x#sk3ce:;ѮWSGȠ ֽ geh׫  IDATZ3.# F?uC*Bbٸ 20 $gPD}N0.ǓA 2<ώ:h׫ѬUH20&v l.՘-!dPDuȥ`cPf:3/~ө3x 20 ݽwɉ)[0[k;hNgPȭF?.,gSg0F|,\ŕ+ߎfb\^ $1rs:165+WGᯣP|'2٩Y0R2gu/uDăqF\hoU]gNc͠ F?u|R)JeJYp,1bPa̠wz5[ke)1Sǹ3d'P,GX^z5Jt`10(cuZѬUYD: A3Axf\>.^p\fNՓ'O~?u}%;L]~:~M1t&_?W: 'Oſ?o]Ly#&2'wЊ~4H&:x p䦗J1TahoE^M/A3A9'''R<R'p dQ(P,ǠwZ%Jt0(cV3t'uL&;՘-FӊV4xaf:^l.+W?BdRgˤ^  R';/G\h~h׫H1r`TN|-w:uU(P,ǠwZ%Jt1ts:J&;՘-Fw;J֢wJOe"uF}:B,\W7(IO,:Hc9s 'RgP^*R)W>v{o2(cjяwKc!Bb9zV4kh*;hNG|ɓO$s2ukv'\ꌡSS3J&;b^ފA+ ":Hc9H^n~9r1X9vZ%:;멳ce`Lq~H^&;b9 r:h*ѬUwJqb حF?ul.s/~N`dRl6qa9:FR)JAثވ~#u#̠ 02(Q(Z%J zi20v[ 0vfbqJ,\V5JY20nR'X^*R)zVثވA+uǘAs{A="|̖Vch*ѮWcNqZ foPHn~9r1X9v{opZ f^M~Nx2(Q(Z%J zi 1206wS'<R'@2S3 r%WDh*YO2(cnOuqx _k`_d̖Vcj4kh׫5If^7uPH cqJv=^SIC':> NFXBثވv: `(>gӠ pL#7N+>f^7u@2s{?OIJ|,\׮K"{*: 2Nxjd8z#7V$ʠ nR'^]o_Lv*u0 _j9H;Nx!|]pX&{*: 8 _j5;Sgcn;:d' \g/]3,<2NbLn91bPx"e^BoxH&up$n5q{?6X(0&0^f쥫1OaP`HƉd\x+G9qsw$?̹Sxɲa!_9s̯RGo3{_?.477 |:0ٸ<|0@s{?I/OC?:c2u*NFLӊ~z=j z9SJsZ`]x+xjꔸ}7շ?|:8nk2SyA~t1q^F}hX9sW#ŅO=v8k=k b9ֽm ~=>OǗѵ'O\Sg fⵙ qI0^gb6;Vp`'\Ο_>5I`t5::`,e1wr̖3,WΜ9;L_|zH2nn|?n|5G;L_^=:?7Sg fⵙ 3(65?z:-y[ol܍_5Oǘ p\<2@J4kRfPxk‰)c vm݋ m R 78ĠEg?6,C :`ԼƉɉ)cˆ{Zenwf?[qwZXBlXA#dLf831p nq27{Qw 3g*u(01nn<t`fq7~yx?6ݽ2K65Ù8p"u s<o*,k3 3˰ |軰}7շ?nk{A/3dHP,GX6,/A`1`gZeZm͋_7&0¾z⋟K 2xNdxL~~j>$nzhz~揮~ !skax 8u@DDx PF]3=_95~lXE[jR' }&S5(4S}24*/ Ġ 9쵞axwei浃zQ 3WBtSN?0,oeP Mͦ ^|1kS@2ezc2܋H@cʽO,膩S'p P tG'VNx;<,3ʩs8!葙o00u@Qo/9k UcN^61saJAoPyXj9c ŐA%M)d|{ P2 UcNfzfzOcKP R;zĨk/-1MGjp8g +kS' %+S5(4S}Ұ EǠ @WIP<,3kS@w P @7TՎ|cX92TՎ;-F"_rqk$xA覆-q?FDfOw~*shmO\eH oӯӿR]vO|ٽo;c^?zqR)~װ KP^y2uܠ  eaxK|c2VYņG/i܇ebMe=M@+/{۟8?/_~^,wfP,?:ntM\?ry}C_WqpAxa -q%?Qu8'cG IDATuW@;2ݰm 잸+z6;'+WMУ ofP^iP\|#[qWn{ʥovwx^9fPn8:-*N(I^&ޟ\{y[lxקEê{<ʇAnhruW֦N 0j]d+ꍯ>>?bPֶM@/jBGTGlo<~UI[(^eimK>rGOeSgDDa{{ cSPd tӑӱ%: UdR'C_L6Mc~.>MqQs(e:R'DթJθ g4kҶИ7)2USP vO<:]e3cnӮsOM@3(p PvvM@>e^7P,}_4?ɘ~Us(@eS͝t:68d쪡{ cSP@ #㙖| z7(1go}릸x92aEs.uPgS'P`fM5Ejp2(pֶcS32կ":MbMx1(pֶS'ی:x 1a|AU,eS'@Q?lOxOţGdR=O [G'VN8;7yǞKĘK+xsI~tϾAM36vz"Sgu6gi4$\2 \Z&K*c%}̀(R#*;w\Xoϼ: fP<k['N~xq{>ؼ=mNN5o:oz߼ׇf?4("&I@jxu =u=Ġ ztUAE7s7ISYsMEbX<~w0: dPd*F zWOGgG+uRQҚ-X#35+AWǴCb! 8P:JZX|#;?KaH,Kp#@Ώ;/KEk|ue蕃 Jթ(c퉕_;kqhȠ @ZќKlޞwn|1Z]a[Z1[Emq8 ȤNe+ᑡ1o^SdM =O [>~hrLX@Cc̭~)$Mb q͓S ͹ '^ix~arӶD4rܽ-R\sN(Zcc6Ʀ({ez؊=:zWO -o9b|JXnr'W7>=.V:lk[\@@ꉘ=g| [Z1[cᒽS(Q;֦N((CS'e+>#}ۧ(Kez:R'@9늅KƤ[cٚs(` &5vz"u <o|!u@0(ЇjL@=g<=u}'qζxbkS VN(Y*_;~Ƹh3CG:OjTw8H=+,w/jK@lꄂү":d?7u^_<9:HA>v ùh-zeJCۣqq8ו:>Ԟ:("_7U'H  @[ےOD~1Ĥ[cvyl=קEêS)2 hL@ ؼ=fn5&Ci!'V:\.sg`N3eXќK@ۼ=sEGgWH+, M}_E&u?+|T^gP =O3-^=cL`;pR( (S.uÃżyM:Hdm !c2v9ی.7u}$[q,6'J+ $3rGO3Қ726ojꡩ$nǷ1.V:GH  c2pv]8g[u {;Sg@WIP=u`=+_sΛA]Ց:eL.̲5▯\WVN8_ȎX|B\9Š @bk[\;=1@;sn_:~Ƹx9Ġ @bG:Oڙ:3{XܡPc̭y&bW/N@VK@c#CMS͠ @x9:X@ ()mNDmFe(jUJV]vO X6s<ܮx qńs*:6O'V,j۬ڳ~{\(4]1[c?;n:Yf P?`ovS:ޙ: R@ho?}q7&3.꯾:ӦEmmmL8n-͛ñ~ᅦR0g2lűGOy)uۼK.Dod&~Rg\WխSWӦM3fĴiӢ ?4s+KIꄂ2CG3Jyԏ_ \7dR{{gZqlhc2cbƌqwĉb֬YoӫWO?=pZǾ>6u tKթ^<ْ: ""ֶM@-3~Yubǎx$c2?QU+Wƌ3Rg9Y@̞3utK gtLjC}qQs ͝;z:u}կŲ5ܹsǎXti444$;77|sяҥQ__: eٚq̭q8ו:79zD]voJĔK5NʜATsg`޿`عcG,^8]5kVlڸ1iӦc֬IpV[Z8gQ _&:8lxm|!06uP ͹ ù+oyߌ3b`ITֳ&NK.Ă օ.2S' ijO7>=2USeƠ @yiضd z;m߉SWϮ[+K\;jjjbsǎxbL9)~~D S'P¾~0>u PF GWuN==V?w(""u eΨ  pV_ȎX|B\5yBH(YՑ:G+N]R&NϮ[3fHB3*;^7"uBKސ8:eLu{7Ed A"gضd үFQ+BMMMяbS(sFe *2Jθ pNd詟w=է A"誎 ͰO]Qv̟-]:2gTψڑqbLU@!2(P$ֶ#wt Τ{#FN]Qf͚iS֦Nutv-_iù)E=7(uBAP:$<:#[AƔ{WNMX"2EHX ֥_J)M81]Ψ I;s@lꄂ00u@IWݚ:ٕCzT ?_d=2E\IN]AaT>u elKkި S'9;qScʽO+qP 6O*G71*C!0*pa:O HPP**R' P|{Lՠ}1EjpVƠ @Ώ;R'ff~TRSScT䶴w(JMPP2N(9[S'y}w1'cS(De {#.30*C!X@̞3ueJao IDATN֝QLՠ}1E(:2EfSLQp O/dFe(ȤN(9#*Nv.HM)>ïڋE@1(PV4R'7PZO~-u@x JթJι r@rsLՠ}1EH:2EhmK>rGO(of.Ī+6u el΂]Fe@nM.n1'cS{(4eS͝WRWpuʐ~LRݓ:.cDLՠ}1Ejp  @Ϊ xO''Ƴ֥ΠutvEmFeŎS'2 75d rjĠ @ڳTlu2u@Y:=tf.ĉ㱥KSgP::Où)d pU^md/2UF(bHP~q 4k֬xRgPƶqζ~ %.'u\75&p^Vc ePmGesu!s+5+uelKk>fߙ:N((VN(9[S'qUȸE"2U{gP<k[3JEmCz<^ut9 MPPs czciOA"Ts.u@xvݺMB[7RgPUdR'2޺?WՎ\/"S5WzA"we}8u&V\:2wmy{>u@Ah JPPgS'S'@r^S?z8wl<2%;?HPvz"_s] zICCC<3(c]8g[uNHnAzѸ c{{ڑ1Kǘ{,(k7xj޶?jjjRgЋuW̘1#ueQx~ %.'uƈʃ}r֘c cP*i1*[xSg[4jkkSgPƶc3jeS'S'#[q,uqcL}v&p~ ͹ %ӦΠĪ+SgP断9O~-u@2A(QL=.x{\}EБ}~6=eJږ|*u@9 S# sSgP,SgP**R'+lO=4&/-SoIr> -.2i-WOO3c/9p+u@ڟ˦N(8S'Ndggnb\}Ejp HPrx@L6-u |R'P::qζ}j_ e(M[_{Ęr1ʩI;?0(PB?/l9:du@Ejo::᪖ݹ9yS`V0(P N]z\,%΀؉̀ @hoz5u‡*޲&%=NgPJ&R'T}OK?LXCN#3Љbg.Oelkkl<w5S@2(PO*d oL2lÆ O1rd2O@r P6 +cP V=do1`PS'Tc'b}lÆ jȪG}4uDDDb"nN!u@UR'@Y5V֛OkcG1:A*qRgT:: _x[oQ:`Z:0uURW(nȒOF׶]oHUà @z! N@xGX,΀=9;X ʠnN!u@9=5?^(u>@myto6nNU @3c*sble3•̝;7z&;:MLեNȔ\O},up]vE)P TW_+~8f 7p}n\zK/Gi? Î*3(޲&{R@2(0 S'dZib\ *ܹs㡇J16q1|L¼ U^lL^:\cs靱r#ķcP`W32kO@CEXLs1q,r=Tf?:]5%-Z{Wt?'mSO*{`2u@f=ԩ Tsg?u\K/Gib 2~>uB7NjCgzάOjtriꄲh,F=l)P1 XL:vb*F=CK/`Nz{_Q ]vE)yef|!V x\*\{{{|Sg%?6":0uQŋ㷦N[D`uO4273: s N@:.K/Gib nB]S!u3'0uܔ3SS'̘\cs靱r#ķL2(04צNȔc'bd 5k7u\26q1Op޸P:!sjjsf_x?KR 964uŒ[~pO:R@%sȔ]K P >s2u*OpM~v:!S1:4Og̅sຼ8~k$ѽ}O,۸9u do-^?RGP~5~)u@Կȑɫ>_rj .4DD)~w:C:032!?/޺.up$zuES/RM^Sg$Wze$^zxS Fc2qԇNˌSg|g}^5܏_;KRgp+uB&oYƂ=S Zx|Z5{~;Rd:?6{뗿htX:.37_/Ʋ S:SgdF(.5uWp$ڛ^eMƂp$u׎~>߉c2zs"u $nB*O5&~p7::eZGooo NK&.ƎgnȮ RSY_k/l8 F{ӫќWf(ɋs|%=-ӏɗSs@[ښ324~1^8M5(!s?.)gg}/ TS ͼa-/n d(߶?86l(c fܹq@ȑx[ ^:})N9x}?θL{ӫl,h8 Gf:yq8=5?uFEX'/}{W^NegP k˟w $u WQS{\Sxq>9Mƪ‘D εYv(/=Xy9P<2K[scs1u@f=u=T*j6wܸ{c`` u OO,eRDDġ S'd1\znjT'_S'T-k{xOi*G\xp5r}2e*O!JG >@ݜB̬*Wcuho: &zn2@ZS+us]l*Յ#H,?pvy矊ɥ3V9Vnbo錣ޜH7̝U`ik.vl.ȼo;6!tח:{^|Ӡ 7N+:=5?NOЙ|`fݼCTąάNy-Z{W:⥧/bP |푅ڡ T5kDXR:> c6*9]60JD{ӫp$VU#f?Y{_lY%߶<I͠ @[xRr6(M퍁pE_Zet)N\}}cD=0=P*U#*'D?:cZqQ\&^x͉9p TqaYahh(6lؐ: dPz| <Fe4&.ԥNȔ¼ 0myǪ‘Xr5zq˟}>&/6Nď'_NĠ @{xXK;AnHWggP_Ze"`6yqxqֈh-oˬ.i:.[gSgk޾'>7x&u|(wT}n)éPC/磷ur9uB)N3y)늃"73CH,?0gNa7x&uA yAnHggg&?uʠ @B9 F'#73Ū‘u7nx_(._/}{WDĠ @}-zy} Yi`` zT pM?.eR3 RSr.VYU8[Ǫ‘0&/6N&,X?3&N:""/^#6-'F&u @E6n{^_rjmruu7_H_ơ Sgd. Rg@k-oˬ.i::2tf}<}qzj~gϤ6$'>: é3C 1&/ZZ(._/}{WDf12;:꣥6}%ae!˖-3(CEu2}`I`85ޜ:!S R'@Uz†p8Vĺye9 ๮:>F'dςU=S;c˩s ̀X(wֺh~M~>1|3u3Rg57pƠ PNO͏S=1t'╈WcUH,kz5ڛ^i:~C%1:4~:~k8~[?TbktoG<:YȠ uzLϚ9 Qh6ʯT*HY&u X,Nk6zr*;yS*v R7:fɥ1:7Md7z{㭦8sa>Њ{5ҷw[oN`1(zwGK;:꣥6"".Œַl.틯~30]<)23֥\%9x+a nڶ+^z8rf W!Ueik.,LsM-704&:  p]^8NLŲ S*u?߭]T|ڶ+>'N{s 7Osђ_ȴslt4bÆ S k֬ImN_>Ҟ:RR'dJ~·? kl[:{7'R'Pq ̘,m}BP IDAT~337_'kko>2@92@ٜoN)5. +mӏɗSP\ܐ|M暸ϭl(4xcc1w)TLlT 3N}vO;A -mŒEK}AvK&n憎k?ZvL7(Tϟ(jSUbLi(|2tƏSP% @ƽwg͜Kwf掎(4hv1::Sc0u܀=>󉅩3*ƅ ѽ}oQze8uU d\Qw4Xښ%N v_WSgP!ڗ-K7NS'dJݜB56G׶c2uݩ =McBG}4Ν:lFLƱSlqCTSx۲;7GS;7'RPjRlӒߓK{{~;}Ř TR3ns*r RTH@oY|[G*A!K[sG??4v>0߈ T eotUS\c5EkN@2(e֒7ϋɥw4R<6:Ȓ#qT J=SL)Ȩ+7=|*;Y)ɥc +:ok.>{wY^ K;:S'dJ~N2lڻkۮhך: aPʠ%_55 N`6e5/S'UcVИ:˷-{c)Tw4>qo4NfؗR'Eib L\K)9;cͩS820>uw>KZsSchh(u@Y <:pZYvڶ+r)dA&;_(4;,[徾>@j? @;9ќ:!SR'PD#u NWٷ144TcPS'M<8:p ʼ[Mm.uĢwN c M2&חR'QR)uܴѓS1|x2uPN7NȔB*M_I@`L 144:l?x>uPN7NȔ\wE85u `Pndu6370oٲeFCe=v,uL1(ܸe.S7:*o[F)$fPn@K&Ֆ:Bh~9h 7nb.uT\cstm{,ܗ: F4pu}}}166:`ڍM\Ó3 ul1uB4N X5S;`:}|~OS /ncJ뛱mCCC`Z=|q.u]vE)02pZ53le""߽;FFFfdSTJj7R'gg2!?/uU.߶<{R0 u(4;ϟؑ: 84<: @KN9Xqsf;a-mߕOL=`~=&3zXV'4~1uPa-NȔ¼ "w5k.jѾxfe""blllƏKvNn 31U:fzkۮȷuN 5Xښ?;r7T*Ŗ[SgаA Ґ̼|ڶ+I@kiяw`` ߟؤ544:K 31U:\cs靱l)A|Jlٺ5Rg0 N8vb*uPa-NȔ¼ rw5NQhv դ}qCcJزukC,FLN*R'`ڶ+mS&=ͩi,LD@~≤ ̬ P6Çgg2!?/u\o[]vł=Se*Z5=M3iV,R'D___`ƱP6NLN*T]LMN kl;>3mܜ:dPgMc :oK? [*Ol):GS'dJ]S!u|ewn\c>u 7Ƞ \9*6<<;vHA N:TBoN)5 pE]vE)2pwԧNdú ?SgPF:' \nN!u\Umyto[:Sp U_Ә:vu pwԧNʬ!umٺ5FFFRgp )GS'dJm}cKz>w5S.egwP&"΍Tߟ:2e!wIfڶ+mS52ZH!uUJ%2ݻS';d X:!Sꚲ} +߶<-S2bs ʨLeeJS'T쟇56G׶bI}Sf=2p?yB̺nkJpMM‡x|(J3 S\:!SR'@YXAJYmͩYTu122:+ݻw̙K)5 PvF1:`V2(U,|mkV*΍dT___J9GS'dJCa^ȷuNu E`t֜:ɦߟ:2xeo[Mm.u̘bktm VNU U`tlJp݌dϟؑ:2A)Nkl;>3ܗ:`0(W/Nf@ 7Q)^Wé3 NWހ_9r <+7=:`V0(W3*ծʽT*Ŗ[$422}}}3 N7NȔ9 ̢wEķNje* :( 7m֭uX-3 ӎ-NȔ \myt?'mSA"u0R'ܴ}c)Ǝ;bxx8udą :2]vł=SA#oNf@mM`[.FFFRTߟ:2Љ2:2#w|zg,/u @1(Wq~WC2PVVǠLDıѸs7vR6###eP&S'dJMm.udΊ{IPU oNʬ%u´*JeغukΩ*###qƍ3bl1uB4NLZ޾7r)U |D:okNP΍cdd$uJU/JRƛR'dJM.:2+߶<|[GgP>_G2P͊hokHQñvݺS*XܹqcMxuݨ9 ioLP 5NʬoݱcGlb u{gLfxx8u dG?Rݿ7bLoL!]EkNP 5Ñ7SgeԹ9uB ƺWRTXn1R'dJ~N(+7}1Vnz$u@E2(όNʨ붦 3T*E___9622wnFGS@E:tbaLmhLgڻ?|bPwLGLIowK5<<wn[n1Ck׭R:*Bmͩ O)9"-X]ve:|s2ڰnvDD++_1,cccuزuk(Bm ~v:!SR'@ʷ-{ȷuNe:p_8:(~:!R}}}nݺOH[._QB.uAƛR'dJMp3rѵmW,Z{w3(=gc_ʠ I-[Ɗ+fհX}+vݺ86::*RmF#;5>ϭޫn/klKzKie:U|s32nI 166:l֭)PkS'tl1uB7NbGRgdAț3iV,ƚ[RgdƱرcGtX?pN6CCCc6mcU)t֜:Ƞ u2%W?'uTEkm"טO9e2GZR'dNTw+b/I7!;7n9P @:0uB5R'@U*޲&yS2Š ܠ|!R `voӦXpalݺ5FFFR']~C2P&]+R'41U:!SjjsjۖGoHe&woAkS*b_].VX?p߿?ueFFFb֭`زu!(  bLiKU-]vŢwNȄZxJ1X[ `Կȑ7z{{㣽aÆ;X @ Ʊ;6f*c\?(&.ԥȌUg)Y{gRg$Ko?iJL?sA088FWgg/[]sνcpCᛏ119+y mӏNHƠ L?s6z:\:o#:j30^Q,#љRtlXsm\:!SjS'h]/}{WDgP_}\|`~`=(C _zl$*Ӳ  K)9`VZ'CQ`֩I⯟9? 3iKy]+R'tl1uB4W@*{<)3ʠ L 4HK{%~Gy\rѵmWoL0c wuߖdcpX؍5\&N ݋ucL 4v!Y iM7@8 $vn햀cKm$KV|H’?$}9z[:d>/,궘{צ`e`ܳ+zOSۚ K# Jye6up欹6^u{ bP&@OhܺX <\y 5[:TTNKel.u y1(s@ uP:{R'Lg&WnJpFe OD9Z֐:`­iV8Q:gqtъO«nO @"=}~9n 6Wm ܁eޮrZ`5.,>|QͥNx2b瞁9ӜOCK IDAT\R:`rMcSgw2uBAS'aъXzFecP R'h][C Q+nJHPP3 5͍7SbP;tt8;up֭n]یhoUꄂSQ9-u0rMscyS"  {6wé3smFqwՍ"W:dr*ձ􆻍 [>:8FRwݕ 19:(/1veD*ձO6FSA(;wK9͙%53.J ejU>u«n3*$eP 'h ,rMcqqݕ 19:(e~ie_ֿ)u0I7lJdp(=o(uPD^82#uBAdS'Wݞ: @=s@ ,kkH0!4ު g|4.,^u{TdsSIĠ l<:8K7_cfMNHG_uꄂbLx7.7mT0exp(;upѶ>uʆӜIHPP**kkT0e@}qp , cp:{S'U @ըLi^7},up4gb3.uW6ĜL ȼr.uBA:͠ pfFe`P 3p5[mqIMZ^:(bթ J&W:(1􆻍Š l<FSggn%?kIު uP²u3c wΚA(b7H4+u[n13"wjhj MMQP3 @VΚA(b;w}`ʆҔ7^:(KPP+rZ `ըLŭSgP=h dHM ʼi $Q Ѹ)@H\ѸuñSHz爈Gw9ޜʘ3+4gbNs?pn4gb{_OLR&V-I' ʼ*2[xmѹk[عg >$:1s=;_>ݽ#=yNm#>{Y.uشXlQOߟ:-_fĥkuAU1;~FǀqS+HiΤNJgn"""[u~'/N\7jFMsFe`3(%&Wn)%mS]7bS]QKS&Ǻ3%ecqWSg%[▫Sg%cCG{8fEn5FL)ӧG'n}`nkL::^-R s\ 0֌Ȥqn9͙9l{{Rg%fGRg%h,T9l}Sj8*jcthESSg+20yK30"S`̯[iӣ._:༼vd0~^HH.J{3u\kMDݼ߉ܬk(+ӣ]ek32*A(agVĿl:(vd0<Ngw }\weCkפN8gw{8@XXE3uc='u>8'/i cl dr1c%3ޗQ| @ҵkRg-OuŦ-b)L|Mc[;#sڲ$OLKSg%O>oVF%rG|<Uh-:Š Lyv\4"u@z`tQiΤx__K>@Ū53vMNj(.gmxTpmq0u 0 $l`CS s=i˱xNa}⒚M\ ;=wz H|uc|@uOS'%?{Q[12N$2 _ aT&20I|r3 ¦=S0Z2Yn)i~L RgĬ:a\ƴ:0ZuI$aM\%{C3Id瞁زT 3=**1*eSQ7{AD1gTJǔfwW$l`CS i]qo$u %cE]}غ+u}$Z&=:Rg\Ӽ58}΁A ~{^el8+uyӻc)pF&ܘӜILݽ#aYXE3Iki\9`TKy>#uֱ͕DzEn?ƗY=fx_i˱fcKrs͔'WŦ-bps#`2xݼ$vc'!@xȳw<@z WD1ݑ:8 S]i DM,8+.Y:6m=_=NNƜfczYm<߉|y`صZi^]usDâsIs 3QH78t:K=xOJ:cp6ūc06m9LY|lsk`iDKs&>Օ:G;6PTo6=lמ}c+*2QOL2yo{wN ތo͞:Dθ)0&NǶ'czmfR'%jI_`s{K6k`<͹F?v(x8?D珷E_ǫS"*ӣ2u0 gP5?L)@r<N΁11iisɕu냱{` >g-3blxTu?{8wG uEE6yd1*͠ kzNUSv罇p x3u OkƪF6S: (A>Zs*%o,p;9(&C}]=q;bxTd2uPb@ѿ;x 6WO޿8NxxWMA>o\Xtx[ t<ʦVF~f4@477{,!pFgVΊ|$gi]qo$u %G]}ضd(zC?Ҝ <Fes{KggxO; Π u<w<?]?w̨ aP8k<:( [Oߺ?~1:J֧m)@0*+?oRg}LA8=FmqxcP l}cUT&Qxevpc٢L|qC{|iC{ N%ih[3=9@ X:ZTY{i}|x_['/0fF`߻#~Cy02?=*y1*kJss?V+g7ώ|Z`Oߺ?y'u L KWţߘs ;ccdHT̯'_u)gtpRg0IEˣ5ML]OľG6WH󮑸bEu /]7OoƦ-⊕u05uP+OgOD0&{bS3$W#Ctx[ t<ʦVF~f4`E1ݑ:JAxp(VkC IDATN3+Rhc~ ftNCƆtqGS+'_l([{Rg0 C{s׶8?~(bJDՌ٩1fTߔfWl̊.{ǝ:HޑXsKg(Ii]P:}ع۠ "KahX"*VTtz"=!u|>G)1%>ޚMޑi|{GSxh[3=u P ?wo΁bL(V_|* P;=Pu7#[e k8wG(9S]<;.Y:ݽ#b)ʆxRg% _>Pk΀k.+"[73up:w=ِ:JJy>#uP^|u(>wy>u0v|'񳎡){ؽ?7Ll,uPLM\{CjyM sÝòx1:fTGE6: 8yo{wNaP ǿi=2u 0F<uIxW4Ī5ҜCS@Qι+>:|صw0u?v8*ӣ2_: 8 Fe`lMinnv%(pAjreّv+M[_M%G]s{G=:T~f4,Z.\9D{dC (ze1s, _>yjiģߘ R%w$\Rߟ:1̺`\`T.\y>#uP^<8+ZS`Lɾxqʺhl:(LYggkn2pFdRs@v8tt8ulhX2]s`ѹk[ (*e1S+c/ɾ)8s;0^҆+PzOO9Ù)wJCۥqŊeptEC ƿ 蔾%bw>s3S=3hLĔOl.u42p477N3+_6NM[_ט-s֨Q˟Swww{wDDݱL%G]$0~'>}~u,Q}ع۠ \\Ӽh\vy4,^ٺsd{ܵ-u42ҵkfr immKWXti,YdLcO_kGRg%w$僱u{WS]|u^ q7:Jʯe]9PrĿnͬHkcժUP駟-[O?m`Ɖ婮—ɾ)p8+xQ qupRg@IkX"+߽##u$2ymo81Xwuv :{{M6Ŗ-[9PRn1v{K uz-SXvF q' RgѰxE4.<HEoxTpmq0u 23ⳗRgos19--qݺuq7Gmm20$L/|hLg6WO޿8ZTNw{"hO t*hXfTޝA{%e3_z19--~T[Ɩ-[bӃNCq<0{G[;}=u %G]G8oc2V'韢mf &Fkkk|1gΜؽ{wt<: oƾHL /\/!Ͽ Lq˜ӜI}LcqxcPTLE~f,(8eQ3{q|JLinn??Vק&׎ j=)q-qՍ3[MlhX2.Zٻ;o! ɕ$"t bnzܧB9[<[׏/rb+7y}_pa0u $aP$qwsp(nYR +V׾8qbꬢ300?pIPΜU- Rh rUp^};z&uew5L'N( C3rvD:qIIU5G90 Ͼ4)j:*{dߴ)O$uRIhjj+VԩSk׮( (_},u P 0&f5LxOO9Dhz_׻'Q]ט: 0*@2(\k\Pŭ^3k{O=/NTr _BR5W]: FQ*'OnJ`5T:*ƣ:닕+VĦMRTXlYtuuN%ѹSe_9\ uS;NJ@U&ٖis`ض>{6u 2=:}P16o3V=jŏMSqxtÆP4L}JJԹ|y"x"u#GR^=y d[GkniLLm1Fe(W֦Jh! =ĕ5cGCCCꤊsԩSs)PŁÿ-X 0.^_[]-qhȎ#o3gw3${[*u@I|t3svD;q_G!UWf#ؔ: .ۤY(c)0u @[?vt@)ZsKcҬ\dPl[=:FA̞^>vu ({SU/EObɒ%o&uzӓ:;7͊kRs[G'99ė>+_:lké323iV.;b )pI c51xPe н{phmKhhhC'NLĿ[nը ۇ}RgߌG8?JRn>rձpG:(cƦtÂh]pGdRE1*@9_WW6uPK>;.uŖ[ߊEW&??A΁ϑ?u.n_А:`Dͽ6GMo*ǰ̘[kiJ|֘:yB =Åq'#7"lYpAUU|*8;x"u\+&O@qlG6|U3mfzՈXpa<{">ȪUb-3 7@ʟ:8}GϤ)[c咫w5ekLTL6;uihJjp:~cuNNKfP-qE jcL6UNsp(nYR CSLI\Ň1*SZ&ď{P7>u 98;|sӍrɤXؐ1XCgSgڶhnR_|K]_:b==wO[mhn-u 2*2PAiE jb+;oƪ_}+VĦMqP&fǡ? uS$յdtp"^ӡ9IMiKni%jSkL;Ue LCSxOMŠ Eve,DkSU=C+Ĕ)Sq9ygtvv΀dRg#o'OFSwLQwӍƸy^}]oSHpAmhn-u DDı}ŁmRg3(e暦ߖEȵev\$we˱Go|iӦE\['u $ϯ%jLP;0Pt(uebX8>ué.ZU&Ѻ442YӪS轃2^y%LeTJ71;>=h:Ok83E?2sӍ1wfM]_skR'pv5GSg\kۢu1\*ؑ[[SgJ\XywDv\$2,\ИL8qb|>cF90z(ץN(z ucX898SѵdOygp4t-7~]DD,WS&O'`t)Nl=?Ʀhn44LeyNDZ}ϦNdPJձ(WĬiթsrŊ wFenV2T/NĒO5N(ImDD;q&8SKP7>""_N1q?iV.ZsK9 30*@QbɿJX\ە(WuR'#U/Gqq7S0 oK-KIL̎COݱ ;NUƦh-ԦB@ePՑkg;bִ9(XbElڴ)u d׿w_ HbN:*Bܹh 1QƤYh-l˴9ؿqM =:~AH>;.rs2hAm̟֦IŜ9sR0VZlIIuTO<cڶhnRPƌP =:rm= Pf,9J F@rӓ:ܔ q鹩3Z;Rg$SF;#2 Ms(CÅӱg. Nw1(WۮEhmJW:17Λ|>u W_nM놥}qr| 0iV.ZsK9S(3G_hQpMSU,ZP\jREj/Nپ}{,],u$Rg@yճq꟧(:Ʀzˊ4+U9 220Bjb~ە(WMUsR0R0xtÆ0n>vn!uTO<E*h]pGdRP?~bm 0(ꚦߖEȵev\$OI]Aq& IDAT7Λ===3`mzxZ\|U (ǎ%aҬ\FõsRP{.l[: gP.{dfMNCLRg@___8o^)0&fǡ? uS@Ÿai_<:db-+bҬ\TejSP#XgŒkg_?]7L.ƻ":"s3ϤN1u쯢p|ܾ!u T^=s2u@./w?|*_Ul,JLez1xP*'OU(&WǢ\m,ZPUK]@b3:;;Sg{{sc 3m|d|_( f54:s`8T 2TX\ە(WuR'SbSعPVC3J)޲"&EU6u%Z_N@1(@E=:rmlG]̚V:4lDSWPoK-Kcn۟_K>՘: Ke*wDs{GdRP c51xP*A*B}v\dbтژ?'MUJv?HoMtuu΀15eBzzn ([/z6n[#;9S(bFeke([WG-(SQkHōE>OcWǃ[Sg@YcHPQmqRP {c0: `P(WۮEhmJf]̆=0&fǡ? uS@Y?vtHƦhnҨԦ }5o\cTQgPvMSU,ZP\jR|D\RWPn7/zzzRgZGsҾ89x>u@EdcҬ\LuydRPD{c53(se(9r51X֦9S"k׮[Sg{{sc 3lٸmSgf54:"qlsq`ۺ1o(z4UL,F-uR'\.HtMrŊؼeKSw髱s 3ltR'_lh-R';?`\1y_YӪSqݩ+(R}}}qySz~ p^} ( ǎ|Lcӿ tDU6u ض>{6ueh|]]PKn7Ɵ}iR,t}0!j: `dQ3;uE! gDWWWSG~~6V.*uc/Y(fÅ?|*_Ul,4+| =:2sɓ$fOEX&fMN06~#vn @xq/u MOxճq꟧4wDknid[N ߸ר #ʠ c>;.j"ve,D]IcϠ `˖-qU3`LMi.'OWE .Cõm1p)ؿqQFAFՑkg;bִ9M#23RWPf̘GRgXP|h)`db-+)سny SP 0"7'9hmJP\f]JĖ-[URg2!==7u;N`e#ZsK*S:Q6xؿqQ.A.ՑkGde3f̈#}}3`L=xpuk (9{ q皣3%U2 LCSFQpo߸&u%Π dQ&]r5T:t"lٲ%^*uqOFC)PR5_z"uc#޺ܰ @;8m] JA.H}v\,Ģ\mܞIP pf̘GRgzpPR|h)` 5\So] I(xxRgP e1ш H1(EڲeKܽjU SӟSd\q8u4\~[F؁mؾgSgP >ۑ7FkSUbPK0cƌ8ח:ԃWLPܽ?ueb-+ km;u%f|]]mض%>QqsN]@ jhhSg`(GMgS0Oz[?gONx6QmYMUsXdI444΀150x.:_x+uBHDy~kY<Åө Uژ{46N[:jb5ݝFN]@ d2Q8s&R90_|s (jN~wJTCCCS90_|s (ZrGb.CzQGՕ46N"T5F9ܝ:"gP͞^PS̚V:247-[Rg<S&OצN3(1Gű}Fpod l2oloظӫcc2ޟvM7)SRgy;.09&T_:wF4L&=q)0ΜU4MH9_}D?: s~l?|*Ο;ٖ1:uQs5il/wNKycպ(*g.L,Y8u$ G󱻧: 6\#o=Ǒ[cp:u~[斦8] PfO{Oo磩 (K,II=]{OP$ ^3H̠ @zޏNw)20qD2TG8: k 7-SgA24-dRgL]@XpaHb'gRg@2;?:ޗaPLcS1(P_ޘ:2/uebũ -LI?dX Lm|⮇*M@e5MU1N&u)SD[[[ Hbs B`eʶLO|~m 0(Pf_ј:SY N$N1Pz p휘12efQ&uƠ #hA*7S'-NKfX ۢ#ucȠ @YZx% 2T/s3`-3{3Ir3#NE jS'p ?K]@8qb΀d6o3u= 0 l2edL.} (#7/\:iPʱ!{ʓaQL6u ̠ @=:ZRgp .,4(CPJCgSg2,0T2eb \>^K]AhkkKImfu; )P9 l˴{Sg0 'N"S'P&LSLIt<:F]w/S'{gXf7VDZ}ϥ(+(ceթH?{;uem L3ѵd U;R'@2q`ۺس~aԚ#;Rg0 O(9NN6w:FKSg@reFek"2=u#̠ @uiPjo3(s P:_8:F͎NbX`dͽg}dRg0:(WNՕ:21u 92ݧS'@QzgXf"؀;'z(2)2e>TuvvNL̙3'u$׹ 0N>?9t6uؿqaːm3\:1$p^}tuu@D[[[H`J%2G_MPr&ݐ7u# $ٙ:2А:<=t2uq`(Sޑ:dPܾ=ueb… L#jGDT={-7,pf.[ٖ3 e 쌁5s 0b^zl<:J;2Gvn9%a=#ؔ:KdPiwvv&,\ܼpaH8ƙ0"v|(u#o5,p2L6u @pgJ׹}{‰ 0"vt;#m0̱}ϥ(jٖi153eOMe쌾 P:w?o@0 q`ۺسް tC.f|\$2M7ֿP&N:®s3-NP8߸7{Sޑ:`PLxS1@裩Fޓ PQx3l\ 2e \#}}k׮ P PLām룐OPT޳>2M3eOI%~͛7'*\444NйDdt3lY<l[ÅөsBU6>qCQɦNC(=R P6o3J^3q ݽLwejX "-bƧM0(P&~rl:N R''S'% { [cϺqlsskn-޺ýs{#2=uà @c3e}|AwLyL (n #'o\?(SLm|k*Mo0(PFNgcP+v55k pN>{ 3tسny7c`,{2eϞJyS'W(;8J߉=Ǒ[Sl˴A2{(^NE}+v55ſ?:.Xw/S'i0G{/cK0fo 2e[ON`<éJZOR'EDض.o| {SDez   @Y=NO:w~+v55k v䠿@ď6 9n=#ؔ:(C'WHzC?:mKP /3N>:v}=J]___(Z=ONϞJ$?{:l['>62M3*A2wr||yݛ3GGIA3(C}??9t6uP{6[GvnM0b2L6u @E1(Pvt'Otc=oÆ 10005|>:VgR'[H`y~kY<ܝ:`Dd[;פ(e*W7$|>w(PNPx_;:uP 'Oln[e*kWϦ}̝YsݼeKڵkk(U}GNs!]ϩcGCwXqm-cҬ\ `P<5*P&U]Jّ PEԹk{ ql߳g8sk2sm:0'Ǘ׽NO{̽梞?(PzzzR'@Q9ݮQ 7\#o=GpoKRL6u @Y3(P~rl,[sԨ @2yE 6D__(P"ϧ΀v3J‰ؿqM@s.ZeZ̼sM fPB(.S/aP&ݫVB 'u>2g䠿.'[<.NpQ&ݐ.OP T02g{Ͽ-Ke@X^l.nRڦafNqwlSl'?z)0MvK BfJru rM]%~ :cyqJeKsxd2u>k IDATsrneݸ$PnՓ༽]n&[]{ǑN0.m7l3*AiG2ܘ޽;zzz&rٙ:J^nl8uR'Xǫ_^윅3*A僣{M0mo}k(7eu`$uDD+F́b W~o ^J_&[W#mHPQ >7*E?;vsPNzz|,\ >5:pG^x*߳=)aXqŠ HkKzݻ瞛~ P6}:uLLB>?p<&Jۢkn%nMP1 >Fei_Ugܺm[ M@ 夳3u>2$ʡxs:F GvE!7:h^ڞ:"\ irqmPC2(PF i+]qG0:g"mHP 3ÃwOSgL;oh3:;;c=L@ Oes߉ Ls>5:?p{8v+u Odcܛ:}nQ2SfBٽ{w<rq[xh ( K_; 9ӰxYvw fP˨ jvκ}ǎ陰(=CCC㏧::}rqG0:E9u@2(2*0u6olr\ЄIi1&U7ΣO N?p{8v+u y+n (Ke s4^94:]R;uwwǭ۶M虔::R'@ M4@1^>t⥯@dL!u @1(vWQIR'رcDŽIz}}}ٙ: d l~894m^WvW cP v"?fT` 3%/uSé3ǾcR\uѶu{ bPq1*0֯s蘔ZCCCpQ>:ihxd,^>⥯슗@`ka{[)u@0(\&gP&";'?xrP 0vLpIp`[Y:,࢜ȏᑱ)vRϿ}ǎk0vޝ:q Xg^3S/?6N(yeh/mw`76M\.nغըL}}3@#cd S/=+yjX,Vܲ3u@3(%1*09֭ʔݻwN`+]V7R̢knEܜ:xWMLQrRg0{7:` x/žvFP`YqhX87*s\gO coED8櫉 &V&?uW[)u PB]?:,55T]kդNr>+~e ;./ܱ$ubdtf_Fꌤ~4@3cFUO 7F3Vgߍb! ,[)Vo;2)@}ܑ:lk>bv2u@x5ycS *^*Z:$͚=?.[EL`OJB&WvW4/]:(ou}#xK3.AʚQ`b:lhnN@ͩ3JҜ+Fe-\oODD;S#frAl5ڶnL>u P^zdW{+uE1(@3*LG?8n{1u@YX.^x3uޒ:do̤?B>Xȿ7>/4I.0}d,R #;%2TxKǒ f'G_%~m^=SgP!ZU3JҬIc3Q<.ԒMF֧N}ܑ:`m @E8w ]Us'o=r$u@k_&wN(Y"""bޚM??98Sx?#>exc}04,^m[gN0.3ZZZΥ5Fei'cm/(yUu3>%uFjiUVCf|l5ڶnLx5LW;rݩ3.A*Q`:Y:u@ɚPT?hKQf͞-oO1 ( i*;ga\?R  #Q,S\2T$2tq瞾#3J֯o}qe *-:$͹rm_֒:#=6ssG08: `m[G Sg z{bw eXԞY:`Rudl%O2~3RgPkSg-QUIQ;?S#N\ca){/[]Peh!]SgLk>bv2u@IhK@omZjSgP?u]ꌒ5 Q8'u$|vNdӭ;Rghw{ ()e֌f'G_I[Y/<T?֦Sgl,N:?0cdƧaXhX,u 0 x~(S""qWH7\[TN3"J]x(fdtfѳKQ/kle3b5sarc,hۺ=歽.FM܈&4wz5Ժ&u025Q5y6u @DDhii9:Rjj߻8.Iprgc޿ٗ: 7a}Ԧ}ū3J53g5ΠDz{"0rݑ?IPR՟l}`㭮RgDuccs#qõu1NuK?<ݯLw?(uO!=MQk1RgP²sFSXnK,tk,hbMoQ,Xq4u&$S 2˿JtŚx}1LLs3ZZZΥRP_wq]V:t;[@ $r>?ueͱk7(YKVFÂ+RgP"0# E+nl}`žHLse_ijty,YIpIbN0}wc47VgA[ꌒ"S3+u(s~\&w'|$9 a4,^: ou}#xK3iqW(G)orCHpњ Rkⶏ_: GX5T̜MRgPsFXnK\hj]Y 1zX͈KSuMz{HLS3ZZZΥR5{Gc}U>??b(6u y5ycS ⏾smꌒ5ʵQYK ba$rݑ?C=Nyi{]m^:DH ק(Ys>3 FU&FXtѶu{4/k윅Ã1VM #/<u Zn~kTejnAkl`2( PV-=r$u%RgPϊ%kQYK x윅Ѽ=Wl-歽.F3hlrѼ=25T758)4cP~g_=1u 57fOGk'SLUJ@;_Q|th~Y *_wފ_vM?RU˖~4u[& Ǽbɦ[ PvxߌѼ=up25ԺSĠ \R[Km5$`q͍e~U}<ʟMp-ycS *ߏę7ؙ\olFvNMڢ~v ( UhX<K6^u[jfO`ҝzX ϦNh5w: OOyW:7})fOع̚=?/kI#;ga]1Z>hѰxEČ+z{"^U91w8v10 8*AsSu< ?*USs"NM3ϝcWn^m˯P2نhX<Wl-G&cQ70! xOFk";gahj]o3 cP P ֯8~&u [^ל: pb Ȥ_wv4?j:o4,յvPUmIFv˜rc|WcцaÃ1VM@+ƑѼ=ujDfVC)@1(`PΊ'+c_\: q|y8i)tGDD_ݼ8SU3̚0f5/HR& ǂu[ͷEdb4n 7@DSԺ&r=Q N*A2@hkgi8ON`WU3c#q]sm1ySw4#Q=6u9 cʍdӭh͑(fɣoNrq䅧nAkoM OXq4u P 8*IıŵW,O@8tY;;s65?fMyÅ˯J lC4Ēn+DU& n4CG㝞gX+7~B&5s؁)@0(`P$m-qS>c_\m-3|(Ν:Gc/x8SUZ=^,jg>DU&ƼͷżEU&FF0:vq@W]ymd sa9':(s3ZZZv ݻ8~i]6u9X+Sg\ohoTӯc8duM|c S"S3+up 8JW{+rݩs(QlC]1oͦ)R,{GO]#\|h]XZ p){nӹo8q {/ל .ߏę73ΛylbWn^mJ3kh$ip2نhj]9\wkͿ"bFdkg8<H]1u/25Q5y6u P 8*Q۽c(6u O?>(ne3c_H3՝돿m dumEmQSטD`ݖhۺ=ZGU& 1VM@ 88v+殼62ن9@Doba$Ny u P 8*Q* Nx WE*u bSqOh)tGDD_ݼ8S5uKTUgⲥioyk7oQ07FF0: Fq䅧nAkoMDDk pQ 8*U? G_),_\p8ʼn8w\ 6vlzF_ݼ)欹 cV)Pܕcɦ[c*Sc\`+;=ݬ:w90Ueja8SS2dPơul I~u}_{'u@DD\)_: r31Rwv46zcm7k~ ͬmHTϬkqejD0iLocb_LMֲsF̈NʌAM kѼ>|x/Dsc&udG̛epx?:4^g&YѴxل 9Ѽ=Z>h͑(Fe`'5 $Ӽ= 0.e` 5=CSi w\幩3 gNqɮ]k1 7'e"fh(FR0A}}_+LMV2نYᄒ/u P 8=>'uXtVdp~;P:WǢy3SgPa?CO1ef;s19qCSYKd.:`:dbʍdӭ1ouQ1.P!N}3}}_4FKSuMz{H---RG@9yWFc}U )>??b(_'w_E3@s"NvMߡn^&4~,̚*|x8JW g e ▝蚛RR ľwzm@ՍRG@9rm].̤ڪXtV,S'b3X}h-KvG<: eQ۾-z7E1j 5fJ8ԡ"6ve/SlMC\N,2eפXp-cKnǖڧ`w(NzFfz*NuxS\4l}066LPrmEntOEÖ=Q1b)}1q?u 6:WmL}&Wȿ mSX/N?:cI578)WSDž ?vmŬ~]t"׺)u ,kx/B>u H|k7Xu}$_+;]%(Sg J8s$5 kHVY&qH`0(aoת^: ʲx׾K,17ݔ:ell|q4f\x[?EC\jRy6uEmh{Ѹ}_e1q?fJiLzT-SU}1q?u 밹=wuUH"dP){1uqK^ރSmsZ>7rm1S*:@ƅh(/аeO ;`l0(妈_ ŋL3''R܎-Ooʲ),s?{)f/ϦX2S1x"v<c9u5njFˮQUTO1p@4lٚ9eQzN3(P)>~ܳgM8:XGKcEɓS1msmUq"v|":(TNpM2Um}0R1 C Lȵve=gb| !2pvuIUU;||Le_6J pQ:;:c٪ϟ?X*F<: ekqhnZxFRgXz02Nea˞8v.`e:Rg$WWw)"?W:`tXaqW(er9ץ,\kGܱ?Zv폈b|V Bow4xGe\)d=I$bPLBKcEVxb8u H|}-_~-u+cQ<5:cLO3Oƍ1\Ӝ: erѰewQUxFRg(p ; [D>u,M?S t~x:޻&jseS[WGDw#Dt >}Q\: Z;Ѳkk2C1S*XfJ8XTշD#u, [~+A-qǶ=kW&㙓SDvlo>t[ V^.O>>c8/l$EvQݴ> #CQX.vGad(MBY&qH`?zpM Eȓcd`R=*Rј<:Xd{0Jlܼ5u +d#mo?6uEDD~/q ѼQ1V7=gb|`0:>{VELE?ũ)Y+u5SXA OOw/gdb'`iN0'Eq˾"(Sg,[p ; [D>u,y [1S*NAA'kSg,*Uew5bM<a{lhL 38:78O>F_kg*WNelm[>( Gad(u4S*Ǣ%rs`I+d#[zS Ġ ܠӱ&Wwlspg]˯ dq6u0OtmN 3u_˧רϟ?X*F<: `T7Ge(ƣ0<.BowFq)Z;btq\X! 8rro;\ *]^4*ː1RZ>K3JϝzF)S\4nmwٚx,e%?zy;,^uS ̑qfQ+Kh4Veꛟ-ܑK 4}q:8:kg5v<c9u*d}[ܲȵuDqlP1?~t$6lM}X2U(ƫ/O320NQ,FtnFeIQX~w4`<9:봪8O>F_kg*WNsMrhٵ? IDATJ( 7(\ϑ4D#u,Ibt!\X ,ўB|XkIQX>nJ 5sy6?w)f,ygUxy(7`Tqh(Fad(JYKLz#nؕ:M]q 2fPdq6vOW壽"6WNHΨ ,}dHɸd s'ރQd歩sEY&u▽FU}KFNپhز'2 ZdrQVW_8:'e`׏ўBTDL$eLg/e'Tl=l5ͩM#zmR!S',YGÖ=ʥ%}[P`rfǙRtvTFm,u@2WFe~ГSs`L`h!& 3G1lvFru$ySU.w-G0ᡘ)Sg,9p}]-ץ%%׺9=:e`+ܜMhi1QXј ¥G1}q:u >>c8/l$yEvQV)2hTOȵv%#[SqS)3()ėEqWWU$*ˌ"&W=޹.u ɩ,N]#3=:S̫L66v{U-?Ņ( ES`ɨzN!2dq6+򱦦u xdXl/NRgتD<|6nI.-w쏺M]Q2,p #C ǣ}{dko_'[SqS)1(șRu(u 0 "v%*Rϙ<ßd5V'E1\5ͩDY&u 9EY7fjos?:x%b8'+R+R'̻ʲx྆XSCݗR_?|s?.ON` ϟ'X1 S',4ą~@ad(^}xԶolM}X2٨os=GR7 ,13#q-Ѿ.: `޽mG.]_?<9l|7Gך:^>r.{NT 6nRy6u(d}[ܲo>2s=Gv_:ȟ틉SdP3CxP>~W]۪6W: `^mh?u|4p#ʣ˝}uSMM-Dw!uKXfz*:OξEru ݘ: `AZ; R1>u(["ڑ:-{b؁)S ,q?韊?:gJQiXX֪*4ŚL꾔:[OoթSWK1{y6uDұ|qiN Q*GÖݩS`)d"px,u Z#_ө3X/olrŰ /8pUEeIsݵw7MKs`Aɕß|K|}-SM_/eqhb{02S1ظѰ "hܾ/2@mqGG2=;_:0bDa`٩h{vwKI0ovl_oۑK#/΀ecD^*Wڍ2,7EOL: `AFGÖ=3xVL6[\ϑ)aPVl)ėźLnJ򳡭2>;-s1YM\s#k}zKdRu8_KohUq"nXt >51\Ӝ: ]vQV5,8p}hز'5s ȟ틉S_  있ǚr2tZLG9pO%>)pCƿ}9&ON΀_>>v|".Fru$WVR1njOI5l,be3:>'hO![*}]&u,w)FFKɉIp]vl_oۑK7dl RړahJǢ!.n4,HWeRa<}ĕQȵvd2(ƫ/O 2:3TG V]M& K'u5ާND;]|Ѱ erѸ}ooXXQ.vGad(MԶo=QJ2teXP):;*6W: `N]gwmlaQ2-w7N91sy6?w)fR3,e6uEaxA2`EEad(6uEY&:ȵncހAજ+3C׵**7NS*nђaw[|趸m)0g'p:aur~2W_8;aT)[SqS)/0(\}ҁ(#:7g N]Me^l,V5xoDUeY33gcsbv*u ̭+2mOG>kS',+2U-?x$ySǫ/&׺9dq6 ڕa?uQUySJ1.Sgܽ6WgZ:\DNSgiJ>Dt >k7&.Xx֎eYb~`y*\ϑhزǨ +NY&qCSaPnWe~d<ԔIs,]2FFY,skr?>ӍQUY:ܥJ]>>nX>y8Vc9 Sg,mvQV)24S*ƹ#i\kGXPU"/&N~ʠ pFg`D|Pް ܺ:>@S|M12Z&c8:e]͇nwKɸNVUʼn<ohȟu$X8elm{T`_$97S*ƅo1*ӰeO ;`H 22,s-Ѿ.: `^dn[V#Ҡܘ5]ƨ^g/e\m_OUiBY "S{q8IsBowFq)`2(ƫ/ODMmmm]]U];R̻&O _gpM}o}Y]:`A=D9>sr"u]qx ѵ:u,gbL_NK֩Ć;3nL0o #CŅwN3\Ч"׺)u ̻Ra<QJ+A \YX`a`E?j|xip2uiM<]쩍{w71q=:\Sjgo3NuIsntOCK0'\gSgePHʰ k^?1ӁѸNě{Wm켭:V=kcC[e$XŘ̗3Z; ٧x(J|9q{s3`= ?N+A`Qh_}>~7rSg<9O??=''R'H?;sZ: =SU娞.Nc8:c`k}+RV*NjrZ9aT02?4 2oldl:y~2sX1ut;~r( N!FeX #?ؗ:V2vWWU|e&_>6cKudbmQWSh̕{>Ύ}@z Wf~v`f`(Tt_kg8qɱ2* ɽ6QWS;o[*cC[eDDܳ6Yxbϛ~dǁ']Y*`>\E?;:s 0/ #CŅwNn֎O`z?g::V 2rWWU|u)+ώ\qi4'Ͽ&;V 7^oٱ_։ 3ߋmc PTVlj wơ;܈=ER\\kGtǣn]sx/B>u e%c7,H}__sߋm'86ub|镸q|}Se&SFݦ9L 㩓Lȵv9kK˞A`Yxw2t`,ňY2+ϾuWoy.UTwn󕵱}앨B`ϟUx)2TU.n`MS1S*NjzdkT)l)Hoc-s|/U7Ʒ:#;3LJyeqbÝ1V]:X6vEs׽QsڅȬEm)0gjoc <2(,;e/Vğ}(NNe5xݦyr8csqI^REu|w8_Y^$ T۾-?&.9R1?lTev8#Q*NeŠ b]9Sh_I$}ź /U7Ʒ:#;3LJoUq"Rg+TY&;\[G:,jWFeLU.u\L6[\ϑ)V3CxPް uOykꌈ*3kMqp4R' ZuS{Θ)Mho7U٧-{"[S:[uS{ˆx+e~ʰ 쉗Gj IDATSgKݵ|eml{%*fS'W'v'u@eѰewm`_éLz`ɫgMˆA_`X<=3KՍLqw5-q|}3^WU.zM#{R!2,\ 1ߛ:2o° #ocSgJSexf8^)nX$W88֙:m슖]#?x* #gTcEU}KZ;Ru]-R1u ,ye~+2?+ƮmUQ+KӃM㷧θj*kD22~6*fS'oO2UhcdVb9ۀEBoQL65 q;u ,yeOƙRtvTV?}'[[MQ75^:Zo'v'uU۾-( %FeXr1rgnAeщa`E;xrC|K`TY&mޚ։ QWHD#~$kSg\LU.ZU-1r'fJI?Ǩ KYus {,u,iea`b6u ;_YnꌉLeelTNN+u5˵vD۝ą8ߟ:\P4nߛ:I>JMKAdXXI3OVķ:pFR3vC?Np2hqo:ՓcTL`Qb:#enXO8]:eMeh[>JTO@© E<:U7G۝ą8ߟ:uFeX24ą)$ceoc-3u]򅨘N\w7#de,F#^=y]ԁEè KQ#FNDad(u ,9ea`9O<(NNY57ц-h*΁ee8yt=u nj; 1q?u@D6*? [DYƨKCU}K}P Xr 32r;֦XPݵxPTOS'G1\Ӝ:`ޕeѼȵuī'L{ ǣy;$TկPRbP`\]۪2{S$24V8 TwotlJKRn]|m?ܰ/ʣ2unj;0^1?lT%nSW ;`ATd|XeEO틳cSg$5Ug֬uh*N%a<h#߈Sqyx(/ɉ.T12R'̋L6ZU8 92,%elUdN%㦶+Um,~?6jV%O6GqoEߝ{&3p,7/uKoٚkz\Yy&*Vռ_GDTG** s_T~&u @Z;b>=" O? C3`I0(oO.֥X'ߏ/>: ٚmy{lUd"Gf Ѽ*Xlt??9P 2,#{Q X ,"e 'X~XKIMgܕ:T^\}T B/"?ؗ:XE,rR~<.;u,ze!2\126eTE02?EϠ "fX`exxi`2~n"FJsr{ڨ)U=kkꨫ)bV/㷧XrcRKǒEk[wq?ߚg4H%˒-lX^l'76 4Mn6mslg)wOn${sm q4^HJ!9rڢFdْkF= lYxfy1 z>NPCN (?9f1*J0+ @-ꩁ=50\p֧̕?oN#S]'4r_(S*&?UZ&=yU!}3(?|N}MgNP@+s1 e0,Pfz'ȓzdI1}MR%=.*u`euF uGSS C2)Gd:@чU!NP@;?XgeA@GHhm:L31lѴc]kPk:>>a댪3>wjrgSeXsn\SC2oڸCA'at{5uu Ũ ݡ=wx^q\ywIG];3cm *Xg7|3w2-џL<99J7Puv6bQUczWԓ1.xcͽ[5ذNsޠuyERkU(_(uWՅc9jbչjޥz(CDZg2P(?SE:1딷X7:'Iqg̸hJbQ5wjRu𶆜μGu|PC-x|I斖IfSԠXf5!I5QPE1eGSSd/X1%/ܑ~lQ_Ks)j[wXO~Gqk2q>댚#*\tSIҜ7xkթpuNJmܡ 'R0Rt|׸:PT?{)9;TgSun92j+hkWP: fTҘ$M,q90 puF8IVO*A ;Uߤ\>}sM:ظQuRY+yE 5 E3]Ҁ (łgP"hku:/Ţ)@Yd2K[ mYTJyWO~G0"Pr_(2,da˺ZFyz:YO%7T:l~uчԉ)jЦOޥuޡuP6mX=G];3cm *X'TJywI?vǕnbP}m:4ΨY#jڤbQr;Vǜ7pf7kϐry Œj/U[:qv%7>ԯP"hku P"s3 eV w10*SO3jނǧ r֨gUu/hz&lܨP:yIf3@_߫xg_b2(7TN *?p; 1(5aVi1.Y~[BA7_:;XK$';b\J4 `F=ҫ:>u*ܤ:jݼbPE~Ts5wu¨ MuFuPڰ~W}֨uƊXumINfC3p C ;17xa:engF0*rȳXpSS $1,p>jlb:c<3%wxZ}& \!g6vyY9Uߤ7n?yNnHZuZM$3 (['ujnΟP#@Z,:1hd2KސpGBN(;_|߫;bz򛛭3 fC(Sp~a}rY\Y 9]!gN4 Z' Rw($3]߫fl]J_a @?'Ǭ33 2ovrd^;>E딒ͺqg:+ ,SʝN>ͳ#)X!t*^ѩpuE&y> ,ї/ODd@9׿w[gf\pgBu ŰuFɬk jXAFS7Yg`ȳ ]\7ǜopA,\קLMpE >|_NP#@98.M8l`PpEȼ6|uF}˝RX!Їu|"nrgOhu /\!T],gYgZve 3^qTܢtJ(~uVC/l:3A=ܬ9_Psg_*Z'מNnlHmթpa$'ݡ@رemVSn]8 u*7>ԯP"hku jTI(?5u Pr 7e>uY4.YgĂnSG&hs)X#ilVJ7|UNZz5yx>%7Ne 8 U3*?5f1*k^o J좾Im)uf`l'Gujt:?^ dmnG];3cm *eTf&tR;>\-NiXO5mR` 1뜪|0fUNq (J5ubP:@:7x@ݻp)1DZgJA@ɼqX=W*I,2<( 2A]-j7?ݡ%3P<>nhשpzg^hT5o{uV c2jQKݻts*s9beT&Beki`qIx@=ЗՇ?~Q[['GNe:4c@w_{uJwZ'`x>%0&fE[;OS|}u *Uguhϟ);u j̆c$mMg z/yjkY'\N2*#IF[kܤ@Ztr$';b\SHmթpuVP0Ph<ݢB>C9bչjޥ@@MXpp^g_Ճxj`:ۿوuÙ?n]:.NwNw>MKP:@*:ϔ}:5w:UA@82?s^qa2ƠLy n TS&o=)`4݊vZ@YJ_am %ZST!FePjPDkw:XU 2{h6h78ܬuy=ʺ~ T9oP_[)@y>v+սC@uhkv}NP@u;N@U:su2[ԁ߬\Wں!`: Ԡxt\F3lAu.g'3ޡM iZ9IkYS/˿TΩM:I[g`RJv*kN9͜Pe Pc.uj/h|:X ޼ׇe>Ţ,PCyywIw~,N\>r^딊\M k6H泓5vc:حW/YTiXN \o ^9y~H;J5ubł ǞS[sP墭]:1Ԙu T׆eљv%q9=B:ܸ3M3xf3*R0P,AP}<%77S'Gy:ظQ98nSRMex}rj/ȟap]jޥsj&±5oQP"Yg+A@E:2>,Ӟ+`C)aPPUΌNex+"t!ל_~nuF +?yܢ:"9Ǜ<bI g'T,t8N7LcT ;jS};(vs6+҅XpsT FeP yvgP5T2v:,7Q IDATP2/Yge}o^b0a9<^_:?W$Ң*֕iQwkՂgR<^t_`:jZ8զ]p99UNjnd*Xt5ub:X LnQ.}r]i2`yeƝ1ud5kKz腍+޾iYuBф泓Z*V|M %)eiH:qH&K^H`ݪ f'sT󧕟SS )R :RPԄywIOXA[ErpMF3ʧ?bPH}[ZT$Dz _^dF|N* #$'soZc-5!(_@|T1eGsT02X5_@~1(9G];3cJ%8PУK5Nnk"5O\q댊\|~:Gƴg&uaYJ)e%\t5`:jy!5v*ѱ!M=7WՅc)2XM.>90(YG]}燳:8W[گu(wuuz 늲nhBMlΨXhBL>?Q$V|NrƉ!)eg cՐL|m;(i`H*LmBN jZ`5E[7}UaPPΌ@_V)hKW: Mk:x$ݸ3ƠL\uykR;Wq<BrZZZ\c9oP#7y:=ڪ#+!MqۮQ XBKݻtn2VDvtXDZ.TPES'NA~dQ`_V Wi:,Pnꤾi늲L}mzt:bEN/vTآn~UUFB E6 %t*dR<^[._: BNB~T NZC`Ui}:X6e 3Ef e6ӼdbniNx:fM?aQ<^]xJp,"Ɍ<^ܴWE[;9딲Q'`F댊 کDiy~$*jvOkiUQPE1eGSeaP1.`^m *]M@y =wuu 2%sGW XT5t%=f ҠPCRnnF.O#i}huJXK<>딊N*ۮQ P'_ĉyVP.Sm)"LAż#îљ^p%S ʔmNΨX@HT4V44i(iXszg^N)#N3ʖQ,ݡ*HNhADZC)ؽKzBQPP v@_VjKFO[bP4O'ΨhMcA'`4줖Ӗr7(Έ `x|5oYnvRaN2*k۬ܧB>g\eX%G]}燳:8W[گuXG7u)%uUۿѓ-޾IHue DTOhP, N􁉣)KE ;5[o H2#C[TofDSjCn:Դ?!guUoH)Zx&5v)KXgj@S Gu؀u 6wScj:.ڥ~I]1(@Ne5[ uY`ܺ;&SVUCԫud)U_.3*Zr3Xǣxg&ht7k s)fꤧ5pwnL!A[nL+iNԠXfidGu> ]1(@up0jvr5o5i]NY5?6ۢUg'XgTpUNsuU"ol uU;ICG3̤Y=ҫ:m6 t(ѾYNsBdE3SKL.4P?>X[e >-:1Ԙu ȼ#îљ^ ݅ݶ;Qo~S:jM?aQ<^6\:O8{~ESk%II㚫3Kz#%vGZ4JXg.M(((RS8զ]:7xQv؀B])`DZg2#î`^uuuN˔n+ף?/wKYgT]?z. ] 'ݡP,iNBhBZZZY!gvNP0gbbvc$3jXA͊$3 : d'$ؽK=B>gB3*J({vXsO[oAșTW~uY m&u`Ռ0&6={:mQѼz3V/XHjܴn:gَGҺaKE딒[xtrxb]#]f" j 8 U Vk.7ubPݻp)P:ӿ:x[ Pfr:0pQJmibQ @%~MDSE=B:0&՟ΨxM3VMǣH2#Ia-x|y:RμgE3M((lܮƎ-֪>ެ/X:+PlW0*eO);:l\2ywIڳwFg jOJxeuw\q0&r_rs5Rr%t FOҢu;I'Rne>/^!gcWhB(ZEaǔx;̍9*k2~T_:(ҙ%1(@82;?^mh['pΘez')!Uw>' W)+v/IV[\!gnhRR5`4u[tpW27qEx˶Xpu؀̨ /U!!-œ+9=ؗUU{ڧ`: DwsѶf6Nz?;ѷ~:9Ǜ3JQ$$g+gJA-x|y:.:ظ?/[y^4 es`b5>-\MBNJmibQux&Yι;IJ7SlXwr^딊 ka*$&>Ev5mW 7W sT'MNP䯞K+Xty= à n]љ^%})58>=3ռd$IjzQBAkK}ʔcQ:{ [gUآ٩ꐳV7N ɿTN)pc-ZO DJP@U(Pu V~jQ\h<ޣ@cP*rd}Y̫N[I%uNΛM6k5aӎZ ]!%'aQ6<^*p1ksYA-x|y:dc:7)k*A'Ũ eˎKu.bԉAu PΌNe:ml+ow|SqgLO=7l?wЪPScײq})սSuwS}Y@HnvRKK9x$J)%q*ܤ;~L}CJ k6Ĩ 1ubPDZV`pt*s)$ej3Ejvr # u[a׆dUG&›\n]Nx k6($3V (ԐT~fBKłuλr(PB~ƒX9.5ֹZ,9*P.Sm)_@ø)2ԀywIG];]57o>iݸ3&-I_[nzuIҟ&ÐoLMx`eG_֡=B>kBQm콊vZB}t{3euG}ꖨֶpjjÿ/4=[ǬՑ ⎷ąx;9ׯO}wu)/ܮn댊3Ѻq}e?9o-75(60*`]{ ESP!~~OYg1(^[Ӡ΀u @nҡuFx}Jo-y"/&^>G'G'GXU?Eg[nVݠ bTWcunP gup0:mbXj|=댪oߤ`: 5$fXps.iY'*\,Ͼ0_P-;- 'ޛ4ubPnv:@qrj: ڥOY1(XA`_V3%mP0PgPQO'Ψ hBk3T1Dَʜ 7G3VH(!g[nobP@jv.`TɎ+?5ƨ .K(3Pok&yuf]AŢ,snR XTTy~댪Q(Z{Q 9oq>SjC:J8 o=iP@mXB])(sDN *?Uu1(.ˑaW{`^ Q6qsI댪kT}:*u/ÓE["R:e-xz:-3(@i1*`Ƈe %:|uj2+9=ؗ괱ݯ`: lC=:*x!5uZgT7R~uʛ,x| %)+n<0(@`TrMTc.u X(ѢOY1(e&uY ^֮bQuq})UW`uF  %ԓ}U)w:eEEz4-SE6Fe,bչ]i}:5U.ꁾ{i]z: D+?٥N v9)d"ɌZ6W:M.0/q x/ޫhku Rgu{TSP):58:+9=ؗ괱ݯ`: $;uFUx}JvõJ*Ԑ1---ZHAɎX3ym^PXҠHPu؀u f'u؀,0rB>gà Xq3Ejvr^_зXgT*v3jR9 9ks93Դ?ۊ rۍĨ qrj:e*hQΟN@ aPywIG];yiKWD\_zzEuJUoH)Ψi8*3JG3V7|0ۖC* 1*`y*sji2k߬3{3PC%qfsz/ܒn(*9ׯ/>[g @קdW<^uJ+QR]NYO'7ePF\E"FXC %ҊvY BQƔN@Xrz~gR>qJzyklۿ]'U#)_:w!g"I4 Xg.ZgIPD?{/чԉA aunP gxBAtU CbQ5ф훭3B I]Ңi˂ǧO3vzoiiQKjv.P!_Wc.K ESvt:5A`dQg\WjKz񉸾r^딪!oKONHZ;N( l IDAT^N*#5IUH(RW=ug{߿v?o)lKb+Nc;v(I)73 ft-mig.ӃK(mܒ-=0'?@'DGI,ǶK$kڕV_.-ۻ^|3IFz>X(ޭ>  utUs: d]>t~1dR3m] '3pHL^\z:En=fqUFb׼JQ>@ oQ+!5=Q'U.5Ĩu j2*[c=ޟ<m+XgߺYG5Xg 8-[g`uw1kiոؠ$-粊5wV\ 2.Sc>Th{3PU--j`hQ<=ѱe;xk֩'^٦_Ψ)M~I>:+U1v]_~UiǕԠJ!`4)'`Fe\Ĩ{X8r)e&FSPk’F]K<XguD[7[gԔx["V \׫І-Nhehֱuu+cqAIG '+VQ+=6PUѶnTh{3PkT^t/-ו:Zţ^,Pæ#S-Sj?SÖ3p>rM;Nֵc\ӎ+AŌ͝x'ՆQkfdP] %[SP%PTԔ2)Q 5k]9K訫zG-uAmYgԔ- 3p3g"eiÕX͠$9X:;zunx@Py3GU߳WX:U"ޭ> (e@M893z?#y Ē)0m`uj2`][rWpN::*jk: 9t|8tuF͉u:e).jy1c0Jcfk,c(h[72Vwuz:rBQRSLZF0('ǖ@VgήQ<rdI<:15l:kanR+z3oɝ7-{UB^D|`@)1*`ΟRMNh{3P#xts:ؗQW:ZVpX{#S-SjNӶ_bcx Œμa0ۨf/5OxCj@DۺeNP̜r)5N!'U.5Ĩu j2qrlYgxFxӯ`cJ(gnd:ۺIZg~: 3T;M3&Wok,C (=< `U2rQ;vXP[} B:[ТzƧűpRJFg.IJxG:2lQs\o#XRig"MuvDs&ܨmzenWM^ U{1*`UΟR[qBQ@IxW#֢GsGT:uq쒞|vNAZJBk#uO\B,<4xeuF5?Ns#/Xț/C?0bFb_&6(Y"P)C. EuT:Fr)}{3b(-j`hQ=zASymXgԴ^sZr/ySz;3KW}s?_ߞS]-ae5lB?.댚&a*۠y*~בXPolリĮܜ͝xyZuX|.1xu Dۻ5>g5AJgZC^T^>u8Yp>'BP;f?xAų:ƒqGۃe @MO&N9^m$o*Ш̸VVLQΟPV\4^uՕT g&_yRSʥػ:PTԔ2)X(F]=֟ѶNuP|vNc:~&W;_>Gu:62YׯOޯ c Pz6Xgx^9:-MUeԞԩv5t0~ůx 'KX* EU߳WpQQu[@[}X(tE=u xMRiԭ)\Î>)Xu3*yWSjyN:J(ujXԔu e[֓Y=ޟvi֟T3 d={jT({ڡΨYNE6Zg`pa y<'u5Jt]9^Q8\"P mʥNP̜̜{YBVMo5A*ȒpNGub}FXyK]֣fu޸Z9ur6yuFcje5&PA sZ)+zHn=H?o(E#kb!Xsg @hǨ KLJ)֓PE3#r3s)XCBSy\FǖWSg7_X =4' MO&9j%?h5*K*;F:AI?4_9+" mx@-i.)ujXnE:SPA^'A !^t3z。;{C3l: 0s*պ)=__N֕'Sel\m]cXm] {{:XyZtT:@;ăL:z{JXg` b鹂 .G/h|* Q:Z,"N]~+sWBA>(PY'=S_ޡu%;wo*ybIE;tnx:@[U԰uejɱe=9f jwԔYgW%}NXg d:mNjg_^lQm]kh@ ƒZLMw+vHn=Hrw~FM%=3M ZiP(٪AU,ujXnE:SPѶ::&ej̒FoBA:[4}OĒuF~7[ zS+#ۭ3j?SÖ3P μQ;NP{R*v6g:d#֭\jJQU!Uj Xp:5l*Ǡ @ +zƧűVgZgŒWw: og:y}zv[FAIRfbw4c)#v=װz}"%?T}Ljaz:@*]FԼvyu,ڶUg_|Z| AuQWgxF:Zţ^,m_ׅL:l^>[ĵ=hio_>:o^ qXR| jOTyaFbהܕb͝%?T:bHn-nfN 3cjyu 03Ĩu O 3cSy}Kszc'73_/ĒuFoX'kل>o7XgԼHC‰& {+zPb|S1I*  {PN(jo:=Z'byz^cű:/딲;3[ĵ=h9'gS)Sj?SÖE ?}^GbAec?llI9pT߳WT̻9T԰݊4uXPTԔ2)RXF |>ƧYX)XgT̟?u0&S^ͽEeۺ*v߿҂/P]e;[z>.Ѷ.m}}ܱ'TfG(:UXGzE=?Q0N:/딊93[ĵ=h TNsBF Seg*3uԞKiLYRǯh:/ْ7|P}mrQ?1dJc#jyN4` Eu 2x[Sy\#OktlY>u(G3*..螻x'd:Eڴ:TPƮѯN*JJzy<^5P};KM)31jJ995N@b|:UA\ҒF]=֟+huzPc>'t!SׂO4)cx;Yׯ?x6MX<8-~ mܤV ߵuiOT\W>_dgXsgէwfFfSTĨpT)(PESʥSPeeIgz~8}i=?Qg`c5;CiW&3ljQ *1&S9^]ra@WpL '*rߙHymZ)yC'ZKrŬuPwޮs (ZRO )ѵKdu $lK2 OuhpA<=ѱeyu֨O?9OGeSPX_ҙ7>1Ӂ/j|ֻO}g(maL͝ '3Uy࢜PS IDAT)T>ѫ_u J i_@`PfƦ{t}o`_Z٢u` d*/M*:,NI댪NU$h;~u*ұ>`2ظ@2ógSz$d`?T稡{upE !\JbNm}}AYgĜP{Yg 0(shpAv|i\N*˜ 1ۺ3u2Zo:@;J@m~Ͻ  j3E=֟GL{t :#: eqe~0&c#Wp:*N!댪R@mP^(PQ0(al*ZZ7tc:ؗԊGK @1&c#Цv y}7]gPP䄢)T>ѫ|:%q`A9cSy}Y1q:ؗ|h!X'T3 ʠ1&c)Z d3uRD3Tԩu/Xgm]JleCX,v:Rs -G/+wYlu xpܢyj:j캶N7Q#30&Sa^)@I64*;3Ɔu%3@ %[䄣:b:@J(ޭHSu J$lK0Jiti\N*ݺ'nPU.89G1 ]@y}m]k}PŎ=r) HbNEۺ3`AԜt3ȁ)уz~8gKe72@-;9ǟMo$6(KZgem?0W,0H.maBo+>`ڸ 0b#rYrWڨ3z?sy5;jJ&LA3ʊGswuP2؉4i5۬3 F7(;u)ǫv PN@^P1ZBnfN\V={SPѶnM_\:*el*ZZ7tc:YOۓ eLƀ?S3c6wZg Ѷ.mOXgb_Kߴ@l~`AK?yc7t/͸ Aݲ;n߬|vuƺ9jmTTK^c&4ا>h|ae&~dh''@b\AC:ؗ--K>ţ1TZ"ó6;w7YgWW:cj޾WN lTP´u 'V]CuXC{hfdPnf:@*]FԼvyu Xp:5l 6S73֍oOjS[:U^}q:u+Wp:0QЮ`4ifzo+31O?lظ 0_,;`Tc:4eQ0NiOO=?w'uupٲ_Nu+ܩxf T Sv 댊sa5[g5ܡɗSTĨBVEۺSpN@Ԕ2)eU`\rnN?י%3vm.KMG&S֭&o:0U,f/XT\A/pB#N [RSê٫@,im`u*A2y\&jk: l&G0j\ }ǩuʺнK: ΌkehR1+m]`Jl٥ԩaRS)P1*=6杷spPTԔ2)eprlYOdu/ѱeya\6/W2)ے `ՎL4oŐuʺ9j-?hT +?܅i딊bP\:*]U̩wu j~ T2@ ,+zme\޹3GB`RQvpmu*o'[YkfHLKs*9딊aP\ Psx[Qu[ -JV.5e2cP(1eJ#=ԌuJE㧻 z3Kzh [g{M 3Z8?aQ1 JH)uj:@JV}^bI\!'չ 2@1.pu6%I7.Z:קufu/֥XsuP՜`XywQˋ딊`PBb.>*]F~Sp"Mau ʈAB2ȱ~:gRvM?|DxhNY" mJl:XzegƵRN)+QuuuŧU̻)S>U}\!'ȠuʈA2 fSq}꾍:2Ѥ?u&3u)?SÖzS5je̜uJY6:Ps&_NPc#w+a+J2$ Pո|vEu@UsBi-+9eѥA -=6n[Y{pLM=9)%=B:l@APRdRSTLJԼ69u . Xp1(T\C^QW9kBQ[v6ZgIsݭ/nI^]ra`Mra-MYg 2[v)ujXTpx[ D۶=j2aPb'ǖ9ǿu #3űVDcii~N7gR rItKT1ZBnfNP.5Ĩu ʀA`xq QQu@EڨnKO?ߨ.;ݮE:DrSBF ` DbμaQ rqBQE;tnx:@JVkB\h{3P kOeuxpAKRsqnʨ̆O^Cg[ngHlQiuP|3)%Ǡ (HSc#)A:\'U԰r)27=W"2`ݩQ6pm:$e]z}u ~NMf$ SJ*hV(`jXsΟNPyWcj\PU/[gjϏ<ޟ5%}ie=w5hiM.[\Z#$D{~YDT: x}~TcB ƒy:7ٿ_^l7cj-AP\<^>G )%à xe&G0=fJ?xN:m`y:%  ,+zmՓYK#KrVG:zmj;?Hk]O6D}js{:NgnяS1e͌Ĕ=B:$m]ra NACo)̩wu .C*uj:%  -+:9C z ::jzzQu:ݵ?g45l3;{"?j􆝬羻[NusԳ[N@1-(ve@x":7<`Je&FJ*mUmՏ{:%  99EK)Ƀ`mim랻szᕌun3oWk:ؑ&̻tlu Odu 8Tps)W-)?h֑HSc#)T԰w&'N*xr)e&FSP xKs=?ӗ13?W0UGc*WwOh׵u:o)-+&?EBA@^ة~w2n:o~ ƒZ8?aqՒ;:ܡ'fSTbU԰ozu V)ޭ> 2.)-ꥑ%=֟Fǖ5]Qg`cpQ۷٢c\ew\_=箆 ّ&̻Xu ."WzV`XywQˋ딫oN (ѫ/~:@r3sGJleUpBQN +NUbPeYrWڨC z ::jzzQu[ N/ gt!S(]ڂܟlMjmb_N}q9^5[g?Sܘu F|-fRSTԩa%v)lN*8 Xg*yW#Ԇk_Qoꔚ/o<'K:,_kݤ[Kv&p%L4/ݫ:\Bbc͝~״0;aqEѤzv[gu:u*Jh9!~f|{U`P@Yt8]!ݵNwX__PZ/YW{zկew\7l=q}{d]ٽkS 6o:)|{*)-ܩ RS}2)Tc><`U|:3pPwu!mlqs.;Co?,sxKymuʸ~c2@JOHYg\x[m]ԫ|:@z{3p \V^FC0eTTckѾg!eY'g :r:Ę P݊&_ueiڶ[X:@hu*儢?P:lww)*R+6`dlu_guVI9uHNatê?`#d-.יv4RCZ 1`Cs#؟xHʅ׮ KG:oɠ fFX^ZZ{)?Sk]7N&ǩSθ)ՓOWb':7:hPRg 8qh?:h}}ߍ=gcj˝qR!^=%~6qoT/d}5rݛ;{օ)܄;7F:]1)7o}tGnx4_UA*swDNdsQ>g?L`PXuŇmxe?w O orotgc(y Jq;WWnrgnBWO>;::R7#:tvg#?%ugd6E:)@*M]ߋ|_Fw.Mʠ 󿌞|_[u[wGo_+j+En*@㙘4ĽQu&ucFGg&u p{Kzoݓb /ذ'VK4߿?hTپMqA`6ޞ;dז;w q›;ع҆,Pm94x9>9| dutfߨ}3#J4zu>jص?u _#..}~ :{ ~!o]菗{sg}ᮨtFuKv\Xm?_n8sifu׽>)_k}ptϧR;"JS 2u6r~=S _J:`Pv>Wwj˝҆8vx͝qaiCtgc(y:V׺?OxBn1ha6u׺-:֥JǣVK4߿w2LwrX(@X,~:h;h:溗bOBgBl20@u oNJ+uȘ Z5uWڼO*Sđg^NTa{P B4'&t#br=ugԖ;w q›;ع҆,ǐq7w_>rgn1hMa6uƗZb oԝ'S ZLO.6s_D&ٸ0uМZiL&"R3 -{cbj0f*#n)Z_M@{/;Zwn#c2cx:3,nήu3nX&'S V#uwD&oO X,~:h>7F::eM亗bOBgBl_N@u o_;9c2^/V::3Q3#4y*u=|䆷s8qh?:h.}ߍm3&Q[ߕ6ısw oroԖ;}5;WR' k]'_UӇCQuNb˜ ̺Q|qc /V vJ:hP|𿋎4Lw\aTΦNnJwc`ñ:%J;޺?7;w-`8 IDATD / Ԗ;S'J]߹?H;::Wb2:%""z.ߗ:[dsdA*sR_vKH7p,]xe9uJ9sg."""׽{b8c/%`5͔wGR)7%*~+).gLhn?:SSQ`>%[4|>0u6adn@m3~WP߽3>C>*w"n)u" ͘ pGGG|J,VR]#?_a~XR 4y*tN3oO0(|C66l3&-Ֆ;̥B;wwx8{\I\8vߞߐL0- $ucGK&'S ^Ze.vO䆷zu>u _ ޻$VSZFg.ճ[gƱswLJ Q[00Рk]-?[cܛ:5]ܒ:hwtt|,-T5c]/n Q-ͤNTelc{R)|&O+Q,?N4{/cFMl)^l Ϧhk3›;D֕:+z3S-o17/'[e8쓩3G#5 (8qhu [5?`-|<.u<*SgS [cSj[Sg%(Ƕ3f>^xsgݑԺRXgw66&ܐ~5=ߋLwϚ`T>>:h`l.:p42Yͤs:@c.$5roL1153wD /hX/7s|,Xu?j˝H'u^5;ZE:)@ZcHuw?:ϹX,~:Hob%H*+ƞ+lf/鲻u߾;::3S&S轨\ݪ3CWgtw{k=1pĕc?}4ucPU`|z`fG)zR'cxݩSh@ܟ:hb3oP^clX[c48L e"[ؔ:x1Rg)ex h)gcx!g -c>^xsgݑԺRР6 o RgMnefFe+zo4*#ߤuw=q(ua6fL/3_+ƞ )9u ukN3 shpi5Fe::3qR:'GZI4GM@D8<չ\ePڔ1nP~>gch)u;Wc&J+u 3w~7zST轨\-;]=kd6+΋Rg ,ž<¦)m㿈3/=: @2&íu/@)/Xq6ƆgS'mj>^xsgv94|o02=SP҇be;EoqđQ<:h`c Sիq짏*2fɰƊc 8K5__;|w$\*Ρܹ1FLMk qT,fciٝus0z װUK3qoz:h`<x `\|x   c2|)h)Ʈ>|[xql;uM*7% wB9Vϼֵ>o {h@ds'E)u @[::0(mØ )店bt{b8;K۽: hpعN}gWSgp N>TTΦXa{P wxTfRg=2ЈFKcc/h)uȼ6ywTj]shrظՓO-*M#Ϥ?>Oνz4h gPZ1E{)FJx!FK8K5`DՓ;)&x8_U exd{Sji&NO @ 3&CǞlbtcóĈ i}pSgpիqxԫ)@ص?m?;::eLV5VWf _M˩0_7attf;:U2+΋Rg h[3(-Ș $׽te\x!FK8KdDd1^;wwZ\gw6|VđQ<:h`l.:p42)mOz:mcL"󱣿+ƎX#3ڹęK9;7FљIL}'}2uv~t0u@:h[e6=643<: Z86ywvewem61&7hKL84:maLnh)v M)7d18?ZW$Pgw6|WOFun&u 2\:-cQVRg23X(]Z5uǑbG)6/omosŘ.N]#':R-ĉC3~>2Y?Xkg^z>>:mǠ 4{?C{x㥅r_\,-Au/@3C3Y&681u|(lޙ:uգqGSg nb'SgCi&1ϫZKSeb@)1V^J@:s篌ȼv9:qwu)4zu>Nz:hp~>rRg#4y*u@[1(Md>oe Q-fW (Ş_RRgb>= ԺR' n ۢ3:&0+΋Rg .7==\ `&rc2_f4 20\Me2_|b8ùؔ: &11x̙24L})lL@q{F`6/Nh{SBT>B]#':_ęK4L68lo1+΋Rg2РeLʱX>2+C3_283<: %te0B7N5љ "7%u -ͤh+~Xԫ-Ϡ 4Fz,.be.XYNn\RbG)rj1VZ)u@S^1p(l̤Nŕ&Ođ}mKG:,c2_f< ҅XUSluKxpn>6/NXs1xb!\*΂Փ東.ߗ:6۟oO4lߦNh L84:c2W-D4{}dh/_66^R4[vҕx`Ltمe::3q_L@r"p6,Fy2u@ۘ8r JRg42 v~t0uƪXY_XUS' c(9v"v}|flXƜT3 1U3 )ttf"7%r[3:6vգqGSgM`Gnx[ 0+΋Rg42rcÑNYK +3X̥Xq6ݵ(E{R4Ek}pl)|84j%u rcϥh~s5UdPk1[YBB,VZz$]18ܬƙԺ1]^ Vú\_]=)|ܨGMμ||t3ZAHdB9JPr g#"bOBDD"n)v{)eʮL{c>\,T7\*NՓ東.ߗ:҉QI4L6~\d Rji&NOв @"dr=Jb2l,S'-`(?Cˑ@)">Ǧy7x7Feh $ٝ ۢ:QitLy&uv~t0u@[8r JRg$2@&5&sʱPl,-S-,׽t}lfG)rj1CM-c>1! }Sg_w^<:%5bÑޖ:,c< XUS'mh(?ÇhsŜXJ+˽1UbWTH\|L24ji&NO4lߦn8qhev/%koc_.ty}DDq~kc ̮ DGg&uܒw^<ӯ*uF~0#7Bڜ2Fɬk2 \iP~>""rK1:PyFhX g.Rgk1q~c>`mիqxԫ)@~*SgLr yc3R幨^YYNX5cݵό|~&"blx6h]ST̥˽1Us W՝{h@(lcOJN>TTΦh)e` \X\,fci: c(3 c(?xg^7R͔T XJ k?` 2$@WOFun&u Fy*64u@K~xEC~AXedr=s XZ5u@K/En~W ܌&:RY Ɛ Q<2u6-?7=2M]a냷|lh.VnT&L|84~[~e`SYb<l,Vbe: VEgw66 obh|T~/~—nDD4չ [wwl.rۿy.`8<޶߻7ghqϤhix8_U aPV7r,fc<9p >= SV>3R<,}"[}+)F&On-9ePV1ֵP\,bi:nغ\_DOacV*SDZ䩈/|p -Enx=ןg Cir#M@c8r9 o}O?:88s534y:&pcFy*64u@/KFn2p冷]dԦ굅X,E4XYN "ݓ:6V<WbDunP M)]0:*ypL@ds'E)u @Kfġ- &dr,10DnpKDGg&u-Z>S-MG}apՕad(l}0u_ص?-?;::yd2]=GnpKDakp\/N|~0ρ/6T<_غL0پMWGgL laS }8_U \|x&OX%C{6(pQ,?N,#7-u M ΍}ShR^DiT2u6Q `|،N:'GZI4lߦx虣3Zֱ> [`LڰBi6ʩshPX_=IC(M>Se o24ӷL7u@98kx|~ 0um @Z?wc]/u 4y:s3Q-MGQV2u6u@ =ա7ܫGܯhI'}nAɐڵZGgw6[b}1::3sXc|TFelTf?W+Ӏ&veX2Y ^>չ)@{p>:|tqRg4-2p6,Fy2u|a3kg IDAT}pUu)1@jپMe [wjWDoS<-^c?}4u@2(7ahqϤ΀b`9tvg#?%3:UR<1@m>.sehII8<չ@x|;S:D]dd&7-u~xC3&G#MR|{e䆷rm`vqVMz'z љI-*M'2SD&22(lNX' nއǟIrW+3AdhB,bir: %tvg0{"ݓ:o^>?|"7ʸ̶#7=Mn;/J4'ypLMǠ |L6cO)VׇesXKTGϝSؘ:pm<4ypܼlߦ+3WGf q o}O?:&OđgRg42}~`fe: ]) FGg&ux 104+.7kbGSgc7Ϡ |~|0۟:Zp}\fr%ʩ\WO>z#[9| x)@:ff2q@&OD&L7u @8h*eKtVtC3;= cDAU>xLel$Ƶ]u /R<GI4GL2*Sg}p3 `uR-\)}p]Z@nxqSđ7#7-u@8qx8nDoS ص? [L#7h L84:i o'G&ۛ:z,]\O0#22SQ<չI4L6m^=`5&OđgRgM$۷)zh q٧2u6u@S0(@dsЁ.6W-gFfnP<ɀ^N冷އuw䆷ZđQ<:h"#?h EyM m-]\Mji2K+PN4|G12=sRi}bQ`E&OđgRgM$ž<¦)MZ2'ZbyB =wnlacYc|&OEeds1k?O4#7ehqƨn>3Aֽ?Lz,].be.._YUSg;}s`6i+dx#'2#M48b9nxp{|tqRg4<2SgՓ)l|Ꜷrdhj}ߋ]7lȁ(MJ41ġMZ }8}22ͥ3X닞`ttfR'k#2Jv폡}S 4y:&#ps}@ a w٧䆷ǾK4Ok tK Yжb]/z ':mT>oJ&]1.|#+7%۷)=|dSGg^^PcPcO,-bir,/Vc2: ZRgwʀ̝.ImZo(}p:J$HڸEnx[LJ@x|o@&o5hPl.v폡Ga냩sU_ę~9پM3GSg4zu>wGq&GԈrT:$]9%וh(n8{]*.r6Ţ,؋F ]9B) ^C$,QT#ج8k Ԙ='vlI&>`R}hHeh9RO<w/`m.bscsmINVrTgr6K=mݻKh1l)zVK4cWSg4׿{N>AZJ._Bߎ) w#x̦-IVmȐFu\S /DPlzµLh!_>OK4\_>t$?SǏh8eh)}ptJ>/߈xbOc6JmYV=[̹X8_e'@+mCODN|Nl)^mۆ{*u@S^ e:pCkQ77bz[[L*x̦-Y\ǖY^VC2ƓwIܡ/˧З^M Š -wu` W_dhfz{mזi|16w)& QN46DtIܦZ3GSgM{`(é3d9^p bP??y$uwƵXbWׯXGRM\(E0YꥉXAd9@˗zbWCt E.wM@zÒw쉨g à Mз3~r \(Ŧb:iK16K X8n`D._m>{G'uj%N4!9?ˠ M+/ODoG>DD{'37%.HoӖtcsؒ:PϖA,/ZLm Eî w䡯C3d9^p aP#տ'uk|#{7{هyZWOj>:iK1riK1u ޺caHAUg&у3&/ėKДϞzVK Дv8{;uݼq-Vfn^ =}s>r[bs4ZyD|93RTۿ\/t! ;cOǶSg4#1?>:!8g7,uТ6Jt'1R,V#2QNe";u xé3&ˇ6ySeh*]GRg"7wfn\w-FD|8BsiKc1:cDh&|!=xlzçΌ GXI4cWSg4gP/#yA\l.""bsbDhve1̏n_._GwNh*O>Rg$gP'Gз#u |{yFf>51bӖbDt dؘȐZJ._޽cۣ{gKqpԳZ LTjsb٧Rg$gPG|td|#[""k?k|XL{G>r[-R,/b|9uݻ?6,c3&C pΌ GXIA}ñ+é3`]xcC`&"bSg1s?3kp+aX_l)O4xh*O>Rg$ePֻw:p0u4DD[[ׯ{~ݍkBK{-X X8_) #Iw'GO Qc>: )24BxɑN-kRDD{sikŦΟw#ױ!D̏rԳZ}plzµXXCYg TW`<Mpd!xs2.4xg^yZW׮qƵ5o䓵b3Mm#2?p - :{PTgΥODWMcR d Аۻ>i}ͭZ|:Yܧ~/y1FU+pQNд کL٣SgM*_/<:i.سOH:v8dL6O@1|-}8"toQjqx౧woNտ'+S&-Vb~nQo`^, d9~qod9VJ}9&1Qۙ: ZB._r Ic3]qX$ 0 };c7:h@YOoośt$ -d93/Fԓ: Zov2V˩S&Tϖ"ܿ;u @S(nI!x\GAԳx;ΕɨgK6ZѨLD׎ ):b\L4wL}UW܂\ X-NXweh{mX,ǥza} $Vb|"j%v z@@Z/GۦLV7ꅱΠ :p(>H Z˧_7NNSN{d۔"V67:hRKqo~#-(n5 lHeHwؾo8u@=[&>ĥNse2R,nJ}931ȗzS'@m)h IԗmSqG[ba˵)ʠ vƞo|3uΪ3qco74_Db)u4|'8j\cՙ SJf\0:`] \іHzov2ο͘-tԗSgj%|U+ѵc_ |1&˩3&Vϖ{`(u@(n*:'G";u&1?> =Q|}ñm9а"w:hR㣱}pzR4|WOvFmn:u i/SGSGNN`ԗꅱX,G_|r\[wLNX=[r-XߌRgNѻw:p0u&1?> ˩Sh0{=ݩSdJ92:hr_>t,]F>_F^,`c(팁I:R$Vb|"ěo_I@MǛMqS@ QvM\j%_hhAE._$: )*X,ǥvTg&-NԗꅱX,=DGbhoM:hb߾];#_IV7ca:`]`] |@gKW_#k'Y-ƛ}?RіHIu{p`/dݻ?u@C˗zǯ:`]`m7WSgw:3_>_fTg&<xdW"_{OW/XVD׎ȗzR4\GleXSCO3Tϖ⭉׿{8f'67: ϝDm~:>іHIt/\X޽Sg4X,XseX3ROƟ{HVœvW-N`xѶ#wXwmȪU+ѵc0) +_5 leX|!|ݤMb~T\<|\<\c: fW/Euf"v F._H*㣩3&-Vw -)kʠ kb냏>E=[bLȪIY㧢mSGs9n򥞘hԳ)@˪1 OR kʠ wؾo8u .ťՙ )pVqXTg&@tK`W/\X޽Sg4|7~ꋩ3֔AVUog |O-ב:9w67:>SVě}?⮈9:bX/NXVD׎ȗzR4\GWR2\Ht -ŏ_}1hdJ$mՙLD׎ s`ʹ:c-Vw k~3&˩3֌AVמ{ߝ:Ox87:3l)u|.Y㧢mSk|7|3&U+ѵc0) )_b 5cPUm6x &O>$kZJ}9^Dt\: V]G X-N\u\lz"u@CjuDm~:}%u 0K IDAT(?_{&ulXl)ޚxNFVN5U+1?~*:[з3u͸za,uRK~fV7ca:`Mu}sW._/:ݩS`y!јg9DP:pujZJ=[Sg- _/<:!ybx8uk7ޟ:6ܥ4:>ՙX/Nd}%|dݑ/Uі눬Ztճȗzз3u @iuDuf"j%u 3(۾o8zOFuf"ĥx>bQϖb냏UR@ OǶ'Rg4zW/Xue#]!̏׿{8f'+0Y{b)u|.RO4ϣ-ESNGqk̖OXuemROAmn:&=k4X,ZDX޽Sg4b\0:`Uq=Ñߝ:F=[/3GcQjPgܥ)R'-:s.33]@+i/SGxvܢZ'7za,V˩Pϖ⭉W5 };S'juDm~:}%u "Ŋ{C>"/G-N 1]>:>iC2V˱0YЈ6u[ZDVDQ,Nh[ΕA~F._O;rSa :3?yv(u |Llac`լԗ +-ZB[C_?ݩ3!eJL3Gc~|4uFGc٧-Nݻ?uBG#VRg4^,1lz"Rg@ɪx:>9:X- cqQ,uƛ}?uBRtxpK[Cog9@B+xk(nB9w c#Rϖ{`(u@C(nK[{౧#;Ȫ:>g hAԳZL?R@D`͏F=[J]=/hnbpݻ?NIeJ\<|LtA-L#V<@r|!3U+SҶ#Sg4lxd ;֖:tx౧Sg@2YSG̑M4ј:>:w @gK3B׎=>2Cߝ:]=[/|ڐ pG-Iu NZL=l {\@s3(A=Qۑ:C2g ǢR'Mj|9=hTdr;OuNce66x X7dP6*@RݻMlRg4#@33(xSg-0$FejsR 33[~)u@CLp l0~`w57?~*Ό œ֔QRJtTg&Rg$WRO ;bP`6Dtv3!magFc+s ՌA`-̖_JS'2Dogl7:Luf"=pؐ QR=|!ubΗ#`PhVe6]E.w XuKq8{`TgΥ682=0:hAOK[@2(},Y-u-3*zݻ?uЂJ̏JTW ͠ @ݻ?w;V3#1uHd9wĨ з#@ -: Š @ ʗzǞNw6w)=g4$2ݏNZPmn:33Lp[ ~O#;uܶZ#1SQ9:`U`ݟ:hQR'$ePh6eZ}Qۑ:nK=[/|:GS2BߎȗzRg-h|9j%u@2Rg22-з3e8uܖSqp\>},Y-u3*ZhE]>},u@RCnA⡯N:3gFcC2cTһwE-/G=[JLW`[fPEl7j%=gl: zV׿_< *|Wj1[~)u@2];NeeZ@W`lzg Gu\-VуFeXU]5?>: |WOihr|!f'̑a'|ܴQVUPEe?: @0(vN:3gF碞R4Fe`5t\:hQ_1(4 2M{`(w;YƓU+q8{`d9M67SGRg".Xb%33ڱ'u-1(ФuP l).|,̹9Mg~|Ԩ   .>: |WOK=3>A&N?g s4CRg-:s.j%u@]>A&mߓ:"":3gGR'S3hr];^X;ʠ 4|'NQϖbH=z03RG:3:&ֽ @ z:`A&N7[>g h 6w)uM{`(uf/NXwȗzRg|*2MdwTg&b٧碞RzVGF=[J@6*HDW`OePIv `ʪ:>gt Ũ Tj1?~*u^ hteĮR'A͖O_>㣩S6t4 @MvI 4з#uLuf"ƞ}:.|.Y-uW9SGRgd]=Qۙ:hab%33U'P.uз3e8uH=[')(mCNt Emn:u.>?y$u t_{ވ_oDDįt^q-mZL^{0at{+dP:p(ulD\>},Y-u œEݻR$w?OK̹]Bߎ)Hl}=*u@mRL31?>+9|o=:)4b)8l)u V=`u_{hֱ/_w=7ym)lD OdPAv&u--ťbX-ԗ{M:Rjs67:ha SXooǗŦ9 FG@2(Р|ϝ* Z,٣:s.u w- cqo|5u ஈ&^I]ܖBt`忍?lz.C4 ˿of=`-A}p|aϿJ@ʪx?bԗS9,#V{`(u Rg-6w)ͯF[#u yyͿOgc+q˸ϛ{jgK0YN1eLog gRgТ.|,p%u 67RovNۮ kgŭqS ߺǺ~_x5x3] w"3>-u?kׁChAՙ{|XԳZV#Q:׽ 0[~)u Ř:o=\Ut_O*RO 1(@BߎzO>gt٣-uؓ:J̏Jp6٘G}\|kxt6u |B cPAv ,L̑a'lgL@wxX㣩C}?uƇ:o=\Ut_O0uhJ@ȪxG=`cH P9K3MnNu.5L,h GoG ZlDӱp:DGc~T TP`-:UtH u߈?z_l:>T|!u0(Xoglp \mR=z(.|.Y-u]<\.u#.Η- ;gSgܒ/uo >ΦNuؓ:gHlׁChr_>c>ՙsShxOAG`=ԳZ,/OK@+1uH PGS'l |:}\|kġvNeɗzb3hBl).|>=94-H@ڱ'uA榣6w)u7Rg|.7b-]n9lP]gX,N=?{O@L<W/NI\0];#_I@ 0Yb`X/GP >y9uƪw?ks؀3U+3""-uFm 'p[R\<|=z0E7p{^pԳ4 pgQt3}?5L.: k{^,HڟD[#u M:3L\0:&R_wLEShm:b~|4uԗ/Fog>/ߺt߈ťqIlwy4ͮ";uM-8{`d{#:s.f'Rg N6KFusgq6u Y@#1([0Y3G\x]J@JlȪt^'~u~#g9B ^,rBhnyv uk&;/Y?;pcwO}PvІ \p*jc߉StG/;Utc'cP{(]ݯegn*-ĝ8刈Y?~7$Wq-3Q.dgmf]v@3޽ d䡱Lg@:Pv)vdgm:sҡ5 Xb-.d'L6{v@3:r_Rv nRv NVs@[;# [ qKlw4nWcrgޟUh':;h3ͤczu!^yrNg@=z(r_v k`GvЦ*/ŭ>P8tΠ@vu_ʥhK;ƙ 뻻gG4۾M?hA|^]NP;{`tl36Ԩ/FM;s˶زBϸa]#;\v 䱸q/rװL1#Ѩ/fmĠ U* o3Xa?X̣nRv 4zu/@ (u9vҼ۸й~)%z7<;a]#vuOnoͰLDmtvFe4۾/;T.GS)ДN5#;hSW3 >h9ABw? =[6\={v@ Eﮑ VHez<&c?FnRE|b)K׎ggm7 Π9Ono-.wf'ugϏ36.;J=}u V<ƭҦ SOe@KyGXLz-'HqWxwӏ3hA_}97`|S?Ni[;dP Cѻk$;T7jsSTgN:hQL闲ܮW'3haߎnqg_i;6bP n<씶5#;h#e>X}\F}1Nf̎?-QyhAlG-[=Nwӏ>زBvJ[%2[GUg&'Eudv GE * g'mΠ :/}Qc2s6oǮWSZ^ֆAq{);kpCqhk)vN@v+ɱ#~q!3sRmGShsߎop;vd'm  ( Gﮑ Q_W8{Pv I-<4# c27wf? 23V ۾/;e͝<)?jl? ؑx4+Θ EuqGω쌖 X+egpt,J a~8qp_/.dQOggB; -灡ǍPh=[6\hI @0(RO_l/;e8u@:P4}=bv+#PGVCz_΀+\v?xvF2 2޽QڔUh#{x QSpv3'^]ndh&_zdz3Zg,`-bwHvW:3?yh,jsS+8{_5#; *SځfLf4vsRvF2q{ OljQeWC ǎ@ONfdhVߎ;zNdgXZ0(#E Q_S<,đLfgp;EP;Bv -`Phk Յ8qpN@:{Pvשk`{t325,dh7wƖ 3ZNyh8;hqe68:M|dQ;\ɨLfgpvd'TJvu -}wv mk`Glrvav8qp_4:̣ \'ǎ@NGjlrv͠ жnwovQ_S84R;ggp;EQN"c2]ݯf'Xj3(G 2@/GܗO<y Zv ξWѨ/fgpvd'DDDej<;rLxVAzb}ϩᇲ35POegpwg'DDđ0&\pv me_Ҧ "Q_ff_z: AܟQ.dgms׬k`Gv m<4{@Dĉ:s2;Xcz-fǟ8v25[:ŷn{8:׿k섖Q EXvQEmtv dQ_`g'# @1٥m -p'Z mQڝfǟWz-;HԨbv Ayh8; ""js^]]o}Ԙ moNhYebPhyh{ןy4;(ٗF}1;erIej<;h#΀58쌖eX-e_R/;m5q1?q$;(FOegL߁ X+ =c7 ;R<0CePhi:r_v@۪͝Emtv P@/=bv5#;NG/).oc쌖9 X e6ůGGiSv@[LQS,CyhwvTƳչ~)36&C[{na4;-VAeu =_hKljQe7Ѩ/fg bX On{8nNT*# m  -{f'ןy,N~(;hz0@qIBdg-Ę O/Vlh `PhIDyhwv@[ie828vߓJ1&o*# mo`PhI޻7;4q>?IBO<U2(Me֘~kgvF[42@:r_}m6w&?@NgM U*>~q!jsg3&fL>م섶cPXieQѱ QEBv b~ B_3?q$;hb_d=K7ƱHvF1(42@K/GGiSv@[x>Nz-;hOe'pC `PV/hvB[2(42@(Dz3<?LfgpJ=} Шע2=4-.W> (c섶Tڝ2@׳©|-X5gN*2ePXogg@aX3ο9;mu NZA%ϗ3ZZGSV93|pv1(,ǮWcWP(.f'52J2(ѱV.ĉ6w:;hOe'1J=} QEeڨ puU2xci[vF[3($2@}$C3ZVmLd53?q$Յ T6(Seʠ :/'3PUNh{edPhz޻7;eUg&}ѨײS63?q$;QN5eqGω(ʥq2|`XIeֿn_=X%̾t4\AzxZTWvKlvʱʝ k`Gv" M޻7;%͎??F)EfP(# @y.; cxv~4;VAim);:| ^ 8_e'pUF}1;(M뗲0gcrgv1 2@S(u֑3ZΩ|(ŅLfg:J] 25͝ P{ N`ҭҦ Ѩ/G gv>BT~); oqOEN/|);e4qྨ͝N5W3LGv(mRO_v M{f'c2@;tvԕ*S @A-]ޘ*6[;3;`Ph*5b~Hv}wvGLK۲ nv  Mept,;%rLQe|Fgg!JTF}1;(; qEUNZAiN~(;`js6w&;_5#;*/e'f'@cTRWv MQ*[df7;Tv);*SѨ/fgs Hb8 >NzXv@S;u19(pvUƳzva4;R9NAr_v@:u@Onz10@ulܔpE闲:~tycvvK۲3 ];&gP(RW eg4-c2@*;_(.w^vFJrv _/,WhLhIQ;8tQEez<;(Fͥ&*6*u lNA:J]u Ө/Ɖ-˿{K/;cU ?N5hvTNA~QڔT~9&S;j A>K⩟nvX k`Gv T/eg4c2@hk1?|v) רע:3^L3;VͱH,]`wà PH_zv@S1&K OUN 컯ʥ*[NxApJ=}ѿKM6w&?1Tƣ^]=e˝)^1ԌC&fP(/~=;iĉ~~*S k`GvǪ_\0J\KOO}è -o*# \Z2(J 1Fb~Hvظ);%>KЛ_΀1Θ~kgvסӗ4)2@z`L 6w:jsg3pvUΜNHdgu;V3;5#;hRe( Gyhwv@gG?B;H IDATh"IU.mc NZ cpt,;|Pe"|@h*i21*C3{v~4;PNAC~\1,KdvDЌ.oc;3Xr_t3&dP(ѱB3&*Se<4pU3'&cTfs2K;3X!];&dPHW šxޘ `9jsQ_Qs 20(N(ᇌ\A^ʴQlfR94!24w6ggM+^]}"?c`O1:֐ZWT `{s!j.$i"@],/hP5 ;k(ҽEe_Gօ`%+im#JDpp<~ F^Т-[)3^/pM;@# )1^6RIK>;컏`C31e1(ܳϥNU|#xIc2` !+^[?Otg:dBTgNz ;7;DxϷ Rtnlӿ^WoD!Nf}4z/&{3u Z=u=h??&2=9x\]u3=Nc/H厷jw9i7cKw'V"__>`w<j5V۟8qVcag?9ws>n.z͡xC_:{2|>܍A`?:`׬̿^LbDDƧu0Nc58)4|vsi{s3D;n.cщO j⎇;컏j?NcP zX6{D'vT@-7ZŸz@F*HL!+Fqt"" İ msvsy{x#4Rtnl|0h [CFVU.Na.7S'㲑JD#um ;R9:`W O)nƌTn1K?)o;Vc1"":y{TjD8 Nl}V|g-`Gb7S)5?3qH%uЅ )DuD /og@5S80=c,v)Ootn|k SA'=W~::>pePL};u7WS_P6dO ̧ 5߭BD|06sc#֊tvsH> ޳ys(}|Зoc+?:>.dPTC헟s4Rm: 8:YHieJdJD}xolN5:Z^g>0%2{px?@̾h|)|OVNO| 2;z:ul 4>e4T!9v\Ni7sc#J\ @[+Zqt".ϥ\\ʥ)|`Wkkl&m wUȊ1V?: Y%Ͻ:Z6H%JjQȊnvۃ3s[ 13VcOwދLBD T5(Ơ pW#u7=\N1H%R%u>kpX ͸Y:n.z޳oz(S33h5Rg]Ġ pWKyc7R ys(u}S']Ơ pGՙnzV'߈7^x2:y;u Rm7$+U"+U>؇?fl`p^Z bG{NXzGm5#__R/\ZI@h7e82'=:sY%]M] P6Qh5gWX@>q,u@*NNUƂW[~*_EꔁpΠjӾl3(&Dy@i7헟KhTjQp@(GD|Yp\ @:ob]n.NU7ٷǟa }FꜾS'粑JD#u- 9x۩Y'߈7` e#(զcn R%R @BS^;bG{Nkk?^[s#{+NA`[!+FoV|}5uրTjQȆS'64n.GZvsi/YɁ>]|@ym]߫\Jҷ.R'0.bP6vs3j,=sk<֐8:(O>j,FzL'o'=Av\,@?}xp轘)}gGRg0 Y1uE ۪3'S'ܓWbeb UdJiرRm*qbkyk5h5\ `Z[~*_EꔾcP (G"bkLƭ@/i7ꅧSgVmD NOdJd' o5oi5tNN@0 ͛C[O0|#uNxm:RȊ>"  ;7⍿d#(զ|n@$JO̴[#3h-o x$S {bG{N /O)N"  tGSg/<j ؑBVLVNO(9񱭿h7\22΍ Nގ^V#(4uJϻL1(bPS'/?^qtb{@TJKVDVDynd{RzHdP{7_:g]y/O)Nt 20಑W܋3 Y1JSQ<) [Ff~-E+` _OI }FꔞtgL*զ#b6u I#rs3`Hd`pid\i7XH rGSgZˋ͡x/)=gWǕJ*d @0(:s2ugqn DTgNF6)|VZmC3gOTZIo| ~^ǩSzʅAcV9l8ugzi H|ɣQ>R>Gfth7GfZˋՈZ zA|gxmG{3Qiꔞ㵵z X6R he`=:3]{).ϥ`ֈ̑zj)dQME6ۆfKZI@i7n{O o|'z/:t=uJ{mpYjP0(|Y:Sϥ`|tD<@H%+U:s""NlXi-/F'o  eW='1S3pщh5Rg5V?:Sux'Sgnj@o(զn;VL'ňc+ޏhP?jq|)]¿3uD63 :x۩>/?B ol8ʓ9j,62ƍjt(déSkk8rߛOSt^z΀(d @0(!:nve.Ͻ:>5 s4GSME6ql ;n.NǴK[?ăCWN "".`PLuCt@[qI@+NDum Z2@ߏ)/O۲J뫩3 ;z:u]“۩31H%ʓGcJ9@00M'0N Kڼ9O]~o=:%͛ u&+U 3(|`е~y\c#Μt+ni7`xgQ{NIG͡plH]dPXL;Z2^L@(NXLԣ Gf:m2P{D-}o7?My/돤΀OF\B Π l6E+ոϤbTgNӑ<B6z'qڕF0ZEeDăCWN7n߾h D 120 v;n IDATz'SgЅGQ<ՙS}t`Щ"oFky1ZX<=.vsa`אߏ@l<77Rb 120 Y1G3>헟vs)u]cΜTIR%3'FFj,l(*__M56o ̨̳oxgpW20GQȆSgܦXs/KjQ9uGǣ8:cָQUaTG?+?:>S!+PfPR'ܦo/<: Y1GqJ9{TRm*;|c{\Xp=@h5R't~Q㵵z ؑ*0 @+զ/<ToGH= p}SȆŅ}3.ߌ_b7Rܓ+?Ͼu>6oN{ @ΜLog3'H%g:s2 pSȆ:s"3'"n]y=.E:h-/FK]ݮP (4ugڼy .S疍Acc3]t뫩3cщdNN+(c碓oh5b\tv<VR'͛C|;OkWIwtGyB `3(} @7Y%.ϥ`jq(զRB6ՙ[#~g#Xz]vs)uWox^ `PO?(""bW߉+?:vEV2(̠ V헟KΜy xGs7b\]y=Zˋ۩N7u{Z=^[,W.W'C㵵z_Rqt9 (2Ї O:Ї tB6ՙQ9b]Vc`孕 Ơ wkX+G-|cO͛_w6_ R*d @"e< qYH!+1V?l8u;PMmh[2kAw2|_;D4"&{3~g}_|un3P#sB+ND:H BVz h5ڥC2!+Ub~:ꧣolˬ]NN]!__M@Z`w]yCQ9 |}5u'Ƨ|V Ƞ RmA@ Ltv >E6Rm*u }2|ck\vy.u|BVL@k5}$gP@ud`]{u 6],Oxx$ pTgNDuqzBqt"u=.__P63}fPz\!+FuD `@q풇 Q!+ơSgk||\X<:yk%u{ @ΜL N<~.g N;*dQGyq6bʜqCj}Z^8CT 2ƎN kF:ΜEVN{b\ t2Ji$vi6u(NġS*@_0.NގNl8u Rm:Z>2(=:s2u0^x:uQȊqΜH{¸ Ћ%#@ReG@^vs)uϹqvy.upbd ݦ4>B `U>RO vs9]M0J8t|GS@2e:F]+aWWS'Π z ЩQ9:F!̉Μ0.tvs)umJp 2ЃnݵWg=XL<~. pZY+};C @I vs9]rC ~+NġSTJ= XtOGZse`sd|P<5b]NN]dj@1 à t >vIud:u> -8|+h5Rg1وKv9|\6@tD]K2G>n.ǵK3z^!+ơS:s"u Ū3':s"j_wBVL7JV KΜt=~ =8:?gLرTI t| Rmt`Rwa`]{)Z=m~&z,uʓ(O֣oŸ>b뫩J6RIW'|k{ 2ХJ' {oĵK3zV!+o=k pOXt21V/Y:tnlNenRH2ХʓGS'}ꅧSgD1(]j @k5c\ T9>:l8c~:ZX+Sg2x:@F*ƫ`.Tp=^x:u@)d8t|TgNNT6T:u>V/%щ vs)J>W`PXL]{u(QOl8c~:ZX+SgTM7A|A NAB# @[qRgRm:'y >TjSqac΀('uvmщX<:ce˔R/?aE{p8x\ ϔ*q{+s2ѡ*NNϵ#A2ՙ>ve!"*d8t|TgNNgz'둷V/E#ß"N+B8MJ鈘M12E Y1ʓ@ϥ H%?x/$+UЩЩbe>bKNqt"u}p`.R9:S^|}5u@+N#}& p]U9ՙn.ceb꤮aP`wMvs٘=|KBZkfSgt9c2@_+᳏8x\d#I9@:76R'tNNeKd#7{헟K:>:`8x\|8|(զS'%QȊ즼:+ b`R[gR'}Xs3V!+o=zd3':s">b_LoN:+unlNV0x}K-#/ꅧS'tBVG1GwR<~.J=WJW:i7R'Ġ tRm:R? kκ.'f8::8x\|8|(զS'~[+ZWHDTgNNLZ믿:+j=l8u @׫Μ̉h7܋21uҮ*M:k O_JDS'}ڥYmAud<ݧܣx>x|8x\b/TNwͥ ]\NY:c0G2X컛vXL:X *qع8x\̿^WSg}.щ }sc#u@Ws)-J`Ī3'S'}ڥ ]':s"u@_Μ̉h5ڥh5R'ݓTn.NjBj^b` Y1ʓ@Y5c2{TGtոvi6V/Nߧ}:unlNx`})u o/?:kbeJd.gp:s{ʠ 脇T{!xWaL`p}tXfeb_*Nz݆d""F\xUiR%}|G2H%X0X:76R'vs)ʓ%A'#uOiC2o[X Yј waeXHS qݢ4>=)2O< Nd""^>Utc2ԧ ˌ= ur\J92OG.![֘LqtZ T c7*7Kun_[K?@Ô)@ L` TN7*O=*~a(塜 }9@:Fv4(+e` T既LJ)rtC;@=f|!:؁f#: s\N @e~)@"d}`fN} `Zk>/\Aʾ @"dRJϞ970sA{}-:o_NH AʼW"oB0HR;:f#:s\N Ye~ P2$RJ'Dtb`t>;( l7Z _jV0FZS cU_NH)TʩiGg}dP2|QI)Wߓ?{":` fN3Q{}-:>*W1(}T_Jlwt>:$(W~%:f#:`lR^[ƌA裼\cԇdRJie?RVN3hE'G*2G cHf?⳿yV}%:`lR^[&\:3>2(}RΥ,V!RZYDz3Cy31dPdXE/>Xt0 lD'RVN̠ Ie~):&NQdRJie?lj:=W32(_eQPE'}fP\KY>aGoT~sBlwG$n!2ym1:ޮlߜy.}q#oG+Iǟ=W?TFg֪D'C]((e @8ckd}kiꧢ/"Ǡ P6508$RJ'Dt@ߔrAt0ԪJym!:#e`*F'X!m_F+:>;J ` AءRtqI)Wߓ?{":o,=2`bjW3>1(;P;4 C2۾Vt@ߔs~?:nAv 1(;P_NB{Sߞ!R*?jt0Dd`0(rzSOʯ_N?+O}9+ ch0 9~0F T;1C2)t' kiΞN`JwNȠ 2oLnפl?Dgk cU_NƌAQey>$RJ;yz3C,~6u; (g>2(=/E'2$ }Ӟ3i5 )E`scHz[,}?0:`JY9=_+ ciP2Ѓ`Oګ;Þ ̠ @T既`$p[,ѿ:c\EgAKو{Jk XƋACt eH֞ӛV3vjWCeUN0>v&=o};24:`fS0ZgOE'Lf#:#eU既` ܙcg>^{#@V}%:`"FA:k@;P)-DgP='('?Nر=J Psɍ>1(w2C#[gH˽8՘Ny1:`Gչg XDg.OeO:Q8?\Nرrt0k "/E'P~ c2=*?ؑS^[F@\N&\>9#0. mksWQH~# ;RCEg#U_N(`LT_NG/>dtF!_ؑ=NY>VTt=2()-F'^ɦ},: L,NĠ ܆lj:0P>v&ؙBf鉿Xؑ>ҪD'LnLlj::2p*F'=oG'?xz 4s v.Zt=2(!]NG/};QX_bc iW&R`LPٷ' ugҫg63zV_Jy͈&\NĠ Beޘ MՑG'}9:1JtDv +e>1(Pw0:3~PH'ߜ́)˧3i5R{}-:`" A|v!:nGގN(rt@JY9w `ĴΞN` Ms)˧3`> t1:g{>zV}%:`uZ`•s @k 0p>vtB!ՋYt@JY9Yz$:Aebu6 JY9:2p`Dit@|8i5d0 (e3`P8|&ybt@OJY9Yz$:AJt3A1&_SO~г=Nlwt0&^Lru.:2!*F'l]+:0^9Oz'Ti#jWV 80("]Nֽ oE'lS) :` (WROGgЬ^P;y'^I)+=KDg#uTtɠ ebt /N(z1NٞR;:Q ,N @e~):[{ OzRi#و imD'.N @^[Nں+':c;態=sTvGg#yz9:w Oe~):B<9rYz$:aeƋAx!~0o}2ߜ́éFTs)+\۹LRVN Oe~):B=#ϟ; =c 3&0zk +Wg>0(ȦSOGg@盆ooFgda8M5O/G'geym1:B|0:aNГ=KD'#Π 1(ר/E'@˻w\_ϣzS:VTvOAF^[Np4E'Wߓ^=Г=NF\rt#\NvȠ \Klwtֽi茑oE'$N}KkN`rtCe]y7[F'fϞx9:'}G'#~6u6@{}-:(82𮼶#RjswtFLZ>DK @t˼#Ox7fNlwt06NN`D(:2Rg?m]+:#ĩtzFt@O|8:qV#׍nLru.:!2Rk 0r.Ji_Ut@O*K)˧3<Mvʠ +7]ơu茡fϞx9:'3G'`P``eS)˧3`$m]ޕ81TO =ɦSeL溝KU_` 0btg6wEg ןXNɞGh^N6F'2(3(7uyWNPtPrꙍ 8@sDtiG'\NvȠ /]Nơu茁;?/G'dTvGg#۹302Lru.ett˻w3j1:'3G'`L`2`(g6wEg =ɦS^[ z":ԪD'fPϺn] :c`_G'dKyz9:!0(Dk P(/4R󝻣3'ӏ~20&k^Π \Klwt7~+:zG'2|::(@K @`bU既^h.;wGgГʾ @tZ<hE'fP[ }s{қ.FgܱRVN31bP^h.;wGgyT既8y,:!2(Dk PxG^ ;v'y2:'3G'i5R{}-:; MMG';`P.D'@ὴ?^#NI65֚10 ZD';`P`,}K ;/ =;Ĺ姢22Lca޴zqotFOo}2zf#:'3G'^?: ̠ '-F'X9Ɨz ;:'t*Wg38y,:e8BtՋ{Žw쉿XNɞG0(Pl 0qbto|):|7/\Ie~):(rvT:A&N^[NzqoZ7:=y̓b*WROGg<@A&J^[Nu/E'ܖn 8@s)m<@2L|v!:ŽǭoU既h^N: 0QEvpK/zMM,7ڹ姢Nk#:((2LcNm>wEg`tPV#=``b4E'|85:1P `b 0~uoZ7:ㆾW)NltP ru.:2L_N[LوIe˩وO^4A&F^[NzqoZ7::Z峮g[k^No_N ʠ !-F'9Ɨ_NI)+ʾ `u;c2L|v!:&Ži茔RJ3=q=c2l3(Dk 0脔RJO]лʾ @[~*:aP`"^ܛ^>峮gkOf#:>kE'0(k 0ўi =yoz^s)˧3qXt VF';`PWE'D{vg_|';e nAcP.D';oŝ`*K 3&`x/mO[yOvOzš_L-?1(X+WR)oơ孡_*K kOf#:v.E'dPw=1An쉗zN~r=c X{}-:( 2ru.:x]vڹ p3Và 7dP.D'xqhx[C;@r*Wg3fLA˦AV65/`b޴zqϳғ<9 qLV 0hY>Ƞ c+-F'7B{gVw0:a'f#:ePUE'7Bs)5߹{xo .D'#liG'dPB{'yr`RVNY>NZ AR)+ru6:lرwPlBt0^{Ht#Π c\Nnb93}k nRj^``, -<\q~2 AÜ[~*u; FAƒ0`^ܛc~c S)+ru6:Q'E'PeK\tp8=;}=>㩳وKN IDAT`dS @ 0vչTvGg}=ѧ~ [>Ǣ`L dP۴uyWn+{ӛ}zn۹kV}嶎^_Kݷ/+dSӷۛ=60 U?u<2@/ 0vչߗAg_|5\0gSӾ}㑘Qv0 ͔؍Flutr0 j Ġ c']NKSS/8GYbdSөu0̵0y` uq;չTcRVn810(Và wĠ c.KJzBwHvl6RRzwKmf"u6ٸ~r[wM65+o;sN` 0VمiѠ̷^hkbs VTJAaQ]>28SNA@!t;cAƊ0֞]zo=j c1}R6hW<_wud1+=Prn)12yw}>^= W^[N`Dllm^>Lշ9rdS)gΔ53kPL'E'P@e+n z`O2?:W@m HJl^yUa[Jљm ׿wǯ>`r]; p<L(˻ҏ[s}_ƀ jMFj FrݿS:rb*ݵ;sS:C.^oD'0P0(~%Y^G2;y^`pdSnP(nј+yz2,3selWgr*Wg 8yePPʩ\5(ғ<9"ʦS)Z+1#2FtPp^_K}sL:!D'Ppe \t'/mOW[~>>i5ǜ}oD`X:l|gϕ9C3U?3(Xg>ٺ+>tyHEz`x:Fjrc^:$vWN]k{h&]HY><7疟N` `,s @2Gِj+gƖ`|L65չJvj ƀAB^[Nh߽o}2y>ʦ /dIlo؀a ƺKyz9+yz٫ YNJjWL65չ+C3FfD'0f Pxym!:6/N?wǞ] lj::`dl4WOާHƻ?24wjǢ33e(ru.:Ջ{?0(7Ok`(f#ml^a+#3Br#7sGCe(47_x{isu11Mq10^{Htcʠ fPK|Wk 0 gӹRrv9ZjRJ)rg- ^ոx͠ I0V/ݔRJ;yzL=JY9:` Ki䱴qXjEPN;?6U84q ۍ,`rȂf76,\6져^(Cmz?XݡAb"PpDS]ӎ r$WȐe~m !?d1Vlٲ83<k˱""n ˼cd /J(L'2V>:~9ϹSt4i6@W͕ț+g63Y @y@y\| ?/b KgKF:!noM6>­73@ɼoN`j @N3knIҋEh`;[s&6Ϟ3@yț+3re(j}6u'gf{?u˛yW00ŅNN` @H&P&ۯ,ǥsuJ 0AJXHaTR'|ͳDže;[SP R'0" PJlO|+ڭ]5 0 0~}`Z=5 @]yyܷ| D PJ.ёoNJVM 0ڭhq8ҭ]pG:bPR'S'}n0KpC2p3""1.L8t6>57}ePRr7Pk˩ZMys5.pʈ|僿Qd2sKQ Fw)v铩31e(^h6SSg "ߊOPlΙ<{&[L-=2cӥg P:e`t͕ =u ҅K/>b6vk=ڭ88vi$ P:e`t͕ )v S`[nǥgU63ǎGmf>d<|+6ϞI2(@鸃':gڈWhS^[券5?1ǎG>W 02J>:蓼:.-?OLEz\xTTq5!o:@Re(l|2u' )v铱yLuvl=saj@x 52J>:Nz 5R'CSO K@m-r?}2٨5bjDT3yyHΠ K ys%u@[_F:vk=ڭlTjL-z;: 5b7Ο>: P.l nmO)@uvl=gDD=,s<&斢%.-?9 O:FD\I3d`ѵk?5n -EVȷ Rg@DDT:n[3zƠ Mb7Kc2@͕ț+qɨgcjD QϤNp p QOA\IP?7J vkl|2&eGjl-{UϦN XMP ys5ڭ+vZNNC JWe`4͕ =զR'CJRk,'Zc>u K|`4d:Ů{mtߛ[饧 @uݸ©.e(Zc!uys%u@i;[3x">~OFhw1(@)T볩>7VS'FoN!迼gϤdPRƝ oN(bg+uP%bzdcs`?}2uܕAJZMX؍vk=u@iєO C2Х`j @͕ } p?8ⓩS`uݸ© 0 @NGx8% OFhePզR'}7WR' 1tT3S<{&u| 2 ڌ;nnHUo *dל?}2u#ZMA0,饧cjDT9{SgL%NJƠ /MNz,oNZc!?ǖRȷҋϥ{fPWϤNz,XM7S'bzi@$^SSg=3(@gS'}7WR'T6>y0$SRhe1(2 420jRq!:AS'bj))v;u|hehdT볱:1tT3StS)ک3 N:OehBڭ ]O1x"*Xj\Z~6u$>(/2 l|2ucjRgS'o[1ql)u %[`e520ڭTɪ`UjL-O9CNE:AV:vk=u@iU볩`$ 1x"L@^8:Š +w7Ovys%u@iUd)0*Y5O"9~铩 0 kS'Z>kzX1d.-?u6C XHP5(pHy@UjL-OEV3~ȷ Rg@W``eNafL 04jZ<SONxߎNN]aP実0Jҫ5R'@eoȜp\F^'V~CŠ P0 WƢXp|HS'bbn)&-N{Tⷎ^qM֘OAR6.0ڭ Cabnɠ ܃j}6O≨dcspNZDDL?kW~7^I\gPdP[:`(L-OTɪ#2L`u/wF à XHP:`hT[)00ORL[J 7[wc{{q:.<%0(@'S'=dPO`U1tL-E%K WwsߜGW*2 fPY\ILL `L[JVNN}O≘Z<pO:ŗkjFs5n\ҧ*.2 Zc!uczd=2x".-?:zUFd5֛ػQ׼?zU 0pqwa7WS' O`hUjL-z;:(Wwk:7/|U0<ˠ Ǡ 7z#MFys%u tͭ11l,uPb{x*E_O~؛(p:Oe8l\ ;ǟgDbF񡿯D5$Sɪ2(jSr5@L[l|2)T1x"&"M̵rJ뾾;Og?u à ZIHuq30J3!yHȈ {عcx8ӥ*-2 l 0ڭ C֘^[NbD距 /^CXce(Ym*uCys%uHWd9\%ҭcKs浫fkg~n]Wmn2 w/7WR' "LZc>>ߟa-ccjDT3sj9߹G8o]e }2(5R'=e[h&sv2.T\xT\sK11Yͅk@9~{7=^qOs2(p'neǟZc!^JV!J6: C__^iyFT볎0P 00 .VxN] Zc>>g&.p*.-?:DكZc>u}ܸ;_Noxw611ǎGmf>w`8\XN(b<6Nd Ne:葼:5sv2.T\zItQ>BfcR{;3}6vοG IDAT: 08j @[JH]p?S' b9ܧJV}{1.8u #̠  :``||N2I#Ucj3&S'$kq˩3cso4W+SP|3up 0*G=U:CZ|2ͳ37WR' JVBT3kW#t.uڻy=~kq{L#P^eBGPx7c[@YɛqSeĀ z9^E_O~:dPPɪ1n:Pjh6yL$RyL>|$R/,n3Y֖+S(17AʛS(@VdRħ83yLl=V,[#2&a^yJ+uƇ^:cP*Y5u#Ebb)v #Mǟ?gͳg #-|{8fր @ܼv5v.θ/{{QWN` j}6u#zUlE4RWt1dV\z~[?x|T볆h-~3rܸz%u #  eNaeP|3u@Oex_Ǿ~e9זcYO="ӘO0v.{7^:aP 2(pwV8ǖ/wۯk˩p|T병M_ڿx-q9uFWE_O~:qnR:82$WϦNzĠ FQ%'cjyLl=F``TwFkW#t.uFWU?xhm9n\:jS)کC0(@r:c wW䛩dc1TL/=Ejlbl-NFD6>ᘅg ":qK3h?9u CΠ ɹ+ :`6SO)vc{m9_y1Uwx @\Y_Nꌞt/N`' %|vk#DDljl1{b<Kz{'uFO[7q) )2$Uk,Nz7S' NN0&-ıx_"ߊț+o9  dcrZꌞ܌O:'=ܛNN0R;F,:Lֺp*Y`8&ZcFꌤߋ?/տS0j @I fPQ:4j3FR%Zco}ȷZ+BTME6>lTikWc˩3B+S0$ L6nLU:4F nj&c:2z͕[FcN~a-:So6~?-ǍWR0 LVJA{W䛩l,j5xo tvQ䛷`߷c*Y]@\Y_׮({7'&wR@D8Π d㓩 oF<&#Mj?ۭ[#3͕StI_ ww dc) Kz{'u`<}6vοQϦNFXn ANys5u@fzZxϱNLx/Ga"~5զ"|s3)^yZꌁ6lPƁePdT RlEuB0dcC3ǖkڭ(v7=FgU#C1(׮ŵsO>_)A}10\|3u@[Q?}08w~'Ӿ=qpF^'.{)uFigR'#9,P~e| WlEy `JuRX->o`+ t;<0:qKwH2:wORg0 wB tG:Jܼv5u{+"~G @+:E;uPț+=~IS'#:qV w'oNztpҹV ޡsz<: !2P~eJ6:NN0Tڭ p`ϣRg:'S'%gPrʛ+ "n\\K]|t2(@_e @;[J:浫dؑz4~>Gx&u Ơ }U92:2ݕ7WR'0n^Ͻ:ȑc#""MӉJVM8@ @f7WS'0nuRxV>vg ePC+vR' Nl`,D#w|0h WçȍB\Is/ލ"u w1ɹsKOG%^8,20|2nGM=&s)G#+XLEJ>:an2 }ONZO0JFĕc27O~nzi7PdA*a)کrF_G<.V>T%`@7Pڭ C+oN`Ƚ~V +s{饧#wgS'C }Skݲr\M0( )c2ȑ?T8a)ک.0([rP~17ɹ{l|ECX`9'AZM􀻑V\Iٽh>RG>~8v~r ewNnmNzk˩"W~;Rg>֣O~Џ3dd](l 7:NN0_1*|9p=mGӮ=զR'#sm7uej}6ueVfP1&3xg+]{̩'d kS']`PV䛩FB\I@|mS]LAZMtY:`$;[nmɔ'?9pO{zd՞<6ݗONAN̠ @lbJc2%0ɹ8R{g_bS={|+ @9p ?k˩(׮ƕ|>RG>^z:*Y@[.0(@_ pڭ(kWb:GO~/UbS}y.n1(}Fr1rȑ6}}饧UaP'S']nN9ex?d#GG>o%>'NX`VK e/oDM2&S&sonv 鹝W3:fk?N Qr%;`(/6A(W':90t*`<* |b}-n_1ۼ\ИL1} C4=;  D<4]x{w֍~+;ǴmlЌDD:p4C\ݓ͍ }u.Zvqd̶{쌮sb h72tTuPvfź^:.;qױUc2}1RvJREc5;h#2<2͠ @i~XjvO`d""ՉuhvШԦ cPHeg~h ~=;`(ʕ`*͚a3 CV|/ww)<c2]Fy|";`9c􂢱A:S`fvX@[qEc2}ƘW9zv]P;gƠ Cfܺq1mN ze::u(;@eRQc}u.ZFvPy7>1>32Z2&D:x4;+ײ63(@GUjS @fvU4cu\vl܊[7.ƃ1GuVNAP+sƝ_ǝdc2vd=r%;'`P֬/d'X7;`5VnW3xBd̞ïg' Jm:;  1ti~+>W)&32ZN{?JJvpOzAhf'`PΟVZmƭc7Sx d:g RNA:n*2w:;ۼ\0mN),2S*oN XZvmh=kίcڇ~+;`Lv8 m@'eAh X_)]^N{r%; ""Z^LȠ 7@oZyL >~+,\'N)=_N{թC Ѭ/d'`PԦ+s3z½ͻqͭ tY6   [HgUldgubۼSzng-vNIk }:9Ec5;2w;^aPArgheg݃_DcFv [dLw:Zv@1(f}!;2tD6X>?V6֍;`d;f=_N;fP(mNڬhf'Aheg'>{wS؂R$ƪST'3J\NbYTex, ??e/ƭ_^[)lc2vdvx-;T'e'Ds0 X+OVY/fEv3{1(|alvy7֮}OT'3Bur&; @#<O˱:nvc۸ubNa>-ex< 0(#5 t{b#;=ߊO?E|5oeEāW]f'Jm:; ""ZvAexVNX;P6ƭww)s;k}dgER= /CePDƭubۼB<_2&3@Sz^y|";eh͸yDv4Vnĝ~+;6w0MegFƷXtA:Co:.KW3f]0*;6-Ωؾl =Td'C  Te'dlv06kƽͻ)h)v?c)t@=*  `jvIKcu `H5Vnĝ~+;66#v?vdA{г _0(͠ n=b#;"6cڇW)1QNYe^* @Qh `Hl6n'>{wShvGbdBTjSRNBtAΡ 2w: `hxpB<;g Lv@O*Wd'C  m7`~Xv0Vߍ BTo{%;NITv@D 0(#k f}!VdgUlSc*~bfg#w0*/BLv@)Od'|U43(#sgUldgY_ d%U#ؽHlRv JFeruOv gPxlOܙΛ?gFF\Vlmc;SN)թC _( @sq\vЧZF\:v<{_KUl1Lv@O)+ 1(@ە'谛gODks7t?cdđ^ZLx5FFK)JmxԦXt+AW Oy~D㙑΄eצ^ΠG:x4;gɠ TVNGco֬/ƥobUlh)kS)Lv@O(+Q*oBtA]?u,ZFvУVąw##>R$|);W:*/ioVy9=#LuPv@Lv: [ vtv]V IcJ\x͸}u_/w0{ggЧ(D'Ь/d']`P++ $X;+@yq[QuwZ<&-āWcΗScv/'^jP.2@\?u,ZFvb\:V̝)muɶWc؎@ur&; { k^ 6Z<{";f;oFr~R= YDٱDuPv@Dv0 m:.nA f}1.X>?x&;b=_o{%FFK) Lv@2@ˠ v~۟G?Ik9]u섮-?;צS*pzMtACpWhG?Iv 37չ^ Ɏmc;Ʒvg7*Gy|";㪓?0L iKٟfg@iɷ*9s⹝8jNRN(Y@/j.*emetTjӱS-7g3zFD?gth)^ػ?|);H6Qa6#Of}1;VcJ|p c2_>w*;#/]uPvW4 @z¥oE*6⣿I\:Vk9=Y_g#칝ؽHlۑO:ihlle*Fe ̝e|o6;mo{%FFK)%AVNҕ =Y_gOdg@Okɷ*9}X?%ϖc}K)eAVMe'|`z(Ow)b#씾Oۧ7;ƿJ:0( LvW4 @yQ==&z=yBսveAUNFveetԱԦRN4Ec-x4.g ܩser욞mc;S#:`ЋFɷY_kl|p c2mԬ/3a1q/0.Ƚ EtAgf\?u,ZFv tksq7clv@ϝNxRT312Z΁+Od']uPvW4 @zZNeT׬/ƥoG?Ik9Y_g#ƶ{rv tM6V^ '2@kb#ni\xh,] w~w _Z$NNd',5 @Rv4=;:.""÷K}VߍgODhf OgmoK-Wb;^Ћ Aq:iu\TjӱS`KKWbl4.g ,CTy툝ӇXZd+G\1 LvW A<{"JJ9xbb#n=S+Ou~6צ~]Eڴq-``x!Ћ A\?u,"¨ }eXyLfv ']h)vNķvw <> 0(ɠ З:NNot\<{wz?_;~vw^QGUj mQNZEc5;Hiз>O{?:Tv |E7Ϟȷw#x6_5'ڢ:eMF`8df}!;H2 ʴ7b1wXo؎81h@?++QNdg|EXNV{#PcJ\:v\?u,u?^ FJ۾T^|9&vt Cur&;Tj _Y0J*q[ŸyD4.gZ*ʿ>[o{%c< _y|"b)Ue'|-20F:Qf}1;V4q7 W1q/@'J6jv |GǣRX>?+sSz=FFF12ZS3d 2:9 Hv^2bv =Ul{7%͕/^{.)+ O<> N`|>*:nv Vވ*9_3ŸiS`hT'e'<1/gzYcrv`贊f\?u,""~r ݴ:n,7Qen_tY\12@j @222*0< VR VNZBv̠ 0Ԯ:@4ͳ''XEc-Չ ORNZF2[?aT`4h,]Nn IDATݾ:{ ;F6eg8F4)Ct%.|;.|˘ n_VCRNx$*5d'= TN*q7cueH^u\vQzVNz@);Re'@]?u,K?|+;``4Y#2s031Ptv7j`P2(X?B|GǣTޞз /n_av͠ ˚GxJB|pޏG6WVߍK+ ߨ:9P2<py3÷cgwS'|AZu3,~ߥX߾qbЋ_΀m5#+~MI7 p#y A/uQ^1:`ni\tbrMsY9_Y|gR+%bP`y~_xI0SݸxWlrU1v6L>HI8uD ٴ*?γxeR']Rac>u X[ngb:X"e{Š_QoiuݣxטVeH ղz>蟦NAnڍbK+?u> p#:6J9<їa9 iU΁R wS'|V1NAnāxXiUw/Y7#˛2yݍWuGįSgZw} B>HIU1N,!2Kxx*uĦUN{ե$0o׃2v=HIbP`L2{MLκſYL,r؏QNSF1(-oNbK,!2Xp<$V z?=G_>Gz:Hlt?1:9viVeT+zk7ugU 2(ղz_ELκoN`bVexեA}/Rg.OYe1(̕þl<߿G_>gQNh㘜uS(.ɶFP z%dPDX_V3b}p LUctrco%US'sR'|VUxf|An,5XV8篣׉/~eR'P N{n3=z2(%1(F&g[ya㘜uSwTf X+i)e[M_`2XbЋaYƠ 8~SF8&g) ^VE1NAn,vUXUӪOoeꭝI1bׯ1 ;W5gP5X_YnPV]1w}4~G-{: ҴY7F' Nf$j8WbP`Ncr֍G_>R(ӪL,HUR'Zeu_OnĐ5)ezkכV`ML2{M\t!~$XIU1Y7.G ʿ0֮ VVjY=u0c8#oudy3uuSKISc|X eO1(@DD^Oci7Z u,r؏QLκ19glitXŠ:Xbe|g`͍Ncr֍OgexU1Y7.G |T9<:}:FsJ 0sR'41:9G>u$XiunL^Y7uU:^'u 3(y8 뭖S' T]S\t◿7&C2g]T .oNg1([y_G>G_>7,Z)+V[A 1(|Anxf$##LL2upy uy |AnM,qN Rof͟+ 799eZ uD ތL^Y7up V3by u~``U:ZV5x8&gxxyf&198u Aa?ꭝ6-bϵQS'+ 35zk7A/udU".^հ Iu "IVS:ƪb:Xe)2,R18ɱA+`P[wRgKΰ R#2_Eu9NV1EOܒ*)`PzwXfi<|Udy3u+ƈ 0NVW1 0([4ʸE(ƣ/R'X9gQތL^Y7uܕ -4:nS'+Ġ sQ]#ک+UW]o_ūFc|YL'T8&gVVkX)aPQ`(VeNctrN<<: )G1}:Vnà +er֍Y7f<Fc- L^__V zQ]SJc:Vi`N"uq/zl>O,oX[z(1IK*>e3nNVAVڴ*{ݣhua癋3RQ z1:9vYK20+E4uϐ2|bPp_:g&gݘu#jγ>|A,2yݍׯ}:Vnˠ s1*u0g.fˬw/^~ۇOaY[;RULκs殱Ip+Š:X1ezkכO7:9q[,{x+19F1yllYLp+eP;e 7VS^֣׉çSg,DU(1II4?Ipk8ub 0U1J,@Š:VUGՌg}4jكi3U Ncr֍bZw 3^ 0`3~5ڪq|7h<)1IK3`` 2(탈x:`&&gݘu#jFxf,VWoc&_ƞ1` 2(.q=Q[}4F-{: a?&_E?bK^\4`  s3\5@<y|7h<[`qbn^ӘVe$0k=wS]S'+Ƞ sS]2nԲq>YVW? z. NHՌ,obK 2K>k`L2F'1:9lObi[;4cQ z.MI VeP{Adq\t{V3So>k@` 2pWeiUNڍY7u@r8E|틨vci4:e(Q zQ`jY=;3n͠ pWerx|;u)o⻗ d@`;Ġ pWel˥hOиL>zk'u0#dfoZ]NH w3pWezk7ux3.q=x$2jY=urx:X#~[+ 3(T ԲVRu9Q\tގ;xÌ̛C\f [<2̍Ay۸qZV^'A4:`bv<`5x*FfP{%gYVeNctrx;,x.A18rx~= ?iUN`N:Xaezk7&gk⻗DՌ'DO+gZ]E1]OR'YȶQorx:Xae`sdvP]{ݣewI;ytaA/q$nI`A;M^ poٖ6ʘucr֍zk7A4:Mc^'uˠ VoNxMpg>bPvcrM* wߎdy3Q2euCJ3(̊Aʁt,nVFf \(1(QcÕ`~X ӪL^'ufŠ 3۩Xɶ Բ ҩqT(?ZNq+23̊AfI*m5#˷#ُzk7|ZVWocbx aeU NS'kĠ sW N#ou .Q]zk7f[fUpͣ|;ur:XA=c2js%2Tm*Qcr}w8 IDAT:4Sꆐ*VۑӪXLk py u0KeiUN]Xɶ \)?X^'ufɠ sWϣ`S\E r8AgڍZV|g?jY lbpa0zk7u(ju=Hp/> dPʶ\`}9zk7jxL{љ~LzT7";̆GN7#bPp:X,7(fD>uz`LanՏ0?tI lnڍ,5Xm5y0(moeG{3H[QŃ~Q7 >37>41sM-NEml>Mpoey0(BS`d[M~` Mg#$%(O}h]V3 |עfӴ*$X}(?_nIpoE4u 0֮|h=ŵִ*S'+ڍ,12͋ n`38ǛX$y{?urx:XۇOS'[9N֔Aa<e^'u^`M`. )AX 4u"f {V`^ tfԲz 3=0/eXW 0w~X Š:XN{VWe1(BL2ulZVOڍ,o7c2<`!<ToN<f蟦NV 3Q z5fP 0wV3ul^'uLɠ SvR'eAbK,}.6y``aU:H oNvS'ZVW}4uLþ\`a< =묖S'Z(N y3(x ɠ ,Okiu=H0Š:Xse+Xg:ւx$u ̛A蟦Nzk7ur:XrNVWe3(9L fà )NԲ3fR' cE6W:f]nq'f` 0ӪL$#Ͽav+>cש3f蟦N6A*Ʃ`y Q \>I0SŠ:eXҠ l,oFL37̆$I9N6AjZDu7FUR'Kգؠ >A/u! PgLX/eE1(B 03V3jكq`I=M0S*y ``U:H$˛Q3^ 6 NbKl2,@ p/e`v\~׉,orx:0eXNrUg<f*'f蟦N6At6Y>Hb<fjY={3W z cPs6[VVW-G7SgZp^'jك3U NS'Ƞ W @by uI:F9) o͖R'x Q NS'KᓯR'\9Ǵ*SgȠ IVx++'jF-{:ւ#f + 2(@U1J$fPUR'(%,u\R1(@28t1cPxWc:`.i`C 2@:nX:N1NӨeRg\9Ǵ*Sgʠ IT(uX7#jevRgZ /"~Nrx:`eHt0&WVG:ֆKV3 R'̠ x`PUQoNaPxI1(dPdK2Ua$f蟦N'_N;/$ePdm fd[YyH:̊3#@X[y1 i iUN7<ˆ٩3#@DDl>M07Š:peHۦX~~X΋N 1(fPd?\NC,;0;E4u{eRgEU6ADDdy3f mfNγ scHXeHjZ]N7<Æ" jF:`n|A) a|Wc:F9Nγ sePXeHjZ%0>(:̎ۇOS'MU0(@Z A[3=N XŠ:HliԲ3蟦N2$f}gaJ߅#Ņ#Y#HD)V% a](v};zziwjb R‘N-}ffOۿʝ`|oߜ @t6V<t7 seH( 22(([ P  4\Kez3(ABQc0;*W0(@i1NJ-ʕ H)-REg@m A0(@|9/ RJ{VtԊ+ٺCCm@Ġ $:(Vt\YN; sgP(2soH)f 499v4X ^Sq>2sw% A; sE'A~@?G @ 2@y3e*ܤ@0:jŠ 4WwsN/:`1(@i1I":(Vje *[yfǩ8GgAi12mtP"{VtJ~|ɖ{{}0w0:DTgFt ;̒C0(AJOq>ZY;uַ3VNJ~#:1( NtBy P N~M,s(:-Rg}+:`!|ʠ QDܴ"u7-Eg@ p7:`a|ʠ QO+[2*tߊNZir6:XVNNtB䣣dPҰRgc+:nVVg~AJ8G'%4X0{Qt`u0423(@i~ZY;:3pJh^وXiq&'o3~AJut7 \gc+:jvƈ&Pve(i1I":(jr%e^tJ~|,X+k`;:`a|Π t*j?؉NG ޺Pgo^E'.2AZR߈ 14ISq>]e(i1NJCgF: ɱ+a@G Ƞ :k:7`':j'F' h7AJOjllىvVwscPr%uַ3!@TqtPR뷢0 VBwjrr$:tpcf/ySPgo^E'\AJ8G'%Խ>L@Mt7 P;gZu/:`c`P):[ @ZRtN>:N?؉NXiq{Pe(o^@ t7 P;"MNFg 줬ӋX(c2@t4:()7ZY;u vz?:X`':` TAJ8G'%ʖR{Jt iür|t,H{JoEg,ٛW fPRG_;9Lz<]t` H|ޏNg)DE>vp*P)e(ˢ\E/_VRJ?6*-R{e#:jgrr$:Xl ˏ TAJz;[N/e˽ Ƌ@wNvByA PJ @uߊN޿Ww2P]6$ ||t,q6bPR2(ޱ{iZ\3*Ӌ΀):N(e(-?bPEyR?gTgueP/[`;: =@U&' @uS+kGg)]g@yqrq `0UfPR+<{?l? XwsZRt^t0gVa޼Nhe( ʰ(0壣K|{e#|Ԩ <̏+l@ǗWl Pj.{}hyQ^+PKE>N8:[L3>AJO nh|t&'g@nt`uzaUgPR+iZ\Dg%gPEzQXVv`/:3l@Π 79y\P sz|Ψ ,NwsZRtR5Y+ UgPspNe޽|QΨ ,ڝ P[9 48MIt'1(@.à tz|Q֨ WgF: Ӄ`^oEg:{*:{Phg=*^2" ";jnpg>AJ/F'F' {?~Ш ^KvtV~|̑QŅ!M P  ʰh^>?ʖ ; Pkgo^E'svat@ 3aPJ\F0vt rz|IaTfgu5-.:k?̗*ջK?@;-Eg@E'svAt@iƠ 1-&@Ed^j\Π޽|>/xHYP gocPJq!(|t46*ǃ0g=T ue G IDATԑA*Š ! o_L=* < toVt@i3(@G @Fg@໹~0|Ԩ -<s699N8:lw P) @tߊN}~{eè vat^t0F~ͫ0(@LI*r 7Qws}24QKvtԞ*l)|Ԩ ڮE'svAt@G scPqP핍-3hIbcT&Xu/ e˽Yߊ(7Ơ 39yTP@CMIg y;u:܍N;=.MIt0ckF'ʴ0 ԚA*gZLR31AӃ-k<VwUt0cr/ʠ 49yTL o-P7kwD'@Mtz?:Jw PIea\HgS>:Z{^8]d 줬Ӌ΀;=؋Nf,[`;:t ugPJʏ .Pvje  `ۨ vAt4AJgrr$:` PI @Eu7 4X>:L-}=*cP *vREg@MNݏ5-RP:4&0(@%MIGg:܍N}GOP9kwD'@#xgR:{*:` PYN>F{e#eN%Nq>N 2TJke^^3Jǩ8Gg̝A*ˠ V 4Wߤiq핍{+WB>ڝ goӴDg3vat@)ޏNX2TAc; 4ܴ}Yn>zjTRvREg@#E'3-RPJMaPG @E%2;=KE>{Vn>zð=kwD'@#8ޏfhR*CM0(@壣hP?i_4@;)3@d˽lGgR~s9 Piս>LٲK1x:܍X :`n?N(7Ơ fPNt*:!ջK?줬c!|HgF3JiZ\ cPJG @ qz茔RJQBvz hӃ`P#kw| gPG @,a:=.:gZR0WkF'@HgFoEgA P ²N/u7RJoiq_lTh\Ivt4ƴ0%ڝ 699Nbpe ePbRړa@\Et4}SBM;Pj{ ! P 0:aʖ{RJ?N?I@ toxNfd΃;{*: Aj 0 Nt|tS2|k~Rq^As;)80LN}ˠ PӴ*nuٛ^H7=M+)Tp׃`{ yPzMfPG @ŵDgR'caŅ)&lpUt@2mtPe(|￈]l)|d΃ʖ3Q~VNW~PzT36:[)[vT徹-kR^Zދ΀9=؋Nf`=lB6\fe4:R@ɹwf?/X+knt@%Π 299Nj9Lwl!~Uws:[8_}{-Eg^mt@(2J>:Nj-`':~oiqq)tS2L+kw΀))^Z :^G'3(@ [g${<:+OOʕJbֽuz8U *`/: Ajer6:K3_qtƥtF,[3qE:{|l J({Aj8"Gg5z^t*:ჴ_LNt tz$:D>G.Ϩ&v&ׇ)[EgLNަDg|kYߊ΀Fz":D>G>^t@)vatP#/^>OE>`v_V֎N`AZY;]Et4ٛTWZ2skwD'TFmt@)v#0K JgZLҏ>(tSW z^: hN>Qws:[qz?:4 P;iZ\Dg5ʖRws~:{S͛`+OOʕ樽r%~T㔏3Ot rzPe%7Evӏ>b+[J7=5Pc8^>N>QN/:2|&'o3Jà E'5uzF/(|\ZR/_nt 3:M hiqN3Oچ>R1(@-Yfe~EGg|wd˽vAt4 'Zu/ J1 se|tLg}+e˽ U?|Ut')|w<zd=]|"; P[(:WMNަw?d핍t^GnS0:4-&'X0:{P:e|tLZY;:~Wߤ"Gg|toDZY;]$:N>A{J3*`/:t P[QtPCE'?FgD+[J7}>??Nl):+dW~P9E>NcPG @ w7tz]t\؉at4ڻϣOY:[sz?: Pk(:V M?~,M茙GOS+kGZY00;x*ڟG'T^t@),ڝ $W3YJ7=M+)k~ZRt4 'vREgTNmt@)0Y:737Ogo3fn>z~9L@"Ӄ #vz J:{]cfɠ E'5vAt4M茙jeK鳿|V)= hN>{-EgTqMfPZ499j+W37MIzyt\\7*??< ˖{i,>Fmt@iatPS]_|t1vZY;:Խ>΀{"MIt":^G'AjϠ 0/vʖ{~4-.3梽yj\NhVN?΀ƛo3Ya E'Aj/?>Njlu8w/GgM+[J7=MNt @c|/S+[΀;{$:HW~PYE>NfPڛ499j?I;ʖҵx YߊRJGt^وӃ3(@#ZRZu/:_Et\拏yʕvAtR:=. #|OdP :܍N?Tӻϣ3殳n>z+WSj'-Eg)w#:H<c`PFȏkeK?؉΀?~EGq{e#|4u7)qN$TTKkDgT^t@%$MN3[OᇯJ":cZR/_:/t wUt@%1atPcY C8{<:can?H)鳿~|t&'o3Yׇ699N8: ey[F'QttGOS{Jt @kw):_M wzPeh91+~#:.凯J":ca+棧OZVtёtV)3*Ϡ 1$#2|yRwm+[JK^[tM um`i1 24yo /9vA_V֎N(VN 'ё{" ;{P)ehyA䇯J":cׇ棧r%:tq: '޽||ʕlGgԂAcPFqZ-{؂j(oEghl0:4V{(|t~wN7iZL3*Š X0:.`/i)Nl)}/ Rj\IW-:w/G'?I Z8=؋N24SES܋΀KOӴ:n>zZY;: D+kFgfdZ\<( Sq(kF'MI믢3BuַYj\NXejeK/{<:kw\~|24m@)[EgOEg:ߟ`':`a?NirrQ l)}/ջ_Ft+ёrP 8MNFgTA+?>Ndֽ`?|UvA詁(V?؎~ûϣat@Mt@,p39y_o߳^Qtߢ3pf P1P;go^E'TA X"z^t|/R>:(KYZF|CyZRt@LNSq>424Vq>N{}*$DR~x,$TV`ڱ{@UHV.ćƺI.d. av'P;MBv!D4ej3R-RXh6碙݉lٖY?ya/~OyF F!Sg}TT+3jΞ#/cS_u18>wa0 uo$zlgΦN{ehj&RvD(T+z5c_1FOG=:t2]|NӞ#'R'43AA`F!Sg}[<gMQ=>]cS|=GNDǾb .g/Dee)upzMkWfZ){ehjVvDϥ΀rQ^:&18~2'F5kp& ZYkNC'Rg4A^i~.udzG NPr\=zꌚ5L{ u @=ܞ9J9up'S'4jeՁĠ MM`Oqܛ3jZǧkpT ոứ35v8Sg4$ul24 @=8Y{g x gM!'cp|2 Y:h2,wS{=s6r ` Y{HаnϜM0 ףZYM4ރ?Iꯧ}ހgbtS&#SgP)-NNl"Rhe "/ϤNP3w΀R[S3Bǧkp O:aLK[Ht+hXS'42&{'/lG (dyAgRgP)-yYH!cG'Sg44Hˠ D @{&nw: 7RgԍgbtS5v8zN6ꯧS'Ddml\TVRg42JK@2:ʥjꌺw IDAT;:hC?:ؠ\/6(s3 Ǡ |Z@*]cDDCWee)y=uF])d;bpd OF!Su,}vT>; /ϤNh8eKnD)Ix(˗g̻3N31z|:)@ʻbtS Z3 )?u@C[J9u@1(_*_je5uФƞPnw: 7Rgԝ?t*zGSu18>iLH73 ;D | ɠ |Eiby zW 5>=G^ǦSW=>yw>ܞ9nzR,_IА W!7m}#3ࡔǵsRgԭ}8|wؔ13ju o8u@61(_Q:hr&R'C[=Rgԭ3FZ^p:tܩVʩ3 (dy Oh gΦNhXe+*+KQ^:hbm}7:ڵs|~H'btd흩S18>]cϤSyF,ΞOlP(d;Rg4,hXe//NNNVףZYMRKoFP1u ؞#'@vT`F\ p{lfP @:kp xh^lGT9r" Y:Hk찗ۡN-_q ?lll-2JZYM4C`S,Ξ 3BO=>y@`uq/C2 Ddm3셨Vʩ3ANR:x4ulkNEyFꌆwǁN|&aLOGee)uY{gtvYagP {h" Y:ZRg^je5uJs=>31oj ONhҒgA툞Kp=;: Sc:dCEc2P箝;J9u=ţ7:iekTVp#u@F!SgX=gȻ َs hy@ OByF,ΞOl@!ˣD r{l`PQ: َsD 4Ν2޸zȻR!QvNµsR'4l,h e`N jE3w΀Ms_F:qSNR:eL@*FǾb r{laPQ^%Wf9r"ulR\zk*uF=8ǧ Q@1&ZYkN6lje5/Ϥhe.ܴjEǾb΀MS7?:a ǁތéS{0&٨Vʩ3 =4Yav|y562(wQ:zMNMuӱ|ňV)d;bpd?6,O| c28*my@KtgϧNh*e./{m}1TLꯧRZJ:7: c2Xz:uA㓩NOmfPZ)Gi~.u9r"uljޚje5uJC+d;bȉ(dyhzd,_b$ԉȻSg4:{X<:ϲ)Mp=;:)ӑwNeLKMy@HД|:{p5&3`S-Ξ 3B^:yH 43g:B ,_qARTJnb툞Kףp#uF=8^z3)F@)/܈Nl@ȻSg4A؀37'"kL_je5uFȻctN5v8FnL̵sR'1TR< A72Z{'`U+W'Sg4B#y1FO-5v8fqB/18>:iy 2Qt=m}#3`ӕǵsoh:m}q7x4u 4 c2ИոvT `B#u@Ӻ=s6u@2(d!E&R'=s6g/h:lG9bBfL׵sZ)x4Sg4\TVRg4-2A;:ĵsp#uFSj&OGP1u ԥ=GNU3{ȻbϑSg45Ni Z<:kB΀MWۿje5uJS*d;bb)1p'\ `\;w*up,MZY5(AؠjW'k댞Bc,ǿrwJ*N78>]cϤOGyz zMDݟ:9 =2pJ7R'|;Sg(/\gSg4B#x*BSlʘ 4Ji)nw:upC): 3gS'4=2p|:k{'3`,Ξ 3^Ǿb<5y::SfȮ5ԺBd W^3A(/HƞeyPvOcSQ9Tǧ#Ol Q:?n#u@ӻ=s6uaPZ{h"ulu2DDǾb<5y::@sʻKoWƵsRgS<m}é3^˗gRge-ΞO;:LR6*SC َ/O}SɻbtS-vQSgwwĞ#/ "/ϸe>G:`]& ; ם\c:1TL[kpx1hWfbL 'S'3gS'oܹs*uԛ+ݽ/u*dy_kQK[p=m}#SRK5~DibT+`C `T+q)sAs䄱sQ^7?:/zT:zNDޙ:Nך8қS<:6d9b `|tTVRgw7=Rg3gS'e,_q P'S'(/H_(d;bϑcq+^!c{&u MJs^ j,_v(@-1(Mֵ G[H RJ9.K5o8fNR=>SmR3aG'HtXg9u_aPS'NN-WYYz*d;bϑKoF=:6,&OGݟ:F7;]{1gΦN/T1:=4:\yz\=3:ȻK|&P:1z|: َ)6*y j\@)/܈2r,_IpO=ţw΀-8{>nϼ:{=8OM)zGc@z =FÜ;wJCwRh+> u l>('vN. Y]cWy|~jܩN'| Z{h"~ ZY jPKg&EǾb΀mqQ^: )>OM6 @r,5L ]{p"uaLT+| 2r,_1*ԇ=GNNmQ_je5u PvOcSw qOE[p je5.]<J׸=s6u0(tc.uS<:Qӱ^z۪cǧ#k3r {:=GN[ PJsQ^:u| {h" Y:Eyz\;w*u=G^ӑw?B#u Hi~.nϜMEP1ƞIX=:Ν;RG@=VVchٞ:Z ӹR(/\je5v=:w}6q: R_DO)@Bj/G:XG?h)N/T+qRgp-XIǾb΀ms{l,^H=8,6Mǧk)@b7;] OF!ۑ:igP6S'ܗLף4?:uc;SPFKoFݟ:H4?gΦx4SgT;wJZYug{ )dy7MeL#펮ĝ緮 /GK5u Xo"TRȻbO#ZR@X=:Fޙ:MRKo2):=s6u`P6S'ܗ? 3H۪Q:wǁNŞ#'sQy@})@X2˗gRgw{h"RZr]P' &,EyF ұC^3`&OG)Ԙ1z| UJKqө3*FO l7w9:EK5v=:HۮZY>(h)a<~Di :ȉpZY5wkSutC3؀Og|Rgp X+}6uyQJi)u lJ|~jtN;x4^*#Y{g*Njܿ_,J#^1P'.=:Ԓ:Qy6QDib\=3:-{p"JIH5:?V^I_(dy/?BkƕnĥRgw\?J0([[S<:={_,_1@*/\+)l3wEi~.TR'y@|:SuZYdT+Sut cϑ3ؠJi)~7Rg VVchٞ:={(5u$|eƨLɻ≿y6T#>u%u@S=4CϿ,Oԉߺ:XG?h)N`nϼ< 2Z kug{T+hjWf$)l(/܈Ji)u@S;cWkp,^?]'ԙKowk3x@--_0uC=4_ޥp#u(kiۤc^z3Sup#;:ȻSgpg/DRNCΝ;RG@VVchٞ:Z#S@2wkkw|o2Y{gFUlB /Gh)HޞJi)u {h"uX+!-Rh]{x(Y{gTJKQ^:S]>k^nkBOͳV^YFbwNF|G3u1+~S3oICjInʇ6Ş#'3 R|QN!B#OSo$u@]+dy9r"FlG-^3u<'C7w9:YCOG)<;> u $V^>(;6BGhECo$kNTyF\~絸S]Kc腗o8uRZgSg 6h)Ʈ#⏷R@RkbV<>)$wFOh*o]=<BTޞJi)u )>:p{(ϥ`mV,zGSgl]{o '㭨c:ݽ/g[XG=:xh'7C/:tW= 6VV$);w)\yQ"Om}#QFyz${h"9ZwNw}'u3FOGK5u `qB|RgI 6)((E:+/\je5v=:P*F[HTV|NMo$F>#^yF\z{*uBOaKuX+`mRYY'| M?Nu-u $+wE=:wFȟo]je5u)dyg,O4je5>~c0PJs߾:MdPɝZO #N) Y-j>!² IDAT(u Ԅ+3Fe/ylwFU#\@kZk/g_^:zGPnu@1(ۨC4?R FeXϣl|5 7 CJ5~'ZwN<:Q^R$w&ɁMW)-ܿbjT!cњU+q̴k/dP7"~ M}Q3_S]O>0*]<G[HTV|ux4^xA VVc_^{ ԰߈G۝:OA Af_V<})@i N,/a;+QNXW=C/O|]oވ>(uص@ 6ܣhPe G{i@)dy|CFe<;zG#ku5;S ̻߾:XGOhwRhMCh'hVa 3{5\jo P Yc'7@ڹS3Be +ݽ/u+dy|5>)PS+'ᾴZ<,s+&{h"'vN@srTJKSu 5 ȵsoFyz AHdO|[4? FexP-ص@t}pT+L[H|::]yH9԰=GNO&VV;`D+1tlO%GbqBܩNbTQ*6]?, Y:h"7?gMkpg3D;QK3( ѺsW,_I5Ǩ 2Q)-NT!=㓑woH#^;6@֫he gS<:`Q^_V9Fe ,?%2}*cSѱvq)/1B*dy?jd흩SD}:m`PVV#b ylw-kw휗kad흆e ˻bWɿ}> Y:hBj|'c:X /G[p 6٥ZYM60(Zc:`˴ZwǧsNdTdXBG~'#kL47_V `&>:MV3`*+KOylw{AaTfXK=ţT N3'1T?E 342؝Zd]wNR~'>QNdT`XhџOw $w{oI#^UJKqܩl#2P SWlBk{bq|Yk;:cXO=C/&sbL\=3:XG!cW#kLv(/\O62(5?ފo0/ΨVV[WR@ͪ41TLB2,?/5p#.5wkSu r ` T+qRg @ڻRglG}QWR@*/\7*Ö2,^Gwje5>?ODRND,O𵮞3u٥ZYM@e|[OmGbqBܩNV^>Ȩ ?e:;յ(/\Oğ?j3ug/Ob7v` -^0 @ S]MӹR@3*C ;ۣc]>ʪaH$k=G?iHyWf;bp|2v=:-vܛQ)- 2PcZ 1TLmylw:jQR)daHwTܩNS<O~l\|t 2(5p=z>PwD:jQRL(/lBǓ{>^x%=:`C*}QS*lkÝAA,OFbLWR@]0*Ch)F==ţw 2$4쓏Rgw1cSg ոk3egc|Ͽ'Ή96lsBI'6:#;P4a4" ڽFZj=w{Wºv?WsT{/(U=_3lZN|sJ xHrSQ{ذngbvt*/N`TJLsWd sR'@1$ԊK'FbvT .zv @wT2PJ3V]._ 1?9:Q*Q-vGsWDDf&. |;upMۓ:UR8eb(lƍ[RBGwfͷNTZܹ+ZRhrœ;dZ3;~:.:ů`{'= ; @[k־IlLߌr:F9[&ތ ۟1*C 7~Kц(LjtH .;cKé3Xe p#6mY}G..u@;z0uT\D+u ƟE0:U._}96sfܱ(g)'(ttǮ#3?MMMé#Oд!oMDCSK#)PUn⭉7cgnwFsWd s P-mߋ XkHl@˷oC5l1uĠ TBlܗRg$ #pPM-m>;Z[(\M%7ѳo(o5$c2PrB)D}=uƠ TB=(PZ}d*/NLCӆ(tt΁O}ц(L?]_<=\w5-ƅo  bׁ(ttN K'F\K @Xk ۟N̚\C4>%ޚx3u T[奘|KÍT5h'#Yq.J W]k5-ƹcCQ:hܙ:q3@e |z<뿝: ƍ[-ƏONdTjUMR4wG9+ͷN쎞}>~ؖ:`Eгp<$rPXe */9 ?󓣱TZHUɨ ,O|>?;"o_[Yԁ\>?Ԓ: `U5c2Pv 8⛩3PeJh؝: ۟FOFV־)@rBltl/E'4{5b,jP-6?7~Dk`I҉xc3h=RgЕ*ݬ Խ\Ol&LU4sը UoM! ݱypo4wG9+ͷ:gP4wǚ\C$UuH̎JE;~>eŹtb$u̠ ThO\-;6?7(҉#3Omϡ<Tkokg655 OCӆX7u@hw?K)Pn⭉7cg%u|K[ ƚG"+E9[L2+ttGh\: >;T q*/ *tszlܛ:b5-}ěnL[q9?6¦U^o_OCj/~5 ݱ&א: 7}G3f ABl1#Җ:b44DCӆMUQ|K{:Shܸ%|vw/DVr: {oi/^?'v>g(waLC;v· {fPXk`R莬8S&OFBқ:VM._<7#"|]`}ůZ50&աD..u bvt̎J@ydӦM?K<u7|e>;z ΀db̎E0:[ڢ}`w|s[aLC._]Fѕ: rvdUp_655 LCӆX7u@ٰ?KS&fFVXkHnM!o̓{ﹸU^laU>;?ע?rB$aL1>?:*ȦM~:x0xvx 4?9^N5D..u $Wch̎95+Fn"Ș T/ Gk` *CQ:*i8u`b4wG-u @iܸ%bdKxca3R@Rkr QH,ލr: xbmϡضPkr 1=;O@)NOT!2PZ< lt'"+ΥNTZӱa3Ԓ:*B._ ۟̓{;-mjΕԩ:H@*NOĵ7Pߍw~KofͷNS8}S[nߎ|K{#kP /E;RgԤK'FG=(ttǮ#/]:1Yq.uU̠ 7ngRi!u Ԝ(NODksA=*tt;퍆 TZ5 hbl-RgԴK'FbvT ?&˯K@*NOĵ7=iӦ>Eif*rVJ5;^|s[JYq./ƍ"[Azh̓{ѕ:];v8SgP655 GCӆX7u@Ekhj 1?9:jRi!fOdžDCSK:|!o̓{XkһQS\O|>?z EkߠUfLG._]F"bOɗSgPٴiRG#OP|%n:jV._m{ES&fk1q4Y)uPrB ;:nŸ'CxLѕ: g8bPj̮#ܹ3u@U8w¶9:jh_5.2l1)=0&ʊsq2PcZc l10>ѳo(u$2JzDo0rusc2Pmp?.S3e={xRgTT=:j^sgxi!TXAen Fk`>"+ŅW@w8^L@ȊsqԐMMMé#{͝3BCSK[c~r4u Դ8~,6l&rBIDk`<Mݱ&\*/N*X._'v>[_=o07nIGfbEVK#c2܏+'_1 ל IDATzdӦM?K,|K[<;t:h}C2;S &cL3QexqO xm H:RPoL~7SQJGkߠaFRɗ. U}`wJ@ro +ɠ 8OxpcGEij +aOFqj"'\h}.vFk`V@9[sdž UƘ *+#SgP @˷ųCSgTrgrVJueض` Sf8}>/Fq|9}}onK ʊsqac2Pe0.S3ae:0͝;SgTT5l?v4)=(gwe/cPhsX%8wluTc2<8gO@3(uLgvt\:q$uԝBGw;)}*Lwchf~>\4w|s[$Vh\c2Pe܃útb$fO:nFxWN7F_Ku'/DWw0u b_8$uΈDf1VVG: ~0;3.QFqjUj^ΈLsgR'P<S;×SgP\Z @ :8wl(J3WS@]jrjH9[(NMw#[K%v{@#2ITrNST]F6 CɊsq: @w8^LPJ3SqPRKҰPܝqԄT\];92ܕj^dX.N 2PG;cׁ#3^qz"Ju+/Ďsg`f8}>/Fq|3 ͝QJ@0R ˘ %+#SgPG @y_q;21z\9r k̓_NDGqj € k~r4.1BdXNN2PgvGϾ5>^k`;Pԩ;2sdXNFz`9eŹ8{d ACnzX&cG9:ga}Ε(N70}ɷ}`<,cP.|k8/: tb=\k|!z2S R :4w|s[$jL9[ *eLVsdžRgP @ʷųCSgԌT;6嬔:Mn>80Sk7@h殝wFd `%f҉#Q:xdX 6: @eN;/q@>4a?OU(\R'-mwcnJ@K>b1VBqz"J@2(u?v8:}=|9u?v/Yqĝ*Wsg4w3 /x]1Vʹc8}>uuʠ Ա+٥#1;~*us=G3*VŸLijd sRί~mP1͘ +8= :>;zar),c۞C"+Eij&n5`[>4ܹ3ur Eij`%w @{7)@)ttǎ]+43ug\4s1nzx8wl(Y)u q>As[_[?u@q*O._ Ek`'x `vt\:q$u;3se_KPJ3S1v` #6m{ >#3@=)tt1@tb$fO1Vh\xu8u"zSg$O,T/ G-u P-J?`Y8wl($T9c2##[Ke|K[<;t8/}ԺT;6嬔:xdX :@%1(DDĮ#QK'FbvT cl}al8=-bpơV`%["];#6P`LrvdP1 7;~w8u@M;z(J3WSg?v4P PubfFq|d s-Eq|,JWɗ DC 0&j1J @1(onKPb;6dT*T._/ ;D Ԅx{\4s(gi@ȷE; ݑ| +ŅW5 Rge;vGϾ543 9 l cX1"+~hpn7h<njK>;dXM҉#3C wxq7TT=:ʐ@]ɊsweY)SQJf|p4&h\iPq<9:Xdz.Ǻxf'LLWj$BU)g1v`d sSC  Sgb pH̎J|BGwxi8mS3QJ߾Yq6u| ݑ"vWs{["/D+uƞ쎞}C3`Y?.w3jk[ј{1xec'S@8x#ɠ K y`\p_M|\2 bfF/Fgc)8LDDs3U-ƥG5Ę @zz6]O5^ަ˿yK3w-qGDxoZ?ajr7#l&n8*urgrVJˠ vΝ3B9[sdž*[ضPRԝ(NM3ܫ:#_>_0543?F0:X&d*Oڛk~hJ7y#47x_G`>j]}ttjO?g ڙ3>Vsg:p$u@(g1v,P%-mw!s WlaCw~hX1Uһ1z\9r `<h;!on?6*CˊsqpWeOWT;6嬔:G[_[FAZ?<6-EV&>~9+Eiբ|c~=-x2/vI9[ cLV_if*ƎL܇p>+O +rC/c?nXm鉸g1e,O?h\^*k?R"\=#T>2]}; fOǥGRg!/DWw0u 8O,}}ܯtT?-3`]:1RgZ4:\km' 2 ݑoi)=U^&ތr5IP\\xdLlz|63a ԖD\9r 'kRw_r:Sgk1v`fR@ݙ?9SefL3V..vG._H;u@jhj ۟&ތ[9U^&ތr5IPb\7ڙ^U莧+oiKoKAztM9CqW;Sݾ_-N&uP=#+z@Jp !}-ƎDx;z0/NVH;v\~]>A_ TNrc7 @u2(ܗkgN{͝;gCܱr)P|%rj1ٖsbO5H-ƍ゙:A̎fM^4*5k1vPfR@(LCqc) jmL l|h\^ SS'}1ZR x`e }<7u J3Wc)ܵ7уQ:XAgߐ1*` t9uܗ8-͠ pfOE9[L@Dls0vɵ3c(LNUWڃ: acN{Zi8uP]nbͣ ٟ:h8P#J e# qcX*-NVض=_M}3)?:*7+>:>Uif*.:ښ@uS'=ѝ:XF43:VLVsǕ/NVAϾñy˩3OkK@ [ש>VH9+|#FeƔfуqS`}=PϧNVX._}})<:GTkTjA]{R':2P9cGEif*u <8+'_rVJ\b@XWN:Ae s1;~:uL._H,;z0q¨ ԶkgCQJ43cGŕ/G9+VA;G/;ZcPx(\'Rg.2PJ3Wc)𩮽q<Ǝw#u`$mSxHMS'PCZ Pq< *Q}# }PJ3S1v'BikRo_N_Rw_OΠ Њ^PضP `e sqP\9J9l1|%Ǝ9*j;~wؘ 66:~ɵ3ǣRg3(, O\/FϾé3vc;z0'GSPNJ1v`}-u 6}C3 T !Yq+5+: QBGW>Ѹ[Ѹ_A7͟>+qnnYV`NI\la..:}ѳ'Ajb\9r̎J$гס>ɓ7R'\9rX1eesc5OMsTm|n;-1qOX=Fe~_Sc۞CfOǕ/G9+NVY._p_j!GTD_M+Ơ lfOG-u @y\<|.>r.׾lަt9~LDDb-슱]eJYq69:XaNS!j,8|$S u`$ ]S*w P7@[4:l1ZSgԅ~&rZ_S7537?x{3 ,ȊsQ:XYq.fOǭ.Esgjĵ7DžW#+ΥNȷgdމ_kԐ=&+3sk3`EUijvw)5kc=o:U6]^r)X{'~L:H}`wa=;XDl1.oĭRXqeцhOP?oh\^{t9?3?%>:}Q7 IDAT:XEKěQ 0oďA۶Pt}3Ho_-SgPc&=~ΠMiO>VDif*6< !4S׾W#?9=ذxcTZH87F_x$ >e\:q$\ }c [EoԘ$8j +Vy)<0"zz4Z{7uCm}/®۟=:5xb?0*u8=ϩ(tl|K[?GF}`0=?3mb'5ՒvihdVmm&toMwusY]ŽW=:ArЍA9&pAW*0%kl^xpfo>(~IQ>_ׯ_M-)C+NZ'{eFSPP@aN:r:ߘa+f ?PUٔu ?][0L'tu6^4\'m7Xsu) Y'bQSPp@uOJJUau 䌆^n?URZ,(z1]^n"'PEV>N%0{L}%"]m޳O[n1-Yg g4ᄬ3'\'^2`NF`Hpu i jϣ\ZoBMԕmYQL:>]1 [s /bQ{Mu29Wj@Z]`Q]^Ǭ3'.vԕ=@V(gOWCuBNXu1wשvy~Yu=ޡ_U?by#љ/*zu)wuJhxu5@u(,7?\oKlJ3rFI+tavu;( r6]Լ;g KNF'EoTi h9I%4T:@ll|Y~vTRUٔuXyɌ~>ժ>so̳2peV%#Yg䔒"W-P@6bTrR M>"'^: rdtnXuu6yQER@cPKj ᡤbQ 2d [+f)S2D:>c1'x#6=Pٯ+{ y>}< ²eҩ+۬3μ\'cd"PFO::ߘ*Kyay)c|ų)Ssx)r5zC|e&{Y@֙=_N:@xjj~:4#L'3Sڬ#@arzX_P^249~Oi R$ܗywN&}TFy5I`*Q/i(7^Miju |wÏPJ\*{ x`ѹ7x?"PFO: c2 go\ZNppkNCμμOu,T,3ӹ7۸T6vy+%x:9h\'md@ f d [j*)r[ɹU0˵M ۔Zi.EOr qR M>"'q*y/j]':`ܫM|OER@ų:~ t|D:Z sanm!03RK{)z1Q#x䰴L7Ql{o0$y~mz{Zu@cPKdF?j u rD[qVY d!N:zŁ@:@ғZݺ::ߘRs:`ھ}ŝ&uyJU勺rGsi9u2JGE +9^@ga9n}ZsuTMiG) L{ஜTBlr2 kNFGZ:l Ow]n(`+,"WфNAqνB0(N:>="Ou <)=bQʦT3k:MX,02C2Ƨ^Pݗos{=)  wD=& dXg9Au9bVxh+}eu$hGeDѫr7}2*336 'gX<^|k|:IҎS DUٔ~uJhvͻs)@NaPdt|D{krnmǬ3pSIJέ҅59n**ԼKN*GX2C2?\NWyɌu PIh Y |: 4ΩTZCwrUj ղeRNpVFe,OeL72b ྤbQ |Un`Qwi˷3 :P3`,j73_x[7n]{DUSſ u6yQ4{Ը@>=3s'JŢ=ޡTu : b6u@u̻s**)Uņ)4uao\MԕmQu*[\9bQM9U) FOtI%s)ׯ_M-):ߘvVw[gxm&u P/b,e@VKGT x)!0h?dFz&]^nVNF3c)21ky d1{M*6lU Nj ;_Tu 8n׼;g,e@Vw:U6ZUMYg>iwB\M-CJsq w甎k<)cھ:lJ?::ە[g9Aa>䜽k":=Jέ҅59ndt~%# Xt_> U!0hWRGJŢy 1(rdTjmoL_9aO%xVeSI5YQVJh5ܯT,yw: @7_M-)ܷ +,[&:Ku2%_G~^y+jSRUnS,uYj~R4q B4{TGjޥխY'x@XTCJ1X `iU6j}x[@xg+19$g:a@ fp?TB[`k lJMh(S˭s+ץI0kbQy!yn:uf/Y(0zAzAER؎S*$Iq' k3ȜTBl2 g^SEV>]sXkxH%3ھ}ŝ&uIVnƨ SN*ޣ Yu28ݥ5{Tsi$k˷s0Ӿ -eS:~ ,so,'/`0(r3PyuSUٔv))r}e-?u1* {|2,쏨S&: (hN*oj]\'cUlت^ju eϣQ^2Oj:$@^aP'PEVj-3j k j1TbOFef2\zZ&}Toa`bQ |U͌3@ j|%yJSx( Ac9 W/iu׭SXUeS TMN ,XgyAsTBzXՇT^2cER^2W i YSʨ 3)jtUJh*uBͻ XupW˖IlCaPt|D{dnu 5ոbP=MQuPVi7R?b4)bA9JA,`ɸNFj]4{y: צg;4 iguupWބ~>ժ>|JXTC]3Ǡ iJJUau R$IUeSRuNHN:(hpR(t|X(_5IIŢ=ѡE:$#^eb&upOm2uνզu9/QsWhk%Er5E>f4^+7mӥIFe 'ХIMeUyu28ݥ59t|: )ԼK~_`u K扪==ȤM0zC'3 yӪllNPVj dh(S˭sU2* 'NFWhtfc[g,jDו=ruܓצg;2 (8-Yg+_x#8nw{`0(B:>gwaS-2%3ھ}] yz IDAT/P:(Xj?\z:ȼ;t|XJŢ<◯jupO.ܯaIp_z=͗rSu &~WUeSUZt]=& G쏨S&o0oX4zCJT,*X'vUlbu1[iu:{YƠ +N*kS=L%3!ބTݭtssT*o0d:\zZ&Nwi.=-_y~,t|D~]I^NOmun=6֛ЎS}&nb'|X*;? 2 bguu+޵bTRjG)-\Pz/8zy!bQͻs9 9͌kdV|+{36cj]գ k[e^+7mӥI>wTB#5z Wpߒ}Cr䅊 [« j?f<`Uu`D.EOZgAғ 5YER`Ѕ+T]67G%I@A) r6]9\'c nޝX#E%-9Q:>rkDff/Y'Ys6yߑUUٔu@KfVY6N*9bP%ɨTZ({= UX0|RuNHN:((B_:JG49|k`I%4{L}bA| x5jzWkd:x`m2u͹7_lZҲڏ#ןǻ:@{kw~ڪF-`NF(N%kunU6 P \'d_DGESت{ }*}~ ܔܛm@+maޝӼ{]+7Xc AlKb.=dD4,,dD#G@g9u, ׯM|Ou_<9d)}uW&]^nR\'3Ӽ;g<e@^W賻S䩖m-:yUKW h: (<ו=)d9Ú=_L_d `I%49v]>~N: TeckvGif_KZ*ZV|;kT+xx&Np  9lϣGTU6eܓz_WЅ59@^+ U勺rQxsi]9ߣae@s.E#5ٮޣJLJ5Y@֪ذU/*:;7n҄[ѹ7i*N }))r<*FeEV)U>-'P:>l9qTBt:ە0"֦g<9佯WyɌu`NH~:#oo@`Pt|XuԎSi ղe)` T6JˤT,j9qMDC]i7t|f/Yg@v ߮g`u'[R?:J:>c 5?i Ǭr#oxi Xb! u뤭s :kTywN%Q/T쬜u;j_TMY' ׋u2x:}bPllǻ:@i\[SKBOי_dT3x#TրL/b9=x@e)?^Tr 2NZC\@ƭwOuav.̮N?\?so)rWec50G*5"3,խ3(X|c X㽈E5{:`P_Vy5)r@UW|S୨Qs|H\'ޣ^dxXllǻܸ*'Pj$d/r7X{b rϬu(|׬d4uĠ (xmu u Ƶџ_:(r=7mzMC9}G:%^]ذUpurXTɾRJLJs onݭ;2 @h Z'r;L'3< e$Mq:߸u`Rs\NYcSz,t|XC]$I`*>-lh5.I%n ȤFru5oFwYYY,r4Q 4zCMa/{k :X0kQyJ&vZ%{`9 GiluJEHzUlتVUlb\R*5"3,=ׯ*ZS*NFw0 0en3z'll*;Zǘ Petavu Pp[2JLJ59$I7ebVuuA#Jةll=,UYʠ WrnuBNKŢ~33x^YqoEdP0.ӦxL/rtoָ Cd'P/HTN^TeCu u1`\7e@+ 2gj%oEu ,NEN m|yYʙNhr&{J?\k\b< J(5x@&vVt: pVm޳1NrrϬu(.ήNi':{ =P=7m) 2WUS $?\3(I[!V:>!IRņ`1 k_ʆVpxX't|D;3,e Q*#0Y'fo:MpZν٦t|:p>]m\f:<r2{*>y˭SX^#cR#QN: p<^6ՋlhNGstavuFN= 0(p&{)u ,и .=/C``?EoǤ @ 5Ƨ^ǻ:| UeS קrR:>o@aP hW^x, Oi`mdfq! u23N<$oFWYʠ Orn9i A{pFwhS[0TU6ŋT3 jz]L's ud;+˟nC32t )Rcxus y`o:Xp:!'P:>l`1(GGi.oEu #D|wqvu?S߽so101ָLEF1#QW y5ڼg*6lN dg:XP&vg:##=a`0(pnWsXg0NՅ5 ǻ\MϽ49dXBaM$y?{[}8=.fbatMGXt䏐RnFT-3aUd:j!HwNW5%"!? 2(\N4''80I?><>ȯO#3 )N<t$@G`팆)rZrCg:*; ʠ U(Nhҗ:H`kR'z 5x#k`@gH^˷?.koFPfϝ2j %׶!6?zE)u,3OIQ&_w>P \:TXT3ݩksO6SRM2א]YL&ߒ1P:c` `9 A-xL4MRufϝɃC3EdP*gc!'li<:KVAʵ/?>cOrkQ)Fq2M-We]k +Hx & %Ըn:nK3_w:Ts*u \?=PBzR'~ hȬqssX3Q+#qQ#3x W!h{ u WzWœLwꔪ5yp(3ө3EfPTʳq޸SKd]lX4/oI,|gWI@LSq]eRpj4o틍>u?g!FKkgPa{泩sVqXLO,2רH'Es[` li<:NPk=kcOJy6uUFf23EmCdk[6N͞; ǸQѐ-}S%:Ji~U鎟MǫSTJy%%PG \=]C3E.{6+JboI,\Cӻ8q4u5Rя%ȵm!:Q%@mbܩ(N2u> ogtzuj]lT]1: !PG \tL<}NTԪ3~"iȬbjdj\qhć?֐EmCoL52M-ܖ& ?3{TgRM@ ʵm>5:9)Nj8TlꜚS812iP j`Qx(u6H6{%U)Fq屙4D&jh[cH0:v + Lw<;o&uNͪb|xO `Nl<76?+u HeϦN3%sO6?(LΕg<3mhyN__|K`X::V_gB_)uN]8y`P ܀G֞or]Q/fRg:SjO,\}l_+#s#>il!\ۆȵmU#oҫbܩ=wxcQ)SL.6hܓ:Xf Ů8Tљ)up|$y.uMk׮}/u@5˵mXoXM(ͯ7^:Hh򅡘<8:nXmC4dr_`WFcޚ,G=G!:u 4uuMq=Fg4MSw*gS 4vN3@`˞M ɉѱc0]ӻ͞;76sK7fy IDAT TsR<ScW~(|sacehp%NLw `wn?/?ۛdI66ijLM-uFQͷ+?~@jEC&w=;SP Lw*lWK!"y> 2(*8y`ol~pW`V)ЙL%zO#ϥ%DL|h`fd-K \ı+1NE孹+1P]kf`IWx/nJq@be#Ek@;Nnк J':X6?+]qިgS@rNEDDqfrm"w# ,ywxѼ/u PeJR'PP/FgS At}P4H ɉ⍷פ֞{"׶!^_Eyf:u,k앱+#Ї>љ2>ɷF>YdͰ?as\.޷3:˫Ǐ*9\љ|6ubjOMA4{TL<}Nn[:nسnZm}>/Ƈ|̧Lgrܶȵp+o]1 #}4rmSU$\3xTscg"P ,ɃC36@bS)ЙLCfu15L<7uԼg~~f>8@ijLeA;ONG<? Q<`5drG)@ x ,SKkPa{*B{AV)S[.D 3ຕWN~+uP|gW=aCXF>8q#iX:rm|\'}N}a~{4X^vFG -s ,#Kkbt;ǫSp&_w|XWF8q,>ee]l!ON<0Ǘ}oXxᕑksm!V}̿=NA~쳕Q?i<6;b㽏řR{|1;:DJLwct;u7h<8:Xf ,=]Bx"u\gLCfut?'&_rǍ,ܧ |sW] O$ \lh'u P^ebW*9[PC*x:X ,tL0;S`]l.gJ1}3Աc0]ӻRMԐJyj ,b ޷3:!:u PFg-Sgbt;Fg4M<82dP`MhL%u p4H׬4*M<hˏOᆭ7}pu]G#׶>u P'_U]VR{Xx5sX$#15?uLXDl~xO*Z vZ=uP2=1PLJP2xsO,¥5FdD<?y"uXdʼnQ8>[Ra]lf/ngSguc`;wG<:j팎hȬNԩ }e\ҚC.3{<>A%pwv9 [:Ii~UMԡ|Cӻ8q4u@Uwv{\)@;~qS.Rp JLwX7!gH `[ظ;u@;MSOt8>ws%u\7ܰ2Z{"n(NKeZbocecS+>w UC1Z¥5H`~"ޭ\J,s hp ,Sr!+JWN;#{<3:`iog4dVC?3bWtLw泩sXƇD<:+w7Fk@ c6EopU xϥN˷ka g9F־㛻yK_ܰ2uGbĖS7''CxtDD C@hHPOGcjh{ u [eR'Uw!7NCfu15L<7u@R G#߹-u gjȮx+uJ:Sj }qo&uPqXLJT2KlP DCfu6*u\gM3>Q{=1{T%ՐEG &Rk)upiM*lC>#2|Jy.ƇA%V)STLKkbRg|\~8y`o?\%޷3:],Tg+#O,¥51: s{<3:2e(2ʼncܖ:-'R'Uw(gSg\h?y"*I"+2)7dC54*tϦpy> Њݩ#Qqhaܰ2u Խ6bTexv?u5v{NDqX\I`2M-q7ctFC&:M7g!W/bǓh;~SgQexnR 5W;S@[=:>Ui~USg\L%z/ 97!h{ u ~x¨u:\љ8TKB xQ)ϦA&E"׶>u 5Xx(J7c`;b|xOgS\? թS]ߍ슷RTGdFg=gL0NMk׮}/u@=wvE{Rg@ݺ _}7u|7ƿ:`AUs1>' N*[b㽏F&ߒ:`I˞Fe>R{XCFdXpʼnc1Ԯ@[ظ;u@=+aU.n}KK[o=ۿ0:>Vi~Uv 977ijıxr)uʵm/whR,_89>nEeL=׹7j[YԘJy.F<:r <8=ѐY:Ζ=;o&ui'O9WdZcGk=S9~qS<9oO;gd L,=QN2@<{oNug]lXgJ13]&bP5dr~޷eqliFv[s#2 s#<WFRg5  2Qxe$ GyK_+[ON3*u1[Wnh>jH෌to'r_Li~U }q9ԡrq:N؛:!7]\ij9 KdK:>7P $*幘<8S#Su"+2)m\SS#2NC1{T hllܝ:*xN|aSo McKR_׉3ysSae|aSon<1V.NjTmClѐɥXJ8Wbu[17:.v33x(Fz5uu}Q8>:17]|Xc"׶>uԼ{ܙ?:>dB<{Ó4Dǎ?֞{RT-'+/N*]1:3QϦ΁+b]3dP`ʵm΀_[5KkG:`98y`oTʳS*֐E]Dǎ)5!z0vߩS>֙R{l߈ V<39(( ,S"ʮ(w3C78~qS e\<ʼnS*?};!:u @͹ ڟƿlE8Sj }qo&u|X4e/?>|K IMc6MW.v[3gb[3,n_m9w7Dv[Ku L<'8,2X+ޓ:j҃짱sNW;px1{T`wv{\)um;G/\Z3q=^-ݾ(_1GRg5Π 2GPsr_ǖ3 ""~_ v 3PLJ,#ή|)DDvE)z"4uٳ}VpiMZjW8~qV<?|$3өSא:O7yp(Z{!:u Ԕuٳ ""JgSgTѼN4Dǎ?֞{RltL˞슷b]ln(}?jdR{K 䁽d%qڵkKkw|cw r!˶΀:xvڠ |a(&!Z?|Iԉ|+#Q8>[R@Mh^y!uDDDc2 c`4o+ƇSsE֐E]D{hȬNfϝͩ:?y"*P Cg:Gc{0u H2/?>;^<{RM2URuC @ 9~qStI;}kې:X@=d3yp(fϝJ2U8q,uTJ6ukNiLܠd6?ː PU Gbjd 2{RKUs]quc`>/]Sk!L%u5)c'OԊݩ#z\[y'7u T C3cķ4MP7V66Ek@4śgʥIwvKFC&:ຌ=xө3:Ր:k75?Es[JnO@{=x{M @4o<ʼnsߒ슎Aw=w*uPV466N+N֞?VNq-RgP䷢4MP2hUxx[: ^+6LSKR8>'M92URw+6N]Vt}RgPg^*lCDĭo_ g9P \c.3(P<{<+R@uՖ3#Ul~憕; rk7?uH%4$Ԝrq:uAjK΀S[Om\HBLw >FcVމ7O5+Vl~p! + z#+fϝ:XɵmH G䁽30(PǢy])u T¥5q-RP~zqw*dZblA8/ʥ)Wo=~59~w͕)Ԩo$ysSήhs fϝrq:uTC2@={qeǠ @4;q7W4s)Ԩj3 \ Dnn`H7'aP'EֻbecS*[4]jГEi>:XŻwͳScHG#qˠ @yXRg@99ި 8TKae|aSowSqiv&u$gHWtۿw+R|,25LMή)PuNέ¥5+ss[QϦ`eZbUxԥ\ۆXSG8:AʼncѼXؔ:ΫدELC{=RgHn}KT87Φ%_{<5$ԭEH OePFyx}3*77.{6>ws%uUoN~+J,VlȯѨR'xH02M-s)Lejԥٙ.hܛ.;:*r+3X"hqSnR$Xdӻ=Mk׮}/u}k[:^vE)`|`dW:e{߉7 rq:NWFRuwvEG`;NX*{jW̞;:q PSz摸34u {I@bʼncq^J*=?|Kee|8WmEcc,K37]IX[{t+M7ELbxrk 4/ rxr)u|֞㛻g 29# C3Mk׮}/u}k[:jZoXli<McѼB(\Z>,3\<׍,+ \ D]D&ߒ:`Y=w:ƞlkbPN6DODCfu r!4*6-00S'7qЗ:ej8y`o'N5dr~޷s#OQ)tkfP팍>:RvE)z"4uٳD$Xi~U|4M2w1<`IeZg UzǻH bPt?D;" tdƺbv*u7`kJTs15?~LTʳsasO15L<7uu3(Pg2M->7O2]Qu٩zb]lNE J~kRgPe<8<:֞C2ר8q,ƞڕ:C};c㽏BvE)z"eƖgW:Ra{x(uU8q,&Eqh\+:#߹-u @թ{RMpC ԩpm\-u٩+C3RgP NjѺ IDATG䁽QN@i[RTw P ԩLSK>/2S `KX=<4ӼBꤺqwRgPcFɃCn>S5dr3w=`Hg{L>"ty\i,4슷R'- ~kRg@L<RM 4Dǎ?}ѐY:'SRg,2\ަ͏ŝMcu;.Ra{x(u\Q)3eL+z N \rϠj@M3(tFǎ@X=w7"zƢy9KϏ}?x{M 2գg :#oIPWFh̞;:`Q#z3*S/2/ǾRg䁽qsSLSK D{hȬNPwƇ e\ۆ~ 4i,+J㍷פR.N!b˵msOu1>'u0(j}$uPnަ34u {v?|=u\32i Dk@;NkNSRM$ ~g`v˅3?z0W^HsJGlne_C&w==ɷ{\(LNX2eD \|hȬNԘ-'+#qgXdW:Gct;u,2 /׶!vFk=SKʠ yk_ݩ3]Qަxh^y!u':\Rg3,pZ{og֧NොL=w4Mư 4\iȬN8ޓ: 2|L.zlod-S:]Q?j=w7"W^HR_o&i,2.w=[R)fϝvE<: 2\|gWt?`i<w7"4X}&WK/3qsu!}?h| Ts1G<3: 2\1:Cr!\Ӹi,+Zw?-X*幘S?ư Pwrmog4o틆9\I>/rmSgu*McG-٩KbIk@ Ds[bjd pM2M->7qɭ˞?j9w6Ev[7{WųQ.P!ԦG~) &};g3*u1>'u`Pk3ܕ:ަ͏]̙R{XCd?|LsR\}޷3RpfϝvE<:`Y0(u㛻yK_ X=[Om\uٳWKǫ8~w㍷$(R88q4u U4Dk@ D&ߒ:T)teà ץ!?5o}<:c5o֞5f]~[ p]2R.N(2leZg Z{Ԡ'\x1 pC:c` `bjdL2k}Ѽ/u c|؅hǠ 7}k[:Xy>&_QgS5,};g 2Sfϝ>:`2( 4Dc>UqXL)@ i֞wnK{RMl`A w@8RU*׶!vF>uRvSS52,>=D<S#cϸAL \ Dk@֧ '\Zp `2ɷN#~IѼ/eM<'MP rm1S8: џ?y@xwooǨS.A%z|YT˩0!^7vfew7t= Fi Z8a9̯Ob~u=*ٕs 4vNeJV 3<ڏ~{;S-ćzdsP[cxz@06_Lbx|)NSP%z|YT˩0?y/ZS(%A2>\3)oDdJ`뱸v;毭@I;inPZ2ݭ{4 U1<u Z1*s`U+g1J9H" R`첹u18hŋ{Lbqv,ݎz%T IPKv;i̐׍18hyƤU#2r9ب8ݭC. iooNj(NSҫd՘_]?xR 2\JVw7P $3<ڏ~{;y9P*gOpϟ<ǩgL A.U7nF%z 0Fi Z8a90^EdW`,47R*2\ŵqN# {xzV<HZ_ŵ1Ym!X" #(@W܏ŵOS87*NcpЊ~{;G{AdոCNjᅨ89N="[?ҍjD;L=`* L=L=7 bpЊ~{;xoB_$nGz3bpJ=`j ԇEkTF2(&I)0f2$\,/Rxo8xzq9LdTV#a)3CPzL׍EAJ?3Jixy}'ǩL-݈j D{jL(AJͨ-]O=^7G{ooG;L=RU+͍_L0AJUW pAq 1x} Z\JV}9T+'@錊jL8AJZ_[0Z18hh @i ԖnDz^vAJmqv\H=`n v(0Ѫ-xzL1޹k0Fi Z1<ڋA+FEz0òIԖGmFT+'TwH=7$(@Ujܼr)3'uc"Lln!jK7ήRO'&P>2Lln!n{YFi Z1<ڋA+FEzPr1H ucw?@05W>H=^<.331{1^iDDy,Rln< pLVj}9F. oJP҇E.NϿ9ez-8,o6>w7"(i@(N_H=FnL 1<29{GT%(\Qp.ud JT1HEPp28xy)0seyH=to爛0d`zTR-FDD,}x t{xߢ89N=2׍ݭF<?{}wMlcBrE^,9lJ K``P@c$ !AB,A bmPQ8 ,(ah dv) Y9I\LiM&I&ǟyy >xl2@C0*Ԙ1h2eaT`s,M[ QfvX,Il2@1*pwʓ4}.u ɨ ekqX:b;RܭHT+s3Z-[!c2" mf|Ȩ VojZ`Z-x\̌Ev}9u Ϩ [>~dԲj`QX:ɑ@"eaThuјK$dPh*FeVTñ4}.u AZI-[XRJ2@S2*je.^ɨVNAi)ZȮ/NH[XHOEbi|'GRgu(:`;*2@[xe".LAe]yr4ϥAQ-[VN܎ۭ<9KSgܖlu٘ prR(ODDD%Ze)@0(,2@=[>Scd;bPhiFezX:Sc3dPhyFezRs3eP ղjZ)2@*\'GA ݪZVM4dj)-`-MKZ[:hmbq#u@=8}C3&5;B,ΤL.u@Z>aTTl-f~6`3FeTbf|(kS&ePC6C23CQ˪S&fP6>1;5fLrenQn,X Eō`\~gΕ'G#6 ](C'F節PT+R-fGFT\ekS:Sū>iLH  ]2*rEōг?\~g W&bD vGW}SmVbvj,ϥN0(YrB:1jTZH-[VNE-\`T+sW#ǍuŠ &2*ai|̌E-N9mbq#u@ l8zOl٩bt&u{2(OE&ekQ+)+:'G""@V<9ʵ)Ƞ 3*muR\~i8jY5u jNV""zNbl\nfV,7RG78: X>:R~dfTW-[VNceQ_\̌E-N+mbq#u@+*C'F#ߙ:QIHȨ ԇh,MKHʪk13>l-u Z3㧌MX,nhu|!BϾ)27#:`H@D-PT+sS%,M!c2@i+#'|!BϾ)дf^ҙ[  @<GRg@SekqX:`Rʓ#Fe`T+sqoFv}9u 2(Pʓ#Q˪/N4}>fƢUSlb:=p4Rg@Cz!KgRgl\>2pjZ\~i8V/NVee<9PתZVMڊFnOg:1jT(OHƠ @)cÑڝ:Jyr4ϥHʠ @ qhzNpT+R$#uwUcf|()x6&Smbq#uw'/#O=GR[,٩u%:W˪Q0*@˨ekQ+)us8uRD[DW)p_JPڊF6GJ[bi|NE-N[lsQ˪7x*rs`N33^[XH*C'FjŽEr-u @Cؑ:W\VS][5rܘ h+#|!BϾ)pGKgcvj,u@1(rBSekQ+) ɠ @<GRgVߌrK(OD-C:~ZVMڊFOJQbvj,ϥNh lsQ˪7x*rsha\'GZ:iōlB8tbԨ I\-EhԲjbP_VzNN33AЉQ2llu9.4ʵ)Mˠ ⑧#ShR+WKQ>=:R^-Fyr$jY5:94٩bt&u@Kh+#Gop(uM嗆cubK@}Y>}"ߙ::).4:ōԟB8tbԨ wlᕉX0:%}_VzNԲp_Lв rBSPV/嗆US42ܖS=p$uuhᕉX0:hN@[Zh=::Qҋ1ϥNڊFGJ@b+WKQ>=: wг?\~gz!KgRg pW =oTzN`dqVN}8tbԨ @ XZѨe)|2|d}{H X::`PM/#OL&V<9ʵ)ܦ\bLԲj<ӑLG4}>fƢUSpڊFGg:1jTAղsS etvGW}S\\~]_N]2( upnblN#2(z䩧_L IDATekQ+)l2l78:_:).4:MbPm{0 G.3u D,\H&3()쏾SQٗ:eeqVN` `[?6]Nh9Kcvj,jY5u [Ġ I #3ZB-[٩X>:-fPdFP V嗿)l2${0 G.3u @Yxe".L` B<}SBӣ:1u ̠ u!/D}=SPG PrB}y(v8:n,M٩e)24O}x|7HEyr$VRP 0#O=)nuR'G"::fPRdž#ߵ;u z!KgRg prBSlje.ʓ#Q\K@0(@<GRgl٘K@1(@C8}C36Mӣ:1u Ƞ г?\~gdj)ʧGUSР rB:1}Sƒ}+>sc}O:;%*T֢<9+WJShpeh*}{H fs]3fƇ~ŕw>?Xxc}6@kZɑȮ/N tu}=uxbc׽o9Wy,&߿^?nwrO)2\NFg_Mq]?Lڰ~xl'iԛX0:bP7x*k?S"Fe~~#u $W֢<9+WJShA흝é#`\-E>s8u {ŮN3ţVbfTT+RТ вkrxRܖ'vǣF_}o܍:]-[+}>.LĻshaehi7ci||l?;u#QK)Ǐo쉿ͺSYZSQ\KeX> =R/Ɠ_Iq[~?:Rekq…xv3uDDD[XHbgGwNFގ)weV|z4jY5u P/xG|&| ux3qDO~9u=mmWtTl-bvj,ޭLĠ Kߏ_I}CꔻvΧc毤NM:).}k^M﫭X,nz/#OL'vwz:cSߺ?~~#u ܵZ &bt&u |(2!zFwNZ7v0uƦc\pWV/Eyr$˩Sපwvvz.T|ǽTGz|NtVٵ}Sղ?Z:nA n_DB|lρ9@y??jG_[XHdgGwNo :oNr+7%~cVGxOl-.LbLk흝é#ݛ^L@==;jSEGK÷?:~R\~y8ѫS#1(wfzODg}1ɿHXkR@DDԲcDԲ9ōȺFP At3ŁS$׾oI@[ZѨe)i &(cÑڝ:cw<:}+uJr߽|H@ ekQ+);;;SG@YKWDǃ~YeO*W)ux0?X9:r3㧢Z:A$nO.}?jZ|ϥߋٸgG-uJ]ybgF\_K@ ekq…xv3ulb:MW?6)@Ḅcq)ugWJ@[, Q˪S`-pt>:H@̣7RԽ[sg=Sh2rO)m;;;SG@3zv3EEtLl'w_{vR4{v\?nܓ:&X:WfVmbq#u4ރl8rS-Ѿ':!]}xl \2Sc:{9ɠ l\dž)xxѱu[SZBLߦA-2 &Rg@R흝é#[K""z6ѓ/3EG) |xc}OpS@rmbq#uރl8rS}=yt,t:|CղX03SnDrBSw@̣7R4[sgV/Eyr$˩S><:~/}!uFC)ԑZɑXRJuɠ ԁރl8rSpǛq۱:ex׾::4}>fƢUS@2(u"/D}=3+WK1;5)а @(cÑڝ:VGzb|b>FeH-[H\)NgPD._/ŮS=denő vH3v{DsQ#"Jro)\@4N4lѳge}"qd. GxL&[;",\iw_|@6FRQڑѡ(R@M0(UoOtFcfuzVǣ݇y2u נ*?ťlQO5Š TwDѴ~sZ;Fc`6\Ju8W_L3*PEʥczt(u $2P3M?}S@U=a nz9z'SpS1q(]M5ˠ TEјY:*X n2\Z\yedִE}gHg?ǺŦl>u 7Qʔѡ(R@]0(50L#P bghQʱp8\,/u 2PcZEσ#Җ:m6SXfaنKSFeO0eS@3(5i3D4ߜ:nlC1|(~*ʨ 7PL~Ϡ ԉ-Fgpl G#p)u ʨ Q:҅)1(u{[L4fVNn|<}(z'SP,l$K)UT\K:ӘiGko_f;Fc`6\JB9W_L3*p_#Q.-NAS}{03S=a<}(6eSRFeMaT=~0ο:e5#zS7p4tKA 0*pʥ8{`̌NA z'M/Ŧl>u 5Ĩ 7PK S`PmȴN6c`ñ6:u}/O֦N(SqX8^ИiGko_\od>͓SKf#3nԩ8\.̦Nn"2Ui=LK[m4 Rz-(.eS\Ra6?ssSe`PjypNܞ0>)p;U\Z|n8'D:X&ekݾx"3SP6=Rg5).g'ōSܙ\=~0JfS̠ p]3M3}g*Pod(nLԁri1ȟ<BBnwDѴ~sn۳c݇bS6:*.7.|?u PfN/FlEc)ownwkd.NO⵹@)Lѡ(LNA`YtoG-u \<3"nri1?3c#S*cPXvξݩSJdf#3*6POri!u P ɴtoG-u W \92;Fl5477?:Oľ[o[؛:<?P5ncu8KTԩ88KQ.-A ʗwSѲy[4fR'oܞ0n-Ni*.STǟF0:eP*؉񭍽slC1}`]Jw7 ߏ۩S R.-ƹ^_23ssKGG#XKypdZRԽǺ=΀6wymdmfN/FlƠ Pwʥ8\̌Dσ#Җ: ۳NQ\Z77w&g4$$2@*LeotFg9NV:ӣCQOpZgx"oN R'@gS'@]*fc׿4$2pxoo0uYr>uԍ3ō3 1=:3c#SA?K=ODKsne`nKqAC2@]2(o.[?ڷ-Fcfu$ʽYg.nM5\Z|n8'D: 2_afl$NbˮѾ9@*.s:j!AQ.-bfl$zI@9O֦53v"_}1JfST2W05`tFgߞh̬NT7 P |92Wazt(fFbˮۗ:`s?:jNaTL~ΐ W0(pJfx&ZEσ#Җ: }PL5*ݽQ\ʦNQ:ӣCQOP \xs?}{1:uU3v7йP \2izt(fFbˮۗ:]^+Sg@xe?^dAta6g{[(nLU*z$K)PuJ٘)5ᖎSGԲwĖ]{)_*PNUى}qPU  Ϥe.H qG4fR'O?-۷KJ/L$,|?uTri1νRR2d{13v">[Mĭ+R'|[˱΀HUC2u ~sj-75muѾ)n|w>:ʹbguTkɷR6u T,C2i4477?:^]^3c#0^|kSo4fR'uo֌΀W\Zi?)Pʥ8KqWw/N+ttt|:ٷ'1:u PFR h/L$^K\Z|n8'D:n5477?:/x|t9ZЊ[?P^폣wR.-ƹ^ӿ:{|9u@]̚h~d7۞lå)Pq\NK\Z|n8'D:khnn~&u\Z3(L̚ȬiKԁO?->wR@E).~~[H\Zsu ~Yr$-~/2WElSg@xꝧTpOri!u_ @i߾#թSv{8gSg@E:P2۟:1$P]I[8^|O㳥Ѵ~Kڸ"uPo-D6ON,ls:(k/_߽F|V: +pKGG#6زkoo?u P{M| HbxM˪\Z|n8'D:dPdִŖ]{/u Pc mOERXvOt|Pܘ:M0GbflĐ @3(PCZEW`tߙ:!g?{Qй,J٘)ejPKypdZR5y2ϩ3`YY_ΐ @m2(PڷA2 qok.pSVM7!fPtFgߞh̬NTwkd.Nى}qpS,?aC25Π @h4Eݻ Sze?=:nԩxA:Әi-FSU,P}`6ON\3~1/K)pOeTfM[ta l8{:΀;Oō3;#dA:״زkotߙ:Rg?M/God&8pfN/Fl2(@DDtoA255^lå)p;w~:!ADKypdZRU(PƞcS>͓SCsRgW;#QO@2(5ˬi6,\xlh]1::ľ8sqk 33c'bta6u UΠ --}S*m46lå)ԸWfcC3 b̌D>7lHƠ 7LK;SU&P bghjTqiU<>~ K)ɜ<BjAn82Zr>>͓S1/L$^K@+fczt(fFRP pӴo]iiKTּ^Sg.ng'NE>7ssSe j`6نKSb?=u >dm ؉xAMW`t)@6M/=N 8RgPGʥŘ;W_҅9!2,LSt޽۰ pn~^)TkɷR6u u\Z|n8'D::fP$ 5oগu|*~voq3qlLH2$֘i۝:2ζ6\JB:sqk<;/u50u*G05:A*BfM[tpo?u PE xxqOS0Ot|Pܘ:43v"_}1JfS2(@E1,\p4z'SP^폡sK G(R2(@E2,\{[s1XOB"ťU(.eSPJ٘)p P W+Pζ6\J2:P2۟:*W:ӣCQOW͠ U1w;"Җ:V@Ѹ),k3b3c'bta6u \32T;а pEz'c`mLMľ8sqk L03c#?y$ʥ9p P W\ l8+Sp5ؗ:*pcfl$u Peze+m(ƏGcghd.'kSgPfNHSMaPѾ}Go-wN*ܺ1q4i}=u 7o~O=: V.-F>73c#Q0:n*2Ԝm?hXF͓1h6ONVM@*fczt(fFR1(@2,\{[s1XOUq̝E(LNegPҽ-ڷN*X?jmm:+0wym~ K)S1363c#SkИi;ݑiiKTp4z'SԔ~@ Css R@2(ש}M7N*Ƚp,ZW̧NzsƓo?ťl#ӹ(R@3(7HK{wN*D?jmm:j0xmY ̌|n8ο:A2kڢ뾇}јY:V@Ѹ)U\3|3BlO(R@]2(7Ic):}{ <Fodꔪľ8sqk ؉x{e`o]iiKT{[s1XOR\NKW(f#ȞD:=2ZEݻ/u X?jmm:"ԁ37fNHS_  $Y]=9@BV@Ѹ):P ~T#136Bk3Myh߾#2-msn~^)VMPfNHSWȠ T;}h3u ]kފM/G)ɼ0xm/u@Z8~̌HK sdP*L;oOo?u m4 R,sxo}7w Xݔ`@:HK8p "@{;&է>ќb {q*b#TB*Dm)"\o .W쎤|~NlFlܱoߍ~SO1]r3j*qy|GQMǩw@PalFz p$nYUS2b6c0ݽS['l"f_(| {oV]-"2"` /ۋFzp~?Y^)OopMqy|~)hb(V9-yӭF+$'?Տ?I+GxNL1s%%(,=n/Z9-V?kXUcr֏D5Ԁ ,n/6{"l܂=ooj{a_?ٌ[e1br֏('5#(|GE#[K=ao}<ŭA_/|V~`L mY IDAT^J#ˣۋޣ;[7쭯~iލo_{7nU9Q\Ŭ*SV =n/Z9 y~2߾}_.(|,߉j:N=X12hb(V9 j}n\f7}=~Y|#~9-_fULqy|$` 7"lalF#[K=ao}h}O~'XpLY?nuXK=M19YUAdE\&kS .br88O%(܉n/Z;cSOx)U1㣸<> pYqpyg+T8&g<>rtz&($wqFzfUL~` Bk饞qLA^idyla䝭sV poE\,y9Ǭ*SU2Rhb0Z;S% "*A`4 P;aN/AY^lEJ=Dd8A`%dh<͇߉N="2FPX9yg;6f< s8 +VZ4s`%<SAv{y(.*Q NEdn l~饞K*19QsV ghd<,#./ br8&g}e^ X1eஔA\E1"3*+QM̪2,^Jَlq`f?v4ԳnLUD9XDd eȚڋ=4۩g|bx\4]Ĭ*Sxe2kvqvhvROVT9DU\F9bpUqtzu\d͍;[g5l8]D5G9H= I5#[o?oSG5G1}ůgk6ErtWoe"(ۑ57""Z{|}`U8xl>}oVQ.|ԝ +hFdO3b4r4YU>|s18] "(/h""[{=n&BU O_stt ܱi""v4^_/ <~zQ%"bVQ.^'YV X۟4Y"fUSMQMǟbxegAgp3ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBPs2HB P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!MVӬ IDATLe&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P;w 0_P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!h}2Cn ;IENDB`pyo3-0.27.2/branding/pyo3logo.svg000064400000000000000000000241451046102023000146740ustar 00000000000000pyo3-0.27.2/branding/pyotr.png000064400000000000000000012432711046102023000142670ustar 00000000000000PNG  IHDR팥 pHYs.#.#x?v IDATx 02޿Ġ4)<3.OCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8z1 G"o..] ^Ce R(RdxK%("EJtT@u:9K* E^;% {j~sm$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBPKG IDAT A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$֬Wbf؟onwcm}?e8sZgj87mto{^|õ[#/K'qT=X4+?d/Vnbm}~6 TL$"8w7ڍLx24ժƱ՘=z%fk_/+wv7nXLD{v؆nk;}t?>/ARhύhύ>utbnލ;c3Z]z | SXLıV؏nmcs׳aXLqV8^+={Yz^|_z D H7mtG2-̏hWJOy"[;ݸ潸`Fcd7= ˼祧ؙåg\㕸g3Z3¹͘ @ߝ;݌hEkUR hr+g }լWb31hvHsz% -gN֣=7Q-zOPzh{L8{^zIc {X }3ժƙ"*~HLJπXJXhύ@B2QreՊHg˞-'jܚ+n=uZ-: Cc{s*u#Ơ VKkKYl,g3Dcm=)2rՊȕz[Ȯ^nx?#<|dꄡq?x ͩ3(fE2􌓨UgldBϤ΀ciJqiLꌡV3&@O8@_=\M0tJq[OGR ^{Z)d FA(R:c(/eώޜRꌑVZc|NI4fc:a]٩Ge,j-uȨV  92֚:ܟf:~G-+N=uY_<82rՊNZ)ˍe,ɗz>gR'0Ĝ:/&S'RLI5,RtY(ћ>W_ oqu r`;{G#nJ!ug{`]8Vk3~:n;+OUPFo~~;=o7_E|}cM 2rWv3;=$nݾ:!ҝ3y'{:*dt'2\77ߏa6ANƋb~:_7Ww~o0u Cḱ 7ן+uMgۛSY('{ߺx^KJexdr\~&uon_ۻ:!su38?ݼw=H=zH淽ֵŷv8?VGr5u|w"7Rg0D63c2Cn=uL-+սF\~&7c2J!֌b~<^VRG0|b\1hgrܽ nݾ:k6ˍ8Uz,u Gl7>NYNL̷JS>S-+r5lw: >W!uic:#xts|I|[jf{s*un=^k Dvr\q"ZNB\kD- nkèP6lPeX_R[Rt ל6V|4,fŸHA[%C`:*ō\)uʉ\<umju/uA-+}T4(~&B/u&n=SbLfSȑ'bQL ԲBܽ nݾ:PUyn'?GsW;{-vrtNGbϕkyaĭ7>}Zȗb9??:Go^y7u996ϤΠ{y'u|OdBꔞћ;?wrà cc;+OUb;?z~|wsAOݐ7X_Rgya|u'q)$nΥΠ^i|o΀O5c20*@`5Ÿ6O/g7Ƿx.2rbk{b=GZV/F1u ={ؼqMØ'~Xzǩ3 V{#ڭRŅߋ+;/S{קn%J}wFdt˩38ZVr|wS7+|:u=vXܿN_X?}/R}'/|?u cΠ #(sz:ݿgn*=ŲaFn=jY!u=l]zCrRg'OR;o Y\٩v0?|:1fPVROedqރIH6XΠڭRܽ nݾ:e|(;Uz,ʥB~:17c2Oīo|w=Hzٳ~4C(ƕztʩSon_+~a83C8x/ب׈݉ nމ;,Hdd>qރXcH`t'Ƌj|w"^֌4CUs?Gl;aLfl?3:1eL6@N0j^#vwRZ-u dZ)L `8Y_ʢ(`lՌ 5#$xZKu[33N+<ėNT 3㞏F'R ė?QyoOSq|'ucf~d+c`KYꌞY_Ƌ碖=::Y_bcyt_ZEg:w'=7j{m~s22VJq?V)u ˕lc{s*u O{^X` 047FªQhc9F1uv?GFT+;B9:(c2G7(``(t'}WιpJnl,WS'@RT(#⹋өAdokm2ucj:>OQ'T)ҭdx~:1n{3H>x_o:cjJ3ȉqރu~F@-+ RI2tSǫo|w=H0(@~k&fG_>ėć?J V)u [x罇_)_Qzs=nB[k5P10 8)@.moNNȭ+;8ح`m,WS'SKYlRg[Vdl/Vbku2uC*kךdZ)D2(@tY(ȵ,D-~z*y΢e#c˥3lSgcV)gZ>_oN;[Bg3.S[k|5nLik5Gw }Up&6 p2["sxtꌱlc{s*uCl_?c2Y,N`9 @l,WS' jWv8DRy'+uRfЂ尉1[VR'0œ 7bϕRg Kg`:!l:!tiLt'RgZt prXdR8>r", KYx\2pt z[*޳ө3_clc9+;S2@8I@ntONs9IU΂A]Rݺ!85@omoNN c2T%u#ʉNràEo6q?E| R'ͩ3Fouʱ`䇿/eȅZVF1uȩV qLK>݉ޜJ1:帴y&u#v|ɗF1-CaArESSgC[16Jw"uHe80A61ZVR'0 ݅өFޅZ\kD-Āp[7CۛS1(`moNy0vqiL >SF=ȅb9uX8ߝƉ_B=@gVk3blNΠv뱾d@.J~ s\xUJ06JڵfjF\)5Rg ZV3djF1`\^s 䚍bT+e=HJ!gbcqn2Y(ө3N#Ubku2u=bLfxt+1N\UJ0B\٩Z-u l `0.֌W=DN` mբ( ?zˠ uONk{Nn=uT .3P]6v F2T+~f*u!Sbň=dP e>:[3J!5<ѕzT+Hg})f:ce8ܟB9u &"ɹrYlW3roku{\S IDAT\~f*uɘqj;:bP\ɨ̈XbQL,nb{ӈEgѸ00&3fE2$dT+xsN6sVk_>n=ϘhqGF vT>Õ#*EgEe{A߲9e,c"ɌA꺤k6n=jFdjW[>nSU׮5ɌFz)r 6֗8ܟquղB/e3Wf8ܟI\-+n=u|B9V35V)gZly NLg:#+ōEehXmNN1?W1)jө1ѷҭN`8a@2O'*bJw"u `c9Kj})ۯb9.Rgmq'dC&=ɴ[R'pLJ!^kT>d6mSggSղBSgmoNNkdGRQNI#,(9`°XN/t?l|><ةzb6FeYN3+JF$Q .,5jb5EM j33b;3ضj^lc9d̊Nȉ#hJ݉8ܟq~f*u\)v3F#Z)dꌱŕhQ1(@݅өRx񜑠eXN΀cY_bc9K7WQᵵVZkߌɰp<:HhV q?3#pCN}$_'jY(΀V #͘ 绕 1'HBV qe[k)|dxd3lSgLQͩKH=>Ę ,9qk6Q{v:v]Nm;.3ĪB\Wv^)HVRN,0pV)u}ōύ06:Nl~]NqbۛSY(΀Z_ʼ롃z\X gS'0`ڭSRϸl@Q4^X_bkmxGڭR\<: >n=֗Jw"uCʠ Y4t1.>|J=>S'@tC c2|j1#1(=*N`B\~&6]ZVD 5(8c~km{ӈ٣2&Qt+BevՊoO+;|q:u{z9c$U+zl8;帰ZK}Y(2{d8b9uCh8N[02ڭRZ B oJ SղBSg;ZV/3&Ñϕ(`8 @[R'R3Fe`;.3֗Z\ۛSF16 |ZV3<5:!6n@K\)^c&S'@=;rOҝ ~ޜJkd8 2 Tg! ^ˋ+݉)#(z|1V(U-+n=u$1(֚1OcL:ߝZG Y4voV ^#6)Co 0P/[t`J~z`ж7rc2Jp $dEZ>ݕzSg ZVD Rcc9j[3r(gVN`S0>ڭSȱ,f޽x݇sYT+~|w"u}j|_ۭRx}gp={/R rGoޏ}^ܹ uk͘m9w~v|󅟦HƘ |q c2\)nx.-_/Gҝ0&@\XEsL_O 'b9uCZ)+/,uJ]XLc gL~;G]8:!teۛw!bt\, ֗h63Ƙ 0?WI&*N`H]<ʘ~o,gd΢1AL ANb})/Z棍OԲBt'Rgg,G~bc9+;uc2 J:!D}W 1(`ϕ }uro{s*uB|2&tޠ G1}](N`D6q?E_SV'S',Guۘ ) ڭS!J!??YdV1(#9c2T%u9gP,S'0`w2ݓRFRWQ#f1Cg{s*u‰֍ɐ b 1>H(FDόͨ3!3(r:c}ix=+Jrl`8U+ZLq,dȫR4UUJV qe[k)}qa.oZE- dȻb9u95Zg`:V1(V ZV0&PXVR'Sev:1eqȅ|_y&:e8ܟ1&P8ߝH@N1AR,p&[q9(Fg!Q\~&""~u~q_|w=Hɘ D|Ax:u\)g;?QgR'@_ϕ~5r)DD;=ˡ[?;īc2 i2Ξ=QFӍϹK[WMq,]kFRHIqĭ[><ט 'wRg3eS'ގoGVgSg@.ݽ {Aܺaܺ}?{p_oLQ|qH1uXNj-&B~o0u::rkQF1: ߾#3V)vdzŲA~AɖRV)\lb8jDD֣Z)ʄXƷv r䱳g~:su3sݽ w/nݾ:%ڭR[.vsF8/J`HK2A6q?_x}b[|<Y(`t'{:xٳ`ԲB0u˟՗KV) .Z)`|k{Rgv:N=ϿuOUx82sWw:1(@uNNGERoHX,V)B+7U+XN7O@ڭRxdq?_潸sofr[X9_CgA""ⱳg~:_QRgoEb[Pن~'wRgN=SFј #Z)K{p$b4ŸsAsjJS2Tu*uX:߭N  SrY(G-s`9A@Ou ҝH@b0jY!ڭgW_`55 @uO^y7u ,p:ڭR4(G7^}ヸ{Aܺa|u~Kd ҝH@bejY!^΢p:Ο"WgKYDDxq_7ߏ}x^vTVXW_ u 7t qxj)l7cŸJ)3xc{Ts>况B |Z>N7q`O96c;w8H^s3ƹv8w%ΝoBbwϹvחޏ.ȥ`JQqPksH9YL=l㵗vl,k?]N=+.Ǚo_@=nEc[SO!ʹcİX,@Ƹ@ϛ}O~R.fZ\=5cxF1μ+N:ylΝT˹OzF}q5v)l߽;[箤#ʥ)}wO9-?1Z>6X!L?O GH@7svp'dVQqРh55YL=ulKDD[Bgd}xsSXgc[SO`;՗z APwzBϨr17.eV]R.~pSO=sΏSμ+G1R8ЎĹSx{mw lYr3O 1tbSG^˧ChNSO`.ǩ#CQ-;j 'at8m ed%aƶDV9W{ʩpzhAT 8@OȧTJ8yx(μ+s cH`|g^}!@'e:h!{Hr@â2JP O(s8vh0e2; TJ9Q=Rh[W71H=OL5@LnRL?ޘީsz^szBT]caQrI,2@i61|8Nz-zNOQ)y t9ղbYg^@ET3a@q)[*\̴͹zSN='RO'(dB˻9YL='\ૈ%(dh!dN!WrZTˎ'l6'6Lj6\=tym^=1}9&sZȴ\=f[t=Ah!^=1z@O2RL?ޘީsB㣅8ud( !(Z>~p'9YL=LC?]@=AP9F1ǩ#CQS㣅b3;՗z@ =kt9μ+f[Q-{\eȀSGbbL`#!J)3xsSXO:rqȐ+r2 n_h;yx(μ+s:ȈB|`%(㣅?>'^˧1 rSN= e(s8vh0~Z-bD\uCboA|\=f[$31VH= rq`#(*\̴㍹zK=gM5@F=3b"(pFjZ̟ncȰ@ "(bSG^˧eHF­MP!.Ǚwlk l>n1;UJ= 3y`TJiǛs8zκ;z=`bz@fsrA P)8hNSy$r.oc՟zf@bp[h7./t|>7{R#ߗ IDAT`k1'16@Q?/]+ROd1f[lSOG'16}r|'2r̶\ ɥuR.fZ\=N%R-b5!1:F{Tu&Gkqn/]sۛ|>7˛5A奵3 &k61|8~|f%^W6\sh65!(rj|+sS@<;k8z@ReR.fZ\=)?窖s1kq ]^{<LpTJ8yx(ۗޏsg|>7{R^&(AG 1|8-o{' O&.Q(zp 5x}ӫܕr_,lk b…Fj20:}r|'W҇Oh!,C tJ)33`Ck2\#2BP #eP-;:X!'(2| !e9#5AN4ؖz@A:X!'(tjq&G@F^˧e0"(e2BPղ#M cLROj2!(2@xjz@W:F%&(2@ǨixN_cbz@WAzNQL=6 1+eQ)9(ATˎ5<,'/21VH=k d @F婱B ]KP(Җ @Fd Q @Fd Q(;𰜼:h!%(2!(@O+}'t%AzJ@7!(0ܞA:NO=+ ^{<$(2!(t| ]IP8#5A!(2!(tz-z@W:Έ CA:RxrHc @FS(y$@v=@OۚzlA#M5ue2BP #e2BPHc БeǛ!(TO/}Wv,^JiKPHb}=bKi oJk?_O9Yƶ{K奵xkqyim>}x1 bந%_z & 15Yfc[Lbp- qqvWWnRW|ڎV۷_|YhO߾-4d p_& q`O%N=t@拚b48?;{#N_fcz oD.x|X^齸۷c )>㣅 ZL3S}q2evT~O_oƏglܖ|<~q2V/Z{%<K @s-e"Ab"MJq.:V/DRi@+1/!BPbPnQVnވի qw+RO: ^|L.26o@,_ZXY+bGLS㣅8`}a0޾~#No]XM= nD쎈ŋw3"3[er&&s㣅-L?YZgoď^&.˩'thGCdz c(Fj8Ue~zBf@ow/ueqP]O\47W{Ef/\hL2q' EK=#Se^idS˗e/D ;F1L5\zпw^߉ˬ,^ ^Iz dرC'qXʍOb/"3;q?f%(5|6.s8}F8}wkQ'|leb,_:+ zr2@+FyxXYp'2|q!+ @w :R. B\RnDƝbB3 m }S.|+qn^1z(b1}c˗e/.Z{%@`21bԼ62po_߾P$ֿw^b'@P2{*'e6ީxjztDL;q ^I7;՗zH\f}T˹m }S Կw^,^$2x!:2!bTJ3 w˜=A>{#J=cM╣y<<tDD߉,_\K/ dTc[ leNFވg|lk fZg"_,'bS߹K 3ŅXk 豝;w~z>O GQL=e"|r㣅SXwFgky ŷRȜŋf.ԓ@ݩ'az1.s`O9wh0*\)xgtܖ|v^^˗ԓKSX!:3S}T_e\:<LGk'b-TDD\:'2DP2^6/Lsň`勥݈ݍ; ^I; d"Y̶b՟zþYYx;0IdF`$(5.Sc-9(Ծ`s @F4''˜[h^?ROS}qPTJSn Hi//Ņ; A(FQ/ WG]KsCl*bӱ`}=sΏSh6gRe& qP6k~8zFGyߦQ@FʐfeG_ܰ@gړ2VI= &0!T˹8ux([@wo|+VR`⽷\\JItAA:zeZTJu^@7A""V/ގ22t̶bտWzFGn>ye #gs\vua/~Z+GkH?Бe˗nf.7ٖO=XWWn_i|G_w׮[VcT_:2R.Jl݈ݍ~ޯމˬ,^H;u'(qyqp_5;Kk1R `3lr*?9k||yvVVj䌚u\%N Z.$bK U ݧj =q`v.{u:{ZD[;6,.K Dz{HSTd#l7FGQV#I\rJFvg:6c2iO dN6FfY?q!IW 1/TER݌ Ϡ ~=:M|?H1t7O:69=ӳQ.EDDok-zVJ\1(#d=0(^?Ncpv! g""bEok``&I\@A)xJ ` 15_jDDdLos-Y?q!x2(#d u0bKQ.EDDok``J\0> YoNم(]Aw0.Zn'q2(#d3H9D*(Uj݌ Ǡ kY\\ȧRӳ19=R mFos-"Ip7(S'S'G$jLWcnJdNtmFYOpy:M}3 _(FRDDt7\ƭv ?20b|J/x ujLWcnJdNtmFYO0 N%yOS'K/\]ru)""mEwVdw;AA;An65_j-^׉n6q Fzkߠ 0VbKQ.EDDw~00$xy,ڏwHfjSՈnFok```z:`hLNlK1ez ~<CePFzk?u{:D*(Uj#nDok5y/̠ u +:m֣f=qcPF,..SgB1ե(Wb tdyĠ ־A)jLW#.Gw7Xjw[AQ;Fl-^׉n6dPFԝ~/\]ru)2:se`Dy?:^.?J-JZZtn܊n'u0 ;AnFգO(]م[mFV4`L8Q#l۠ 0"^69=ӳQ.EDYjtis F,..SgS'|RK1dy1(#l uODRRq9Q?vRǜAa۝AbjSՈnFݍ[eŠ ~l-^+݌j+mN 20neqq!:49=ӳQ.EDY7.Ǡ ; ώV41 [7(ҩhߟH0r|5rDwn\ƐAqb3rV:OeqON6(0־h\N49Icj38#w[3c`\&"nDwqe` lwN| 3(|mӳ1x%aPzk?uCθ 20 H} IDAT<ePDss?ϞL1c\20&[ex1٩߈n: 20&ۃ 8wjF=ͺqe`L>F!u#hjSU20 XoNx!?F!u\~"JZ*zqn+u$aPN{:DPru)եnFݍ[NƠ =S'R<ɓS'pLN╘[2z ~48Re` iŅ| 27K1U8 #ڍݸf=u 20 0JZ*d{nDV,84e` NDb$fP8z:8r(Wj$K ; (]مzh7Vbև1ƂAA Ř3ݸJVSg42{GD%p*(Uj݌61Fa Ghrz6]Žh7Vb~#Y#D`^R'[R'גOD^?󿎩I#ǍOXo=Hs8/ ojSzعa+1%$NTP+1rt?n'ubPxzk?u0r(UjQԢJ+s{-K qոpz̼d$K ub\ZKn܌Rg z:K*[;sJ.u0|S'"IAsGqjDgODRRة߈n: 2(|;O.DBdN|mcSg93|۫Y/q[A_+N8RpmGI1LS'مx[;sc  L $Q8._ ׮ʠ L[R'|x0,3r򓩓!dPx&۝Ḁe2ʥ0Lr{m_,Y@bNOw&oNg|s 'TERvasedLavc%z[̠ O_\7,cD`8:P8oxps :>oq2~tE 0 >zףXI']B1]]R9p2 8 c2c2d$R|dN;\_~ v{>;X(0&0~>,NF0Y?u 78VŅ{>70S_8""nf7 ɜ=:r{eƙ3g~:`\}vY(l~^{<,zAfͽ$M|7}ꌡd{eJsZ`]n>bn)qq!g577tpf=erD~|1O̥(Wߋh7V"I;qsae1T.\|| n}ޣa۫YDD>~e1,i}̙3M0 vke>Yo==~?JTN0gONx!?ɯL1T^WgSg|vf+ZMc!:`}O<~Vss?~灙 b=e> *(UjZ~qݰ o9s淩#W'Oc2|a ۃ{9*7?ɯL1T^Wc33a8Z?6&S(6ޣ?Ik_;mL`N~+us+]a8"e^q~d F/V_ŸxXӁO\_;߫ME*?Qdw;`$|̙3Mp]n>Gө3@ss?~;1`$'z3uP9Gٸ+Ũo0,aP]T:ߢ*FM A2_\єI0,eNʕd :aMR@2(pNWVW|6nJeN'*S'GY8Y١k2,@I0(pň3ޣb`a9+ EUNUf9 c Pt eRvtaATU:^ş'*MgX:uWEy y&u@ٸ+Ũo0,@0(PN( U1j @3('aa㦤dPNRevh|ڻ⒯<u61(Go~u|\q7#;1uN]E{,xgo/fP$lyhH}fg0rEsLM[,Xqm4,@1(p~ݠ @y_, IDATFP{|5zi,pQ9xheP$ 1fptGV̮^?ϥucX1vڜ(sP MS'@I3lmdy3e,x%fj 7(eNҚE'=]E{,xgōэI{(LeNҚ<:^Pu3""bLM[۴<{Q\q7rI2'@Xҕ: N(::}.[\4~ozL(N@0(p Zّ: IPtԴN@ӆ(h߿)F]~a>ASGcc3aCNPC1g;^/}kn 7%uyʠ )z Pr˦NU*ko7swdG7N 8EO4wNyؐ1&ncjަދ۾N O8E:-]3!u7(K#W/ߛ=+S'AӰ9:(a353ӆ(h߿)F]~C2(pִtŮRg%_YyPP1(~*?I@n}:0\2=bžVDZÝ8e/]{ň^b@Ox#nÁxb݆ٝ: ljMm]_FfjˢcUq'jb҄A1i ąp˦N);ӆ(&~x#bϚSgp\~#PZvŋģϽںRxixiえx=""&d`yꄼS62u@Q:!/U/X}xtz ZSgp>|RGA╕3Ƒx'oŃ)I\68&}bP\6aP4~,:>_n0~yeĸ:,N;q߉X<7u'Gb#]sA1ScH%Sv(>7쎳cɕs~bҒ: q:X>#xt՛{b#s8 db!qK@Ӗ:#S'e g7=:hLɽƑs83?//aLlj//o֭]s(AlϦN+֤NiLy"b9Q^Y: Š @ZќKɴnYW.ݩaںbu΅;bΟ/ү޳mT+FSg Ő3 RmqG!.{8v`,}=lEsgO7ٯs^6HCb.go֭]S(bGNNlk,W]թJA^T8mzِ ﱩ+_9,ޕ:"=:! :>PP|nK/}kn]ؔ: H=f;,o!-Xz9^{Hh5.VM\q7rI%à @/գ3=bͱ`ٝ:+O,ۓ:<0-zi NթA^9:Nkoɳ_khΡttvǗi!""6%~6nJfP<ܙ:N˂ŻbS(p^|+c%NS'䝲 pZ2e,ǿqVLQ}yA^rx<7Fe([bͱ`ٝ:"y%\#u  yb`8#cjS^6'+S'2hON`֕:"=1nx#S֭'oj߿):hEkZbc3nq7ǂůNlj7ǣL@Ȕ>?7swdG7N(xezي [=lOL%6uNttvƬyc;u~Ǎ{{/ թ A^9:c;_^#:: zb-ѺՠnO*uB?&uKͱ7ňis A^sXp ֭]1~X[S 6u[UoN eR'},Sv(fl<7{IŠ @XќK=1ͱc)=՘5o{u {{/Dyeu$`Ph3(Qs1kS-]/&an}9:p1{3@9ZvN esǿqVLQ9xh$`P=ܙ:"7kxpٞcv>goGW:BLMUUfԶPiLy"ۃ_u}WVNH_a*RPd纣_D)U[?W9xat}U:; NPf )D{d^zsg$$(5k~z0uEf;&|2e{bWb;u }hO*uP@2e▋VM\~]Q9xh$>gPi]{Hc267GVy>ؘX:W]:OH`Esg@֮?}1JΎݿRzt՛SX: F>˾˸#;1u@0(\ \֮<{KttvN$::cWc]SO++O=mZK3:.KQ^Y: WH`c|OX5o{P^=$u%"S}`|5Xbظ)szADִL@2&t<{QgvNdsg#9/u@3(Ȋ<:bL>ئ83?֭>M6fp( #3O.{6⫮I=Ơ @BO4wN@ɳs?y+u ʡk[[KߚэszAV4R'P ,ۓ:CR'% Sv(ָ^=?kN[R Oh;o8}֭]qwOoLfT}}4q٤IfᴎcǎرcGuEFDeF>nuG<ڛ: =>|RGѡ?$?}}RU_&MSƤI =4̋#8,J} >ĤOʠs΍A眛:(-N@{y|o/O2y{M$0nU_SN3gFCCC}f[*{9pZfA]Aٙ3f g73R' mjɳ#lϦN;S'');_VM\~]Q^Y: (Ae̊\\wL=M:5o͋De=!,Y#ua8˨ E>3uEhLM[,t,ǰqSR%Ơ @գ3emDDĨxax>qY鶴mQE=*GR}+uEs#giw}=*M2y衕E,^|+""n;76n'NL\7jkkcƶmbfS'lj7GV'W:1=uEndfW`1JARǍ眗:(beЁtumظaC\s5 bs=ON(ZUe^w*ަW?qUקAuFqN0*Ũ|CP|c#oX\v㗢:uP 䱝{-޸Pv}%>5m6nFKzFeN(=ԴC׽ S]ؔ:(Pe܊\NSWяOMQⅵk㶹sSQ>=:! :( hO);3}6V,ΝթcP ϭi38U٫"sI]QTjkkcѢE#u9iP7 kdfWXQwaS(O4wNTT!(Z\sMvm466NWٙ:Ns#.o+*M28Yeq|G%E!^X6N:gTw{Hꄼ?ߗ!Sv(u] e11iZ (;-M7߀a+JBmmm2(P@hΥN^Q56uQ)e IDAT)Mm]Fe О:N !WVWcqo cc3xasSW.FeFeL瑊 yl@eTWaPS_ώn ,MGe tNΞQJmmQw~ yb`3-uyWVWcAo 5?Jo!,]/f۞:W3;S'i;A膘p4|cP{,o1*~gVDYu >Q΅;RgPN(:CNv*HUq79EࡽX2hEs.uω~&u' e{Uo(/1$uB^?&u@9A7zʏɎn ,Mz7e К<:==u6V>td)_5*ybLM[8m]ʪ8crADsgUV~&u>^X֨ IѺ+u_yyRٙ:H]E{ ~ڏώn ,Mz 'e +;R'UqVYu NCCCCvm JXGgwLŨ n_?&u@Q1(C18qyeU1v}Q9xhU  @ڹXlyh t| xdɒ¼?ם: /u:"Wٕ:ؘ9NvtCLeqh#Aʎ w߀a+8C3f̈?u%lS[WL%u_YySٙ:XO>+o?OWVqt 5-];x3RgЃjkkㅵk#ͦN-Xz<~eAIo>4%_y,.lsǠ @[z8v=:$|"u6V>t Jܝ[Rg= y&u@Q2=u mWVxO|گDyeu YetN(zq$.wE zĉOA ɳ\wviK=>O3lܧc­э}r>(k~ӫzۊ3Eso5N: [ E>3u2OUc,bWV9gP{,o1*[p3,Yl6u%lS[W̚=u@R{r y EcȀȔJ=jL>=߈Ƅ[<9O 2EbEs.u@zplҤXө3(qKWGW: =  3١1?QNA"+v=:u'NL81n;7u%nWukW @ـ EA[S'@&zb-5A"EF=ecOA[hQ466ΠM%SgLꄼS^10u@Rў:z̮>;4-i^e+;R'G&MJA?| <{K >*uEnAӘ/9ι/*MA"sXp 7c#11u 444SgP6uŝ w EeAԅN膘p6nJG}yz@MOA*Pj)5g6u@ٌ\OPZNغ;ߘ:2U[NP|b1a YDWWW MG`4gN*Dkɢ;6F=8cNje`4u@EڻT ^5d͗}2ujHlz(\LpCF.ԧNȔ Utg0N(F4u T2S_?7: F8q?pdxblzL\ Uo3*$?oItl :KgP`k[ȜϦNµgx u\m*ҡS'0Z4rKI}5S@fB T pM3 uM Sƞ?pSNL0WǷY+;S@&BZkS'd1xx,uU`ժUՕ:.{fo_K95 Sʳo~*srlA!GNt"טObP`X8'%u@>?_*&jH;x.u5yL1uBHchlao8}af./ܒ:!F4u d͟?_SGP~cNQgS LYcW;/TC55{!"2e-Ma tOȌ}˚Sފu 8MJW4vqZ|H;ߎ?<:I@mk4&>G \>@s,uG:r:>॑[b럋#Z[: >ų2!~0nķ~o:iX0': S|dD9ڷ<G/p_t<b bb )\]} p>eȜ/碫%u zeAtj|fʖW.nƋdjc֊+~̗ٷRq@٩2N@{"6oN5?M+N ~;4sX6M֦7bvÙUf230T[[>q uL 2U;b/źuXC>}zs=ۛ:.3xx,|d|S>bHC3϶~;.F̮?ĊN$c^%NLQrq;O>|ows~4uA*Ԓ/?d+}l=A2{gGP:2R'dJ]S!u340~`lfvÙU&Vc*lϾ g;#?oi1z9P6e  2ãeZs=7΀9? u WQSk\S3xio;MoĊDˋsmDq{{؁R@Y8,m32녃RL%Tӧ=S|zv,ߐ: "":!S0fdHP`ngs~4uL(gTow= jwϧ?mP},+KSg!R'P>ldfEp6+[^֦c1L:s$NLQf茎/쎟=#FO:&͟?_SG01)cN Lы>gNӧj5<<3gJWowSSgdFC~F̾eM gbEX?h::؂˟?:*Ѿ8}3`BR01Z5凼G1Xn]jfӧOH˻ߌ}۠ 腺 P:)85;#"v,Vñ.N=.uFZt(.n=#9?:nJM& DD7%LsOEs3bt>upc_%gǧ ^hgbhlaꌪV\*>}_NbP ,m32oogP7S'īg|}jS';c럋/f.NKW~|zmL1%}h)püt=@٩ڡ TUVEXR:>ThIo] @85>3Nw;tzDkp8V+ WO=.uƔ莍Q\/?D?V.59kc*V PNe ]]]ા wt1u0AZ_{~/ܒ:brlA33UѱuOZٙ:K.u7N0%ǺuRgP7u\QhILQR'dJCaF0Cc chl(-ĊXQ824rK|ՇbbS)-߿#n9pM TG6Έs|j0^3( iokK˻ߌ}۠ 0qQ$L%//McaW%˖^{^\ cAQ\?{Kq[s\uPsdH@2DD%\<]Lͩ2nZ!uLMql{<(-cVą"~701P(N\w.Ngԥ_%?oItl/?DŁ9pA ZbSRooo}ObbSnB9nG;8ݩs " T|M󕥩3)bVH륑[⥑[""v,V;,JAӱuOũS@ :3_gJgPRg4r1)pr)uP.6ql{Dn`x(VYg&zmϓcυU~ޒغ'^~8s dڶKo_Z-͵ޖEDD,ZȠ axbzD<)pr9uB4fN gbEXY8kf_帧/̌gۣ[Xc=qwv`2(0 łKΩ|M֮ܶj ;zo"Eooo &{{O֩qj3OwFF(EMoDkMnq9 /FnFnS3'J(.nCz49?:)Ơ uzLinm K\3m_TXjU*LXLlx>63RUЉ٩2nZ!uLYCc chleokmz#j͹hmz;MqL1|%gOsB SmK%K룥6""ł9~4=_+_1Z_WSgPaR'uyeZ IDAT&QMS K;0sl{*]9ڷ<G/p_g!Ue\,暸miCDDkⶥY1Iաנ ׭X,N8z|<oHT#}l|߻fmw;GSP w'OwvmK%_&ѡu֥NZ*u\]ϜmoMT u2%W?@E+.^߾/}=Z+.Is=Q| L%Zݻנ Pzt֠ P6'GS'dJMS\cstlG'x.uUY imK~\-msk/ݾ}i}k&ʭwpL>=u +Rg5:1ϟ{)@:aP2u D~0KV39?:*cP4FDmK% 9X0ǧQ*7x)eA,FR'@RVtFvϞ'^K@q%(Tsr`ns=!%_-t?ZuuL1(T/(jSUșbLi(s}8q?H@0(U.^AۗGfR`닡hmmMBX}#>ONT/ԥN56 Fqq[xh$*AȈsrqmiCmksr`uv튯~3N' 3 R7: [?{Kq[s`Nn[Zd<*ޞxcSfX=>7NJ5OD=O_H@ISMK&>_Kv~lŘ TR3ʮ*r RTH@wĢSP $Y8'>;FdtwwN(R'TZ7ݱ1ڷ\c>u Ơ YK&8#} OGpHizvP߿ K3*qt1uB7N WǷS d2ΦƶNh,]ey\,}lJ\O)iȰ\cstlsWߕ: aPʠ%_cN|{ǜ(4{ SA___(8:GNچ TG1:se+LۖΦ)$rww(\LT u2%W?-ub;}h1'u fP&gdz;ł9)@}}}ߟ:KTFWM+p}D=1keg2ʠ Lܕ?:; ͞f@-__rwwY smN)u @h)d+]`vLȾEP500:nZ @;9bPjjs`[vF1: 1(7ɘ ~_N@FJ pӆN+c3 vr)uB5R'PኋWEvG~)dA d3慃R'HsLͥN 4D1w]S2pn[ZoL*PۭsM&8TGS'2;aP2u XXvCSH̠ ܀|MsW> ͞:@5iߐإR)6mޜ1pP(c 56G'bR0A\ ;S'lQASI\}}}l^1*\WS'dJC~F Sg0 Uk:RgXȥNL$CC3lOT RS9)wF=ķN&\՘:([ȖJMbxx8u eֻ(WNT#g2:>T~ޒ}4u 7Ƞ \ڶi*600۶mKAN:xBiN)5 pEغ;殾+u 7 \mKS'enMKꄈ===3( PVG_HTe.S7:> Sgp U]՘:=H Π ߟ:nS'HSLR'5h߲3r)\#2p-O'>VHpIT/S0z{{S'@ ^LT#ͩ2nZvG).^_yKSp =]j6KpCCq3@ñ'uLS'HSLsQ9Ѿeg]}W>+d :WMKQٻy`` 6oޜ: ۛ:&͐A#mN)u cGcS 2LIB.u‡z*u]R'@f9]L) ,ccg;"טO0(WВtYۭMh۶mӓ:0883`<:ȸ u2%W?-uܴY+:}h1'u Y֧ۖNʬu^C+ڴys =䓩 S.NȔ 0!D=Q\ܖ:0(:?2w_oT ޞ)# W~Z0hD]}W~à S'>VHpURɨLzr׮ 0<:ȸCgNȔl?|ã|A\ꄏdT .2LA*JMmh߲3r)SAv!uPf6N&JGxr׮(J3 S:!SR'@Y/S,2pF:([S'\Rk::bpp0u W044vJ3:^:!Sjjss}Θ3u dP)X׬T*ɨ(J3 s)NȔŒ 0)rq;bA}S2p:m6N.Fe?L:9RYϷʭ6:&ղR u`/oJp݌d_lۖ:2AM+NI7wѱuOS2p?B`oHpC~;*ӓ:eWb`` udɑ+\.u$$:;Nze*~OFeڵZ8JشyQ;udɑ R7:i,Ή-;c)U͠ \Ł2hIp6m7oN1 ǟoڔ:2șbLoLwĂRT-2p?U`kHpO~2SL۶miR'dJ~ZȌew?7lOP U<:m6N}}}f͚LRzzzboOO ȼCgNȔBȔ{"טOPU UuĨ T1(qth(X>z`lڼ9uT RSK$:;Ne#oNʬ%u„*Jiؼys Ω*q3bz:!S3R'@&5DQ\ܖ:*?MYۭͩboOOܱ~} N q}ETJHSLR'@f}1w]S*AF@5+ju^CꌲkĮJRцP('GsFM+N[Xa{ fP`$uPf]}qmb'?CQodR@f}co(pc)NȔ P1殾3ڷ\c>u @E2(''SgeԶ9uBŚWRTXf1R'dJ~Z(ū}h1'u @1([ Nʨ֦ T*Ewww9688w_GR@E:t|vLmhL'?oItlyKST2p`,~2x>uP&]-&@ܱ~}l޼9 _OOO^&JRm6N2ht>uBꧥNklcRT 2pl֭Z2{{zbeؼyslڼ9u Tb6uA)NȔ Pіox4ߘ:"~4uP&X!uBR)c͚5ӓ:'XfM¿p\ N4NȔ+f-cc,߰=u@31Sgevksꄤ Ŧ͛cٲeSjXfxx8XfMJVϭޯn/6wѱuOS2ˠ \s;:( a]O=éff͚Nkz6uAGS'dJm}c*yK}[: Oϧ&XPniJGb۶mtٲxGbhh(u҄dܷaC_vks F/ԥNȔ\ Pu\AA_}&uPXK)J]tٲ}߿?u G___ Bm :!S *c)bPn__WJL2Wmfώ͛7`kcHʤ}yS FS'dJMm.uTE7 2pqwRgȠ̵)J'VY˖-Gy$ߟ:2y5{vlڼِ I @z:!S3R'@[tXa{ Lkdk:@?1xx,uFꊮDWW[nҎ;<<}}}}}}qthhҎ SwRgdƜ&Rg0zзwΏNHƠ L1')u0A=oΨ]]]E{[[o1c``  C``Ρ:ȠoiLY`J=OOR$KKDg[ckR%" LڢX,FĻ3W300RٰC:1;uB7N)'?oIoQ`J2(މ;;:Pnnʴh~C FR'p7IH.$ X~&,l;"uT[;`nufe궸{9G{nv,]pGi;:ҽ8U-[Q+ 4 I<z?|1L@_p}^߼RV>!uIeXpU%X|x0YqY]`ne =^:!TW@*e{꘺)ʠ =:&K.N,^ ce~[IiY.-1;Rg20^L ֥uAtN+'R'ѰQɦNqe`ݷ=HM<2u@ |&N+ -73*=20:돧eWN[#r++:-ƙ?l)#Ơ R'% ]:!TdR' S;9ܼΨ P ur(upZTFM4u@^jS:C{զN+%eQE>.O0 9pd xg .KwgWƌ@:U:!̥N>ܫWWVe`ݷ=^~?upZMLw.:u^;^:!`P %^}G acPFؚS'ui]dKSg% pWeꄼRRZ:8M / [elsfPF;{c3sк.u@^|]UJE%ycϠ 6GɡYj]61u@Xqqh:!gR'g!83ܼ.R520 :{RҺɖ K.N]UJY Y2*:20JM֥uR'ypWeꄼ22:8eXphXAH{(֬?:8C7:`TdKu@{̠o++:aFe|fPztKw<7upf4UĥU5]@/OW*uQP7S2_{4upV֧N5Ҹ@qhRꄼRZILU\xhXud, 8=G*S'rHYʨ 0 @zi_|mSG 4Jui] aqÕ1"uP@v:!gR'y,Sj}4,\: @'iXjja 8SR' @{j23(y{(n_w4upf4UĊRgM3ڱ ye2Ǜ{꘺@3(ym=3pu ZM4֬:(@{me @sܫH)2n_w4N>ƒEqEթ3m5Č@1&~'R'aFeaP\gPܷ=upjJ3V-[mL]1l4,<.nmeS"bP _O|%czcE 3ru Q+MkS'䕲L@[ n^gT6e@~ iXjJ6"n1uP3(WR',8Ө 0l @xi_lx3u1V+Rg5Dm4uPںR' &83m:(peܷ=H|5NX+bI3xmꄼRVILXp:291({(x c\1)7VH=3uPv}'R'E,SeT8'e<'~'u1֬:C]zQu,YT:(`R'䕊l]fT~)@2(GɡGXbR\z ?}oN y":(BeڵѰpyt@ܷ=u1jJhc87?;t^ꄼRV>!uP^ڨ pF @3dQu\zQu dKk3#uPMW*u"71uU3aP ؚS'㫫Nxm5Dm4uPN3JiE&u0\[bw @i.[:8; DM4ΫH|Mƛ}sOO`X?;uP^~ԫ3Rg䍒Ҳm8{[ }ڣP #Y55u@@:9s?lY&YQwFeQZQ~~5•k?r3>@^ؙ:ee=1>ۜIPvv<<2n!ZN\iơHt̩LwV6ΊܔQ=Dĩ_uE ﯋/nI"2PĦM.4-u@AzP_ WIdQu3vL5L5LM OtWWFMgD\u`ﰽHŤ8-Fe`l1(E+ŗMP0|=zhlڞ:0"n!V9m5?]{zRgnzcE RgEGtkdgE";uvM@_U׈٪DcLͨ e` MbyC}Гb[_AM4ZŚUScFSE՞K?OmKUUoKG53u9%g';ם#SgG?HpF`Pƀ϶d{SgwCOp,u #ҋ㫫8\ 佻8w=f @zmC|3"7e/R'DY&3vFE(?!chp`[&}Ս+2P q⋗gSg䅇6o|pӓ:Q4"֬+WLJ^s'MotJSE[sEQ9yFNE_W{ 6\%e#:#O+߿7u0B Q-l)Itt C7}8!!2@>jO,8=:( ?0/,N={4ui6Ί Ev'&{}`<LfTWi.[:y}DߩwESFUG`vol>q{06?=y,jKcIiزD@zmC'ƀ=/.Kq8w` uEE.ƕ@9F\T}i6ΊL]C۽-u 0555:=k6gRgw>lD4"֬+WLJn\xf͕Nƀ/M1,2un¨~aL83Ս3q/>|02(çfǖSRgC2-2@>Y32#ȧeNe `F |bfKLGxR֦F-)êk0C7l;}93'c]1cJEhHaLs6|,u 2%t'Rgc##fdtwo~ttx9JKJcByJJchwNuÌ(ߍ@6ΊL]C۽-u 0 5559UcLu$^?%N.Kp:io|pLCxez`3<<2^|ө31zƵGRg$?yqd͋1hSgc+)9(rkSGxfy.u 9yh_[~ m}\d*JR'cВEձ]/u 'jQ3 [OzSg$3{2wo;~'|%zߊ(MԉærҴ8xkOqMMMNY+Sg'm/߳zFMM4֬]ې::c֟,NtNƻfRgchwAmD=%2UYwcN20UgK'E$u ijO=/tNaj]_dQu`yn{gͻSg.v ` wJQ0~_̜ߜ:U֦'N-L://߈m}sÎ?o>]G͹TgFnjɕŖm'RLo^?0 g=:~+%xfStbWvL.suN[y.&ξ8ڵ5Sg`\SS;#[mΤ@k8=:~GM4{V.u=Wݾ'6omO$#9E,ڙQ{~K_ɩ>VwcN&2@|jVylY?%uxn{g=cמ).:{fhH]즗]aYs˔XsMq&v#%S79joyo`,S: bPk'W=o?8:N[M4֬]ې:8]8=:^Tl:nZ{$fndg7.S{~saT A ""%)1urY` {h=`]zQuA={ gUƧNƐo|p\{c)0,߉-N֟vE벉(Isk0;GҺ+}bdtc/H۽-z呩:Csuq^e]mѸ&3mrY/ۣ<712y@*)+ۯm90kjjiRUgK'E!WVLosRE~|\qImg]!dK㙍~|ۣP 菞mqpql9z0sЋţ[Sgdžm_kkǏD}幉QɦDIYy׼4~m{w*MeKbR]i |'}OlyD(x}}쭘T x;0<@_:C}oKw<7uxqpql9z0s/NEلleQdTF׸&N[u$~iZhk0}O)0&4Ϯ3 ;c=즗D`SgW3Gm4u G:xd 3a=%3Sddذ:NfP8c,WOJ$՞=/u )5xfhS:(Fe`t čk`MyDe` 0*#4˭M 1mrY`=h#oJcN_;Sǣ~|,S:( Kj㑧G_OH0\C)e֓1'8۞c"ETN: %eq^xݞ:Ҹ&شe|Ɗ8w=f "653V:(]즗cמ)P~3&22u imN2䇲L6jg6GK~(Yb2{2vlXmR@)rkSGPqٖL`ut __7{$u ϶oE벉S"(/]QOKG9~*uc2@oG_S8{[ǏD}14p*&d,M8yinOEe\SSOg6MRg#k0rӓ:7\Y=+uPDns_@oǑwb;u \.6uP^թ335)<"u 0 ߉G:W\R SEuĘTmOyɘ P,~'nU Cݶ/ڵ5n{"zQ9iZ4]elL}qkk cP6G&[ UNNCG`,ص'u 0#ah]:1~/'D` 5翟K'N[g2suFe,kjjz'uP<\;9tqe c|'@ɖ3GN\gbā#3 oeQ?[:ƴcdž1۝: A`TgKbSgc=즗D``9o|p|3 Wuwmqˣ90&3S֦CeUqG0&cK_;SKj~||9K'ƿ#O΁Q3"y\c2@yxt8am_~qKٖm+s1~3*+>9@i_>z~:ůyvel1"u ޖx~Wo ('82.̨ qMMM癩 ߴe񯛦>CMk^?1c>cF,hiڈX~:::bΝqݯ;::bFWxfs;h w; MyDm:Zwc0eaar iii˖,X`A477kcΝcxbc3j]/>@NauÕݳRgyWP42uc⫢~NNEɨ |42Mb91h]",YQSS3 uksœ7s=g`FCH{}q{0u 5L5LM0?@ (ZYѰpqFe٧fǖSRgtdZ[[c 7Ċ+Fڵ+zx'S@QچSgEk0|N񮙱rŤ#{OwMcB-˔eR@Q8MyǠ pcR|l |Ԙ̌㆕+[oQ.;;e`9$wƍwRiɖ3G˜)b[w΀1~⨟wqFe 'G$u1}zY&nUgOC?: |ay`ut 7w=fXͳ+㙍6W:`,_f?uYee/yS@2*ˠ pNX\NNdeH߿?z7s dKG?3*Rc;_Й:> Wf1`̙weѰpy4,\ƙsɠ pNcR|l >xLf͚5qۭFMMM]woߟ: Nxf|Q{)w͌+&u/nK|Le2˨ Zi.[:(Lْ@Lfɒ%̏~+VD&IX6:ZZZ[o3fΝ;ĉIP0?W+>:#?!n!"g^< jq, )r ksI#GkCe,k7;'\k2qo S55vvztL;U tcH'}N7fcCb j 9BD}$$E\^G:)x?B󏃇9Ͽ S♭%uS=Cg$u.FGDhOz"NFUnLL-;}vdK]S )2e[~kuSg@{L]]]ɟIoQWW~b 9|K&.E5ĉGés(Cn>:7fΘ: -O ˯,u> 7?y_Љ#qag>;uQqu6)U3f?OEaoէбkozT74lLܼ18t!up*2٘6?mQw9ss8'u$aP,Iͩ3u׼CիK_RL:5uV~8#SMNgΏ GitI}a0u %j U_{@D7ĴyKiݑkHŨ jrMM@YĭT9&/})d2 R&+0>`=V<3h)Reh)qkb8sw6u%䳟lǾ0;fΘ: |8>: c#1"`a6u P9,<,>:?^ux8~xqnTT| *kSg@Fe(7W͘1@qw+jc?}>n_bT3O? .LTvY|>u ƪt쵳cON5O}aV,]T: >s!ݛ:H SM1m~.2u s`:22%{Y3bLGqɌXretvvN35;9|#QW39u ȟ>|/u޾s(0dc>u=Ɑ[-uNId2qW]eT~so=CqkR̔ItQmh1%  oܸw52)u@A=Cg$uɗx1|7FeP&UTƇox::U3fx+uP<Zݵ3oǶnիW)i===qwD>OƃkRgcGy"uCS0f'ǃO6N(l}eߔ>;[ۢ-*2թs`܌[Pߑ)0. ;P6޸wغukꜲ000+V)PP2/.2. gOE3ooL8'MQW39u @QhLֶ6/:ș1r?u 92E[02XϨ.ז'󏾑:(Ru׷Dck[LLuFe(EeESCE (y^;7x|XlYꤲqG)P9dc +}x8퓩Sӧc_eH` SgE"isє[R3*@1(\+cϣצ?}>n_bh8/_;oR'oݩS rcU1?}>f_|'b`|~O5ƽˮIP2`իjh d)"[ۢ"S:.P+kkSg0(\}0>}'@x[?]ϝ81uI@~Fe >[:`mz|'GéS-7]KyX:?jի3bڼ\,'<vnJWlrMM@EmvR (iۿ}2""o~3ZZZNL&O|"~DoooHEkI]1uӍ5=bVDa N/9cJ0~Ŀ<'9ƨdSgEN8RW"W͘1@ax[6PҶz=<y1GDđ_U2<}JߋɩS]ض/۸2\..3d 0Q$~x\ Le-["Sא:ױgvıwbP+#גro#|}g#"իc֭XFe b٭ݐ:`Bu<{*:y3:=e\5Oo~1fΘ:>s!ݛ: ""Eck[LKqp @kU▫=WM s,ŮN_E\*27Sg$a\MN-7V([Ov }SgL}C4Eck[dR2*@12(e了h_R^wԶz=.M@DlEck[LK Ơ \U,n:sUP:x퓿|}嗣9aWb=DGGG Hf٭ݐ:`{ltlqw͵uQmhܳ/ux_hlmֶ59#Ss]CE,nD{:r-: -n_R}'߻zulݺ5qWb`` nN 3GϏS'][n[&.jS>m;:Mֶ6/:PT @ xYsA#/͉RFe(wS>u5S}Ltc?9[#3\7ͭƪI\}=#q-Smє[912 2Pj=WIAKws#1{ΜS evC }x8Gs`Oxڈk""bh1%fΘ27K;RgֶhlmNLcWP @X02sѾ*ϪL_ S0nƨ'|2u Lފ'?:޾Zua\ o#'"٩(5Q_zK3f:UmvRf}Iu,^Iqb…SGk֬m۷΀$2/.MemGH0*2hZrw4E!u%āM3W `veZ2qW|Y~"^~;;u LSnJem5: isє[u`T3 IDATrО-WG{*\o[|y&ԩS;E"ϧ΁ w6xpmS([]=#:bW|+2 є[mQN@il3Gā=S ""1c[#\PKb«\U@:bٲe3 v+W΀$^M1sƔPv^|\ܹ'3 JE&b"Sא:shf220FsUhUESCE,Lx #3`rsmu Lq{ɩSl[CRgֶhʭYS(bFeHmrMMPjbŪF)qM9Wdg \}u<䓩S`B=Vw-KeWŖSg#?mD٨II񡅷k0z.ue3f: ɂٕў%U1VeT-${#uL{S̜1%u-O }#u@7DSnE4EE:uEf8e} Nf'E{*r-WG{*j'NJ]G"f~5u 9s"ϧN u͵y3SgL6;VE!uEĨ ),-]L|&ϪL~<+(v+W΀ 7Sg@I7.(Iu׷;VE SP$Nx*ܔ:2bPPh_Rf"uPήOus Dggg Pӧđݔ:J֋;$u@7WǴT`"d-]Lܕ{{D`ZD!7/Z|>u L^mJ%iGHP6*2hZrw4E!u3;;RgP PRsUhUESCEwSP`Ws\ PS>u5S@Y?vw (Kmu/L@:ss8'u%Π Eh_R^wRߙq_ݼhQtww΀ NǾ0;uy+zcpB Vw}eL@2*x3(@iU▫=WM s.MG"f~5uh޽qw΀ wo3+ε?Ie)"[ۢ"S:1:r&nYC}GRP&lL庆h_R?Z|&ZMi5_577GoootwwN upܻP2:;i ~ntL?|' ]l,TQZx[qnTJU3fx+u-hUG%gU;/RWPz{{E"ϧN ytQm ( k6ֶhʭYSHl$.FGRPb&lLIx`U}bGkuޔ~r4UsKDՂ9{6:;;S:sqkRg@Igy@!;FhOT\kK@"l|ߏy..K@ jƌ  +=WKb9c"oJ]Ao9N Yq22p%^|\ܹ'3Dyhl3u -SgPB 0aj=W=W5ՓR'L<2\۷}k֤΀ <}JJlyb0>3Ll4-;r+"S: vSqh2+#גYsқFd椮̙3'΀ YqkRg@ѺgC_Idc\̼cUdR0w=/2-DX0M  ˂O]@ؾ}{ܷfM Pӧđݔ:ֵmGS'0[ۢ-_: rh8q`O A؂ٕk]Gdxes̉c3`B=xpmS (:zF}3'u׷;V(FeRe,Xru窢"u@0(%ؾ}{ܷfM PS>u5S@QҎ||qǩL}C̼}u4ޙ:q4:r&nYC}GRP pQj=W+W:x͙3'΀ kM3ܳ/u`d)"[ۢ"S:q`T+aP%FdƊA.5kRgG:ƵmGS'@E&MK 2%h8e} N]}-)Š aΜ9q7uL^mJEɮoc klmwL]CƐQ.䚚#([2sx[Mf'(=/uE.:vJ"3M|;qॳ3HlHz"FoʚIʚ@|+u E]DDDmvR.gM٘:`veC 1VeRPĦ76ƶSg:3M7VN7c̅ё3q8șN*?P,&UTƇox::5)ukعy1TL]@[bfss p:NNt4^M@9ǞoZǞ#gR'p*21w冨dSP *bQS2{Mn ѹ0u]é(#CePvӛSgP$(IC dݻzuH+8: ξNbXpwڹ9Fxb 3(@kjj6`}Oud+(buuuNX욨H?>F=V JPߑ8D#;cvTd-gGxSP@&`=xa&uN.,_,u$S'@xs18t!u%ā=Uqhhm3( eJL|¹ (˗/OIt<{*ϧé(#e ܕ555SG0>j;̈)WN&g#L&==q)0Ξ{+NlH8GSgPf'b$Wg#Sߐ: w6IqnT:vPPΝH]@XlYHowNGRgPN[6DhO~"SƨxP @sD-]6ug} (˗/OI3 .c2n2&S7}zQ27fcޣCq]CE M-H]Ad2N.?x>>73^::~i$'ў7F!u@YʚɗRȤ-X0:PJҥKS'@;^sxé]v- ?ړ:5s>.u(AO{>|ٲ ]N$ƫ3=( M-u (15T⅙s'RP"%u$dHb_Hheқr}]rcP<>ugǩ (!.]:;ϞJnϤNKfX jcdN2(PbsUx?eCK Pƶu:&\WHleҨTLJ?1*2)L2%=W5.™ (e(g;Sg3CRg3,02u qӧ7(N%թX#?N]@:uj΀dz=uL}#`LXbGץ`(!fR'pH]@ u ̶2]gR'0,0q[wJ83(P"̮\SPBh8qw̅s3`\bX1OPf޾*[Rg0 +S'p)~'^M]AhiiIImzw )P>NoZeX`]>g`( fOI%:S'P"cfss HS`uu4uL82OoL}C ƁA`ve.я_J@ i Lo?: aQdS0 (:NNu:͋ 3 _ ˼ș9%!;}V̽g} ƘAQS<===3(7u<{*uNxUqeyrC ƐS%` \:;S'P"fΜ::oTAyu#CqeHcږ:1bPf] N:y3ug.Kׇe|sW[Rg0<D.HBhiqCS`NE2WʼnO(ZN:+dPH@KI PZ:ȩ8saT+7DE&:+`Pص+u%bҥ m^OcjwDu?ړ:dϊjc AH""":::b`` q @ixT3/r..6w$nYl0,p _sWnHe2(Xˏ;::P*n]4u$w6v6uN%#2#9EhlmKe0(P<uڕ:dt<{*u]gR'@7C;7sW[Rgp 9:+3(r--nށg PVzqx/7nwڕR0u P0Sg3:M3; 'L6u ɠ @pS1@{+_IP2:N+DcO7JPg{֧"(GS'p޽{SgPZZZR'@A0(@0p#Cqhx~aw3m^.|t] .A#gS'pn_ym۶D% P:9:.ۓ]18t!uSqh8eC((M-uà @JRmHPzƱ׌P4uqp8eCS+Gv2%G3T P #JB pYv8uUqhf2?wӧ7GE&:  @ I%Z7>}۶% P|ƫ3wquq1:r&u@Rj2̠ @ f%Rp7oߞ:u?:. {cO7JTvu3xeJO)meXo8pI<@Pڹ)߼*Nԕ: ;)"uƠ @ O(*3ˠLgggݻwkJO pNGRg`T76-"'u@s>6ϥ o9:1N(z݇ P;u@2(Px7Xy'Rp7uP^|\AP6N.=#FGΤ6FE&:,(aG. ]]M3v55lOOUWH` űwJ0.2u OmLP ?z>s!uƪz>q.N}ؓ(\s:uȩ8sSܲ!G{RƜKPv Ǜ^O8 3(`e;xx8u#Rgv-1O0rwGck[ bP -O =rsEGqX Pz_;:վ @9q`O8̎9:`N:l( 7$|>ƹbu;uS'}_5:2Ǟ6Nx*uTMl`Pܷ?^|\ Ms.۶o{c Ūر P; @9}B2~Sqh8eCb`(#Cb>2g<Ͽ%5R#ea0^rwa,8c.&+^ IDATM\c.UO&0wL9Y]$;{B[=xf%iv~d-ȍ?fOOx<4YrUWC73con4A%Tb /G=} @(Ra0uuuKnIP ԙƶhO/i'U___h}?NkT9t n'_ٕ:̺1{Sg42uȱXQ 2ov˘SOPP(΀vR'G﹘:2R1N+^r]}'u5[tu,LP )2e5  xt N7`P 򣞋q}ڔ 红wǖ(>:`2iq]R$2ų @eYȕoMADo]Lg8uP 'g\.Rg$2u2מ\n\CNprR'5TϋuqKSƤ}Xt5Ǡ qH|RgԽ> GAd}? T7;@) p=P=b̺5Š @Ѩ @b73ؾXC5wc\ \H԰cѻcs“Q.Yâ6Fca aP_1*֧^n8PM={R'@8K b9t ^߶.N+u 'dwE&KP FeYduڵ14445T P5 Gr NK8xuQ8џ:ʶK9u@M0(}:目B];5T!2U:Csѻcs~+J9kƭbu3^S>J@I)~g֔7 SԕWB t]g D44Dgg8UQv{MUc\ٖ::~[nFF1qjG\T/ן\s~kDvM3A~+2k-v֣GײسgO ~tn0zwlwE0:#2iqCl.u @U2('2*0y:WYB!GchhhΤ} =qp8ʮ)%ݷ1u@U2(Uƶ#3j޼-z^___sV=:ભ|ڨ ?%n5ݱ~q=;uWi tn0zwlwE0: ""ݷ!r SgT2\Q2`i~vosI穧J>p!uU;FOܾ1N+u @DD|z22\ aP11*0>uBݴiSܹsBfr k2KCG1ե\*ɗwO‰9@dwe32kxtػwسgO PN`﹘: F OF4:c Ţ6 e&狣mŅ)5g =룿7V[N` ؍@;s@m]aYŘq۪Ϡ ȱXQqֹmB/ qFeΝ;@ ҅s1u(qt3qQ<}100k֬Ir}I=:jA&ß:G0u@r8fONG-#ͥNjTQ8`SPt׹KUK%v+WPҎz544裩3Gcp/^߶.N+u Pnː%@`|c{Fe%qC)iC___X"vԣM6E___ 1w]qQ8`eRg$gPIaTtlK'իcΝSS۷aB>pV<},zwlrk'`|/Xۘ: )2L2c饭""P(ģchh(uNM۹sglڴ)uԬKNƝ,3©m=S3gcmRg$cPImGRgTΕm>{;wݫWGꔚ{,u ؔK8\W~+J9@ YvKdߔ: 2LOJ6(w^Omߞ:ݫWGPHu}Bt8}caFd$u@et狣Fe7*S(bӦM{b`` uN3&PN 1\rG=;D0:[b}SgL:2$aT|ꄏ+VoORTjBD_m]|eWYŘq۪ʠ :+R'VB!6m'RT^{͘ @ }Br]qQ<}(KݱpѢ144:ܹӘ @ 95X#njcq qt߳Q. T&;-l.u 0(@rGͧwQ[Ɗ+b޽S*Sg@].jکp?u PrĢ6eFe~>O0&'kc=k:b Ċ+{;wN`xq(u@+g\NTYw|>fqo gPaTulKpMիc=@Ꜥھ=V\}}}S͛ݒ:xg:ny1^߶.ξٓ:B3&A*/GejXhQ_>SLX}=iӦ( s7(}BS.s]q(SU$KnL6:`96|灻Nn۹3X"VsOks&Pl}XhQtww"b^1&_LPξo[gIT\-辍3&LS>Jڑc#qjjZq@Pq100۹3S٘?~dYfΝqǏ~)|ɴxdԘ7߯THj߹52\$ :F0Rqv(7|/u@Ÿke[q_ -Gk644;wEţGPH+g7NToTSUb}#ױ0u3(@E3*-_:ZRgLB۹3X"V\Om@KԞ>kv$ۣ3:;;Xl٤^?^={Dww^?KZSgPC{e@K#^9@9|W}'u0(@U1*Ի…1M840|;ɓBa\)ϩ!GZN/N*dz]Y)@*tn0u u3(@1*Իv}\ꌊ}ttwwGDɓqr``Bۀ4-nCm j^*7:1j_<~isdoJTq 3AQcیW0#Ԑ]b A&ŜU_LTS=?Ip]Sx#3X[R'PC. bR1{&zwlRa0uPab̸mU bPt8k76*ԥ[bUse[jS'0 'q燩S tds3AQwOOPU/: rG=;D0:촸̠ Uͨ P| Uch7F,Ǒcޗ5}qp8)@h_,^:rT`9u Y5u ^Қ:C R1{&zwlri8uP߽.,O0fe 狣h`\M0i==u@UXtZj_L+׷oN*wE&K0&eGͧufN wlK@I),`K8\W~+ʥ9@BXͩ3Ġ 5Ũ PO/iy-3* X5u5b dg׷oNq몘W͠ 5Ǩ PO==u@E\ٖ:b(q8|WKésDݷ!r Sg\2Ԥ#FSgLG:u~Ơ /|ј=@=;FO|zCNNYvKdȠ 5'}P˗Ʋŭ3*]+ 0>x8utn0zwlrkD7[b}Sg|"2ԴFeȚ*ҼX`9\L@9b|zCOOLYw|>fqo ʠ 5Ϩ P|nzԹ2:aLߤtn0>!N+u 0ݷ1oJ Pl언sE[ S'P#v: v]qQ<}|DŶ># 3p#sn89ޚ: S~OQPW񃗊3ݚ7RgTyϋ\.NJK8ݱ%J9$h_7=u@L[jxO)苃77{R"ͥ2%2@-zd G=|q4uU\*]Q. &P&;-~is 0(@2*ԚΕm1%u@rٞ~\H@;FO|zCNN&Ќ[WŜU2Եǟy?8>:`|Y{d Ԁ ãb j@`G=:@W\aP:w8k76*ԌG0sS'P:s8(>:XvK 0(FeҞo~aF d\g>p!u5xXz~:[b}Sg2@myd <ƨ#q R1{&zwlri8u0b/X:serT`9u u\:ZRg$s7NR'P 'm=Sqv]Rgu̠ 狣h`\Mp]xsI/̈|S jR1?G=p`db6AWOښ7*53S'P~R1G:bSdƭbΪSguʠ Fejמo2ԕy-ѹ-u5.NNOOoS=?LEca aTv_hVI=pN[RgP{&zwlri8u p2it@j]#RwrK{SƬ=p)޾:`my(a*]N@+/Z?57ZgM\L?`Opj{NL{6ufĿ!u5_\JCܟˣ1IԱHjKq╩s6(Ra0u P' U8rlĨ PnWB :`͋[RgPJb"""NĊlSt9ky3ξmso95qۿ_-NAJGąѸkek1sK{6usE[|kԀ /Ƈ?:2)?+i`x.54G[Sנ1:MkJ0f+b^GK Ț\=OfOsI*qt3q(S`ƭbAo9u<03u5b3x|FK<;+}tξSk辍~S t Y؜:<̘ђ:`\q IDAT`e~lS<7{jl9 Xtn0zwlJQ&;-ݒ:qe` r^BPKn5#L@ qc~M=sT9ݱ%ʥ)/XWK0w@x䁙1%uÇgNF\klgƊl8V+׷oN`"ױ0uP @y|ͩ C3\=>wY֌76CMTu}ϦN`-Rg5Ƞ ԑG:ZRg\?|xVRgPJr3gj|y\u8(SW!qK_.uP @y|ͩ C3ſ8gkSbϜX5+>o3^J\9 jA3<03-nMpMYўwS.SߑigfecۧёioR.[/<ppWd@ 1(u?Ѽ c6%0'u5W':MgNk|9e\gxxd/mN2P:Wŝ+RgoN@Jz/M5>%=5e&P<},zwl3^J3n]7uP# @ahG:QLu;2 xvV67\*[/l^x2ʥ9XtN)uP|2Tʶf*} Ԑ{@{G)=55% I[/gxx7dҵ[Rg5 Ա7I\+RgP#.a\~rꌈ/=sWڦNO̡RAe1gՃ3*הRG@{S&uik|s믞z]r_inhNmsS#q|%uu`<gRa0oYIpq͞)KT@Z_#uЬ?sc+q:743S4N9t zwlSe-*֔RG@{S&uʶ4F{[SkfTrM/l}|kĥ##3~S+mS"!~>2#WRPFW9c:Ys~zDCDD 6<03\і:#E{)u5WNj_k͞ 0ʥb¶x'\Nw3\20?+N0N;W#L@ q˩3Ƥ#hggecq0:;6G)?ds3*ӔRG@X|j|vy6u5cJ.\bx;F{>:r/wʩ3IG1Oٙ8T+e#snќ1r S@ds89SUW91%uPps̟sq:ݗĞ9SkͩSqR1za[“SѾ`y 1xg =GRgulx|ÜԘZ\cC|}J+MsqgOoRa0u Խ_l.uP%|Wmj邩ڹKc֌)31B\JqolsXm.Gq4ujx.z)Z?57ZgMu+Es8fO 4*wX7|90ps,_Қ:s'lSnl|cCjTTu}ϦN6njVA#FR'L|S|3:lqk7=kz N#VL_K?\cC<>%=5VdRP 'mp?u ԥLvZ,@3(ctaب P?¸!4`by|Ik jN673S4Kݱ9N0u ԥJT020F7O,L԰;W>4+u5h+Q꽔:#֦x~Z{s 0{&?R}9@JKnL6:PM|+uT[5-͝:`,]05Nå{bܐknl{/W߃2 "NDqJ=2: sw~0sn4fSsWSȠ Ѣ37C˩S_ƧF#Xm+qw)w_X:F̹QcPYkhnhC%+wތoħ}.3ͩs5f#ױ(:: : 7̉;W &c2L_RU!_k{FgkSjHx}ۺ(>:Be1gՃ3 bPrd^qCMfy-3aŗ?HPu:2 SxvV678\*7ĩN0N)uP!|c#i7+߹-uPpstlK@ J\1(s6sƷfD!u5gri8u ԴLvZ,]%uP!|W66ggSg$3kƔ!=CS*] u5⃿:-nnL474ġ9Ԁc??7.Ld9Pori8οf 12p-"|o>u@R˲\K)@[5^%miL@{Cq+3jBsCC6)8]{řC/EF̹sfέ߿p !2p N uSg$b 1S uC)^m1kƔ)ԸKo/=oƆ?٦irGSPF#n  Ԙi\Ǣ8s@ !2pV-soʤH*ۿky/.r=.::0b\NQ:2)ol×F?p= 'xXܸ3јiN5';(;oNiL'} ax;*w˗\~rz/Ψ 6%̙_i:*wݱ9N4N)uHS>Jh-u@E5cJ̛{\B|Y?:;uuw1F:n474g6)8]: *5R<3Ҙi\Ǣ8s@ 2p;w9h5N^2-""^H\/̈oԉD/{2.2"?-]h"hy$5!}9PSori8οf`0w֖֔se[K)@"{fi kDw$uF]4WڦD!_+FQSw ̔S'&\7GkRۢwG `DnY5S) ՟| TٹVl-23H}%u0 @X &: O|'@ ෌Pmq4FJ3Hh0߻NJf|cdkΏM RۢwG `*reKs\>u @_՗:=c2T##3{.]84wi3RLa(DTL0eesq\۲)0i [Rgc6ߞ:xJܷO,5Dc&u+ラS`Z!d*W*3G~s/ǞΨfS'ѴtM7\V] -ff6CqRN0eгߏȵuI!S860hoo?:xk٘[4)_WS`ZY!ڪhצN7xd~p T)Ou~ YwCꔳV*Ga(;4؟: `JX~S7Iۓ:8Ke5jY5s&̾Cbӿ;wNiuq =8GNA̵#nWN3o)8pZ+6YS{D]F`󷧎ޱxzg)P,:&DS>׿^ cQW7~`^Q_grⵓ1KvGFGs1Z>j}_vm,bS4.^ܜ8Q)G8:`9| ^UwY~idsseQ) RgaF{{[ _yn)?/nc snZ:ӥLBXغ)1,v*(=;c`O4؟: esq\۲)P*&`3(k-q)_WS`?ؒ:V T'ZvVqW*GaGfp|[&uTޝ[SgRm>=upW⾭xVGc&uZ^b=:&ٹ躧3)F.HW)uXfxt><YqhI*S\[G[>6FȜ`S'T]]3"IUyA QI e`qG`%:; SZ}]M|֮WSzyC< cͅ S^LpNy$.ltYnZ&ěfo>歺"ZEl ^a(iٚdS@UjZ&=0 )rH1Q: `\\9b9:&+5ʊX^:ѱcёL1 qǣFnV 7G㢕1UxѴlM7/Q*H;~Qx 5l4_/|"u p r|2Yo>4ٚX!Q`j73(O~YLU3m{IPC1zd4uSW#"wҨNσ ih]1^)lnND4:`”/G6ߜ:NCˢ(i&'SGcтLrcs|\qdcS7?ؒ:N˱cLlCͭkHU%SxWݩS4d`b\>xX,:`<}4>=XHuqGS6u ##3]߻qh)URwG )uXPu9=3PoOLCquјI0斴g?Ov%4>ָϏ:?0z_1`k.?ØS|9wFHd#qT IDATVyl9*(SboOzbK&gB8qѪ8Sg LCX>3R' 4ƍl/cs`Bƽ}A|So:z82ǣwR2 okkceqdEi?NTʩ޵_u5*7G̈(ݙ:fLӘOhv|zScgդOvO|~a//%uS]*΀b0!_:e)m[wG{{R+\\;#׶,u TJi8)JSwPoOs|2Yo>4 dL=Kk/ım|5hgR2zd41:9呸h\ `~~I#o9/ˮu#v~ČRrh(Zj2ȵ}۶NށA "^yk$b 4_|xA'g,΁6;WُN2kqlݏG/RݬIJ>X-kL6*bTJéѩQȵuDx4Tފ'._SliWקN/~`|)^yy,iKgk'sqbKX\~u 1:e+]?ۓ:+6ߚ:;D䍽SG`%ZwbQX : `L53qsDh%vIn:7 )t&#Qz:X}}?_CsFnVI+okkuƨonYn TboO ѴlMds L691+u  ԰JtvEc&u:5,ƈaXv^[]N1qⵓ1K3,32h\2毾*^)ZG̈( Ɖ):{{_u5*kޝQ*N~ό##sśF~a`jwX|+NwєMcf8p SXغO2 ꊁ^syAt~ k[:);~Om>=u0y4rD٨H09q[pceܤ3;Woo^u:Nv28yo>歺"j2(_J0F4/|",49D>1#wgM gXdnO0{;?)LrsW7/~5u #3 \Kt/:_sR?^芾m[h]ڍqYS`BUJ[R*NiϠ 0n ɾC⻏{,ujn;'s`܍<]߷^~u<=Zd\Sw`9@iϠ 0޿!pX :`Bxi${㻏 8.96\׽9uL#3=eeko\۲)0}[HӚA`|dc.nlXV0;W.i > .u$3t)~4uL*e&q`w$F΀IkOEDO[g4uΔvj\`QOLr\ƼS={RgePH1WF2T>Jw$F]K%=mfѩqm[R*&%Kޒ:&xoOӒA*,Z[nl_KPv4_'~44;wN<sbͅ `Rƨ?Fh9u L.?3vu Dڍb3`BMK"'*9| u0NNY~idss`L:wg X3(Le]O_/:aiX~S;D#ЉJ9^Ql9*8z`WR ֩awbQX : `RG6o?j8?i SGݐ:cJhhYW_6F\ Q) Q+yA8kWơgr2 JܷhX]j/=qYꌈ8^GwӲ8`R'AE5pȵwĉJ9FHrmͭkHg&l~N JSA2,p?SgWg6ď箌uj71h$4 śSgLY -bꫢuȜR?*YYeT)!;TOSAcXlmgSg G-=1{:L8yt/:uƔE5pȵwDyhAČ0UΏC~?uL eކaw'.Y3L옽8Ź<: x˯=흩3EѺvc3b8Q)(cުS]曣RvNIϠ pjX慞r[YImmot_:㴽:!~p<~hDgGa`Z^V:zVk3y dOEśSghژ8Q)G'up0dω]]S`R3(p)w/Б:];^e+n72MI@Dwgb0??uo7ǼUcff6JSgQek&Mg,\LAwɰ 0]G<%kG[:c$S ̓`ImdѴtM,\)[RR?u=ʯc`RjhY}۶Iˠ Y2,L'Xc׳ZG-qni0K90]s38Mh]1Zm|}Xf?NTʩP.`Ҫo^B{{RdP`^)cxM&sAʟ~ `"i(g6*8O6\[>smdsbd@TJécTɬiٚ8C]0(0 SսWijZSguk""bk1h"Y{}wgLr5l4.Z o֨TOɩQ9/L}.uL6jff_uNIgF{{SG6-ͱpA&u ?(gN0-塸iߏbС)0 Z6~.]:qRm[Soş3rmRy-Q4b g6ߞ:`*{w?p4W.s5]O_/<7uƄ]0ZNO:{wk Nae1oXxŦb8QPHD/|",49prm/3dP`>VG]vF$?_zo'筈8;»q -"F̺ILL6(D4: 52LF #NIcF{{Mc&>MU:}bUἑSrPFjk;tj9dcfC>fL9<};Rş3rmRi)onJ:&2 ޖJQuг0ZNUMK㛋8gg33o9" L!B{۶5u L[\t~hZ:u }'uL eaZ}į4ΨJ ?+:@6_]x!]6[9#3h}TJi8vwDVl-Z^:Ji8)JS"ej%/MQV &nh+NFjפN9-uׇhf6.uabUJ1BW{@Fe,vus{ zeaN) Ǝk.iLTt2\574+uʤг3`fں9gan[/SLkOS`Z1*d;? @3,0=<}44/Da;wc\MڸxECl1\8+\t_w_:ci)M~+N +⛋} sۢiQSI2] ]S`0*dPwݔ:AI Q'ƓG㉟=3zyC|ͱ}jgb gGQ,L2i]yŸS0ZNsWw/|qSSb9Sq(cߣD߶S`Z0*dwtށAIİ T>J|z+5ǯ`˄^?qi%3&cqたĕG^Lcf: VŬ3ׇem?} *bҌP*x-0(0 5j-ͱpA&u໏'>GvVue~})>mҪMy)fď筜VC2or7*8uagk7ƊͷuC_IUɠ $92U_=_oRg#\ؐ:* ͇ͽ?Om '箈,X#usDk?Z?m{$=( N)ɨ ;7o6ߞ:wr8_ΎhդN C_{[}/^?r<_ 4& IDATlmot_:cڕ?7Ź<:֮|{|Ůqƈɓ'3 VES6u ^l>lly <7-FwK4%-\'8KB{۶5u LZk7Ɗͷ}QISG0)wbQXdXo_M1׿n&OǽW-ʟMhΡ d+{kK$yqƽ0-jjg,ds1oh]1*a](DVOohhYlD  wm-8C;^}ΥNa g_(SxlG[:#"bk1h"ɮ|{<`Ms/1{qoN5m3{~dI0,gǨ զyAzb)Ԍ#[4STe=:c/g.u X_(u<7Q::D3/vύB9^.og**cߣxk8Ck7Ɗͷx3wlIISGP=W⾭xzg)ΌE 2z0+3ձH|)uv D"'JY~tTNnM&͛& ߻wLvmm6#5uZ:z&G+UJ#i=حGǻ'9QiԒHv3 @X탇>xX+sS*dfM'Pr3*df>xt ;VWvjt `'NWLGjO)5絔k1ۣ#/h4K[Lg%e٥gyt 6`.~ -j7_Qfӥ=y)ԅԁk:P׏) 9) ֥_|:Ovt QLMgTͶ.G߽t6s3I=3~9J܄_lץPV,k+=t T22WFNf:0AMaX4KӫLgTOHt6ȿoBt6H]֟]zJ{M4]?9$lM*?d:0,0*Z)gMgUD"t~deYщZ#^NW錪ڪ3~t6Њ3=Z_R2_y&[_]=ܧˡv-BA"^C0$TQ[4@MLU!)hr]ٰ ܒIrYcKZu+3nvaMGF՛vL6]yܒt 6ŖζT9%%+^ӎw;sX^[=Xw*}C S]P7@aT TfrL̬ܖ7eZJ ,Mgɖ'Lg6|w=ld+^G$hv#UJtRӹlj7MlT(2CcXw jAk@c:*ebխXaаuRAHRm:๙vN-)nӎbܪ__]MSI,XԠ7e`X٩U.4$BfV )@0(P F~U-J3ږvt ܂Gb:t „Gcu|}[s:Ҋ錚PX3M:<7ߎi:5f:S}ڑPFx&G[{Lg`Y^[j7ĕ:pT!g45Fe`J_#rsSMŠ +E=6cXԼguyftFM<g[Mg`ʹ~Akg{$Ii5>]rqx6)hPxR*O)wuBBtF0*SB]ٰ `S1(0a'GVp,"P[<2zӎ tP?tjxdFc}3B%tN:19'j:$է޽>)h~m=1S/\| x2c*dfMA@͘[,ȊN 2,j2o՛vt jv9/%ԁ%_HO֖¢҅霺Lb72 Ǖy)hB=J,_19T20!7+#'MgA@oюthb ʼUg>4wa@YlmۡPU9uAfymnPg,te>]GU,䕛0@U1*ja2@bPPΌ^Sr]i߀a`2oY./(m:7KisMg%(*\tMs%̼"_d:n\bKtnA5Dv)@X탇RaqV̬$&73b!MI4}TS4.e5oխXah22oV$ئSkO?ܒtJ]jݧ-ܢs木ζkWLԅ%_H> ^@}Czey}s ;:pTtS*Ը]S,ۯrUfrt ԍ7elQe@UiE>3QSj {vIΨK֤"^I+Kg+^Ggv(mMԼ㩻Lg`,HWC>zcGͼҴߛe~|QTMk@?A_4eu„LOʧd.9==l:БQ 1}ݦ3V{Q8URQn~`9kX$i07m*%9Q]N%ԶcS[>-*73a:MǨ Ų͏N62vaգYٱS>uwڦ@:鄚'LgW>tztF] w(O@4!'jnQRea MڊV[^C9 ;$yEk: M !TfrL̬`C0(hH|ay<u/:Ҋ錚 y ֫nP{M}ՒHR)/mRYZyۮ뻝CZl)Mڊzն9-smRއ0LmGS]>`PвΌ^Sr]i߀apk<=銚r`TitF:Ru+uXфp\EUJM]Kq锚 bKtFS!@4!eNl}V榸6ᔋ^;è 6?W!3h/2Vtv/cIWf(NΨ)HACO=A%锺uﺭZi yWW6>L~y`ߴvh 7ĕ:pTxJ*0~]9i:m ΅ WNfueO8p,]zmU_jws`Twj1є>}3Qڶo}{2$pWR+39f: è 6KqNuA@Ӻ0,XA);mIy\aݪD,ocY U7fh:/N)I7f1bp\m*ֽKPtP@XGN+;5b!o: V.Ncl˲*\e&LA~en#+:1Skī-1jGY2]Q{vMLgԭhWM=?QSk+9¦Lj)ϚNJIӁ.M-k+֩D"=$!zcGͼu-ˣ`Sg@bPߐ͗uzdEO-u}~evo+'fVLWx&Mg4fe:nY^[mDzp,ZiY^[n~IJyӏiN -XqtJH:۶tFjSwB,tАbۇ1t YM0*b~فGLA[ٱZԚ;7bPUGM-0(S%yק>\.UrZZzLK EǮ5Ŗ>4tJH2n,tJ]%ۺK]Ve hvv +7y k`uÜ;@]bPVtaձY]-5Uw'̆v+'fVLŠLsK[Lg-_0x#[%IE# հ iv4}tJ͘u9n:fESj~Bl'h: hJx2csennQnnQ탇Ltgæ3Ơ 7„džs:;VPwǰ M*X 8GLŠLu\\sOg:%a|‰Z-R*m,[R̽l:&x$ma:X^[NUOVy,tICJuTWT̚f&T2* w*399eWfzl89F7a}[ZʕLàLu|錺lM*5!IZiZ3)#[uda\J~6!]軝CZ&%W[^cIn:pTtS*i`3)]ٰ 0(m:=9e{Lg*swH7a 2k?'zLg-k+?$3&e)/jvAJt҆Z:ŋSjt ˡvF1ֻWxJ@$Jv+uAkNf&T,ն4@SZ22llc?Œ-Y`eKz#\bSΨkT7 (֩JntΆ{}^Btq+^G>U#2-<ʁzd~¨ 6Unft . I.Lz;:;VPwʧNtҝC:锪q_6 k?'zLgԵ֝rZZMgUXRn>0Y.M嫔4Ӓ/d:ex$ҊtwFd&ޣie~J+sSsX7Fe~]9i:XedWfzl89F76XoQfgϙN;Ceyf IDATBL{>u e:x}Bm)Z%sNT-%WY)F-Bl1q[I[٭֮~ -Teձ~tztF]kWF=`C`DU*eI|kf&+N1㑞I1qS|Bm)ֻW->ij@ ީԁe\< 墫0* S*])bP*:;VS˚ZӾ~G0w|ʉY)g6Ѱs9/t;Z i;;p\9U*e9l3r[|$7?tFKlC4ib:!eanEg :v2+E|Jƽ:=x8&IzztpɭaLf]o-qv1 H\N8Ҝ*霛v%kJx;#[4Do=p\~Zi9HC)OW!<ϝ5)73BfQܲpW|sI P'.Lz;:;VPkثn$GF-,NYְW#{sOݧ :k}Цo^Ъ[1 ?ۃSޏ.՟5QZ ȉMgTDzԒHKVs3X%I+^Gk쫦Slێ֝ >Y_m;*7̄:h|1)ML52ԩl#+:~jY+ulEsfMݧ?D~p@?)[TR6.4{MIwtJU\bK]_lMuˎ*YCj<ԸܢT.z}>$&>X@S12SI вΌ^S˚ZӾ~G0PKzӎÔqeӇe?|zΦ ow}zúv=`:zvii5Q  sxd~3b&֞w|J?U w׏.m1Qp\]3j%_R-yW+_~& l5˫g{HWhEP;bۇ>xX٩qE9&Ma2LNI;mŧoM,\?e]Y߿3>@|*^?#O6:+_0b:\|A+ 33^]7V~ϧe .}Q]ޣ3PQ5:R_ A]4lO~Up4\@,ty=--omiGiGCZx\ww}Wʹ>)u/ѣ֝3R~aZ_0񮶭 0?֊y֤C6f^ыE 0Qܬ?φMg1(Gjo:a}3B5htFCR*djvTr]\xtƦ5zձkN4?H72rt2ee+Xҕ٢;-Y5/WN{VHg:ax,KVZ36sNT-%WY)PR[{x$x7W΃ )3y^Bt >vFm;fT%3&Š X XAa|  uˀv )$ N}h_䫔Ll5˫g{82>xR[Tnftɔ<(fD.5sT.SЄ7lQ:׉hGOc: f~Wn w錆D*,͙Ny5t /^42p,ۯC uQ.TU׵GձFe,ۯrUfrt 2de㧖51}atQbS-yM4sLg4<(R2Ӂs).NP-U=mcIM %!OientEe^TQ)qM; .Ap[V݊.L:v2c#O\锆QK"m:iCcI]_UR6VYR2a|9}D 7˲`X٩8 P5̬ Y2f~K2cSdlQ:׉hGOc: *ûtn*e:!x%!eNi*^@kFeV|sӦS6ԍe>Gh@ 4hu ݯܢ@Lc:5,5s@U1(6\6_֙:~jYSk(иNԫ50 hJ8*3٢IŊ+S6hOK[+*c+}CGP5^U Rt jeU.@U1(6ͪ[х WNfuv ǣ~YBL{>%锆lM*5jqTf&^4a~ܶCsN-UJEƔ`Ķ}𰮽 y9&0?>GSP]>wJk:MAPWf:=9e{Lgܖ#OJ<(eNiz6*3Dt Lbe$%6P+uAEf&LcgԶnFepCW*39f:MAPU|Yg 7teO8wK?KR3FgVZy!E*%)eJnAXR^c e>xHt4\tWd~9AM;9 T2 βYQK^ e:Fe,[kF;6hl>WuT[(٭yE̬@ss(2!\r3& 0nn#+:v2+וSat;瞺Onk:!X^[;'3Y> KsSt%IŊ+Snt Ȗ>Wr jIn)l$;VQ#.l*7(7CSP]>wJk: AP3V݊ΎtdV/Lhix߾_׮L4- DMg]CY^[‹3nxd;T*ey}~[Z\!}H탇u埨Xț4̄v4c~K.t tqjM tb8'y<矺O/00p\=3VZ31Dtюn2V+S"h.H\-*73a:РS S wN@m՟3v MŠ i|YgFeMLi_h27ߡ4P93NNMEh -ܿW)U5(S)㲝`X_탇3 ИGR i:5D4?>b: APV݊.L:v2cy<M乙>}3JOxtnDzhMheaFJXǚekͲ5}XxAIG :M,կ[4h@/mGSPC]a y)hP se#+:v2+וSath`!=rK^) ('WaihŖ,P5q+3(v=pG<>`فb: APV݊ΎtdV/Lhi o߯ %}EPDE֮v\ /m$;?B@vToH/\2@rs9~,㙻un*e:DkZHVR*ks>t!cVwPNnB x>ԋ*dfM[T!3CSPC@D#3Ѐ %/u?5|Jƽ@:R:tFC#Jlt6DzĕhpJy 7k2墫PKW*,ۯԁGL4̄`X=SP#]a y)h0 VtaգY֓#+ 8zRtb0p;'1 jnXÊ ic 7=j_k-ON$EmRoH/\tMĵG7a"1à hxs%YS˚_,iۯh2jX|ܒtJCv)Os"q./5\Cs"_dfҜ]kuE:z6NN}H٩U̚4v-?՟XțN@aP4UɬΎxo: Ԡ??[k1P|0MDZYQR6r5VעI#ǿY$v{PR**Ks6 N,ۯԁܮrcg!Y6?D4?>b: AДuzdENfRwV4l5?[R3Nrh`';Т닳.u03XqXz̠$y,&#}H!Ϳ0r5s墫k/c@~]99le@S[u+:;VбY0*43??8kZJ54 $v&=mLN̤i6?2I[Ha6-fIH@%FdUّ$K֫]yѐK<5k3NS&EԻ@Qy.f& 4{AҢbe,T8ѩSzr)!5@}2s2sj۶:UX@`P'N/ѣY(]VOc*D>wduF 4ԺPE sZ.M5i[U{&=%]_.o?*c`7]J>`2Ooac:*=e~N:[98K:Z\tP{#c+SNXC|p,̫f #_=ovJuMe\oڡy *a]vYU,x $Kzx ӖހBAu(gIF딺_  TkB9!{ZqZ~MaiQ2V#T)=~\ԔuƆu E733^ UcP`٢]Խ]Й~tY@j鳋?$c|E;ulѓR EJ^c#XBSf~: Z0 IDATgGX.)opٯ[.i T׮[eԨbӹJ>9n:F7bSjl:5ΗL&#jQOO~Y5Xc-:GӷMCi]\:E7iR)qu D73SP(tCuCtf*_=u&:++gu!S(SKYzuQ&W|N+Sw޿ ps3g\ݧ#m{E iF#mW`cqj۶WDfFs5(56hOpܠOa(eQOdtp #|P(ңONUO,ftyڨ@p^@;Oʡe;Ĭ3Pe|#7ܨsS{quCړopM>QCErvm>YsY@9bH-+KX@{>M@`P٢]Խ]KAG{x(?ZM?=}NoV8tX;I/kΨKn5um@ .jbwE-9X+["@c uMʥ*?]ż<]q90 XN@ bPN/ѣY(]VO(WmT9 I'7ucnl&z:댺ַS>s୅b-Zr!_nH{RcuZ yEZZAuU\V@ յVvogW1_ Hgzz8ziS8hs+/9딟-#Jt۾uy-c[3Vۦ 3P|`CL '*~Hn=HGbI}Uh)Pi-{M!X.5\jJmZ7qe&FSPc0vr|I@Fg嵹'( \ʯI <}:-=` ww[gԭMjlMZgF yyϺ!IUP|Ӫq\W ,D{#25 ^Q]vY¢>O6[g%=txVoRW[:XNuΨ[Z7:5&جI-tM7WUoHlݪ)u`%Kc-ZuF̌ m>c T*Rfb:5A*tf*à :p(%vԞ[g>W3VB}qFe'gcr||9±3VҞX}?'oti,v8 c~'Ɔs5Q%o|7XK># v }i@=ue[ d>/ub:n{*k@B\E=iͳ)x5$gb Fb%9 `+q>?1bsvο20*r)e&FSP#s\н]Й~tڝ:_ZSȢg99@zcTuJjhnW-qXBSp>놴'5V;%i&c]Kvjw<H{ZWz|D^̩m^TP4٧33P#A/zzx SG_MQJ@「s25K7>iԽ;I/kΨ[`Xm[v^(ڬ̫tM7WP!:=R!&W<`,haf\ 9*US5)7U.5Ĩu j25,-E8KAG{Y@I}3z_f3JbjvInN֟^OZgQ6P h:$IޛuCړ :UyOMݛJv:8nPK>)56lr_R|XD>u e%=z4Қ+U{oʩbQR?x!W7j/oΨkMݛؚ@ V1Uӑ6<{\B]5P4!7Pw(C =3/ c~u * K(56\j:UA:-빑E=y\P8䨷U(N.ۇ~X(#K7>ҩpȱN#/l?jQBфZ6\k:6+;jE̺!IU7RtC %?P"=j^_yV\:PyOaulE@]|n:UA:6=Wʫ9WOkȣO(EoY3>.>A_n댺]mN?`:$Iy:Ҧg+R~H,^SsHKWT`,])=~w%/3'/3m{SPDRcĠ ⨧2:8Q:.WMQ: xK[/B`Q6ϟX{!Nj'Ψ{-ߡPcu\(Դ&놴'5V{ӺU#u%?wyXGoT k׭ʥTĨ܆zJ?f Nti T1XcƧsq:E,g|3:=hQvz߫ @M;9ח:E;zoѲa[EoԂ?X{1&#I/Wsi?:PN>~RcvYgc]qf*à zy/9WOk5.5_ЯI-z)ewzbQ7i҆d:9'gc)u-S[ !~N\U%UXжٲݱ/hBnlKOmQu ͼ4冣)(3 ifd:Uʱt2LwKtf*o5iB2댊^Njc2]mԽIXZvP|SΖe=P}ݛw]o*G. T@׮*@b#P=٢U(N/e딊9=4iC2dd*e;jl6+;Sѵ%U23e9_t,gKnTlc-Zux9RSj۶:ec@bPoT^_RsԯN: u#zy댊K <d:E;zT,e/T侗b_rĒZ򆒞|>GɲNTJXLfbTD})(hw&8|.k*à ֢G==_'g)u/S[ @f-Mj/]KTQ{Rc%;s_lyV‰.ލ3#j۶OX:eW#PeeIgzz8zz8'ϧ.W: 5CiW'3̬OQ *1&S9U{n9u (w:Ҧvo^/Δ/oU'Jr֥,jT{-ݧmtny:PEοv& ZL":L?A\3Sy\kt|I>pe>=b:̒~#@aLZ6Cf P셊7ߴQP_ty ErC PZWz|D^f:P%յVU,xJ [0(U[⨧Gfup 3TSԱN@ b`jjvI{1:TVW^ Μr" 7tM;?V`pY%卷i$Luo!ޡ@wS0P[?\j:P%r)sYN@D73SP%@IE=7:2%iKo@: UCi=،uɐ޹=jTd*+S[ MGnQ*PpBl-)\GbI}-yy." P7]*Rfb:P%#&iN@8nP 3,?K&}{y8oiRxi sߟ?Uu`1r:Qn:u´f?OGRl!D;z!otfN>~uJv~E7Y r)};3P%@E5Eݾ7֘޵=l*jQnNL1&Sy[v+KXgoXkGOX[TP4*57teSU ݧGn:epkh T:kK:Sg&;u:3C@kgƷ d*{c2US& jN׮d8 jQ|> Ɇ_:UAsZ71[?Jk>[L{y:0L兢 9Ps EAy9@voҞ߹O>@|n@gYg N7@`PUQOr߬~~)F: 0uPqT?VkLN&{x I:}Lu`/a*bwYGwr|ItPZKɧ=,?>6UaYo|:d*jr`u pE$i13g\R]?8nP]nU.5ĨuWU׮AP8ѩذr)bPUk[֋=Μ˫U{o{9|*gQfǿyuP؈nU:X@$I-)U#b( 2mm+C)C\Vuu JmQ bP5!-깑E=yH>:Zj:i(O]Է3߮x̵ʊ1n5wYgsbZ8?aR5[ .KS5 '432h0KMI>)qu J(ޣ(ZOO';u^ՁCigYXfS~鳋 @Y1&c#Sk3 jhnΨK\]՞߾_n8j0tTjl:%=N!eP^'jOodA;X'Tc//X'e35aLƀw޿:(Ćkb!oQM{NtZ ޥ|.k^Fd0eP7. w֑A7iN*y l\xVd ftujd@͋voҞ߾_>|.c>cj`Aԝt2]SCLuMٸ>~euʚXMuP6ю^T,0HX7ܨG;SF2:(~Hn8jX,vuP.޲^@F2:s.W u~N*S댪?n c2v"j.mVvU S>֤u9nP]nU.5Ĩu@z|Dd"=)( )=>b sJsZW;u:3;7TܒNPOlЯ?^d bjYuPԍ6#GԔuJ}N,:tFuPZG$ueJ<:=hbn}2:X'6 O^o&aulA>sv9u 7ؠ֤u7P8ѥA@RcJ>*Rfb:Ġ ּ鹂]d\ ě\=|d:2kwվ:|#'T´u eS8ѥذy:PA^fN\V-{SPD>u T2~\QOޒ*Y [76хL:2u~z|:c͊nU:0Ĵ8?N8eSK:7|QXc#&iN*c ƆKMYB%\н]`\M~=u'ŭ3˖7ߩNY7)?ֶ`$̫Ǡ 2F?1冣)XpK XgBVqyu>;)f>nl.K wۯc)kVCsXg딊cP PNXBߧ ˬ!XXKyOa%oxu V)eSP eAG{Yueúxl:WbupYNٯS֬@CL};s*9uJ,jdsT[5)˪u V 432h `PXKzhV5:$|dH~B:޿?jرvM:1lf9~W׼SߵNq]N(eڨSfb:P!E}X`}u ʌAe81.PB7nó)XTg?Ϋ39|b>wdߏ IDAT:erw 6XU'iq~N/gR1 *qj۶W2?1冣)X|.ذuʌA(pέ=،uJE9ۺwpX[njl 댊aPPiR{J +yS :*=2@1.:!IҷK*cҦj\R |5{b@UsC {t1cR ,m۫pK3#) 2sjc+A-̌3 P*q+s&;OSK]MG'nұ5/ڭUW[g5!kQv挖)e]ź6Xg֨hw2GM)c+M! 2e.m:fSMO]ecch2hbj|uP3|3s)ellVck:1*kCJ>9n:W Gu ʄA؛g*YTpmG-[&mH37 [|:e 4޿[>DZNjJ(Pv y딲q EԶm U1Yʨ?]Z c-|n:e  PE^9<{F=yKb\@R<}q=txFenݤ?Udc[S j!7`$7ؠsSeà Zc _Ϩ ԔwX N@0(TKNW[.Ge6iC2d>Mzf:1 4ĬS7jq~N/gR 2vƆߴCDu 432h2`Po6.uu*Fe޿??N@1(ԠeJ?2`ͨQ_m :} ~Db6F"B{t1cRr c-:2Pfձ}u @>Ujl:%Ơ P ::tqèWbv^$IY/;I_`׉v:+HL Z^.ZTCCV q0=.!kSpݛuU{)(!e:q9WG: ,:lZSK9cҦ?D:$hק~Yu"jYuPw@E-Vb 26eHm)&5qZWfb:%Ġ P٢Yԃ_L(訧ӵN(xGoo3:=h"#_nQ8Xߦ/'`Pᐣ]^]'s.i{Dm>7O_`h|S@GU´uJ0(T۶ʥ:eT/u .*39q2-QO~8(oIr VidH~6Eo: ~!Nԩ|&8NzkԽ`$Y-)%ԽIn:aT[z|Dd"=) X&@0(a޲N/}^4=WTG_MQ:켺QM.Yw۴u#zN Kݭvyu~wվ:A>NliuFI4&Fe?1冣)XpS3#2s)(e%:2鹢cn;a7]V!f)nAs*x9UuYgpYU{Lvj!͌ Zg zz8>9W(訧ӵNXpmqu|/Eo٤s9&Y/v}񻻕9x mS:X`OXgZH۶JXJ,|R|POgSJ x[lQύ,၌Jkt|Iev }yuc~#:>vQ/Uޛv7_bw?D|zf:XM  `rC {t1c*Mݛb-{NtPRcj۶OX:+T,xJ [g`|dmԅF }oDWu9s<ec}wHuvv^@_V_bXMI `{5Yg\P4sm(pS{~~F@.5}uVPN/E8֑MsԞ[֍ tҽ~M_z}jcw. d{t1crE`Ou!ݧpK3#)2sj۶:+ʥN*d~C~ջvuFݶ7byAGzxVzοWڛv7iֈnӤܒ(c%2Y// .]è @-LM 2*ݾQUu%}{譇enT`eya2t2^:+ PXg\Mjd@I1* GwS8i8vNƞbP@]{um Z5l\_ܩcgۭSBխXkGOX[\-%3(9Fe7O}9@mb#-s==Ӄ_ׁCi/':[ }y@z}黻|uV1GE-fS.KW@:v)Ƞu Dr)2n>Mp@\:WAe8ѣY4izuPuya>wd^:j P;3g\NYD5 2PRcj۶OX:o#*56l+ rr|IG.dt\^N: 0ԩ|h:!S3qsҳ)+Q[A\B{~3pP٢Y8G-IQGMQ:cc[xbj-0@- 66+;{V˅u 6ؚeT/u .qʥNebP@MXur|ItPZG4zfIN:(}zMp@\:+Ġ sƞm[׏SMz:|_OZTnA] o [#]xShBI 0*#56冣)x \Va /LP|*7߽ULN^U'3'6+C49haLo?zJ/gю^ůsmXI>T|.X!,:V*kbIqIόw :|bFg㒤HNAi^s}^~y2^:%˜ P܅i7hl[`$fhw‰.͌ ZV!US5)xT.5Ĩu VL&K&Pvͻձ翪U依i]<_pV[S 6M7Z֎=ܨ@2foҞ߾_Mxa; 2jB[Z.Ls\fY]}NԎ__L Ej FdgjK?]%w0*/ݧ=}u}y"Y%U"E%Ebnv<lcvM e/0i.⃁m@`0Ft6{Z#R^:U"C'IUzB%D瞉|LT::?#ndk㵋~~ ~1[J_ 6#YMƲ9uooF+:508<=R$? Wދk6k-14\MNq|_*cq)ܦVc>bSDyCSl`SZMw8_8LM du.&RB+?[ʥa ֯ܟ:HoI3`Ú9J}X Sǣkf|LT::/z36XK_qb!:LsdXL]J&ukȘ `)׮<73`*Be:X›1ȟD_6:Oh5Ig0(l8#;+T۩SnKk%_X_?G)ߊbrD뿻?~?ν_N:0&lkVc1:%>Qn.j{9x4u 083;|2RZ?ՕJ&ν_.?ɯv6#IVs.V߾S!FyWSg@n Wދk=/Vbhl}L>)|DP:n>A`G'k+STsw.6Gk O:b>:uT(Jlbyi!_${|4}"jJm]x3S}|\~g3?Dvdu.^\Lϥiď;\|` WSgL3o?}RNu1s܆G{<:OxhϦ2Rh򯢯0uƆ1SK_cjz4f"JWSxdW<L$Y_&&h`ZFFyWql;x(hLOԘ>ٙ:¦jz-uЛϟrꔎ2Yc:ssB+^'Sc>:29 Rb=fu(8 c˩3b<vQ w,u)JGSGgpdg|O2&sfC1ui4~wLMlc0bSXj<3[߿?=3|$ 1ac2c>+>=D_& fCѬFc|v+^y7FS/`TVzKekJꔮ4Yc:ss6jwcH6@)F|-2)@X^nW۝}x̜~9u_:;:ĩN'Վ1ud`C!P6b%=dLj*~/Sp 1gQ0B1{Dd ^(N=A`?]3zGfb(: `W x=S؀cWOt3%k#ʚ>"2iC_M 3_/KGŁ'*VSGpKõx:pu 5frw4Z9lP8j3+߭٨L+ch&?0*Щvߡ֯;f#u 7TP=OO11\j1Y/I_B+^'~8~9unZQL68w2'[(cϞla(u q㽓?L e5/ Ǟ'VXi!Z$jvx=hRe1rk(NP_E b~W:r6uγx/ "x`PX[v^=BrLl1YI@~~ ^XJ1R]lywK/3BlC5(>OczQƶ "^x6jL@@ekJdu.bz9P~9uХZ/wǏ;ν_NC2G_&:b\}:ksXe/Ub`h Gֱ2%[(cϞl4@j3_/K@G(4&J pu.&k1yv-r{ x=sP]Qq un`l@Fe:˶ⁿ8:x;|`0(5;ϣdW 6b~9&嘬Z Sgk{ǿܝ:W:tu4w(u@ϻqoNyeb?:6ΠL bZLVbbõI̫F+:חȁEn:PFe:GPǞ=P֬ye;ɿ /4rVcbWb(: XFdX RZeSgTsl;x(3\ IDATz?W~q2u@O)e /US\L]K#7o+-չĶZL%,Sg]boDc|wSW~q29;:=A %_=O<+˭)tPCm:o <<~9&V.^xOL]1"Údcˎ14\Mt'v3_N8w>mBe{4gSMjZ 쌝_d211\s1_Nć#2]ƫIC mC(N;}3&x:u@OqoNYe/2}RTc?\mᚑX'x=_sS#DeїɦNz瞉|ɧGyσ3zV6;:gbÏǵՕ)𥍕\L|043>: Hvxb5fCs18+uCͅzQ P~f ?W~q2u@O2(|!f 7VWکSஙm5#3%xB5޸4V.u=(/Ķ}En:ABzhϦN38͘x=ʙIeϵrXi!00Sõ/55[7G xh4ZI}llQ`T`+G=OOſ9:>Ձ'*VSGёZYpZxHL]W/Vc>: >&7PFn:cjފ3LJSgfm6^?o1fPOUxb~9&>6431\Kjjz$.FcHT]Qq u9J}X >ã~>{Sg4d bPlſvõؿcZ SgЃν_KGd^xO\|!~/UR|N(ν|b)_)\9s2=Š pS4{v:^1jprp-&k2yh4ZIGwїɦNξx;=à #;c1&sc7fb(: ZxH{o\K7|QdSܶvs!^8Sbc3zN6;:gWOfm.ksԘO|qC38~9.į\"/֯J¨ ƶ9S/< o e}0&- }Օv,.Rc>X]i'*nηůoǼqi4])GKk8+6L6u ]՘~'^8f#u -gO{ӯ eG}ژ̭,cbv9VZuC3㥅+-du.Ƌ t5u@ϛsWqr%t@)>R5cT`q1ө3zk G'[Ѭbm.kP01|}hfb[-JWΌϥJ޿>sJ9~~9.Nu՗Qݕ:`]\9s2Sǣ=K{':3qGZ]ibr,5YՕ]Q/ĶZEչ Rt鑘ǣїɦNXW3_/K'*#'Rgfm6^?v8u@3(=nR}>a.X_6Z3Ņ^: `-r7cfC+8~9ulRwR%u @21hXO{&Sgt52#zLڭhnVc3rL Rܱs_Fc>3Y!eeǁNξx39n| X>9~9])t}(ν_N/(L6un. G`)y(&r@3zi7clNZe17Rg|b=X|`E)ߊm(?NcRlHBzhϦN#6{c˩3AbՕv,.Rc>X]iN6f _l}0CqJ9\qi4f1SJ]X(N G`س'"[1z]x+^8:k. c2X\,by:@չxz9""&kQ_õ/L13ƹ+嘮Ź˩ӠJQq K)1Nz|#ǽO:`~p4gSgt%2Ѕ:uLVWڱXKhbu: c+]Rjxq!>K/߸4H /14\MбfNg_<:|x<:'wGqJet˘̭,/c6KXj̧X1|slfp-+]BDDLϥ̃v~ gH:Be{0S|11\brD|8>sۇv,rc03FDFo63d}`H8+29]\Dc|nxQ(oO9oh cP:1[`Xfv9VZ9_GfK 1VZb~9&n khrׯ_z+SFÐ j7sOGs~6u QPL>u,u@Ox;ߌv:fLic>#3+Ikf:wz)'h""&55Kc)/z>k  @:wb# vߡ]K{':eL-/c6X^PJ 1VK 1VZ~tcmn 箔mVן l WΜw4uq}Ǟ=vӬ*e{VWڱTKXi5S'tZ?>6`e|QR>~9 x;8wSg;}3&x:u@;3ј>:kcLfm[Tfm.Nk"/14\M-}x̜~9u跟=9J}X )JGSG_1חE~[Ǣ4;#GDJ\&_u,Sl;x(9|wu{]P.u@0(˜L\*14\{#7PL?j:b%;]E:5kQEq|_՗G6SAd6\a( 8#"[l6VWqm:~/6WF0://ɸ $VVTO/Oн6E\~g+Al\"?XhFwxJ)"Vۭvm5u"=lpx<=őHmʗ*18u[jǶRt1n.Nxe`3&Y2bpXv@y$rش /P VƢ/K]083ͯONiQP*StgRgt<2A|\䇶|l`&돈V3q$7P-LߋR%6N.ۼhf1}>u @OkLi 583;Ϡ l@dS&J Wc/V"?f=[FrDKsXc+gNF1:g(NJBs_ l0dzG _Z_&C#;b8ߐY\ۗbJг~٨F_6:+eʙ3:A@OJǵU  rrD (lL.u e?o[jǶRtBe,?͠ ld\a( 8#"? @Ɩ{&"?XJ/U"_l 5GyCQlOuhf1}>u @2(1>Ϧ lJd""bL\ݔbغb2v>@q|_ wϤNYQ?MН6E\~g+:V6u:c2ܮR%K_/c138<C[1ј> oNI1s{SζEPv:#eJЫp7eTjlJd""bL\ e|ol{1X7|aקel څ}|jo=:#Dɰ>903P\a(6mv+][Mг2غ=;_Жח: ԗ[?v+u@Ymb[<:K[ɠ $`L2mcQ}s`/Օv\[iNzRlg"*XdR'J o,u @Ogb?|:KrdS:AXgd(>(FitW Gn,wI&_jl@lRlK@)v)=ܻ13j{9~S3:AXGd2y8#;8+C["WV3q!@g(lL.u]h̜sN9l*cQߗ:K[㽓?Jq :1&CP*14\{X`)6mv+][M +y|ol} Vnzzo~}*Z)=1s>Stlh<6u1:^ C[bpXvxJїFĦXmR'@)6{4___,zT_6wo\\>{JUVqeSZ:ݽO>c|#uՕv,_Rc>XՕv,./@y4n Fsx{GSgǞ=]\׏v:cdJ͌K6E KFilw G"W\>VWq С2B Wr(lL?uh7Is}}|\n4ϧN͌@DnͯWWڱTU#3b<C:OGc|.:\ɨ]x+{L5<3_N16Uk#/nyXjF,/S'=̈ ݤ\S=)=P9:~_PT*MƘ |9\K1PȎ(D_&V\:b|!Quolg6G&ן: X_6=qj:g (NwϤM&x&vuڭXڈz,c1: p|!ʣ14<RXS3_/KSb<Rt;q깧SgtLT::#?Sg@W"WR%y|o G"?%qmuՙUϕ(QuolÑ5Wl4ϧNVcGSt|3oB Ϡ %c<>y$uL?(lȎ<7/MFf2Qy 6ЖRgvP\9s2Z)=m0J.)~S#6MjZtd`Z]iz,5cj=ZXi5Sgk(/D[Fc<:6fm6NDH3{ɧ l~p Ϡ !c2y@ b< R֬Fs~wnoLJۋ ј>~~]B1} QlR?Ptڅbou4w(u@Wz٨]x3ufPA02/By$(F_&: \Ql4k3~/5×s}dfc>9 c{EP4ׯ>^dgtX_~8v\׾g3642p@o[b=ZXYjRc>utLp}@fh*їɦNё@L6syˌEDDy-8/">w\S= :س'< Ѹ򋓩36,2%neyX^lz,/cu: :J_&J#_D6?: "|0Ӝ>n6n~RmO@hL{:u@q1߻wj+qc36,2%d x/`, iceKXZb=VZYa|0 _/7PJDXLc|Yl<+c3^MŹ:g< ; ^7lؐ -cR}>n5cj=`q kvqs(_;8S(E?􌷿4d PPL>u,u@;9r ɠ |dn-F,/cꍱz,#}lJdXswlD›Q{7Lq|_d (] IDAT}n. GoɧGyσ3:ڕ3'M!/o?oLHb>bQ_&{s8T@)u]䣣1ŅhLfm&Ӡ}0.SX*  GlNzxȉ|X[0('G:Օv,_b=ڭ+iLp}y$u`hZV37[2/V"7XL6uY9c8|;1‘h7SZPGQ(oOбν|w362 d"^j^l-R3 >:(En@,:D;1 ozLLyCFfWRgt=S3wsOP G<OP,Y]iz,/cuK3f4nx wY9S{hf9?: //z~(Mб^?~aPn(ɧ;6-/cݎc3'/D~R+/ kLss<1}>jLp 7e<: # 1‘hLO՜μwGq0 @Xkfb%r (E:b<eׇe̔>I1NLp$F6qY׏Nae x/"D>:6T1:XO\^nh`)"HE1ٲb>xshA{Ι^=;r"u@:3ј>:`C0(@O1(M-cj=ڭXi5_.5ЬS5Je,]/Dn:Ӭ^y-1wR'loh\]'G:#CAzڣ~ޘ @[^j}s`fK3ԗFnBd_ܼ_Vps4v: +*ۯ)NH\S=)]P~yY׏N!g9@L+K뗭fu@Lq|b4߉S=:{aPeLՕv,_>6X|DOd#7Pјn]x+jތ;oEc|I|lƶ0{By{$5w'ߜHеb<RtN(ν=xtvk1VicLe_DDDnԬFc|޹>"lyP=]g`bS/< oZ;}3&x:u@ifcSg$gPbLҎf뱺ҾmЗFn|0 fmxL›ќM``fCQ]\׏v:gc;ϿEzdXSDj((NwݢNl8 v]l l7-[@QoXgB*Vҵp 1T!;5'>RL1YiR_G7nC?H~f  /`G ܂o> `3(QݷRgLvEDd}|Xb) OD[>sڅֹr{2;-jVCsnة8wI`](ľG8a3?dvX~1 #67A30 *ѹkotNZ'+:`7)o|9u@ReX r|扣dX~y&"W;?~?χ(w;~mff@Rꎭ{]{c97lE}f2uԹs(=t sb~: 2iR9=z$ʽR@SOc)_^Տ'e< Ӷqf':mcg3a@ղup8:w(uvP { B=z$:wMRfNŹˠ k`eo;m4:s}W߶N76~]qc`jsQP+1?^pIc~>2z|<rʽqV g7: 2Y>D-Oc)?}bwpc5Pz˟a6}#6nsod9yxo<6JdWR'J (L>w(+3$@x g7k /ehYn+x! RWwlqOTJ|扣QN^~ {֕RG9=r(u33wWΏFVK^5D\:|OTb)Ŏ-Q(S-}[{?S|[SgQc2+P*Gq_Rgw`eOES ;bߣOhz|,33VƎC#*ʱ#Q g\xㅣq[ө5f)_kqr"jSՈށY*(ѶWΏNX\trX_hˠ Mi[vߟ:֥JyXgNVMVJ̾4yֈRWOJY ܿ'곓?,\?:Jq3VԆwSG/{SgRH̏W"s޳up8~(:wMs!(LkN5b~c#Qz%u9w?غg8u />}0:啺3M^DMxO`Mq(uSΡʓ3eOTw#qh,֯Nh oMHOTpG{R'7P 곓qC3[5ɠ I{bWG[:ZJV7~xo,.= oMNhj1?QٗF"QuIh>;mʳFzl|M)o|9uq(uWΝ{Sg@ӫ\ #߉׾L\X_MŸ6=+'"Eo r,~W\N(Nh:mbOT>Xs v3: `]ŰD% wxD[w)--ѳ@ SꎋL5Š +P*}:J?0kFVO~;ƏTIܖ\P*NytnA}f2z>uk[ʯD%um1(-+ޯN$ʉqG#Xg3qr"B1uB1өSZR5bp PD9.VN-e%R9Sr\~qMUZ @rצ'ٓb{1,}[g'c)->3w?#{dg_q0 pK~p{Rg MU#oE}f2uRj\(:\[y;eDm*FΡM>s@K3(M uܐٱSsbDd9DQN-P*Gۦb\9?:g.Do1 )m\=t{~u@˩\V(+ZAnؾG4J]ݩ3WdxcMUc)_LD\:{26cs9]g6=:,Ѿm{{R$Xj [bPré3}jSxㅣqL/ƕ1H{1c=qG#SZJ}v2~(u@c##nA> ԦqxㅣdXwc#QF管(ʩ)QөSZJ5ށ)I%eHށPL1?Q׾Ljss 6+'"yqod,5:g'Rg$5%Ъ rSQN:7;v*^}P\:{Ґ צ'ٓQށ9t6ocb)_L23{qh fPK_-O:!ٱȳFhZKbOT6Ur=QJMP*;QNh)չ u@Rm;Sg42|bǃSgY#.W֐ ܂6>yֈD[: BΡbjsPS$S芋/N)eށ{Ugx̱qG m6=Ξbǖ(оm{̎h9[S'$uD,5:} rSN`̕Ne/D%jS(ŎIT;\g&Sd|@J),c~:}ve3X jsqgؼ}O ]CqIעnB5bp d (ʉ7Š  v3w?qJ`*1HY#u 3(@DD{b+V!Ho)_QF管(ʩ`mjd)-mS1:wH>s!33nAP*}<)Add;K,z(u{O\:| Q}EV5b~: v[Sg涔/Fmh߶8J+צ'R|1ڷmr@$ (ʉ7̠ :up8c3XC @kY_ٱȳFl޾' I*6oΞt g'Rg$Q(c]GheֱRWwx8eaHZ۵鉸Qms`ŵQ)-!Qr@$D bP`F;ukة?xŐ AuP*ǞB1u -6UW;>oH։6cmS16I+b=qXS4d|I`]ZxAR%Xg~poO@MU# GRWΏFm<8 V(Fۦb\9?:El-OYө3>V[VώFν3h!Ym.^~xǣ6J +1S`=(h c#gsPPV^w 6v;~$\,qhԦѹk( r$X6۶H /FcKlߓ:`U1?Q)ɠ :P(cqS?+q%Əde;m"`(uuGVsm ,OXu o]k3>Au`;Y#>ߎw>?^菅w>~#&~;~П?>:CXc rGߊRgwʉxG#SuO~;.V:u@S+?GVS/zl?;+Tg?Z6vttJʓO D/ӱ/T5'*eP*ytla)_RWO{R7.Ŀn-|cOkzw1qM+P +/Em:XCz3H>s!Ə7B5sPSg=οo/ԖǞbGc~RֳVJ;xh dP`}[ xㅣ1DV?:;E+u|r=NyVn vy|>ߎnwN+?͸jSUMɠ ѳ@ VD%d̏Wb)_Lp>Ocs9J] oMGϧDTN2?y߭+:3YO\zV{í\pД r@ 3XE 1~pyXY#umr~4jS:@sCu3܆زܦc2-nwN+?͸$p#Yө3~AV(cq:g?d`jsqؼ}OS*ʑg |﷿h,={|Wu&f΁To9:Wha忉-܉Nʉx6J/HĆΝCsm޾'.=Kb/FQH-ן3޳-nwN+?͸I>mbOTb~5u hQ;b} VXm>w(fF<jԦuh+SѶWΏNhZYm.~닩3Iw?)4Ld=q)IŸ6=:} B{MkXVsǏą)Vٓy(uuܿ'f_Ԧ<>e4v97R'ADD,SgA4';: G;)I-1;6!sPxRW> ܠ*>JWu&f΁(vl7K>eZLw u+6Ux̏Wb)_L4jSըMUcV(hjd)M>3=:R9u JqS6-x'ݔ:uPJ,֯NxARykLVsǏą':)etdl(vt(uH UD9:w#o\?Mmy[Wu&/mR簎-u1MOxAr#OE,7^8ۑLNhzKb\:|>Q{R@#͹!\=P >SgܖMmy _F,Ӟ:uhŸ\=:=eZEo}!uˤ6Ux̏Wb)_LRdlh+SΕbD g(uDw u ?w:cl? "&~sXg[3RgǠ @ (ĽnX\;~$.|;g9-kr~46F+uXTi~U5g)nOk/]x?=uD[/heZޯISgp.VN_d5a~5.WOGcK{R{KgOR:dԁ p4+ͥX1ߎwx+iO:Pihr;<w܆T5^}P̎x`-1?Q3:0?^}<\֑{X4;6yH|mןGƷSg4oǿgCOlΡ{w9Th ;::g:w/܀JQz%u c~5fNŖݟbGWցBYm5(vl{RgA|-}q+/]x?=u]sLm fⴲKg.FҤnP-f:jGmv'h:M1+%鶕 t5E֌:x3q Mmrpl$?)P~$x<ĘG"xj4NL482U"EU\ӏ쏳9\x'ߏlK{:zRrGxܞ:!\t2X:4-9nj}<6_D~հ ep2#3gPJtqO85`?TaV,"՟::yޢR|wd[RԽz 3jښ˟7,%,A*ꏍrq:x'4a:Prq:,2uu,ױ!CWxS'Եi9:nbd[GA2\=R6~t1W8:T<WQͲ8{f>#SJir,:oZ`\r$v^ꌺG[īZ̭MDz} 2uqO[&c/s#yz0@/sc.V6NcgRMPUV6_WMPw\|ƯNJe)u+^[k3W7E $ꏍӏ߽'K3SXdl<7X\FeX4lsFRgTܞ:E/hM_>?,l=^ՊUTwHŠ @"l.dsSxMir+̭5,V6_??@3(ȺG)$RrmoP&ѡUugMCSg4*DOW_|<ژ;Ӕ:eVFat}(@2eu;:(M}_FK@xQ.N; uDqb$)U497neSjڵM'O{Ŋe)Mm+ӯFa~u$؋'ODir,uР $-3ӏ߽ӠxX⪍umiჩ3ʵ3jV:w5ܙ++_Hg0::hPe-;꾏hhcSRsO O~ߨ &ʼn(STܞ:fO4-9o9P\j[cLS,Q\z0uР ,\GOl˩3ӏ߽'K3Srxqͱ%uu"SSgTJy6miKPs-k~:bY%zO=W_|̞iY,Lܠ|XB}{7$Rύ<:2_F6~{,lK[b)Uu`D|O6Z<sgӯW"u S^IX"숫>:!=8{b4:t2ύ<WlK[zЃ3Fyf:bYfepmzXVIiZr\r4>~ȯx1&1w)u `4/ٖue(49:*GӚu.@:EbY%6&mU'_gxV^ჩ3dP` |Mk֦h(F8::R2*]LP5wnKPt'SgN W<ϖ_H\ʶӏO4 2sp{\;htOg+sCѡg㪍קNe(49:*̗fu󍱲%u @ڱ{qS3XbM_{|C[٩x1w)u81H3(-m2+S4cp2u uœQ.NG)԰|wsw:zRgԽJy6:x)M}YYgGqb$u @U;}2|g smˍHAYsqU5GDijxW+WNΞFK42u`eG Woy&RЀJcQ7Ʋ9Ԡ\džx'ȶ{=V,N 5-9?eFa54-XL42 u_qET)/ZT8/u49Ǿ; CS ""K3Fed O2 sOFGE&K_cCn"u5ڦSePir:״ʦM-S&k=`,onnޝ:VOP~t87VS*E=r=SrlsFȶǕk{Sg,d5J]r4 㙹SVqb$NL4ejU&Mٕ:q;GN%s~8uU}`'DĩR', c2T/v׷IQ]aPux{dnTѡ8QKKΨ b-wNH<3 K]6&CUb׷cϧΨK @0(p -m3jS}+ݿ;*RHƨ }`Æ15|0uR׷ZOiŮoΨK @0(p 6qwT.NoSCN`T֝3( c2Ԓ'֡u)՟:he.R6Oѡ8QKUŨ &!*RFhj1jюuߋs3N'u \L6oੇr)u T%2[vNHnj`KfLZմ帾HꌺcPX e.-;"]:fq;S"՟: 񡨔gSg\4c2ԺHꄺK42(ѡ8QK5è d+JpQP55?:dmRguΠ p 5㩇r)u 2|W_:zRg$uj ̘ KPwA 9=rݩ3^<Gf^xv:NH49t dLzS'ԝ|w_xl.oّ:'F_)PV[#Җ: ʘ u'՟:seÆ[wF&*u@U;5`ٷ+*R+'¨[JԩR'sd I92"[SgTJy6}gw<нSnQO@hٖɔg]Ui\.X&k;`Qx>+u@*MǑ}pS`1Uʥ8oCR'$55|0uyɬk::1 @3(oټ35kR@C0*l${F: "O'uP lK[tnOPz[qKSrWd3QJ4kN1A֝ɮJPU*885@hXFex]ȶHpܠ εM'+M_NK u)՗:ce"3Jir5u@rSo~)*R"'Ɖ{SgHds3(8uPo~8%uBCwNAp =зā=3K45|Ш @dWE獷Hp|(*@iZ>kTHPa0uBCuNAl\Gw d*885@}>O=$9=2\ $ LJR'uĘ qթ3A`1Z& LLir<ʼnSrj聘~8uK,]Sg$QqN_ ^_,2b0(4[vD&*u@ѡ8oW&R ā=Fe-;R'$Q8>l _\g1uFutG&K2@uD385`wTʥ)"9q`O'FRghؖ: @ 3&o-N'uPg kí;S'$qx{SgK49:%~ˎ Iz uPZ=c23Wġ`ꌆK2@Cj<.RSSKR.ő}4l-Xrɱ(Sg5m>:NhH @1(4 LJq_X`Uʥ8q`OTʳSX"eFU8>:1k.>NUPa0uBC2(,42@YeGdm3Lat(OdFU#vhwXrSS'5]ߎ/΀ qթ3R6l.uPG %Sg,R.N+Mʼn{RgDoّ:`ɕ&Ǣ\6?O΀-Z'uPG e-wE&*u8q`Cbʼn{Sg]}# p|(uP#c:K㙹3Z/uPG #[Sg,Jy6;Nx3XS',9i\|$4uTCR'4<B2(4[vNXttٷ+n|ӏ쏩SgF-u*ME8:r׷IU0:Sg4<2B2(4mKJq;49:'H [J LJR'UڦS*ܐ:"ͥAeXeG E55pٷ+*Rw&SgZ7:4ჩ*wm P5\?ڒ::zR'u  P:o=Ѓqc2EKΦN`dSg,Xө3*j\?.45 @ȤXLٖܞ:`ќ8d["obn&-\].NEyƁh\ɮJ"O??u*D@Zt*uT~*uoI 2@][]n|R<')А]o[]ȶkl.r݋nYߪ49rM_+LG8qĦR.Eirl"Wć`wA&*(Jae=1N:uo`PX(eqSP*8oC@8a7~=c5o;6.#6tg#c3g\:=(Ʀ;vN`߲à P LJRT"o{oe֝\ir<}o?/+V$I&o{ͰKo)MEY3Fh?@ۢu`NX2Cm5whZr H0:F_ژ:@3(ԥ̓{o!8oWTʥ)\?Ͻ?7lKա\GL<{~ll_)Mp\=G= 0c2zfnm6?::R'r=e͠ P6ܺ3u~8z^hļ>s~@ƀ, ]u;9)MG\:nq|$*!N޸ {4@wy=P LJRLvU^Yќҙ;sE*V @0(ԝDԕā=3`#sŪuD6ٖ׆d`q~ -wtg49vntf|$ũ(L'(*R-gu}`AE@yznm^<: 2B0(ԕL6H`z[qjpɲ-mͷym0׌R]s.nl49T&Ǣ5~FaeucRg@2 x?$0(ԕowC3P7NSSgy}8&|{d[05.h}e^)M%Q76ݱ+u sp{<н3Dq|$uPN:~>NN% qթ3x~82@ȶ[vx*8vn7P2\:z0C#"Ϳs3ũ(Dir,*RJxδl *RF~c,[]΀%-An [<GX8?|W:z"]: ^;r~q˹TʳQ(MN GG6[S2U>-N =:`I~bǺES}ic<36u ѓ:qew3P8vnc2$yӏ|W_$+wjSbw@獷Fqh ͝iTX)d~8%u(Җ:qe~ˎ Kir<r)u x Twy}`8>1׈TJǾ7q|+2UsxhSS,tӑ; ͭCTXtqx\ An Pӌ-mo\&*Z{w0s_+M8ʼnQN @C+LǑ}?7u H#>5uP5C:N":z49:Qe֝.Yat(N^c2,|Wux.ԁ\Gw:xg8qH'&.є&ā]Sx]}h3skgo|?u ,3Wġ 3Heà P9Ԭā=3al.}K,LvUFk`-V87,c`25|0]ԁm^G 8>:b~m~"zHPa04"e[# \:2@ds֝3.1.E-]drݩ*;7*e`%t׮Q Բ=3өSU\UwOES \|WDO(2@dWhO??~7":`w\Vqۼo 4Q2;;ʦESQ8\\GO]v5*udsoP9'썩ჩ3RdR:?.SK@uu_sV)󷷧Xt;uPm:iTw'"F_ژ:K{wDyf:uP2.ņ[w)9dx+2@*;EqhE\J\@)MSؕ:Kɮm^q|$uP[KKԸ\GAjN-(dPe IDATx]#29z=;"JQqEir,u5bj`:zs)\[vx{r)#KTCsFeu 7N}uDP jΆ[wN`lw'N \GO_qH~ut[vD<CQ8CQ)RPŞz׮]Ԣl-]^qkVWsLuNjAׇ[@mgȾ]QKdsǜdWNdh[#(M(Nu :vOl-u u8>qK V`jKARj-;R'\c2%utX4p""\(r*Rw\jPk`d[ڢ<3:`xXFeEsgCRg 7jyss"oP d_&6^nllmgwiK&ŕk{}`[t޸=֬,bi$6_LnL%,^xpEl{fnmW-F 9~Z.u 81OdR\ LԯlK[u`: Fh[R(N񡨔KH`j`}`k.Rx偺V8@9T8K\[R'r=Q0h\2@Mh49'1&PGr=Bq\&(Eqtu1h<SS,H-+ZdTZb~eu P-uP 5aUir<,@uDh<ټޯh4.РɮJEnPkʼnfTjN`:zR'5Ƞ P9T5c2u`>Ae菣p|(uR.űwu_ؓ:|W'F"՗:Q ʦESy/mї6`f.ݩ#I&2+S-c2u`鳱3wGuD&K0r=quǢѴf]TʳQ.N`ESpQ.¨H~e[\/_@Cq*s ""xxfnm F<:!e;^:m=o7"c emmmiI7EԙH鉦54Ԋ\G@,jQIa~uRgH#1wd V&͟+dLvcԀL6WѺ8[ţN`ḺcRp*(NXt߲#uPP-Slw \gE1(Tu7W} @uĺ??ۍԠ-Ѻy0|gd[ڣRrq:u|'F߹-u (LhmiK26wljūZ:ER)s#jA*eٿr:dW-:o>swθrmodY,\GOll(RM%/D<WmPZɞ.MNXٖwQRzu3XDV4 \2@U?+nJ&dO&k~?O|>]FdX&|Wtn5=q2sO"xr4-I\ჩ3e>-uPGʐ784`ex3IVٖhؚ:MTmѺy0Z{SHk15|0Fyf:u詇\GO:S]}mis ԥ @zfnm݉lZ4-9u G+Sg]_ yw7pDJbg>Mk֦N dwGȶG<境le>^<9W~,ˬL{d0::`Q#Җ:3|1 -V,ΡQ7(J@0(TlK[lcW miO~9tg:z6:z}`[d۹a8[O;/|i&Z7N=d[ٟ<KٖwQKg?:%2W8/;|g:zR'ww1Vw翓C]Ub(YTcieF$RL'uaZ"pӫ0ho(y/z%)Te kunԎ¤&5Qs>a{a 1y({^/)Nby>?2h\~`5jh=^'go?ھ3;"kwڝmBv mfkwegkggm j;GTq;~#Q_z@L/ @G(zc`zư @ŨN eX/3.v2ׇ3h1֪~wkv-<82{(;B'3Bed2{X92sm L=GcQ*9r%;雨z tʕh6ngg]nڝm)Vf'bʃc @3YNDzgP4IMu;q̉ eHRĞQh{xxv<8 #Q+Wt3Htֳ Za1(l὇.r;| C2JLٹ(zsG vi!;1T=ajKsno 2Ee ;hqeMQtH4d 䫌=GcQ*9mk͹hV3LD5;`CՖ.f'gl;⃛Shv3ˎ:wuqQ὇7GwƟo?5k//ejމN "QhVr%;`CQG_?dI毿oΠ]Z;@Fv*#Qq=W/~r$zv @K(\L ZP_=GRx p:;:,X%;M~wK|ps*;B὇.l6&𙢷?ݯ0$mxcxDG}jvQ,1jW/f'<ݭ#2]ս~wkv-<802SUtxx|!=Gc`z_vvVckoxF=O33 ٨G@o/gg[f' _Š T9(=9)*15{<{Xrv@˻vv>+W3^Q鏾jv-]NJ_K) Ryp4;haefx-H10=cH@j9:C)-o"o ¥@;xñvg[vҭgXvТ OEed2*#3pژ Е*#15;DQ6A_9|ʕ|v@+Wٸn?>wdAN s8N\>s";`S+bjOR]1_\z} Q_>Y_`n=A1D|2+zc`z_vСjKc MS*ʱcsd>v:D x(vDTF&SZ҇Eq;; Ud'l҅rno շhCe/cPp/UvС+Wß4C| U_NZLQ鏩c(ҸggthOvbvCr\lvi8]QNZA`C10/;@ODQNx*#|j U_?8p*jKdNxb+ ڝmC@sЮ毿n=d۲3hsEe ;hAe 1K@wTcñQqK=;NHU_ޝZ}'R_^p1V~~N @ 2(2`$1OEmBv+xc15{'вJEOkwegtK5SUg IDAT'-Ġ Ȇ6xr ~@[Lƞ1T#1~hv SոggtR} Ӭ|8nN ֞NÕDzbPx$Eo L؍čogg;k Ld'<҅fqֳiTv]<82Cz(=@|L٨gkwegtVݭtR{2C)e7Q_Pݯhv @KSsQglfϜ Q'{O|8nN(֪ tXv" o';hC 3Vyp,vF x(;GckoDed2;`C}k3BA}=毿1[{>~mt ex\u3bk'<86JEOL ủh6nggt<#veP֪䯿@1(|Π &QT|Y?^^vF9oe'JE9;he/U 4j\v =SǣgtR_;aϜfvv@GhGensn=6lsk.9!N   6l܎v,zv }etGbx`@{k6q|v@Gph?enPvF[8g|de2(eZND5vFTFvetOdyTWfgt#ЖjK6.0nhiwoΠ˕d'- @C/— ùqq {JE9v?}6\rv c|Dv@Gs Ў\t[G?his*nΠUF&`Px krՁbjv./e.2@[-]X}GfPVo/}/;eg@D``z&Jv۱xx4\GS=QNx,Ϝfvv@G**^'mǠ έU㽵3Z{ko~-;<3DAg6q J-Tc?x$JEOv_60~z,/XUڍInPvFK9og'=EESȮ 8N8vv@bjv.eJEOLEed2;];;jv@Gꛨf'<TX%;%7~mpOQN/aW3'3b`z&f<8#tTϤ\v@G**Qx$+ n-0;#-qW΀x)zc`z_vOftRQGc(=9>9_PN""T=|K p*;b}QN`<fg<ո|v@)*=mt!;e>OT* @22@D|z(Tdg-Q[73.6P;塬_lgkv6T[oNW'۟*t!;H`PP@vЂ@6 L#t2@+|D~Dv@GLƍogg|2O#"v>bw/b' GU\l|psjC~Lhu$1(]Tc`z&;h1p*;p;Kt}l @k\߹7~뛨ƍeW_Q.z6.zޟ|?şme?/g[x_~wK|=">Y%>ݭ_ZDyp,;HbPLD5JEOvBώegTc;Gog5;4T}rݟ};Q*lԳSRjv@GᔊrvNZRQ9c2s"zvb xl'fTS.wݟf'elԣٸp2} @*z2+;Hvi!>Z:cČqs5n';mMZ[}Jv}@v @~dX|s.; 0رpv宽UNJeVSg'̠ tRQv'GQX(c L὇3.ָ 3ڒg"V׸p2} @ꛨF]Z36V*15;gL6صlh;E?ʃc_r%;>EŠ t2ЁD|Dv>)fSca4F=Negdv2(ר t2aʃc}@vv>7W36eLnS*zWE(g]jlh;}/lԽZNQN6A0C @E77&@W**+Dz3.l}*#-r%;>Eov @)e7p@|DvЦʃc7е*#b@Z~t43ڎg$VfPh5e7QRѓ$R9'zC՗b`z&;BF=Negdvj\NOQN6A rըƵ@2&۱pDz3.h6nggjvrj`QGedWvd͹ /*=1~hrv ez,/h+ в ] @N8NԖ.dgmƘ |hHvЅ? 7QNxfRʃ &2(b`z&;Hl܎gNdgmƘ |Uck6걼p*;|!;KWd'ܧTMbP:􌃠Х.9F=;h#djDz3.h6ngg@2(y@(eOn`z&;HP[7οc2lfCi6}`Tբ?JCWwؠ+iz,/eXh!; 7W.eP\]@gNd'mĘ ~qs \jK6qUF&?FiGUTc;GßNczxԷ2@KzeR6OƠ  w=|<4c2t1">݈O4Fd:z]XrD|lDDQ7Fc\j U©K4X^8/Nh h5^ @3(ݧQ[Oggm˜ @{\f~oqs57Wk~bPXD5Jv.9F=;hdZ_@1+̗TF& (z@zck4)z,/eȤA%Ֆ.FedWve @N6Ymb}c2t Ջc kRQا2[z22ih\Q)@X~t Ux&p*; 7W#F+>UN6AhS};&s` xdr4jѸ Ѹlԣtw>fʃcQXW`S4Xh!e<變VըNdz$= @N6ٵw?+xQ_b8šOLypaHha+zlkԠ CꛨZN}Jv}~o@0(mʠ tFm5?8c2r5+WQr%zvr hRJEO<ɑ 4nƍxI2@qXh5Eeke }z&ϜppJd1t!; 82S{#3~]1P\;;tkԠ CLf'|wK @N6Qm4dL5jQzx mt᾿g?20lCтÁS׸7οcTkGW@ h1ϣ@0(molœdzfL5|>"lԳ`|>p*" f?x4>_wjP!TF&ͷ3H`630=tkλERϽr{ӨFŨ-]7fvV3'S׸Qٕ*#qAԖ.xdDggOAh3}|@h6n3U*15;E?; ]}jԖ.1jTF&olKBԖ.d=* @1(mw0tgNDQZc2; Szk&xDk-G q̉>s|!*|Oh;G⃿;%uŨK2E~5 IDAT?ʃcQ_p_VRN6Ah#};_N6Imb8vvЂȀ <=p*NE(6,BMTTdA[)*1P\>s";p V4&w@ @z`\;;^9fLxjԮ^҅Xh lfk-G '?=7Qjs"ʃc10=c\wwaA੺vv>hY/-]=2ʀA<=~m˴$!E_@h,,p%cqDr{ {:UMBtCw.uR/ޚfuJ#\G- M2sGj~{_|Pre`5{(;NN_bv0}OggtMkf4׮ֵ%cz 6VSeصX??Xcy1.xbGT&(0H*Nz'xxv;T~>;^rl][̓_x(޷.k/}9nx/u)Mo懭o][K/x Quަ61[ח⇭)@\뇭\W61w7\%;xFennƭ_较k nnֵغ͵+9@6VceDBD}z6F,Sť?Xcy1;"h|v[Z 1(@} negdt:|4;ྴ6nFcy1ۛ9@9 U)Q]:;; TvX?3v+n-SRmbovONv[c @W) Cv5ˋMKo I:V4ձw0FJ#; nh,/YzhP=&fv%; "¿G@ w0;o+ޮ:6 dDոqT8{a,J#˧EѾs1T۽׀0P:;FwPNz̠ 82P~sfRIɈ 0ˋX^bH=a(&F}z6-e%~eEmb&"jlE͠ A`ձɨzlQ)1u@1"t[f8{*n=ƮCRzSśsKhތUށAӾ1] Gx;濍_=@_r "~<&9050Z7㵗hmƏ:?JͯEsjD\T&'|K)@Ioo较Xvv@DDTe2j3\fv#էgĭ_sG:;X^b6Vs!\͵+~1`=bGvtծg}=\fS1 ~1(>=O(i30uXrl]_U@hތq>='T|H\>}4;(1uؿ1?61d'9]AP=j77ҙ `=L^~1ˋiw0F,xh1`4Sj,/ƓJ#;`TvG ڕ;@UNzh|v0F'dv0D碱9,Sse|Hl][r[Kgb S۽7-egDDD} sd?ktA @5׮z9ձɘ:|4;f8|(VNڕ|h\>},;U)vc@ozTNxKkc5; ""j3 @UUNzh|v:6@m]_o\͵+Q~;F=mX^tNs~ʏI 0:Vv0~RF}A(h]UjL>bGv PBb\<9pܘ Pjۛp".oO>s$;([KgNmbov[9A0f'=p";H9ձ@ɴp2.gOEfv@߼}Xf!-ިO͵61-00A(Jv @y5y8cdj][KgbxQsQ؛gzvڕ 3?+v8\ %~ @s1 $cqQ~JsJ\>}4.>͵9H=Pcy1Mޮ61ePH}G/{ }c ɹXY8a3Efg%X^N( i!`PȮf'=i߉[/$MƓNN_?LJbeᄑ:X^'F}';~F P$ϪMd'DDDkfv@DD;G1(:6E y([KgeTGdT)6s~~Ct^NkY]i|.;`vNpM@y1`vo!eLxPdznxr./eO귳t&;`&f""v%;(920 ӳ @Z:8 '9ձ6bHڷ7Ǣ΁@׵6Vv5;``T&P^e`T&dg]nn tvM\OōNNvˋ R0* M@okPvd`8;O9 ?C2ҙxb.Sr t]cyp۸G Of']nnz/ d<̑ `0$0x:V,˧E?`[KgFmhmf'DDDulwv#e Y}z6*Ŏ g'}V)w}xҐ k]Qk:Yul2; "":; @d=.k77Ѐ!6 Kq\,xr.kWSBO>s$;(غ0H;6V""F2(ɼegðy#Q؛ ո|XqC2Pf\>}4nWEm$FJ/f' Lv@tڭ(j @D٨;3.j77较k `p2.>͵+9<[Kg≹غ?0LsJ.""c XNJ̠ $ٟtў'^. c3G3i߉ qĜ9[ /NNvC较@zPN_M('2>=t'^4}s|Os>ǏGؑ xb.gC[ז≹غ?0KJQ\kc5; ""*yʨjtAO`īq_=OK.#?Em$;͵q) Np~[?}_w 5lvҋ~~d͸|hs(6v%(j#)A}'*Ŏ aT6&KO'&c2}%VDz3D͵q#q)c2q#nnfPBuU&AH`P R)1uDɸ|xWո{G|.;)j#QJR0*3\  @UjAvC2isا2 ӓ xb΁KI݊p2:;9D:42@:@>OAu?C2oWU 5{(F=YO }k,/ƥ?)Dmbo&f31 tCs$;22ge`<ȐLDwڵ. ձxOfg}~a>.ޑh]N`kތK2S(s @4׮D:6 jv@DD*0L*E5{ X})k5"v/t4 Z7ceᄇ誕\Sf&Fs$ڷ @q C:;;'aR6&ç_x1k]r0h;Em$; qO'ˋq#iNa귳ٺrv@Lv0ĚkW""(2Ge W7dt T梾5< ͸X??@ɵ6V≹hmNaiތKjf'sǠ I: I9$qSq eMSs@_K2Z) NO}i,/f'Mf'Cv5;(Jv 1跏՗֕{~Bdvg]o#?'n|,`;bv@J##s~@T`Xxzc8u}D՟r|ug} ׮CQ؛Hkf,p>4l}?0g[KgbicѾ N#0 %zç_N\ձxOfg=rkŸ|1Rkconf}{0Ԫc 3h bHvee{g'@)kHMXw_W)zӾ|x8{[^hFexfe'%rkLv@Lv0 d0P}yzckW`[qјzhMbÇ@Wl][8]67;bf#;(GӳQ)vdgwT}Lfkc!unl\>}Ԙ N݊W^8s)lfe'%i|C:6 )#(vzA }HЯ|-)@oU&c\vEf\zHZ:eeCܓ}RT3غrv@2@NNv@*Pvؖni#2oKqo6W)1uXT)@4ōne@W,ڕ:|4;V)vD}z6ˋ)@ l][vs3QǠ @O: id?ﷲ?0ձ@twSQPJo~=Z蚭kKk 3( c{2y$;ʬ61ލj|zSqW60c2w~%_eg]Vu0 Jq3.>5X^ n V kmf' %S2Of'{ѻG̈?tYc@4ōne@ϽyծCp";(j6nFulwv @U&:)͠ Hul2Hv Ab|KW3.ǏGؑ<g?dg@_5nci٨:tEcy1|}gPҾ#PVf'X})GI LDv !twG0-GӾ€;>=RT&!eP @xh~KO'&nv{)stQul2egv5.h^kcը h$ڷ7cRv@tڭd @;GdgNC2o?e']6uXTP=DUv{,5[ ç67;Rn3(=P߳?;vyӧW.?0ձɸqTv 2}غ;Jձ~@6n;DDzv%j.;xf\>}4ˋ)07{:*E5;(N[ז3J Kkfv0*Ŏ @;G:;;Rl!7NRTc9ka;jm܌Kw$Z)0Zp2;b薭/g'A KNJeSNX})kzDMW6~)n KEQSc\,mS *kqkLvP[זӾP1(diތȮ]s%gP>=}S!7?tI}z6v>ܧoQTF:6-辧367;Rf#; ڨA(GL*E5{ P~̧_(՘_}"tAc}+_:nLRcy1VNfg0vNJ4`;GJ%;ʤ>mLrīq_=OK;bGvpxXNRh,/Fs$ƟN!Q}z6*giSmv%(jQ `4o^x*(GLj3 {x5?Ҏ]>==ahm܌KwĘ th, Qa蚭kK }UNHQ۽7;2E~J=$?ZvSe%] IDATg|..>v+;JieQ!7`vPB! CNJĠ tImb&*Ŏ #S_p-;肩玺.mҋp˜ ‰hm Imbo;G3hmF7ձ`oǠ tI}z6;{+}bR}z6{\vp2n=CFeX}$-e'MwEm4;2%e(ON|>~[}?|5;xHSegӾ+ 'CnGӾB]NJo9`T&!dVNĠ tAul2ï3fYoWCzhT{G@$FeWQqj}S۽7;Bv+;( 2_ܯQvF_?d'>=={h77XNX$w0;(kK }SF!dP2,>1섾)/3P)1uXvZ71&bR,ΠF8h,/f'Mul2;B0(RT:;;ڞ'^=OW9;xHSJ#;xqQoTX^ fv@_xF0(~5;;]XvAg`8;݇ COFؑA/ƅ?vخj3k {NJbRv@_8D [sJvPe!xpN󿐝/egcbm]Xvs3;HTjv0d:; <#;2#P z }ҷ>o(;xձj.;)+ 'Jb+'q3;ٟ5CdpMf'C 9 5e?N|w]=̑r[p›K>=߃p؎ ޛܧf=b#;xfEm58 c2PNոqTv=T)vDmb&;(ƪ2`(;G!i0(RT<(~ ;opTjƘ [cy13qݱum);c imf'CRT.0({ovtwp ?fv;bGvpXY8A[seawAx=XvBϽ[?Smb&{tAaL‰dgEmā+-JRJQHfvPevNw5;>>UjL=w4;[d`6VSHmb&;(kK =g'2@7T6]ug'Zܧ]u ˜ b4egf'%\seaR) @䍝 =sf'9OegaLqTގ^6ձ]um);犝ρi7 N ܧlvtݵ8;gv~3;OSe'aLNp<;7:Vl]7*[ul2;"F]gPCFmbovt7艗~G}OϺ~aޘ j_Πj3 @I4o^N)2vcPCmC7F|~5;Segk,?i|4 I}ۺrv@OUQ)d'ۜA=gGn܇sQ)vdgPk,ZY8P[TQJ}{3Z73zuO /Nr&fdPCmkwwegte':6f΀fLx?ۛ~~>;.Of'%\SΑ{fPQul2(ol™܇'9Cm1Z:[ח3 @I4zʠ Ov+; =Md'@ϽfzvpӳQ؛Cq3Vr2;FVr2:;tAulwTjvPU @ynjv{Tp+wߖdTf~Uj<̑ ZqQo;K݊tݲum);g# }7lef'@_|}@vCNfvpv6P C}ǘ -ueP߳?;(/g'01(۟Aic2 xWx(";GΑj.;1Vr2:;< @I4o^Ndv0$\Wˠ ܃LvK[ ;e-;GSe'PzsLlsv+ggڈ]i3P^  2 fcx W7Gƫ &f67;ҍ]sk[-e'Lul2;Q 軅r^M=w4;h,/fg%p";dPڕ)j 0 d3 ۟Ax`X]Ѹcn/73{kP :^4&Df_!vNJfv@O;ne'CRTdPއA7?7ΞJlm8 tMMf'2>ӳ qDz3k =?0bGv Mc2@_|dv>-[_NJ#*E5;`3(:6+Cǟlθ'iŸGs$v>C܌˧FN@sJ4eg Ҽy5;gc hmf'ۘAx77x_ =:|,;J}'^y1n=-۔@tڭhʩ9s C2(>=x{; ČM^y7}ib|v:;*E5;(kK =aP {p~qDz39nsG`,ڕ `HZ:&fhތ <70 ;ٟ륭3""n[?Es$F=Ca|l][xGv+n=}Mf'%\3 %`wP۽7;_fvBDD|~?;xSe'Pغ3Scy1 @7ʨf''2S#QF3`5[?@jN&f6azq3Vr2;n>ci޼uNϕgloe&f`[~K(NN,NpOkWfT`[:ҩMf'A O4ܛK?_p6>xoFmbov‰hmfgܗ #nj]NJ#;=RNmc/+sӮſsaPNһbl][o͵+uuv`Pͫ ]z demc"较QF3ԚkWS̵4M͵+ ]W) hAxLvl; [}_ (NN Ҿsd0 vNmov-{kQF3^yxtڭ ~ C@75׮d'tU =UF`Pƃ`YX},Uj=~a;4ڷ7|.;Q4 tO PvfPVul2*Gg|pv4Psj _N}T&1 pZ 6w?ǟC[2IsClPfM>X=E^s޳X`bQ6v  9j'd'5ڠ !k~淞dϏs |ʠ ?ibwߋ΀FW/~7:Ϣ3x2^ X62@ftp e ܎N~7__7 :Gy51O>At/P) yc%:Ro/~ }Mz~Z}/:4=FgܨlQwc+:hrt0+uePnlNQH_|ka'~{a,ƛ|4;'EgxCodP v>wZ?oZ^t4ң>Ljr|s:Ŋz4=`f'Lz H_|گU/gn:yuc8zOG' Ͽ@StWeP v>wP,JOEg@CRJӣaIt)V @Ô^ h2?@ jݍ-O%:7_ݺk`|hyu}at@mZpO_.x|@a 31=yu:oorePV vM_?^Stӭ31yzEgde^ V嘝Nk :h~E<MEPٛW4=Fg^F' 4;qM_:<0:ȐAZ7؉NRJ2_ӑmnP_+ @Ccɠ lG')/J_OOA5 vRwc3:Ru6hT_EnlE' 5;yp-'MȗAZ7؉N._G7Wo U9IO܋h?N` + K) U,@d߇~2(V7؎΀FxE'4atBX2@8d ԉAZp,WVr'҃_tk7 :tT3:0:Š >ۘH IDAT:1(@y'ӽRJX3 {<}Gg4Ƞ @0(@kTsғ//NSwF'@# 2Bo@9r@"ލN=yp/ͫYt@LF'` `PVmnG'/nl{eÏ3Ziz4L<:u:oD' fPYwc+:`2(@+ TTM3n{E'h:>sb g<~|zhbwߋ΀MDgat loV}\AX[Fr ލN}G'hyt 4;E'\Ywc+: dP v(GQnY{TM3H2*f'{%. x4;y5΀VZ߽:Jtdk^?V lUy=248ޏN}Ert=*@]z81z،΀lU$ߏy5Kat R Wyc%: dP vo0S9>΀VZ߽Y{E' Ge:yu524Zwc+:d F3 [0> Yf'StRJeh82PO0:Z֝F'@֞< Tg4;EgBoA WS  tS3ԑCݻ |:D'd͠ )3Te!=|^az4N`A\CuePnlE'ߠF'@+{?:t'd`v8ͫ i WvtPjdƠ tQ9>N)Vnb+WɃ{0:WT]ʠ ؊NAyޏNl=~쩟q932WeP vT!{7:4ӇDgp ӣat b$ UF',@ Hj?u 90:Zg}pEOy5,NF,+qhÙ'24sNN4Pu6N2cPF'h 2pyd͠ @\c0(\AX{̼:w?ܐVnlFg@Vyz u Uit@v ݍ97g}ntd4f,Qu6IU)p3_.ˠ aPF'@k˙WO3 \q0 7a1z9lX:Jtdt~W n y SwF'@v?N8~+a- ދ΀-b j24B[N܌dಞ|nd5NG'dŠ ܎NޏNTM3aSmyttXNZΠ ؊NS~nlFg@V<@2yuȍXheh7@T$ͫYt4JUNR9> !řrr E\P atB\"rQ -OsztjX.2>$:3/2Ǡ nlE' v 10nv2N5 [vtpXN b\`PXftdv2NȂ@@reFwc+:xf^y5΀F v eX$7^OUF' fPlWX{ P{U9=Tg. + 3; P{ӣat ǫNF \Ap-ԋVXݍ- hjP{Uy|x92dXG'Tgh{ P{< h@p3 @ 2P/b}':joz4N澚#XNtb} _eBwc+:x*"E،΀ڛ?N# <,Vos;:jo^0:ZD'dgj@$2d<,w@t Geb\iX*Oju at@mztpD8j?=*1u+ \Aj\0;y0ͫYtx7V | 1mnG'@M Zy pe`':x!"X,uAtkAVM+2(@`qDg@NFnL`atB-NF sˠ W @]̫Yt4h-@ݹ^ beVtpA9nX`':joz4N֪2|beNэN.p7؎NZW@ :* PkMlNIt4Bo7=F'@xVt!2Ԛ@}NF AtVUNҼEgpEe5OWh`':joz4N%yP͠ Vg$ f'4fZ\@S^ 2(@=2P$:7؉Nڛ?NV+G ԀLȗAjX5&ubP7=F'@y,@}>_.Ϡ U֣ $ vչ9*'8 92Vwc+:A"X O+ jgP꼱NF^UUTM3^[ڏNX:1WePZ*z 0j?=\e @K1(ksfPZrԇp}Nt^9:NV`q`^͢k0(@-I[ Pk Qa0(@-=2PN D'@9 y<9>gʠ S:W^wc3:jUeY P;Eo=:!O WsxbȠ SgytdVTM3Ռ<,6M`fP1(fWVtԚ ּ:w `,:h5WeP)z 3nv v\X :+ @ P;j?:x!b&OxWrtv @}̿>Nu7չ2µs #cP)zq!`':je`f'!<1͠ ,n+ jӣat@̫Yto oe\?\OoV\h&2JڏNnlE'@NG'@ra%@uXN2fPZ1(Q ker,:ZdIt7PcF: P+ Oxrd z(z$( T V2 wen>f' k> "ՙAȝAjStg,:lG'@Xӣat/Q֣V 3u7Atؘ ̿>NXG'3(ٻ6<߀AbPH:8JHCuv8.|;<7̳Y951Kt  @p .YϷϓv7J*\ gP7D'@J)r:9N,mr`PlE:N2(sCĺx[t `q\gPT=s IDAT+՗ ZnfUXYuuwzZtBý`it@eȆn w< \E'tZ]E' G G ZfeEzer+:XߌN-8zat7 ,:x 2dÍ8:Zŝp=c Qt@#[Wh?2dIpǼF'@kȚ IQnE',Żߢj@{TA2lG'24NtdArj78}_gPWSQo ĸx7Jz-ʠ Y( `Ntdm:9N/ zoG =ZNAm+|3(W 1(A6;y=N:( A?ȋp?kze tr)WgX 2dh-:y=Nra'\Ϡ 9YQг7VB}yR2(@&zE?:7ýȚ1dM\-:QA)wHIt2da @7 y=Kz+g:9qc39/]lG'+ e~r+:6G'脥8{*:`eYt@Jɠ 9ȇ ]~VFDj|+o +Ã& @ b-:H"\ύ(n:9q,t.[@ `PpyN\ sYgo^E',9+PWg @ ΍YtRYƇ ^яNXwE' @SVaX<2N'^`':`{`Pp^t0:Z( knbx;NX^яNtro Nt漋g8 ՉB TV.8=N?f @C SZtdm:9Nee( W#z@,7@w '@>QtYV.~;=NXyyttABy mNVb}3:Qz.ގ3`@k@3M2(pOp/:6 ݜwvX)XȰ6%@w L./ϣ܊Nhyt8 t F; W?hrY׳JИĈ#R_rU=ZN:Ġ 87rИ(Ur+:Xquu4Ƞ ar;7!. Y:{*:`9tqm)whA2=ZN`T ]zһ1`usYttARJe~twPnE'4t<:`+M' @G AeD' n 7EЈw#Jr~ȕ.ptA~t[9Γaf b}3:N+֢2D'a<hARJ@] 7]T3 @ 4xxtAtIqtF9܏N@N2DnrU_G'Z: n1(@tX.ܘ7g(: Dp:N: [<e:9N/t{y p8:舢܊N:Ơ !\@E'@ @n0(sUt@.|44N:XߌNH0:hAB2D'@xB @ٛ<: \M' @Gx@42y=NVq \I觢lPm96)vt1eڣ?؉Nxj| 0mk:9NhL5>NfP.<(SWFg*4G'|A\ wVQ}|,: \QnE'\i^O09tAB~t.xs, .vt½y:{*: \p(: O`E'@< \{Yt@[r @SYt02whwy=Kgo^Eg+ <yN;tA:2 Yh8}ztc` Ipʱ,\Σr{/:,": ~r5G'+֢ҼF' 3(@' /QtFG'@K2WSQnFg Xo8 4ŀ Ù=e6ޔ7ghg9,:Š ýnn40(j:9N::N KWXEFm#,": zZtf @G9ɠ И:NR~:z4: mVK5>N:1(enmOXUfy^Dgd@<:^яNHqteHuuИ y=ȊA WA9p/:QeXrIpȍ _.iӠ̼^DgdXߌNtrp#2dnf ; v:zW(~ hJPnN0(4Ơ zE?2gi0zh A:M#i^O3SoF'|S]E'QnE'|2(ҵBn#Dzk yzN{%9/ϣ9UeX:'h+Dz+ r:z4: Km,Vtrt=` p/:Fuu>~-7WC<ȁL.2ToF'prp+dWSXtrtH4:X2,p /(:Z(Mat+ދNQ]73D'|A)raPˠ K&\`~t>9: kmVW}ytDQnE' g@a#(]Egd?؉N&7ZMq,A[pQ'@~t>~=NN=ZNH).3(p 5k]j|^OEpy=N: jE' bP49`r˟8ڌM0 3 TNP!8Hyt@<ș9Ivt@J)8:X2PoF' p?:,}|,:r<p%e0(p .WM_?Kz Nt7R[ )` jp?:JuuNGϣ3ZXLb-:JndDȅ1t62,@^t•St@k:RJuutH= e TNM=NR5>J0:5<trt!= @7)ct@y,f~t 8Oʆqa'@r 8Hyt@ dPh Qt@ehb}3,}|,:Ur#c@S`E`r+:>9it@{ Tq:NȠ K +@SrGͫ v:4:~t7չ2,'+?؎H)TQt@k{ KI3(Ry P *7CfPhRZtgyt`eh\?r<2@ gPź$dc :!yYt@rgPhA 'z,AVtFG'qp?ZދNy=Kyt!991 gPhkh t"U V+7SQnFg|+ 1(@kDyYh@kTQ%0(Ҹ xb}3eMx^4 ?r7G'R[ 1(@+l<>/ލQh@W{ 2(4ɱj|,AZac ,姰b}3ftCr+:X1e^rD4G'\E'S1G'K`PhLw/ݶ{F(Ơ ;7WMHf  {Q2zS{tUHmTC/Yte4?Ib-:Zqt!E<:X2,M؍x7JoG! Up?:ZzJQ^tgu 2,MbnW蠍/=,姥/@׹trtLQnE'|f@VAip3p{"l,=cӥ/@m<^g:]Tc à =Hbmy:z.ގ9qt1p/:3y`u [_yR`UlD'͕@/?͢%1(4We4K}OUQUW穾<:(`DVA1vt{z>KpiJMsc%дr{/:XQe^I`ՔV[ _0à Y=XY?m)Qt1Nt rq4M=Hbm)ϩ<_{rpj|tLY56 Ġ KA+ t>go޼Z{r0NN1D2(@v6vuu>yPqt1ftatDeFy&{z%`@Ӝ/"{趍/=>4/}V]r3:F /T'G  + }wt:z1PzfPh\nTcP`; Yt'nW-<姅>_ZH@PeT` Eޠ]BrxB_%BT3nJiheF랸 ~z򧅽n4`6vn:9N:?؉NB5VAQEiPYŻQ:=_52@[Tc E L''/?-rp$:`': 4`1XL׳Ӽ6|Ak7rS%p/: O` n y/NB^o[:@ MvwrX=e ֓E:{f JiΑ9` 4|4EF_/n5rzZt<՗@; _1 Ǡ K@s\@ӊr+:zכ׳kp{ RE'T0g @2@Zy=KӼ6܍A-atAf:9N+ A* ?F?q#д^Ob-: yt <?؎N%6k\v| IDAT^7{=n[32@Yt \P+ dW֓?5Z(}xs#mD'J5>N:ދNJ}y0(,ppFkpN* [NrnȑAXMeHź h/仃zcx'OnF'dPtr0(X_N2{p+zh\觢tnȏAvXMe(ʭ2~a5+2(,A Y_Iz4 [Ƈ @; W:.2¸?*(>:.zAtJ`!rTW @ 2p?E@F<ןٛW zE?m<6(E1(䨾4(̠ X62+iɟߜ^}"]E'|8:dPTeXO {2@T~t4:dPXbp)}{?.*7Spkuu +U'G @ 204Nv{vCɉ1;q#%(΃ A[N\H ֓y54ac :NatQ΃r62R* tTQnE'XLo1OLA* ;x;N:WY A`m=yzcL]6p'ɉcM`!+՗e`ø`u4(3g7߻ZW֓?EgI5>N:ދNtr3(p .1(g'At WF2R*ֿ}s<3io1 .pgoG @G+U'G @02b`뛩]όS ;nXLb-:Juu3(pKuuD'd+d뻃(:(>՗sUgP\h+R]ugL6vF'U4D'0(@J)܊N<`Nۘ @m=yzZtչO`ar5 @ R\ljIȘ @m=ypgQtap/:J0:ȀA[r#O=ʎ6ѹ3-A7XHD6{~gΌm[Uzw6.oStPftgח @E`f(: × OCPK ru|4UV/0(̔P},Ob YO @Eqy5T_w{7:ޮ+ U^_F'aP<+Z@-N-@?E'cP?heytT޸NF0(ձ4x ei? ɠ 33<=Nn!F'@9V @V3mxz(:hbe3:&A o^t\D' WhxrTAat4F{}':ZIE+PoWT]9N*Ơ V#Ŋi 2:?Iet`ԁE2(pGO YIb':RIrq?:hEӣ YэNv 6XNxን/*/ 2(drxD'ieynFgN.zf*oxrTA F'@-C20)l P+Et]|x4_uP/ 2(̔>:p܎[be3:Fw{׻`M/:p +e/hϷ0YK;ϣ :yo5:G @EOVtT^9NF{+xݔ 4\TK1(pc7 xOl\ޤ \ԁK1(dnY1(gP_`PQtPQe2uO 8ft-?ًN (V6^D'eP(:- :˜8P&]Dg -v<;P^_F'eP?{ P hd/:`"@ O 3( O[jeyt¸E'@7 8ݔ 2@ח @O MˊN{(O&b\ޤ `+ _5:TA$D'@-NFjo 1ۻ)+:aLl 2'2`:; O&~t0Vt8|AR[N+ Hyo%enn怜hqy39`Pqy(:02VG'@ח X'{ cL :F矢3(L˛EmOۻ Pkݔqq?:yo5 2(|Afʋk2p;":)[d/:`bM:>@ߊN1(gw/RVjØ 0+ftח @/y n ntN+ :;x 'bxzTA0(ӓVR6u穕-DgLL9LO{Z(+_gPV^߉NheyZ`N[1 ܆Afu5qyލNXy.8G's1N2m`Etpyo5:j! NtT^Iˏ3&^zLߌN0(g<:j! NtT&l]t0'Vt9܆A>+[D'@-ח hK;ϣjn? ho nY%6 YevӕV3={0qI3SnexzԄA> P e`ۻ PIE+ ;;x̉Vp+)ePXD:{ P rMt4Z{c:>NDb2: 2|V+ˣ6ӕ2ۻ)DgLǃ4.GhD'ܚ3Jm|L𿵲<-?ً`+ 6<=Nj  _20}.,DLF9NjĠ _Vk6`-vEtT\D'spk.  35<=NϺ0>Zw@3NHpke0(rxVR؉0E+uFgLE9$0SE+:^  _ 6`6/ >:#E+ [s6 2|Q[Nphf!ۻoFgLA`U@}˛T^_Fg5bP7 d 20l!70S,OO3fxzH`; \pWe9/^  ܖg]ntskF>:#,Oyo%:֜Kʠ _-HnL&:B{}s#[{S3.oAt0G;1(ܕA*+ Potw`&={0UWi\39Rę$ Uyo5:jcxzsà o :`.>NL{P/e2(2:FVtxkD'LU9tZ1:?NjȠ _U6eP&[~0Ug9D'܉H}ZYVL٢hl/3~t0g; w<pe2<=NG^V0UWRy}̑V7P;e0(y -v6:Cqp_e64.o3`dEǭ^[Mˏmt0gjje K9Njʠ 3g%Gp7{az{utL ORy}̙ :Ά'G @M`(:VG'@ O`͔-v3^/Rߌ9^߉N3ZeP[{+ P+s@G'ed/:`&A`ŎyS/] ܛAn-F'@m O`.uVGg joxǠ ebe3:jš4x ;0{E+:Ά'.qϠ : F+[H '{-DgŇ jo ´wet~4A+[D'@ O`uL-?KY(0F's1N! 6(uVv հDJK!M>:Syo5 {1(LAoF'@jn?M٢VWo3œNXw{7: bP{1>My}etRZ~}t M Pu}t0{si0)ee7[Vtv'G @J4 1Hu- IDAT1?Rym`V 5NBwm|ګ7)+:P/ŇkoT4AjtS7_X~@uwS{Ø PeE' ePPO - : E3uw3={P&\+ <=0-e5&:4<=N>c^jeytS*m `ε7gP2N0(4 i1(@( E+:ji\$:-v3Mr\+S{ݠ Po+`j j\ { P[Whe ѳ{~_R{Ø P `l!e  T3Vo)Jx 2@#?E' fPpӣ`jtS7zzˆ6:ZYe8GLA&  AtYIO3 (QFgg5ɠ `Vt+/Rfz{ѳGgTү%: dPhItpeW/ ( P[Ó+ZBzutS?GgTR9L ^7(ԟX`bjtҸWoEg0%|Sje ?NH)0&4Stpee84AQtp kޤVGg0aNE3:e>: dPhatpe7&:uq?:褥LPw{7- _Kt@J)VAe*/33(@q9N&$F'@mחit~="ﭦG^GgTV9LGg @?E's {+ PkW[!@<1:;2@S O9`P*[ P[W -ʹ4xzc$ M>: R4 YY0(@%O )V6FR9ni^jeytd/vv6Qt@J)Nt O9`PJp #F'@]D'ګ7Qw{7-?ދqyEg0ӣ`N @s52P/Ajo.jzut@uJtD O9aPJN&-l5<=L&:?VGg,O|Sje )6.o uw&ƹy`V 0qE+:j :V^+ưm ߵ7 3<9NA*:4K[NZQ{}`P ^ft@˛t.:wyo( ƿD'zx4.=#CݬzZYn Z8;xFR/&%,Et0Ayo%:j :'{^qyEgA{c01``ŠVtnl 8;x(:wAje cP%2LEvu|Mtpk/L,k,Oni\ޤw^߉NrxV` Pӣ`VtAtpl!z0^Iyo%:6ަq9]+SwitČ?E'sƠ SV>G'^ :`.1&qyEgw@ O\ ̖A*:4K+[0*tu|MtpOk/L,+~P+goӸEgAw{7:` 1(@e8S{je ~E+|P+&lftČ3gP(/ +V򃇺<@LKVz[^߉Nat0 PeyVtA7,?Kyo5:ZYSje\ޤw<:`F矢9dPp4O+[Hb':j :xV^H,Os !୳@Uv@ O9dPʰT.>N(ﭤG^Gg4ګ7)DgθIg30q`RMt0aeᆧ^Fg4x"1tv6Qtfxz)2TSt0aft4At0|Sjeyt@uwSwit@-? F'sʠ S-v3.>N&-Wo3j^mp_dnF'L(:Se LE+:jot) `냴4xPKyo5=z::sZY s>bP3(q.:Gjt@?VP[ލNQt0 P)/h }O2&p_2]|x M4:12L]VtR؉΀+/$:G^GgT^+ӷ?;FR[Myo%:`↧ 3(@Xa*[ go n?u*W|>0xhQt0 P)rLA`={jt@%ј _>ˠ DgPeIt0ft4¸FeIZB滟R+ˣS*e叩4:Gixz3&0 A*;4SVtR؉΀F>:褵Wo3*ci˜ Y0(D3(@?E'SRҸ&>HKۻѳGg4Ň8TVIAtT O9gP`J \|xLgOyo5: Lw{7|E'|V{}':`*F' P9njo]&Š 4׷?ZY0syo՘ ߿2:ೖvG'L0: 3&:Vjt4SDgSҷ?0Syoo! 7l]tg 0(TA*gt):q}t0%yo%=z::`&gL-D44.GލNQtAǁ&hbe3:à 4@rxEg|V+S{c0J0(@% O@Shq9JLѣgS[V?_Jko <5<=NH)`ZقQ)je ~J,NVo9录Fxo TEt  E:4[1<=L2:og~^<Ͽ*(r -QP/mKbDvjLet72{he.qAy i AmX[2I=b /;+?y7~^ Ƙ y`3;UzZ{w'; " 6;Cm0jbny-;8=}XN85薝 0(@í6{)*E5;A 5͘ zvNvfF>~bPd_̥嫣8~z`nvTfgs?5&pJQv7Reg2@?1(@_NN`n?Nzdau# 72Ƶ -O Uo,e'Nv1(@' )CI+ʶgaTѿJQNx-dN~^tNv*'6m2('3`n?Nz:u&.~}/megSucPU:NN`Rsk˘ 3& zc);Tww~AV>NNY̥*嫣8~z޸#|/8}C@7RegcP9x:_NzlnvL\7dz壭bv?`Po' @f`G>zlny-Sg3W{ɨ^8U~Ƞ }ˋu  0tXՍ`nylfgSNek$;8e:=K2*d2&;{-;?RTX8UE@_2(@_NNYuL0Te'3թ3q `蝲}/meg ͨcʘ Я WG @f`e'Ijbny-;dz6ݼpڻ; ɠ }lf'=0qCs"{>XQUo\s?1jVvkNԙ S{ :/8oPN tFK2&{Nxm͛ [[ekv2n?}$[mTx~~C/0AZ{qv#Jds˷:u6;dz[G[XJ1p|32nyt}?; FewR)d<ݲڦ?e~fP9x@QtNAW@J1fTxk dvpavkGQ8ue(WGˠ }ϋvJ/>P)Q))ݘLuLv Hz`3;Lx#;'~A^>NzdB3;R({;@(jaTx-drGEvk+'c8;w|QQ;ֽOT~1\$^>x#Rv@we{ݲ7i8~Ҋ} 2)'${`nNl@3(@NzȠ V:X1D8~Fꍥc=qePPg':~ҊnyzZ-eg}:u6V7HfvnNNv2(@(_QQ)bB3;R~^vgd~~t^dg|TdgD< eP;|v g'}Ȩ zc)omH-O壭 7Vo,e'AaPP:NzhB3;VW@2*XDijw[v3H1>Ƶ id'2 20ZdTfgz)20Z7N?iegzc);~Z 0:/!Qn)20O3gwd')G.JABD<z6;Cpavnjp[^zZv[$XJ13ݝfP9xPuL0{#S)aLxh+;L7of'ӯ^AA=?NcݘLmRv ˍRԙ jﺼ eݲXC8:@3*:u6V73_E{qv[\`tv} 2 0zSg΀ߺ 20nylfgb|2k=u7bPQjleg zc)V7Re<f{``M7of'Vv1((_9 hB3;G[ 0*XdP{o'fgJQzc);It^dg2 NvcQ)0F62]4ogg=ݽ%izk IDAT=Nxce(+\`M\hf'{h+; Fe?Uj-tFv /| =kI+;` A8}[dgĨ JQՍ7e=:ƽ6qEm2;{ޘAJ{w';H0qCou/;0ƵXXwUFTd?Nx'͛ =9؍Qv3(@)ۇ @ z_ߏny %2Ș `ow=0ЪSg6{);Auw]euNeg:uƨ $7bfT~@>3tfv@'bPNLo:='2*5su%ogg}ݲ֊ɨ7eg\< bPS:NL\hf'떝oTuL\^ۊZsk1se%;pÇnNH0 0pavĠ [dgRQ8 Qo\N5t˓x`3;TjK)ޚAN{w';H2qC[vbu/;`gШNk[Q:kzvNtNv;FT  o͠ lf'&.4`$}?Iv0~3*s͵K /9~r=0FU`7WGo͠ |u`+02ݲ{[+1|ۘ 'ˍ wVo,EQH{N 0:/$Q)0ox/oZv JQ嵘zvNtNv;Y]OZ Ġ ɠ  ݲ{7TOFײSxCO[C6;Em2; E< wbPT:N~t˓ `HbQ))зSgcQ:'ˍ bJv@c200(@NMo:=-;fv0DSgbau#q7?To,ͨc)gwDdg|f/eg9~NxgeHV legC:u&o}թ)7bnvvoiˁC`hK | 2 ,Z`M7of'Hyh+;2b,V70*E5o}ƵR Qo\N=xvNtNv{Q)1ݼI+;1(D{ ԙXyTf{Uރ47Regj=Nxo 0d&.4`| J1 Qo,e{1su%V8 0$Q<^ CŠ |u$+jQ:#88]b,oǹf[ոz\YN=zFtNv{So,?F^{oo=``u^d'}my{nzey#.~o:u6?یޣh=xf@8~r%``""&.8V:31q QOfknތ[Q< n|^K["CǠ ͋{ "RlF<FDuL,N@#[vbu/;!b,Vtfv XX݈zZv /.NEm2; Vv{gP- "b|3*E5;F[dg#Obny~F Q:)G[K;~8;3(3(ąfvnى63To\Ս(ݞ @JQ嵘[b,;S-O⛿ 6;KI?iegwexݝOL7of'H:~e(;Aթ3xg0Sgcau#k)|'0|fd'SaP9xԙ('3`$=r#;Qb,V8@OM7oͨNN?m~^v{W pp* 0e'Iv'ꍥIF̕zTjv CRTq')nybHZA`X`(t^d'}  yvNv0&7cͨNN`fc͘8Nb=e';ཫGmRv@_ -2 OɨggH*_W+jadjJ,މ6@Z3WWScP9x!-O3W)bnv-Ef0 \q`Ttv壭 SQ qScP`P M!I~^v@DDbau#SgS@xsnF̳w[v3N7F>Qv1(P(_E<D Y/mE SgbauóRTcny-.~b,;zsCޓVv2(QmRvg_nd'J1?Zs?JQUgQo\N{;ߺpjf";AF{qvGj΀{ 3ݼ Q:@6y0jI|zv)'&|K<90 04:/>3ݼ#; :u&V7XNO㓱x󘹲@oXn853W~WNAANV: ?P)bnv-Efhy3o}թ3)$ow+=0Ԋɨ7eg_g':2 Qt˓ I2-@ߪ7gQ:@Uj\x=]$*XvI:fvN8ue* @7`uˎ@_+jxk37S葉 ͸ ny8Udײ3VtNv3(Pi=NfTjvs]$V7<7 JQŏ֣ReMCo/Vv@O` .Rv6~TmR\^ۊ ޳|,~=qUn?8Udײ3A`T`7`u^W?RŏORTsxG wMfl`$\Ev@FdgAJ(Ivgdf3`=yfTfjfL7 bA`f޸wf'ANEvЇꍥyݲ/meg66cJv oRTOcaN i|_g'AN{qvЇkQ)0[Ffϣwfc͘nN?m~^vGmRv@F(;g 0t&|  "?Nxcթ3xnN;Tji,މfWٗ=1su%;/5e:ݝO9s"[3Xs?Ս~6;mtFv }/֣[v3N]mv>j32(閝(G@N "^>ڊnyVjVL\hfJQXXEm2;>9x3WWR>9eJ^gy3; A>{';Uz\x=*E5;`L\h嵭7eǎbu/;'jQЗzΠ Cɠ }&.4>q w2q7k)#RTqc9}Ͼ虙+ }ˠ 0 0ڻ߭REֳwY;qNtf\^ۊ7_GdgDmv>j3R< 3(P!N~|u/^L7ogQN*d,nĹD`<yt^dgܟN[OZ ) 0: @*jzCyh+Qv{Q&caNiTjvooEmRv pozc)dv@:~uv@ 2 -?XNٗ tF,~i-fV\YN`tv t˓8~HaP{zZTjv[DZߺ^XX5Uj-(j9 nyމnNzcs30&22 K |$;ཛnވ66;ꍥƵFՕv4eZ>~7o閝xvNv(jz']4*E5;TF-ߎJ1:*fgՕ(j}Ơ C+j1q|V?meg捸 "*E5fͨ^`@uv U#RTcy3;?mEdg1(Pk=N\lF<85b,.~?^JQH1qm̕Xj3A0(Hhd'޸dv^>ڊnv@͸͛)(jޫp:{;fv@s?NO[-;} #8;Rv=ݽRŹFTf#RTO8` 4RTdg 'aP9x {t^_neg^[qQ)9nތk[1ݼ'nFՕaP`$wwQ)ƢXG[9 qym+&.4S1q׶ORe0?t 0fDQ]bP-;my3;Nb,.~ Q;X|,nŏfg[pav@JQK77$3(pkSg6;|x RooՕ`H1 w6{);ۉ63RMx#*Xv8~uv@_1(h=N7ߺ 3se%?ی `Uj\]˷޸7_gg*'cJvF(;`dfxvNt˓ S&G뱰թ9!-WH-O~ޯj/>`=;z[7'eSv=I?.fb|2~,*ůNX忉MK ͓wHUs?(O(?`KQ)osGL7o嵭7S>4q׶bnvFVv@+ i+e';`w4^_s7_G<kb,oϣ6;|,nŏ poH7qK8)w3(Hi=N7-; P: wbny-q`nHfan<]4;`n?ֳ#W~y3WW3R)Qs";_:zTf ٨74~?n$q3WW 7I薝t3WWb|3;`?m Nv0`ꍥ5<e(;``Tmz!VOZ\K9wIۘ @撋 sз 0r{S GtNRT~6_?nyb|2]1|;Sgs;Vggb|2.0ppav@ߪd@g'h|3(_e?壭8aTd ͘8ߌxh+e'; x d\EײSn/megt~{; 5}$ IDAT;`M7o嵭b|2-c2n<7jQ0 02`עRT3P:r0=c1se%.mE|!M[թ9Z~7&$ߛn[r(Ivdh:ͨ 5=r!6{)Vcթ1ooEq-;ȳwJQ+[Vv@|b‡ƳSoڇ0 ~UtvXN*dYnyC6;sg_t` =yn?+g_EmRv@=}Ϡ #?Oggߺ}G9 U:͛Qף*; dfD1>op}eg٘[0^r+uv@3(, JQ})kjD̼C:u6~?Y]2ꍥ[^~0{;_gg I<0~Yڻ; oXny0*X\Yk[1su%*E5; J׶bnvTd;7_gg ͨ^XOZ |zv}y=F((d YAFlg8YY80;BɅxzYB?;He#p+և5[7Ȣ01=Rs3G_va[?>%?}~^HfFO>={Rmy}=u pn6oGѩSt=(}\zO4+qy#uBVǾbzG|3LhlNh9S~؂߾}A `P#36 \ |QFs.3,᧣oF: ZF7x//OƞBO$|3qsr 7ci\ aP=ө36 D}u!zWۗ:+bOcO5,@+cߋ3Q3$@Y|Q_]Hr?y3oou9u@0(@W/ط^L7񛅟o?bȷ '_ FMGqh,u숥s>//,E73چA|*zNԃ쏵f:|3>}N=:[bs1ƾo>Y@$1k/hIq:X:=xhD QVIܣ> (zHİ *cߋNGd9 Y1u쨵4{6u@:ҏ\vEk㷿:zO<:t b碙oNou9'"7@B7fF,gqS_ ?{ =`5+=|W#|aO b{Q]q WȊq31\~>|d$5J\9?ͼ:%bzQ]Sg2t?TKX㜛p 5A<:t"bO'J Ҳ9t<:tb$U|33Smh;e "|d<"ur>|QFs@ LއHWNĞBO$u|3Fu9u @*_I~_ A=_GNy,~fF>Wtpd}S=xhD OD7e/ Y1֋1GN_qWRgC/(zh{Յ^y3u@[2(q_6o:hs{ =qw7HmX}\)Nsb|"ƿlD^_O@+cߋ0JS'@rK7 ?O҆'b33:o_Fu9u@[*VѨDq@ OKoF3oNC3oĻ?=O|6u _7J$:D!+gc#+ bm~.u@K+d96:c}m޽gRG@+x@S艛Յ)}7ǟLWѩcOfvB[ip^L~OF!+N61{-A<tpd}3P:[^6vy#kԿ=9ܣXsQ:p8y].cߋŃO-Q]+g7Rc?QN1~ߢv:O4z8uznD}u!u 7Qxt)ܧo z:وx >]ѩc8OD!+c'?0&p?y8=6zﭟD^_O '4Rg8t0~X6чDxhDǟ}\م)kQTgb3Q_]XKbȳ?Y4:V3ߌ+gQ]N'?QNQj }>uC/mfsv:y#u EON@y}a|c=uw)bȳQ:::WOK76޽{ϤVS|8~@S艛Յ)lS&zR Y1Jc|"fF|N=OÏ?={Rg@GX=mo*m֨?3:B!u @.ތfHlQZI(GD9z+d,Ú#f\ Qө3:gS{IFc#(d)@S艛Յ)6hTb<"u ;4z8'o,n6oG~: O?N fOŞBO|~V7G}?9x5+OxNGS돣Stsq:/p?cȳ37w# Sm\o0CcSh={ǟǾbŞBOm848xŁoUX}A,{ DS1rl:&_a<:t<ТlԿ?go_ 򟢙o8+ nfqқ^O/B֛:Vzc31xhQ[Dڥ-VR|,GipR34&vP}u!ɠ | @*dqX=:fr,͞C=:6qڵʭŊC@2YFd &@1&5Y@NR'tJ3ιi@._I@3.S_F`GbL}<"sqhowd)m뉗Eit*u@jiC;:Z]}eۡ^y#Cc'ؒrO#"Q]ڵKQ[8 lXO4z!I dֳ$T[Ae+Ԯ]r1G7S;`ilƢ8t u 8t Cbt,|<0p7CccLEipI63&u'Oxks:}he?:`kcil `b<92ڵ3 ; @w1&=t&'ʩ3:Z^_wNhe.<8 +OG}j `≗9 Q[D}jW7R'Ā t/c2ۣ4z8xE;/?:0rl:FZvN}u!IX;2"XO`d_GdwvO^_wNNj.yqYi z>م)k捸r~&xQ^V4刣~7o ̬^|c=^M [T=Y@d}論Y@0&FM{`]f}~:Eqh,k3.7㝳S]YnӨD^_Fu97֣Q]NBVtHƘ <wvQ!uFu9f)@+d1rl:{ˋ X='gR(Ё(J4FWFЌ)š(d(=3vg>Z17~tRV}.3(X#Ϥp^y#).s(Ȩ ݬ8t ""JSy3ߌFuL}ի)2i3÷јo @2fL`3vg[gPQ%29X=:%ksQ=>?.뭁ʧ17e~š9::-VRgt2pF G9a2*w4:OFu9y#7oߵ[՝Q#1荬4Y?s<йS'tc2i{Q_]6rl:w š9::W>`w=o߾ߧv ğ\Ht+tBV4*.zmQ0kqLG'$4{.RgtBhGp;P욬4qF`5FG+sntd}3xgRg 켑cӑ|B 12ի.4r{DWci\ +3A؂b%uЅ<é3DnL`b0:k5MX2R96:HȨ @iTWߜ2&_4:k+3A؂fވFu%uЅJS1x@Bks61uwQ]+ga(jks2eR96:HhiQgL`wb<:^M@-]:RY = IDATi z>uQeL`zL]7S'pAآ|c=z K OD7:H̨ @YhL` ODit*u@[Kme`+.UzcRg-`ilԮy6hkci1] ȱ]om`bPA #Dip ,Q]I;}GQzSgt |Aի7Sg]̭@DD3oĕ3Fe^yӘ .96š3^^_|A&JFbȳ3`T s[1rԥ 7S'e`Ԯ]JtOE!+ZQݵ4{.RgtBVfRgpgbcPIm:r7z>u"c2SRgk7Rge`ծ9:Yg[f_=eL`Oc33s1@k2(ۨhPHo @ 1*\Stowa-$G}j >AFeVPr >1DOB֛:م |2y# 3ScT`3rl:JS3omd96:h1wFefsgL7RtX@+-V<#02j.NRg-ƨ [_}A9 Y1t&uqFAfz4+3Rg-Q]6*p/]S\JՕhTSg% XK(N 2_~bL r y&uqFAի>6LEiTWRs$ ө3fJ Arbt EfWΟ)]w7u6?ͼ:`Pv} OD7:hQͼaT D}j6rl:CRg9WH]0(;mu@+)dq@ 3*tFu%.J4˩SZipN稯.D:`PvHy&@(Gip UW8X!+ơΤ p}T[NfSg-̨ m/ƕ3SޭzSg9A6bPv/MVbSg-Ψ -/Yc2-`|"'ʩ3ދh/e`57Sg|Rg-Ψ fDDqh,%u_  @{1(;XIGON2@'jߟqEbzL 7Sgp ]:F:hFeN7f"+ Keh?e`+7Sg񓧣Sgm7)Q]˯rncȳ1rl:uwݿ?RM6'utڵKpDd}36.7XKgS3 Յ7Sgp .-V,-ө366?gThJsv:)|F!+QzSpWH]T[NBѩ,ڐQԮUh)|OEq@ B^_3@3(vR/uVb WOE3Lt7ݟ1&Т'b33Kks"2j+Vzct M5˷o장s[ WRgp_z3u[dPvYm:K @2*f_=tVȊq33k7RgEe`ծ]J_BVLFu99;JC5+qWQ]Na&@ e`+7Sg|4O=:hcͼW]Z%|c=u _b|"'ʩ3  $P[NJ#G84:hcwFej</Ļ?=ͼ:/Q=:{6?:mbP]:஌<:hsͼL_LfK]HW(d8ҙܣnPj3Rq@ O:ٸ^y3uІz\9?P@8ҙ(d3G:AHXIpWFMG7:Z,͞KFu%.ͩhTSp?ѩ܇\I @"VvQzc@X3*ܕqW7Rp'1\~>uamocPiT#+ѩ.Hth曩S4{.fϦ.\PƮWH63( +ȱRgQ]+g7bm~.u wc(dSՅhTSg @B^I!u$xt4+SШ!6v2L>]:`PjT#kѩ,:H3oĕ3Q_]H$61.J4FpDO]-VRg @bksQȊ3rgTfmb s4{6u4z8%u[pқ!e 12@)d1L -͞߾:%|3.zwm(C/I4M̠ $oG:O:@B,͞KFu%9;rá( Yo XfH1(-?ЎOBVLtrt4)X_}š565~t`R' @ ]:a&uСWSm7ci\,͞M}lv1u pj*GcSp Y1x\ Aի3aeE+K!F fވٳq4h7}!h)l/B֛:mpFvAhͼkFe?Qr ýk4\h|3?Bh(H66?:]`PZ/hv6~tb íWOE3L|Fu%.JWN`<GI62@0(-Xq(h[7_ItFu9Fu%u +oW_|c=u [T|3_z3uk{=:y,Cc3˃f)@؈,<zl"9f,^q0 d}q䕿=)l,=O[K%#Ǧ;7X:ZWDm:mPȊq?B֛:m:]dPZL}jө3.4{6fϥ61Fu9u SQ::mTV|Ġ 74:3.6?WΟf:B3ߌs4{6y#ud|"<:mvқee]:`FMGqh,uEWD::ZW\Qd9%u۬Q]22Ђu Wzc@7]N61Fu9u ۨ84{K{I=x'SglI޾" S.ry#~(|Ho/_o_sF^Qd}Sfy}=fϥ =Ϸ6?:`[X k4{.fhkJ\9?;Lu3Q::Ygc;ϿM1=d:Ѷ$" IP6#-na+.Ш(.j[ܝ]y{hj CY$e DBmCAb cYiy(2&WJ4k0߰cH'O@0 /`2( Ucnt(ux }Rg+Pyd09Ye6u 48{PTgS?v` ԳZLx 1( lA5;OHPՙۃQ(NQj}1v셨g9,={gSgD#V02~Z EqSv UϪqȡr:ՙK1.havŶRg^I@BeHh%\:X.r7 ~ȮϦN`zģ_K*lWLhrbv UGEV|qėSrO//u Khz $fP\eC@KY}olt `ΌD)u $W(k/Ĺ),Gͩ3XBRTgSgAh 'Dk} `g8{PLO\bz8{aOZ/#USLrB~?S Y-#3h eAЪn{ĹxQ:nKuR x0^I2{ɃQٜ:e2=!Y>  4Ĺ*3O>lޒ:#Y5_|6N[2=t<9ՙ),8{>:e4=?Vž[MRg,\{_v_ppTfcіkOT=E..Q_H2޳/y` Qyd\yL L[֔GS',Bf9 kP lTg.N57:p *R@]m,:X,n^=E]Z:`Ix_J Y-D{qMz䩁Q_H@-ϟ\{Qy*XeIݱ7uY _tsCUfs.4H2QמwRH._텮),cP:Ԗ:ugK&/B_ _<2g̥)@Ogl wO2L:3:X,n]Ǻг%uw'4R:5X6ՙKq+څ)$*lT ;Y,-up{^IWϪ1v;:7yz _|6t=M@RT&Υ&U̥K/E._HkGCXՙK1<5:нg1<2:X,nO[=lT %޸R::Z^˯;rbu9qP:нg_l(ud;֟:ז:}nVƽOiO|9|/Y-u M:s)_<R =[' ! eճjGNX"/Ķpp @;?Ye6uwm?:MGG=NMxH._Ggsg;?:&X,LBtnڕ:`YtzVwFSܒ2_?FǺ94̥(}R::_=v _=. I\yd0uzgг%u-gx}qKQjshbg:3:mX}o g4Ub/upgY- XQl},#'F}!u -{wj4]ս;ؕ:3JLO{J@xգqp Ah7 KlrBt< дߎܽXݻ=uh@?|,TNAu.}+Qjshp|!vER@|{nAhAkwM]#ɍͮ~2uWD]sE呓QsQO@ Xכ:R9r%n[[`qGDX @K<5/̥)܄2gc/D= |0&Sٜ:3yR'Vžj/սSg$vq3FPWJgvz l@}?RD_ŚJ@)` X[`M: \xO:`Qճj\<8{pd9D)_<USD?{>:dL;X,W=E]Z: bW仺cnt(u *Q95Qْ:`Ego}obz=uM'Ɔ|2u 2Q3hreEճjmI+Pr_\0:&Խg_l:u jXd492ТNE'E._HL]q°4u*.~":荎usV2o~GRЄmAU&J1yz u- ܴܽ+u@2mX(9F}!D<k>mI-k@}?RФ돬2:Ж:X: ;Ƕ8hmsPS(c@ԳjTgK<4D)*Rg"VžҨg(lzS$ձ7⮟|xЪnJLTfcіkOY-֗/BzXgK~?rRƎGVM@0(-F}!{3ܴ+::`I_˯z ܦݩ)49c2܌D)&O7u*?/rBl},]v4nJLTfcіkO3<27 shr|!>o^2&5v?l ZAXrsӮɵcuR:@"_˯zc]oUjq;1Ǝ`Eb3Z:W(2Tg.Ń'3B{+ڋkbnt(u Q_+3Q-ǚE[=u@C)WĹ)d =SƎGVM@1(+B仺г%u @C(lzVwFS,Sq@otM\uR?|L7 shdRLH@ 2(+D=E}3ƚD OrWJg2Qͻ"/NXvo}Kַƻ!?>VnK@9NGeb~Σ_|ˮ2q.`LOk/`Zжs42sRgТVžgXco іkMJLܨ/XV7 qpT&JѹyWIK2Q7_Ƞ@,mGϦ\ugxգ1~7}p;.x; AXaظ sӮcTdף<2mIlnt(|/ōBZƽOǃ'3h2Ye6Ǝբs.|5[kcz=u @RNƕ7D;:)ՙKqGR십oSgЄ.x)33hqe`gx`h8mXݻ#θXY-D<|!uǪgx[_7UfStJ@*1v?u+AXNE'9 1ڋ]QLNEyd{qǻSSX!p'Ǝթe`[MRg4|[kS4va8Fbuh/vNVѡ(};?7 sX!p'*`0(+TuR<:aYe63SBz\~QjіkO0R돷_=:Ę wjXde`Q_|WwzNhXkw썹ѡX^OPޝ+o|WwtMYe6.x).W,;Ǝ?y.uM2Q3XA Ufco~.u@C{`Ǖ7θԳZ\)D):7\: hAoz4ƾN`*lGh˵N7 2(+BztnSV[=:7+3q:d٘:qWD]sR9>. {/@-K@Lb@ V2@ݱ7u@Ck/vEqt&u @êLQyp)pG*8CQ4$@2dX,c#̦`1(+\uf<6>tS4u. NhXc#/NHecc@ԳZV0c2,D)&O`2(DѹiW w{d٨ΌNhhW*R@D`돬2:ʠ Ye66Rg4\{tnWJgF}!u@S:C#(<mI@呓Qsq°*4 c2,D)&O`3(DDBztnSB{+V?=#SJeW8Xכ:X&呓}Q4$@C1&R;Ye6u+A#؛:iG;FR4zV+3Q(Eh/vNHeo_vԳZc2,ɘz%u+ACՙ SFgKԳZ;5:d~p{S'2Qc1yz S/0&Ry>ú$gPܴܽ+u@SYSQ-թ)MݩѸh=VnO܁2o~1yz lXdX*呓QLq׆ ~:h|!J SjqȡΌNhjmܴ3u p lLp` gLZȮ Ub/u8n"-SJ[=qq:iճZG2Qͻ"/N~2Oc #'0ڰaÏSG%ߵ>>}h u@S\GE=Nh >?q!h0Ye6&O 8$@0&R{@dgSg@DD*}#RjѹyW֧Nh:Ůx7ΤNh NODw{XY-~h}?ޝM7Ř KmzoEh(e]=Rg4uꎹѡ)-F}!]?FC2|\07 `ճZ>Kh(eUf"/NhJ-Uf:3:eԳZG2Qͻ<20$@33&rxգqp 2/UjvMk펽Q-թ)-%*ѹyWS'@1$@3&rg8;ܵaÆS._Oqg8{PTgS\*6}+,zVWb{ǣUSm1&[q_n>׿{[>Wtr$BS<=Rg/0(J?q 3Z=k/p ` gѽ糩S)U:b=߉?U??s{չߎ;WV=] ɠ +ǧ9NUg.#|D =['F禝S)`%Yw;[j?DeXƎGyd0u|,2ma7,D)9:`Eܴ+}P;קNdHVcLV8}xc*:VpYGcnҥ?NeUf_ʠ kǧ h 呓1v+F} Oe( tth4uL[w⡎^|~qGFDWc_A:|Do>i&?D ?΀e5v?#32(ܔG禝3Z遘>ݧ>MY ??;B!1~-~vݗp0?? qC:f.忷Ќ3bgSgdP)vg^H2TrB<āظ)l ʌ4GTXYޞbTwLKҪbؗ:h|Ye6?/rBvިL"̦NX1nڅ(`(lIK:s). ~%ƎGuff8n!߸gxunoX2RLHAճZeڅX^OԳZ̍Pt{0]S'LbX\!Z1񩮳?/{NA睸뮈>:ر~ڰaÏSGӇ"bgxQϪSVM'D禝SU&J1yj *R2&8>v(rRgР/?Mjnt(z_ )b_y-D]3ZF[=l},čB)Fyd0X কGNƛ/qcy`l:uaL_oýxuno XT=:nATg.ņ\SbWX\~۩SVS-lbXUjqx( :mO "ꘊHVOB[w;1'bn)(#'<2:nAܨ/D{qMݞ:"sCSV̸aR=ۯx>qƐ +ƶ{gSgow:&pWD Wv΀;Vjq] MŠ pbާSgB2 :3呓q(<mIPYe6.x)֗څQ_HƘ @c>>y.uM⡎'~|w#oz4bPe(lIr =["FufTltEGN鿋lH1B)Uɮ3hB:1nOVS3ඬ*}#]=Rg;kcz=u ?F}!*Bz\{,P=ۯ7ŸƙgI1?kSgЄn?TvH≗:3:nAeXh/vNhImx`h`e]ՙKqi+qQ(ōB$Hг%4?\*NAX?M:s)ߤfP#7 v--{wĕanP/ť~г%v?S%rWz (>uܒG2:nATgƣ"/NhYŮX12M ''FL._~u4꜋hRLHwĠ pY-^׿:`X2ccnt(Y-u4Mb?oLXV4u\p|/Sgɥ?Y+lmرRpY5&O ǟ{ T&J1=J̝J {ϾضP nCShy'kGNFuf[ߦ:~1w?\5ԳjGcާR>ՙ( N6ԳjLSѽg_<āwO-Ĺ)4?{>:[dLŰ?G4zVOƠ h^1(?aTɕG<2hX ԳZLȮϦbLy5"Xk7yj Y5u,2ɮFyQL]sITe&/ĶN^|+uRYe6^Iʠ &OAeȓ:3ՙ),Ĺ8{\tna+DY-#1=JdgS@S (lN4uWt O|9u,:2ʮFyQe鏳Gh!sQ8gmeRCg9д]?1&VZv24D)EX,ZK=E}3V\{<څX^O"g?F=Eh˵h)WJߍc1yz 3q: VgKyKZ:;w3k:1pc#̦EKܠ^M;S(}~Ȯ dgc@Lxtمt IDAT*e܉̥z%E=P\)@YNɨLKKbUXKltٗ:`i˵GqtM-F}!ޝUf#womJ1v?&ODuf34,=bǿwdZȺ{މϬ~ Z]q΀r_ԳZ X@kLD):7L=1~;VѱPG~{c{#".{+8 =c3q!`GsӮ޳/|6u@êL>'`uJ4;S'&ODv}6u,6l@kܴ+v?B g{Txc*ߺ?{[18֘c*PdT`w{=Ye6+zɃqS3Xۋo_o?RgB/#gxԧDs} γɮѱKʮ;6.M¨ ʔb펽<+PGcPhy=M1(b?/Sg]Tݾ7u \`G 2 s),!2,W..?J Uf%KȠٺ{މS'kXߏY}okmMj kT`eLĹw{="/ugGd3s` (lN4ŷR'}?u,Ub/uY-p :X5r_nju @m>}3m9+WS缣ի.Cxq?LQ""^+_xGOEaxD|(ݩWq\?dxkqȡXxy*uԝ|gw GcH-@0(b[qЅE$5L @0(,rR J Gr|:o>^\3ܞ:x2U0s'cz@ȶv*J0<1h2u2^+_Iuc˶W[dMSXF}RgPcNxԑ::sҏJƠ ,3gc)U#װGV\帯Ї"NRorR2u2u (LQp6Vl;Sgu\?;_c8Wߌy7G@b[E>CGt jLyUt) PW21=?߿+u@UXG{\)7eOEoOWssظ(qȡ)T1wb<ѱe[tlٖY@;y!^@eٹ':<:!FXn\*eܼ7uP3?Gɼa?W1*o0J(ΜM@*.EaxLⅳbecVߙ: 1řsq_ĩ}q!Qd_;c2u?XtM뙏ΠN MΠ l^+_+ks|:+ʩSm+_/_9[z,<?;w1=~ #;#ͧTq\?d߈󇟌x|%ul>wH@beX +W ΐ,NRg3(,̹>+2S*κTf͍ɼarlᘻr{pg-p^+_WN(LE|} qqɯO+S'\: x_#9a霹K0q<_$ X1Z6N(rShk:e }(//u FeJ٘;9/`,ME|d[Sg8?Fd;h8SeX*_Ըo\)Χ$23X3#2٦)!װue]ɼaOƋ󟉅WssJ\@5)qȡpPd[ۣc˶ز--e 1wb<.9dLǖm'XjrSq<)A`ٕKŘߕ:"+2Sm<>3m+1xqw/~}[um}1wr<SPŮcx?d/+#Y")f‘_}3_בPzv5J@t6NA:{iCTHA :OOIx|%VlͩS5,o)I.Gooq!ܞ:x݇7sh^? sS%YdDjK&-}3~箁)T02,_8SgPcJ gXiLĿYؘHQV(}mܕŅ;S"hTEZJgƅ#?EcDcsk4]ڔ{>gܐ: gPԸ1Π{l HΠ k+bectmNzOǮ?HQqZŇW] S0**.+S'=e\*Lq\?d߈ɱQ ;h8SeXJ|%fvkVNF&33"*Μ;"Ә:`Y=/c3*Һtocہ!FeXo).E&l\QaxLq(.Yǖm6z,6'RgP^/:RgP#ni IV+V6FK)˦tݧRgT;?s?}2PʥKQ8~m\4hl2ʥK<? K?zʈ Ը I@:ƅ9,_8SgPώ] e3?Ѐ?{2ΦΨx|%Ň_ms rR2uҸ ,Ra6N<όƩ}řZJ4` e_؞:*t_seXR+~c/Q \t)~0($ZJX-]S,ի.ƿ^Ψ+W㣷ůoLuϨ )S9/'E̝Rg$Gp]SReXj|%`,KB;WߌWNI1X3#2٦)KcNr|;k35uԽL)wGqlTi~6ȶG[Fǖmܐ: *;1cQM$axW3RřsqȡPqx|%VlͩSԿY5\NQ6UB{+2M<~Jq>uu\L~T\4hlhlnM˦T G󇟌O~-~v8s6ʥKD:l\^u1u5Cx翟:*uɯE`T.: 5;hjֺT5:du3>\MWN})^ͥ΁6Ep(ΜMQ1=?2| ^VSjOax̝1߰~X׭tԅ#OGaX H {SGDDV+V6FK)K_|0ඕDmg.m_9PVdÛy'Ǖ| DqlxedVud[;bE1u|`l̝x.&xGO+S'dq׿wfSS!NBs | ҥ8ҥ)P>twS7dȞdR,G{7(^%zKSKwGql.-]o0#Ҟ:(;s'le|)ԘS'P'OΠL>3c3b*bRg,:Ʒ&$ ΀gTjmm?hڔ::W9cQ8s'SU"C.n`I8r9&?i D0cΙ{ɤxgĚ5tꄚĺtLklS gcz|LL6-6]K\s'ƯȔgS'Uc˶ظaa67W]u{NgP8R1Ԏ[_HP>>M 󟉅WssnڕKŘ;1s'#]Ὥo0z0RP# ǯx܌5J@ [J@m~!^` *ɫ͠ P=kwE Y-=rSS_2* 1*u W9ř196l>Z6l? "Ҟ:*Q9s'¹^'"GϧwG[XZ˩3GIU PʥbLJ(zON ks_Rpg[WGeS‘Cs`QKŘ;1s'#""-]_q7gEaGTLԐ|gw Sݽ-"װ"!3QMU P=kwD&۔:বMk.ǣ=Ƿ&S@]ٹ;"¨ 58s63gcz|DDtmh>:c@X.-]:Pn=TgaPXR1wN)rSNr|qH|kO`kFeo DDdhٰL=qɀ šqC33}::4rԠ `Ph5;ܰTө绾}ͧ㉉S@]3*@)1wbZ6lzȌRxsuU\_oMILugȶhHR1N܉kk󵑙|gC0sogΦNx_=;DǖRg@DD45,NN.@x~?u 98bnAjL :}/N|;zON]mSKU0q, " [;f$V.]6ƈMjh;*t@AzW8cP[wE=u usrXx1{3j.uԥ7n5*\qlgƅ#"ꃇhٰL&۔`iKǼ> S9Y7,C^ŽG#&RWps Uerl4zvNp]zON}|XQHĨ ,rcQ8ve[#}m`kSBc<u[ .7::kG)$0̨&ʅ#bwnHn}!uamn:ppgKFe`ig4?s'#b4"̛C3FfQ*\-1@=dqJk:bŠL=*fc3Ι#?ac6Nujk<ߚxA$Hc)Np8ʥbYo 42hd8s`LBYmm{>g.R5eR'@z4b"u"0(Tı(Lw6PR'.7ķ&$ ΁;Cqۻe#3q7f δV0(L;[ԓq9@%5\Ɲ#s'cx e496CxWrSk:D_xb)P@(_x햮We28!H "\tm,ıYe]]3@Q2u\gaPJcQ8-]Rө k{.V]Xx5:Q\Wߓ́lk{d[:eæȶtD{6PJScQ戌߻L6=mz8@Xߨ4?:jAjMFc3Q߭/N&6?y(o\[=;gwnHPZ9|TɱPS>twSճsOtly uo/G[,WooM<NT.]mTj2ȶ_Õ@q\K(LKQ9,-b kPOל_X4uKEIp3&A^uјL 5\/n/}"sdM?4lTj1?mm}\;24EKh*LrřFcǚO ksӱzxWNa \81XeV G6*TR'vTMWssQ[^2WGg^y4P3yp0d?4l|:u]TʥKqH Ie7w e]n:uKޖc=Ƌ w΁6##qjp\8r(u@T:1?#3W:DANStڨ1s-]L)u @͹925hrl4ʥb IeWgFcRDDD_ XBksh9Pwzv0*lg{| IDATupLwDDlat3\*FT|s4Rg|f @չ*O[XrP )L3fjb7bmn:uK,p9q$fvkL;FeQ.0q,"|gwdtm7{PRaLi~6J P[c l>z>;zS5\N≉SgHI5͠ PʥbLw:c2ucB|ԗb\+=;wGK8)@y܉k[6_:[:;7,A)K\řQ.#ׇcԯ|gw󹽑miOj]n*u{[FL`1L*,12@͘~@h [_H2[olr|'6N9PW:<aTH0q~/ohٰ=>"7Oqܵ7Sql/_?~ۯwfpGlP XW]L(p9ksS lLgPR1Sut5\G{/}"so\!{ᙈ-M~_ҵKYg4?{CK&O^1P PZrge`P)[wE=u P Էw<ͧ?y8^ͥ΁ѱwvov oy 7"=;DsCX2rS=r,V/)܀6VXlcpBh=:JsC G&OԠ-ۢhؘ 5/p9u{[ɨFҥ8sp$u 2@͹pP&Po T\ƑصS1*NԈL6=;Dݑ6%w }qXnhgSg@0(Ԥɱ @rxX_u)P7%Cѱ)lr S'jk,F)Μ3jRaX&Lo Txx۱`dM?4-]SUc˶ǫ7NeejaTSKuǠ P| ,ի.wk yg4Z6NԽ-XT3GR'aP#@ 2(b5\/nS؃%6##ѱe[`mp=lSXksөqX^7hgΦ  Pg&FS'5Ƙ Kޖc_S@Mٹۨ Ԩlk{ _+)P:<=;D&O܄L6=;Dݑ6B@ umz@&  PwJ1=~ uP#zON.Ǯ?G{wHǖhب T|gw |a$:<:JSf!uܔƋR$R.]ɱhKRgUnk::|:vWcuI ?4)~xd$-SPZ8Sr:x2@]*1=?uPz_H@qSw [@ȶGpWZM Qxꄺ3wrQkw5v_N6##ѱe[] #ODKצ)PS'M[qeS.]S?N 2@]MTu p͎;?+/a 뷺*I&{L)uTի.NE3z4uBݘr:xevȡ(LOT\Â۹8ksh)Ps߿+zvIDDKHtly u ԄF2ԎөBaxLO2@ݛMT[>2.Ǯ?SR@M@ G&Ouk]?Xd[S@XJי%W.]SK2@+L GNTt?竾WatmȶzXS=y"߿+u ԜJmc3jhgSgà @DL> @mvb22٦xd$:lK5+=?lSYM `QY:=:Ne^7(.1绾;Sg@ٹ;oݕ:jN[`|dhN67:=Kc(ΜM\'2+qH ňj㎧⾶Ps߿+zvI5!=lSyW]L+Μɱ`P-.9řs3 w };Fe` tly y"2|Z-]c #fSSn5ޠ^|=: ͙# .7:nʮ?uPsb #NUg]?Xd[S@]1?ř3Ƞ &@Z[zP_΀mihLU!<ߕ:RSf!u,\ 5Tɱ 0(ITR'Xש3&eMqgƚSߺ+|)PzON*ةGTL24?ϸUmrө`|},r nqCѳsO 8Jug?c3dP]L?{ ʥK3 BX4q_s3uly y"2|kw#ODKצ)@DuJ٘s)T32\*ƙ#3 kXpc;7F"ٝ:ɶGplPdMsXbBpKM0(.9řs3 Θ 5bM΀mL[`Xvkw#ODKצ)[5v]=uB՚?c3dP}98:}:Do P2٦{c),2| E&۔:xP^AQ*h `xcqө3 `tZe, E=3`I GFKצ)h,N%q~aMꄪuQ.Sg u|Q.]J$fPZb;[GL6:U&{>7dR9jՉ_^ꄪ4=~ RgĠ u(@BrS`ɬMN3)(#{Fw0u pR'8< UTɱ"2(p=l r2٦-R dq=lS:|Z4wxqU\*AT.@"}:6EݱqéSk)z $(LK,Lj2wb< ǣkS`s+Kl"?^7PqÆdJ5]=Q*h ` HPmI,ի.:HhCÑNjx c2PR'= U]x5ʠ T9Rg!*j5wnh0%CñqC6nBSf!u,Ψ*0q,uD ܀ɱ(.Io ^\3u6lSٽ~)kw#ODKצ)"pZr~aMLꌪR*h ` R1I,R':˻R'bL6::mmظdRa!u, k+:pK2(p.9řs3e67:;CÑN@YuW jL 196:XenBaX\8t ` BXR^d:eMqgRPoDsC`5z-zK?g'&4&sNp8ʥb `dRT3Go|PR'˿=uW;`QtmOlK{`9 A5r{ [G ܠgF0q,uL ܤrcqCS%|:u,}/}2upzh8N{,3gSP2|ߺ+ ~*u L2 ,zK|٭sZq\LAE0=?:l|)"Z\$xWnBsC Ǚ#qȡ9TظȶNѺTxOP)5ԾR'̠ "9sp$| *j5履L,L)zv|gw98:*ӻP\C%:&`h,KSS&23(H ‘cSE|:u,'&L,5|gw{{\*L)u un|xWΩIřs196:H ":sp$.7:>/.ܙ:X-]#{Fw]ߒ쎍MSĚR'P^%a?`]sjZt)N{,uAET.crl46n(u pr 67:5履L,L)S‘CsJT!H `.-۞Mܠ (-oJ BGq=POm6D#ccS*QZ\:*vb+ 12۝:߰P/KT2KhrPGMSx6uߙx:.&uPAڷ/쉹sEM]٦)@y>>[\Wvlwss:.| ;wd0ٛ:8uܲg\)]sG9܄lsKlٶ3)@rf-_,ĉng(6: eɘ>mS!7:nɛz3 e۳Ѵikϕ:*V"]:RͧNBŇx`Df±@1( .֞~: {ȯ:nZiqU|WRgU"QޯsM]ehX)u Pμ@*HŇ9܄/qD-eBy>ڝ:rS'-Ӯ7$ܑ19|(u!m-vFkSf-M 81#s12۝:[p!Ck2(LGFkO4oM|Ƴঽ<pӶl{66m^P! ;bc@dS5海?mPł5b~|\86:Peѹ#ѻk0u16.Nf-@wq=$԰vslٶӱ `Ɍv-Rg NulwvGi1:d|%MT02h~Pl|l u :ϦNVZ\' -M-ѻk0ÇRԕL!6 D[a{Ɲy(-܊wR,81]:%pؐ#!2(&x8Z{#Ԓ: dVx>uPcl{66mBy>u@k-vF&:u P'Nv:ۤxuM|oψL(vDeBy>'u 6.Nv噾@wq=,c˶Ծ5u Pg_,rūkbd;vN,KRgU @׆xf8)yϏS' )-odg eZw`OwP'bd#2Է/\/2 M֞~Ft48u\5wo~1uPM-ѻk0.:"u6Ǿ=Nb.^)u rN'3*bP sG3mMNm|l ڻ<\#2թS{}D˱ȭx'uJz/\w\zwM*̅Wb~@Yظ'u@=+DfUCܳ#u ԵP|ꮷRg'zy/]z4u@D{2޺8幙9%YO?BܙY:#])uxuM<ߙx:q&e-sb@ʤ ±hw?7:>Q8'Sg|H&:Çܑ9e[S3}a'XŇ9T?7uP T|}iOKgS'uiȀVM]qſLe6ƾh+lOpSO<7SgԜ81ߛ3" ?׷W׆xf8)Pw:qD?(>g~ ujX)zwsGczheV"]:ঽQZ~dXOSޯGdFcd;uUhz(6:be*ȹ#), cW߽%]>;ڻܑX(ϧNX2M]ehX)u mq_Ƴx6uJU:1#q7<7 ֭{?uM[aGll +ȭx'u|>2*f {b~)U%lP=]-ulwss#+p2C!,{V%zw ƅW±9,mGR,b.9ʛf-_,Fd.:dL-Xn#w` c[Fe*-?KIp2ʳ3SnJ[aGlLvuex6JQ1~="sbw|ĩ;;uP#V466I]#+u ԼǖpMߝ~"FfSg+㽅_[ϤnM]'⾭;3+S,5Q&zONIxuM/$qʦ(-RgQWbt⽅SIMpG%u Դ ,~!umɮ-۞M[c}PO-SES)/Dn;sEŇ9ԉ{}?n;֭[~+ٛ:jڋHoęHdW {bn~/Z)m-vFkS*ƆfGeJlw|Xe79|8LԘL>(|G!u ԤƳ~P|5e19|8.rmH.mGG[aGdST7J/9ůGdFcd;uuj~|\86:Aw[|L!>ܐGh9C 磴Kl1?zNƾ6NxC:1lClٶ3Z{OP3r<N7Kmb!Nuǥwפ΁k*쌅|"me۳3&6şnL81WRgTSq=R,mGG[aK޻/-pVl?xuM|oψ Ucs17q2uP TgESPƎu:>S{p +1~po_NT֞زm!eh~8z3MK3Q&Ffxx~I~, ŅcC3:`P4Sg@*:Ϧ΀8'O: Kb<:Blٶ3M-SVnE):9gcCM(^]o⵷>g~ UinT؝:eƾ@ jȭx'uDiqU|QZ̥Nx幙i_M,%K64wƾhjߚ:kؐĆX)}Fi}\Y6ԩz +{M&u7±w< k7NtݗP1 \lSKt?7&DžcC[mnzΐ @{>""μ@X> ,;SpsMU+r5L_ V_)@v*(6:3e19|8uT{~:""b/NZ٦~folH$6Ėm;s9e~|;2:Cܼ dž"YlSKnЙUocx$S mGG[aGdS\BJ~/Sguܼ|/uT+  5a5RK#>Pl|l PL Nhllܓ:W̪g}Gwݹ::vb+;D G⭋gl6j鏇xOܷqgfe5=JySgu,:[wP; mjIU*uun9u@jX)zw ƅW±9-j鏍}Uc~|;2:sw-c}3jQZ::q53jwhX9u pڻwxdPBy>u PV466I+Dyٸ˩3C}+QZ̥ +cg#bnT:4wŃ7+Sܐ_2: 2}|g!2թSvGGԙKIPw6>6Gbޘz=up M]o ڷN)ӣqOnFx1)P~xX HiqU|Di1:.llu}2⎈Ss_iX9:#6 D%uM:)aP.]u#w)PJl{)ԉN?#ݩ3^S{W;.sne[b˶fHj +q=QI25_ώĺ{2̬Lһx4ԁ$~]SͱOFfUCuqܕ@XFyѰvs[vSOFRg|A(/}[?:*Zl{)ԸN?~P ~=;⾮y`j+qաŠ @*] 6GSyh~8s!u 5*?_W!m֞Ȭj.{ WS'@M1$Ԫ?#P ԰=;~ɸ32u Tb.ʭ7:'J'g}G'TKS@3$Բ8(ͤN&25콅Q*^~>u T[OKjw&b.uʸoaxX(_IUǐ PV@2(PJ.Fú͑w}hl2*mqXH ݻ>Z{0[EuL dz1=J\xu(uǺcݺu硫`ie "]:*ޣ")Ԁz>.&u`~|SNmn}9Z{O؁ݱPOV466Izoj㾭O8ߍ||ꮷRP~P|8 3E+cg̪xxp5uTlsKlxѰvs%Pcyw\M ԉҥѰns]:*8v;"6.]w.N Di1:q_<7KS@2dz?o]Op]Xn#XlC|dWN[Q/No+3X"3q`ggR6Ǿ=NXvÇܑmEcc,Fx1)P5~]12/wņŸ΅YTrᏣxuM Hq]+cnTXRز+Sa9n~|~qO rǺuOz\[<3M'SPμ@|s3X&幙i_MjKS{WlSY(_o?ٙ)7Ġ @dmjIU-c: ""zw폆Rg! ˿V:ñTq`ML@6D[aGӣ3n 2DDDѻk0uprt486&?!o#μ@ ĩ?7ʳ3SAؗ)Ua~| )A>o 6>6: gcCbtˡ˩ƙo#uUjz8wdTnh{d{; SBJSNm !GM3[tݗ2?sjw&}/ܼ>? [ ;b˶gSgK6E~IUϞ?B jLyn&.2,5e h7$p &N؁ݩ3A}Ծ5uLrt48:g"I*v(-RPǹ#17q2u  m9Um|%y@,S, 2\S%zw Ԇmަ?7:"px:uu`nT\86dXN5!SԌoSg,2||g!Ҟ@b_4EGȭx'uREһkRgPG&NŹ#ԉ|g! ;}k2~p_LM =(*HoX6gv\Ňcө3SӣąW.ʳ3S2نwbc@dZRԜWbKΠ +mޯz \ӆx4m˩sO=]::gXvd[? ;"]:&Oc<:`5wE3^e~P|8O<:>`Xz5mxP#~75nlٶ3 SgUy,z3c[N맞KIŰ @w#ڷN c3A[ѰvS <LS?yy/b X^|L!Z{mjIP7ÇRg,+2\w` J{LXQȯ:熕WN>\D +19|Ȱ @6ǾBdSԕ8žΠ 7#l{6uP:3c[Nvlw !eijGG:.O}'AnX3}k Vy,˩s>҉O:na6D"Ԓ:n-؁1?z$ pò-ѻkdS5lA~8~?)f-oDi1:nٯeGFyv&u@6D[aG~PN' HƠ 7%Y'uPr+JG"rҖG_ a[,DkO; S ŅcC32(M{碵@ {4?ggYjO`91lCG##Ԓ:xf8N'u@reilC~uci`{xjw3c[Β3o?(-g@0,nŽw"]:0?u>쎅| pKn]3:[QcqnUq_gn ° GkO4oMGX(_c~) lc@l|l uPg6.4En;kW3}(-nS!TSqPML-m n IDATɮN'8(6:b~f˜@2c4v2oB/>lH>a; BӅW±Š E%zwwHnCbt4{r럿QZo۟KIPi~|LѣSnL!Z{mjI (/IPq p; ЗPyn&.2,Th֞Sp؁ݱPOPq p[=s^@(јat6DkO==M-sI +1g<;:"da@X(_C1=zԃ]b5wEkOQ|1v๘8:bkX9zw +qտ3,TL!Z{jȹ#crP fP%o 6>6:H`nT\86*$DS{WGkSͦG_{SgT<2,gES@"ScrPLMԸL!Z{mjI:#~6u@U0(6DɮN$TѣPOԐ|g!DkSXB +{|kNeXRB<=3 PӣGcrPggRU*=٦9,oSgT 2,-vF[a{ LӣGcndJGB}1=z4u@U1(d}ѰvSOC԰vsGkOdS&ǹ#3AE>k*јX(ϧd>1VPg {RgT%2,Žز@}%&Se,DkO; SHl~|M2(zx\S1=z4GNH=ɮN@X(_eXVlC~u0M-S*Qѣ1îP@ d>iX)ufs17q2u@U3(kX9zw +1=z#bBBG: 5~p_LMP ƾ@ JOCQ|m8sаvsvD9TWb5 t?/ڷBJLCQIDD%Z{?M-sScϦeH&m=7")p[Mѣ1=z4u ԝL!h+숆RPEs317;c<:f ~fo ,=ٙ9Ph|G!u Uh|%S2$o 6>6:A31=z4 N,Dw"]:*v=,2TgES@*ј=ٙ9Pun֞w"Ԓ:0~p_LMP P-ѻkK+ѣ]'6DkOක}%MP P1xK{Rgub|%G(Τmn|# k7MSg42T-vF[a{ MѣQ|m8s`Y`O}Xbe8{$P׆crPO:L&/(,؁ݾ,2TlsK)@+QW2 FdHis17q2u@]0(@Ew/I31=z4 NbDJ0~p_LMP7 Plm3>PӣGczhO:Ɉ drp;2: k7-Sczh0ʳ3ssFdD3q=3A*Z%zwLvuT<3׆czh*;;SA*^}iO OP9ԠlsK;֞hX)u\BJc2wmye @$)FR HbtHT3.wҹ nC׫^&]h+;0Ht0I0l`  wNA`o!YlI/)RDe(-) 72Yw' LD"\m@B2ƕ+QO=IJn'zc{P鹘ygDd(.3ƚ Q⏷Fz!u;t|^);|'SO!&P 2F#)vbh#N9#6=s`$eNl6bg2_܌zH{h#[h#sW֎1 Qj}2$iy/ @AP:׾3 a^8ճx' '0ڈz oHPҩ^k_߉JB)ݎGRxkՋ1ɧQ̂k|sSL`e(B\z@ø̣nJj-&./F}f!QOnDz'$(@i}R(a>q\&?K= sj-MϦx]AJYOS(y!0p3 EdS֣\N=$(@Urcŝi0ROJ6=d W+7VRz XȺnGfTmz03;ueNl6bge SW?Kgv?ڈVdݝs" CL<eq3>ZScm2ݭROΑ a>Ն0<@I0VX|{?f:z %|<ƵYMb2#(XTk[w`DeNw#3@qTGmzN@ Kh# N c6=׾zoݭwf`T/NF}f8 SM= 8vs%z38e2ǥ38!HY8>;鹨'SOO?p7 ΀ c[1u3x3p6*q8>ԓSkGzgDPv;QM=SݎsYIPxsMo{Kgpekj-xnTRO dNw#3^I\Zq@>3zpNn'6W%'(ثMŵo9{qqhʮ>p9T듩' Aǥ3Hs\vBMdͦa>|^)A8rY$> f`; ̧a>ՆcDPs; w2Yw\8w1zM11#(ϩTk[wRz #l3vdݝYYx pZ͕R /Ԧ׷S`^dN>lI@I/A SW?KgPp"3EgyzP}fqvůgm(*1^GPG* (VD DdTSQyBԦREmz."cN oBPbgg@)dN ,L|2QY8\H9`<>ܿz (w6=z_Fg""툈R΃¨Tkǁ\T޿bFFr Jz;S#ݣsᙬ J AWSQxx>3loGLSP+7Vܵ f"=~~~SdTSb &">s-@)ϥ33>~Euwbs߻uM_""?`* h1u;ڈa@)|/SF1_i"~|?; ^xzq2'_|>3BLw!([1u31u;/@IyMWMggksQyq{y] )TkqJԦgSO $Ńz0ώ4H=(a>dxg2pDe75ڈz % (g$Dz0d8m2pmēwRF gAPӍZO=1O 9h7#vRFDZ Ն &s2̳h7cRO 9ʺ;R@b2A8gݭh7WRQ.&zx}9֣\N=1!(<;z33$&yܿYzpdHAPYl6"丹"1RĆy-01Ruwὥ3wu;b2$%(#J[ʺ\mkӍSNYLfg0e`<;z37$&(n.G FPFjCTF HPF0Ϣ\a>H=1F stDTF LPF\݉'o OP Zvs% k| &֢ZO=ƒ E!(n.9{ɺ;k @<;n'  b2 0ώYeySd(*A(`/6W2pd(2A(rPb2 h7WR ezwS,e$~nZg@P&2P"r?H= CLi}%n' yb2 0ώˈPV2PBH=N X˺;d gQ(ۉ.)&!(aT\I=N,vbsH=d g*?;:$*0Nb2 p d A\^k=3`l FTd =A\eJ\q.F pmDz\^k- eDz5QRI=_]H\mDI=x{Zvs% N@LF @q=1a,uw"~QYH=Ⱥh?RO^釻koȺ\m0RO^z刈Y%[k8A`.j#[ (=Q`TeN<Ⱥ;!(2csM=`]~+~z0& [V)@URUrD p^<Yw'e^AT8kYY)@  pVzxr pjeހ pڞn|ON=(A7$*vs%z38Q] Al6?{}yhLƣ]%UNv"I嬩?Z0GpCRhd -CR{( Ada K\YRb]euzg8? m~x<y90kx!u Т "2,ٿӨ]YJf\1굕SM<7Ǟk+SIЬǣ^DP]:z&FRgm  tdDQ&F`=CFe^[/ GyLXFe_,Fib$*RmȠ *1*KQURmjCP:{ǞnLK^H XFe&Fҩ3x!Nzm%u 굕8}1aX#FeUgѡ(ϝI>2kף2R`ѡ,^H6 #Z]&=G#߻-u p'bfr,u+u@;*U)(MAubTWotddP`SYPT/NX HlD #\:zLEVIpS2Uib$"¨ 4cx5*@C(Mٗ^NhjeX&ǦONͿ1S3ZB&uk(MDD`k+Q巋SZFGggpZ>Wzm%)lRI@cX(zCShq 139:%m( 7RG8cd7Nk+139NLв [cvNETg41 SZA>P&=G#߻-u Mҩcfr,JgP9:&TX\:u2u @0(<>:&RYHT/Nh+e) \:zLEVIv2h QUp(u ^[ɱtdP(H@n=G#ݘ:RYHT/NhkeekpdzR.z=f&Ǣ^Nh{e-l>|)$RX\:u2u bPۖcǾñiSXg(MDeBLWVHkFg_ܙ)&2ݱkpdSsq*SeX7?x$RoL 3XeXWl>5*j8pT/N` #i3֥SXk)"2$yرP RX\:u2u k Iu?6G"ݘ:UgiԮ,N` |ص8]=SZBDL`!dsp4Rzm%ξ43SXeh(Gb'Rgs(2Z%u Ġ gӱcߡM^[X(O:3(@C~l D&1u @S,Fib$*RAVw{?ٮ)Max"f&RgAZ&=G#߻-u @êVKQ;: ĦOh8Qze4JA恧cǾC3BSP<:bPշ;vLvcd*Q)424|<mS1?5:ePctuQ+/E(ϝI@3(@S۱plx*uZ>W+QUR 6bXuJ&FbbAZBw{98)<7]YJ@1(@dh{N#3/Bx AZNش8,^H@2(@KW+QURЂ VvǮÑnLfvv?ؚ[XJ;-kr>zm%J#v1u -̠ m'{_Oҷ"߻-u ;xgj]ܗu ]yn:J#Q:gPcǾñiSVCqXl-Fek+1?5 Shé#`WQ>:|_~4}gݫ[⧵M~74tLOJ@P(nvǮÑnLp?Q҆{sNuKh$ox ڐA}=Kߊ|)7%QoYl-NڙDz.u $UYHT/NMutvv굕#߻=uGz(w1ۮNy'#xsy u $3xĵʕ)12+կbKb|uu\M[rl\)*1g?LP(H&߻=Lvc >j<]x-u3+{Rgc҆Bp#u4L6 E΁)@ \w1~UQ~o|wz=:nKWF!ow`:O:'~)4s8}H)AH<7~ݩs;Pb|swcƹ)M{.՘K@41S^ZHjCP:Y&]өSdTrꌖ/Ǜ3h 1?5Z%u 42 xRg Q?2;;ϧNi9NuK XWFFB92-<7]YJ- 4|<mS=3SIFe_3cq)R @d恧R@yl߱y>u zڙDz.u ҩcfr,Jh9eEt?6G"ݘ:“=S1૑븚:;nus|Q&QYɱ(ϝI-ˠ }=?x$>:Cq`˱|VQWBxONgPZ_8@ h8O^K0*иsQڕ) @ E'u $Pb;[s SXCFeK3cv1u 22|?3;R@j >Z<3:ubT1,Oxk)v @شcd7Nu|v,ワ:u˟羒:-cfr,*R@2(m"߻=Dw[XSj >Z<3:zm%cxCqXl-NI5J,x&~CWf(]=S7 >j<]x-u- Y>Wɱ]YJ2odPtH|BZQW+/E(ϝI2~l D&1u m(Q_'{RТޭnQӿ|2u @CVbxӅ'bזS L3H Q)~8x<:wgq䱨-R }%=]H:g;1mXLkNjOZDeLx <0:5Ɠw1+x'MzJ\dM׶ĞgkSXel~'5Rd;Nus?wب Dk˩SePXw1x VA|9˽:GNZ\el?y,/:hpe$zƞGLOonُbgv!u $U]5~8Dtw*8XgS&aPH3?r u 7h{.َSapFy$u"+ S&cPHgpoyN:ܟǷC hHFeP,'E:hBeЙ銁9:? |/?:hBqX~JӑM1&Ϩ p#jR?y,3)@ ~!uUJQ,/}yCmCsgCsݯKMBlgkSV]3?9O>J2@eZgoEelܱ7:3]ُoSꚏ-a)@ZwBTϤNZAa*(Nŗ!춡9m)Q_=HMgSQ?=/R-۷*u{}:2=Sʓ/}7Sg@S+_Ͼ|TWS/}O)@~!uUJQ,/}yCmCs=߉?:^jl?[S *8Ř6jR ܲ}_={cϣOG7u @vTo>َSe9w8f/NzJ,'cזSm7V)Bx-`gO-eSg5:X©|~-uf:Sܬ QǞgksZُܛ3Eϙغq1>tK`TbS6Bumy)>F37u@Kwub hI|%_1 f1q:hsVÅ(c3ѵͣ,5=Cs3eݳx4:X%J).LOD0:7 -cֿy2Gxtf6Nh:c;NNf ZCv%pxk˩s~A,'<{:==wh[7.u0=wnRp*Ο9 \>u۳[KwSel\)Š x/DΑ3Ltf6Nh8l~'WSg@èUJq(^AmgxHPy'u4Z'XJpS m^[ͿyNhC6:׮B~2Nzm9uM3(x`v=|(zJP:ʇR'X8^QԖJSVA-_z?` GgfS$uu{v!uO>ݒ:^el?y,/:`g (Ϟ]Hus{ 6+ƇRg@۪̟ Q?:`-R"wHzPdzzS'92~^;uZOL>u 3(GgQl Gȁ9k*q5u\MmV)Ņ(R2^['E0{ƞmwNXu[7.N1{yw|X-uzJ\dugPs,_z?7OF̦I& W~HhyڕXOQ-H  uZOFytzPFRMޘ;u O27TwB]LOo$UWn:ZVp*.-R427<g1xGOcH3(p0=|zP ޕ: h0oWkR*g+mH3/?r0Fǣ3)u׶ċ<:ZFel\) ͠ *YOF0>}.VS'@K?١dS@3$pc zm9ν׿vG$?ŇRg@S3$ps:_HjjR|__%kۮRIfd;΀Zi4N\ڟ:VRsM|_}*9M3u@+0=TzPFRQ|%rSg@K;&.>:RR<2kTwB =>IcKMb?~C3X]eIeL_x̦Ia +ƋODu%:!q:tfbÇo)ƿRg@S;rp^ޝ:!eP m_]Rmؙ]HMߌ7#3X/hWזXZ]ۿI@KM+?:Zv%.8&9-۷*u@̦9@ٺq1KMb?}{3akWb!? G:mh0~0u fkߏم׶ij>Օlh8d~!u_֯Ey6|dI@_}9|&u4ʭQK ^Iǣ񋟽_KЖnپ}RGrwĮEǰ w"q5u43(Q]d,>rB>[b!<█mKR IDAT'-l×)Rg@z4'.O ^Iǣ񋟽_K@Dܲ}_tfb`t+).jR\ba*u _A<}NXv\M5gHhq={c`tu Ƞ @{}:2=S&4=W3`]]?ٷSg̟ Q?:5`P q2 ?o +SgFu%:V!`P uf?r0:3RMd{.َS`M9w8f/NX8”!6aP˰S&r{WEnbXUFcc3` ?R)u Ƞ <}NDKb?pTWS 3$ ͽg+u $v_M_s=VoK7^ X8}<9$dP?37F G1K7eo+?$uC2>2|Cѵ)@?/Gjn{K7V)Ņ( ; xdzzS .QWSuym3ːL0:ePfX^[7.Ο_Iio+?$u\XOFy&:gPҙ{DlJ4x|Obgv!u xU?'2ocPbX1v\M{LJRgg*NŅRA2vTclǫw:u mno+?$uzJ S4$M3(lS nK1=:6T%:s4uzJ,'cזS k{.mXLB9rp^ޝ:""V)Ņ(RB & kt8َShqFcc3 *gX2$0(2,\lG5v{SТ+SgFu%:6VQ?:fPu>)@ۺq15R uϥNpFwR(NŅRڀAUR Η#a1u -`8rp Lv%pxk˩sh#eH° p=vӑ:&GOM*0=噼!0(@Reϓ;_roN M~x珤 TB~23)9242=Q|9R$׶ij>ՕlZXp*̟IaPcXv SHrkFSgЄjR\L>9p e~"˽:uR%:s4uM26.LODeLXeh e2=c;NP\ؑsc4zJgqEm:VAZaܟ؎W#a1u k`8rp \RǣXzm9u 2LW{ GFgfSAd;Ptl9=|%u 26QɧN5gPfXcn\'ܛSX?-=^"u ^|\xGQ[*ucP/2}"ӛ:hCs1D uϥN&UWnJ6u V)Q,LE:֝AN7,|x5rSp&?FGRg*gc!?|Hʠ m˰ ۲xo:NGjCږx磺M@"ڕ(?R)u4210:=wN֍1Dܗ{3u ߌ7#3HV)Q,LE:Ag={Ꞌ'b{.u Dږxl>N)а lS \>v S-G˻Sg+ba*jK9 gl7/:3R e;Ptl9mo8rp Xel SQ,LNbP>Gg+=# @ۺq1ƶroNikG˻Sg+QB~2/:A}b`t<2=SblljKv~Zz8D VYRǣXzm9u452pE+u |x5rS=|%uX8TTϤNaP NvT㡾;َsZkјX ZT SQ[*cPVAfso Ah={c`t:gQ,LEy&:eufox_{ 2=sup{r uϥNIrk:%UF0|k˩s5dPZ@fso +)M^KAh#}ox_ ޕ:XeCs1D uϥN!G˻Sg4l>(S Ƞ m_s$:3R\>v S>߈W~H |(Xzm9u @tEΑ9]HlG5ꛎӑ:z7~ohhJ)3XOFm:he}o)*vT/}7SQ]ɦNhH©(ϞL>u Є 3}M۳Ηc{.uJTWn^|) 26(^[N412g}o)*Ꞌ'x)r_]5;VoKr?@UJpxgOGm:heՙ銾}srd;۝d~^T S|9@ 2(ܐ7/L|َj<7{|Xb?~pɧ[FV,(S-Π pS:3]7/=9Mںq1ƶro?-=~t񱨮d|FV?TgQ-ڄA }"wHtf6n֍b{nU+_^~="3{:jK9@2(LWѵ9MꞋ'nzX|mKQzhTW\ИjRgQ,LSmΠ &}%GFΑlJܠ۳=߉)_;ުo-ݽNikW<\=wNn֍۰^ޝ )ϞL>uePX7ͽ.dfQ- Iн7`?P?”tEΑ9]HKzDftԖJsnAad6FMsع4x?]Q̊)F PH)qp_r%\8Pb$KbP n9px aF 72Q]]RO2֛xxO ;2Qegr0J=8Qmxh֋s^ p2~w=꧞9 'w=Mg)GBD8w2I>.s=, Oel]囷QFHDe,q\yYU?7A {Ynw=NM="2?FP8+o~ROY/^Ed~ p:EY\ypzfwEI=d gG&.߼r0J=Ά Lqя7o(~9wxj." e]e|<ƮmRȚ wk̻6"(s(fz5O=l ,zW72fwm4E9 ez׳(~9g^Em4E9dFP(.ѻ,$&]<+]&$2&(3j49f:E7$kQ懈LI= 3"(*]Ϣwu`zQWwLu2z׳]ϢStSOH7x{&$A~A5F5D&(W֛wj&$*A^D(w=j8,:E7$kẋL^EPWQѻE&(T[N SQ&ѻj4꧞pr (oW\q,L4> m9*Ģ IDATeHN?enR2y@^ŮmROW'(Q!.S&QTԓ! 2pYTitnIऔqTiTIf 7ANǸL5F5zuwԫy9peL&(;m4녀 "A)ʨF}df8#k1zzdAP!0Wh6'@e8[3z]4> ]ۤgAP>egIIpv6|YEgKPE5 rYͣ^ͣ}ڤ| (?Ef:E7$xUv)f]ۤ| r0~)~IKi֋h֋ԓ (/SQ&p`z|Ӯ1."vmz eUiTIqTitnIz4EԫyOԓ&(Y92($2Ԭxǀ ?AHShrtnY| ,Y/b6g *oص}8f5?dceDTiT!4STԓxe_c"ڧMY)C`NStS'/AP2R\q}hfz_!AǸ @m9Dc]x je ff~zyzI= 8#2@Dz4EOWԓeo22S)gVm9c>#AC\NGQSxi֋Wԓ~ :Ě&QT3ԳY/ј]COԳ~ jaq(Գ3֛h6Q>mY/Y/Rx52o)(F(IY2 pnePQ\2(,;A}(.QTԳW֬k$(C\Cl.R~P]D^D^DfH= d Y)CdFhC[oó~iz@veP\.MSL覞٨Ww>mY/b~jzY^53(((Գ(իصM4>c&4BP8:tNSb3dO4t r0NQF5DDpRvS,~boEc2 (Š~>:G74""$2I˻صM4EY2AߨSL9GQ]4(~yf<bΓ هe>EfS覞o$8!_gvY(&"^ퟫyi8At28:t#"N#"nygc,&SY/b~m&<2'(pf~ե OhصMS4fy!Q:E)63DDDQ]Fq߿Nmx m9`| ӊ~eD| |)dkѬ!S?DDD^6vms\[TiDDt3EuEGQNC^Ʈm>Q@j2}\ctM(m~ݮF^<y8w2dNr0݈?+}^&!ڧoDPy&"M~ry&"Y/b6~82 ~w_Fi"(WFzٻ]D^<~wmo<Z|&롚|-im|H )(O},.Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( Aod[+&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!D[sIDATLe&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&'aajgIENDB`pyo3-0.27.2/branding/pyotr.svg000064400000000000000000000240631046102023000142750ustar 00000000000000pyo3-0.27.2/build.rs000064400000000000000000000041221046102023000122520ustar 00000000000000use std::env; use pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result}; use pyo3_build_config::{ add_python_framework_link_args, bail, print_feature_cfgs, InterpreterConfig, }; fn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> { if cargo_env_var("CARGO_FEATURE_AUTO_INITIALIZE").is_some() && !interpreter_config.shared { bail!( "The `auto-initialize` feature is enabled, but your python installation only supports \ embedding the Python interpreter statically. If you are attempting to run tests, or a \ binary which is okay to link dynamically, install a Python distribution which ships \ with the Python shared library.\n\ \n\ Embedding the Python interpreter statically does not yet have first-class support in \ PyO3. If you are sure you intend to do this, disable the `auto-initialize` feature.\n\ \n\ For more information, see \ https://pyo3.rs/v{pyo3_version}/\ building-and-distribution.html#embedding-python-in-rust", pyo3_version = env::var("CARGO_PKG_VERSION").unwrap() ); } Ok(()) } /// Prepares the PyO3 crate for compilation. /// /// This loads the config from pyo3-build-config and then makes some additional checks to improve UX /// for users. /// /// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler /// version to enable features which aren't supported on MSRV. fn configure_pyo3() -> Result<()> { let interpreter_config = pyo3_build_config::get(); ensure_auto_initialize_ok(interpreter_config)?; for cfg in interpreter_config.build_script_outputs() { println!("{cfg}") } print_feature_cfgs(); // Make `cargo test` etc work on macOS with Xcode bundled Python add_python_framework_link_args(); Ok(()) } fn main() { pyo3_build_config::print_expected_cfgs(); if let Err(e) = configure_pyo3() { eprintln!("error: {}", e.report()); std::process::exit(1) } } pyo3-0.27.2/emscripten/.gitignore000064400000000000000000000000171046102023000147450ustar 00000000000000pybuilddir.txt pyo3-0.27.2/emscripten/Makefile000064400000000000000000000053521046102023000144240ustar 00000000000000CURDIR=$(abspath .) # These three are passed in from nox. BUILDROOT ?= $(CURDIR)/builddir PYMAJORMINORMICRO ?= 3.11.0 EMSCRIPTEN_VERSION=3.1.68 export EMSDKDIR = $(BUILDROOT)/emsdk PLATFORM=wasm32_emscripten SYSCONFIGDATA_NAME=_sysconfigdata__$(PLATFORM) # BASH_ENV tells bash to source emsdk_env.sh on startup. export BASH_ENV := $(CURDIR)/env.sh # Use bash to run each command so that env.sh will be used. SHELL := /bin/bash # Set version variables. version_tuple := $(subst ., ,$(PYMAJORMINORMICRO:v%=%)) PYMAJOR=$(word 1,$(version_tuple)) PYMINOR=$(word 2,$(version_tuple)) PYMICRO=$(word 3,$(version_tuple)) PYVERSION=$(PYMAJORMINORMICRO) PYMAJORMINOR=$(PYMAJOR).$(PYMINOR) PYTHONURL=https://www.python.org/ftp/python/$(PYMAJORMINORMICRO)/Python-$(PYVERSION).tgz PYTHONTARBALL=$(BUILDROOT)/downloads/Python-$(PYVERSION).tgz PYTHONBUILD=$(BUILDROOT)/build/Python-$(PYVERSION) PYTHONLIBDIR=$(BUILDROOT)/install/Python-$(PYVERSION)/lib all: $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a $(BUILDROOT)/.exists: mkdir -p $(BUILDROOT) touch $@ # Install emscripten $(EMSDKDIR): $(CURDIR)/emscripten_patches/* $(BUILDROOT)/.exists git clone https://github.com/emscripten-core/emsdk.git --depth 1 --branch $(EMSCRIPTEN_VERSION) $(EMSDKDIR) $(EMSDKDIR)/emsdk install $(EMSCRIPTEN_VERSION) cd $(EMSDKDIR)/upstream/emscripten && cat $(CURDIR)/emscripten_patches/* | patch -p1 $(EMSDKDIR)/emsdk activate $(EMSCRIPTEN_VERSION) $(PYTHONTARBALL): [ -d $(BUILDROOT)/downloads ] || mkdir -p $(BUILDROOT)/downloads wget -q -O $@ $(PYTHONURL) $(PYTHONBUILD)/.patched: $(PYTHONTARBALL) [ -d $(PYTHONBUILD) ] || ( \ mkdir -p $(dir $(PYTHONBUILD));\ tar -C $(dir $(PYTHONBUILD)) -xf $(PYTHONTARBALL) \ ) touch $@ $(PYTHONBUILD)/Makefile: $(PYTHONBUILD)/.patched $(BUILDROOT)/emsdk cd $(PYTHONBUILD) && \ CONFIG_SITE=Tools/wasm/config.site-wasm32-emscripten \ emconfigure ./configure -C \ --host=wasm32-unknown-emscripten \ --build=$(shell $(PYTHONBUILD)/config.guess) \ --with-emscripten-target=browser \ --enable-wasm-dynamic-linking \ --with-build-python=python3.11 $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a : $(PYTHONBUILD)/Makefile cd $(PYTHONBUILD) && \ emmake make -j3 libpython$(PYMAJORMINOR).a # Generate sysconfigdata _PYTHON_SYSCONFIGDATA_NAME=$(SYSCONFIGDATA_NAME) _PYTHON_PROJECT_BASE=$(PYTHONBUILD) python3.11 -m sysconfig --generate-posix-vars cp `cat pybuilddir.txt`/$(SYSCONFIGDATA_NAME).py $(PYTHONBUILD)/Lib mkdir -p $(PYTHONLIBDIR) # Copy libexpat.a, libmpdec.a, and libpython3.11.a # In noxfile, we explicitly link libexpat and libmpdec via RUSTFLAGS find $(PYTHONBUILD) -name '*.a' -exec cp {} $(PYTHONLIBDIR) \; # Install Python stdlib cp -r $(PYTHONBUILD)/Lib $(PYTHONLIBDIR)/python$(PYMAJORMINOR) clean: rm -rf $(BUILDROOT) pyo3-0.27.2/emscripten/emscripten_patches/0001-Add-_gxx_personality_v0-stub-to-library.js.patch000064400000000000000000000020261046102023000303770ustar 00000000000000From 4b56f37c3dc9185a235a8314086c4d7a6239b2f8 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 4 Jun 2022 19:19:47 -0700 Subject: [PATCH] Add _gxx_personality_v0 stub to library.js Mitigation for an incompatibility between Rust and Emscripten: https://github.com/rust-lang/rust/issues/85821 https://github.com/emscripten-core/emscripten/issues/17128 --- src/library.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library.js b/src/library.js index e7bb4c38e..7d01744df 100644 --- a/src/library.js +++ b/src/library.js @@ -403,6 +403,8 @@ mergeInto(LibraryManager.library, { abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); }, + __gxx_personality_v0: function() {}, + // ========================================================================== // time.h // ========================================================================== -- 2.25.1 pyo3-0.27.2/emscripten/env.sh000064400000000000000000000003571046102023000141100ustar 00000000000000#!/bin/bash # Activate emsdk environment. emsdk_env.sh writes a lot to stderr so we suppress # the output. This also prevents it from complaining when emscripten isn't yet # installed. source "$EMSDKDIR/emsdk_env.sh" 2> /dev/null || true pyo3-0.27.2/emscripten/runner.py000075500000000000000000000002361046102023000146460ustar 00000000000000#!/usr/local/bin/python import pathlib import sys import subprocess p = pathlib.Path(sys.argv[1]) sys.exit(subprocess.call(["node", p.name], cwd=p.parent)) pyo3-0.27.2/guide/book.toml000064400000000000000000000007051046102023000135340ustar 00000000000000[book] title = "PyO3 user guide" description = "PyO3 user guide" author = "PyO3 Project and Contributors" [preprocessor.pyo3_version] command = "python3 guide/pyo3_version.py" [preprocessor.tabs] [output.html] git-repository-url = "https://github.com/PyO3/pyo3/tree/main/guide" edit-url-template = "https://github.com/PyO3/pyo3/edit/main/guide/{path}" playground.runnable = false additional-css = ["theme/tabs.css"] additional-js = ["theme/tabs.js"] pyo3-0.27.2/guide/pyclass-parameters.md000064400000000000000000000123131046102023000160440ustar 00000000000000`#[pyclass]` can be used with the following parameters: | Parameter | Description | | :- | :- | | `constructor` | This is currently only allowed on [variants of complex enums][params-constructor]. It allows customization of the generated class constructor for each variant. It uses the same syntax and supports the same options as the `signature` attribute of functions and methods. | | `crate = "some::path"` | Path to import the `pyo3` crate, if it's not accessible at `::pyo3`. | | `dict` | Gives instances of this class an empty `__dict__` to store custom attributes. | | `eq` | Implements `__eq__` using the `PartialEq` implementation of the underlying Rust datatype. | | `eq_int` | Implements `__eq__` using `__int__` for simple enums. | | `extends = BaseType` | Use a custom baseclass. Defaults to [`PyAny`][params-1] | | `freelist = N` | Implements a [free list][params-2] of size N. This can improve performance for types that are often created and deleted in quick succession. Profile your code to see whether `freelist` is right for you. | | `from_py_object` | Implement `FromPyObject` for this pyclass. Requires the pyclass to be `Clone`. | | `frozen` | Declares that your pyclass is immutable. It removes the borrow checker overhead when retrieving a shared reference to the Rust struct, but disables the ability to get a mutable reference. | | `generic` | Implements runtime parametrization for the class following [PEP 560](https://peps.python.org/pep-0560/). | | `get_all` | Generates getters for all fields of the pyclass. | | `hash` | Implements `__hash__` using the `Hash` implementation of the underlying Rust datatype. *Requires `eq` and `frozen`* | | `immutable_type` | Makes the type object immutable. Supported on 3.14+ with the `abi3` feature active, or 3.10+ otherwise. | | `mapping` | Inform PyO3 that this class is a [`Mapping`][params-mapping], and so leave its implementation of sequence C-API slots empty. | | `module = "module_name"` | Python code will see the class as being defined in this module. Defaults to `builtins`. | | `name = "python_name"` | Sets the name that Python sees this class as. Defaults to the name of the Rust struct. | | `ord` | Implements `__lt__`, `__gt__`, `__le__`, & `__ge__` using the `PartialOrd` implementation of the underlying Rust datatype. *Requires `eq`* | | `rename_all = "renaming_rule"` | Applies renaming rules to every getters and setters of a struct, or every variants of an enum. Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". | | `sequence` | Inform PyO3 that this class is a [`Sequence`][params-sequence], and so leave its C-API mapping length slot empty. | | `set_all` | Generates setters for all fields of the pyclass. | | `skip_from_py_object` | Prevents this PyClass from participating in the `FromPyObject: PyClass + Clone` blanket implementation. This allows a custom `FromPyObject` impl, even if `self` is `Clone`. | | `str` | Implements `__str__` using the `Display` implementation of the underlying Rust datatype or by passing an optional format string `str=""`. *Note: The optional format string is only allowed for structs. `name` and `rename_all` are incompatible with the optional format string. Additional details can be found in the discussion on this [PR](https://github.com/PyO3/pyo3/pull/4233).* | | `subclass` | Allows other Python classes and `#[pyclass]` to inherit from this class. Enums cannot be subclassed. | | `unsendable` | Required if your struct is not [`Send`][params-3]. Rather than using `unsendable`, consider implementing your struct in a thread-safe way by e.g. substituting [`Rc`][params-4] with [`Arc`][params-5]. By using `unsendable`, your class will panic when accessed by another thread. Also note the Python's GC is multi-threaded and while unsendable classes will not be traversed on foreign threads to avoid UB, this can lead to memory leaks. | | `weakref` | Allows this class to be [weakly referenceable][params-6]. | All of these parameters can either be passed directly on the `#[pyclass(...)]` annotation, or as one or more accompanying `#[pyo3(...)]` annotations, e.g.: ```rust,ignore // Argument supplied directly to the `#[pyclass]` annotation. #[pyclass(name = "SomeName", subclass)] struct MyClass {} // Argument supplied as a separate annotation. #[pyclass] #[pyo3(name = "SomeName", subclass)] struct MyClass {} ``` [params-1]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html [params-2]: https://en.wikipedia.org/wiki/Free_list [params-3]: https://doc.rust-lang.org/std/marker/trait.Send.html [params-4]: https://doc.rust-lang.org/std/rc/struct.Rc.html [params-5]: https://doc.rust-lang.org/std/sync/struct.Arc.html [params-6]: https://docs.python.org/3/library/weakref.html [params-constructor]: https://pyo3.rs/latest/class.html#complex-enums [params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types [params-sequence]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types pyo3-0.27.2/guide/pyo3_version.py000064400000000000000000000032651046102023000147220ustar 00000000000000"""Simple mdbook preprocessor to inject pyo3 version into the guide. It will replace: - {{#PYO3_VERSION_TAG}} with the contents of the PYO3_VERSION_TAG environment var - {{#PYO3_DOCS_URL}} with the location of docs (e.g. 'https://docs.rs/pyo3/0.13.2') - {{#PYO3_CRATE_VERSION}} with a relevant toml snippet (e.g. 'version = "0.13.2"') Tested against mdbook 0.4.10. """ import json import os import sys # Set PYO3_VERSION in CI to build the correct version into links PYO3_VERSION_TAG = os.environ.get("PYO3_VERSION_TAG", "main") if PYO3_VERSION_TAG == "main": PYO3_DOCS_URL = "https://pyo3.rs/main/doc" PYO3_DOCS_VERSION = "latest" PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"' else: # v0.13.2 -> 0.13.2 version = PYO3_VERSION_TAG.lstrip("v") PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}" PYO3_DOCS_VERSION = version PYO3_CRATE_VERSION = f'version = "{version}"' def replace_section_content(section): if not isinstance(section, dict) or "Chapter" not in section: return # Replace raw and url-encoded forms section["Chapter"]["content"] = ( section["Chapter"]["content"] .replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG) .replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL) .replace("{{#PYO3_DOCS_VERSION}}", PYO3_DOCS_VERSION) .replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION) ) for sub_item in section["Chapter"]["sub_items"]: replace_section_content(sub_item) for line in sys.stdin: if line: [context, book] = json.loads(line) for section in book["sections"]: replace_section_content(section) json.dump(book, fp=sys.stdout) pyo3-0.27.2/guide/src/SUMMARY.md000064400000000000000000000035501046102023000141540ustar 00000000000000# Summary [Introduction](index.md) --- - [Getting started](getting-started.md) - [Using Rust from Python](rust-from-python.md) - [Python modules](module.md) - [Python functions](function.md) - [Function signatures](function/signature.md) - [Error handling](function/error-handling.md) - [Python classes](class.md) - [Class customizations](class/protocols.md) - [Basic object customization](class/object.md) - [Emulating numeric types](class/numeric.md) - [Emulating callable objects](class/call.md) - [Thread safety](class/thread-safety.md) - [Calling Python from Rust](python-from-rust.md) - [Python object types](types.md) - [Python exceptions](exception.md) - [Calling Python functions](python-from-rust/function-calls.md) - [Executing existing Python code](python-from-rust/calling-existing-code.md) - [Type conversions](conversions.md) - [Mapping of Rust types to Python types](conversions/tables.md) - [Conversion traits](conversions/traits.md) - [Using `async` and `await`](async-await.md) - [Parallelism](parallelism.md) - [Supporting Free-Threaded Python](free-threading.md) - [Debugging](debugging.md) - [Features reference](features.md) - [Performance](performance.md) - [Type stub generation and introspection](type-stub.md) - [Advanced topics](advanced.md) - [Building and distribution](building-and-distribution.md) - [Supporting multiple Python versions](building-and-distribution/multiple-python-versions.md) - [Useful crates](ecosystem.md) - [Logging](ecosystem/logging.md) - [Tracing](ecosystem/tracing.md) - [Using `async` and `await`](ecosystem/async-await.md) - [FAQ and troubleshooting](faq.md) --- [Appendix A: Migration guide](migration.md) [Appendix B: Trait bounds](trait-bounds.md) [Appendix C: Python typing hints](python-typing-hints.md) [CHANGELOG](changelog.md) --- [Contributing](contributing.md) pyo3-0.27.2/guide/src/advanced.md000064400000000000000000000006211046102023000145600ustar 00000000000000# Advanced topics ## FFI PyO3 exposes much of Python's C API through the `ffi` module. The C API is naturally unsafe and requires you to manage reference counts, errors and specific invariants yourself. Please refer to the [C API Reference Manual](https://docs.python.org/3/c-api/) and [The Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/ffi.html) before using any function from that API. pyo3-0.27.2/guide/src/async-await.md000064400000000000000000000110021046102023000152260ustar 00000000000000# Using `async` and `await` *This feature is still in active development. See [the related issue](https://github.com/PyO3/pyo3/issues/1632).* `#[pyfunction]` and `#[pymethods]` attributes also support `async fn`. ```rust,no_run # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use std::{thread, time::Duration}; use futures::channel::oneshot; use pyo3::prelude::*; #[pyfunction] #[pyo3(signature=(seconds, result=None))] async fn sleep(seconds: f64, result: Option>) -> Option> { let (tx, rx) = oneshot::channel(); thread::spawn(move || { thread::sleep(Duration::from_secs_f64(seconds)); tx.send(()).unwrap(); }); rx.await.unwrap(); result } # } ``` *Python awaitables instantiated with this method can only be awaited in *asyncio* context. Other Python async runtime may be supported in the future.* ## `Send + 'static` constraint Resulting future of an `async fn` decorated by `#[pyfunction]` must be `Send + 'static` to be embedded in a Python object. As a consequence, `async fn` parameters and return types must also be `Send + 'static`, so it is not possible to have a signature like `async fn does_not_compile<'py>(arg: Bound<'py, PyAny>) -> Bound<'py, PyAny>`. However, there is an exception for method receivers, so async methods can accept `&self`/`&mut self`. Note that this means that the class instance is borrowed for as long as the returned future is not completed, even across yield points and while waiting for I/O operations to complete. Hence, other methods cannot obtain exclusive borrows while the future is still being polled. This is the same as how async methods in Rust generally work but it is more problematic for Rust code interfacing with Python code due to pervasive shared mutability. This strongly suggests to prefer shared borrows `&self` over exclusive ones `&mut self` to avoid racy borrow check failures at runtime. ## Implicitly attached to the interpreter Even if it is not possible to pass a `py: Python<'py>` token to an `async fn`, we're still attached to the interpreter during the execution of the future – the same as for a regular `fn` without `Python<'py>`/`Bound<'py, PyAny>` parameter It is still possible to get a `Python` marker using [`Python::attach`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach); because `attach` is reentrant and optimized, the cost will be negligible. ## Detaching from the interpreter across `.await` There is currently no simple way to detach from the interpreter when awaiting a future, *but solutions are currently in development*. Here is the advised workaround for now: ```rust,ignore use std::{ future::Future, pin::{Pin, pin}, task::{Context, Poll}, }; use pyo3::prelude::*; struct AllowThreads(F); impl Future for AllowThreads where F: Future + Unpin + Send, F::Output: Send, { type Output = F::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let waker = cx.waker(); Python::attach(|py| { py.detach(|| pin!(&mut self.0).poll(&mut Context::from_waker(waker))) }) } } ``` ## Cancellation Cancellation on the Python side can be caught using [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) type, by annotating a function parameter with `#[pyo3(cancel_handle)]`. ```rust,no_run # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use futures::FutureExt; use pyo3::prelude::*; use pyo3::coroutine::CancelHandle; #[pyfunction] async fn cancellable(#[pyo3(cancel_handle)] mut cancel: CancelHandle) { futures::select! { /* _ = ... => println!("done"), */ _ = cancel.cancelled().fuse() => println!("cancelled"), } } # } ``` ## The `Coroutine` type To make a Rust future awaitable in Python, PyO3 defines a [`Coroutine`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.Coroutine.html) type, which implements the Python [coroutine protocol](https://docs.python.org/3/library/collections.abc.html#collections.abc.Coroutine). Each `coroutine.send` call is translated to a `Future::poll` call. If a [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) parameter is declared, the exception passed to `coroutine.throw` call is stored in it and can be retrieved with [`CancelHandle::cancelled`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html#method.cancelled); otherwise, it cancels the Rust future, and the exception is reraised; *The type does not yet have a public constructor until the design is finalized.* pyo3-0.27.2/guide/src/building-and-distribution/multiple-python-versions.md000064400000000000000000000121231046102023000251050ustar 00000000000000# Supporting multiple Python versions PyO3 supports all actively-supported Python 3 and PyPy versions. As much as possible, this is done internally to PyO3 so that your crate's code does not need to adapt to the differences between each version. However, as Python features grow and change between versions, PyO3 cannot offer a completely identical API for every Python version. This may require you to add conditional compilation to your crate or runtime checks for the Python version. This section of the guide first introduces the `pyo3-build-config` crate, which you can use as a `build-dependency` to add additional `#[cfg]` flags which allow you to support multiple Python versions at compile-time. Second, we'll show how to check the Python version at runtime. This can be useful when building for multiple versions with the `abi3` feature, where the Python API compiled against is not always the same as the one in use. ## Conditional compilation for different Python versions The `pyo3-build-config` exposes multiple [`#[cfg]` flags](https://doc.rust-lang.org/rust-by-example/attribute/cfg.html) which can be used to conditionally compile code for a given Python version. PyO3 itself depends on this crate, so by using it you can be sure that you are configured correctly for the Python version PyO3 is building against. This allows us to write code like the following ```rust,ignore #[cfg(Py_3_7)] fn function_only_supported_on_python_3_7_and_up() {} #[cfg(not(Py_3_8))] fn function_only_supported_before_python_3_8() {} #[cfg(not(Py_LIMITED_API))] fn function_incompatible_with_abi3_feature() {} ``` The following sections first show how to add these `#[cfg]` flags to your build process, and then cover some common patterns flags in a little more detail. To see a full reference of all the `#[cfg]` flags provided, see the [`pyo3-build-cfg` docs](https://docs.rs/pyo3-build-config). ### Using `pyo3-build-config` You can use the `#[cfg]` flags in just two steps: 1. Add `pyo3-build-config` with the [`resolve-config`](../features.md#resolve-config) feature enabled to your crate's build dependencies in `Cargo.toml`: ```toml [build-dependencies] pyo3-build-config = { {{#PYO3_CRATE_VERSION}}, features = ["resolve-config"] } ``` 2. Add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) file to your crate with the following contents: ```rust,ignore fn main() { // If you have an existing build.rs file, just add this line to it. pyo3_build_config::use_pyo3_cfgs(); } ``` After these steps you are ready to annotate your code! ### Common usages of `pyo3-build-cfg` flags The `#[cfg]` flags added by `pyo3-build-cfg` can be combined with all of Rust's logic in the `#[cfg]` attribute to create very precise conditional code generation. The following are some common patterns implemented using these flags: ```text #[cfg(Py_3_7)] ``` This `#[cfg]` marks code that will only be present on Python 3.7 and upwards. There are similar options `Py_3_8`, `Py_3_9`, `Py_3_10` and so on for each minor version. ```text #[cfg(not(Py_3_7))] ``` This `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.7. ```text #[cfg(not(Py_LIMITED_API))] ``` This `#[cfg]` marks code that is only available when building for the unlimited Python API (i.e. PyO3's `abi3` feature is not enabled). This might be useful if you want to ship your extension module as an `abi3` wheel and also allow users to compile it from source to make use of optimizations only possible with the unlimited API. ```text #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] ``` This `#[cfg]` marks code which is available when running Python 3.9 or newer, or when using the unlimited API with an older Python version. Patterns like this are commonly seen on Python APIs which were added to the limited Python API in a specific minor version. ```text #[cfg(PyPy)] ``` This `#[cfg]` marks code which is running on PyPy. ## Checking the Python version at runtime When building with PyO3's `abi3` feature, your extension module will be compiled against a specific [minimum version](../building-and-distribution.md#minimum-python-version-for-abi3) of Python, but may be running on newer Python versions. For example with PyO3's `abi3-py38` feature, your extension will be compiled as if it were for Python 3.8. If you were using `pyo3-build-config`, `#[cfg(Py_3_8)]` would be present. Your user could freely install and run your abi3 extension on Python 3.9. There's no way to detect your user doing that at compile time, so instead you need to fall back to runtime checks. PyO3 provides the APIs [`Python::version()`] and [`Python::version_info()`] to query the running Python version. This allows you to do the following, for example: ```rust use pyo3::Python; Python::attach(|py| { // PyO3 supports Python 3.7 and up. assert!(py.version_info() >= (3, 7)); assert!(py.version_info() >= (3, 7, 0)); }); ``` [`Python::version()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version [`Python::version_info()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version_info pyo3-0.27.2/guide/src/building-and-distribution.md000064400000000000000000000663011046102023000200740ustar 00000000000000# Building and distribution This chapter of the guide goes into detail on how to build and distribute projects using PyO3. The way to achieve this is very different depending on whether the project is a Python module implemented in Rust, or a Rust binary embedding Python. For both types of project there are also common problems such as the Python version to build for and the [linker](https://en.wikipedia.org/wiki/Linker_(computing)) arguments to use. The material in this chapter is intended for users who have already read the PyO3 [README](./index.md). It covers in turn the choices that can be made for Python modules and for Rust binaries. There is also a section at the end about cross-compiling projects using PyO3. There is an additional sub-chapter dedicated to [supporting multiple Python versions](./building-and-distribution/multiple-python-versions.md). ## Configuring the Python version PyO3 uses a build script (backed by the [`pyo3-build-config`] crate) to determine the Python version and set the correct linker arguments. By default it will attempt to use the following in order: - Any active Python virtualenv. - The `python` executable (if it's a Python 3 interpreter). - The `python3` executable. You can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.7`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`. Once the Python interpreter is located, `pyo3-build-config` executes it to query the information in the `sysconfig` module which is needed to configure the rest of the compilation. To validate the configuration which PyO3 will use, you can run a compilation with the environment variable `PYO3_PRINT_CONFIG=1` set. An example output of doing this is shown below: ```console $ PYO3_PRINT_CONFIG=1 cargo build Compiling pyo3 v0.14.1 (/home/david/dev/pyo3) error: failed to run custom build command for `pyo3 v0.14.1 (/home/david/dev/pyo3)` Caused by: process didn't exit successfully: `/home/david/dev/pyo3/target/debug/build/pyo3-7a8cf4fe22e959b7/build-script-build` (exit status: 101) --- stdout cargo:rerun-if-env-changed=PYO3_CROSS cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_VERSION cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile -- implementation=CPython version=3.8 shared=true abi3=false lib_name=python3.8 lib_dir=/usr/lib executable=/usr/bin/python pointer_width=64 build_flags= suppress_build_script_link_lines=false ``` The `PYO3_ENVIRONMENT_SIGNATURE` environment variable can be used to trigger rebuilds when its value changes, it has no other effect. ### Advanced: config files If you save the above output config from `PYO3_PRINT_CONFIG` to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var. If your build environment is unusual enough that PyO3's regular configuration detection doesn't work, using a config file like this will give you the flexibility to make PyO3 work for you. To see the full set of options supported, see the documentation for the [`InterpreterConfig` struct](https://docs.rs/pyo3-build-config/{{#PYO3_DOCS_VERSION}}/pyo3_build_config/struct.InterpreterConfig.html). ## Building Python extension modules Python extension modules need to be compiled differently depending on the OS (and architecture) that they are being compiled for. As well as multiple OSes (and architectures), there are also many different Python versions which are actively supported. Packages uploaded to [PyPI](https://pypi.org/) usually want to upload prebuilt "wheels" covering many OS/arch/version combinations so that users on all these different platforms don't have to compile the package themselves. Package vendors can opt-in to the "abi3" limited Python API which allows their wheels to be used on multiple Python versions, reducing the number of wheels they need to compile, but restricts the functionality they can use. There are many ways to go about this: it is possible to use `cargo` to build the extension module (along with some manual work, which varies with OS). The PyO3 ecosystem has two packaging tools, [`maturin`] and [`setuptools-rust`], which abstract over the OS difference and also support building wheels for PyPI upload. PyO3 has some Cargo features to configure projects for building Python extension modules: - The `extension-module` feature, which must be enabled when building Python extension modules. - The `abi3` feature and its version-specific `abi3-pyXY` companions, which are used to opt-in to the limited Python API in order to support multiple Python versions in a single wheel. This section describes each of these packaging tools before describing how to build manually without them. It then proceeds with an explanation of the `extension-module` feature. Finally, there is a section describing PyO3's `abi3` features. ### Packaging tools The PyO3 ecosystem has two main choices to abstract the process of developing Python extension modules: - [`maturin`] is a command-line tool to build, package and upload Python modules. It makes opinionated choices about project layout meaning it needs very little configuration. This makes it a great choice for users who are building a Python extension from scratch and don't need flexibility. - [`setuptools-rust`] is an add-on for `setuptools` which adds extra keyword arguments to the `setup.py` configuration file. It requires more configuration than `maturin`, however this gives additional flexibility for users adding Rust to an existing Python package that can't satisfy `maturin`'s constraints. Consult each project's documentation for full details on how to get started using them and how to upload wheels to PyPI. It should be noted that while `maturin` is able to build [manylinux](https://github.com/pypa/manylinux)-compliant wheels out-of-the-box, `setuptools-rust` requires a bit more effort, [relying on Docker](https://setuptools-rust.readthedocs.io/en/latest/building_wheels.html) for this purpose. There are also [`maturin-starter`] and [`setuptools-rust-starter`] examples in the PyO3 repository. ### Manual builds To build a PyO3-based Python extension manually, start by running `cargo build` as normal in a library project which uses PyO3's `extension-module` feature and has the [`cdylib` crate type](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field). Once built, symlink (or copy) and rename the shared library from Cargo's `target/` directory to your desired output directory: - on macOS, rename `libyour_module.dylib` to `your_module.so`. - on Windows, rename `libyour_module.dll` to `your_module.pyd`. - on Linux, rename `libyour_module.so` to `your_module.so`. You can then open a Python shell in the output directory and you'll be able to run `import your_module`. If you're packaging your library for redistribution, you should indicate the Python interpreter your library is compiled for by including the [platform tag](#platform-tags) in its name. This prevents incompatible interpreters from trying to import your library. If you're compiling for PyPy you *must* include the platform tag, or PyPy will ignore the module. #### Bazel builds To use PyO3 with bazel one needs to manually configure PyO3, PyO3-ffi and PyO3-macros. In particular, one needs to make sure that it is compiled with the right python flags for the version you intend to use. For example see: 1. [github.com/abrisco/rules_pyo3](https://github.com/abrisco/rules_pyo3) -- General rules for building extension modules. 2. [github.com/OliverFM/pytorch_with_gazelle](https://github.com/OliverFM/pytorch_with_gazelle) -- for a minimal example of a repo that can use PyO3, PyTorch and Gazelle to generate python Build files. 3. [github.com/TheButlah/rules_pyo3](https://github.com/TheButlah/rules_pyo3) -- is somewhat dated. #### Platform tags Rather than using just the `.so` or `.pyd` extension suggested above (depending on OS), you can prefix the shared library extension with a platform tag to indicate the interpreter it is compatible with. You can query your interpreter's platform tag from the `sysconfig` module. Some example outputs of this are seen below: ```bash # CPython 3.10 on macOS .cpython-310-darwin.so # PyPy 7.3 (Python 3.9) on Linux $ python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))' .pypy39-pp73-x86_64-linux-gnu.so ``` So, for example, a valid module library name on CPython 3.10 for macOS is `your_module.cpython-310-darwin.so`, and its equivalent when compiled for PyPy 7.3 on Linux would be `your_module.pypy38-pp73-x86_64-linux-gnu.so`. See [PEP 3149](https://peps.python.org/pep-3149/) for more background on platform tags. #### macOS On macOS, because the `extension-module` feature disables linking to `libpython` ([see the next section](#the-extension-module-feature)), some additional linker arguments need to be set. `maturin` and `setuptools-rust` both pass these arguments for PyO3 automatically, but projects using manual builds will need to set these directly in order to support macOS. The easiest way to set the correct linker arguments is to add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) with the following content: ```rust,ignore fn main() { pyo3_build_config::add_extension_module_link_args(); } ``` Remember to also add `pyo3-build-config` to the `build-dependencies` section in `Cargo.toml`. An alternative to using `pyo3-build-config` is add the following to a cargo configuration file (e.g. `.cargo/config.toml`): ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` Using the MacOS system python3 (`/usr/bin/python3`, as opposed to python installed via homebrew, pyenv, nix, etc.) may result in runtime errors such as `Library not loaded: @rpath/Python3.framework/Versions/3.8/Python3`. The easiest way to set the correct linker arguments is to add a `build.rs` with the following content: ```rust,ignore fn main() { pyo3_build_config::add_python_framework_link_args(); } ``` Alternatively it can be resolved with another addition to `.cargo/config.toml`: ```toml [build] rustflags = [ "-C", "link-args=-Wl,-rpath,/Library/Developer/CommandLineTools/Library/Frameworks", ] ``` For more discussion on and workarounds for MacOS linking problems [see this issue](https://github.com/PyO3/pyo3/issues/1800#issuecomment-906786649). Finally, don't forget that on MacOS the `extension-module` feature will cause `cargo test` to fail without the `--no-default-features` flag (see [the FAQ](https://pyo3.rs/main/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror)). ### The `extension-module` feature PyO3's `extension-module` feature is used to disable [linking](https://en.wikipedia.org/wiki/Linker_(computing)) to `libpython` on Unix targets. This is necessary because by default PyO3 links to `libpython`. This makes binaries, tests, and examples "just work". However, Python extensions on Unix must not link to libpython for [manylinux](https://www.python.org/dev/peps/pep-0513/) compliance. The downside of not linking to `libpython` is that binaries, tests, and examples (which usually embed Python) will fail to build. If you have an extension module as well as other outputs in a single project, you need to use optional Cargo features to disable the `extension-module` when you're not building the extension module. See [the FAQ](faq.md#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror) for an example workaround. ### `Py_LIMITED_API`/`abi3` By default, Python extension modules can only be used with the same Python version they were compiled against. For example, an extension module built for Python 3.5 can't be imported in Python 3.8. [PEP 384](https://www.python.org/dev/peps/pep-0384/) introduced the idea of the limited Python API, which would have a stable ABI enabling extension modules built with it to be used against multiple Python versions. This is also known as `abi3`. The advantage of building extension modules using the limited Python API is that package vendors only need to build and distribute a single copy (for each OS / architecture), and users can install it on all Python versions from the [minimum version](#minimum-python-version-for-abi3) and up. The downside of this is that PyO3 can't use optimizations which rely on being compiled against a known exact Python version. It's up to you to decide whether this matters for your extension module. It's also possible to design your extension module such that you can distribute `abi3` wheels but allow users compiling from source to benefit from additional optimizations - see the [support for multiple python versions](./building-and-distribution/multiple-python-versions.md) section of this guide, in particular the `#[cfg(Py_LIMITED_API)]` flag. There are three steps involved in making use of `abi3` when building Python packages as wheels: 1. Enable the `abi3` feature in `pyo3`. This ensures `pyo3` only calls Python C-API functions which are part of the stable API, and on Windows also ensures that the project links against the correct shared object (no special behavior is required on other platforms): ```toml [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["abi3"] } ``` 2. Ensure that the built shared objects are correctly marked as `abi3`. This is accomplished by telling your build system that you're using the limited API. [`maturin`] >= 0.9.0 and [`setuptools-rust`] >= 0.11.4 support `abi3` wheels. See the [corresponding](https://github.com/PyO3/maturin/pull/353) [PRs](https://github.com/PyO3/setuptools-rust/pull/82) for more. 3. Ensure that the `.whl` is correctly marked as `abi3`. For projects using `setuptools`, this is accomplished by passing `--py-limited-api=cp3x` (where `x` is the minimum Python version supported by the wheel, e.g. `--py-limited-api=cp35` for Python 3.5) to `setup.py bdist_wheel`. #### Minimum Python version for `abi3` Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py37`, `abi3-py38`, `abi3-py39` etc. to set the minimum required Python version for your `abi3` wheel. For example, if you set the `abi3-py37` feature, your extension wheel can be used on all Python 3 versions from Python 3.7 and up. `maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp37-abi3-manylinux2020_x86_64.whl`. As your extension module may be run with multiple different Python versions you may occasionally find you need to check the Python version at runtime to customize behavior. See [the relevant section of this guide](./building-and-distribution/multiple-python-versions.md#checking-the-python-version-at-runtime) on supporting multiple Python versions at runtime. PyO3 is only able to link your extension module to abi3 version up to and including your host Python version. E.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.7, the build will fail. > Note: If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py37` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.7 and up. #### Building `abi3` extensions without a Python interpreter As an advanced feature, you can build PyO3 wheel without calling Python interpreter with the environment variable `PYO3_NO_PYTHON` set. Also, if the build host Python interpreter is not found or is too old or otherwise unusable, PyO3 will still attempt to compile `abi3` extension modules after displaying a warning message. On Unix-like systems this works unconditionally; on Windows you must also set the `RUSTFLAGS` environment variable to contain `-L native=/path/to/python/libs` so that the linker can find `python3.lib`. If the `python3.dll` import library is not available, an experimental `generate-import-lib` crate feature may be enabled, and the required library will be created and used by PyO3 automatically. *Note*: MSVC targets require LLVM binutils (`llvm-dlltool`) to be available in `PATH` for the automatic import library generation feature to work. #### Missing features Due to limitations in the Python API, there are a few `pyo3` features that do not work when compiling for `abi3`. These are: - `#[pyo3(text_signature = "...")]` does not work on classes until Python 3.10 or greater. - The `dict` and `weakref` options on classes are not supported until Python 3.9 or greater. - The buffer API is not supported until Python 3.11 or greater. - Optimizations which rely on knowledge of the exact Python version compiled against. ## Embedding Python in Rust If you want to embed the Python interpreter inside a Rust program, there are two modes in which this can be done: dynamically and statically. We'll cover each of these modes in the following sections. Each of them affect how you must distribute your program. Instead of learning how to do this yourself, you might want to consider using a project like [PyOxidizer] to ship your application and all of its dependencies in a single file. PyO3 automatically switches between the two linking modes depending on whether the Python distribution you have configured PyO3 to use ([see above](#configuring-the-python-version)) contains a shared library or a static library. The static library is most often seen in Python distributions compiled from source without the `--enable-shared` configuration option. ### Dynamically embedding the Python interpreter Embedding the Python interpreter dynamically is much easier than doing so statically. This is done by linking your program against a Python shared library (such as `libpython.3.9.so` on UNIX, or `python39.dll` on Windows). The implementation of the Python interpreter resides inside the shared library. This means that when the OS runs your Rust program it also needs to be able to find the Python shared library. This mode of embedding works well for Rust tests which need access to the Python interpreter. It is also great for Rust software which is installed inside a Python virtualenv, because the virtualenv sets up appropriate environment variables to locate the correct Python shared library. For distributing your program to non-technical users, you will have to consider including the Python shared library in your distribution as well as setting up wrapper scripts to set the right environment variables (such as `LD_LIBRARY_PATH` on UNIX, or `PATH` on Windows). Note that PyPy cannot be embedded in Rust (or any other software). Support for this is tracked on the [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836). ### Statically embedding the Python interpreter Embedding the Python interpreter statically means including the contents of a Python static library directly inside your Rust binary. This means that to distribute your program you only need to ship your binary file: it contains the Python interpreter inside the binary! On Windows static linking is almost never done, so Python distributions don't usually include a static library. The information below applies only to UNIX. The Python static library is usually called `libpython.a`. Static linking has a lot of complications, listed below. For these reasons PyO3 does not yet have first-class support for this embedding mode. See [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416) for more information and to discuss any issues you encounter. The [`auto-initialize`](features.md#auto-initialize) feature is deliberately disabled when embedding the interpreter statically because this is often unintentionally done by new users to PyO3 running test programs. Trying out PyO3 is much easier using dynamic embedding. The known complications are: - To import compiled extension modules (such as other Rust extension modules, or those written in C), your binary must have the correct linker flags set during compilation to export the original contents of `libpython.a` so that extensions can use them (e.g. `-Wl,--export-dynamic`). - The C compiler and flags which were used to create `libpython.a` must be compatible with your Rust compiler and flags, else you will experience compilation failures. Significantly different compiler versions may see errors like this: ```text lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2 ``` Mismatching flags may lead to errors like this: ```text /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE ``` If you encounter these or other complications when linking the interpreter statically, discuss them on [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416). It is hoped that eventually that discussion will contain enough information and solutions that PyO3 can offer first-class support for static embedding. ### Import your module when embedding the Python interpreter When you run your Rust binary with an embedded interpreter, any `#[pymodule]` created modules won't be accessible to import unless added to a table called `PyImport_Inittab` before the embedded interpreter is initialized. This will cause Python statements in your embedded interpreter such as `import your_new_module` to fail. You can call the macro [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) with your module before initializing the Python interpreter to add the module function into that table. (The Python interpreter will be initialized by calling `Python::initialize`, `with_embedded_python_interpreter`, or `Python::attach` with the [`auto-initialize`](features.md#auto-initialize) feature enabled.) ## Cross Compiling Thanks to Rust's great cross-compilation support, cross-compiling using PyO3 is relatively straightforward. To get started, you'll need a few pieces of software: - A toolchain for your target. - The appropriate options in your Cargo `.config` for the platform you're targeting and the toolchain you are using. - A Python interpreter that's already been compiled for your target (optional when building "abi3" extension modules). - A Python interpreter that is built for your host and available through the `PATH` or setting the [`PYO3_PYTHON`](#configuring-the-python-version) variable (optional when building "abi3" extension modules). After you've obtained the above, you can build a cross-compiled PyO3 module by using Cargo's `--target` flag. PyO3's build script will detect that you are attempting a cross-compile based on your host machine and the desired target. When cross-compiling, PyO3's build script cannot execute the target Python interpreter to query the configuration, so there are a few additional environment variables you may need to set: - `PYO3_CROSS`: If present this variable forces PyO3 to configure as a cross-compilation. - `PYO3_CROSS_LIB_DIR`: This variable can be set to the directory containing the target's libpython DSO and the associated `_sysconfigdata*.py` file for Unix-like targets, or the Python DLL import libraries for the Windows target. This variable is only needed when the output binary must link to libpython explicitly (e.g. when targeting Windows and Android or embedding a Python interpreter), or when it is absolutely required to get the interpreter configuration from `_sysconfigdata*.py`. - `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python installation. This variable is only needed if PyO3 cannot determine the version to target from `abi3-py3*` features, or if `PYO3_CROSS_LIB_DIR` is not set, or if there are multiple versions of Python present in `PYO3_CROSS_LIB_DIR`. - `PYO3_CROSS_PYTHON_IMPLEMENTATION`: Python implementation name ("CPython" or "PyPy") of the target Python installation. CPython is assumed by default when this variable is not set, unless `PYO3_CROSS_LIB_DIR` is set for a Unix-like target and PyO3 can get the interpreter configuration from `_sysconfigdata*.py`. An experimental `pyo3` crate feature `generate-import-lib` enables the user to cross-compile extension modules for Windows targets without setting the `PYO3_CROSS_LIB_DIR` environment variable or providing any Windows Python library files. It uses an external [`python3-dll-a`] crate to generate import libraries for the Python DLL for MinGW-w64 and MSVC compile targets. `python3-dll-a` uses the binutils `dlltool` program to generate DLL import libraries for MinGW-w64 targets. It is possible to override the default `dlltool` command name for the cross target by setting `PYO3_MINGW_DLLTOOL` environment variable. *Note*: MSVC targets require LLVM binutils or MSVC build tools to be available on the host system. More specifically, `python3-dll-a` requires `llvm-dlltool` or `lib.exe` executable to be present in `PATH` when targeting `*-pc-windows-msvc`. The Zig compiler executable can be used in place of `llvm-dlltool` when the `ZIG_COMMAND` environment variable is set to the installed Zig program name (`"zig"` or `"python -m ziglang"`). An example might look like the following (assuming your target's sysroot is at `/home/pyo3/cross/sysroot` and that your target is `armv7`): ```sh export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` If there are multiple python versions at the cross lib directory and you cannot set a more precise location to include both the `libpython` DSO and `_sysconfigdata*.py` files, you can set the required version: ```sh export PYO3_CROSS_PYTHON_VERSION=3.8 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` Or another example with the same sys root but building for Windows: ```sh export PYO3_CROSS_PYTHON_VERSION=3.9 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target x86_64-pc-windows-gnu ``` Any of the `abi3-py3*` features can be enabled instead of setting `PYO3_CROSS_PYTHON_VERSION` in the above examples. `PYO3_CROSS_LIB_DIR` can often be omitted when cross compiling extension modules for Unix and macOS targets, or when cross compiling extension modules for Windows and the experimental `generate-import-lib` crate feature is enabled. The following resources may also be useful for cross-compiling: - [github.com/japaric/rust-cross](https://github.com/japaric/rust-cross) is a primer on cross compiling Rust. - [github.com/rust-embedded/cross](https://github.com/rust-embedded/cross) uses Docker to make Rust cross-compilation easier. [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`maturin-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/maturin-starter [`setuptools-rust-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/setuptools-rust-starter [`maturin`]: https://github.com/PyO3/maturin [`setuptools-rust`]: https://github.com/PyO3/setuptools-rust [PyOxidizer]: https://github.com/indygreg/PyOxidizer [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ pyo3-0.27.2/guide/src/changelog.md000064400000000000000000000000401046102023000147350ustar 00000000000000{{#include ../../CHANGELOG.md}} pyo3-0.27.2/guide/src/class/call.md000064400000000000000000000111141046102023000150320ustar 00000000000000# Emulating callable objects Classes can be callable if they have a `#[pymethod]` named `__call__`. This allows instances of a class to behave similar to functions. This method's signature must look like `__call__(, ...) -> object` - here, any argument list can be defined as for normal pymethods ## Example: Implementing a call counter The following pyclass is a basic decorator - its constructor takes a Python object as argument and calls that object when called. An equivalent Python implementation is linked at the end. An example crate containing this pyclass can be found [here](https://github.com/PyO3/pyo3/tree/main/examples/decorator) ```rust,ignore {{#include ../../../examples/decorator/src/lib.rs}} ``` Python code: ```python {{#include ../../../examples/decorator/tests/example.py}} ``` Output: ```text say_hello has been called 1 time(s). hello say_hello has been called 2 time(s). hello say_hello has been called 3 time(s). hello say_hello has been called 4 time(s). hello ``` ### Pure Python implementation A Python implementation of this looks similar to the Rust version: ```python class Counter: def __init__(self, wraps): self.count = 0 self.wraps = wraps def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.wraps.__name__} has been called {self.count} time(s)") self.wraps(*args, **kwargs) ``` Note that it can also be implemented as a higher order function: ```python def Counter(wraps): count = 0 def call(*args, **kwargs): nonlocal count count += 1 print(f"{wraps.__name__} has been called {count} time(s)") return wraps(*args, **kwargs) return call ``` ### What is the `AtomicU64` for? A [previous implementation] used a normal `u64`, which meant it required a `&mut self` receiver to update the count: ```rust,ignore #[pyo3(signature = (*args, **kwargs))] fn __call__( &mut self, py: Python<'_>, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> { self.count += 1; let name = self.wraps.getattr(py, "__name__")?; println!("{} has been called {} time(s).", name, self.count); // After doing something, we finally forward the call to the wrapped function let ret = self.wraps.call(py, args, kwargs)?; // We could do something with the return value of // the function before returning it Ok(ret) } ``` The problem with this is that the `&mut self` receiver means PyO3 has to borrow it exclusively, and hold this borrow across the`self.wraps.call(py, args, kwargs)` call. This call returns control to the user's Python code which is free to call arbitrary things, *including* the decorated function. If that happens PyO3 is unable to create a second unique borrow and will be forced to raise an exception. As a result, something innocent like this will raise an exception: ```py @Counter def say_hello(): if say_hello.count < 2: print(f"hello from decorator") say_hello() # RuntimeError: Already borrowed ``` The implementation in this chapter fixes that by never borrowing exclusively; all the methods take `&self` as receivers, of which multiple may exist simultaneously. This requires a shared counter and the most straightforward way to implement thread-safe interior mutability (e.g. the type does not need to accept `&mut self` to modify the "interior" state) for a `u64` is to use [`AtomicU64`], so that's what is used here. This shows the dangers of running arbitrary Python code - note that "running arbitrary Python code" can be far more subtle than the example above: - Python's asynchronous executor may park the current thread in the middle of Python code, even in Python code that *you* control, and let other Python code run. - Dropping arbitrary Python objects may invoke destructors defined in Python (`__del__` methods). - Calling Python's C-api (most PyO3 apis call C-api functions internally) may raise exceptions, which may allow Python code in signal handlers to run. - On the free-threaded build, users might use Python's `threading` module to work with your types simultaneously from multiple OS threads. This is especially important if you are writing unsafe code; Python code must never be able to cause undefined behavior. You must ensure that your Rust code is in a consistent state before doing any of the above things. [previous implementation]: "Thread Safe Decorator · Discussion #2598 · PyO3/pyo3" [`AtomicU64`]: "AtomicU64 in std::sync::atomic - Rust" pyo3-0.27.2/guide/src/class/numeric.md000064400000000000000000000304551046102023000155720ustar 00000000000000# Emulating numeric types At this point we have a `Number` class that we can't actually do any math on! Before proceeding, we should think about how we want to handle overflows. There are three obvious solutions: - We can have infinite precision just like Python's `int`. However that would be quite boring - we'd be reinventing the wheel. - We can raise exceptions whenever `Number` overflows, but that makes the API painful to use. - We can wrap around the boundary of `i32`. This is the approach we'll take here. To do that we'll just forward to `i32`'s `wrapping_*` methods. ## Fixing our constructor Let's address the first overflow, in `Number`'s constructor: ```python from my_module import Number n = Number(1 << 1337) ``` ```text Traceback (most recent call last): File "example.py", line 3, in n = Number(1 << 1337) OverflowError: Python int too large to convert to C long ``` Instead of relying on the default [`FromPyObject`] extraction to parse arguments, we can specify our own extraction function, using the `#[pyo3(from_py_with = ...)]` attribute. Unfortunately PyO3 doesn't provide a way to wrap Python integers out of the box, but we can do a Python call to mask it and cast it to an `i32`. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; // 👇 This intentionally overflows! Ok(val as i32) } ``` We also add documentation, via `///` comments, which are visible to Python users. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self { Self(value) } } ``` With that out of the way, let's implement some operators: ```rust,no_run use pyo3::exceptions::{PyZeroDivisionError, PyValueError}; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } } ``` ### Unary arithmetic operations ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __pos__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __neg__(&self) -> Self { Self(-self.0) } fn __abs__(&self) -> Self { Self(self.0.abs()) } fn __invert__(&self) -> Self { Self(!self.0) } } ``` ### Support for the `complex()`, `int()` and `float()` built-in functions ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # use pyo3::types::PyComplex; #[pymethods] impl Number { fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles(py, self.0 as f64, 0.0) } } ``` We do not implement the in-place operations like `__iadd__` because we do not wish to mutate `Number`. Similarly we're not interested in supporting operations with different types, so we do not implement the reflected operations like `__radd__` either. Now Python can use our `Number` class: ```python from my_module import Number def hash_djb2(s: str): ''' A version of Daniel J. Bernstein's djb2 string hashing algorithm Like many hashing algorithms, it relies on integer wrapping. ''' n = Number(0) five = Number(5) for x in s: n = Number(ord(x)) + ((n << five) - n) return n assert hash_djb2('l50_50') == Number(-1152549421) ``` ### Final code ```rust use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::exceptions::{PyValueError, PyZeroDivisionError}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::{PyComplex, PyString}; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // Get the class name dynamically in case `Number` is subclassed let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __xor__(&self, other: &Self) -> Self { Self(self.0 ^ other.0) } fn __or__(&self, other: &Self) -> Self { Self(self.0 | other.0) } fn __and__(&self, other: &Self) -> Self { Self(self.0 & other.0) } fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles(py, self.0 as f64, 0.0) } } #[pymodule] mod my_module { #[pymodule_export] use super::Number; } # const SCRIPT: &'static std::ffi::CStr = pyo3::ffi::c_str!(r#" # def hash_djb2(s: str): # n = Number(0) # five = Number(5) # # for x in s: # n = Number(ord(x)) + ((n << five) - n) # return n # # assert hash_djb2('l50_50') == Number(-1152549421) # assert hash_djb2('logo') == Number(3327403) # assert hash_djb2('horizon') == Number(1097468315) # # # assert Number(2) + Number(2) == Number(4) # assert Number(2) + Number(2) != Number(5) # # assert Number(13) - Number(7) == Number(6) # assert Number(13) - Number(-7) == Number(20) # # assert Number(13) / Number(7) == Number(1) # assert Number(13) // Number(7) == Number(1) # # assert Number(13) * Number(7) == Number(13*7) # # assert Number(13) > Number(7) # assert Number(13) < Number(20) # assert Number(13) == Number(13) # assert Number(13) >= Number(7) # assert Number(13) <= Number(20) # assert Number(13) == Number(13) # # # assert (True if Number(1) else False) # assert (False if Number(0) else True) # # # assert int(Number(13)) == 13 # assert float(Number(13)) == 13 # assert Number.__doc__ == "Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\nIt's not a story C would tell you. It's a Rust legend." # assert Number(12345234523452) == Number(1498514748) # try: # import inspect # assert inspect.signature(Number).__str__() == '(value)' # except ValueError: # # Not supported with `abi3` before Python 3.10 # pass # assert Number(1337).__str__() == '1337' # assert Number(1337).__repr__() == 'Number(1337)' "#); # # use pyo3::PyTypeInfo; # # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let globals = PyModule::import(py, "__main__")?.dict(); # globals.set_item("Number", Number::type_object(py))?; # # py.run(SCRIPT, Some(&globals), None)?; # Ok(()) # }) # } ``` ## Appendix: Writing some unsafe code At the beginning of this chapter we said that PyO3 doesn't provide a way to wrap Python integers out of the box but that's a half truth. There's not a PyO3 API for it, but there's a Python C API function that does: ```c unsigned long PyLong_AsUnsignedLongMask(PyObject *obj) ``` We can call this function from Rust by using [`pyo3::ffi::PyLong_AsUnsignedLongMask`]. This is an *unsafe* function, which means we have to use an unsafe block to call it and take responsibility for upholding the contracts of this function. Let's review those contracts: - We must be attached to the interpreter. If we're not, calling this function causes a data race. - The pointer must be valid, i.e. it must be properly aligned and point to a valid Python object. Let's create that helper function. The signature has to be `fn(&Bound<'_, PyAny>) -> PyResult`. - `&Bound<'_, PyAny>` represents a checked bound reference, so the pointer derived from it is valid (and not null). - Whenever we have bound references to Python objects in scope, it is guaranteed that we're attached to the interpreter. This reference is also where we can get a [`Python`] token to use in our call to [`PyErr::take`]. ```rust,no_run # #![allow(dead_code)] use std::ffi::c_ulong; use pyo3::prelude::*; use pyo3::ffi; fn wrap(obj: &Bound<'_, PyAny>) -> Result { let py: Python<'_> = obj.py(); unsafe { let ptr = obj.as_ptr(); let ret: c_ulong = ffi::PyLong_AsUnsignedLongMask(ptr); if ret == c_ulong::MAX { if let Some(err) = PyErr::take(py) { return Err(err); } } Ok(ret as i32) } } ``` [`PyErr::take`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.PyErr.html#method.take [`Python`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`pyo3::ffi::PyLong_AsUnsignedLongMask`]: {{#PYO3_DOCS_URL}}/pyo3/ffi/fn.PyLong_AsUnsignedLongMask.html pyo3-0.27.2/guide/src/class/object.md000064400000000000000000000243751046102023000154020ustar 00000000000000# Basic object customization Recall the `Number` class from the previous chapter: ```rust,no_run # #![allow(dead_code)] # fn main() {} use pyo3::prelude::*; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } } #[pymodule] mod my_module { #[pymodule_export] use super::Number; } ``` At this point Python code can import the module, access the class and create class instances - but nothing else. ```python from my_module import Number n = Number(5) print(n) ``` ```text ``` ## String representations It can't even print an user-readable representation of itself! We can fix that by defining the `__repr__` and `__str__` methods inside a `#[pymethods]` block. We do this by accessing the value contained inside `Number`. ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { // For `__repr__` we want to return a string that Python code could use to recreate // the `Number`, like `Number(5)` for example. fn __repr__(&self) -> String { // We use the `format!` macro to create a string. Its first argument is a // format string, followed by any number of parameters which replace the // `{}`'s in the format string. // // 👇 Tuple field access in Rust uses a dot format!("Number({})", self.0) } // `__str__` is generally used to create an "informal" representation, so we // just forward to `i32`'s `ToString` trait implementation to print a bare number. fn __str__(&self) -> String { self.0.to_string() } } ``` To automatically generate the `__str__` implementation using a `Display` trait implementation, pass the `str` argument to `pyclass`. ```rust,no_run # use std::fmt::{Display, Formatter}; # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(str)] struct Coordinate { x: i32, y: i32, z: i32, } impl Display for Coordinate { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {}, {})", self.x, self.y, self.z) } } ``` For convenience, a shorthand format string can be passed to `str` as `str=""` for **structs only**. It expands and is passed into the `format!` macro in the following ways: - `"{x}"` -> `"{}", self.x` - `"{0}"` -> `"{}", self.0` - `"{x:?}"` -> `"{:?}", self.x` *Note: Depending upon the format string you use, this may require implementation of the `Display` or `Debug` traits for the given Rust types.* *Note: the pyclass args `name` and `rename_all` are incompatible with the shorthand format string and will raise a compile time error.* ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(str="({x}, {y}, {z})")] struct Coordinate { x: i32, y: i32, z: i32, } ``` ### Accessing the class name In the `__repr__`, we used a hard-coded class name. This is sometimes not ideal, because if the class is subclassed in Python, we would like the repr to reflect the subclass name. This is typically done in Python code by accessing `self.__class__.__name__`. In order to be able to access the Python type information *and* the Rust struct, we need to use a `Bound` as the `self` argument. ```rust,no_run # use pyo3::prelude::*; # use pyo3::types::PyString; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // This is the equivalent of `self.__class__.__name__` in Python. let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; // To access fields of the Rust struct, we need to borrow from the Bound object. Ok(format!("{}({})", class_name, slf.borrow().0)) } } ``` ### Hashing Let's also implement hashing. We'll just hash the `i32`. For that we need a [`Hasher`]. The one provided by `std` is [`DefaultHasher`], which uses the [SipHash] algorithm. ```rust,no_run use std::collections::hash_map::DefaultHasher; // Required to call the `.hash` and `.finish` methods, which are defined on traits. use std::hash::{Hash, Hasher}; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } } ``` To implement `__hash__` using the Rust [`Hash`] trait implementation, the `hash` option can be used. This option is only available for `frozen` classes to prevent accidental hash changes from mutating the object. If you need an `__hash__` implementation for a mutable class, use the manual method from above. This option also requires `eq`: According to the [Python docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__) "If a class does not define an `__eq__()` method it should not define a `__hash__()` operation either" ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(frozen, eq, hash)] #[derive(PartialEq, Hash)] struct Number(i32); ``` > **Note**: When implementing `__hash__` and comparisons, it is important that the following property holds: > > ```text > k1 == k2 -> hash(k1) == hash(k2) > ``` > > In other words, if two keys are equal, their hashes must also be equal. In addition you must take > care that your classes' hash doesn't change during its lifetime. In this tutorial we do that by not > letting Python code change our `Number` class. In other words, it is immutable. > > By default, all `#[pyclass]` types have a default hash implementation from Python. > Types which should not be hashable can override this by setting `__hash__` to None. > This is the same mechanism as for a pure-Python class. This is done like so: > > ```rust,no_run > # use pyo3::prelude::*; > #[pyclass] > struct NotHashable {} > > #[pymethods] > impl NotHashable { > #[classattr] > const __hash__: Option> = None; > } > ``` ### Comparisons PyO3 supports the usual magic comparison methods available in Python such as `__eq__`, `__lt__` and so on. It is also possible to support all six operations at once with `__richcmp__`. This method will be called with a value of `CompareOp` depending on the operation. ```rust,no_run use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } } ``` If you obtain the result by comparing two Rust values, as in this example, you can take a shortcut using `CompareOp::matches`: ```rust,no_run use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { op.matches(self.0.cmp(&other.0)) } } ``` It checks that the `std::cmp::Ordering` obtained from Rust's `Ord` matches the given `CompareOp`. Alternatively, you can implement just equality using `__eq__`: ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __eq__(&self, other: &Self) -> bool { self.0 == other.0 } } # fn main() -> PyResult<()> { # Python::attach(|py| { # let x = &Bound::new(py, Number(4))?; # let y = &Bound::new(py, Number(4))?; # assert!(x.eq(y)?); # assert!(!x.ne(y)?); # Ok(()) # }) # } ``` To implement `__eq__` using the Rust [`PartialEq`] trait implementation, the `eq` option can be used. ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(eq)] #[derive(PartialEq)] struct Number(i32); ``` To implement `__lt__`, `__le__`, `__gt__`, & `__ge__` using the Rust `PartialOrd` trait implementation, the `ord` option can be used. *Note: Requires `eq`.* ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] struct Number(i32); ``` ### Truthyness We'll consider `Number` to be `True` if it is nonzero: ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __bool__(&self) -> bool { self.0 != 0 } } ``` ### Final code ```rust,no_run # fn main() {} use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::PyString; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } } #[pymodule] mod my_module { #[pymodule_export] use super::Number; } ``` [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html [`Hasher`]: https://doc.rust-lang.org/std/hash/trait.Hasher.html [`DefaultHasher`]: https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html [SipHash]: https://en.wikipedia.org/wiki/SipHash [`PartialEq`]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html pyo3-0.27.2/guide/src/class/protocols.md000064400000000000000000000472061046102023000161560ustar 00000000000000# Class customizations Python's object model defines several protocols for different object behavior, such as the sequence, mapping, and number protocols. Python classes support these protocols by implementing "magic" methods, such as `__str__` or `__repr__`. Because of the double-underscores surrounding their name, these are also known as "dunder" methods. PyO3 makes it possible for every magic method to be implemented in `#[pymethods]` just as they would be done in a regular Python class, with a few notable differences: - `__new__` and `__init__` are replaced by the [`#[new]` attribute](../class.md#constructor). - `__del__` is not yet supported, but may be in the future. - `__buffer__` and `__release_buffer__` are currently not supported and instead PyO3 supports [`__getbuffer__` and `__releasebuffer__`](#buffer-objects) methods (these predate [PEP 688](https://peps.python.org/pep-0688/#python-level-buffer-protocol)), again this may change in the future. - PyO3 adds [`__traverse__` and `__clear__`](#garbage-collector-integration) methods for controlling garbage collection. - The Python C-API which PyO3 is implemented upon requires many magic methods to have a specific function signature in C and be placed into special "slots" on the class type object. This limits the allowed argument and return types for these methods. They are listed in detail in the section below. If a magic method is not on the list above (for example `__init_subclass__`), then it should just work in PyO3. If this is not the case, please file a bug report. ## Magic Methods handled by PyO3 If a function name in `#[pymethods]` is a magic method which is known to need special handling, it will be automatically placed into the correct slot in the Python type object. The function name is taken from the usual rules for naming `#[pymethods]`: the `#[pyo3(name = "...")]` attribute is used if present, otherwise the Rust function name is used. The magic methods handled by PyO3 are very similar to the standard Python ones on [this page](https://docs.python.org/3/reference/datamodel.html#special-method-names) - in particular they are the subset which have slots as [defined here](https://docs.python.org/3/c-api/typeobj.html). When PyO3 handles a magic method, a couple of changes apply compared to other `#[pymethods]`: - The Rust function signature is restricted to match the magic method. - The `#[pyo3(signature = (...)]` and `#[pyo3(text_signature = "...")]` attributes are not allowed. The following sections list all magic methods for which PyO3 implements the necessary special handling. The given signatures should be interpreted as follows: - All methods take a receiver as first argument, shown as ``. It can be `&self`, `&mut self` or a `Bound` reference like `self_: PyRef<'_, Self>` and `self_: PyRefMut<'_, Self>`, as described [here](../class.md#inheritance). - An optional `Python<'py>` argument is always allowed as the first argument. - Return values can be optionally wrapped in `PyResult`. - `object` means that any type is allowed that can be extracted from a Python object (if argument) or converted to a Python object (if return value). - Other types must match what's given, e.g. `pyo3::basic::CompareOp` for `__richcmp__`'s second argument. - For the comparison and arithmetic methods, extraction errors are not propagated as exceptions, but lead to a return of `NotImplemented`. - For some magic methods, the return values are not restricted by PyO3, but checked by the Python interpreter. For example, `__str__` needs to return a string object. This is indicated by `object (Python type)`. ### Basic object customization - `__str__() -> object (str)` - `__repr__() -> object (str)` - `__hash__() -> isize` Objects that compare equal must have the same hash value. Any type up to 64 bits may be returned instead of `isize`, PyO3 will convert to an isize automatically (wrapping unsigned types like `u64` and `usize`).
Disabling Python's default hash By default, all `#[pyclass]` types have a default hash implementation from Python. Types which should not be hashable can override this by setting `__hash__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] struct NotHashable {} #[pymethods] impl NotHashable { #[classattr] const __hash__: Option> = None; } ```
- `__lt__(, object) -> object` - `__le__(, object) -> object` - `__eq__(, object) -> object` - `__ne__(, object) -> object` - `__gt__(, object) -> object` - `__ge__(, object) -> object` The implementations of Python's "rich comparison" operators `<`, `<=`, `==`, `!=`, `>` and `>=` respectively. *Note that implementing any of these methods will cause Python not to generate a default XXXXXXXXXX implementation, so consider also implementing XXXXXXXXXX.*
Return type The return type will normally be `bool` or `PyResult`, however any Python object can be returned.
- `__richcmp__(, object, pyo3::basic::CompareOp) -> object` Implements Python comparison operations (`==`, `!=`, `<`, `<=`, `>`, and `>=`) in a single method. The `CompareOp` argument indicates the comparison operation being performed. You can use [`CompareOp::matches`] to adapt a Rust `std::cmp::Ordering` result to the requested comparison. *This method cannot be implemented in combination with any of XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, or XXXXXXXX.* *Note that implementing XXXXXXXXXXXXX will cause Python not to generate a default XXXXXXXXXX implementation, so consider implementing XXXXXXXXXX when implementing XXXXXXXXXXXXX.*
Return type The return type will normally be `PyResult`, but any Python object can be returned. If you want to leave some operations unimplemented, you can return `py.NotImplemented()` for some of the operations: ```rust,no_run use pyo3::class::basic::CompareOp; use pyo3::types::PyNotImplemented; # use pyo3::prelude::*; # use pyo3::BoundObject; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__<'py>(&self, other: &Self, op: CompareOp, py: Python<'py>) -> PyResult> { match op { CompareOp::Eq => Ok((self.0 == other.0).into_pyobject(py)?.into_any()), CompareOp::Ne => Ok((self.0 != other.0).into_pyobject(py)?.into_any()), _ => Ok(PyNotImplemented::get(py).into_any()), } } } ``` If the second argument `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.
- `__getattr__(, object) -> object` - `__getattribute__(, object) -> object`
Differences between `__getattr__` and `__getattribute__` As in Python, `__getattr__` is only called if the attribute is not found by normal attribute lookup. `__getattribute__`, on the other hand, is called for *every* attribute access. If it wants to access existing attributes on `self`, it needs to be very careful not to introduce infinite recursion, and use `baseclass.__getattribute__()`.
- `__setattr__(, value: object) -> ()` - `__delattr__(, object) -> ()` Overrides attribute access. - `__bool__() -> bool` Determines the "truthyness" of an object. - `__call__(, ...) -> object` - here, any argument list can be defined as for normal `pymethods` ### Iterable objects Iterators can be defined using these methods: - `__iter__() -> object` - `__next__() -> Option or IterNextOutput` ([see details](#returning-a-value-from-iteration)) Returning `None` from `__next__` indicates that that there are no further items. Example: ```rust,no_run use pyo3::prelude::*; use std::sync::Mutex; #[pyclass] struct MyIterator { iter: Mutex> + Send>>, } #[pymethods] impl MyIterator { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(slf: PyRefMut<'_, Self>) -> Option> { slf.iter.lock().unwrap().next() } } ``` In many cases you'll have a distinction between the type being iterated over (i.e. the *iterable*) and the iterator it provides. In this case, the iterable only needs to implement `__iter__()` while the iterator must implement both `__iter__()` and `__next__()`. For example: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct Iter { inner: std::vec::IntoIter, } #[pymethods] impl Iter { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { slf.inner.next() } } #[pyclass] struct Container { iter: Vec, } #[pymethods] impl Container { fn __iter__(slf: PyRef<'_, Self>) -> PyResult> { let iter = Iter { inner: slf.iter.clone().into_iter(), }; Py::new(slf.py(), iter) } } # Python::attach(|py| { # let container = Container { iter: vec![1, 2, 3, 4] }; # let inst = pyo3::Py::new(py, container).unwrap(); # pyo3::py_run!(py, inst, "assert list(inst) == [1, 2, 3, 4]"); # pyo3::py_run!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]"); # }); ``` For more details on Python's iteration protocols, check out [the "Iterator Types" section of the library documentation](https://docs.python.org/library/stdtypes.html#iterator-types). #### Returning a value from iteration This guide has so far shown how to use `Option` to implement yielding values during iteration. In Python a generator can also return a value. This is done by raising a `StopIteration` exception. To express this in Rust, return `PyResult::Err` with a `PyStopIteration` as the error. ### Awaitable objects - `__await__() -> object` - `__aiter__() -> object` - `__anext__() -> Option` ### Mapping & Sequence types The magic methods in this section can be used to implement Python container types. They are two main categories of container in Python: "mappings" such as `dict`, with arbitrary keys, and "sequences" such as `list` and `tuple`, with integer keys. The Python C-API which PyO3 is built upon has separate "slots" for sequences and mappings. When writing a `class` in pure Python, there is no such distinction in the implementation - a `__getitem__` implementation will fill the slots for both the mapping and sequence forms, for example. By default PyO3 reproduces the Python behaviour of filling both mapping and sequence slots. This makes sense for the "simple" case which matches Python, and also for sequences, where the mapping slot is used anyway to implement slice indexing. Mapping types usually will not want the sequence slots filled. Having them filled will lead to outcomes which may be unwanted, such as: - The mapping type will successfully cast to [`PySequence`]. This may lead to consumers of the type handling it incorrectly. - Python provides a default implementation of `__iter__` for sequences, which calls `__getitem__` with consecutive positive integers starting from 0 until an `IndexError` is returned. Unless the mapping only contains consecutive positive integer keys, this `__iter__` implementation will likely not be the intended behavior. Use the `#[pyclass(mapping)]` annotation to instruct PyO3 to only fill the mapping slots, leaving the sequence ones empty. This will apply to `__getitem__`, `__setitem__`, and `__delitem__`. Use the `#[pyclass(sequence)]` annotation to instruct PyO3 to fill the `sq_length` slot instead of the `mp_length` slot for `__len__`. This will help libraries such as `numpy` recognise the class as a sequence, however will also cause CPython to automatically add the sequence length to any negative indices before passing them to `__getitem__`. (`__getitem__`, `__setitem__` and `__delitem__` mapping slots are still used for sequences, for slice operations.) - `__len__() -> usize` Implements the built-in function `len()`. - `__contains__(, object) -> bool` Implements membership test operators. Should return true if `item` is in `self`, false otherwise. For objects that don’t define `__contains__()`, the membership test simply traverses the sequence until it finds a match.
Disabling Python's default contains By default, all `#[pyclass]` types with an `__iter__` method support a default implementation of the `in` operator. Types which do not want this can override this by setting `__contains__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] struct NoContains {} #[pymethods] impl NoContains { #[classattr] const __contains__: Option> = None; } ```
- `__getitem__(, object) -> object` Implements retrieval of the `self[a]` element. *Note:* Negative integer indexes are not handled specially by PyO3. However, for classes with `#[pyclass(sequence)]`, when a negative index is accessed via `PySequence::get_item`, the underlying C API already adjusts the index to be positive. - `__setitem__(, object, object) -> ()` Implements assignment to the `self[a]` element. Should only be implemented if elements can be replaced. Same behavior regarding negative indices as for `__getitem__`. - `__delitem__(, object) -> ()` Implements deletion of the `self[a]` element. Should only be implemented if elements can be deleted. Same behavior regarding negative indices as for `__getitem__`. - `fn __concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+` operator, after trying the numeric addition via the `__add__` and `__radd__` methods. - `fn __repeat__(&self, count: isize) -> PyResult` Repeats the sequence `count` times. Used by the `*` operator, after trying the numeric multiplication via the `__mul__` and `__rmul__` methods. - `fn __inplace_concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+=` operator, after trying the numeric addition via the `__iadd__` method. - `fn __inplace_repeat__(&self, count: isize) -> PyResult` Concatenates two sequences. Used by the `*=` operator, after trying the numeric multiplication via the `__imul__` method. ### Descriptors - `__get__(, object, object) -> object` - `__set__(, object, object) -> ()` - `__delete__(, object) -> ()` ### Numeric types Binary arithmetic operations (`+`, `-`, `*`, `@`, `/`, `//`, `%`, `divmod()`, `pow()` and `**`, `<<`, `>>`, `&`, `^`, and `|`) and their reflected versions: (If the `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.) - `__add__(, object) -> object` - `__radd__(, object) -> object` - `__sub__(, object) -> object` - `__rsub__(, object) -> object` - `__mul__(, object) -> object` - `__rmul__(, object) -> object` - `__matmul__(, object) -> object` - `__rmatmul__(, object) -> object` - `__floordiv__(, object) -> object` - `__rfloordiv__(, object) -> object` - `__truediv__(, object) -> object` - `__rtruediv__(, object) -> object` - `__divmod__(, object) -> object` - `__rdivmod__(, object) -> object` - `__mod__(, object) -> object` - `__rmod__(, object) -> object` - `__lshift__(, object) -> object` - `__rlshift__(, object) -> object` - `__rshift__(, object) -> object` - `__rrshift__(, object) -> object` - `__and__(, object) -> object` - `__rand__(, object) -> object` - `__xor__(, object) -> object` - `__rxor__(, object) -> object` - `__or__(, object) -> object` - `__ror__(, object) -> object` - `__pow__(, object, object) -> object` - `__rpow__(, object, object) -> object` In-place assignment operations (`+=`, `-=`, `*=`, `@=`, `/=`, `//=`, `%=`, `**=`, `<<=`, `>>=`, `&=`, `^=`, `|=`): - `__iadd__(, object) -> ()` - `__isub__(, object) -> ()` - `__imul__(, object) -> ()` - `__imatmul__(, object) -> ()` - `__itruediv__(, object) -> ()` - `__ifloordiv__(, object) -> ()` - `__imod__(, object) -> ()` - `__ipow__(, object, object) -> ()` - `__ilshift__(, object) -> ()` - `__irshift__(, object) -> ()` - `__iand__(, object) -> ()` - `__ixor__(, object) -> ()` - `__ior__(, object) -> ()` Unary operations (`-`, `+`, `abs()` and `~`): - `__pos__() -> object` - `__neg__() -> object` - `__abs__() -> object` - `__invert__() -> object` Coercions: - `__index__() -> object (int)` - `__int__() -> object (int)` - `__float__() -> object (float)` ### Buffer objects - `__getbuffer__(, *mut ffi::Py_buffer, flags) -> ()` - `__releasebuffer__(, *mut ffi::Py_buffer) -> ()` Errors returned from `__releasebuffer__` will be sent to `sys.unraiseablehook`. It is strongly advised to never return an error from `__releasebuffer__`, and if it really is necessary, to make best effort to perform any required freeing operations before returning. `__releasebuffer__` will not be called a second time; anything not freed will be leaked. ### Garbage Collector Integration If your type owns references to other Python objects, you will need to integrate with Python's garbage collector so that the GC is aware of those references. To do this, implement the two methods `__traverse__` and `__clear__`. These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. `__traverse__` must call `visit.call()` for each reference to another Python object. `__clear__` must clear out any mutable references to other Python objects (thus breaking reference cycles). Immutable references do not have to be cleared, as every cycle must contain at least one mutable reference. - `__traverse__(, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` - `__clear__() -> ()` > Note: `__traverse__` does not work with [`#[pyo3(warn(...))]`](../function.md#warn). Example: ```rust,no_run use pyo3::prelude::*; use pyo3::PyTraverseError; use pyo3::gc::PyVisit; #[pyclass] struct ClassWithGCSupport { obj: Option>, } #[pymethods] impl ClassWithGCSupport { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.obj)?; Ok(()) } fn __clear__(&mut self) { // Clear reference, this decrements ref counter. self.obj = None; } } ``` Usually, an implementation of `__traverse__` should do nothing but calls to `visit.call`. Most importantly, safe access to the interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic. > Note: these methods are part of the C API, PyPy does not necessarily honor them. If you are building for PyPy you should measure memory consumption to make sure you do not have runaway memory growth. See [this issue on the PyPy bug tracker](https://github.com/pypy/pypy/issues/3848). [`PySequence`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PySequence.html [`CompareOp::matches`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/enum.CompareOp.html#method.matches pyo3-0.27.2/guide/src/class/thread-safety.md000064400000000000000000000112171046102023000166630ustar 00000000000000# `#[pyclass]` thread safety Python objects are freely shared between threads by the Python interpreter. This means that: - there is no control which thread might eventually drop the `#[pyclass]` object, meaning `Send` is required. - multiple threads can potentially be reading the `#[pyclass]` data simultaneously, meaning `Sync` is required. This section of the guide discusses various data structures which can be used to make types satisfy these requirements. In special cases where it is known that your Python application is never going to use threads (this is rare!), these thread-safety requirements can be opted-out with [`#[pyclass(unsendable)]`](../class.md#customizing-the-class), at the cost of making concurrent access to the Rust data be runtime errors. This is only for very specific use cases; it is almost always better to make proper thread-safe types. ## Making `#[pyclass]` types thread-safe The general challenge with thread-safety is to make sure that two threads cannot produce a data race, i.e. unsynchronized writes to the same data at the same time. A data race produces an unpredictable result and is forbidden by Rust. By default, `#[pyclass]` employs an ["interior mutability" pattern](../class.md#bound-and-interior-mutability) to allow for either multiple `&T` references or a single exclusive `&mut T` reference to access the data. This allows for simple `#[pyclass]` types to be thread-safe automatically, at the cost of runtime checking for concurrent access. Errors will be raised if the usage overlaps. For example, the below simple class is thread-safe: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct MyClass { x: i32, y: i32, } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.x } fn set_y(&mut self, value: i32) { self.y = value; } } ``` In the above example, if calls to `get_x` and `set_y` overlap (from two different threads) then at least one of those threads will experience a runtime error indicating that the data was "already borrowed". To avoid these errors, you can take control of the interior mutability yourself in one of the following ways. ### Using atomic data structures To remove the possibility of having overlapping `&self` and `&mut self` references produce runtime errors, consider using `#[pyclass(frozen)]` and use [atomic data structures](https://doc.rust-lang.org/std/sync/atomic/) to control modifications directly. For example, a thread-safe version of the above `MyClass` using atomic integers would be as follows: ```rust,no_run # use pyo3::prelude::*; use std::sync::atomic::{AtomicI32, Ordering}; #[pyclass(frozen)] struct MyClass { x: AtomicI32, y: AtomicI32, } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.x.load(Ordering::Relaxed) } fn set_y(&self, value: i32) { self.y.store(value, Ordering::Relaxed) } } ``` ### Using locks An alternative to atomic data structures is to use [locks](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to make threads wait for access to shared data. For example, a thread-safe version of the above `MyClass` using locks would be as follows: ```rust,no_run # use pyo3::prelude::*; use std::sync::Mutex; struct MyClassInner { x: i32, y: i32, } #[pyclass(frozen)] struct MyClass { inner: Mutex } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.inner.lock().expect("lock not poisoned").x } fn set_y(&self, value: i32) { self.inner.lock().expect("lock not poisoned").y = value; } } ``` If you need to lock around state stored in the Python interpreter or otherwise call into the Python C API while a lock is held, you might find the `MutexExt` trait useful. It provides a `lock_py_attached` method for `std::sync::Mutex` that avoids deadlocks with the GIL or other global synchronization events in the interpreter. Additionally, support for the `parking_lot` and `lock_api` synchronization libraries is gated behind the `parking_lot` and `lock_api` features. You can also enable the `arc_lock` feature if you need the `arc_lock` features of either library. ### Wrapping unsynchronized data In some cases, the data structures stored within a `#[pyclass]` may themselves not be thread-safe. Rust will therefore not implement `Send` and `Sync` on the `#[pyclass]` type. To achieve thread-safety, a manual `Send` and `Sync` implementation is required which is `unsafe` and should only be done following careful review of the soundness of the implementation. Doing this for PyO3 types is no different than for any other Rust code, [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) has a great discussion on this. pyo3-0.27.2/guide/src/class.md000064400000000000000000001360321046102023000141260ustar 00000000000000# Python classes PyO3 exposes a group of attributes powered by Rust's proc macro system for defining Python classes as Rust structs. The main attribute is `#[pyclass]`, which is placed upon a Rust `struct` or `enum` to generate a Python type for it. They will usually also have *one* `#[pymethods]`-annotated `impl` block for the struct, which is used to define Python methods and constants for the generated Python type. (If the [`multiple-pymethods`] feature is enabled, each `#[pyclass]` is allowed to have multiple `#[pymethods]` blocks.) `#[pymethods]` may also have implementations for Python magic methods such as `__str__`. This chapter will discuss the functionality and configuration these attributes offer. Below is a list of links to the relevant section of this chapter for each: - [`#[pyclass]`](#defining-a-new-class) - [`#[pyo3(get, set)]`](#object-properties-using-pyo3get-set) - [`#[pymethods]`](#instance-methods) - [`#[new]`](#constructor) - [`#[getter]`](#object-properties-using-getter-and-setter) - [`#[setter]`](#object-properties-using-getter-and-setter) - [`#[staticmethod]`](#static-methods) - [`#[classmethod]`](#class-methods) - [`#[classattr]`](#class-attributes) - [`#[args]`](#method-arguments) - [Magic methods and slots](class/protocols.md) - [Classes as function arguments](#classes-as-function-arguments) ## Defining a new class To define a custom Python class, add the `#[pyclass]` attribute to a Rust struct or enum. ```rust # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass] struct MyClass { inner: i32, } // A "tuple" struct #[pyclass] struct Number(i32); // PyO3 supports unit-only enums (which contain only unit variants) // These simple enums behave similarly to Python's enumerations (enum.Enum) #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 30, // PyO3 supports custom discriminants. } // PyO3 supports custom discriminants in unit-only enums #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum HttpResponse { Ok = 200, NotFound = 404, Teapot = 418, // ... } // PyO3 also supports enums with Struct and Tuple variants // These complex enums have slightly different behavior from the simple enums above // They are meant to work with instance checks and match statement patterns // The variants can be mixed and matched // Struct variants have named fields while tuple enums generate generic names for fields in order _0, _1, _2, ... // Apart from this both types are functionally identical #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing(), } ``` The above example generates implementations for [`PyTypeInfo`] and [`PyClass`] for `MyClass`, `Number`, `MyEnum`, `HttpResponse`, and `Shape`. To see these generated implementations, refer to the [implementation details](#implementation-details) at the end of this chapter. ### Restrictions To integrate Rust types with Python, PyO3 needs to place some restrictions on the types which can be annotated with `#[pyclass]`. In particular, they must have no lifetime parameters, no generic parameters, and must be thread-safe. The reason for each of these is explained below. #### No lifetime parameters Rust lifetimes are used by the Rust compiler to reason about a program's memory safety. They are a compile-time only concept; there is no way to access Rust lifetimes at runtime from a dynamic language like Python. As soon as Rust data is exposed to Python, there is no guarantee that the Rust compiler can make on how long the data will live. Python is a reference-counted language and those references can be held for an arbitrarily long time which is untraceable by the Rust compiler. The only possible way to express this correctly is to require that any `#[pyclass]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[pyclass]` cannot have any lifetime parameters. When you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`Py`][`Py`]. #### No generic parameters A Rust `struct Foo` with a generic parameter `T` generates new compiled implementations each time it is used with a different concrete type for `T`. These new implementations are generated by the compiler at each usage site. This is incompatible with wrapping `Foo` in Python, where there needs to be a single compiled implementation of `Foo` which is integrated with the Python interpreter. Currently, the best alternative is to write a macro which expands to a new `#[pyclass]` for each instantiation you want: ```rust # #![allow(dead_code)] use pyo3::prelude::*; struct GenericClass { data: T, } macro_rules! create_interface { ($name: ident, $type: ident) => { #[pyclass] pub struct $name { inner: GenericClass<$type>, } #[pymethods] impl $name { #[new] pub fn new(data: $type) -> Self { Self { inner: GenericClass { data: data }, } } } }; } create_interface!(IntClass, i64); create_interface!(FloatClass, String); ``` #### Must be thread-safe Python objects are freely shared between threads by the Python interpreter. This means that: - Python objects may be created and destroyed by different Python threads; therefore `#[pyclass]` objects must be `Send`. - Python objects may be accessed by multiple Python threads simultaneously; therefore `#[pyclass]` objects must be `Sync`. For now, don't worry about these requirements; simple classes will already be thread-safe. There is a [detailed discussion on thread-safety](./class/thread-safety.md) later in the guide. ## Constructor By default, it is not possible to create an instance of a custom class from Python code. To declare a constructor, you need to define a method and annotate it with the `#[new]` attribute. Only Python's `__new__` method can be specified, `__init__` is not available. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Number(value) } } ``` Alternatively, if your `new` method may fail you can return `PyResult`. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; # #[pyclass] # struct Nonzero(i32); # #[pymethods] impl Nonzero { #[new] fn py_new(value: i32) -> PyResult { if value == 0 { Err(PyValueError::new_err("cannot be zero")) } else { Ok(Nonzero(value)) } } } ``` If you want to return an existing object (for example, because your `new` method caches the values it returns), `new` can return `pyo3::Py`. As you can see, the Rust method name is not important here; this way you can still, use `new()` for a Rust-level constructor. If no method marked with `#[new]` is declared, object instances can only be created from Rust, but not from Python. For arguments, see the [`Method arguments`](#method-arguments) section below. ## Adding the class to a module The next step is to create the Python module and add our class to it: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # fn main() {} # #[pyclass] # struct Number(i32); # #[pymodule] mod my_module { #[pymodule_export] use super::Number; } ``` ## Bound and interior mutability It is often useful to turn a `#[pyclass]` type `T` into a Python object and access it from Rust code. The [`Py`] and [`Bound<'py, T>`] smart pointers are the ways to represent a Python object in PyO3's API. More detail can be found about them [in the Python objects](./types.md#pyo3s-smart-pointers) section of the guide. Most Python objects do not offer exclusive (`&mut`) access (see the [section on Python's memory model](./python-from-rust.md#pythons-memory-model)). However, Rust structs wrapped as Python objects (called `pyclass` types) often *do* need `&mut` access. However, the Rust borrow checker cannot reason about `&mut` references once an object's ownership has been passed to the Python interpreter. To solve this, PyO3 does borrow checking at runtime using a scheme very similar to `std::cell::RefCell`. This is known as [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html). Users who are familiar with `RefCell` can use `Py` and `Bound<'py, T>` just like `RefCell`. For users who are not very familiar with `RefCell`, here is a reminder of Rust's rules of borrowing: - At any given time, you can have either (but not both of) one mutable reference or any number of immutable references. - References can never outlast the data they refer to. `Py` and `Bound<'py, T>`, like `RefCell`, ensure these borrowing rules by tracking references at runtime. ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { #[pyo3(get)] num: i32, } Python::attach(|py| { let obj = Bound::new(py, MyClass { num: 3 }).unwrap(); { let obj_ref = obj.borrow(); // Get PyRef assert_eq!(obj_ref.num, 3); // You cannot get PyRefMut unless all PyRefs are dropped assert!(obj.try_borrow_mut().is_err()); } { let mut obj_mut = obj.borrow_mut(); // Get PyRefMut obj_mut.num = 5; // You cannot get any other refs until the PyRefMut is dropped assert!(obj.try_borrow().is_err()); assert!(obj.try_borrow_mut().is_err()); } // You can convert `Bound` to a Python object pyo3::py_run!(py, obj, "assert obj.num == 5"); }); ``` A `Bound<'py, T>` is restricted to the Python lifetime `'py`. To make the object longer lived (for example, to store it in a struct on the Rust side), use `Py`. `Py` needs a `Python<'_>` token to allow access: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } fn return_myclass() -> Py { Python::attach(|py| Py::new(py, MyClass { num: 1 }).unwrap()) } let obj = return_myclass(); Python::attach(move |py| { let bound = obj.bind(py); // Py::bind returns &Bound<'py, MyClass> let obj_ref = bound.borrow(); // Get PyRef assert_eq!(obj_ref.num, 1); }); ``` ### frozen classes: Opting out of interior mutability As detailed above, runtime borrow checking is currently enabled by default. But a class can opt of out it by declaring itself `frozen`. It can still use interior mutability via standard Rust types like `RefCell` or `Mutex`, but it is not bound to the implementation provided by PyO3 and can choose the most appropriate strategy on field-by-field basis. Classes which are `frozen` and also `Sync`, e.g. they do use `Mutex` but not `RefCell`, can be accessed without needing a `Python` token via the `Bound::get` and `Py::get` methods: ```rust use std::sync::atomic::{AtomicUsize, Ordering}; # use pyo3::prelude::*; #[pyclass(frozen)] struct FrozenCounter { value: AtomicUsize, } let py_counter: Py = Python::attach(|py| { let counter = FrozenCounter { value: AtomicUsize::new(0), }; Py::new(py, counter).unwrap() }); py_counter.get().value.fetch_add(1, Ordering::Relaxed); Python::attach(move |_py| drop(py_counter)); ``` Frozen classes are likely to become the default thereby guiding the PyO3 ecosystem towards a more deliberate application of interior mutability. Eventually, this should enable further optimizations of PyO3's internals and avoid downstream code paying the cost of interior mutability when it is not actually required. ## Customizing the class {{#include ../pyclass-parameters.md}} These parameters are covered in various sections of this guide. ### Return type Generally, `#[new]` methods have to return `T: Into>` or `PyResult where T: Into>`. For constructors that may fail, you should wrap the return type in a PyResult as well. Consult the table below to determine which type your constructor should return: | | **Cannot fail** | **May fail** | |-----------------------------|---------------------------|-----------------------------------| |**No inheritance** | `T` | `PyResult` | |**Inheritance(T Inherits U)**| `(T, U)` | `PyResult<(T, U)>` | |**Inheritance(General Case)**| [`PyClassInitializer`] | `PyResult>` | ## Inheritance By default, `object`, i.e. `PyAny` is used as the base class. To override this default, use the `extends` parameter for `pyclass` with the full path to the base class. Currently, only classes defined in Rust and builtins provided by PyO3 can be inherited from; inheriting from other classes defined in Python is not yet supported ([#991](https://github.com/PyO3/pyo3/issues/991)). For convenience, `(T, U)` implements `Into>` where `U` is the base class of `T`. But for a more deeply nested inheritance, you have to return `PyClassInitializer` explicitly. To get a parent class from a child, use [`PyRef`] instead of `&self` for methods, or [`PyRefMut`] instead of `&mut self`. Then you can access a parent class by `self_.as_super()` as `&PyRef`, or by `self_.into_super()` as `PyRef` (and similar for the `PyRefMut` case). For convenience, `self_.as_ref()` can also be used to get `&Self::BaseClass` directly; however, this approach does not let you access base classes higher in the inheritance hierarchy, for which you would need to chain multiple `as_super` or `into_super` calls. ```rust # use pyo3::prelude::*; #[pyclass(subclass)] struct BaseClass { val1: usize, } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } pub fn method1(&self) -> PyResult { Ok(self.val1) } } #[pyclass(extends=BaseClass, subclass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass { val2: 15 }, BaseClass::new()) } fn method2(self_: PyRef<'_, Self>) -> PyResult { let super_ = self_.as_super(); // Get &PyRef super_.method1().map(|x| x * self_.val2) } } #[pyclass(extends=SubClass)] struct SubSubClass { val3: usize, } #[pymethods] impl SubSubClass { #[new] fn new() -> PyClassInitializer { PyClassInitializer::from(SubClass::new()).add_subclass(SubSubClass { val3: 20 }) } fn method3(self_: PyRef<'_, Self>) -> PyResult { let base = self_.as_super().as_super(); // Get &PyRef<'_, BaseClass> base.method1().map(|x| x * self_.val3) } fn method4(self_: PyRef<'_, Self>) -> PyResult { let v = self_.val3; let super_ = self_.into_super(); // Get PyRef<'_, SubClass> SubClass::method2(super_).map(|x| x * v) } fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) { let val1 = self_.as_super().as_super().val1; let val2 = self_.as_super().val2; (val1, val2, self_.val3) } fn double_values(mut self_: PyRefMut<'_, Self>) { self_.as_super().as_super().val1 *= 2; self_.as_super().val2 *= 2; self_.val3 *= 2; } #[staticmethod] fn factory_method(py: Python<'_>, val: usize) -> PyResult> { let base = PyClassInitializer::from(BaseClass::new()); let sub = base.add_subclass(SubClass { val2: val }); if val % 2 == 0 { Ok(Py::new(py, sub)?.into_any()) } else { let sub_sub = sub.add_subclass(SubSubClass { val3: val }); Ok(Py::new(py, sub_sub)?.into_any()) } } } # Python::attach(|py| { # let subsub = pyo3::Py::new(py, SubSubClass::new()).unwrap(); # pyo3::py_run!(py, subsub, "assert subsub.method1() == 10"); # pyo3::py_run!(py, subsub, "assert subsub.method2() == 150"); # pyo3::py_run!(py, subsub, "assert subsub.method3() == 200"); # pyo3::py_run!(py, subsub, "assert subsub.method4() == 3000"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (10, 15, 20)"); # pyo3::py_run!(py, subsub, "assert subsub.double_values() == None"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (20, 30, 40)"); # let subsub = SubSubClass::factory_method(py, 2).unwrap(); # let subsubsub = SubSubClass::factory_method(py, 3).unwrap(); # let cls = py.get_type::(); # pyo3::py_run!(py, subsub cls, "assert not isinstance(subsub, cls)"); # pyo3::py_run!(py, subsubsub cls, "assert isinstance(subsubsub, cls)"); # }); ``` You can inherit native types such as `PyDict`, if they implement [`PySizedLayout`]({{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PySizedLayout.html). This is not supported when building for the Python limited API (aka the `abi3` feature of PyO3). To convert between the Rust type and its native base class, you can take `slf` as a Python object. To access the Rust fields use `slf.borrow()` or `slf.borrow_mut()`, and to access the base class use `slf.cast::()`. ```rust # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; use std::collections::HashMap; #[pyclass(extends=PyDict)] #[derive(Default)] struct DictWithCounter { counter: HashMap, } #[pymethods] impl DictWithCounter { #[new] fn new() -> Self { Self::default() } fn set(slf: &Bound<'_, Self>, key: String, value: Bound<'_, PyAny>) -> PyResult<()> { slf.borrow_mut().counter.entry(key.clone()).or_insert(0); let dict = slf.cast::()?; dict.set_item(key, value) } } # Python::attach(|py| { # let cnt = pyo3::Py::new(py, DictWithCounter::new()).unwrap(); # pyo3::py_run!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10") # }); # } ``` If `SubClass` does not provide a base class initialization, the compilation fails. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass] struct BaseClass { val1: usize, } #[pyclass(extends=BaseClass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> Self { SubClass { val2: 15 } } } ``` The `__new__` constructor of a native base class is called implicitly when creating a new instance from Python. Be sure to accept arguments in the `#[new]` method that you want the base class to get, even if they are not used in that `fn`: ```rust # #[allow(dead_code)] # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; #[pyclass(extends=PyDict)] struct MyDict { private: i32, } #[pymethods] impl MyDict { #[new] #[pyo3(signature = (*args, **kwargs))] fn new(args: &Bound<'_, PyAny>, kwargs: Option<&Bound<'_, PyAny>>) -> Self { Self { private: 0 } } // some custom methods that use `private` here... } # Python::attach(|py| { # let cls = py.get_type::(); # pyo3::py_run!(py, cls, "cls(a=1, b=2)") # }); # } ``` Here, the `args` and `kwargs` allow creating instances of the subclass passing initial items, such as `MyDict(item_sequence)` or `MyDict(a=1, b=2)`. ## Object properties PyO3 supports two ways to add properties to your `#[pyclass]`: - For simple struct fields with no side effects, a `#[pyo3(get, set)]` attribute can be added directly to the field definition in the `#[pyclass]`. - For properties which require computation you can define `#[getter]` and `#[setter]` functions in the [`#[pymethods]`](#instance-methods) block. We'll cover each of these in the following sections. ### Object properties using `#[pyo3(get, set)]` For simple cases where a member variable is just read and written with no side effects, you can declare getters and setters in your `#[pyclass]` field definition using the `pyo3` attribute, like in the example below: ```rust # use pyo3::prelude::*; # #[allow(dead_code)] #[pyclass] struct MyClass { #[pyo3(get, set)] num: i32, } ``` The above would make the `num` field available for reading and writing as a `self.num` Python property. To expose the property with a different name to the field, specify this alongside the rest of the options, e.g. `#[pyo3(get, set, name = "custom_name")]`. Properties can be readonly or writeonly by using just `#[pyo3(get)]` or `#[pyo3(set)]` respectively. To use these annotations, your field type must implement some conversion traits: - For `get` the field type `T` must implement either `&T: IntoPyObject` or `T: IntoPyObject + Clone`. - For `set` the field type must implement `FromPyObject`. For example, implementations of those traits are provided for the `Cell` type, if the inner type also implements the trait. This means you can use `#[pyo3(get, set)]` on fields wrapped in a `Cell`. ### Object properties using `#[getter]` and `#[setter]` For cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block. This is done using the `#[getter]` and `#[setter]` attributes, like in the example below: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } #[pymethods] impl MyClass { #[getter] fn num(&self) -> PyResult { Ok(self.num) } } ``` A getter or setter's function name is used as the property name by default. There are several ways how to override the name. If a function name starts with `get_` or `set_` for getter or setter respectively, the descriptor name becomes the function name with this prefix removed. This is also useful in case of Rust keywords like `type` ([raw identifiers](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/raw-identifiers.html) can be used since Rust 2018). ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter] fn get_num(&self) -> PyResult { Ok(self.num) } #[setter] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, a property `num` is defined and available from Python code as `self.num`. Both the `#[getter]` and `#[setter]` attributes accept one parameter. If this parameter is specified, it is used as the property name, i.e. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter(number)] fn num(&self) -> PyResult { Ok(self.num) } #[setter(number)] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, the property `number` is defined and available from Python code as `self.number`. Attributes defined by `#[setter]` or `#[pyo3(set)]` will always raise `AttributeError` on `del` operations. Support for defining custom `del` behavior is tracked in [#1778](https://github.com/PyO3/pyo3/issues/1778). ## Instance methods To define a Python compatible method, an `impl` block for your struct has to be annotated with the `#[pymethods]` attribute. PyO3 generates Python compatible wrappers for all functions in this block with some variations, like descriptors, class method static methods, etc. Since Rust allows any number of `impl` blocks, you can easily split methods between those accessible to Python (and Rust) and those accessible only to Rust. However to have multiple `#[pymethods]`-annotated `impl` blocks for the same struct you must enable the [`multiple-pymethods`] feature of PyO3. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { fn method1(&self) -> PyResult { Ok(10) } fn set_method(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` Both `&self` and `&mut self` can be used, due to the use of [runtime borrow checking](#bound-and-interior-mutability). The return type must be `PyResult` or `T` for some `T` that implements `IntoPyObject`; the latter is allowed if the method cannot raise Python exceptions. A `Python` parameter can be specified as part of method signature, in this case the `py` argument gets injected by the method wrapper, e.g. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { fn method2(&self, py: Python<'_>) -> PyResult { Ok(10) } } ``` From the Python perspective, the `method2` in this example does not accept any arguments. ## Class methods To create a class method for a custom class, the method needs to be annotated with the `#[classmethod]` attribute. This is the equivalent of the Python decorator `@classmethod`. ```rust # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[classmethod] fn cls_method(cls: &Bound<'_, PyType>) -> PyResult { Ok(10) } } ``` Declares a class method callable from Python. - The first parameter is the type object of the class on which the method is called. This may be the type object of a derived class. - The first parameter implicitly has type `&Bound<'_, PyType>`. - For details on `parameter-list`, see the documentation of `Method arguments` section. - The return type must be `PyResult` or `T` for some `T` that implements `IntoPyObject`. ### Constructors which accept a class argument To create a constructor which takes a positional class argument, you can combine the `#[classmethod]` and `#[new]` modifiers: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct BaseClass(Py); # #[pymethods] impl BaseClass { #[new] #[classmethod] fn py_new(cls: &Bound<'_, PyType>) -> PyResult { // Get an abstract attribute (presumably) declared on a subclass of this class. let subclass_attr: Bound<'_, PyAny> = cls.getattr("a_class_attr")?; Ok(Self(subclass_attr.unbind())) } } ``` ## Static methods To create a static method for a custom class, the method needs to be annotated with the `#[staticmethod]` attribute. The return type must be `T` or `PyResult` for some `T` that implements `IntoPyObject`. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[staticmethod] fn static_method(param1: i32, param2: &str) -> PyResult { Ok(10) } } ``` ## Class attributes To create a class attribute (also called [class variable][classattr]), a method without any arguments can be annotated with the `#[classattr]` attribute. ```rust,no_run # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] fn my_attribute() -> String { "hello".to_string() } } Python::attach(|py| { let my_class = py.get_type::(); pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'") }); ``` > Note: if the method has a `Result` return type and returns an `Err`, PyO3 will panic during class creation. > Note: `#[classattr]` does not work with [`#[pyo3(warn(...))]`](./function.md#warn) attribute. If the class attribute is defined with `const` code only, one can also annotate associated constants: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] const MY_CONST_ATTRIBUTE: &'static str = "foobar"; } ``` ## Classes as function arguments Class objects can be used as arguments to `#[pyfunction]`s and `#[pymethods]` in the same way as the self parameters of instance methods, i.e. they can be passed as: - `Py` or `Bound<'py, T>` smart pointers to the class Python object, - `&T` or `&mut T` references to the Rust data contained in the Python object, or - `PyRef` and `PyRefMut` reference wrappers. Examples of each of these below: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct MyClass { my_field: i32, } // Take a reference to Rust data when the Python object is irrelevant. #[pyfunction] fn increment_field(my_class: &mut MyClass) { my_class.my_field += 1; } // Take a reference wrapper when borrowing should be automatic, // but access to the Python object is still needed #[pyfunction] fn print_field_and_return_me(my_class: PyRef<'_, MyClass>) -> PyRef<'_, MyClass> { println!("{}", my_class.my_field); my_class } // Take (a reference to) a Python object smart pointer when borrowing needs to be managed manually. #[pyfunction] fn increment_then_print_field(my_class: &Bound<'_, MyClass>) { my_class.borrow_mut().my_field += 1; println!("{}", my_class.borrow().my_field); } // When the Python object smart pointer needs to be stored elsewhere prefer `Py` over `Bound<'py, T>` // to avoid the lifetime restrictions. #[pyfunction] fn print_refcnt(my_class: Py, py: Python<'_>) { println!("{}", my_class.get_refcnt(py)); } ``` Classes can also be passed by value if they can be cloned, i.e. they automatically implement `FromPyObject` if they implement `Clone`, e.g. via `#[derive(Clone)]`: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct MyClass { my_field: Box, } #[pyfunction] fn disassemble_clone(my_class: MyClass) { let MyClass { mut my_field } = my_class; *my_field += 1; } ``` Note that `#[derive(FromPyObject)]` on a class is usually not useful as it tries to construct a new Rust value by filling in the fields by looking up attributes of any given Python value. ## Method arguments Similar to `#[pyfunction]`, the `#[pyo3(signature = (...))]` attribute can be used to specify the way that `#[pymethods]` accept arguments. Consult the documentation for [`function signatures`](./function/signature.md) to see the parameters this attribute accepts. The following example defines a class `MyClass` with a method `method`. This method has a signature that sets default values for `num` and `name`, and indicates that `py_args` should collect all extra positional arguments and `py_kwargs` all extra keyword arguments: ```rust,no_run # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } } ``` In Python, this might be used like: ```python >>> import mymodule >>> mc = mymodule.MyClass() >>> print(mc.method(44, False, "World", 666, x=44, y=55)) py_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44, num_before=-1 >>> print(mc.method(num=-1, name="World")) py_args=(), py_kwargs=None, name=World, num=-1, num_before=44 ``` The [`#[pyo3(text_signature = "...")`](./function/signature.md#overriding-the-generated-signature) option for `#[pyfunction]` also works for `#[pymethods]`. ```rust # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyType; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(text_signature = "(c, d)")] fn new(c: i32, d: &str) -> Self { Self {} } // the self argument should be written $self #[pyo3(text_signature = "($self, e, f)")] fn my_method(&self, e: i32, f: i32) -> i32 { e + f } // similarly for classmethod arguments, use $cls #[classmethod] #[pyo3(text_signature = "($cls, e, f)")] fn my_class_method(cls: &Bound<'_, PyType>, e: i32, f: i32) -> i32 { e + f } #[staticmethod] #[pyo3(text_signature = "(e, f)")] fn my_static_method(e: i32, f: i32) -> i32 { e + f } } # # fn main() -> PyResult<()> { # Python::attach(|py| { # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let module = PyModule::new(py, "my_module")?; # module.add_class::()?; # let class = module.getattr("MyClass")?; # # if cfg!(not(Py_LIMITED_API)) || py.version_info() >= (3, 10) { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # let sig: String = inspect # .call1((&class,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(c, d)"); # } else { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # inspect.call1((&class,)).expect_err("`text_signature` on classes is not compatible with compilation in `abi3` mode until Python 3.10 or greater"); # } # # { # let method = class.getattr("my_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(self, /, e, f)"); # } # # { # let method = class.getattr("my_class_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); // inspect.signature skips the $cls arg # } # # { # let method = class.getattr("my_static_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); # } # # Ok(()) # }) # } ``` Note that `text_signature` on `#[new]` is not compatible with compilation in `abi3` mode until Python 3.10 or greater. ### Method receivers and lifetime elision PyO3 supports writing instance methods using the normal method receivers for shared `&self` and unique `&mut self` references. This interacts with [lifetime elision][lifetime-elision] insofar as the lifetime of a such a receiver is assigned to all elided output lifetime parameters. This is a good default for general Rust code where return values are more likely to borrow from the receiver than from the other arguments, if they contain any lifetimes at all. However, when returning bound references `Bound<'py, T>` in PyO3-based code, the Python lifetime `'py` should usually be derived from a `py: Python<'py>` token passed as an argument instead of the receiver. Specifically, signatures like ```rust,ignore fn frobnicate(&self, py: Python) -> Bound; ``` will not work as they are inferred as ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'a, Foo>; ``` instead of the intended ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'py, Foo>; ``` and should usually be written as ```rust,ignore fn frobnicate<'py>(&self, py: Python<'py>) -> Bound<'py, Foo>; ``` The same problem does not exist for `#[pyfunction]`s as the special case for receiver lifetimes does not apply and indeed a signature like ```rust,ignore fn frobnicate(bar: &Bar, py: Python) -> Bound; ``` will yield compiler error [E0106 "missing lifetime specifier"][compiler-error-e0106]. ## `#[pyclass]` enums Enum support in PyO3 comes in two flavors, depending on what kind of variants the enum has: simple and complex. ### Simple enums A simple enum (a.k.a. C-like enum) has only unit variants. PyO3 adds a class attribute for each variant, so you can access them in Python without defining `#[new]`. PyO3 also provides default implementations of `__richcmp__` and `__int__`, so they can be compared using `==`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant, } Python::attach(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let y = Py::new(py, MyEnum::OtherVariant).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x y cls, r#" assert x == cls.Variant assert y == cls.OtherVariant assert x != y "#) }) ``` You can also convert your simple enums into `int`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 10, } Python::attach(|py| { let cls = py.get_type::(); let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler. pyo3::py_run!(py, cls x, r#" assert int(cls.Variant) == x assert int(cls.OtherVariant) == 10 "#) }) ``` PyO3 also provides `__repr__` for enums: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum{ Variant, OtherVariant, } Python::attach(|py| { let cls = py.get_type::(); let x = Py::new(py, MyEnum::Variant).unwrap(); pyo3::py_run!(py, cls x, r#" assert repr(x) == 'MyEnum.Variant' assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant' "#) }) ``` All methods defined by PyO3 can be overridden. For example here's how you override `__repr__`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Answer = 42, } #[pymethods] impl MyEnum { fn __repr__(&self) -> &'static str { "42" } } Python::attach(|py| { let cls = py.get_type::(); pyo3::py_run!(py, cls, "assert repr(cls.Answer) == '42'") }) ``` Enums and their variants can also be renamed using `#[pyo3(name)]`. ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int, name = "RenamedEnum")] #[derive(PartialEq)] enum MyEnum { #[pyo3(name = "UPPERCASE")] Variant, } Python::attach(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x cls, r#" assert repr(x) == 'RenamedEnum.UPPERCASE' assert x == cls.UPPERCASE "#) }) ``` Ordering of enum variants is optionally added using `#[pyo3(ord)]`. *Note: Implementation of the `PartialOrd` trait is required when passing the `ord` argument. If not implemented, a compile time error is raised.* ```rust # use pyo3::prelude::*; #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] enum MyEnum{ A, B, C, } Python::attach(|py| { let cls = py.get_type::(); let a = Py::new(py, MyEnum::A).unwrap(); let b = Py::new(py, MyEnum::B).unwrap(); let c = Py::new(py, MyEnum::C).unwrap(); pyo3::py_run!(py, cls a b c, r#" assert (a < b) == True assert (c <= b) == False assert (c > a) == True "#) }) ``` You may not use enums as a base class or let enums inherit from other classes. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] enum BadBase { Var1, } ``` ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] struct Base; #[pyclass(extends=Base)] enum BadSubclass { Var1, } ``` `#[pyclass]` enums are currently not interoperable with `IntEnum` in Python. ### Complex enums An enum is complex if it has any non-unit (struct or tuple) variants. PyO3 supports only struct and tuple variants in a complex enum. Unit variants aren't supported at present (the recommendation is to use an empty tuple enum instead). PyO3 adds a class attribute for each variant, which may be used to construct values and in match patterns. PyO3 also provides getter methods for all fields of each variant. ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing { }, } # #[cfg(Py_3_10)] Python::attach(|py| { let circle = Shape::Circle { radius: 10.0 }.into_pyobject(py)?; let square = Shape::RegularPolygon(4, 10.0).into_pyobject(py)?; let cls = py.get_type::(); pyo3::py_run!(py, circle square cls, r#" assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 10.0 assert isinstance(square, cls) assert isinstance(square, cls.RegularPolygon) assert square[0] == 4 # Gets _0 field assert square[1] == 10.0 # Gets _1 field def count_vertices(cls, shape): match shape: case cls.Circle(): return 0 case cls.Rectangle(): return 4 case cls.RegularPolygon(n): return n case cls.Nothing(): return 0 assert count_vertices(cls, circle) == 0 assert count_vertices(cls, square) == 4 "#); # Ok::<_, PyErr>(()) }) # .unwrap(); ``` WARNING: `Py::new` and `.into_pyobject` are currently inconsistent. Note how the constructed value is *not* an instance of the specific variant. For this reason, constructing values is only recommended using `.into_pyobject`. ```rust # use pyo3::prelude::*; #[pyclass] enum MyEnum { Variant { i: i32 }, } Python::attach(|py| { let x = Py::new(py, MyEnum::Variant { i: 42 }).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x cls, r#" assert isinstance(x, cls) assert not isinstance(x, cls.Variant) "#) }) ``` The constructor of each generated class can be customized using the `#[pyo3(constructor = (...))]` attribute. This uses the same syntax as the [`#[pyo3(signature = (...))]`](function/signature.md) attribute on function and methods and supports the same options. To apply this attribute simply place it on top of a variant in a `#[pyclass]` complex enum as shown below: ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { #[pyo3(constructor = (radius=1.0))] Circle { radius: f64 }, #[pyo3(constructor = (*, width, height))] Rectangle { width: f64, height: f64 }, #[pyo3(constructor = (side_count, radius=1.0))] RegularPolygon { side_count: u32, radius: f64 }, Nothing { }, } # #[cfg(Py_3_10)] Python::attach(|py| { let cls = py.get_type::(); pyo3::py_run!(py, cls, r#" circle = cls.Circle() assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 1.0 square = cls.Rectangle(width = 1, height = 1) assert isinstance(square, cls) assert isinstance(square, cls.Rectangle) assert square.width == 1 assert square.height == 1 hexagon = cls.RegularPolygon(6) assert isinstance(hexagon, cls) assert isinstance(hexagon, cls.RegularPolygon) assert hexagon.side_count == 6 assert hexagon.radius == 1 "#) }) ``` ## Implementation details The `#[pyclass]` macros rely on a lot of conditional code generation: each `#[pyclass]` can optionally have a `#[pymethods]` block. To support this flexibility the `#[pyclass]` macro expands to a blob of boilerplate code which sets up the structure for ["dtolnay specialization"](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md). This implementation pattern enables the Rust compiler to use `#[pymethods]` implementations when they are present, and fall back to default (empty) definitions when they are not. This simple technique works for the case when there is zero or one implementations. To support multiple `#[pymethods]` for a `#[pyclass]` (in the [`multiple-pymethods`] feature), a registry mechanism provided by the [`inventory`](https://github.com/dtolnay/inventory) crate is used instead. This collects `impl`s at library load time, but isn't supported on all platforms. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) for more details. The `#[pyclass]` macro expands to roughly the code seen below. The `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization: ```rust # #[cfg(not(feature = "multiple-pymethods"))] { # use pyo3::prelude::*; // Note: the implementation differs slightly with the `multiple-pymethods` feature enabled. # #[allow(dead_code)] struct MyClass { # #[allow(dead_code)] num: i32, } impl pyo3::types::DerefToPyAny for MyClass {} unsafe impl pyo3::type_object::PyTypeInfo for MyClass { const NAME: &'static str = "MyClass"; const MODULE: ::std::option::Option<&'static str> = ::std::option::Option::None; #[inline] fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject { ::lazy_type_object() .get_or_try_init(py) .unwrap_or_else(|e| pyo3::impl_::pyclass::type_object_init_failed( py, e, ::NAME )) .as_type_ptr() } } impl pyo3::PyClass for MyClass { type Frozen = pyo3::pyclass::boolean_struct::False; } impl pyo3::impl_::pyclass::PyClassImpl for MyClass { const IS_BASETYPE: bool = false; const IS_SUBCLASS: bool = false; const IS_MAPPING: bool = false; const IS_SEQUENCE: bool = false; type BaseType = PyAny; type ThreadChecker = pyo3::impl_::pyclass::SendablePyClass; type PyClassMutability = <::PyClassMutability as pyo3::impl_::pycell::PyClassMutability>::MutableChild; type Dict = pyo3::impl_::pyclass::PyClassDummySlot; type WeakRef = pyo3::impl_::pyclass::PyClassDummySlot; type BaseNativeType = pyo3::PyAny; const RAW_DOC: &'static std::ffi::CStr = pyo3::ffi::c_str!("..."); const DOC: &'static std::ffi::CStr = pyo3::ffi::c_str!("..."); fn items_iter() -> pyo3::impl_::pyclass::PyClassItemsIter { use pyo3::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); static INTRINSIC_ITEMS: PyClassItems = PyClassItems { slots: &[], methods: &[] }; PyClassItemsIter::new(&INTRINSIC_ITEMS, collector.py_methods()) } fn lazy_type_object() -> &'static pyo3::impl_::pyclass::LazyTypeObject { use pyo3::impl_::pyclass::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject = LazyTypeObject::new(); &TYPE_OBJECT } } # Python::attach(|py| { # let cls = py.get_type::(); # pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") # }); # } ``` [`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html [`Py`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [`Bound<'py, T>`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`PyClass`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/trait.PyClass.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html [`PyClassInitializer`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass_init/struct.PyClassInitializer.html [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html [classattr]: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables [`multiple-pymethods`]: features.md#multiple-pymethods [lifetime-elision]: https://doc.rust-lang.org/reference/lifetime-elision.html [compiler-error-e0106]: https://doc.rust-lang.org/error_codes/E0106.html pyo3-0.27.2/guide/src/contributing.md000064400000000000000000000000431046102023000155200ustar 00000000000000{{#include ../../Contributing.md}} pyo3-0.27.2/guide/src/conversions/tables.md000064400000000000000000000176031046102023000166450ustar 00000000000000# Mapping of Rust types to Python types When writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPyObject` is required for function return values. Consult the tables in the following section to find the Rust types provided by PyO3 which implement these traits. ## Argument Types When accepting a function argument, it is possible to either use Rust library types or PyO3's Python-native types. (See the next section for discussion on when to use each.) The table below contains the Python type and the corresponding function argument types that will accept them: | Python | Rust | Rust (Python-native) | | ------------- |:-------------------------------:|:--------------------:| | `object` | - | `PyAny` | | `str` | `String`, `Cow`, `&str`, `char`, `OsString`, `PathBuf`, `Path` | `PyString` | | `bytes` | `Vec`, `&[u8]`, `Cow<[u8]>` | `PyBytes` | | `bool` | `bool` | `PyBool` | | `int` | `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`, `num_bigint::BigInt`[^1], `num_bigint::BigUint`[^1] | `PyInt` | | `float` | `f32`, `f64`, `ordered_float::NotNan`[^10], `ordered_float::OrderedFloat`[^10] | `PyFloat` | | `complex` | `num_complex::Complex`[^2] | `PyComplex` | | `fractions.Fraction`| `num_rational::Ratio`[^8] | - | | `list[T]` | `Vec` | `PyList` | | `dict[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `PyDict` | | `tuple[T, U]` | `(T, U)`, `Vec` | `PyTuple` | | `set[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PySet` | | `frozenset[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PyFrozenSet` | | `bytearray` | `Vec`, `Cow<[u8]>` | `PyByteArray` | | `slice` | - | `PySlice` | | `type` | - | `PyType` | | `module` | - | `PyModule` | | `collections.abc.Buffer` | - | `PyBuffer` | | `datetime.datetime` | `SystemTime`, `chrono::DateTime`[^5], `chrono::NaiveDateTime`[^5] | `PyDateTime` | | `datetime.date` | `chrono::NaiveDate`[^5] | `PyDate` | | `datetime.time` | `chrono::NaiveTime`[^5] | `PyTime` | | `datetime.tzinfo` | `chrono::FixedOffset`[^5], `chrono::Utc`[^5], `chrono_tz::TimeZone`[^6] | `PyTzInfo` | | `datetime.timedelta` | `Duration`, `chrono::Duration`[^5] | `PyDelta` | | `decimal.Decimal` | `rust_decimal::Decimal`[^7] | - | | `decimal.Decimal` | `bigdecimal::BigDecimal`[^9] | - | | `ipaddress.IPv4Address` | `std::net::IpAddr`, `std::net::Ipv4Addr` | - | | `ipaddress.IPv6Address` | `std::net::IpAddr`, `std::net::Ipv6Addr` | - | | `os.PathLike` | `PathBuf`, `Path` | `PyString` | | `pathlib.Path` | `PathBuf`, `Path` | `PyString` | | `typing.Optional[T]` | `Option` | - | | `typing.Sequence[T]` | `Vec` | `PySequence` | | `typing.Mapping[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `&PyMapping` | | `typing.Iterator[Any]` | - | `PyIterator` | | `typing.Union[...]` | See [`#[derive(FromPyObject)]`](traits.md#deriving-frompyobject-for-enums) | - | It is also worth remembering the following special types: | What | Description | | ---------------- | ------------------------------------- | | `Python<'py>` | A token used to prove attachment to the Python interpreter. | | `Bound<'py, T>` | A Python object with a lifetime which binds it to the attachment to the Python interpreter. This provides access to most of PyO3's APIs. | | `Py` | A Python object not connected to any lifetime of attachment to the Python interpreter. This can be sent to other threads. | | `PyRef` | A `#[pyclass]` borrowed immutably. | | `PyRefMut` | A `#[pyclass]` borrowed mutably. | For more detail on accepting `#[pyclass]` values as function arguments, see [the section of this guide on Python Classes](../class.md). ### Using Rust library types vs Python-native types Using Rust library types as function arguments will incur a conversion cost compared to using the Python-native types. Using the Python-native types is almost zero-cost (they just require a type check similar to the Python builtin function `isinstance()`). However, once that conversion cost has been paid, the Rust standard library types offer a number of benefits: - You can write functionality in native-speed Rust code (free of Python's runtime costs). - You get better interoperability with the rest of the Rust ecosystem. - You can use `Python::detach` to detach from the interpreter and let other Python threads make progress while your Rust code is executing. - You also benefit from stricter type checking. For example you can specify `Vec`, which will only accept a Python `list` containing integers. The Python-native equivalent, `&PyList`, would accept a Python `list` containing Python objects of any type. For most PyO3 usage the conversion cost is worth paying to get these benefits. As always, if you're not sure it's worth it in your case, benchmark it! ## Returning Rust values to Python When returning values from functions callable from Python, [PyO3's smart pointers](../types.md#pyo3s-smart-pointers) (`Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`) can be used with zero cost. Because `Bound<'py, T>` and `Borrowed<'a, 'py, T>` have lifetime parameters, the Rust compiler may ask for lifetime annotations to be added to your function. See the [section of the guide dedicated to this](../types.md#function-argument-lifetimes). If your function is fallible, it should return `PyResult` or `Result` where `E` implements `From for PyErr`. This will raise a `Python` exception if the `Err` variant is returned. Finally, the following Rust types are also able to convert to Python as return values: | Rust type | Resulting Python Type | | ------------- |:-------------------------------:| | `String` | `str` | | `&str` | `str` | | `bool` | `bool` | | Any integer type (`i32`, `u32`, `usize`, etc) | `int` | | `f32`, `f64` | `float` | | `Option` | `Optional[T]` | | `(T, U)` | `Tuple[T, U]` | | `Vec` | `List[T]` | | `Cow<[u8]>` | `bytes` | | `HashMap` | `Dict[K, V]` | | `BTreeMap` | `Dict[K, V]` | | `HashSet` | `Set[T]` | | `BTreeSet` | `Set[T]` | | `Py` | `T` | | `Bound` | `T` | | `PyRef` | `T` | | `PyRefMut` | `T` | [^1]: Requires the `num-bigint` optional feature. [^2]: Requires the `num-complex` optional feature. [^3]: Requires the `hashbrown` optional feature. [^4]: Requires the `indexmap` optional feature. [^5]: Requires the `chrono` (and maybe `chrono-local`) optional feature(s). [^6]: Requires the `chrono-tz` optional feature. [^7]: Requires the `rust_decimal` optional feature. [^8]: Requires the `num-rational` optional feature. [^9]: Requires the `bigdecimal` optional feature. [^10]: Requires the `ordered-float` optional feature. pyo3-0.27.2/guide/src/conversions/traits.md000064400000000000000000000645511046102023000167050ustar 00000000000000# Conversion traits PyO3 provides some handy traits to convert between Python types and Rust types. ## `.extract()` and the `FromPyObject` trait The easiest way to convert a Python object to a Rust value is using `.extract()`. It returns a `PyResult` with a type error if the conversion fails, so usually you will use something like ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; # fn main() -> PyResult<()> { # Python::attach(|py| { # let list = PyList::new(py, b"foo")?; let v: Vec = list.extract()?; # assert_eq!(&v, &[102, 111, 111]); # Ok(()) # }) # } ``` This method is available for many Python object types, and can produce a wide variety of Rust types, which you can check out in the implementor list of [`FromPyObject`]. [`FromPyObject`] is also implemented for your own Rust types wrapped as Python objects (see [the chapter about classes](../class.md)). There, in order to both be able to operate on mutable references *and* satisfy Rust's rules of non-aliasing mutable references, you have to extract the PyO3 reference wrappers [`PyRef`] and [`PyRefMut`]. They work like the reference wrappers of `std::cell::RefCell` and ensure (at runtime) that Rust borrows are allowed. ### Deriving [`FromPyObject`] [`FromPyObject`] can be automatically derived for many kinds of structs and enums if the member types themselves implement `FromPyObject`. This even includes members with a generic type `T: FromPyObject`. Derivation for empty enums, enum variants and structs is not supported. ### Deriving [`FromPyObject`] for structs The derivation generates code that will attempt to access the attribute `my_string` on the Python object, i.e. `obj.getattr("my_string")`, and call `extract()` on the attribute. ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] struct RustyStruct { my_string: String, } # # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let module = PyModule::from_code( # py, # c_str!("class Foo: # def __init__(self): # self.my_string = 'test'"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` By setting the `#[pyo3(item)]` attribute on the field, PyO3 will attempt to extract the value by calling the `get_item` method on the Python object. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item)] my_string: String, } # # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let dict = PyDict::new(py); # dict.set_item("my_string", "test")?; # # let rustystruct: RustyStruct = dict.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` The argument passed to `getattr` and `get_item` can also be configured: ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item("key"))] string_in_mapping: String, #[pyo3(attribute("name"))] string_attr: String, } # # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.name = 'test' # self['key'] = 'test2'"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.string_attr, "test"); # assert_eq!(rustystruct.string_in_mapping, "test2"); # # Ok(()) # }) # } ``` This tries to extract `string_attr` from the attribute `name` and `string_in_mapping` from a mapping with the key `"key"`. The arguments for `attribute` are restricted to non-empty string literals while `item` can take any valid literal that implements `ToBorrowedObject`. You can use `#[pyo3(from_item_all)]` on a struct to extract every field with `get_item` method. In this case, you can't use `#[pyo3(attribute)]` or barely use `#[pyo3(item)]` on any field. However, using `#[pyo3(item("key"))]` to specify the key for a field is still allowed. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] #[pyo3(from_item_all)] struct RustyStruct { foo: String, bar: String, #[pyo3(item("foobar"))] baz: String, } # # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let py_dict = py.eval(pyo3::ffi::c_str!("{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}"), None, None)?; # let rustystruct: RustyStruct = py_dict.extract()?; # assert_eq!(rustystruct.foo, "foo"); # assert_eq!(rustystruct.bar, "bar"); # assert_eq!(rustystruct.baz, "foobar"); # # Ok(()) # }) # } ``` ### Deriving [`FromPyObject`] for tuple structs Tuple structs are also supported but do not allow customizing the extraction. The input is always assumed to be a Python tuple with the same length as the Rust type, the `n`th field is extracted from the `n`th item in the Python tuple. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple(String, String); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let tuple = PyTuple::new(py, vec!["test", "test2"])?; # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!(rustytuple.0, "test"); # assert_eq!(rustytuple.1, "test2"); # # Ok(()) # }) # } ``` Tuple structs with a single field are treated as wrapper types which are described in the following section. To override this behaviour and ensure that the input is in fact a tuple, specify the struct as ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple((String,)); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let tuple = PyTuple::new(py, vec!["test"])?; # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!((rustytuple.0).0, "test"); # # Ok(()) # }) # } ``` ### Deriving [`FromPyObject`] for wrapper types The `pyo3(transparent)` attribute can be used on structs with exactly one field. This results in extracting directly from the input object, i.e. `obj.extract()`, rather than trying to access an item or attribute. This behaviour is enabled per default for newtype structs and tuple-variants with a single field. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTransparentTupleStruct(String); #[derive(FromPyObject)] #[pyo3(transparent)] struct RustyTransparentStruct { inner: String, } # use pyo3::types::PyString; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # let s = PyString::new(py, "test"); # # let tup: RustyTransparentTupleStruct = s.extract()?; # assert_eq!(tup.0, "test"); # # let stru: RustyTransparentStruct = s.extract()?; # assert_eq!(stru.inner, "test"); # # Ok(()) # }) # } ``` ### Deriving [`FromPyObject`] for enums The `FromPyObject` derivation for enums generates code that tries to extract the variants in the order of the fields. As soon as a variant can be extracted successfully, that variant is returned. This makes it possible to extract Python union types like `str | int`. The same customizations and restrictions described for struct derivations apply to enum variants, i.e. a tuple variant assumes that the input is a Python tuple, and a struct variant defaults to extracting fields as attributes but can be configured in the same manner. The `transparent` attribute can be applied to single-field-variants. ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum<'py> { Int(usize), // input is a positive int String(String), // input is a string IntTuple(usize, usize), // input is a 2-tuple with positive ints StringIntTuple(String, usize), // input is a 2-tuple with String and int Coordinates3d { // needs to be in front of 2d x: usize, y: usize, z: usize, }, Coordinates2d { // only gets checked if the input did not have `z` #[pyo3(attribute("x"))] a: usize, #[pyo3(attribute("y"))] b: usize, }, #[pyo3(transparent)] CatchAll(Bound<'py, PyAny>), // This extraction never fails } # # use pyo3::types::{PyBytes, PyString}; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # { # let thing = 42_u8.into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = PyString::new(py, "text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # "text", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = (32_u8, 73_u8).into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # (32, 73), # match rust_thing { # RustyEnum::IntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = ("foo", 73_u8).into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # (String::from("foo"), 73), # match rust_thing { # RustyEnum::StringIntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.x = 0 # self.y = 1 # self.z = 2"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (0, 1, 2), # match rust_thing { # RustyEnum::Coordinates3d { x, y, z } => (x, y, z), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.x = 3 # self.y = 4"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (3, 4), # match rust_thing { # RustyEnum::Coordinates2d { a, b } => (a, b), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = PyBytes::new(py, b"text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # b"text", # match rust_thing { # RustyEnum::CatchAll(ref i) => i.cast::()?.as_bytes(), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # Ok(()) # }) # } ``` If none of the enum variants match, a `PyTypeError` containing the names of the tested variants is returned. The names reported in the error message can be customized through the `#[pyo3(annotation = "name")]` attribute, e.g. to use conventional Python type names: ```rust use pyo3::prelude::*; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum { #[pyo3(transparent, annotation = "str")] String(String), #[pyo3(transparent, annotation = "int")] Int(isize), } # # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # { # let thing = 42_u8.into_pyobject(py)?; # let rust_thing: RustyEnum = thing.extract()?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = "foo".into_pyobject(py)?; # let rust_thing: RustyEnum = thing.extract()?; # # assert_eq!( # "foo", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = b"foo".into_pyobject(py)?; # let error = thing.extract::().unwrap_err(); # assert!(error.is_instance_of::(py)); # } # # Ok(()) # }) # } ``` If the input is neither a string nor an integer, the error message will be: `"'' cannot be cast as 'str | int'"`. ### `#[derive(FromPyObject)]` Container Attributes - `pyo3(transparent)` - extract the field directly from the object as `obj.extract()` instead of `get_item()` or `getattr()` - Newtype structs and tuple-variants are treated as transparent per default. - only supported for single-field structs and enum variants - `pyo3(annotation = "name")` - changes the name of the failed variant in the generated error message in case of failure. - e.g. `pyo3("int")` reports the variant's type as `int`. - only supported for enum variants - `pyo3(rename_all = "...")` - renames all attributes/item keys according to the specified renaming rule - Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". - fields with an explicit renaming via `attribute(...)`/`item(...)` are not affected ### `#[derive(FromPyObject)]` Field Attributes - `pyo3(attribute)`, `pyo3(attribute("name"))` - retrieve the field from an attribute, possibly with a custom name specified as an argument - argument must be a string-literal. - `pyo3(item)`, `pyo3(item("key"))` - retrieve the field from a mapping, possibly with the custom key specified as an argument. - can be any literal that implements `ToBorrowedObject` - `pyo3(from_py_with = ...)` - apply a custom function to convert the field from Python the desired Rust type. - the argument must be the path to the function. - the function signature must be `fn(&Bound) -> PyResult` where `T` is the Rust type of the argument. - `pyo3(default)`, `pyo3(default = ...)` - if the argument is set, uses the given default value. - in this case, the argument must be a Rust expression returning a value of the desired Rust type. - if the argument is not set, [`Default::default`](https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default) is used. - note that the default value is only used if the field is not set. If the field is set and the conversion function from Python to Rust fails, an exception is raised and the default value is not used. - this attribute is only supported on named fields. For example, the code below applies the given conversion function on the `"value"` dict item to compute its length or fall back to the type default value (0): ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item("value"), default, from_py_with = Bound::<'_, PyAny>::len)] len: usize, #[pyo3(item)] other: usize, } # # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::attach(|py| -> PyResult<()> { # // Filled case # let dict = PyDict::new(py); # dict.set_item("value", (1,)).unwrap(); # dict.set_item("other", 1).unwrap(); # let result = dict.extract::()?; # assert_eq!(result.len, 1); # assert_eq!(result.other, 1); # # // Empty case # let dict = PyDict::new(py); # dict.set_item("other", 1).unwrap(); # let result = dict.extract::()?; # assert_eq!(result.len, 0); # assert_eq!(result.other, 1); # Ok(()) # }) # } ``` ### ⚠ Phase-Out of `FromPyObject` blanket implementation for cloneable PyClasses ⚠ Historically PyO3 has provided a blanket implementation for `#[pyclass]` types that also implement `Clone`, to allow extraction of such types by value. Over time this has turned out problematic for a few reasons, the major one being the prevention of custom conversions by downstream crates if their type is `Clone`. Over the next few releases the blanket implementation is gradually phased out, and eventually replaced by an opt-in option. As a first step of this migration a new `skip_from_py_object` option for `#[pyclass]` was introduced, to opt-out of the blanket implementation and allow downstream users to provide their own implementation: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass(skip_from_py_object)] // opt-out of the PyO3 FromPyObject blanket #[derive(Clone)] struct Number(i32); impl<'py> FromPyObject<'_, 'py> for Number { type Error = PyErr; fn extract(obj: pyo3::Borrowed<'_, 'py, pyo3::PyAny>) -> Result { if let Ok(obj) = obj.cast::() { // first try extraction via class object Ok(obj.borrow().clone()) } else { obj.extract::().map(Self) // otherwise try integer directly } } } ``` As a second step the `from_py_object` option was introduced. This option also opts-out of the blanket implementation and instead generates a custom `FromPyObject` implementation for the pyclass which is functionally equivalent to the blanket. ## `IntoPyObject` The [`IntoPyObject`] trait defines the to-python conversion for a Rust type. All types in PyO3 implement this trait, as does a `#[pyclass]` which doesn't use `extends`. This trait defines a single method, `into_pyobject()`, which returns a [`Result`] with `Ok` and `Err` types depending on the input value. For convenience, there is a companion [`IntoPyObjectExt`] trait which adds methods such as `into_py_any()` which converts the `Ok` and `Err` types to commonly used types (in the case of `into_py_any()`, `Py` and `PyErr` respectively). Occasionally you may choose to implement this for custom types which are mapped to Python types *without* having a unique python type. ### derive macro `IntoPyObject` can be implemented using our derive macro. Both `struct`s and `enum`s are supported. `struct`s will turn into a `PyDict` using the field names as keys, tuple `struct`s will turn convert into `PyTuple` with the fields in declaration order. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use std::collections::HashMap; # use std::hash::Hash; // structs convert into `PyDict` with field names as keys #[derive(IntoPyObject)] struct Struct { count: usize, obj: Py, } // tuple structs convert into `PyTuple` // lifetimes and generics are supported, the impl will be bounded by // `K: IntoPyObject, V: IntoPyObject` #[derive(IntoPyObject)] struct Tuple<'a, K: Hash + Eq, V>(&'a str, HashMap); ``` For structs with a single field (newtype pattern) the `#[pyo3(transparent)]` option can be used to forward the implementation to the inner type. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; // newtype tuple structs are implicitly `transparent` #[derive(IntoPyObject)] struct TransparentTuple(Py); #[derive(IntoPyObject)] #[pyo3(transparent)] struct TransparentStruct<'py> { inner: Bound<'py, PyAny>, // `'py` lifetime will be used as the Python lifetime } ``` For `enum`s each variant is converted according to the rules for `struct`s above. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use std::collections::HashMap; # use std::hash::Hash; #[derive(IntoPyObject)] enum Enum<'a, 'py, K: Hash + Eq, V> { // enums are supported and convert using the same TransparentTuple(Py), // rules on the variants as the structs above #[pyo3(transparent)] TransparentStruct { inner: Bound<'py, PyAny> }, Tuple(&'a str, HashMap), Struct { count: usize, obj: Py } } ``` Additionally `IntoPyObject` can be derived for a reference to a struct or enum using the `IntoPyObjectRef` derive macro. All the same rules from above apply as well. #### `#[derive(IntoPyObject)]`/`#[derive(IntoPyObjectRef)]` Field Attributes - `pyo3(into_py_with = ...)` - apply a custom function to convert the field from Rust into Python. - the argument must be the function identifier - the function signature must be `fn(Cow<'_, T>, Python<'py>) -> PyResult>` where `T` is the Rust type of the argument. - `#[derive(IntoPyObject)]` will invoke the function with `Cow::Owned` - `#[derive(IntoPyObjectRef)]` will invoke the function with `Cow::Borrowed` ```rust,no_run # use pyo3::prelude::*; # use pyo3::IntoPyObjectExt; # use std::borrow::Cow; #[derive(Clone)] struct NotIntoPy(usize); #[derive(IntoPyObject, IntoPyObjectRef)] struct MyStruct { #[pyo3(into_py_with = convert)] not_into_py: NotIntoPy, } /// Convert `NotIntoPy` into Python fn convert<'py>(not_into_py: Cow<'_, NotIntoPy>, py: Python<'py>) -> PyResult> { not_into_py.0.into_bound_py_any(py) } ``` ### manual implementation If the derive macro is not suitable for your use case, `IntoPyObject` can be implemented manually as demonstrated below. ```rust,no_run # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(Py); impl<'py> IntoPyObject<'py> for MyPyObjectWrapper { type Target = PyAny; // the Python type type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound` type Error = std::convert::Infallible; // the conversion error type, has to be convertible to `PyErr` fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.into_bound(py)) } } // equivalent to former `ToPyObject` implementations impl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper { type Target = PyAny; type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.bind_borrowed(py)) } } ``` ### `BoundObject` for conversions that may be `Bound` or `Borrowed` `IntoPyObject::into_py_object` returns either `Bound` or `Borrowed` depending on the implementation for a concrete type. For example, the `IntoPyObject` implementation for `u32` produces a `Bound<'py, PyInt>` and the `bool` implementation produces a `Borrowed<'py, 'py, PyBool>`: ```rust,no_run use pyo3::prelude::*; use pyo3::IntoPyObject; use pyo3::types::{PyBool, PyInt}; let ints: Vec = vec![1, 2, 3, 4]; let bools = vec![true, false, false, true]; Python::attach(|py| { let ints_as_pyint: Vec> = ints .iter() .map(|x| Ok(x.into_pyobject(py)?)) .collect::>() .unwrap(); let bools_as_pybool: Vec> = bools .iter() .map(|x| Ok(x.into_pyobject(py)?)) .collect::>() .unwrap(); }); ``` In this example if we wanted to combine `ints_as_pyints` and `bools_as_pybool` into a single `Vec>` to return from the `Python::attach` closure, we would have to manually convert the concrete types for the smart pointers and the python types. Instead, we can write a function that generically converts vectors of either integers or bools into a vector of `Py` using the [`BoundObject`] trait: ```rust,no_run # use pyo3::prelude::*; # use pyo3::BoundObject; # use pyo3::IntoPyObject; # let bools = vec![true, false, false, true]; # let ints = vec![1, 2, 3, 4]; fn convert_to_vec_of_pyobj<'py, T>(py: Python<'py>, the_vec: Vec) -> PyResult>> where T: IntoPyObject<'py> + Copy { the_vec.iter() .map(|x| { Ok( // Note: the below is equivalent to `x.into_py_any()` // from the `IntoPyObjectExt` trait x.into_pyobject(py) .map_err(Into::into)? .into_any() .unbind() ) }) .collect() } let vec_of_pyobjs: Vec> = Python::attach(|py| { let mut bools_as_pyany = convert_to_vec_of_pyobj(py, bools).unwrap(); let mut ints_as_pyany = convert_to_vec_of_pyobj(py, ints).unwrap(); let mut result: Vec> = vec![]; result.append(&mut bools_as_pyany); result.append(&mut ints_as_pyany); result }); ``` In the example above we used `BoundObject::into_any` and `BoundObject::unbind` to manipulate the python types and smart pointers into the result type we wanted to produce from the function. [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`IntoPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObject.html [`IntoPyObjectExt`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObjectExt.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html [`BoundObject`]: {{#PYO3_DOCS_URL}}/pyo3/instance/trait.BoundObject.html [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html pyo3-0.27.2/guide/src/conversions.md000064400000000000000000000004401046102023000153620ustar 00000000000000# Type conversions In this portion of the guide we'll talk about the mapping of Python types to Rust types offered by PyO3, as well as the traits available to perform conversions between them. See also the conversion [tables](conversions/tables.md) and [traits](conversions/traits.md). pyo3-0.27.2/guide/src/debugging.md000064400000000000000000000355711046102023000147620ustar 00000000000000# Debugging ## Macros PyO3's attributes (`#[pyclass]`, `#[pymodule]`, etc.) are [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html), which means that they rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs ``` (You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.) You can also debug classic `!`-macros by adding `-Z trace-macros`: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs ``` Note that those commands require using the nightly build of rust and may occasionally have bugs. See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate and stable version of those commands. ## Running with Valgrind Valgrind is a tool to detect memory management bugs such as memory leaks. You first need to install a debug build of Python, otherwise Valgrind won't produce usable results. In Ubuntu there's e.g. a `python3-dbg` package. Activate an environment with the debug interpreter and recompile. If you're on Linux, use `ldd` with the name of your binary and check that you're linking e.g. `libpython3.7d.so.1.0` instead of `libpython3.7.so.1.0`. [Download the suppressions file for CPython](https://raw.githubusercontent.com/python/cpython/master/Misc/valgrind-python.supp). Run Valgrind with `valgrind --suppressions=valgrind-python.supp ./my-command --with-options` ## Getting a stacktrace The best start to investigate a crash such as an segmentation fault is a backtrace. You can set `RUST_BACKTRACE=1` as an environment variable to get the stack trace on a `panic!`. Alternatively you can use a debugger such as `gdb` to explore the issue. Rust provides a wrapper, `rust-gdb`, which has pretty-printers for inspecting Rust variables. Since PyO3 uses `cdylib` for Python shared objects, it does not receive the pretty-print debug hooks in `rust-gdb` ([rust-lang/rust#96365](https://github.com/rust-lang/rust/issues/96365)). The mentioned issue contains a workaround for enabling pretty-printers in this case. - Link against a debug build of python as described in the previous chapter - Run `rust-gdb ` - Set a breakpoint (`b`) on `rust_panic` if you are investigating a `panic!` - Enter `r` to run - After the crash occurred, enter `bt` or `bt full` to print the stacktrace Often it is helpful to run a small piece of Python code to exercise a section of Rust. ```console rust-gdb --args python -c "import my_package; my_package.sum_to_string(1, 2)" ``` ## Setting breakpoints in your Rust code One of the preferred ways by developers to debug their code is by setting breakpoints. This can be achieved in PyO3 by using a debugger like `rust-gdb` or `rust-lldb` with your Python interpreter. For more information about how to use both `lldb` and `gdb` you can read the [gdb to lldb command map](https://lldb.llvm.org/use/map.html) from the lldb documentation. ### Common setup 1. Compile your extension with debug symbols: ```bash # Debug is the default for maturin, but you can explicitly ensure debug symbols with: RUSTFLAGS="-g" maturin develop # For setuptools-rust users: pip install -e . ``` > **Note**: When using debuggers, make sure that `python` resolves to an actual Python binary or symlink and not a shim script. Some tools like pyenv use shim scripts which can interfere with debugging. ### Debugger specific setup Depending on your OS and your preferences you can use two different debuggers, `rust-gdb` or `rust-lldb`. {{#tabs }} {{#tab name="Using rust-gdb" }} 1. Launch rust-gdb with the Python interpreter: ```bash rust-gdb --args python ``` 2. Once in gdb, set a breakpoint in your Rust code: ```bash (gdb) break your_module.rs:42 ``` 3. Run your Python script that imports and uses your Rust extension: ```bash # Option 1: Run an inline Python command (gdb) run -c "import your_module; your_module.your_function()" # Option 2: Run a Python script (gdb) run your_script.py # Option 3: Run pytest tests (gdb) run -m pytest tests/test_something.py::TestName ``` {{#endtab }} {{#tab name="Using rust-lldb (for macOS users)" }} 1. Start rust-lldb with Python: ```bash rust-lldb -- python ``` 2. Set breakpoints in your Rust code: ```bash (lldb) breakpoint set --file your_module.rs --line 42 ``` 3. Run your Python script: ```bash # Option 1: Run an inline Python command (lldb) run -c "import your_module; your_module.your_function()" # Option 2: Run a Python script (lldb) run your_script.py # Option 3: Run pytest tests (lldb) run -m pytest tests/test_something.py::TestName ``` {{#endtab }} {{#endtabs }} ### Using VS Code VS Code with the Rust and Python extensions provides an integrated debugging experience: 1. First, install the necessary VS Code extensions: - [Rust Analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) - [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) - [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) 2. Create a `.vscode/launch.json` file with a configuration that uses the LLDB Debug Launcher: ```json { "version": "0.2.0", "configurations": [ { "name": "Debug PyO3", "type": "lldb", "request": "attach", "program": "${workspaceFolder}/.venv/bin/python", "pid": "${command:pickProcess}", "sourceLanguages": [ "rust" ] }, { "name": "Launch Python with PyO3", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["${file}"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] }, { "name": "Debug PyO3 with Args", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["path/to/your/script.py", "arg1", "arg2"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] }, { "name": "Debug PyO3 Tests", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["-m", "pytest", "tests/your_test.py::test_function", "-v"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] } ] } ``` This configuration supports multiple debugging scenarios: - Attaching to a running Python process - Launching the currently open Python file - Running a specific script with command-line arguments - Running pytest tests 3. Set breakpoints in your Rust code by clicking in the gutter next to line numbers. 4. Start debugging: - For attaching to a running Python process: First start the process, then select the "Debug PyO3" configuration and click Start Debugging (F5). You'll be prompted to select the Python process to attach to. - For launching a Python script: Open your Python script, select the "Launch Python with PyO3" configuration and click Start Debugging (F5). - For running with arguments: Select "Debug PyO3 with Args" (remember to edit the configuration with your actual script path and arguments). - For running tests: Select "Debug PyO3 Tests" (edit the test path as needed). 5. When debugging PyO3 code: - You can inspect Rust variables and data structures - Use the debug console to evaluate expressions - Step through Rust code line by line using the step controls - Set conditional breakpoints for more complex debugging scenarios ### Advanced Debugging Configurations For advanced debugging scenarios, you might want to add environment variables or enable specific Rust debug flags: ```json { "name": "Debug PyO3 with Environment", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["${file}"], "env": { "RUST_BACKTRACE": "1", "PYTHONPATH": "${workspaceFolder}" }, "sourceLanguages": ["rust"] } ``` ### Debugging from Jupyter Notebooks For Jupyter Notebooks run from VS Code, you can use the following helper functions to automate the launch configuration: ```python from pathlib import Path import os import json import sys def update_launch_json(vscode_config_file_path=None): """Update VSCode launch.json with the correct Jupyter kernel PID. Args: vscode_config_file_path (str, optional): Path to the .vscode/launch.json file. If not provided, will use the current working directory. """ pid = get_jupyter_kernel_pid() if not pid: print("Could not determine Jupyter kernel PID.") return # Determine launch.json path if vscode_config_file_path: launch_json_path = vscode_config_file_path else: launch_json_path = os.path.join(Path(os.getcwd()), ".vscode", "launch.json") # Get Python interpreter path python_path = sys.executable # Default debugger config debug_config = { "version": "0.2.0", "configurations": [ { "name": "Debug PyO3 (Jupyter)", "type": "lldb", "request": "attach", "program": python_path, "pid": pid, "sourceLanguages": ["rust"], }, { "name": "Launch Python with PyO3", "type": "lldb", "request": "launch", "program": python_path, "args": ["${file}"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] } ], } # Create .vscode directory if it doesn't exist try: os.makedirs(os.path.dirname(launch_json_path), exist_ok=True) # If launch.json already exists, try to update it instead of overwriting if os.path.exists(launch_json_path): try: with open(launch_json_path, "r") as f: existing_config = json.load(f) # Check if our configuration already exists config_exists = False for config in existing_config.get("configurations", []): if config.get("name") == "Debug PyO3 (Jupyter)": config["pid"] = pid config["program"] = python_path config_exists = True if not config_exists: existing_config.setdefault("configurations", []).append(debug_config["configurations"][0]) debug_config = existing_config except Exception: # If reading fails, we'll just overwrite with our new configuration pass with open(launch_json_path, "w") as f: json.dump(debug_config, f, indent=4) print(f"Updated launch.json with PID: {pid} at {launch_json_path}") except Exception as e: print(f"Error updating launch.json: {e}") def get_jupyter_kernel_pid(): """Find the process ID (PID) of the running Jupyter kernel. Returns: int: The process ID of the Jupyter kernel, or None if not found. """ # Check if we're running in a Jupyter environment if 'ipykernel' in sys.modules: pid = os.getpid() print(f"Jupyter kernel PID: {pid}") return pid else: print("Not running in a Jupyter environment.") return None ``` To use these functions: 1. Run the cell containing these functions in your Jupyter notebook 2. Run `update_launch_json()` in a cell 3. In VS Code, select the "Debug PyO3 (Jupyter)" configuration and start debugging ## Thread Safety and Compiler Sanitizers PyO3 attempts to match the Rust language-level guarantees for thread safety, but that does not preclude other code outside of the control of PyO3 or buggy code managed by a PyO3 extension from creating a thread safety issue. Analyzing whether or not a piece of Rust code that uses the CPython C API is thread safe can be quite complicated, since many Python operations can lead to arbitrary Python code execution. Automated ways to discover thread safety issues can often be more fruitful than code analysis. [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) is a thread safety checking runtime that can be used to detect data races triggered by thread safety bugs or incorrect use of thread-unsafe data structures. While it can only detect data races triggered by code at runtime, if it does detect something the reports often point to exactly where the problem is happening. To use `ThreadSanitizer` with a library that depends on PyO3, you will need to install a nightly Rust toolchain, along with the `rust-src` component, since you will need to compile the Rust standard library: ```bash rustup install nightly rustup override set nightly rustup component add rust-src ``` You will also need a version of CPython compiled using LLVM/Clang with the same major version of LLVM as is currently used to compile nightly Rust. As of March 2025, Rust nightly uses LLVM 20. The [cpython_sanity docker images](https://github.com/nascheme/cpython_sanity) contain a development environment with a pre-compiled version of CPython 3.13 or 3.14 as well as optionally NumPy and SciPy, all compiled using LLVM 20 and ThreadSanitizer. After activating a nightly Rust toolchain, you can build your project using `ThreadSanitizer` with the following command: ```bash RUSTFLAGS="-Zsanitizer=thread" maturin develop -Zbuild-std --target x86_64-unknown-linux-gnu ``` If you are not running on an x86_64 Linux machine, you should replace `x86_64-unknown-linux-gnu` with the [target triple](https://doc.rust-lang.org/rustc/platform-support.html#tier-1-with-host-tools) that is appropriate for your system. You can also replace `maturin develop` with `cargo test` to run `cargo` tests. Note that `cargo` runs tests in a thread pool, so `cargo` tests can be a good way to find thread safety issues. You can also replace `-Zsanitizer=thread` with `-Zsanitizer=address` or any of the other sanitizers that are [supported by Rust](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html). Note that you'll need to build CPython from source with the appropriate [configure script flags](https://docs.python.org/3/using/configure.html#cmdoption-with-address-sanitizer) to use the same sanitizer environment as you want to use for your Rust code. pyo3-0.27.2/guide/src/ecosystem/async-await.md000064400000000000000000000025061046102023000172520ustar 00000000000000# Using `async` and `await` *`async`/`await` support is currently being integrated in PyO3. See the [dedicated documentation](../async-await.md)* If you are working with a Python library that makes use of async functions or wish to provide Python bindings for an async Rust library, [`pyo3-async-runtimes`](https://github.com/PyO3/pyo3-async-runtimes) likely has the tools you need. It provides conversions between async functions in both Python and Rust and was designed with first-class support for popular Rust runtimes such as [`tokio`](https://tokio.rs/) and [`async-std`](https://async.rs/). In addition, all async Python code runs on the default `asyncio` event loop, so `pyo3-async-runtimes` should work just fine with existing Python libraries. ## Additional Information - Managing event loop references can be tricky with `pyo3-async-runtimes`. See [Event Loop References](https://docs.rs/pyo3-async-runtimes/#event-loop-references-and-contextvars) in the API docs to get a better intuition for how event loop references are managed in this library. - Testing `pyo3-async-runtimes` libraries and applications requires a custom test harness since Python requires control over the main thread. You can find a testing guide in the [API docs for the `testing` module](https://docs.rs/pyo3-async-runtimes/latest/pyo3_async_runtimes/testing) pyo3-0.27.2/guide/src/ecosystem/logging.md000064400000000000000000000062121046102023000164560ustar 00000000000000# Logging It is desirable if both the Python and Rust parts of the application end up logging using the same configuration into the same place. This section of the guide briefly discusses how to connect the two languages' logging ecosystems together. The recommended way for Python extension modules is to configure Rust's logger to send log messages to Python using the `pyo3-log` crate. For users who want to do the opposite and send Python log messages to Rust, see the note at the end of this guide. ## Using `pyo3-log` to send Rust log messages to Python The [pyo3-log] crate allows sending the messages from the Rust side to Python's [logging] system. This is mostly suitable for writing native extensions for Python programs. Use [`pyo3_log::init`][init] to install the logger in its default configuration. It's also possible to tweak its configuration (mostly to tune its performance). ```rust,no_run #[pyo3::pymodule] mod my_module { use log::info; use pyo3::prelude::*; #[pyfunction] fn log_something() { // This will use the logger installed in `my_module` to send the `info` // message to the Python logging facilities. info!("Something!"); } #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { // A good place to install the Rust -> Python logger. pyo3_log::init(); } } ``` Then it is up to the Python side to actually output the messages somewhere. ```python import logging import my_module FORMAT = '%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s' logging.basicConfig(format=FORMAT) logging.getLogger().setLevel(logging.INFO) my_module.log_something() ``` It is important to initialize the Python loggers first, before calling any Rust functions that may log. This limitation can be worked around if it is not possible to satisfy, read the documentation about [caching]. ## The Python to Rust direction To have python logs be handled by Rust, one need only register a rust function to handle logs emitted from the core python logging module. This has been implemented within the [pyo3-pylogger] crate. ```rust,no_run use log::{info, warn}; use pyo3::prelude::*; fn main() -> PyResult<()> { // register the host handler with python logger, providing a logger target // set the name here to something appropriate for your application pyo3_pylogger::register("example_application_py_logger"); // initialize up a logger env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); // Log some messages from Rust. info!("Just some normal information!"); warn!("Something spooky happened!"); // Log some messages from Python Python::attach(|py| { py.run( " import logging logging.error('Something bad happened') ", None, None, ) }) } ``` [logging]: https://docs.python.org/3/library/logging.html [pyo3-log]: https://crates.io/crates/pyo3-log [init]: https://docs.rs/pyo3-log/*/pyo3_log/fn.init.html [caching]: https://docs.rs/pyo3-log/*/pyo3_log/#performance-filtering-and-caching [pyo3-pylogger]: https://crates.io/crates/pyo3-pylogger pyo3-0.27.2/guide/src/ecosystem/tracing.md000064400000000000000000000112341046102023000164570ustar 00000000000000# Tracing Python projects that write extension modules for performance reasons may want to tap into [Rust's `tracing` ecosystem] to gain insight into the performance of their extension module. This section of the guide describes a few crates that provide ways to do that. They build on [`tracing_subscriber`][tracing-subscriber] and require code changes in both Python and Rust to integrate. Note that each extension module must configure its own `tracing` integration; one extension module will not see `tracing` data from a different module. ## `pyo3-tracing-subscriber` ([documentation][pyo3-tracing-subscriber-docs]) [`pyo3-tracing-subscriber`][pyo3-tracing-subscriber] provides a way for Python projects to configure `tracing_subscriber`. It exposes a few `tracing_subscriber` layers: - `tracing_subscriber::fmt` for writing human-readable output to file or stdout - `opentelemetry-stdout` for writing OTLP output to file or stdout - `opentelemetry-otlp` for writing OTLP output to an OTLP endpoint The extension module must call [`pyo3_tracing_subscriber::add_submodule`][add-submodule] to export the Python classes needed to configure and initialize `tracing`. On the Python side, use the `Tracing` context manager to initialize tracing and run Rust code inside the context manager's block. `Tracing` takes a `GlobalTracingConfig` instance describing the layers to be used. See [the README on crates.io][pyo3-tracing-subscriber] for example code. ## `pyo3-python-tracing-subscriber` ([documentation][pyo3-python-tracing-subscriber-docs]) The similarly-named [`pyo3-python-tracing-subscriber`][pyo3-python-tracing-subscriber] implements a shim in Rust that forwards `tracing` data to a `Layer` implementation defined in and passed in from Python. There are many ways an extension module could integrate `pyo3-python-tracing-subscriber` but a simple one may look something like this: ```rust,no_run #[tracing::instrument] #[pyfunction] fn fibonacci(index: usize, use_memoized: bool) -> PyResult { // ... } #[pyfunction] pub fn initialize_tracing(py_impl: Bound<'_, PyAny>) { tracing_subscriber::registry() .with(pyo3_python_tracing_subscriber::PythonCallbackLayerBridge::new(py_impl)) .init(); } ``` The extension module must provide some way for Python to pass in one or more Python objects that implement [the `Layer` interface]. Then it should construct [`pyo3_python_tracing_subscriber::PythonCallbackLayerBridge`][PythonCallbackLayerBridge] instances with each of those Python objects and initialize `tracing_subscriber` as shown above. The Python objects implement a modified version of the `Layer` interface: - `on_new_span()` may return some state that will stored inside the Rust span - other callbacks will be given that state as an additional positional argument A dummy `Layer` implementation may look like this: ```python import rust_extension class MyPythonLayer: def __init__(self): pass # `on_new_span` can return some state def on_new_span(self, span_attrs: str, span_id: str) -> int: print(f"[on_new_span]: {span_attrs} | {span_id}") return random.randint(1, 1000) # The state from `on_new_span` is passed back into other trait methods def on_event(self, event: str, state: int): print(f"[on_event]: {event} | {state}") def on_close(self, span_id: str, state: int): print(f"[on_close]: {span_id} | {state}") def on_record(self, span_id: str, values: str, state: int): print(f"[on_record]: {span_id} | {values} | {state}") def main(): rust_extension.initialize_tracing(MyPythonLayer()) print("10th fibonacci number: ", rust_extension.fibonacci(10, True)) ``` `pyo3-python-tracing-subscriber` has [working examples] showing both the Rust side and the Python side of an integration. [pyo3-tracing-subscriber]: https://crates.io/crates/pyo3-tracing-subscriber [pyo3-tracing-subscriber-docs]: https://docs.rs/pyo3-tracing-subscriber [add-submodule]: https://docs.rs/pyo3-tracing-subscriber/*/pyo3_tracing_subscriber/fn.add_submodule.html [pyo3-python-tracing-subscriber]: https://crates.io/crates/pyo3-python-tracing-subscriber [pyo3-python-tracing-subscriber-docs]: https://docs.rs/pyo3-python-tracing-subscriber [PythonCallbackLayerBridge]: https://docs.rs/pyo3-python-tracing-subscriber/*/pyo3_python_tracing_subscriber/struct.PythonCallbackLayerBridge.html [working examples]: https://github.com/getsentry/pyo3-python-tracing-subscriber/tree/main/demo [Rust's `tracing` ecosystem]: https://crates.io/crates/tracing [tracing-subscriber]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/ [the `Layer` interface]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/layer/trait.Layer.html pyo3-0.27.2/guide/src/ecosystem.md000064400000000000000000000006031046102023000150260ustar 00000000000000# The PyO3 ecosystem This portion of the guide is dedicated to crates which are external to the main PyO3 project and provide additional functionality you might find useful. Because these projects evolve independently of the PyO3 repository the content of these articles may fall out of date over time; please file issues on the PyO3 GitHub to alert maintainers when this is the case. pyo3-0.27.2/guide/src/exception.md000064400000000000000000000117141046102023000150160ustar 00000000000000# Python exceptions ## Defining a new exception Use the [`create_exception!`] macro: ```rust use pyo3::create_exception; create_exception!(module, MyError, pyo3::exceptions::PyException); ``` - `module` is the name of the containing module. - `MyError` is the name of the new exception type. For example: ```rust use pyo3::prelude::*; use pyo3::create_exception; use pyo3::types::IntoPyDict; use pyo3::exceptions::PyException; create_exception!(mymodule, CustomError, PyException); # fn main() -> PyResult<()> { Python::attach(|py| { let ctx = [("CustomError", py.get_type::())].into_py_dict(py)?; pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\"" ); pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); # Ok(()) }) # } ``` When using PyO3 to create an extension module, you can add the new exception to the module like this, so that it is importable from Python: ```rust,no_run # fn main() {} use pyo3::prelude::*; use pyo3::exceptions::PyException; pyo3::create_exception!(mymodule, CustomError, PyException); #[pymodule] mod mymodule { #[pymodule_export] use super::CustomError; // ... other elements added to module ... } ``` ## Raising an exception As described in the [function error handling](./function/error-handling.md) chapter, to raise an exception from a `#[pyfunction]` or `#[pymethods]`, return an `Err(PyErr)`. PyO3 will automatically raise this exception for you when returning the result to Python. You can also manually write and fetch errors in the Python interpreter's global state: ```rust use pyo3::{Python, PyErr}; use pyo3::exceptions::PyTypeError; Python::attach(|py| { PyTypeError::new_err("Error").restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); }); ``` ## Checking exception types Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) method to check an object's type. In PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing. ```rust,no_run use pyo3::prelude::*; use pyo3::types::{PyBool, PyList}; # fn main() -> PyResult<()> { Python::attach(|py| { assert!(PyBool::new(py, true).is_instance_of::()); let list = PyList::new(py, &[1, 2, 3, 4])?; assert!(!list.is_instance_of::()); assert!(list.is_instance_of::()); # Ok(()) }) # } ``` To check the type of an exception, you can similarly do: ```rust,no_run # use pyo3::exceptions::PyTypeError; # use pyo3::prelude::*; # Python::attach(|py| { # let err = PyTypeError::new_err(()); err.is_instance_of::(py); # }); ``` ## Using exceptions defined in Python code It is possible to use an exception defined in Python code as a native Rust type. The [`import_exception!`] macro allows importing a specific exception class and defines a Rust type for that exception. ```rust,no_run #![allow(dead_code)] use pyo3::prelude::*; mod io { pyo3::import_exception!(io, UnsupportedOperation); } fn tell(file: &Bound<'_, PyAny>) -> PyResult { match file.call_method0("tell") { Err(_) => Err(io::UnsupportedOperation::new_err("not supported: tell")), Ok(x) => x.extract::(), } } ``` [`pyo3::exceptions`]({{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html) defines exceptions for several standard library modules. ## Creating more complex exceptions If you need to create an exception with more complex behavior, you can also manually create a subclass of `PyException`: ```rust #![allow(dead_code)] # #[cfg(any(not(feature = "abi3")))] { use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::exceptions::PyException; #[pyclass(extends=PyException)] struct CustomError { #[pyo3(get)] url: String, #[pyo3(get)] message: String, } #[pymethods] impl CustomError { #[new] fn new(url: String, message: String) -> Self { Self { url, message } } } # fn main() -> PyResult<()> { Python::attach(|py| { let ctx = [("CustomError", py.get_type::())].into_py_dict(py)?; pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\", repr(CustomError)" ); pyo3::py_run!(py, *ctx, "assert CustomError('https://example.com', 'something went bad').args == ('https://example.com', 'something went bad')"); pyo3::py_run!(py, *ctx, "assert CustomError('https://example.com', 'something went bad').url == 'https://example.com'"); # Ok(()) }) # } # } ``` Note that this is not possible when the ``abi3`` feature is enabled, as that prevents subclassing ``PyException``. [`create_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.create_exception.html [`import_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.import_exception.html [`PyAny::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance [`PyAny::is_instance_of`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance_of pyo3-0.27.2/guide/src/faq.md000064400000000000000000000222771046102023000135750ustar 00000000000000# Frequently Asked Questions and troubleshooting Sorry that you're having trouble using PyO3. If you can't find the answer to your problem in the list below, you can also reach out for help on [GitHub Discussions](https://github.com/PyO3/pyo3/discussions) and on [Discord](https://discord.gg/33kcChzH7f). ## I'm experiencing deadlocks using PyO3 with `std::sync::OnceLock`, `std::sync::LazyLock`, `lazy_static`, and `once_cell` `OnceLock`, `LazyLock`, and their thirdparty predecessors use blocking to ensure only one thread ever initializes them. Because the Python interpreter can introduce additional locks (the Python GIL and GC can both require all other threads to pause) this can lead to deadlocks in the following way: 1. A thread (thread A) which is attached to the Python interpreter starts initialization of a `OnceLock` value. 2. The initialization code calls some Python API which temporarily detaches from the interpreter e.g. `Python::import`. 3. Another thread (thread B) attaches to the Python interpreter and attempts to access the same `OnceLock` value. 4. Thread B is blocked, because it waits for `OnceLock`'s initialization to lock to release. 5. On non-free-threaded Python, thread A is now also blocked, because it waits to re-attach to the interpreter (by taking the GIL which thread B still holds). 6. Deadlock. PyO3 provides a struct [`PyOnceLock`] which implements a single-initialization API based on these types that avoids deadlocks. You can also make use of the [`OnceExt`] and [`OnceLockExt`] extension traits that enable using the standard library types for this purpose by providing new methods for these types that avoid the risk of deadlocking with the Python interpreter. This means they can be used in place of other choices when you are experiencing the deadlock described above. See the documentation for [`PyOnceLock`] and [`OnceExt`] for further details and an example how to use them. [`PyOnceLock`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.PyOnceLock.html [`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html [`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html ## I can't run `cargo test`; or I can't build in a Cargo workspace: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError" Currently, [#340](https://github.com/PyO3/pyo3/issues/340) causes `cargo test` to fail with linking errors when the `extension-module` feature is activated. Linking errors can also happen when building in a cargo workspace where a different crate also uses PyO3 (see [#2521](https://github.com/PyO3/pyo3/issues/2521)). For now, there are three ways we can work around these issues. 1. Make the `extension-module` feature optional. Build with `maturin develop --features "extension-module"` ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] ``` 2. Make the `extension-module` feature optional and default. Run tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` 3. If you are using a [`pyproject.toml`](https://maturin.rs/metadata.html) file to control maturin settings, add the following section: ```toml [tool.maturin] features = ["pyo3/extension-module"] # Or for maturin 0.12: # cargo-extra-args = ["--features", "pyo3/extension-module"] ``` ## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory The Rust book suggests to [put integration tests inside a `tests/` directory](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests). For a PyO3 `extension-module` project where the `crate-type` is set to `"cdylib"` in your `Cargo.toml`, the compiler won't be able to find your crate and will display errors such as `E0432` or `E0463`: ```text error[E0432]: unresolved import `my_crate` --> tests/test_my_crate.rs:1:5 | 1 | use my_crate; | ^^^^^^^^^^^^ no external crate `my_crate` ``` The best solution is to make your crate types include both `rlib` and `cdylib`: ```toml # Cargo.toml [lib] crate-type = ["cdylib", "rlib"] ``` ## Ctrl-C doesn't do anything while my Rust code is executing This is because Ctrl-C raises a SIGINT signal, which is handled by the calling Python process by simply setting a flag to action upon later. This flag isn't checked while Rust code called from Python is executing, only once control returns to the Python interpreter. You can give the Python interpreter a chance to process the signal properly by calling `Python::check_signals`. It's good practice to call this function regularly if you have a long-running Rust function so that your users can cancel it. ## `#[pyo3(get)]` clones my field You may have a nested struct similar to this: ```rust,no_run # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct Inner {/* fields omitted */} #[pyclass] struct Outer { #[pyo3(get)] inner: Inner, } #[pymethods] impl Outer { #[new] fn __new__() -> Self { Self { inner: Inner {} } } } ``` When Python code accesses `Outer`'s field, PyO3 will return a new object on every access (note that their addresses are different): ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" ``` ```text AssertionError: a: b: ``` This can be especially confusing if the field is mutable, as getting the field and then mutating it won't persist - you'll just get a fresh clone of the original on the next access. Unfortunately Python and Rust don't agree about ownership - if PyO3 gave out references to (possibly) temporary Rust objects to Python code, Python code could then keep that reference alive indefinitely. Therefore returning Rust objects requires cloning. If you don't want that cloning to happen, a workaround is to allocate the field on the Python heap and store a reference to that, by using [`Py<...>`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html): ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct Inner {/* fields omitted */} #[pyclass] struct Outer { inner: Py, } #[pymethods] impl Outer { #[new] fn __new__(py: Python<'_>) -> PyResult { Ok(Self { inner: Py::new(py, Inner {})?, }) } #[getter] fn inner(&self, py: Python<'_>) -> Py { self.inner.clone_ref(py) } } ``` This time `a` and `b` *are* the same object: ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" print(f"a: {a}\nb: {b}") ``` ```text a: b: ``` The downside to this approach is that any Rust code working on the `Outer` struct potentially has to attach to the Python interpreter to do anything with the `inner` field. (If `Inner` is `#[pyclass(frozen)]` and implements `Sync`, then `Py::get` may be used to access the `Inner` contents from `Py` without needing to attach to the interpreter.) ## I want to use the `pyo3` crate re-exported from dependency but the proc-macros fail All PyO3 proc-macros (`#[pyclass]`, `#[pyfunction]`, `#[derive(FromPyObject)]` and so on) expect the `pyo3` crate to be available under that name in your crate root, which is the normal situation when `pyo3` is a direct dependency of your crate. However, when the dependency is renamed, or your crate only indirectly depends on `pyo3`, you need to let the macro code know where to find the crate. This is done with the `crate` attribute: ```rust,no_run # use pyo3::prelude::*; # pub extern crate pyo3; # mod reexported { pub use ::pyo3; } # #[allow(dead_code)] #[pyclass] #[pyo3(crate = "reexported::pyo3")] struct MyClass; ``` ## I'm trying to call Python from Rust but I get `STATUS_DLL_NOT_FOUND` or `STATUS_ENTRYPOINT_NOT_FOUND` This happens on Windows when linking to the python DLL fails or the wrong one is linked. The Python DLL on Windows will usually be called something like: - `python3X.dll` for Python 3.X, e.g. `python310.dll` for Python 3.10 - `python3.dll` when using PyO3's `abi3` feature The DLL needs to be locatable using the [Windows DLL search order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-unpackaged-apps). Some ways to achieve this are: - Put the Python DLL in the same folder as your build artifacts - Add the directory containing the Python DLL to your `PATH` environment variable, for example `C:\Users\\AppData\Local\Programs\Python\Python310` - If this happens when you are *distributing* your program, consider using [PyOxidizer](https://github.com/indygreg/PyOxidizer) to package it with your binary. If the wrong DLL is linked it is possible that this happened because another program added itself and its own Python DLLs to `PATH`. Rearrange your `PATH` variables to give the correct DLL priority. > **Note**: Changes to `PATH` (or any other environment variable) are not visible to existing shells. Restart it for changes to take effect. For advanced troubleshooting, [Dependency Walker](https://www.dependencywalker.com/) can be used to diagnose linking errors. pyo3-0.27.2/guide/src/features.md000064400000000000000000000370151046102023000146400ustar 00000000000000# Features reference PyO3 provides a number of Cargo features to customize functionality. This chapter of the guide provides detail on each of them. By default, only the `macros` feature is enabled. ## Features for extension module authors ### `extension-module` This feature is required when building a Python extension module using PyO3. It tells PyO3's build script to skip linking against `libpython.so` on Unix platforms, where this must not be done. See the [building and distribution](building-and-distribution.md#the-extension-module-feature) section for further detail. ### `abi3` This feature is used when building Python extension modules to create wheels which are compatible with multiple Python versions. It restricts PyO3's API to a subset of the full Python API which is guaranteed by [PEP 384](https://www.python.org/dev/peps/pep-0384/) to be forwards-compatible with future Python versions. See the [building and distribution](building-and-distribution.md#py_limited_apiabi3) section for further detail. ### The `abi3-pyXY` features (`abi3-py37`, `abi3-py38`, `abi3-py39`, `abi3-py310` and `abi3-py311`) These features are extensions of the `abi3` feature to specify the exact minimum Python version which the multiple-version-wheel will support. See the [building and distribution](building-and-distribution.md#minimum-python-version-for-abi3) section for further detail. ### `generate-import-lib` This experimental feature is used to generate import libraries for Python DLL for MinGW-w64 and MSVC (cross-)compile targets. Enabling it allows to (cross-)compile extension modules to any Windows targets without having to install the Windows Python distribution files for the target. See the [building and distribution](building-and-distribution.md#building-abi3-extensions-without-a-python-interpreter) section for further detail. ## Features for embedding Python in Rust ### `auto-initialize` This feature changes [`Python::attach`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach) to automatically initialize a Python interpreter (by calling [`Python::initialize`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.initialize)) if needed. If you do not enable this feature, you should call `Python::initialize()` before attempting to call any other Python APIs. ## Advanced Features ### `experimental-async` This feature adds support for `async fn` in `#[pyfunction]` and `#[pymethods]`. The feature has some unfinished refinements and performance improvements. To help finish this off, see [issue #1632](https://github.com/PyO3/pyo3/issues/1632) and its associated draft PRs. ### `experimental-inspect` This feature adds to the built binaries introspection data that can be then retrieved using the `pyo3-introspection` crate to generate [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html). Also, this feature adds the `pyo3::inspect` module, as well as `IntoPy::type_output` and `FromPyObject::type_input` APIs to produce Python type "annotations" for Rust types. This is a first step towards adding first-class support for generating type annotations automatically in PyO3, however work is needed to finish this off. All feedback and offers of help welcome on [issue #2454](https://github.com/PyO3/pyo3/issues/2454). ### `py-clone` This feature was introduced to ease migration. It was found that delayed reference counting (which PyO3 used historically) could not be made sound and hence `Clone`-ing an instance of `Py` is impossible when not attached to Python interpreter (it will panic). To avoid migrations introducing new panics without warning, the `Clone` implementation itself is now gated behind this feature. ### `pyo3_disable_reference_pool` This is a performance-oriented conditional compilation flag, e.g. [set via `$RUSTFLAGS`][set-configuration-options], which disabled the global reference pool and the associated overhead for the crossing the Python-Rust boundary. However, if enabled, `Drop`ping an instance of `Py` when not attached to the Python interpreter will abort the process. ### `macros` This feature enables a dependency on the `pyo3-macros` crate, which provides the procedural macros portion of PyO3's API: - `#[pymodule]` - `#[pyfunction]` - `#[pyclass]` - `#[pymethods]` - `#[derive(FromPyObject)]` It also provides the `py_run!` macro. These macros require a number of dependencies which may not be needed by users who just need PyO3 for Python FFI. Disabling this feature enables faster builds for those users, as these dependencies will not be built if this feature is disabled. > This feature is enabled by default. To disable it, set `default-features = false` for the `pyo3` entry in your Cargo.toml. ### `multiple-pymethods` This feature enables each `#[pyclass]` to have more than one `#[pymethods]` block. Most users should only need a single `#[pymethods]` per `#[pyclass]`. In addition, not all platforms (e.g. Wasm) are supported by `inventory`, which is used in the implementation of the feature. For this reason this feature is not enabled by default, meaning fewer dependencies and faster compilation for the majority of users. See [the `#[pyclass]` implementation details](class.md#implementation-details) for more information. ### `nightly` The `nightly` feature needs the nightly Rust compiler. This allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::detach` function. ### `resolve-config` The `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's build script automatically resolves a Python interpreter / build configuration. This feature is primarily useful when building PyO3 itself. By default this feature is not enabled, meaning you can freely use `pyo3-build-config` as a standalone library to read or write PyO3 build configuration files or resolve metadata about a Python interpreter. ## Optional Dependencies These features enable conversions between Python types and types from other Rust crates, enabling easy access to the rest of the Rust ecosystem. ### `anyhow` Adds a dependency on [anyhow](https://docs.rs/anyhow). Enables a conversion from [anyhow](https://docs.rs/anyhow)’s [`Error`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `arc_lock` Enables Pyo3's `MutexExt` trait for all Mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) or [`parking_lot::ReentrantMutex`](https://docs.rs/lock_api/latest/lock_api/struct.ReentrantMutex.html) and are wrapped in an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) type. Like [`Arc`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html#method.lock_arc) ### `bigdecimal` Adds a dependency on [bigdecimal](https://docs.rs/bigdecimal) and enables conversions into its [`BigDecimal`](https://docs.rs/bigdecimal/latest/bigdecimal/struct.BigDecimal.html) type. ### `bytes` Adds a dependency on [bytes](https://docs.rs/bytes/latest/bytes) and enables conversions into its [`Bytes`](https://docs.rs/bytes/latest/bytes/struct.Bytes.html) type. ### `chrono` Adds a dependency on [chrono](https://docs.rs/chrono). Enables a conversion from [chrono](https://docs.rs/chrono)'s types to python: - [TimeDelta](https://docs.rs/chrono/latest/chrono/struct.TimeDelta.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [FixedOffset](https://docs.rs/chrono/latest/chrono/offset/struct.FixedOffset.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [Utc](https://docs.rs/chrono/latest/chrono/offset/struct.Utc.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [NaiveDate](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [NaiveTime](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [DateTime](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `chrono-local` Enables conversion from and to [Local](https://docs.rs/chrono/latest/chrono/struct.Local.html) timezones. The current system timezone as determined by [`iana_time_zone::get_timezone()`](https://docs.rs/iana-time-zone/latest/iana_time_zone/fn.get_timezone.html) will be used for conversions. `chrono::DateTime` will convert from either of: - `datetime` objects with `tzinfo` equivalent to the current system timezone. - "naive" `datetime` objects (those without a `tzinfo`), as it is a convention that naive datetime objects should be treated as using the system timezone. When converting to Python, `Local` tzinfo is converted to a `zoneinfo.ZoneInfo` matching the current system timezone. ### `chrono-tz` Adds a dependency on [chrono-tz](https://docs.rs/chrono-tz). Enables conversion from and to [`Tz`](https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html). ### `either` Adds a dependency on [either](https://docs.rs/either). Enables a conversions into [either](https://docs.rs/either)’s [`Either`](https://docs.rs/either/latest/either/enum.Either.html) type. ### `eyre` Adds a dependency on [eyre](https://docs.rs/eyre). Enables a conversion from [eyre](https://docs.rs/eyre)’s [`Report`](https://docs.rs/eyre/latest/eyre/struct.Report.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `hashbrown` Adds a dependency on [hashbrown](https://docs.rs/hashbrown) and enables conversions into its [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html) and [`HashSet`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) types. ### `indexmap` Adds a dependency on [indexmap](https://docs.rs/indexmap) and enables conversions into its [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html) type. ### `jiff-02` Adds a dependency on [jiff@0.2](https://docs.rs/jiff/0.2) and requires MSRV 1.70. Enables a conversion from [jiff](https://docs.rs/jiff)'s types to python: - [SignedDuration](https://docs.rs/jiff/0.2/jiff/struct.SignedDuration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [TimeZone](https://docs.rs/jiff/0.2/jiff/tz/struct.TimeZone.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [Offset](https://docs.rs/jiff/0.2/jiff/tz/struct.Offset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [Date](https://docs.rs/jiff/0.2/jiff/civil/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [Time](https://docs.rs/jiff/0.2/jiff/civil/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [DateTime](https://docs.rs/jiff/0.2/jiff/civil/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Zoned](https://docs.rs/jiff/0.2/jiff/struct.Zoned.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Timestamp](https://docs.rs/jiff/0.2/jiff/struct.Timestamp.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [ISOWeekDate](https://docs.rs/jiff/0.2/jiff/civil/struct.ISOWeekDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) ### `lock_api` Adds a dependency on [lock_api](https://docs.rs/lock_api) and enables Pyo3's `MutexExt` trait for all mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) and [`parking_lot::ReentrantMutex`](https://docs.rs/lock_api/latest/lock_api/struct.ReentrantMutex.html) (like `parking_lot` or `spin`). ### `num-bigint` Adds a dependency on [num-bigint](https://docs.rs/num-bigint) and enables conversions into its [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html) and [`BigUint`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html) types. ### `num-complex` Adds a dependency on [num-complex](https://docs.rs/num-complex) and enables conversions into its [`Complex`](https://docs.rs/num-complex/latest/num_complex/struct.Complex.html) type. ### `num-rational` Adds a dependency on [num-rational](https://docs.rs/num-rational) and enables conversions into its [`Ratio`](https://docs.rs/num-rational/latest/num_rational/struct.Ratio.html) type. ### `ordered-float` Adds a dependency on [ordered-float](https://docs.rs/ordered-float) and enables conversions between [ordered-float](https://docs.rs/ordered-float)'s types and Python: - [NotNan](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html) - [OrderedFloat](https://docs.rs/ordered-float/latest/ordered_float/struct.OrderedFloat.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html) ### `parking-lot` Adds a dependency on [parking_lot](https://docs.rs/parking_lot) and enables Pyo3's `OnceExt` & `MutexExt` traits for [`parking_lot::Once`](https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html) [`parking_lot::Mutex`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html) and [`parking_lot::ReentrantMutex`](https://docs.rs/parking_lot/latest/parking_lot/type.ReentrantMutex.html) types. ### `rust_decimal` Adds a dependency on [rust_decimal](https://docs.rs/rust_decimal) and enables conversions into its [`Decimal`](https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html) type. ### `time` Adds a dependency on [time](https://docs.rs/time) and requires MSRV 1.67.1. Enables conversions between [time](https://docs.rs/time)'s types and Python: - [Date](https://docs.rs/time/0.3.38/time/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [Time](https://docs.rs/time/0.3.38/time/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [OffsetDateTime](https://docs.rs/time/0.3.38/time/struct.OffsetDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [PrimitiveDateTime](https://docs.rs/time/0.3.38/time/struct.PrimitiveDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Duration](https://docs.rs/time/0.3.38/time/struct.Duration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [UtcOffset](https://docs.rs/time/0.3.38/time/struct.UtcOffset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [UtcDateTime](https://docs.rs/time/0.3.38/time/struct.UtcDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `serde` Enables (de)serialization of `Py` objects via [serde](https://serde.rs/). This allows to use [`#[derive(Serialize, Deserialize)`](https://serde.rs/derive.html) on structs that hold references to `#[pyclass]` instances ```rust,no_run # #[cfg(feature = "serde")] # #[allow(dead_code)] # mod serde_only { # use pyo3::prelude::*; # use serde::{Deserialize, Serialize}; #[pyclass] #[derive(Serialize, Deserialize)] struct Permission { name: String, } #[pyclass] #[derive(Serialize, Deserialize)] struct User { username: String, permissions: Vec>, } # } ``` ### `smallvec` Adds a dependency on [smallvec](https://docs.rs/smallvec) and enables conversions into its [`SmallVec`](https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html) type. [set-configuration-options]: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options ### `uuid` Adds a dependency on [uuid](https://docs.rs/uuid) and enables conversions into its [`Uuid`](https://docs.rs/uuid/latest/uuid/struct.Uuid.html) type. pyo3-0.27.2/guide/src/free-threading.md000064400000000000000000000424121046102023000157030ustar 00000000000000# Supporting Free-Threaded CPython CPython 3.14 declared support for the "free-threaded" build of CPython that does not rely on the [global interpreter lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (often referred to as the GIL) for thread safety. Since version 0.23, PyO3 supports building Rust extensions for the free-threaded Python build and calling into free-threaded Python from Rust. If you want more background on free-threaded Python in general, see the [what's new](https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-free-threaded-cpython) entry in the 3.13 release notes (when the "free-threaded" build was first added as an experimental mode), the [free-threading HOWTO guide](https://docs.python.org/3/howto/free-threading-extensions.html#freethreading-extensions-howto) in the CPython docs, the [extension porting guide](https://py-free-threading.github.io/porting-extensions/) in the community-maintained Python free-threading guide, and [PEP 703](https://peps.python.org/pep-0703/), which provides the technical background for the free-threading implementation in CPython. In the GIL-enabled build (the only choice before the "free-threaded" build was introduced), the global interpreter lock serializes access to the Python runtime. The GIL is therefore a fundamental limitation to parallel scaling of multithreaded Python workflows, due to [Amdahl's law](https://en.wikipedia.org/wiki/Amdahl%27s_law), because any time spent executing a parallel processing task on only one execution context fundamentally cannot be sped up using parallelism. The free-threaded build removes this limit on multithreaded Python scaling. This means it's much more straightforward to achieve parallelism using the Python [`threading`] module. If you have ever needed to use [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) to achieve a parallel speedup for some Python code, free-threading will likely allow the use of Python threads instead for the same workflow. PyO3's support for free-threaded Python will enable authoring native Python extensions that are thread-safe by construction, with much stronger safety guarantees than C extensions. Our goal is to enable ["fearless concurrency"](https://doc.rust-lang.org/book/ch16-00-concurrency.html) in the native Python runtime by building on the Rust [`Send` and `Sync`](https://doc.rust-lang.org/nomicon/send-and-sync.html) traits. This document provides advice for porting Rust code using PyO3 to run under free-threaded Python. ## Supporting free-threaded Python with PyO3 Many simple uses of PyO3, like exposing bindings for a "pure" Rust function with no side-effects or defining an immutable Python class, will likely work "out of the box" on the free-threaded build. All that will be necessary is to annotate Python modules declared by rust code in your project to declare that they support free-threaded Python, for example by declaring the module with `#[pymodule(gil_used = false)]`. More complicated `#[pyclass]` types may need to deal with thread-safety directly; there is [a dedicated section of the guide](./class/thread-safety.md) to discuss this. At a low-level, annotating a module sets the `Py_MOD_GIL` slot on modules defined by an extension to `Py_MOD_GIL_NOT_USED`, which allows the interpreter to see at runtime that the author of the extension thinks the extension is thread-safe. You should only do this if you know that your extension is thread-safe. Because of Rust's guarantees, this is already true for many extensions, however see below for more discussion about how to evaluate the thread safety of existing Rust extensions and how to think about the PyO3 API using a Python runtime with no GIL. If you do not explicitly mark that modules are thread-safe, the Python interpreter will re-enable the GIL at runtime while importing your module and print a `RuntimeWarning` with a message containing the name of the module causing it to re-enable the GIL. You can force the GIL to remain disabled by setting the `PYTHON_GIL=0` as an environment variable or passing `-Xgil=0` when starting Python (`0` means the GIL is turned off). If you are sure that all data structures exposed in a `PyModule` are thread-safe, then pass `gil_used = false` as a parameter to the `pymodule` procedural macro declaring the module or call `PyModule::gil_used` on a `PyModule` instance. For example: ```rust,no_run use pyo3::prelude::*; /// This module supports free-threaded Python #[pymodule(gil_used = false)] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { // add members to the module that you know are thread-safe Ok(()) } ``` Or for a module that is set up without using the `pymodule` macro: ```rust,no_run use pyo3::prelude::*; # #[allow(dead_code)] fn register_child_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let child_module = PyModule::new(parent_module.py(), "child_module")?; child_module.gil_used(false)?; parent_module.add_submodule(&child_module) } ``` For now you must explicitly opt in to free-threading support by annotating modules defined in your extension. In a future version of `PyO3`, we plan to make `gil_used = false` the default. See the [`string-sum`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/string-sum) example for how to declare free-threaded support using raw FFI calls for modules using single-phase initialization and the [`sequential`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/sequential) example for modules using multi-phase initialization. If you would like to use conditional compilation to trigger different code paths under the free-threaded build, you can use the `Py_GIL_DISABLED` attribute once you have configured your crate to generate the necessary build configuration data. See [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build. ## Special considerations for the free-threaded build The free-threaded interpreter does not have a GIL. Many existing extensions providing mutable data structures relied on the GIL to lock Python objects and make interior mutability thread-safe. Calling into the CPython C API is only legal when an OS thread is explicitly attached to the interpreter runtime. In the GIL-enabled build, this happens when the GIL is acquired. In the free-threaded build there is no GIL, but the same C macros that release or acquire the GIL in the GIL-enabled build instead ask the interpreter to attach the thread to the Python runtime, and there can be many threads simultaneously attached. See [PEP 703](https://peps.python.org/pep-0703/#thread-states) for more background about how threads can be attached and detached from the interpreter runtime, in a manner analogous to releasing and acquiring the GIL in the GIL-enabled build. In the GIL-enabled build, PyO3 uses the [`Python<'py>`] type and the `'py` lifetime to signify that the global interpreter lock is held. In the freethreaded build, holding a `'py` lifetime means only that the thread is currently attached to the Python interpreter -- other threads can be simultaneously interacting with the interpreter. ### Attaching to the runtime You still need to obtain a `'py` lifetime to interact with Python objects or call into the CPython C API. If you are not yet attached to the Python runtime, you can register a thread using the [`Python::attach`] function. Threads created via the Python [`threading`] module do not need to do this, and pyo3 will handle setting up the [`Python<'py>`] token when CPython calls into your extension. ### Detaching to avoid hangs and deadlocks The free-threaded build triggers global synchronization events in the following situations: - During garbage collection in order to get a globally consistent view of reference counts and references between objects - In Python 3.13, when the first background thread is started in order to mark certain objects as immortal - When either `sys.settrace` or `sys.setprofile` are called in order to instrument running code objects and threads - During a call to `os.fork()`, to ensure a process-wide consistent state. This is a non-exhaustive list and there may be other situations in future Python versions that can trigger global synchronization events. This means that you should detach from the interpreter runtime using [`Python::detach`] in exactly the same situations as you should detach from the runtime in the GIL-enabled build: when doing long-running tasks that do not require the CPython runtime or when doing any task that needs to re-attach to the runtime (see the [guide section](parallelism.md#sharing-python-objects-between-rust-threads) that covers this). In the former case, you would observe a hang on threads that are waiting on the long-running task to complete, and in the latter case you would see a deadlock while a thread tries to attach after the runtime triggers a global synchronization event, but the spawning thread prevents the synchronization event from completing. ### Exceptions and panics for multithreaded access of mutable `pyclass` instances Data attached to `pyclass` instances is protected from concurrent access by a `RefCell`-like pattern of runtime borrow checking. Like a `RefCell`, PyO3 will raise exceptions (or in some cases panic) to enforce exclusive access for mutable borrows. It was always possible to generate panics like this in PyO3 in code that releases the GIL with [`Python::detach`] or calling a python method accepting `&self` from a `&mut self` (see [the docs on interior mutability](./class.md#bound-and-interior-mutability),) but now in free-threaded Python there are more opportunities to trigger these panics from Python because there is no GIL to lock concurrent access to mutably borrowed data from Python. The most straightforward way to trigger this problem is to use the Python [`threading`] module to simultaneously call a rust function that mutably borrows a [`pyclass`]({{#PYO3_DOCS_URL}}/pyo3/attr.pyclass.html) in multiple threads. For example, consider the following implementation: ```rust,no_run # use pyo3::prelude::*; #[pyclass] #[derive(Default)] struct ThreadIter { count: usize, } #[pymethods] impl ThreadIter { #[new] pub fn new() -> Self { Default::default() } fn __next__(&mut self, py: Python<'_>) -> usize { self.count += 1; self.count } } ``` And then if we do something like this in Python: ```python import concurrent.futures from my_module import ThreadIter i = ThreadIter() def increment(): next(i) with concurrent.futures.ThreadPoolExecutor(max_workers=16) as tpe: futures = [tpe.submit(increment) for _ in range(100)] [f.result() for f in futures] ``` We will see an exception: ```text Traceback (most recent call last) File "example.py", line 5, in next(i) RuntimeError: Already borrowed ``` We may allow user-selectable semantics for mutable pyclass definitions in a future version of PyO3, allowing some form of opt-in locking to emulate the GIL if that is needed. For now you should explicitly add locking, possibly using conditional compilation or using the critical section API, to avoid creating deadlocks with the GIL. ### Cannot build extensions using the limited API The free-threaded build uses a completely new ABI and there is not yet an equivalent to the limited API for the free-threaded ABI. That means if your crate depends on PyO3 using the `abi3` feature or an an `abi3-pyxx` feature, PyO3 will print a warning and ignore that setting when building extensions using the free-threaded interpreter. This means that if your package makes use of the ABI forward compatibility provided by the limited API to upload only one wheel for each release of your package, you will need to update your release procedure to also upload a version-specific free-threaded wheel. See [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build. ### Thread-safe single initialization To initialize data exactly once, use the [`PyOnceLock`] type, which is a close equivalent to [`std::sync::OnceLock`][`OnceLock`] that also helps avoid deadlocks by detaching from the Python interpreter when threads are blocking waiting for another thread to complete initialization. If already using [`OnceLock`] and it is impractical to replace with a [`PyOnceLock`], there is the [`OnceLockExt`] extension trait which adds [`OnceLockExt::get_or_init_py_attached`] to detach from the interpreter when blocking in the same fashion as [`PyOnceLock`]. Here is an example using [`PyOnceLock`] to single-initialize a runtime cache holding a `Py`: ```rust # use pyo3::prelude::*; use pyo3::sync::PyOnceLock; use pyo3::types::PyDict; let cache: PyOnceLock> = PyOnceLock::new(); Python::attach(|py| { // guaranteed to be called once and only once cache.get_or_init(py, || PyDict::new(py).unbind()) }); ``` In cases where a function must run exactly once, you can bring the [`OnceExt`] trait into scope. The [`OnceExt`] trait adds [`OnceExt::call_once_py_attached`] and [`OnceExt::call_once_force_py_attached`] functions to the api of `std::sync::Once`, enabling use of [`Once`] in contexts where the thread is attached to the Python interpreter. These functions are analogous to [`Once::call_once`], [`Once::call_once_force`] except they accept a [`Python<'py>`] token in addition to an `FnOnce`. All of these functions detach from the interpreter before blocking and re-attach before executing the function, avoiding deadlocks that are possible without using the PyO3 extension traits. Here the same example as above built using a [`Once`] instead of a [`PyOnceLock`]: ```rust # use pyo3::prelude::*; use std::sync::Once; use pyo3::sync::OnceExt; use pyo3::types::PyDict; struct RuntimeCache { once: Once, cache: Option> } let mut cache = RuntimeCache { once: Once::new(), cache: None }; Python::attach(|py| { // guaranteed to be called once and only once cache.once.call_once_py_attached(py, || { cache.cache = Some(PyDict::new(py).unbind()); }); }); ``` ### `GILProtected` is not exposed [`GILProtected`] is a (deprecated) PyO3 type that allows mutable access to static data by leveraging the GIL to lock concurrent access from other threads. In free-threaded Python there is no GIL, so you will need to replace this type with some other form of locking. In many cases, a type from [`std::sync::atomic`](https://doc.rust-lang.org/std/sync/atomic/) or a [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) will be sufficient. Before: ```rust # #![allow(deprecated)] # fn main() { # #[cfg(not(Py_GIL_DISABLED))] { # use pyo3::prelude::*; use pyo3::sync::GILProtected; use pyo3::types::{PyDict, PyNone}; use std::cell::RefCell; static OBJECTS: GILProtected>>> = GILProtected::new(RefCell::new(Vec::new())); Python::attach(|py| { // stand-in for something that executes arbitrary Python code let d = PyDict::new(py); d.set_item(PyNone::get(py), PyNone::get(py)).unwrap(); OBJECTS.get(py).borrow_mut().push(d.unbind()); }); # }} ``` After: ```rust # use pyo3::prelude::*; # fn main() { use pyo3::types::{PyDict, PyNone}; use std::sync::Mutex; static OBJECTS: Mutex>> = Mutex::new(Vec::new()); Python::attach(|py| { // stand-in for something that executes arbitrary Python code let d = PyDict::new(py); d.set_item(PyNone::get(py), PyNone::get(py)).unwrap(); // as with any `Mutex` usage, lock the mutex for as little time as possible // in this case, we do it just while pushing into the `Vec` OBJECTS.lock().unwrap().push(d.unbind()); }); # } ``` If you are executing arbitrary Python code while holding the lock, then you should import the [`MutexExt`] trait and use the `lock_py_attached` method instead of `lock`. This ensures that global synchronization events started by the Python runtime can proceed, avoiding possible deadlocks with the interpreter. [`GILProtected`]: https://docs.rs/pyo3/0.22/pyo3/sync/struct.GILProtected.html [`MutexExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.MutexExt.html [`Once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html [`Once::call_once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once [`Once::call_once_force`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once_force [`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html [`OnceExt::call_once_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_py_attached [`OnceExt::call_once_force_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_force_py_attached [`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html [`OnceLockExt::get_or_init_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html#tymethod.get_or_init_py_attached [`OnceLock`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html [`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach [`Python::attach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach [`Python<'py>`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html [`PyOnceLock`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.PyOnceLock.html [`threading`]: https://docs.python.org/3/library/threading.html pyo3-0.27.2/guide/src/function/error-handling.md000064400000000000000000000221031046102023000175520ustar 00000000000000# Error handling This chapter contains a little background of error handling in Rust and how PyO3 integrates this with Python exceptions. This covers enough detail to create a `#[pyfunction]` which raises Python exceptions from errors originating in Rust. There is a later section of the guide on [Python exceptions](../exception.md) which covers exception types in more detail. ## Representing Python exceptions Rust code uses the generic [`Result`] enum to propagate errors. The error type `E` is chosen by the code author to describe the possible errors which can happen. PyO3 has the [`PyErr`] type which represents a Python exception. If a PyO3 API could result in a Python exception being raised, the return type of that `API` will be [`PyResult`], which is an alias for the type `Result`. In summary: - When Python exceptions are raised and caught by PyO3, the exception will be stored in the `Err` variant of the `PyResult`. - Passing Python exceptions through Rust code then uses all the "normal" techniques such as the `?` operator, with `PyErr` as the error type. - Finally, when a `PyResult` crosses from Rust back to Python via PyO3, if the result is an `Err` variant the contained exception will be raised. (There are many great tutorials on Rust error handling and the `?` operator, so this guide will not go into detail on Rust-specific topics.) ## Raising an exception from a function As indicated in the previous section, when a `PyResult` containing an `Err` crosses from Rust to Python, PyO3 will raise the exception contained within. Accordingly, to raise an exception from a `#[pyfunction]`, change the return type `T` to `PyResult`. When the function returns an `Err` it will raise a Python exception. (Other `Result` types can be used as long as the error `E` has a `From` conversion for `PyErr`, see [custom Rust error types](#custom-rust-error-types) below.) This also works for functions in `#[pymethods]`. For example, the following `check_positive` function raises a `ValueError` when the input is negative: ```rust use pyo3::exceptions::PyValueError; use pyo3::prelude::*; #[pyfunction] fn check_positive(x: i32) -> PyResult<()> { if x < 0 { Err(PyValueError::new_err("x is negative")) } else { Ok(()) } } # # fn main(){ # Python::attach(|py|{ # let fun = pyo3::wrap_pyfunction!(check_positive, py).unwrap(); # fun.call1((-1,)).unwrap_err(); # fun.call1((1,)).unwrap(); # }); # } ``` All built-in Python exception types are defined in the [`pyo3::exceptions`] module. They have a `new_err` constructor to directly build a `PyErr`, as seen in the example above. ## Custom Rust error types PyO3 will automatically convert a `Result` returned by a `#[pyfunction]` into a `PyResult` as long as there is an implementation of `std::from::From for PyErr`. Many error types in the Rust standard library have a [`From`] conversion defined in this way. If the type `E` you are handling is defined in a third-party crate, see the section on [foreign rust error types](#foreign-rust-error-types) below for ways to work with this error. The following example makes use of the implementation of `From for PyErr` to raise exceptions encountered when parsing strings as integers: ```rust # use pyo3::prelude::*; use std::num::ParseIntError; #[pyfunction] fn parse_int(x: &str) -> Result { x.parse() } # fn main() { # Python::attach(|py| { # let fun = pyo3::wrap_pyfunction!(parse_int, py).unwrap(); # let value: usize = fun.call1(("5",)).unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` When passed a string which doesn't contain a floating-point number, the exception raised will look like the below: ```python >>> parse_int("bar") Traceback (most recent call last): File "", line 1, in ValueError: invalid digit found in string ``` As a more complete example, the following snippet defines a Rust error named `CustomIOError`. It then defines a `From for PyErr`, which returns a `PyErr` representing Python's `OSError`. Therefore, it can use this error in the result of a `#[pyfunction]` directly, relying on the conversion if it has to be propagated into a Python exception. ```rust use pyo3::exceptions::PyOSError; use pyo3::prelude::*; use std::fmt; #[derive(Debug)] struct CustomIOError; impl std::error::Error for CustomIOError {} impl fmt::Display for CustomIOError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Oh no!") } } impl std::convert::From for PyErr { fn from(err: CustomIOError) -> PyErr { PyOSError::new_err(err.to_string()) } } pub struct Connection {/* ... */} fn bind(addr: String) -> Result { if &addr == "0.0.0.0" { Err(CustomIOError) } else { Ok(Connection{ /* ... */}) } } #[pyfunction] fn connect(s: String) -> Result<(), CustomIOError> { bind(s)?; // etc. Ok(()) } fn main() { Python::attach(|py| { let fun = pyo3::wrap_pyfunction!(connect, py).unwrap(); let err = fun.call1(("0.0.0.0",)).unwrap_err(); assert!(err.is_instance_of::(py)); }); } ``` If lazy construction of the Python exception instance is desired, the [`PyErrArguments`]({{#PYO3_DOCS_URL}}/pyo3/trait.PyErrArguments.html) trait can be implemented instead of `From`. In that case, actual exception argument creation is delayed until the `PyErr` is needed. A final note is that any errors `E` which have a `From` conversion can be used with the `?` ("try") operator with them. An alternative implementation of the above `parse_int` which instead returns `PyResult` is below: ```rust use pyo3::prelude::*; fn parse_int(s: String) -> PyResult { let x = s.parse()?; Ok(x) } # # use pyo3::exceptions::PyValueError; # # fn main() { # Python::attach(|py| { # assert_eq!(parse_int(String::from("1")).unwrap(), 1); # assert_eq!(parse_int(String::from("1337")).unwrap(), 1337); # # assert!(parse_int(String::from("-1")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("foo")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("13.37")) # .unwrap_err() # .is_instance_of::(py)); # }) # } ``` ## Foreign Rust error types The Rust compiler will not permit implementation of traits for types outside of the crate where the type is defined. (This is known as the "orphan rule".) Given a type `OtherError` which is defined in third-party code, there are two main strategies available to integrate it with PyO3: - Create a newtype wrapper, e.g. `MyOtherError`. Then implement `From for PyErr` (or `PyErrArguments`), as well as `From` for `MyOtherError`. - Use Rust's Result combinators such as `map_err` to write code freely to convert `OtherError` into whatever is needed. This requires boilerplate at every usage however gives unlimited flexibility. To detail the newtype strategy a little further, the key trick is to return `Result` from the `#[pyfunction]`. This means that PyO3 will make use of `From for PyErr` to create Python exceptions while the `#[pyfunction]` implementation can use `?` to convert `OtherError` to `MyOtherError` automatically. The following example demonstrates this for some imaginary third-party crate `some_crate` with a function `get_x` returning `Result`: ```rust # mod some_crate { # pub struct OtherError(()); # impl OtherError { # pub fn message(&self) -> &'static str { "some error occurred" } # } # pub fn get_x() -> Result { Ok(5) } # } use pyo3::prelude::*; use pyo3::exceptions::PyValueError; use some_crate::{OtherError, get_x}; struct MyOtherError(OtherError); impl From for PyErr { fn from(error: MyOtherError) -> Self { PyValueError::new_err(error.0.message()) } } impl From for MyOtherError { fn from(other: OtherError) -> Self { Self(other) } } #[pyfunction] fn wrapped_get_x() -> Result { // get_x is a function returning Result let x: i32 = get_x()?; Ok(x) } # fn main() { # Python::attach(|py| { # let fun = pyo3::wrap_pyfunction!(wrapped_get_x, py).unwrap(); # let value: usize = fun.call0().unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` ## Notes In Python 3.11 and up, notes can be added to Python exceptions to provide additional debugging information when printing the exception. In PyO3, you can use the `add_note` method on `PyErr` to accomplish this functionality. [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html [`PyResult`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/type.PyResult.html [`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html [`pyo3::exceptions`]: {{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html pyo3-0.27.2/guide/src/function/signature.md000064400000000000000000000226361046102023000166530ustar 00000000000000# Function signatures The `#[pyfunction]` attribute also accepts parameters to control how the generated Python function accepts arguments. Just like in Python, arguments can be positional-only, keyword-only, or accept either. `*args` lists and `**kwargs` dicts can also be accepted. These parameters also work for `#[pymethods]` which will be introduced in the [Python Classes](../class.md) section of the guide. Like Python, by default PyO3 accepts all arguments as either positional or keyword arguments. All arguments are required by default. This behaviour can be configured by the `#[pyo3(signature = (...))]` option which allows writing a signature in Python syntax. This section of the guide goes into detail about use of the `#[pyo3(signature = (...))]` option and its related option `#[pyo3(text_signature = "...")]` ## Using `#[pyo3(signature = (...))]` For example, below is a function that accepts arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number that was passed: ```rust,no_run #[pyo3::pymodule] mod module_with_functions { use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] #[pyo3(signature = (**kwds))] fn num_kwds(kwds: Option<&Bound<'_, PyDict>>) -> usize { kwds.map_or(0, |dict| dict.len()) } } ``` Just like in Python, the following constructs can be part of the signature:: - `/`: positional-only arguments separator, each parameter defined before `/` is a positional-only parameter. - `*`: var arguments separator, each parameter defined after `*` is a keyword-only parameter. - `*args`: "args" is var args. Type of the `args` parameter has to be `&Bound<'_, PyTuple>`. - `**kwargs`: "kwargs" receives keyword arguments. The type of the `kwargs` parameter has to be `Option<&Bound<'_, PyDict>>`. - `arg=Value`: arguments with default value. If the `arg` argument is defined after var arguments, it is treated as a keyword-only argument. Note that `Value` has to be valid rust code, PyO3 just inserts it into the generated code unmodified. Example: ```rust,no_run # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } fn make_change(&mut self, num: i32) -> PyResult { self.num = num; Ok(format!("num={}", self.num)) } } ``` Arguments of type `Python` must not be part of the signature: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (lambda))] pub fn simple_python_bound_function(py: Python<'_>, lambda: Py) -> PyResult<()> { Ok(()) } ``` N.B. the position of the `/` and `*` arguments (if included) control the system of handling positional and keyword arguments. In Python: ```python import mymodule mc = mymodule.MyClass() print(mc.method(44, False, "World", 666, x=44, y=55)) print(mc.method(num=-1, name="World")) print(mc.make_change(44)) ``` Produces output: ```text num=44 (was previously=-1), py_args=(False, 'World', 666), name=Hello, py_kwargs=Some({'x': 44, 'y': 55}) num=-1 (was previously=44), py_args=(), name=World, py_kwargs=None num=44 ``` > Note: to use keywords like `struct` as a function argument, use "raw identifier" syntax `r#struct` in both the signature and the function definition: > > ```rust,no_run > # #![allow(dead_code)] > # use pyo3::prelude::*; > #[pyfunction(signature = (r#struct = "foo"))] > fn function_with_keyword(r#struct: &str) { > # let _ = r#struct; > /* ... */ > } > ``` ## Making the function signature available to Python The function signature is exposed to Python via the `__text_signature__` attribute. PyO3 automatically generates this for every `#[pyfunction]` and all `#[pymethods]` directly from the Rust function, taking into account any override done with the `#[pyo3(signature = (...))]` option. This automatic generation can only display the value of default arguments for strings, integers, boolean types, and `None`. Any other default arguments will be displayed as `...`. (`.pyi` type stub files commonly also use `...` for default arguments in the same way.) In cases where the automatically-generated signature needs adjusting, it can [be overridden](#overriding-the-generated-signature) using the `#[pyo3(text_signature)]` option.) The example below creates a function `add` which accepts two positional-only arguments `a` and `b`, where `b` has a default value of zero. ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::attach(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # # #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug? # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` The following IPython output demonstrates how this generated signature will be seen from Python tooling: ```text >>> pyo3_test.add.__text_signature__ '(a, b=..., /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` ### Overriding the generated signature The `#[pyo3(text_signature = "()")]` attribute can be used to override the default generated signature. In the snippet below, the text signature attribute is used to include the default value of `0` for the argument `b`, instead of the automatically-generated default value of `...`: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = "(a, b=0, /)")] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::attach(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` PyO3 will include the contents of the annotation unmodified as the `__text_signature__`. Below shows how IPython will now present this (see the default value of 0 for b): ```text >>> pyo3_test.add.__text_signature__ '(a, b=0, /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` If no signature is wanted at all, `#[pyo3(text_signature = None)]` will disable the built-in signature. The snippet below demonstrates use of this: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = None)] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::attach(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # assert!(fun.getattr("__text_signature__")?.is_none()); # # Ok(()) # }) # } ``` Now the function's `__text_signature__` will be set to `None`, and IPython will not display any signature in the help: ```text >>> pyo3_test.add.__text_signature__ == None True >>> pyo3_test.add? Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` ### Type annotations in the signature When the `experimental-inspect` Cargo feature is enabled, the `signature` attribute can also contain type hints: ```rust # #[cfg(feature = "experimental-inspect")] { use pyo3::prelude::*; #[pymodule] pub mod example { use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (arg: "list[int]") -> "list[int]")] fn list_of_int_identity(arg: Bound<'_, PyAny>) -> Bound<'_, PyAny> { arg } } # } ``` It enables the [work-in-progress capacity of PyO3 to autogenerate type stubs](../type-stub.md) to generate a file with the correct type hints: ```python def list_of_int_identity(arg: list[int]) -> list[int]: ... ``` instead of the generic: ```python import typing def list_of_int_identity(arg: typing.Any) -> typing.Any: ... ``` Note that currently type annotations must be written as Rust strings. pyo3-0.27.2/guide/src/function-calls.md000064400000000000000000000000331046102023000157310ustar 00000000000000# Calling Python functions pyo3-0.27.2/guide/src/function.md000064400000000000000000000263271046102023000146530ustar 00000000000000# Python functions The `#[pyfunction]` attribute is used to define a Python function from a Rust function. Once defined, the function needs to be added to a [module](./module.md). The following example defines a function called `double` in a Python module called `my_extension`: ```rust,no_run #[pyo3::pymodule] mod my_extension { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } } ``` This chapter of the guide explains full usage of the `#[pyfunction]` attribute. In this first section, the following topics are covered: - [Function options](#function-options) - [`#[pyo3(name = "...")]`](#name) - [`#[pyo3(signature = (...))]`](#signature) - [`#[pyo3(text_signature = "...")]`](#text_signature) - [`#[pyo3(pass_module)]`](#pass_module) - [`#[pyo3(warn(message = "...", category = ...))]`](#warn) - [Per-argument options](#per-argument-options) - [Advanced function patterns](#advanced-function-patterns) There are also additional sections on the following topics: - [Function Signatures](./function/signature.md) - [Error Handling](./function/error-handling.md) ## Function options The `#[pyo3]` attribute can be used to modify properties of the generated Python function. It can take any combination of the following options: - `#[pyo3(name = "...")]` Overrides the name exposed to Python. In the following example, the Rust function `no_args_py` will be added to the Python module `module_with_functions` as the Python function `no_args`: ```rust # use pyo3::prelude::*; #[pyo3::pymodule] mod module_with_functions { use pyo3::prelude::*; #[pyfunction] #[pyo3(name = "no_args")] fn no_args_py() -> usize { 42 } } # Python::attach(|py| { # let m = pyo3::wrap_pymodule!(module_with_functions)(py); # assert!(m.getattr(py, "no_args").is_ok()); # assert!(m.getattr(py, "no_args_py").is_err()); # }); ``` - `#[pyo3(signature = (...))]` Defines the function signature in Python. See [Function Signatures](./function/signature.md). - `#[pyo3(text_signature = "...")]` Overrides the PyO3-generated function signature visible in Python tooling (such as via [`inspect.signature`]). See the [corresponding topic in the Function Signatures subchapter](./function/signature.md#making-the-function-signature-available-to-python). - `#[pyo3(pass_module)]` Set this option to make PyO3 pass the containing module as the first argument to the function. It is then possible to use the module in the function body. The first argument **must** be of type `&Bound<'_, PyModule>`, `Bound<'_, PyModule>`, or `Py`. The following example creates a function `pyfunction_with_module` which returns the containing module's name (i.e. `module_with_fn`): ```rust,no_run #[pyo3::pymodule] mod module_with_fn { use pyo3::prelude::*; use pyo3::types::PyString; #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module<'py>( module: &Bound<'py, PyModule>, ) -> PyResult> { module.name() } } ``` - `#[pyo3(warn(message = "...", category = ...))]` This option is used to display a warning when the function is used in Python. It is equivalent to [`warnings.warn(message, category)`](https://docs.python.org/3/library/warnings.html#warnings.warn). The `message` parameter is a string that will be displayed when the function is called, and the `category` parameter is optional and has to be a subclass of [`Warning`](https://docs.python.org/3/library/exceptions.html#Warning). When the `category` parameter is not provided, the warning will be defaulted to [`UserWarning`](https://docs.python.org/3/library/exceptions.html#UserWarning). > Note: when used with `#[pymethods]`, this attribute does not work with `#[classattr]` nor `__traverse__` magic method. The following are examples of using the `#[pyo3(warn)]` attribute: ```rust use pyo3::prelude::*; #[pymodule] mod raising_warning_fn { use pyo3::prelude::pyfunction; use pyo3::exceptions::PyFutureWarning; #[pyfunction] #[pyo3(warn(message = "This is a warning message"))] fn function_with_warning() -> usize { 42 } #[pyfunction] #[pyo3(warn(message = "This function is warning with FutureWarning", category = PyFutureWarning))] fn function_with_warning_and_custom_category() -> usize { 42 } } # use pyo3::exceptions::{PyFutureWarning, PyUserWarning}; # use pyo3::types::{IntoPyDict, PyList}; # use pyo3::PyTypeInfo; # # fn catch_warning(py: Python<'_>, f: impl FnOnce(&Bound<'_, PyList>) -> ()) -> PyResult<()> { # let warnings = py.import("warnings")?; # let kwargs = [("record", true)].into_py_dict(py)?; # let catch_warnings = warnings # .getattr("catch_warnings")? # .call((), Some(&kwargs))?; # let list = catch_warnings.call_method0("__enter__")?.cast_into()?; # warnings.getattr("simplefilter")?.call1(("always",))?; // show all warnings # f(&list); # catch_warnings # .call_method1("__exit__", (py.None(), py.None(), py.None())) # .unwrap(); # Ok(()) # } # # macro_rules! assert_warnings { # ($py:expr, $body:expr, [$(($category:ty, $message:literal)),+] $(,)? ) => { # catch_warning($py, |list| { # $body; # let expected_warnings = [$((<$category as PyTypeInfo>::type_object($py), $message)),+]; # assert_eq!(list.len(), expected_warnings.len()); # for (warning, (category, message)) in list.iter().zip(expected_warnings) { # assert!(warning.getattr("category").unwrap().is(&category)); # assert_eq!( # warning.getattr("message").unwrap().str().unwrap().to_string_lossy(), # message # ); # } # }).unwrap(); # }; # } # # Python::attach(|py| { # assert_warnings!( # py, # { # let m = pyo3::wrap_pymodule!(raising_warning_fn)(py); # let f1 = m.getattr(py, "function_with_warning").unwrap(); # let f2 = m.getattr(py, "function_with_warning_and_custom_category").unwrap(); # f1.call0(py).unwrap(); # f2.call0(py).unwrap(); # }, # [ # (PyUserWarning, "This is a warning message"), # ( # PyFutureWarning, # "This function is warning with FutureWarning" # ) # ] # ); # }); ``` When the functions are called as the following, warnings will be displayed. ```python import warnings from raising_warning_fn import function_with_warning, function_with_warning_and_custom_category function_with_warning() function_with_warning_and_custom_category() ``` The warning output will be: ```plaintext UserWarning: This is a warning message FutureWarning: This function is warning with FutureWarning ``` ## Per-argument options The `#[pyo3]` attribute can be used on individual arguments to modify properties of them in the generated function. It can take any combination of the following options: - `#[pyo3(from_py_with = ...)]` Set this on an option to specify a custom function to convert the function argument from Python to the desired Rust type, instead of using the default `FromPyObject` extraction. The function signature must be `fn(&Bound<'_, PyAny>) -> PyResult` where `T` is the Rust type of the argument. The following example uses `from_py_with` to convert the input Python object to its length: ```rust use pyo3::prelude::*; fn get_length(obj: &Bound<'_, PyAny>) -> PyResult { obj.len() } #[pyfunction] fn object_length(#[pyo3(from_py_with = get_length)] argument: usize) -> usize { argument } # Python::attach(|py| { # let f = pyo3::wrap_pyfunction!(object_length)(py).unwrap(); # assert_eq!(f.call1((vec![1, 2, 3],)).unwrap().extract::().unwrap(), 3); # }); ``` ## Advanced function patterns ### Calling Python functions in Rust You can pass Python `def`'d functions and built-in functions to Rust functions [`PyFunction`] corresponds to regular Python functions while [`PyCFunction`] describes built-ins such as `repr()`. You can also use [`Bound<'_, PyAny>::is_callable`] to check if you have a callable object. `is_callable` will return `true` for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with [`Bound<'_, PyAny>::call`] with the args as first parameter and the kwargs (or `None`) as second parameter. There are also [`Bound<'_, PyAny>::call0`] with no args and [`Bound<'_, PyAny>::call1`] with only positional args. ### Calling Rust functions in Python The ways to convert a Rust function into a Python object vary depending on the function: - Named functions, e.g. `fn foo()`: add `#[pyfunction]` and then use [`wrap_pyfunction!`] to get the corresponding [`PyCFunction`]. - Anonymous functions (or closures), e.g. `foo: fn()` either: - use a `#[pyclass]` struct which stores the function as a field and implement `__call__` to call the stored function. - use `PyCFunction::new_closure` to create an object directly from the function. ### Accessing the FFI functions In order to make Rust functions callable from Python, PyO3 generates an `extern "C"` function whose exact signature depends on the Rust signature. (PyO3 chooses the optimal Python argument passing convention.) It then embeds the call to the Rust function inside this FFI-wrapper function. This wrapper handles extraction of the regular arguments and the keyword arguments from the input `PyObject`s. The `wrap_pyfunction` macro can be used to directly get a `Bound` given a `#[pyfunction]` and a `Bound`: `wrap_pyfunction!(rust_fun, module)`. [`Bound<'_, PyAny>::is_callable`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.is_callable [`Bound<'_, PyAny>::call`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call [`Bound<'_, PyAny>::call0`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call0 [`Bound<'_, PyAny>::call1`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call1 [`wrap_pyfunction!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.wrap_pyfunction.html [`PyFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFunction.html [`PyCFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyCFunction.html [`inspect.signature`]: https://docs.python.org/3/library/inspect.html#inspect.signature pyo3-0.27.2/guide/src/getting-started.md000064400000000000000000000147451046102023000161340ustar 00000000000000# Installation To get started using PyO3 you will need three things: a Rust toolchain, a Python environment, and a way to build. We'll cover each of these below. > If you'd like to chat to the PyO3 maintainers and other PyO3 users, consider joining the [PyO3 Discord server](https://discord.gg/33kcChzH7f). We're keen to hear about your experience getting started, so we can make PyO3 as accessible as possible for everyone! ## Rust First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.74. If you can run `rustc --version` and the version is new enough you're good to go! ## Python To use PyO3, you need at least Python 3.7. While you can simply use the default Python interpreter on your system, it is recommended to use a virtual environment. ## Virtualenvs While you can use any virtualenv manager you like, we recommend the use of `pyenv` in particular if you want to develop or test for multiple different Python versions, so that is what the examples in this book will use. The installation instructions for `pyenv` can be found [here](https://github.com/pyenv/pyenv#a-getting-pyenv). (Note: To get the `pyenv activate` and `pyenv virtualenv` commands, you will also need to install the [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv) plugin. The [pyenv installer](https://github.com/pyenv/pyenv-installer#installation--update--uninstallation) will install both together.) It can be useful to keep the sources used when installing using `pyenv` so that future debugging can see the original source files. This can be done by passing the `--keep` flag as part of the `pyenv install` command. For example: ```bash pyenv install 3.12 --keep ``` ### Building There are a number of build and Python package management systems such as [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](./building-and-distribution.md#manual-builds). We recommend the use of `maturin`, which you can install [here](https://maturin.rs/installation.html). It is developed to work with PyO3 and provides the most "batteries included" experience, especially if you are aiming to publish to PyPI. `maturin` is just a Python package, so you can add it in the same way you already install Python packages. System Python: ```bash pip install maturin --user ``` pipx: ```bash pipx install maturin ``` pyenv: ```bash pyenv activate pyo3 pip install maturin ``` poetry: ```bash poetry add -G dev maturin ``` After installation, you can run `maturin --version` to check that you have correctly installed it. ## Starting a new project First you should create the folder and virtual environment that are going to contain your new project. Here we will use the recommended `pyenv`: ```bash mkdir pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` After this, you should install your build manager. In this example, we will use `maturin`. After you've activated your virtualenv, add `maturin` to it: ```bash pip install maturin ``` Now you can initialize the new project: ```bash maturin init ``` If `maturin` is already installed, you can create a new project using that directly as well: ```bash maturin new -b pyo3 pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` ## Adding to an existing project Sadly, `maturin` cannot currently be run in existing projects, so if you want to use Python in an existing project you basically have two options: 1. Create a new project as above and move your existing code into that project 2. Manually edit your project configuration as necessary If you opt for the second option, here are the things you need to pay attention to: ## Cargo.toml Make sure that the Rust crate you want to be able to access from Python is compiled into a library. You can have a binary output as well, but the code you want to access from Python has to be in the library part. Also, make sure that the crate type is `cdylib` and add PyO3 as a dependency as so: ```toml # If you already have [package] information in `Cargo.toml`, you can ignore # this section! [package] # `name` here is name of the package. name = "pyo3_start" # these are good defaults: version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "pyo3_example" # "cdylib" is necessary to produce a shared library for Python to import from. crate-type = ["cdylib"] [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["extension-module"] } ``` ## pyproject.toml You should also create a `pyproject.toml` with the following contents: ```toml [build-system] requires = ["maturin>=1,<2"] build-backend = "maturin" [project] name = "pyo3_example" requires-python = ">=3.7" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] ``` ## Running code After this you can setup Rust code to be available in Python as below; for example, you can place this code in `src/lib.rs`: ```rust,no_run /// A Python module implemented in Rust. The name of this function must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pyo3::pymodule] mod pyo3_example { use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } } ``` Now you can run `maturin develop` to prepare the Python package, after which you can use it like so: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import pyo3_example >>> pyo3_example.sum_as_string(5, 20) '25' ``` For more instructions on how to use Python code from Rust, see the [Python from Rust](python-from-rust.md) page. ## Maturin Import Hook In development, any changes in the code would require running `maturin develop` before testing. To streamline the development process, you may want to install [Maturin Import Hook](https://github.com/PyO3/maturin-import-hook) which will run `maturin develop` automatically when the library with code changes is being imported. pyo3-0.27.2/guide/src/index.md000064400000000000000000000011511046102023000141210ustar 00000000000000# The PyO3 user guide Welcome to the PyO3 user guide! This book is a companion to [PyO3's API docs](https://docs.rs/pyo3). It contains examples and documentation to explain all of PyO3's use cases in detail. The rough order of material in this user guide is as follows: 1. Getting started 2. Wrapping Rust code for use from Python 3. How to use Python code from Rust 4. Remaining topics which go into advanced concepts in detail Please choose from the chapters on the left to jump to individual topics, or continue below to start with PyO3's README.
{{#include ../../README.md}} pyo3-0.27.2/guide/src/migration.md000064400000000000000000002633371046102023000150230ustar 00000000000000# Migrating from older PyO3 versions This guide can help you upgrade code through breaking changes from one PyO3 version to the next. For a detailed list of all changes, see the [CHANGELOG](changelog.md). ## from 0.26.* to 0.27 ### `FromPyObject` reworked for flexibility and efficiency
Click to expand With the removal of the `gil-ref` API in PyO3 0.23 it is now possible to fully split the Python lifetime `'py` and the input lifetime `'a`. This allows borrowing from the input data without extending the lifetime of being attached to the interpreter. `FromPyObject` now takes an additional lifetime `'a` describing the input lifetime. The argument type of the `extract` method changed from `&Bound<'py, PyAny>` to `Borrowed<'a, 'py, PyAny>`. This was done because `&'a Bound<'py, PyAny>` would have an implicit restriction `'py: 'a` due to the reference type. This new form was partly implemented already in 0.22 using the internal `FromPyObjectBound` trait and is now extended to all types. Most implementations can just add an elided lifetime to migrate. Additionally `FromPyObject` gained an associated type `Error`. This is the error type that can be used in case of a conversion error. During migration using `PyErr` is a good default, later a custom error type can be introduced to prevent unneccessary creation of Python exception objects and improved type safety. Before: ```rust,ignore impl<'py> FromPyObject<'py> for IpAddr { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { ... } } ``` After ```rust,ignore impl<'py> FromPyObject<'_, 'py> for IpAddr { type Error = PyErr; fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result { ... // since `Borrowed` derefs to `&Bound`, the body often // needs no changes, or adding an occasional `&` } } ``` Occasionally, more steps are necessary. For generic types, the bounds need to be adjusted. The correct bound depends on how the type is used. For simple wrapper types usually it's possible to just forward the bound. Before: ```rust,ignore struct MyWrapper(T); impl<'py, T> FromPyObject<'py> for MyWrapper where T: FromPyObject<'py> { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { ob.extract().map(MyWrapper) } } ``` After: ```rust # use pyo3::prelude::*; # #[allow(dead_code)] # pub struct MyWrapper(T); impl<'a, 'py, T> FromPyObject<'a, 'py> for MyWrapper where T: FromPyObject<'a, 'py> { type Error = T::Error; fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { obj.extract().map(MyWrapper) } } ``` Container types that need to create temporary Python references during extraction, for example extracing from a `PyList`, requires a stronger bound. For these the `FromPyObjectOwned` trait was introduced. It is automatically implemented for any type that implements `FromPyObject` and does not borrow from the input. It is intended to be used as a trait bound in these situations. Before: ```rust,ignore struct MyVec(Vec); impl<'py, T> FromPyObject<'py> for Vec where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { let mut v = MyVec(Vec::new()); for item in obj.try_iter()? { v.0.push(item?.extract::()?); } Ok(v) } } ``` After: ```rust # use pyo3::prelude::*; # #[allow(dead_code)] # pub struct MyVec(Vec); impl<'py, T> FromPyObject<'_, 'py> for MyVec where T: FromPyObjectOwned<'py> // 👈 can only extract owned values, because each `item` below // is a temporary short lived owned reference { type Error = PyErr; fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result { let mut v = MyVec(Vec::new()); for item in obj.try_iter()? { v.0.push(item?.extract::().map_err(Into::into)?); // `map_err` is needed because `?` uses `From`, not `Into` 🙁 } Ok(v) } } ``` This is very similar to `serde`s [`Deserialize`] and [`DeserializeOwned`] traits, see [here](https://serde.rs/lifetimes.html). [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html [`DeserializeOwned`]: https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html
## `.downcast()` and `DowncastError` replaced with `.cast()` and `CastError` The `.downcast()` family of functions were only available on `Bound`. In corner cases (particularly related to `.downcast_into()`) this would require use of `.as_any().downcast()` or `.into_any().downcast_into()` chains. Additionally, `DowncastError` produced Python exception messages which are not very Pythonic due to use of Rust type names in the error messages. The `.cast()` family of functions are available on all `Bound` and `Borrowed` smart pointers, whatever the type, and have error messages derived from the actual type at runtime. This produces a nicer experience for both PyO3 module authors and consumers. To migrate, replace `.downcast()` with `.cast()` and `DowncastError` with `CastError` (and similar with `.downcast_into()` / `DowncastIntoError` etc). `CastError` requires a Python `type` object (or other "classinfo" object compatible with `isinstance()`) as the second object, so in the rare case where `DowncastError` was manually constructed, small adjustments to code may apply. ## `PyTypeCheck` is now an `unsafe trait` Because `PyTypeCheck` is the trait used to guard the `.cast()` functions to treat Python objects as specific concrete types, the trait is `unsafe` to implement. This should always have been the case, it was an unfortunate omission from its original implementation which is being corrected in this release. ## from 0.25.* to 0.26 ### Rename of `Python::with_gil`, `Python::allow_threads`, and `pyo3::prepare_freethreaded_python`
Click to expand The names for these APIs were created when the global interpreter lock (GIL) was mandatory. With the introduction of free-threading in Python 3.13 this is no longer the case, and the naming has no universal meaning anymore. For this reason, we chose to rename these to more modern terminology introduced in free-threading: - `Python::with_gil` is now called `Python::attach`, it attaches a Python thread-state to the current thread. In GIL enabled builds there can only be 1 thread attached to the interpreter, in free-threading there can be more. - `Python::allow_threads` is now called `Python::detach`, it detaches a previously attached thread-state. - `pyo3::prepare_freethreaded_python` is now called `Python::initialize`.
### Deprecation of `PyObject` type alias
Click to expand The type alias `PyObject` (aka `Py`) is often confused with the identically named FFI definition `pyo3::ffi::PyObject`. For this reason we are deprecating its usage. To migrate simply replace its usage by the target type `Py`.
### Replacement of `GILOnceCell` with `PyOnceLock`
Click to expand Similar to the above renaming of `Python::with_gil` and related APIs, the `GILOnceCell` type was designed for a Python interpreter which was limited by the GIL. Aside from its name, it allowed for the "once" initialization to race because the racing was mediated by the GIL and was extremely unlikely to manifest in practice. With the introduction of free-threaded Python the racy initialization behavior is more likely to be problematic and so a new type `PyOnceLock` has been introduced which performs true single-initialization correctly while attached to the Python interpreter. It exposes the same API as `GILOnceCell`, so should be a drop-in replacement with the notable exception that if the racy initialization of `GILOnceCell` was inadvertently relied on (e.g. due to circular references) then the stronger once-ever guarantee of `PyOnceLock` may lead to deadlocking which requires refactoring. Before: ```rust # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::sync::GILOnceCell; # use pyo3::types::PyType; # fn main() -> PyResult<()> { # Python::attach(|py| { static DECIMAL_TYPE: GILOnceCell> = GILOnceCell::new(); DECIMAL_TYPE.import(py, "decimal", "Decimal")?; # Ok(()) # }) # } ``` After: ```rust # use pyo3::prelude::*; # use pyo3::sync::PyOnceLock; # use pyo3::types::PyType; # fn main() -> PyResult<()> { # Python::attach(|py| { static DECIMAL_TYPE: PyOnceLock> = PyOnceLock::new(); DECIMAL_TYPE.import(py, "decimal", "Decimal")?; # Ok(()) # }) # } ```
### Deprecation of `GILProtected`
Click to expand As another cleanup related to concurrency primitives designed for a Python constrained by the GIL, the `GILProtected` type is now deprecated. Prefer to use concurrency primitives which are compatible with free-threaded Python, such as [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) (in combination with PyO3's [`MutexExt`]({{#PYO3_DOCS_URL}}/pyo3/sync/trait.MutexExt.html) trait). Before: ```rust # #![allow(deprecated)] # use pyo3::prelude::*; # fn main() { # #[cfg(not(Py_GIL_DISABLED))] { use pyo3::sync::GILProtected; use std::cell::RefCell; # Python::attach(|py| { static NUMBERS: GILProtected>> = GILProtected::new(RefCell::new(Vec::new())); Python::attach(|py| { NUMBERS.get(py).borrow_mut().push(42); }); # }) # } # } ``` After: ```rust # use pyo3::prelude::*; use pyo3::sync::MutexExt; use std::sync::Mutex; # fn main() { # Python::attach(|py| { static NUMBERS: Mutex> = Mutex::new(Vec::new()); Python::attach(|py| { NUMBERS.lock_py_attached(py).expect("no poisoning").push(42); }); # }) # } ```
### `PyMemoryError` now maps to `io::ErrorKind::OutOfMemory` when converted to `io::Error`
Click to expand Previously, converting a `PyMemoryError` into a Rust `io::Error` would result in an error with kind `Other`. Now, it produces an error with kind `OutOfMemory`. Similarly, converting an `io::Error` with kind `OutOfMemory` back into a Python error would previously yield a generic `PyOSError`. Now, it yields a `PyMemoryError`. This change makes error conversions more precise and matches the semantics of out-of-memory errors between Python and Rust.
## from 0.24.* to 0.25 ### `AsPyPointer` removal
Click to expand The `AsPyPointer` trait is mostly a leftover from the now removed gil-refs API. The last remaining uses were the GC API, namely `PyVisit::call`, and identity comparison (`PyAnyMethods::is` and `Py::is`). `PyVisit::call` has been updated to take `T: Into>>`, which allows for arguments of type `&Py`, `&Option>` and `Option<&Py>`. It is unlikely any changes are needed here to migrate. `PyAnyMethods::is`/`Py::is` has been updated to take `T: AsRef>>`. Additionally `AsRef>>` implementations were added for `Py`, `Bound` and `Borrowed`. Because of the existing `AsRef> for Bound` implementation this may cause inference issues in non-generic code. This can be easily migrated by switching to `as_any` instead of `as_ref` for these calls.
## from 0.23.* to 0.24
Click to expand There were no significant changes from 0.23 to 0.24 which required documenting in this guide.
## from 0.22.* to 0.23
Click to expand PyO3 0.23 is a significant rework of PyO3's internals for two major improvements: - Support of Python 3.13's new freethreaded build (aka "3.13t") - Rework of to-Python conversions with a new `IntoPyObject` trait. These changes are both substantial and reasonable efforts have been made to allow as much code as possible to continue to work as-is despite the changes. The impacts are likely to be seen in three places when upgrading: - PyO3's data structures [are now thread-safe](#free-threaded-python-support) instead of reliant on the GIL for synchronization. In particular, `#[pyclass]` types are [now required to be `Sync`](./class/thread-safety.md). - The [`IntoPyObject` trait](#new-intopyobject-trait-unifies-to-python-conversions) may need to be implemented for types in your codebase. In most cases this can simply be done with [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros). There will be many deprecation warnings from the replacement of `IntoPy` and `ToPyObject` traits. - There will be many deprecation warnings from the [final removal of the `gil-refs` feature](#gil-refs-feature-removed), which opened up API space for a cleanup and simplification to PyO3's "Bound" API. The sections below discuss the rationale and details of each change in more depth.
### Free-threaded Python Support
Click to expand PyO3 0.23 introduces initial support for the new free-threaded build of CPython 3.13, aka "3.13t". Because this build allows multiple Python threads to operate simultaneously on underlying Rust data, the `#[pyclass]` macro now requires that types it operates on implement `Sync`. Aside from the change to `#[pyclass]`, most features of PyO3 work unchanged, as the changes have been to the internal data structures to make them thread-safe. An example of this is the `GILOnceCell` type, which used the GIL to synchronize single-initialization. It now uses internal locks to guarantee that only one write ever succeeds, however it allows for multiple racing runs of the initialization closure. It may be preferable to instead use `std::sync::OnceLock` in combination with the `pyo3::sync::OnceLockExt` trait which adds `OnceLock::get_or_init_py_attached` for single-initialization where the initialization closure is guaranteed only ever to run once and without deadlocking with the GIL. Future PyO3 versions will likely add more traits and data structures to make working with free-threaded Python easier. Some features are unaccessible on the free-threaded build: - The `GILProtected` type, which relied on the GIL to expose synchronized access to inner contents - `PyList::get_item_unchecked`, which cannot soundly be used due to races between time-of-check and time-of-use If you make use of these features then you will need to account for the unavailability of the API in the free-threaded build. One way to handle it is via conditional compilation -- extensions can use `pyo3-build-config` to get access to a `#[cfg(Py_GIL_DISABLED)]` guard. See [the guide section on free-threaded Python](free-threading.md) for more details about supporting free-threaded Python in your PyO3 extensions.
### New `IntoPyObject` trait unifies to-Python conversions
Click to expand PyO3 0.23 introduces a new `IntoPyObject` trait to convert Rust types into Python objects which replaces both `IntoPy` and `ToPyObject`. Notable features of this new trait include: - conversions can now return an error - it is designed to work efficiently for both `T` owned types and `&T` references - compared to `IntoPy` the generic `T` moved into an associated type, so - there is now only one way to convert a given type - the output type is stronger typed and may return any Python type instead of just `PyAny` - byte collections are specialized to convert into `PyBytes` now, see [below](#to-python-conversions-changed-for-byte-collections-vecu8-u8-n-and-smallvecu8-n) - `()` (unit) is now only specialized in return position of `#[pyfunction]` and `#[pymethods]` to return `None`, in normal usage it converts into an empty `PyTuple` All PyO3 provided types as well as `#[pyclass]`es already implement `IntoPyObject`. Other types will need to adapt an implementation of `IntoPyObject` to stay compatible with the Python APIs. In many cases the new [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros) macro can be used instead of [manual implementations](#intopyobject-manual-implementation). Since `IntoPyObject::into_pyobject` may return either a `Bound` or `Borrowed`, you may find the [`BoundObject`](conversions/traits.md#boundobject-for-conversions-that-may-be-bound-or-borrowed) trait to be useful to write code that generically handles either type of smart pointer. Together with the introduction of `IntoPyObject` the old conversion traits `ToPyObject` and `IntoPy` are deprecated and will be removed in a future PyO3 version. #### `IntoPyObject` and `IntoPyObjectRef` derive macros To implement the new trait you may use the new `IntoPyObject` and `IntoPyObjectRef` derive macros as below. ```rust,no_run # use pyo3::prelude::*; #[derive(IntoPyObject, IntoPyObjectRef)] struct Struct { count: usize, obj: Py, } ``` The `IntoPyObjectRef` derive macro derives implementations for references (e.g. for `&Struct` in the example above), which is a replacement for the `ToPyObject` trait. #### `IntoPyObject` manual implementation Before: ```rust,ignore # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); impl IntoPy for MyPyObjectWrapper { fn into_py(self, py: Python<'_>) -> PyObject { self.0 } } impl ToPyObject for MyPyObjectWrapper { fn to_object(&self, py: Python<'_>) -> PyObject { self.0.clone_ref(py) } } ``` After: ```rust,no_run # #![allow(deprecated)] # use pyo3::prelude::*; # #[allow(dead_code)] # struct MyPyObjectWrapper(PyObject); impl<'py> IntoPyObject<'py> for MyPyObjectWrapper { type Target = PyAny; // the Python type type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound` type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.into_bound(py)) } } // `ToPyObject` implementations should be converted to implementations on reference types impl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper { type Target = PyAny; type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.bind_borrowed(py)) } } ```
### To-Python conversions changed for byte collections (`Vec`, `[u8; N]` and `SmallVec<[u8; N]>`)
Click to expand With the introduction of the `IntoPyObject` trait, PyO3's macros now prefer `IntoPyObject` implementations over `IntoPy` when producing Python values. This applies to `#[pyfunction]` and `#[pymethods]` return values and also fields accessed via `#[pyo3(get)]`. This change has an effect on functions and methods returning _byte_ collections like - `Vec` - `[u8; N]` - `SmallVec<[u8; N]>` In their new `IntoPyObject` implementation these will now turn into `PyBytes` rather than a `PyList`. All other `T`s are unaffected and still convert into a `PyList`. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] fn foo() -> Vec { // would previously turn into a `PyList`, now `PyBytes` vec![0, 1, 2, 3] } #[pyfunction] fn bar() -> Vec { // unaffected, returns `PyList` vec![0, 1, 2, 3] } ``` If this conversion is _not_ desired, consider building a list manually using `PyList::new`. The following types were previously _only_ implemented for `u8` and now allow other `T`s turn into `PyList`: - `&[T]` - `Cow<[T]>` This is purely additional and should just extend the possible return types.
### `gil-refs` feature removed
Click to expand PyO3 0.23 completes the removal of the "GIL Refs" API in favour of the new "Bound" API introduced in PyO3 0.21. With the removal of the old API, many "Bound" API functions which had been introduced with `_bound` suffixes no longer need the suffixes as these names have been freed up. For example, `PyTuple::new_bound` is now just `PyTuple::new` (the existing name remains but is deprecated). Before: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn main() { # Python::attach(|py| { // For example, for PyTuple. Many such APIs have been changed. let tup = PyTuple::new_bound(py, [1, 2, 3]); # }) # } ``` After: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn main() { # Python::attach(|py| { // For example, for PyTuple. Many such APIs have been changed. let tup = PyTuple::new(py, [1, 2, 3]); # }) # } ``` #### `IntoPyDict` trait adjusted for removal of `gil-refs` As part of this API simplification, the `IntoPyDict` trait has had a small breaking change: `IntoPyDict::into_py_dict_bound` method has been renamed to `IntoPyDict::into_py_dict`. It is also now fallible as part of the `IntoPyObject` trait addition. If you implemented `IntoPyDict` for your type, you should implement `into_py_dict` instead of `into_py_dict_bound`. The old name is still available for calling but deprecated. Before: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; # use std::collections::HashMap; struct MyMap(HashMap); impl IntoPyDict for MyMap where K: ToPyObject, V: ToPyObject, { fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { let dict = PyDict::new_bound(py); for (key, value) in self.0 { dict.set_item(key, value) .expect("Failed to set_item on dict"); } dict } } ``` After: ```rust,no_run # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; # use std::collections::HashMap; # #[allow(dead_code)] struct MyMap(HashMap); impl<'py, K, V> IntoPyDict<'py> for MyMap where K: IntoPyObject<'py>, V: IntoPyObject<'py>, { fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); for (key, value) in self.0 { dict.set_item(key, value)?; } Ok(dict) } } ```
## from 0.21.* to 0.22 ### Deprecation of `gil-refs` feature continues
Click to expand Following the introduction of the "Bound" API in PyO3 0.21 and the planned removal of the "GIL Refs" API, all functionality related to GIL Refs is now gated behind the `gil-refs` feature and emits a deprecation warning on use. See the 0.21 migration entry for help upgrading.
### Deprecation of implicit default for trailing optional arguments
Click to expand With `pyo3` 0.22 the implicit `None` default for trailing `Option` type argument is deprecated. To migrate, place a `#[pyo3(signature = (...))]` attribute on affected functions or methods and specify the desired behavior. The migration warning specifies the corresponding signature to keep the current behavior. With 0.23 the signature will be required for any function containing `Option` type parameters to prevent accidental and unnoticed changes in behavior. With 0.24 this restriction will be lifted again and `Option` type arguments will be treated as any other argument _without_ special handling. Before: ```rust,no_run # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyfunction] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, amount=None))] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ```
### `Py::clone` is now gated behind the `py-clone` feature
Click to expand If you rely on `impl Clone for Py` to fulfil trait requirements imposed by existing Rust code written without PyO3-based code in mind, the newly introduced feature `py-clone` must be enabled. However, take care to note that the behaviour is different from previous versions. If `Clone` was called without the GIL being held, we tried to delay the application of these reference count increments until PyO3-based code would re-acquire it. This turned out to be impossible to implement in a sound manner and hence was removed. Now, if `Clone` is called without the GIL being held, we panic instead for which calling code might not be prepared. It is advised to migrate off the `py-clone` feature. The simplest way to remove dependency on `impl Clone for Py` is to wrap `Py` as `Arc>` and use cloning of the arc. Related to this, we also added a `pyo3_disable_reference_pool` conditional compilation flag which removes the infrastructure necessary to apply delayed reference count decrements implied by `impl Drop for Py`. They do not appear to be a soundness hazard as they should lead to memory leaks in the worst case. However, the global synchronization adds significant overhead to cross the Python-Rust boundary. Enabling this feature will remove these costs and make the `Drop` implementation abort the process if called without the GIL being held instead.
### Require explicit opt-in for comparison for simple enums
Click to expand With `pyo3` 0.22 the new `#[pyo3(eq)]` options allows automatic implementation of Python equality using Rust's `PartialEq`. Previously simple enums automatically implemented equality in terms of their discriminants. To make PyO3 more consistent, this automatic equality implementation is deprecated in favour of having opt-ins for all `#[pyclass]` types. Similarly, simple enums supported comparison with integers, which is not covered by Rust's `PartialEq` derive, so has been split out into the `#[pyo3(eq_int)]` attribute. To migrate, place a `#[pyo3(eq, eq_int)]` attribute on simple enum classes. Before: ```rust,no_run # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyclass] enum SimpleEnum { VariantA, VariantB = 42, } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum SimpleEnum { VariantA, VariantB = 42, } ```
### `PyType::name` reworked to better match Python `__name__`
Click to expand This function previously would try to read directly from Python type objects' C API field (`tp_name`), in which case it would return a `Cow::Borrowed`. However the contents of `tp_name` don't have well-defined semantics. Instead `PyType::name()` now returns the equivalent of Python `__name__` and returns `PyResult>`. The closest equivalent to PyO3 0.21's version of `PyType::name()` has been introduced as a new function `PyType::fully_qualified_name()`, which is equivalent to `__module__` and `__qualname__` joined as `module.qualname`. Before: ```rust,ignore # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?.into_owned(); println!("Hello, {}", name); let mut name_upper = bool_type.name()?; name_upper.to_mut().make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ``` After: ```rust,ignore # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?; println!("Hello, {}", name); // (if the full dotted path was desired, switch from `name()` to `fully_qualified_name()`) let mut name_upper = bool_type.fully_qualified_name()?.to_string(); name_upper.make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ```
## from 0.20.* to 0.21
Click to expand PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see . The "GIL Ref" `&'py PyAny` and similar types such as `&'py PyDict` continue to be available as a deprecated API. Due to the advantages of the new API it is advised that all users make the effort to upgrade as soon as possible. In addition to the major API type overhaul, PyO3 has needed to make a few small breaking adjustments to other APIs to close correctness and soundness gaps. The recommended steps to update to PyO3 0.21 is as follows: 1. Enable the `gil-refs` feature to silence deprecations related to the API change 2. Fix all other PyO3 0.21 migration steps 3. Disable the `gil-refs` feature and migrate off the deprecated APIs The following sections are laid out in this order.
### Enable the `gil-refs` feature
Click to expand To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature. > The one single exception where an existing API was changed in-place is the `pyo3::intern!` macro. Almost all uses of this macro did not need to update code to account it changing to return `&Bound` immediately, and adding an `intern_bound!` replacement was perceived as adding more work for users. It is recommended that users do this as a first step of updating to PyO3 0.21 so that the deprecation warnings do not get in the way of resolving the rest of the migration steps. Before: ```toml # Cargo.toml [dependencies] pyo3 = "0.20" ``` After: ```toml # Cargo.toml [dependencies] pyo3 = { version = "0.21", features = ["gil-refs"] } ```
### `PyTypeInfo` and `PyTryFrom` have been adjusted
Click to expand The `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`. To tighten up the PyO3 traits as part of the deprecation of the GIL Refs API the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`. The methods `PyAny::downcast` and `PyAny::downcast_exact` no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively. To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`). Before: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let list = PyList::new(py, 0..5); let b = ::try_from(list.get_item(0).unwrap())?; Ok(()) }) # } ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { // Note that PyList::new is deprecated for PyList::new_bound as part of the GIL Refs API removal, // see the section below on migration to Bound. #[allow(deprecated)] let list = PyList::new(py, 0..5); let b = list.get_item(0).unwrap().downcast::()?; Ok(()) }) # } ```
### `Iter(A)NextOutput` are deprecated
Click to expand The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option` and `Result, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration. Starting with an implementation of a Python iterator using `IterNextOutput`, e.g. ```rust,ignore use pyo3::prelude::*; use pyo3::iter::IterNextOutput; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> IterNextOutput { if self.count < 5 { self.count += 1; IterNextOutput::Yield(self.count) } else { IterNextOutput::Return("done") } } } ``` If returning `"done"` via `StopIteration` is not really required, this should be written as ```rust,no_run use pyo3::prelude::*; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> Option { if self.count < 5 { self.count += 1; Some(self.count) } else { None } } } ``` This form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception. Note that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `Result, E>` variant, this form can also be used to wrap fallible iterators. Alternatively, the implementation can also be done as it would in Python itself, i.e. by "raising" a `StopIteration` exception ```rust,no_run use pyo3::prelude::*; use pyo3::exceptions::PyStopIteration; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> PyResult { if self.count < 5 { self.count += 1; Ok(self.count) } else { Err(PyStopIteration::new_err("done")) } } } ``` Finally, an asynchronous iterator can directly return an awaitable without confusing wrapping ```rust,no_run use pyo3::prelude::*; #[pyclass] struct PyClassAwaitable { number: usize, } #[pymethods] impl PyClassAwaitable { fn __next__(&self) -> usize { self.number } fn __await__(slf: Py) -> Py { slf } } #[pyclass] struct PyClassAsyncIter { number: usize, } #[pymethods] impl PyClassAsyncIter { fn __anext__(&mut self) -> PyClassAwaitable { self.number += 1; PyClassAwaitable { number: self.number, } } fn __aiter__(slf: Py) -> Py { slf } } ```
### `PyType::name` has been renamed to `PyType::qualname`
Click to expand `PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
### `PyCell` has been deprecated
Click to expand Interactions with Python objects implemented in Rust no longer need to go though `PyCell`. Instead interactions with Python object now consistently go through `Bound` or `Py` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust. Use `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.
### Migrating from the GIL Refs API to `Bound`
Click to expand To minimise breakage of code using the GIL Refs API, the `Bound` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones. To identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on [almost](#cases-where-pyo3-cannot-emit-gil-ref-deprecation-warnings) all uses of APIs accepting and producing GIL Refs . Over one or more PRs it should be possible to follow the deprecation hints to update code. Depending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first. For example, the following APIs have gained updated variants: - `PyList::new`, `PyTuple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc. - `FromPyObject::extract` has a new `FromPyObject::extract_bound` (see the section below) - The `PyTypeInfo` trait has had new `_bound` methods added to accept / return `Bound`. Because the new `Bound` API brings ownership out of the PyO3 framework and into user code, there are a few places where user code is expected to need to adjust while switching to the new API: - Code will need to add the occasional `&` to borrow the new smart pointer as `&Bound` to pass these types around (or use `.clone()` at the very small cost of increasing the Python reference count) - `Bound` and `Bound` cannot support indexing with `list[0]`, you should use `list.get_item(0)` instead. - `Bound::iter_borrowed` is slightly more efficient than `Bound::iter`. The default iteration of `Bound` cannot return borrowed references because Rust does not (yet) have "lending iterators". Similarly `Bound::get_borrowed_item` is more efficient than `Bound::get_item` for the same reason. - `&Bound` does not implement `FromPyObject` (although it might be possible to do this in the future once the GIL Refs API is completely removed). Use `bound_any.downcast::()` instead of `bound_any.extract::<&Bound>()`. - `Bound::to_str` now borrows from the `Bound` rather than from the `'py` lifetime, so code will need to store the smart pointer as a value in some cases where previously `&PyString` was just used as a temporary. (There are some more details relating to this in [the section below](#deactivating-the-gil-refs-feature).) - `.extract::<&str>()` now borrows from the source Python object. The simplest way to update is to change to `.extract::()`, which retains ownership of the Python reference. See more information [in the section on deactivating the `gil-refs` feature](#deactivating-the-gil-refs-feature). To convert between `&PyAny` and `&Bound` use the `as_borrowed()` method: ```rust,ignore let gil_ref: &PyAny = ...; let bound: &Bound = &gil_ref.as_borrowed(); ``` To convert between `Py` and `Bound` use the `bind()` / `into_bound()` methods, and `as_unbound()` / `unbind()` to go back from `Bound` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyList> = obj.bind(py); let bound: Bound<'py, PyList> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ```
⚠️ Warning: dangling pointer trap 💣 > Because of the ownership changes, code which uses `.as_ptr()` to convert `&PyAny` and other GIL Refs to a `*mut pyo3_ffi::PyObject` should take care to avoid creating dangling pointers now that `Bound` carries ownership. > > For example, the following pattern with `Option<&PyAny>` can easily create a dangling pointer when migrating to the `Bound` smart pointer: > > ```rust,ignore > let opt: Option<&PyAny> = ...; > let p: *mut ffi::PyObject = opt.map_or(std::ptr::null_mut(), |any| any.as_ptr()); > ``` > > The correct way to migrate this code is to use `.as_ref()` to avoid dropping the `Bound` in the `map_or` closure: > > ```rust,ignore > let opt: Option> = ...; > let p: *mut ffi::PyObject = opt.as_ref().map_or(std::ptr::null_mut(), Bound::as_ptr); > ```
#### Migrating `FromPyObject` implementations `FromPyObject` has had a new method `extract_bound` which takes `&Bound<'py, PyAny>` as an argument instead of `&PyAny`. Both `extract` and `extract_bound` have been given default implementations in terms of the other, to avoid breaking code immediately on update to 0.21. All implementations of `FromPyObject` should be switched from `extract` to `extract_bound`. Before: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract(obj: &'py PyAny) -> PyResult { /* ... */ } } ``` After: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { /* ... */ } } ``` The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed. #### Cases where PyO3 cannot emit GIL Ref deprecation warnings Despite a large amount of deprecations warnings produced by PyO3 to aid with the transition from GIL Refs to the Bound API, there are a few cases where PyO3 cannot automatically warn on uses of GIL Refs. It is worth checking for these cases manually after the deprecation warnings have all been addressed: - Individual implementations of the `FromPyObject` trait cannot be deprecated, so PyO3 cannot warn about uses of code patterns like `.extract<&PyAny>()` which produce a GIL Ref. - GIL Refs in `#[pyfunction]` arguments emit a warning, but if the GIL Ref is wrapped inside another container such as `Vec<&PyAny>` then PyO3 cannot warn against this. - The `wrap_pyfunction!(function)(py)` deferred argument form of the `wrap_pyfunction` macro taking `py: Python<'py>` produces a GIL Ref, and due to limitations in type inference PyO3 cannot warn against this specific case.
### Deactivating the `gil-refs` feature
Click to expand As a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22. At this point code that needed to manage GIL Ref memory can safely remove uses of `GILPool` (which are constructed by calls to `Python::new_pool` and `Python::with_pool`). Deprecation warnings will highlight these cases. There is just one case of code that changes upon disabling these features: `FromPyObject` trait implementations for types that borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the GIL Refs API is in the process of being removed). The main types affected are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`. To make PyO3's core functionality continue to work while the GIL Refs API is in the process of being removed, disabling the `gil-refs` feature moves the implementations of `FromPyObject` for `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>` to a new temporary trait `FromPyObjectBound`. This trait is the expected future form of `FromPyObject` and has an additional lifetime `'a` to enable these types to borrow data from Python objects. PyO3 0.21 has introduced the [`PyBackedStr`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedStr.html) and [`PyBackedBytes`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedBytes.html) types to help with this case. The easiest way to avoid lifetime challenges from extracting `&str` is to use these. For more complex types like `Vec<&str>`, is now impossible to extract directly from a Python object and `Vec` is the recommended upgrade path. A key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines. For example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs` feature. Before: ```rust,ignore # #[cfg(feature = "gil-refs")] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { #[allow(deprecated)] // GIL Ref API let obj: &'py PyType = py.get_type::(); let name: &'py str = obj.getattr("__name__")?.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` After: ```rust,ignore # #[cfg(any(not(Py_LIMITED_API), Py_3_10))] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { let obj: Bound<'py, PyType> = py.get_type_bound::(); let name_obj: Bound<'py, PyAny> = obj.getattr("__name__")?; // the lifetime of the data is no longer `'py` but the much shorter // lifetime of the `name_obj` smart pointer above let name: &'_ str = name_obj.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` To avoid needing to worry about lifetimes at all, it is also possible to use the new `PyBackedStr` type, which stores a reference to the Python `str` without a lifetime attachment. In particular, `PyBackedStr` helps for `abi3` builds for Python older than 3.10. Due to limitations in the `abi3` CPython API for those older versions, PyO3 cannot offer a `FromPyObjectBound` implementation for `&str` on those versions. The easiest way to migrate for older `abi3` builds is to replace any cases of `.extract::<&str>()` with `.extract::()`. Alternatively, use `.extract::>()`, `.extract::()` to copy the data into Rust. The following example uses the same snippet as those just above, but this time the final extracted type is `PyBackedStr`: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { use pyo3::pybacked::PyBackedStr; let obj: Bound<'py, PyType> = py.get_type_bound::(); let name: PyBackedStr = obj.getattr("__name__")?.extract()?; assert_eq!(&*name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); ```
## from 0.19.* to 0.20 ### Drop support for older technologies
Click to expand PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
### `PyDict::get_item` now returns a `Result`
Click to expand `PyDict::get_item` in PyO3 0.19 and older was implemented using a Python API which would suppress all exceptions and return `None` in those cases. This included errors in `__hash__` and `__eq__` implementations of the key being looked up. Newer recommendations by the Python core developers advise against using these APIs which suppress exceptions, instead allowing exceptions to bubble upwards. `PyDict::get_item_with_error` already implemented this recommended behavior, so that API has been renamed to `PyDict::get_item`. Before: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a").map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b").is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item_with_error(dict) .unwrap_err() .is_instance_of::(py)); }); # } ``` After: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| -> PyResult<()> { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b")?.is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item(dict) .unwrap_err() .is_instance_of::(py)); Ok(()) }); # } ```
### Required arguments are no longer accepted after optional arguments
Click to expand Trailing `Option` arguments have an automatic default of `None`. To avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults. In PyO3 0.20, this becomes a hard error. Before: ```rust,ignore #[pyfunction] fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, y))] // both x and y have no defaults and are required fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ```
### Remove deprecated function forms
Click to expand In PyO3 0.18 the `#[args]` attribute for `#[pymethods]`, and directly specifying the function signature in `#[pyfunction]`, was deprecated. This functionality has been removed in PyO3 0.20. Before: ```rust,ignore #[pyfunction] #[pyo3(a, b = "0", "/")] fn add(a: u64, b: u64) -> u64 { a + b } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } ```
### `IntoPyPointer` trait removed
Click to expand The trait `IntoPyPointer`, which provided the `into_ptr` method on many types, has been removed. `into_ptr` is now available as an inherent method on all types that previously implemented this trait.
### `AsPyPointer` now `unsafe` trait
Click to expand The trait `AsPyPointer` is now `unsafe trait`, meaning any external implementation of it must be marked as `unsafe impl`, and ensure that they uphold the invariant of returning valid pointers.
## from 0.18.* to 0.19 ### Access to `Python` inside `__traverse__` implementations are now forbidden
Click to expand During `__traverse__` implementations for Python's Garbage Collection it is forbidden to do anything other than visit the members of the `#[pyclass]` being traversed. This means making Python function calls or other API calls are forbidden. Previous versions of PyO3 would allow access to `Python` (e.g. via `Python::with_gil`), which could cause the Python interpreter to crash or otherwise confuse the garbage collection algorithm. Attempts to acquire the GIL will now panic. See [#3165](https://github.com/PyO3/pyo3/issues/3165) for more detail. ```rust,ignore # use pyo3::prelude::*; #[pyclass] struct SomeClass {} impl SomeClass { fn __traverse__(&self, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` { Python::with_gil(|| { /*...*/ }) // ERROR: this will panic } } ```
### Smarter `anyhow::Error` / `eyre::Report` conversion when inner error is "simple" `PyErr`
Click to expand When converting from `anyhow::Error` or `eyre::Report` to `PyErr`, if the inner error is a "simple" `PyErr` (with no source error), then the inner error will be used directly as the `PyErr` instead of wrapping it in a new `PyRuntimeError` with the original information converted into a string. ```rust,ignore # #[cfg(feature = "anyhow")] # #[allow(dead_code)] # mod anyhow_only { # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; #[pyfunction] fn raise_err() -> anyhow::Result<()> { Err(PyValueError::new_err("original error message").into()) } fn main() { Python::with_gil(|py| { let rs_func = wrap_pyfunction!(raise_err, py).unwrap(); pyo3::py_run!( py, rs_func, r" try: rs_func() except Exception as e: print(repr(e)) " ); }) } # } ``` Before, the above code would have printed `RuntimeError('ValueError: original error message')`, which might be confusing. After, the same code will print `ValueError: original error message`, which is more straightforward. However, if the `anyhow::Error` or `eyre::Report` has a source, then the original exception will still be wrapped in a `PyRuntimeError`.
### The deprecated `Python::acquire_gil` was removed and `Python::with_gil` must be used instead
Click to expand While the API provided by [`Python::acquire_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.acquire_gil) seems convenient, it is somewhat brittle as the design of the [`Python`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html) token relies on proper nesting and panics if not used correctly, e.g. ```rust,ignore # #![allow(dead_code, deprecated)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct ObjectAndGuard { object: Py, guard: GILGuard, } impl ObjectAndGuard { fn new() -> Self { let guard = Python::acquire_gil(); let object = Py::new(guard.python(), SomeClass {}).unwrap(); Self { object, guard } } } let first = ObjectAndGuard::new(); let second = ObjectAndGuard::new(); // Panics because the guard within `second` is still alive. drop(first); drop(second); ``` The replacement is [`Python::with_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.with_gil) which is more cumbersome but enforces the proper nesting by design, e.g. ```rust,ignore # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct Object { object: Py, } impl Object { fn new(py: Python<'_>) -> Self { let object = Py::new(py, SomeClass {}).unwrap(); Self { object } } } // It either forces us to release the GIL before acquiring it again. let first = Python::with_gil(|py| Object::new(py)); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); // Or it ensures releasing the inner lock before the outer one. Python::with_gil(|py| { let first = Object::new(py); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); }); ``` Furthermore, `Python::acquire_gil` provides ownership of a `GILGuard` which can be freely stored and passed around. This is usually not helpful as it may keep the lock held for a long time thereby blocking progress in other parts of the program. Due to the generative lifetime attached to the Python token supplied by `Python::with_gil`, the problem is avoided as the Python token can only be passed down the call chain. Often, this issue can also be avoided entirely as any GIL-bound reference `&'py PyAny` implies access to a Python token `Python<'py>` via the [`PyAny::py`](https://docs.rs/pyo3/0.22.5/pyo3/types/struct.PyAny.html#method.py) method.
## from 0.17.* to 0.18 ### Required arguments after `Option<_>` arguments will no longer be automatically inferred
Click to expand In `#[pyfunction]` and `#[pymethods]`, if a "required" function input such as `i32` came after an `Option<_>` input, then the `Option<_>` would be implicitly treated as required. (All trailing `Option<_>` arguments were treated as optional with a default value of `None`). Starting with PyO3 0.18, this is deprecated and a future PyO3 version will require a [`#[pyo3(signature = (...))]` option](./function/signature.md) to explicitly declare the programmer's intention. Before, x in the below example would be required to be passed from Python code: ```rust,compile_fail,ignore # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] fn required_argument_after_option(x: Option, y: i32) {} ``` After, specify the intended Python signature explicitly: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; // If x really was intended to be required #[pyfunction(signature = (x, y))] fn required_argument_after_option_a(x: Option, y: i32) {} // If x was intended to be optional, y needs a default too #[pyfunction(signature = (x=None, y=0))] fn required_argument_after_option_b(x: Option, y: i32) {} ```
### `__text_signature__` is now automatically generated for `#[pyfunction]` and `#[pymethods]`
Click to expand The [`#[pyo3(text_signature = "...")]` option](./function/signature.md#making-the-function-signature-available-to-python) was previously the only supported way to set the `__text_signature__` attribute on generated Python functions. PyO3 is now able to automatically populate `__text_signature__` for all functions automatically based on their Rust signature (or the [new `#[pyo3(signature = (...))]` option](./function/signature.md)). These automatically-generated `__text_signature__` values will currently only render `...` for all default values. Many `#[pyo3(text_signature = "...")]` options can be removed from functions when updating to PyO3 0.18, however in cases with default values a manual implementation may still be preferred for now. As examples: ```rust # use pyo3::prelude::*; // The `text_signature` option here is no longer necessary, as PyO3 will automatically // generate exactly the same value. #[pyfunction(text_signature = "(a, b, c)")] fn simple_function(a: i32, b: i32, c: i32) {} // The `text_signature` still provides value here as of PyO3 0.18, because the automatically // generated signature would be "(a, b=..., c=...)". #[pyfunction(signature = (a, b = 1, c = 2), text_signature = "(a, b=1, c=2)")] fn function_with_defaults(a: i32, b: i32, c: i32) {} # fn main() { # Python::attach(|py| { # let simple = wrap_pyfunction!(simple_function, py).unwrap(); # assert_eq!(simple.getattr("__text_signature__").unwrap().to_string(), "(a, b, c)"); # let defaulted = wrap_pyfunction!(function_with_defaults, py).unwrap(); # assert_eq!(defaulted.getattr("__text_signature__").unwrap().to_string(), "(a, b=1, c=2)"); # }) # } ```
## from 0.16.* to 0.17 ### Type checks have been changed for `PyMapping` and `PySequence` types
Click to expand Previously the type checks for `PyMapping` and `PySequence` (implemented in `PyTryFrom`) used the Python C-API functions `PyMapping_Check` and `PySequence_Check`. Unfortunately these functions are not sufficient for distinguishing such types, leading to inconsistent behavior (see [pyo3/pyo3#2072](https://github.com/PyO3/pyo3/issues/2072)). PyO3 0.17 changes these downcast checks to explicitly test if the type is a subclass of the corresponding abstract base class `collections.abc.Mapping` or `collections.abc.Sequence`. Note this requires calling into Python, which may incur a performance penalty over the previous method. If this performance penalty is a problem, you may be able to perform your own checks and use `try_from_unchecked` (unsafe). Another side-effect is that a pyclass defined in Rust with PyO3 will need to be _registered_ with the corresponding Python abstract base class for downcasting to succeed. `PySequence::register` and `PyMapping:register` have been added to make it easy to do this from Rust code. These are equivalent to calling `collections.abc.Mapping.register(MappingPyClass)` or `collections.abc.Sequence.register(SequencePyClass)` from Python. For example, for a mapping class defined in Rust: ```rust,compile_fail use pyo3::prelude::*; use std::collections::HashMap; #[pyclass(mapping)] struct Mapping { index: HashMap, } #[pymethods] impl Mapping { #[new] fn new(elements: Option<&PyList>) -> PyResult { // ... // truncated implementation of this mapping pyclass - basically a wrapper around a HashMap } ``` You must register the class with `collections.abc.Mapping` before the downcast will work: ```rust,compile_fail let m = Py::new(py, Mapping { index }).unwrap(); assert!(m.as_ref(py).downcast::().is_err()); PyMapping::register::(py).unwrap(); assert!(m.as_ref(py).downcast::().is_ok()); ``` Note that this requirement may go away in the future when a pyclass is able to inherit from the abstract base class directly (see [pyo3/pyo3#991](https://github.com/PyO3/pyo3/issues/991)).
### The `multiple-pymethods` feature now requires Rust 1.62
Click to expand Due to limitations in the `inventory` crate which the `multiple-pymethods` feature depends on, this feature now requires Rust 1.62. For more information see [dtolnay/inventory#32](https://github.com/dtolnay/inventory/issues/32).
### Added `impl IntoPy> for &str`
Click to expand This may cause inference errors. Before: ```rust,compile_fail # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { // Cannot infer either `Py` or `Py` let _test = "test".into_py(py); }); # } ``` After, some type annotations may be necessary: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { let _test: Py = "test".into_py(py); }); # } ```
### The `pyproto` feature is now disabled by default
Click to expand In preparation for removing the deprecated `#[pyproto]` attribute macro in a future PyO3 version, it is now gated behind an opt-in feature flag. This also gives a slight saving to compile times for code which does not use the deprecated macro.
### `PyTypeObject` trait has been deprecated
Click to expand The `PyTypeObject` trait already was near-useless; almost all functionality was already on the `PyTypeInfo` trait, which `PyTypeObject` had a blanket implementation based upon. In PyO3 0.17 the final method, `PyTypeObject::type_object` was moved to `PyTypeInfo::type_object`. To migrate, update trait bounds and imports from `PyTypeObject` to `PyTypeInfo`. Before: ```rust,ignore use pyo3::Python; use pyo3::type_object::PyTypeObject; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } ``` After ```rust,ignore use pyo3::{Python, PyTypeInfo}; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } # Python::with_gil(|py| { get_type_object::(py); }); ```
### `impl IntoPy for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`
Click to expand If this leads to errors, simply implement `IntoPy`. Because pyclasses already implement `IntoPy`, you probably don't need to worry about this.
### Each `#[pymodule]` can now only be initialized once per process
Click to expand To make PyO3 modules sound in the presence of Python sub-interpreters, for now it has been necessary to explicitly disable the ability to initialize a `#[pymodule]` more than once in the same process. Attempting to do this will now raise an `ImportError`.
## from 0.15.* to 0.16 ### Drop support for older technologies
Click to expand PyO3 0.16 has increased minimum Rust version to 1.48 and minimum Python version to 3.7. This enables use of newer language features (enabling some of the other additions in 0.16) and simplifies maintenance of the project.
### `#[pyproto]` has been deprecated
Click to expand In PyO3 0.15, the `#[pymethods]` attribute macro gained support for implementing "magic methods" such as `__str__` (aka "dunder" methods). This implementation was not quite finalized at the time, with a few edge cases to be decided upon. The existing `#[pyproto]` attribute macro was left untouched, because it covered these edge cases. In PyO3 0.16, the `#[pymethods]` implementation has been completed and is now the preferred way to implement magic methods. To allow the PyO3 project to move forward, `#[pyproto]` has been deprecated (with expected removal in PyO3 0.18). Migration from `#[pyproto]` to `#[pymethods]` is straightforward; copying the existing methods directly from the `#[pyproto]` trait implementation is all that is needed in most cases. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::{PyObjectProtocol, PyIterProtocol}; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } } #[pyproto] impl PyIterProtocol for MyClass { fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ``` After ```rust,compile_fail use pyo3::prelude::*; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ```
### Removed `PartialEq` for object wrappers
Click to expand The Python object wrappers `Py` and `PyAny` had implementations of `PartialEq` so that `object_a == object_b` would compare the Python objects for pointer equality, which corresponds to the `is` operator, not the `==` operator in Python. This has been removed in favor of a new method: use `object_a.is(object_b)`. This also has the advantage of not requiring the same wrapper type for `object_a` and `object_b`; you can now directly compare a `Py` with a `&PyAny` without having to convert. To check for Python object equality (the Python `==` operator), use the new method `eq()`.
### Container magic methods now match Python behavior
Click to expand In PyO3 0.15, `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` would generate only the _mapping_ implementation for a `#[pyclass]`. To match the Python behavior, these methods now generate both the _mapping_ **and** _sequence_ implementations. This means that classes implementing these `#[pymethods]` will now also be treated as sequences, same as a Python `class` would be. Small differences in behavior may result: - PyO3 will allow instances of these classes to be cast to `PySequence` as well as `PyMapping`. - Python will provide a default implementation of `__iter__` (if the class did not have one) which repeatedly calls `__getitem__` with integers (starting at 0) until an `IndexError` is raised. To explain this in detail, consider the following Python class: ```python class ExampleContainer: def __len__(self): return 5 def __getitem__(self, idx: int) -> int: if idx < 0 or idx > 5: raise IndexError() return idx ``` This class implements a Python [sequence](https://docs.python.org/3/glossary.html#term-sequence). The `__len__` and `__getitem__` methods are also used to implement a Python [mapping](https://docs.python.org/3/glossary.html#term-mapping). In the Python C-API, these methods are not shared: the sequence `__len__` and `__getitem__` are defined by the `sq_length` and `sq_item` slots, and the mapping equivalents are `mp_length` and `mp_subscript`. There are similar distinctions for `__setitem__` and `__delitem__`. Because there is no such distinction from Python, implementing these methods will fill the mapping and sequence slots simultaneously. A Python class with `__len__` implemented, for example, will have both the `sq_length` and `mp_length` slots filled. The PyO3 behavior in 0.16 has been changed to be closer to this Python behavior by default.
### `wrap_pymodule!` and `wrap_pyfunction!` now respect privacy correctly
Click to expand Prior to PyO3 0.16 the `wrap_pymodule!` and `wrap_pyfunction!` macros could use modules and functions whose defining `fn` was not reachable according Rust privacy rules. For example, the following code was legal before 0.16, but in 0.16 is rejected because the `wrap_pymodule!` macro cannot access the `private_submodule` function: ```rust,compile_fail mod foo { use pyo3::prelude::*; #[pymodule] fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ``` To fix it, make the private submodule visible, e.g. with `pub` or `pub(crate)`. ```rust,ignore mod foo { use pyo3::prelude::*; #[pymodule] pub(crate) fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use pyo3::wrap_pymodule; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ```
## from 0.14.* to 0.15 ### Changes in sequence indexing
Click to expand For all types that take sequence indices (`PyList`, `PyTuple` and `PySequence`), the API has been made consistent to only take `usize` indices, for consistency with Rust's indexing conventions. Negative indices, which were only sporadically supported even in APIs that took `isize`, now aren't supported anywhere. Further, the `get_item` methods now always return a `PyResult` instead of panicking on invalid indices. The `Index` trait has been implemented instead, and provides the same panic behavior as on Rust vectors. Note that _slice_ indices (accepted by `PySequence::get_slice` and other) still inherit the Python behavior of clamping the indices to the actual length, and not panicking/returning an error on out of range indices. An additional advantage of using Rust's indexing conventions for these types is that these types can now also support Rust's indexing operators as part of a consistent API: ```rust,ignore #![allow(deprecated)] use pyo3::{Python, types::PyList}; Python::with_gil(|py| { let list = PyList::new(py, &[1, 2, 3]); assert_eq!(list[0..2].to_string(), "[1, 2]"); }); ```
## from 0.13.* to 0.14 ### `auto-initialize` feature is now opt-in
Click to expand For projects embedding Python in Rust, PyO3 no longer automatically initializes a Python interpreter on the first call to `Python::with_gil` (or `Python::acquire_gil`) unless the [`auto-initialize` feature](features.md#auto-initialize) is enabled.
### New `multiple-pymethods` feature
Click to expand `#[pymethods]` have been reworked with a simpler default implementation which removes the dependency on the `inventory` crate. This reduces dependencies and compile times for the majority of users. The limitation of the new default implementation is that it cannot support multiple `#[pymethods]` blocks for the same `#[pyclass]`. If you need this functionality, you must enable the `multiple-pymethods` feature which will switch `#[pymethods]` to the inventory-based implementation.
### Deprecated `#[pyproto]` methods
Click to expand Some protocol (aka `__dunder__`) methods such as `__bytes__` and `__format__` have been possible to implement two ways in PyO3 for some time: via a `#[pyproto]` (e.g. `PyObjectProtocol` for the methods listed here), or by writing them directly in `#[pymethods]`. This is only true for a handful of the `#[pyproto]` methods (for technical reasons to do with the way PyO3 currently interacts with the Python C-API). In the interest of having only one way to do things, the `#[pyproto]` forms of these methods have been deprecated. To migrate just move the affected methods from a `#[pyproto]` to a `#[pymethods]` block. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::basic::PyObjectProtocol; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ``` After: ```rust,no_run use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ```
## from 0.12.* to 0.13 ### Minimum Rust version increased to Rust 1.45
Click to expand PyO3 `0.13` makes use of new Rust language features stabilized between Rust 1.40 and Rust 1.45. If you are using a Rust compiler older than Rust 1.45, you will need to update your toolchain to be able to continue using PyO3.
### Runtime changes to support the CPython limited API
Click to expand In PyO3 `0.13` support was added for compiling against the CPython limited API. This had a number of implications for _all_ PyO3 users, described here. The largest of these is that all types created from PyO3 are what CPython calls "heap" types. The specific implications of this are: - If you wish to subclass one of these types _from Rust_ you must mark it `#[pyclass(subclass)]`, as you would if you wished to allow subclassing it from Python code. - Type objects are now mutable - Python code can set attributes on them. - `__module__` on types without `#[pyclass(module="mymodule")]` no longer returns `builtins`, it now raises `AttributeError`.
## from 0.11.* to 0.12 ### `PyErr` has been reworked
Click to expand In PyO3 `0.12` the `PyErr` type has been re-implemented to be significantly more compatible with the standard Rust error handling ecosystem. Specifically `PyErr` now implements `Error + Send + Sync`, which are the standard traits used for error types. While this has necessitated the removal of a number of APIs, the resulting `PyErr` type should now be much more easier to work with. The following sections list the changes in detail and how to migrate to the new APIs.
#### `PyErr::new` and `PyErr::from_type` now require `Send + Sync` for their argument
Click to expand For most uses no change will be needed. If you are trying to construct `PyErr` from a value that is not `Send + Sync`, you will need to first create the Python object and then use `PyErr::from_instance`. Similarly, any types which implemented `PyErrArguments` will now need to be `Send + Sync`.
#### `PyErr`'s contents are now private
Click to expand It is no longer possible to access the fields `.ptype`, `.pvalue` and `.ptraceback` of a `PyErr`. You should instead now use the new methods `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`.
#### `PyErrValue` and `PyErr::from_value` have been removed
Click to expand As these were part the internals of `PyErr` which have been reworked, these APIs no longer exist. If you used this API, it is recommended to use `PyException::new_err` (see [the section on Exception types](#exception-types-have-been-reworked)).
#### `Into>` for `PyErr` has been removed
Click to expand This implementation was redundant. Just construct the `Result::Err` variant directly. Before: ```rust,compile_fail let result: PyResult<()> = PyErr::new::("error message").into(); ``` After (also using the new reworked exception types; see the following section): ```rust,no_run # use pyo3::{PyResult, exceptions::PyTypeError}; let result: PyResult<()> = Err(PyTypeError::new_err("error message")); ```
### Exception types have been reworked
Click to expand Previously exception types were zero-sized marker types purely used to construct `PyErr`. In PyO3 0.12, these types have been replaced with full definitions and are usable in the same way as `PyAny`, `PyDict` etc. This makes it possible to interact with Python exception objects. The new types also have names starting with the "Py" prefix. For example, before: ```rust,ignore let err: PyErr = TypeError::py_err("error message"); ``` After: ```rust,ignore # use pyo3::{PyErr, PyResult, Python, type_object::PyTypeObject}; # use pyo3::exceptions::{PyBaseException, PyTypeError}; # Python::with_gil(|py| -> PyResult<()> { let err: PyErr = PyTypeError::new_err("error message"); // Uses Display for PyErr, new for PyO3 0.12 assert_eq!(err.to_string(), "TypeError: error message"); // Now possible to interact with exception instances, new for PyO3 0.12 let instance: &PyBaseException = err.instance(py); assert_eq!( instance.getattr("__class__")?, PyTypeError::type_object(py).as_ref() ); # Ok(()) # }).unwrap(); ```
### `FromPy` has been removed
Click to expand To simplify the PyO3 conversion traits, the `FromPy` trait has been removed. Previously there were two ways to define the to-Python conversion for a type: `FromPy for PyObject` and `IntoPy for T`. Now there is only one way to define the conversion, `IntoPy`, so downstream crates may need to adjust accordingly. Before: ```rust,compile_fail # use pyo3::prelude::*; struct MyPyObjectWrapper(PyObject); impl FromPy for PyObject { fn from_py(other: MyPyObjectWrapper, _py: Python<'_>) -> Self { other.0 } } ``` After ```rust,ignore # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); # #[allow(deprecated)] impl IntoPy for MyPyObjectWrapper { fn into_py(self, _py: Python<'_>) -> PyObject { self.0 } } ``` Similarly, code which was using the `FromPy` trait can be trivially rewritten to use `IntoPy`. Before: ```rust,compile_fail # use pyo3::prelude::*; # Python::with_gil(|py| { let obj = PyObject::from_py(1.234, py); # }) ``` After: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # Python::with_gil(|py| { let obj: PyObject = 1.234.into_py(py); # }) ```
### `PyObject` is now a type alias of `Py`
Click to expand This should change very little from a usage perspective. If you implemented traits for both `PyObject` and `Py`, you may find you can just remove the `PyObject` implementation.
### `AsPyRef` has been removed
Click to expand As `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef` was `Py`. This removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to `Py::as_ref`. This should require no code changes except removing `use pyo3::AsPyRef` for code which did not use `pyo3::prelude::*`. Before: ```rust,ignore use pyo3::{AsPyRef, Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ``` After: ```rust,ignore use pyo3::{Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ```
## from 0.10.* to 0.11 ### Stable Rust
Click to expand PyO3 now supports the stable Rust toolchain. The minimum required version is 1.39.0.
### `#[pyclass]` structs must now be `Send` or `unsendable`
Click to expand Because `#[pyclass]` structs can be sent between threads by the Python interpreter, they must implement `Send` or declared as `unsendable` (by `#[pyclass(unsendable)]`). Note that `unsendable` is added in PyO3 `0.11.1` and `Send` is always required in PyO3 `0.11.0`. This may "break" some code which previously was accepted, even though it could be unsound. There can be two fixes: 1. If you think that your `#[pyclass]` actually must be `Send`able, then let's implement `Send`. A common, safer way is using thread-safe types. E.g., `Arc` instead of `Rc`, `Mutex` instead of `RefCell`, and `Box` instead of `Box`. Before: ```rust,compile_fail use pyo3::prelude::*; use std::rc::Rc; use std::cell::RefCell; #[pyclass] struct NotThreadSafe { shared_bools: Rc>>, closure: Box, } ``` After: ```rust,ignore # #![allow(dead_code)] use pyo3::prelude::*; use std::sync::{Arc, Mutex}; #[pyclass] struct ThreadSafe { shared_bools: Arc>>, closure: Box, } ``` In situations where you cannot change your `#[pyclass]` to automatically implement `Send` (e.g., when it contains a raw pointer), you can use `unsafe impl Send`. In such cases, care should be taken to ensure the struct is actually thread safe. See [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) for more. 2. If you think that your `#[pyclass]` should not be accessed by another thread, you can use `unsendable` flag. A class marked with `unsendable` panics when accessed by another thread, making it thread-safe to expose an unsendable object to the Python interpreter. Before: ```rust,compile_fail use pyo3::prelude::*; #[pyclass] struct Unsendable { pointers: Vec<*mut std::ffi::c_char>, } ``` After: ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass(unsendable)] struct Unsendable { pointers: Vec<*mut std::ffi::c_char>, } ```
### All `PyObject` and `Py` methods now take `Python` as an argument
Click to expand Previously, a few methods such as `Object::get_refcnt` did not take `Python` as an argument (to ensure that the Python GIL was held by the current thread). Technically, this was not sound. To migrate, just pass a `py` argument to any calls to these methods. Before: ```rust,compile_fail # pyo3::Python::attach(|py| { py.None().get_refcnt(); # }) ``` After: ```rust # pyo3::Python::attach(|py| { py.None().get_refcnt(py); # }) ```
## from 0.9.* to 0.10 ### `ObjectProtocol` is removed
Click to expand All methods are moved to [`PyAny`]. And since now all native types (e.g., `PyList`) implements `Deref`, all you need to do is remove `ObjectProtocol` from your code. Or if you use `ObjectProtocol` by `use pyo3::prelude::*`, you have to do nothing. Before: ```rust,compile_fail,ignore use pyo3::ObjectProtocol; # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ``` After: ```rust,ignore # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ```
### No `#![feature(specialization)]` in user code
Click to expand While PyO3 itself still requires specialization and nightly Rust, now you don't have to use `#![feature(specialization)]` in your crate.
## from 0.8.* to 0.9 ### `#[new]` interface
Click to expand [`PyRawObject`](https://docs.rs/pyo3/0.8.5/pyo3/type_object/struct.PyRawObject.html) is now removed and our syntax for constructors has changed. Before: ```rust,compile_fail #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new(obj: &PyRawObject) { obj.init(MyClass {}) } } ``` After: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new() -> Self { MyClass {} } } ``` Basically you can return `Self` or `Result` directly. For more, see [the constructor section](class.md#constructor) of this guide.
### PyCell
Click to expand PyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper for ensuring Rust's rules regarding aliasing of references are upheld. For more detail, see the [Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references) For `#[pymethods]` or `#[pyfunction]`s, your existing code should continue to work without any change. Python exceptions will automatically be raised when your functions are used in a way which breaks Rust's rules of references. Here is an example. ```rust # use pyo3::prelude::*; #[pyclass] struct Names { names: Vec, } #[pymethods] impl Names { #[new] fn new() -> Self { Names { names: vec![] } } fn merge(&mut self, other: &mut Names) { self.names.append(&mut other.names) } } # Python::attach(|py| { # let names = Py::new(py, Names::new()).unwrap(); # pyo3::py_run!(py, names, r" # try: # names.merge(names) # assert False, 'Unreachable' # except RuntimeError as e: # assert str(e) == 'Already borrowed' # "); # }) ``` `Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`. Given this `#[pyclass]`, calling `names.merge(names)` in Python raises a [`PyBorrowMutError`] exception, since it requires two mutable borrows of `names`. However, for `#[pyproto]` and some functions, you need to manually fix the code. #### Object creation In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`. In 0.9 these have both been removed. To upgrade code, please use `PyCell::new` instead. If you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()` on the newly-created `PyCell`. Before: ```rust,compile_fail # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj_ref = PyRef::new(py, MyClass {}).unwrap(); # }) ``` After: ```rust,ignore # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj = PyCell::new(py, MyClass {}).unwrap(); let obj_ref = obj.borrow(); # }) ``` #### Object extraction For `PyClass` types `T`, `&T` and `&mut T` no longer have [`FromPyObject`] implementations. Instead you should extract `PyRef` or `PyRefMut`, respectively. If `T` implements `Clone`, you can extract `T` itself. In addition, you can also extract `&PyCell`, though you rarely need it. Before: ```compile_fail let obj: &PyAny = create_obj(); let obj_ref: &MyClass = obj.extract().unwrap(); let obj_ref_mut: &mut MyClass = obj.extract().unwrap(); ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::IntoPyDict; # #[pyclass] #[derive(Clone)] struct MyClass {} # #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }} # Python::with_gil(|py| { # let typeobj = py.get_type::(); # let d = [("c", typeobj)].into_py_dict(py); # let create_obj = || py.eval("c()", None, Some(d)).unwrap(); let obj: &PyAny = create_obj(); let obj_cell: &PyCell = obj.extract().unwrap(); let obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the object { let obj_ref: PyRef<'_, MyClass> = obj.extract().unwrap(); // we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references } let obj_ref_mut: PyRefMut<'_, MyClass> = obj.extract().unwrap(); # }) ``` #### `#[pyproto]` Most of the arguments to methods in `#[pyproto]` impls require a [`FromPyObject`] implementation. So if your protocol methods take `&T` or `&mut T` (where `T: PyClass`), please use [`PyRef`] or [`PyRefMut`] instead. Before: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: &Self) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ``` After: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: PyRef<'p, Self>) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ```
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html pyo3-0.27.2/guide/src/module.md000064400000000000000000000114761046102023000143120ustar 00000000000000# Python modules You can create a module using `#[pymodule]`: ```rust,no_run # mod declarative_module_basic_test { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } /// This module is implemented in Rust. #[pymodule] mod my_extension { use pyo3::prelude::*; #[pymodule_export] use super::double; // The double function is made available from Python, works also with classes #[pyfunction] // Inline definition of a pyfunction, also made availlable to Python fn triple(x: usize) -> usize { x * 3 } } # } ``` The `#[pymodule]` procedural macro takes care of creating the initialization function of your module and exposing it to Python. The module's name defaults to the name of the Rust module. You can override the module name by using `#[pyo3(name = "custom_name")]`: ```rust,no_run # mod declarative_module_custom_name_test { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule(name = "custom_name")] mod my_extension { #[pymodule_export] use super::double; } # } ``` The name of the module must match the name of the `.so` or `.pyd` file. Otherwise, you will get an import error in Python with the following message: `ImportError: dynamic module does not define module export function (PyInit_name_of_your_module)` To import the module, either: - copy the shared library as described in [Manual builds](building-and-distribution.md#manual-builds), or - use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or `python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust). ## Documentation The [Rust doc comments](https://doc.rust-lang.org/stable/book/ch03-04-comments.html) of the Rust module will be applied automatically as the Python docstring of your module. For example, building off of the above code, this will print `This module is implemented in Rust.`: ```python import my_extension print(my_extension.__doc__) ``` ## Python submodules You can create a module hierarchy within a single extension module by just `use`ing modules like functions or classes. For example, you could define the modules `parent_module` and `parent_module.child_module`: ```rust use pyo3::prelude::*; #[pymodule] mod parent_module { #[pymodule_export] use super::child_module; } #[pymodule] mod child_module { #[pymodule_export] use super::func; } #[pyfunction] fn func() -> String { "func".to_string() } # # fn main() { # Python::attach(|py| { # use pyo3::wrap_pymodule; # use pyo3::types::IntoPyDict; # use pyo3::ffi::c_str; # let parent_module = wrap_pymodule!(parent_module)(py); # let ctx = [("parent_module", parent_module)].into_py_dict(py).unwrap(); # # py.run(c_str!("assert parent_module.child_module.func() == 'func'"), None, Some(&ctx)).unwrap(); # }) } ``` Note that this does not define a package, so this won’t allow Python code to directly import submodules by using `from parent_module import child_module`. For more information, see [#759](https://github.com/PyO3/pyo3/issues/759) and [#1517](https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021). You can provide the `submodule` argument to `#[pymodule()]` for modules that are not top-level modules in order for them to properly generate the `#[pyclass]` `module` attribute automatically. ## Inline declaration It is possible to declare functions, classes, sub-modules and constants inline in a module: For example: ```rust,no_run # mod declarative_module_test { #[pyo3::pymodule] mod my_extension { use pyo3::prelude::*; #[pymodule_export] const PI: f64 = std::f64::consts::PI; // Exports PI constant as part of the module #[pyfunction] // This will be part of the module fn double(x: usize) -> usize { x * 2 } #[pyclass] // This will be part of the module struct Unit; #[pymodule] mod submodule { // This is a submodule use pyo3::prelude::*; #[pyclass] struct Nested; } } # } ``` In this case, `#[pymodule]` macro automatically sets the `module` attribute of the `#[pyclass]` macros declared inside of it with its name. For nested modules, the name of the parent module is automatically added. In the previous example, the `Nested` class will have for `module` `my_extension.submodule`. ## Procedural initialization If the macros provided by PyO3 are not enough, it is possible to run code at the module initialization: ```rust,no_run # mod procedural_module_test { #[pyo3::pymodule] mod my_extension { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { // Arbitrary code to run at the module initialization m.add("double2", m.getattr("double")?) } } # } ``` pyo3-0.27.2/guide/src/parallelism.md000064400000000000000000000213521046102023000153240ustar 00000000000000# Parallelism Historically, CPython was limited by the [global interpreter lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (GIL), which only allowed a single thread to drive the Python interpreter at a time. This made threading in Python a bad fit for [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound) tasks and often forced developers to accept the overhead of multiprocessing. Rust is well-suited to multithreaded code, and libraries like [`rayon`] can help you leverage safe parallelism with minimal effort. The [`Python::detach`] method can be used to allow the Python interpreter to do other work while the Rust work is ongoing. To enable full parallelism in your application, consider also using [free-threaded Python](./free-threading.md) which is supported since Python 3.14. ## Parallelism under the Python GIL Let's take a look at our [word-count](https://github.com/PyO3/pyo3/blob/main/examples/word-count/src/lib.rs) example, where we have a `search` function that utilizes the [`rayon`] crate to count words in parallel. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; // These traits let us use `par_lines` and `map`. use rayon::str::ParallelString; use rayon::iter::ParallelIterator; /// Count the occurrences of needle in line, case insensitive fn count_line(line: &str, needle: &str) -> usize { let mut total = 0; for word in line.split(' ') { if word == needle { total += 1; } } total } #[pyfunction] fn search(contents: &str, needle: &str) -> usize { contents .par_lines() .map(|line| count_line(line, needle)) .sum() } ``` But let's assume you have a long running Rust function which you would like to execute several times in parallel. For the sake of example let's take a sequential version of the word count: ```rust,no_run # #![allow(dead_code)] # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # fn search_sequential(contents: &str, needle: &str) -> usize { contents.lines().map(|line| count_line(line, needle)).sum() } ``` To enable parallel execution of this function, the [`Python::detach`] method can be used to temporarily release the GIL, thus allowing other Python threads to run. We then have a function exposed to the Python runtime which calls `search_sequential` inside a closure passed to [`Python::detach`] to enable true parallelism: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # # fn search_sequential(contents: &str, needle: &str) -> usize { # contents.lines().map(|line| count_line(line, needle)).sum() # } #[pyfunction] fn search_sequential_detached(py: Python<'_>, contents: &str, needle: &str) -> usize { py.detach(|| search_sequential(contents, needle)) } ``` Now Python threads can use more than one CPU core, resolving the limitation which usually makes multi-threading in Python only good for IO-bound tasks: ```Python from concurrent.futures import ThreadPoolExecutor from word_count import search_sequential_detached executor = ThreadPoolExecutor(max_workers=2) future_1 = executor.submit( word_count.search_sequential_detached, contents, needle ) future_2 = executor.submit( word_count.search_sequential_detached, contents, needle ) result_1 = future_1.result() result_2 = future_2.result() ``` ## Benchmark Let's benchmark the `word-count` example to verify that we really did unlock parallelism with PyO3. We are using `pytest-benchmark` to benchmark four word count functions: 1. Pure Python version 2. Rust parallel version 3. Rust sequential version 4. Rust sequential version executed twice with two Python threads The benchmark script can be found [here](https://github.com/PyO3/pyo3/blob/main/examples/word-count/tests/test_word_count.py), and we can run `nox` in the `word-count` folder to benchmark these functions. While the results of the benchmark of course depend on your machine, the relative results should be similar to this (mid 2020): ```text -------------------------------------------------------------------------------------------------- benchmark: 4 tests ------------------------------------------------------------------------------------------------- Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test_word_count_rust_parallel 1.7315 (1.0) 4.6495 (1.0) 1.9972 (1.0) 0.4299 (1.0) 1.8142 (1.0) 0.2049 (1.0) 40;46 500.6943 (1.0) 375 1 test_word_count_rust_sequential 7.3348 (4.24) 10.3556 (2.23) 8.0035 (4.01) 0.7785 (1.81) 7.5597 (4.17) 0.8641 (4.22) 26;5 124.9457 (0.25) 121 1 test_word_count_rust_sequential_twice_with_threads 7.9839 (4.61) 10.3065 (2.22) 8.4511 (4.23) 0.4709 (1.10) 8.2457 (4.55) 0.3927 (1.92) 17;17 118.3274 (0.24) 114 1 test_word_count_python_sequential 27.3985 (15.82) 45.4527 (9.78) 28.9604 (14.50) 4.1449 (9.64) 27.5781 (15.20) 0.4638 (2.26) 3;5 34.5299 (0.07) 35 1 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` You can see that the Python threaded version is not much slower than the Rust sequential version, which means compared to an execution on a single CPU core the speed has doubled. ## Sharing Python objects between Rust threads In the example above we made a Python interface to a low-level rust function, and then leveraged the python `threading` module to run the low-level function in parallel. It is also possible to spawn threads in Rust that acquire the GIL and operate on Python objects. However, care must be taken to avoid writing code that deadlocks with the GIL in these cases. - Note: This example is meant to illustrate how to drop and re-acquire the GIL to avoid creating deadlocks. Unless the spawned threads subsequently release the GIL or you are using the free-threaded build of CPython, you will not see any speedups due to multi-threaded parallelism using `rayon` to parallelize code that acquires and holds the GIL for the entire execution of the spawned thread. In the example below, we share a `Vec` of User ID objects defined using the `pyclass` macro and spawn threads to process the collection of data into a `Vec` of booleans based on a predicate using a `rayon` parallel iterator: ```rust,no_run use pyo3::prelude::*; // These traits let us use int_par_iter and map use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; #[pyclass] struct UserID { id: i64, } let allowed_ids: Vec = Python::attach(|outer_py| { let instances: Vec> = (0..10).map(|x| Py::new(outer_py, UserID { id: x }).unwrap()).collect(); outer_py.detach(|| { instances.par_iter().map(|instance| { Python::attach(|inner_py| { instance.borrow(inner_py).id > 5 }) }).collect() }) }); assert!(allowed_ids.into_iter().filter(|b| *b).count() == 4); ``` It's important to note that there is an `outer_py` Python token as well as an `inner_py` token. Sharing Python tokens between threads is not allowed and threads must individually attach to the interpreter to access data wrapped by a Python object. It's also important to see that this example uses [`Python::detach`] to wrap the code that spawns OS threads via `rayon`. If this example didn't use `detach`, a `rayon` worker thread would block on acquiring the GIL while a thread that owns the GIL spins forever waiting for the result of the `rayon` thread. Calling `detach` allows the GIL to be released in the thread collecting the results from the worker threads. You should always call `detach` in situations that spawn worker threads, but especially so in cases where worker threads need to acquire the GIL, to prevent deadlocks. [`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach [`rayon`]: https://github.com/rayon-rs/rayon pyo3-0.27.2/guide/src/performance.md000064400000000000000000000167661046102023000153350ustar 00000000000000# Performance To achieve the best possible performance, it is useful to be aware of several tricks and sharp edges concerning PyO3's API. ## `extract` versus `cast` Pythonic API implemented using PyO3 are often polymorphic, i.e. they will accept `&Bound<'_, PyAny>` and try to turn this into multiple more concrete types to which the requested operation is applied. This often leads to chains of calls to `extract`, e.g. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { if let Ok(list) = value.extract::>() { frobnicate_list(&list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` This suboptimal as the `FromPyObject` trait requires `extract` to have a `Result` return type. For native types like `PyList`, it faster to use `cast` (which `extract` calls internally) when the error value is ignored. This avoids the costly conversion of a `PyDowncastError` to a `PyErr` required to fulfil the `FromPyObject` contract, i.e. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; # fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } # fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } # #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { // Use `cast` instead of `extract` as turning `PyDowncastError` into `PyErr` is quite costly. if let Ok(list) = value.cast::() { frobnicate_list(list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` ## Access to Bound implies access to Python token Calling `Python::attach` is effectively a no-op when we're already attached to the interpreter, but checking that this is the case still has a cost. If an existing Python token can not be accessed, for example when implementing a pre-existing trait, but a Python-bound reference is available, this cost can be avoided by exploiting that access to Python-bound reference gives zero-cost access to a Python token via `Bound::py`. For example, instead of writing ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; struct Foo(Py); struct FooBound<'py>(Bound<'py, PyList>); impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { Python::attach(|py| { let len = other.0.bind(py).len(); self.0.len() == len }) } } ``` use the more efficient ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # struct Foo(Py); # struct FooBound<'py>(Bound<'py, PyList>); # impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { // Access to `&Bound<'py, PyAny>` implies access to `Python<'py>`. let py = self.0.py(); let len = other.0.bind(py).len(); self.0.len() == len } } ``` ## Calling Python callables (`__call__`) CPython support multiple calling protocols: [`tp_call`] and [`vectorcall`]. [`vectorcall`] is a more efficient protocol unlocking faster calls. PyO3 will try to dispatch Python `call`s using the [`vectorcall`] calling convention to archive maximum performance if possible and falling back to [`tp_call`] otherwise. This is implemented using the (internal) `PyCallArgs` trait. It defines how Rust types can be used as Python `call` arguments. This trait is currently implemented for - Rust tuples, where each member implements `IntoPyObject`, - `Bound<'_, PyTuple>` - `Py` Rust tuples may make use of [`vectorcall`] where as `Bound<'_, PyTuple>` and `Py` can only use [`tp_call`]. For maximum performance prefer using Rust tuples as arguments. [`tp_call`]: https://docs.python.org/3/c-api/call.html#the-tp-call-protocol [`vectorcall`]: https://docs.python.org/3/c-api/call.html#the-vectorcall-protocol ## Detach from the interpreter for long-running Rust-only work When executing Rust code which does not need to interact with the Python interpreter, use [`Python::detach`] to allow the Python interpreter to proceed without waiting for the current thread. On the GIL-enabled build, this is crucial for best performance as only a single thread may ever be attached at a time. On the free-threaded build, this is still best practice as there are several "stop the world" events (such as garbage collection) where all threads attached to the Python interpreter are forced to wait. As a rule of thumb, attaching and detaching from the Python interpreter takes less than a millisecond, so any work which is expected to take multiple milliseconds can likely benefit from detaching from the interpreter. [`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach ## Disable the global reference pool PyO3 uses global mutable state to keep track of deferred reference count updates implied by `impl Drop for Py` being called without being attached to the interpreter. The necessary synchronization to obtain and apply these reference count updates when PyO3-based code next attaches to the interpreter is somewhat expensive and can become a significant part of the cost of crossing the Python-Rust boundary. This functionality can be avoided by setting the `pyo3_disable_reference_pool` conditional compilation flag. This removes the global reference pool and the associated costs completely. However, it does _not_ remove the `Drop` implementation for `Py` which is necessary to interoperate with existing Rust code written without PyO3-based code in mind. To stay compatible with the wider Rust ecosystem in these cases, we keep the implementation but abort when `Drop` is called without being attached to the interpreter. If `pyo3_leak_on_drop_without_reference_pool` is additionally enabled, objects dropped without being attached to Python will be leaked instead which is always sound but might have determinal effects like resource exhaustion in the long term. This limitation is important to keep in mind when this setting is used, especially when embedding Python code into a Rust application as it is quite easy to accidentally drop a `Py` (or types containing it like `PyErr`, `PyBackedStr` or `PyBackedBytes`) returned from `Python::attach` without making sure to re-attach beforehand. For example, the following code ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::attach(|py| PyList::empty(py).unbind()); Python::attach(|py| { numbers.bind(py).append(23).unwrap(); }); Python::attach(|py| { numbers.bind(py).append(42).unwrap(); }); ``` will abort if the list not explicitly disposed via ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::attach(|py| PyList::empty(py).unbind()); Python::attach(|py| { numbers.bind(py).append(23).unwrap(); }); Python::attach(|py| { numbers.bind(py).append(42).unwrap(); }); Python::attach(move |py| { drop(numbers); }); ``` pyo3-0.27.2/guide/src/python-from-rust/calling-existing-code.md000064400000000000000000000264061046102023000224520ustar 00000000000000# Executing existing Python code If you already have some existing Python code that you need to execute from Rust, the following FAQs can help you select the right PyO3 functionality for your situation: ## Want to access Python APIs? Then use `PyModule::import` [`PyModule::import`] can be used to get handle to a Python module from Rust. You can use this to import and use any Python module available in your environment. ```rust use pyo3::prelude::*; fn main() -> PyResult<()> { Python::attach(|py| { let builtins = PyModule::import(py, "builtins")?; let total: i32 = builtins .getattr("sum")? .call1((vec![1, 2, 3],))? .extract()?; assert_eq!(total, 6); Ok(()) }) } ``` [`PyModule::import`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.import ## Want to run just an expression? Then use `eval` [`Python::eval`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval) is a method to execute a [Python expression](https://docs.python.org/3/reference/expressions.html) and return the evaluated value as a `Bound<'py, PyAny>` object. ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; # fn main() -> Result<(), ()> { Python::attach(|py| { let result = py .eval(c_str!("[i * 10 for i in range(5)]"), None, None) .map_err(|e| { e.print_and_set_sys_last_vars(py); })?; let res: Vec = result.extract().unwrap(); assert_eq!(res, vec![0, 10, 20, 30, 40]); Ok(()) }) # } ``` ## Want to run statements? Then use `run` [`Python::run`] is a method to execute one or more [Python statements](https://docs.python.org/3/reference/simple_stmts.html). This method returns nothing (like any Python statement), but you can get access to manipulated objects via the `locals` dict. You can also use the [`py_run!`] macro, which is a shorthand for [`Python::run`]. Since [`py_run!`] panics on exceptions, we recommend you use this macro only for quickly testing your Python extensions. ```rust use pyo3::prelude::*; use pyo3::py_run; # fn main() { #[pyclass] struct UserData { id: u32, name: String, } #[pymethods] impl UserData { fn as_tuple(&self) -> (u32, String) { (self.id, self.name.clone()) } fn __repr__(&self) -> PyResult { Ok(format!("User {}(id: {})", self.name, self.id)) } } Python::attach(|py| { let userdata = UserData { id: 34, name: "Yu".to_string(), }; let userdata = Py::new(py, userdata).unwrap(); let userdata_as_tuple = (34, "Yu"); py_run!(py, userdata userdata_as_tuple, r#" assert repr(userdata) == "User Yu(id: 34)" assert userdata.as_tuple() == userdata_as_tuple "#); }) # } ``` ## You have a Python file or code snippet? Then use `PyModule::from_code` [`PyModule::from_code`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.from_code) can be used to generate a Python module which can then be used just as if it was imported with `PyModule::import`. **Warning**: This will compile and execute code. **Never** pass untrusted code to this function! ```rust use pyo3::{prelude::*, types::IntoPyDict}; use pyo3_ffi::c_str; # fn main() -> PyResult<()> { Python::attach(|py| { let activators = PyModule::from_code( py, c_str!(r#" def relu(x): """see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)""" return max(0.0, x) def leaky_relu(x, slope=0.01): return x if x >= 0 else x * slope "#), c_str!("activators.py"), c_str!("activators"), )?; let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?; assert_eq!(relu_result, 0.0); let kwargs = [("slope", 0.2)].into_py_dict(py)?; let lrelu_result: f64 = activators .getattr("leaky_relu")? .call((-1.0,), Some(&kwargs))? .extract()?; assert_eq!(lrelu_result, -0.2); # Ok(()) }) # } ``` ## Want to embed Python in Rust with additional modules? Python maintains the `sys.modules` dict as a cache of all imported modules. An import in Python will first attempt to lookup the module from this dict, and if not present will use various strategies to attempt to locate and load the module. The [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) macro can be used to add additional `#[pymodule]` modules to an embedded Python interpreter. The macro **must** be invoked _before_ initializing Python. As an example, the below adds the module `foo` to the embedded interpreter: ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; #[pymodule] mod foo { use pyo3::prelude::*; #[pyfunction] fn add_one(x: i64) -> i64 { x + 1 } } fn main() -> PyResult<()> { pyo3::append_to_inittab!(foo); Python::attach(|py| Python::run(py, c_str!("import foo; foo.add_one(6)"), None, None)) } ``` If `append_to_inittab` cannot be used due to constraints in the program, an alternative is to create a module using [`PyModule::new`] and insert it manually into `sys.modules`: ```rust use pyo3::prelude::*; use pyo3::types::PyDict; use pyo3::ffi::c_str; #[pyfunction] pub fn add_one(x: i64) -> i64 { x + 1 } fn main() -> PyResult<()> { Python::attach(|py| { // Create new module let foo_module = PyModule::new(py, "foo")?; foo_module.add_function(wrap_pyfunction!(add_one, &foo_module)?)?; // Import and get sys.modules let sys = PyModule::import(py, "sys")?; let py_modules: Bound<'_, PyDict> = sys.getattr("modules")?.cast_into()?; // Insert foo into sys.modules py_modules.set_item("foo", foo_module)?; // Now we can import + run our python code Python::run(py, c_str!("import foo; foo.add_one(6)"), None, None) }) } ``` ## Include multiple Python files You can include a file at compile time by using [`std::include_str`](https://doc.rust-lang.org/std/macro.include_str.html) macro. Or you can load a file at runtime by using [`std::fs::read_to_string`](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) function. Many Python files can be included and loaded as modules. If one file depends on another you must preserve correct order while declaring `PyModule`. Example directory structure: ```text . ├── Cargo.lock ├── Cargo.toml ├── python_app │ ├── app.py │ └── utils │ └── foo.py └── src └── main.rs ``` `python_app/app.py`: ```python from utils.foo import bar def run(): return bar() ``` `python_app/utils/foo.py`: ```python def bar(): return "baz" ``` The example below shows: - how to include content of `app.py` and `utils/foo.py` into your rust binary - how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` `src/main.rs`: ```rust,ignore use pyo3::prelude::*; use pyo3_ffi::c_str; fn main() -> PyResult<()> { let py_foo = c_str!(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/python_app/utils/foo.py" ))); let py_app = c_str!(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py"))); let from_python = Python::attach(|py| -> PyResult> { PyModule::from_code(py, py_foo, c_str!("foo.py"), c_str!("utils.foo"))?; let app: Py = PyModule::from_code(py, py_app, c_str!("app.py"), c_str!(""))? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` The example below shows: - how to load content of `app.py` at runtime so that it sees its dependencies automatically - how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` It is recommended to use absolute paths because then your binary can be run from anywhere as long as your `app.py` is in the expected directory (in this example that directory is `/usr/share/python_app`). `src/main.rs`: ```rust,no_run use pyo3::prelude::*; use pyo3::types::PyList; use pyo3_ffi::c_str; use std::fs; use std::path::Path; use std::ffi::CString; fn main() -> PyResult<()> { let path = Path::new("/usr/share/python_app"); let py_app = CString::new(fs::read_to_string(path.join("app.py"))?)?; let from_python = Python::attach(|py| -> PyResult> { let syspath = py .import("sys")? .getattr("path")? .cast_into::()?; syspath.insert(0, path)?; let app: Py = PyModule::from_code(py, py_app.as_c_str(), c_str!("app.py"), c_str!(""))? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` ## Need to use a context manager from Rust? Use context managers by directly invoking `__enter__` and `__exit__`. ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; fn main() { Python::attach(|py| { let custom_manager = PyModule::from_code( py, c_str!(r#" class House(object): def __init__(self, address): self.address = address def __enter__(self): print(f"Welcome to {self.address}!") def __exit__(self, type, value, traceback): if type: print(f"Sorry you had {type} trouble at {self.address}") else: print(f"Thank you for visiting {self.address}, come again soon!") "#), c_str!("house.py"), c_str!("house"), ) .unwrap(); let house_class = custom_manager.getattr("House").unwrap(); let house = house_class.call1(("123 Main Street",)).unwrap(); house.call_method0("__enter__").unwrap(); let result = py.eval(c_str!("undefined_variable + 1"), None, None); // If the eval threw an exception we'll pass it through to the context manager. // Otherwise, __exit__ is called with empty arguments (Python "None"). match result { Ok(_) => { let none = py.None(); house .call_method1("__exit__", (&none, &none, &none)) .unwrap(); } Err(e) => { house .call_method1( "__exit__", ( e.get_type(py), e.value(py), e.traceback(py), ), ) .unwrap(); } } }) } ``` ## Handling system signals/interrupts (Ctrl-C) The best way to handle system signals when running Rust code is to periodically call `Python::check_signals` to handle any signals captured by Python's signal handler. See also [the FAQ entry](../faq.md#ctrl-c-doesnt-do-anything-while-my-rust-code-is-executing). Alternatively, set Python's `signal` module to take the default action for a signal: ```rust use pyo3::prelude::*; # fn main() -> PyResult<()> { Python::attach(|py| -> PyResult<()> { let signal = py.import("signal")?; // Set SIGINT to have the default action signal .getattr("signal")? .call1((signal.getattr("SIGINT")?, signal.getattr("SIG_DFL")?))?; Ok(()) }) # } ``` [`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html [`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.run [`PyModule::new`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.new pyo3-0.27.2/guide/src/python-from-rust/function-calls.md000064400000000000000000000104671046102023000212220ustar 00000000000000# Calling Python functions The `Bound<'py, T>` smart pointer (such as `Bound<'py, PyAny>`, `Bound<'py, PyList>`, or `Bound<'py, MyClass>`) can be used to call Python functions. PyO3 offers two APIs to make function calls: - [`call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) - call any callable Python object. - [`call_method`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method) - call a method on the Python object. Both of these APIs take `args` and `kwargs` arguments (for positional and keyword arguments respectively). There are variants for less complex calls: - [`call1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call1) and [`call_method1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method1) to call only with positional `args`. - [`call0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call0) and [`call_method0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method0) to call with no arguments. For convenience the [`Py`](../types.md#pyt) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the thread is attached to the Python interpreter. The example below calls a Python function behind a `Py` reference: ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; use pyo3_ffi::c_str; fn main() -> PyResult<()> { let arg1 = "arg1"; let arg2 = "arg2"; let arg3 = "arg3"; Python::attach(|py| { let fun: Py = PyModule::from_code( py, c_str!("def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')"), c_str!("example.py"), c_str!(""), )? .getattr("example")? .into(); // call object without any arguments fun.call0(py)?; // pass object with Rust tuple of positional arguments let args = (arg1, arg2, arg3); fun.call1(py, args)?; // call object with Python tuple of positional arguments let args = PyTuple::new(py, &[arg1, arg2, arg3])?; fun.call1(py, args)?; Ok(()) }) } ``` ## Creating keyword arguments For the `call` and `call_method` APIs, `kwargs` are `Option<&Bound<'py, PyDict>>`, so can either be `None` or `Some(&dict)`. You can use the [`IntoPyDict`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple. To pass keyword arguments of different types, construct a `PyDict` object. ```rust use pyo3::prelude::*; use pyo3::types::{PyDict, IntoPyDict}; use std::collections::HashMap; use pyo3::ffi::c_str; fn main() -> PyResult<()> { let key1 = "key1"; let val1 = 1; let key2 = "key2"; let val2 = 2; Python::attach(|py| { let fun: Py = PyModule::from_code( py, c_str!("def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')"), c_str!("example.py"), c_str!(""), )? .getattr("example")? .into(); // call object with PyDict let kwargs = [(key1, val1)].into_py_dict(py)?; fun.call(py, (), Some(&kwargs))?; // pass arguments as Vec let kwargs = vec![(key1, val1), (key2, val2)]; fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; // pass arguments of different types as PyDict let kwargs = PyDict::new(py); kwargs.set_item(key1, val1)?; kwargs.set_item(key2, "string")?; fun.call(py, (), Some(&kwargs))?; Ok(()) }) } ``` pyo3-0.27.2/guide/src/python-from-rust.md000064400000000000000000000076101046102023000162750ustar 00000000000000# Calling Python in Rust code This chapter of the guide documents some ways to interact with Python code from Rust. Below is an introduction to the `'py` lifetime and some general remarks about how PyO3's API reasons about Python code. The subchapters also cover the following topics: - Python object types available in PyO3's API - How to work with Python exceptions - How to call Python functions - How to execute existing Python code ## The `'py` lifetime To safely interact with the Python interpreter a Rust thread must be [attached] to the Python interpreter. PyO3 has a `Python<'py>` token that is used to prove that these conditions are met. Its lifetime `'py` is a central part of PyO3's API. The `Python<'py>` token serves three purposes: - It provides global APIs for the Python interpreter, such as [`py.eval()`][eval] and [`py.import()`][import]. - It can be passed to functions that require a proof of attachment, such as [`Py::clone_ref`][clone_ref]. - Its lifetime `'py` is used to bind many of PyO3's types to the Python interpreter, such as [`Bound<'py, T>`][Bound]. PyO3's types that are bound to the `'py` lifetime, for example `Bound<'py, T>`, all contain a `Python<'py>` token. This means they have full access to the Python interpreter and offer a complete API for interacting with Python objects. Consult [PyO3's API documentation][obtaining-py] to learn how to acquire one of these tokens. ### The Global Interpreter Lock Prior to the introduction of free-threaded Python (first available in 3.13, fully supported in 3.14), the Python interpreter was made thread-safe by the [global interpreter lock]. This ensured that only one Python thread can use the Python interpreter and its API at the same time. Historically, Rust code was able to use the GIL as a synchronization guarantee, but the introduction of free-threaded Python removed this possibility. The [`pyo3::sync`] module offers synchronization tools which abstract over both Python builds. To enable any parallelism on the GIL-enabled build, and best throughput on the free-threaded build, non-Python operations (system calls and native Rust code) should consider detaching from the Python interpreter to allow other work to proceed. See [the section on parallelism](parallelism.md) for how to do that using PyO3's API. ## Python's memory model Python's memory model differs from Rust's memory model in two key ways: - There is no concept of ownership; all Python objects are shared and usually implemented via reference counting - There is no concept of exclusive (`&mut`) references; any reference can mutate a Python object PyO3's API reflects this by providing [smart pointer][smart-pointers] types, `Py`, `Bound<'py, T>`, and (the very rarely used) `Borrowed<'a, 'py, T>`. These smart pointers all use Python reference counting. See the [subchapter on types](./types.md) for more detail on these types. Because of the lack of exclusive `&mut` references, PyO3's APIs for Python objects, for example [`PyListMethods::append`], use shared references. This is safe because Python objects have internal mechanisms to prevent data races (as of time of writing, the Python GIL). [attached]: https://docs.python.org/3.14/glossary.html#term-attached-thread-state [global interpreter lock]: https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html [obtaining-py]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#obtaining-a-python-token [`pyo3::sync`]: {{#PYO3_DOCS_URL}}/pyo3/sync/index.html [eval]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval [import]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.import [clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.Py.html#method.clone_ref [Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`PyListMethods::append`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyListMethods.html#tymethod.append pyo3-0.27.2/guide/src/python-typing-hints.md000064400000000000000000000260721046102023000167770ustar 00000000000000# Typing and IDE hints for your Python package PyO3 provides an easy to use interface to code native Python libraries in Rust. The accompanying Maturin allows you to build and publish them as a package. Yet, for a better user experience, Python libraries should provide typing hints and documentation for all public entities, so that IDEs can show them during development and type analyzing tools such as `mypy` can use them to properly verify the code. Currently the best solution for the problem is to manually maintain `*.pyi` files and ship them along with the package. PyO3 is working on automated their generation. See the [type stub generation](type-stub.md) documentation for a description of the current state of automated generation. ## Introduction to `pyi` files `pyi` files (an abbreviation for `Python Interface`) are called "stub files" in most of the documentation related to them. A very good definition of what it is can be found in [old MyPy documentation](https://github.com/python/mypy/wiki/Creating-Stubs-For-Python-Modules): > A stubs file only contains a description of the public interface of the module without any implementations. There is also [extensive documentation on type stubs on the official Python typing documentation](https://typing.readthedocs.io/en/latest/source/stubs.html). Most Python developers probably already encountered them when trying to use their IDE's "Go to Definition" function on any builtin type. For example, the definitions of a few standard exceptions look like this: ```python class BaseException(object): args: Tuple[Any, ...] __cause__: BaseException | None __context__: BaseException | None __suppress_context__: bool __traceback__: TracebackType | None def __init__(self, *args: object) -> None: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... def with_traceback(self: _TBE, tb: TracebackType | None) -> _TBE: ... class SystemExit(BaseException): code: int class Exception(BaseException): ... class StopIteration(Exception): value: Any ``` As we can see, those are not full definitions containing implementation, but just a description of the interface. It is usually all that the user of the library needs. ### What do the PEPs say? At the time of writing this documentation, the `pyi` files are referenced in four PEPs. [PEP8 - Style Guide for Python Code - #Function Annotations](https://www.python.org/dev/peps/pep-0008/#function-annotations) (last point) recommends all third party library creators to provide stub files as the source of knowledge about the package for type checker tools. > (...) it is expected that users of third party library packages may want to run type checkers over those packages. For this purpose [PEP 484](https://www.python.org/dev/peps/pep-0484) recommends the use of stub files: .pyi files that are read by the type checker in preference of the corresponding .py files. (...) [PEP484 - Type Hints - #Stub Files](https://www.python.org/dev/peps/pep-0484/#stub-files) defines stub files as follows. > Stub files are files containing type hints that are only for use by the type checker, not at runtime. It contains a specification for them (highly recommended reading, since it contains at least one thing that is not used in normal Python code) and also some general information about where to store the stub files. [PEP561 - Distributing and Packaging Type Information](https://www.python.org/dev/peps/pep-0561/) describes in detail how to build packages that will enable type checking. In particular it contains information about how the stub files must be distributed in order for type checkers to use them. [PEP560 - Core support for typing module and generic types](https://www.python.org/dev/peps/pep-0560/) describes the details on how Python's type system internally supports generics, including both runtime behavior and integration with static type checkers. ## How to do it? [PEP561](https://www.python.org/dev/peps/pep-0561/) recognizes three ways of distributing type information: - `inline` - the typing is placed directly in source (`py`) files; - `separate package with stub files` - the typing is placed in `pyi` files distributed in their own, separate package; - `in-package stub files` - the typing is placed in `pyi` files distributed in the same package as source files. The first way is tricky with PyO3 since we do not have `py` files. When it has been investigated and necessary changes are implemented, this document will be updated. The second way is easy to do, and the whole work can be fully separated from the main library code. The example repo for the package with stub files can be found in [PEP561 references section](https://www.python.org/dev/peps/pep-0561/#references): [Stub package repository](https://github.com/ethanhs/stub-package) The third way is described below. ### Including `pyi` files in your PyO3/Maturin build package When source files are in the same package as stub files, they should be placed next to each other. We need a way to do that with Maturin. Also, in order to mark our package as typing-enabled we need to add an empty file named `py.typed` to the package. #### If you do not have other Python files If you do not need to add any other Python files apart from `pyi` to the package, Maturin provides a way to do most of the work for you. As documented in the [Maturin Guide](https://github.com/PyO3/maturin/#mixed-rustpython-projects), the only thing you need to do is to create a stub file for your module named `.pyi` in your project root and Maturin will do the rest. ```text my-rust-project/ ├── Cargo.toml ├── my_project.pyi # <<< add type stubs for Rust functions in the my_project module here ├── pyproject.toml └── src └── lib.rs ``` For an example `pyi` file see the [`my_project.pyi` content](#my_projectpyi-content) section. #### If you need other Python files If you need to add other Python files apart from `pyi` to the package, you can do it also, but that requires some more work. Maturin provides an easy way to add files to a package ([documentation](https://github.com/PyO3/maturin/blob/0dee40510083c03607834c821eea76964140a126/Readme.md#mixed-rustpython-projects)). You just need to create a folder with the name of your module next to the `Cargo.toml` file (for customization see documentation linked above). The folder structure would be: ```text my-project ├── Cargo.toml ├── my_project │ ├── __init__.py │ ├── my_project.pyi │ ├── other_python_file.py │ └── py.typed ├── pyproject.toml ├── Readme.md └── src └── lib.rs ``` Let's go a little bit more into detail regarding the files inside the package folder. ##### `__init__.py` content As we now specify our own package content, we have to provide the `__init__.py` file, so the folder is treated as a package and we can import things from it. We can always use the same content that Maturin creates for us if we do not specify a Python source folder. For PyO3 bindings it would be: ```python from .my_project import * ``` That way everything that is exposed by our native module can be imported directly from the package. ##### `py.typed` requirement As stated in [PEP561](https://www.python.org/dev/peps/pep-0561/): > Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing. This marker applies recursively: if a top-level package includes it, all its sub-packages MUST support type checking as well. If we do not include that file, some IDEs might still use our `pyi` files to show hints, but the type checkers might not. MyPy will raise an error in this situation: ```text error: Skipping analyzing "my_project": found module but no type hints or library stubs ``` The file is just a marker file, so it should be empty. ##### `my_project.pyi` content Our module stub file. This document does not aim at describing how to write them, since you can find a lot of documentation on it, starting from the already quoted [PEP484](https://www.python.org/dev/peps/pep-0484/#stub-files). The example can look like this: ```python class Car: """ A class representing a car. :param body_type: the name of body type, e.g. hatchback, sedan :param horsepower: power of the engine in horsepower """ def __init__(self, body_type: str, horsepower: int) -> None: ... @classmethod def from_unique_name(cls, name: str) -> 'Car': """ Creates a Car based on unique name :param name: model name of a car to be created :return: a Car instance with default data """ def best_color(self) -> str: """ Gets the best color for the car. :return: the name of the color our great algorithm thinks is the best for this car """ ``` ### Supporting Generics Type annotations can also be made generic in Python. They are useful for working with different types while maintaining type safety. Usually, generic classes inherit from the `typing.Generic` metaclass. Take for example the following `.pyi` file that specifies a `Car` that can accept multiple types of wheels: ```python from typing import Generic, TypeVar W = TypeVar('W') class Car(Generic[W]): def __init__(self, wheels: list[W]) -> None: ... def get_wheels(self) -> list[W]: ... def change_wheel(self, wheel_number: int, wheel: W) -> None: ... ``` This way, the end-user can specify the type with variables such as `truck: Car[SteelWheel] = ...` and `f1_car: Car[AlloyWheel] = ...`. There is also a special syntax for specifying generic types in Python 3.12+: ```python class Car[W]: def __init__(self, wheels: list[W]) -> None: ... def get_wheels(self) -> list[W]: ... ``` #### Runtime Behaviour Stub files (`pyi`) are only useful for static type checkers and ignored at runtime. Therefore, PyO3 classes do not inherit from `typing.Generic` even if specified in the stub files. This can cause some runtime issues, as annotating a variable like `f1_car: Car[AlloyWheel] = ...` can make Python call magic methods that are not defined. To overcome this limitation, implementers can pass the `generic` parameter to `pyclass` in Rust: ```rust ignore #[pyclass(generic)] ``` #### Advanced Users `#[pyclass(generic)]` implements a very simple runtime behavior that accepts any generic argument. Advanced users can opt to manually implement [`__class_geitem__`](https://docs.python.org/3/reference/datamodel.html#emulating-generic-types) for the generic class to have more control. ```rust ignore impl MyClass { #[classmethod] #[pyo3(signature = (key, /))] pub fn __class_getitem__( cls: &Bound<'_, PyType>, key: &Bound<'_, PyAny>, ) -> PyResult> { /* implementation details */ } } ``` Note that [`pyo3::types::PyGenericAlias`][pygenericalias] can be helpful when implementing `__class_getitem__` as it can create [`types.GenericAlias`][genericalias] objects from Rust. [pygenericalias]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyGenericAlias.html [genericalias]: https://docs.python.org/3/library/types.html#types.GenericAlias pyo3-0.27.2/guide/src/rust-from-python.md000064400000000000000000000010631046102023000162710ustar 00000000000000# Using Rust from Python This chapter of the guide is dedicated to explaining how to wrap Rust code into Python objects. PyO3 uses Rust's "procedural macros" to provide a powerful yet simple API to denote what Rust code should map into Python objects. PyO3 can create three types of Python objects: - Python modules, via the `#[pymodule]` macro - Python functions, via the `#[pyfunction]` macro - Python classes, via the `#[pyclass]` macro (plus `#[pymethods]` to define methods for those classes) The following subchapters go through each of these in turn. pyo3-0.27.2/guide/src/trait-bounds.md000064400000000000000000000405151046102023000154340ustar 00000000000000# Using in Python a Rust function with trait bounds PyO3 allows for easy conversion from Rust to Python for certain functions and classes (see the [conversion table](conversions/tables.md)). However, it is not always straightforward to convert Rust code that requires a given trait implementation as an argument. This tutorial explains how to convert a Rust function that takes a trait as argument for use in Python with classes implementing the same methods as the trait. Why is this useful? ## Pros - Make your Rust code available to Python users - Code complex algorithms in Rust with the help of the borrow checker ### Cons - Not as fast as native Rust (type conversion has to be performed and one part of the code runs in Python) - You need to adapt your code to expose it ## Example Let's work with the following basic example of an implementation of a optimization solver operating on a given model. Let's say we have a function `solve` that operates on a model and mutates its state. The argument of the function can be any model that implements the `Model` trait : ```rust,no_run # #![allow(dead_code)] pub trait Model { fn set_variables(&mut self, inputs: &Vec); fn compute(&mut self); fn get_results(&self) -> Vec; } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } ``` Let's assume we have the following constraints: - We cannot change that code as it runs on many Rust models. - We also have many Python models that cannot be solved as this solver is not available in that language. Rewriting it in Python would be cumbersome and error-prone, as everything is already available in Rust. How could we expose this solver to Python thanks to PyO3 ? ## Implementation of the trait bounds for the Python class If a Python class implements the same three methods as the `Model` trait, it seems logical it could be adapted to use the solver. However, it is not possible to pass a `Py` to it as it does not implement the Rust trait (even if the Python model has the required methods). In order to implement the trait, we must write a wrapper around the calls in Rust to the Python model. The method signatures must be the same as the trait, keeping in mind that the Rust trait cannot be changed for the purpose of making the code available in Python. The Python model we want to expose is the following one, which already contains all the required methods: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results ``` The following wrapper will call the Python model from Rust, using a struct to hold the model as a `PyAny` object: ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyList; # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } struct UserModel { model: Py, } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::attach(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::attach(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::attach(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` Now that this bit is implemented, let's expose the model wrapper to Python. Let's add the PyO3 annotations and add a constructor: ```rust,no_run # #![allow(dead_code)] # fn main() {} # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # use pyo3::prelude::*; #[pyclass] struct UserModel { model: Py, } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } } #[pymodule] mod trait_exposure { #[pymodule_export] use super::UserModel; } ``` Now we add the PyO3 annotations to the trait implementation: ```rust,ignore #[pymethods] impl Model for UserModel { // the previous trait implementation } ``` However, the previous code will not compile. The compilation error is the following one: `error: #[pymethods] cannot be used on trait impl blocks` That's a bummer! However, we can write a second wrapper around these functions to call them directly. This wrapper will also perform the type conversions between Python and Rust. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } # # impl Model for UserModel { # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::attach(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn get_results(&self) -> Vec { # println!("Rust calling Python to get the results"); # Python::attach(|py| { # self.model # .bind(py) # .call_method("get_results", (), None) # .unwrap() # .extract() # .unwrap() # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::attach(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # # } # } #[pymethods] impl UserModel { pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { println!("Compute from Python calling Rust"); Model::compute(self) } } ``` This wrapper handles the type conversion between the PyO3 requirements and the trait. In order to meet PyO3 requirements, this wrapper must: - return an object of type `PyResult` - use only values, not references in the method signatures Let's run the file python file: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results if __name__=="__main__": import trait_exposure myModel = Model() my_rust_model = trait_exposure.UserModel(myModel) my_rust_model.set_variables([2.0]) print("Print value from Python: ", myModel.inputs) my_rust_model.compute() print("Print value from Python through Rust: ", my_rust_model.get_results()) print("Print value directly from Python: ", myModel.get_results()) ``` This outputs: ```block Set variables from Python calling Rust Set variables from Rust calling Python Print value from Python: [2.0] Compute from Python calling Rust Compute from Rust calling Python Get results from Python calling Rust Get results from Rust calling Python Print value from Python through Rust: [1.0] Print value directly from Python: [1.0] ``` We have now successfully exposed a Rust model that implements the `Model` trait to Python! We will now expose the `solve` function, but before, let's talk about types errors. ## Type errors in Python What happens if you have type errors when using Python and how can you improve the error messages? ### Wrong types in Python function arguments Let's assume in the first case that you will use in your Python file `my_rust_model.set_variables(2.0)` instead of `my_rust_model.set_variables([2.0])`. The Rust signature expects a vector, which corresponds to a list in Python. What happens if instead of a vector, we pass a single value ? At the execution of Python, we get : ```block File "main.py", line 15, in my_rust_model.set_variables(2) TypeError ``` It is a type error and Python points to it, so it's easy to identify and solve. ### Wrong types in Python method signatures Let's assume now that the return type of one of the methods of our Model class is wrong, for example the `get_results` method that is expected to return a `Vec` in Rust, a list in Python. ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 -3 for elt in self.inputs] def get_results(self): return self.results[0] #return self.results <-- this is the expected output ``` This call results in the following panic: ```block pyo3_runtime.PanicException: called `Result::unwrap()` on an `Err` value: PyErr { type: Py(0x10dcf79f0, PhantomData) } ``` This error code is not helpful for a Python user that does not know anything about Rust, or someone that does not know PyO3 was used to interface the Rust code. However, as we are responsible for making the Rust code available to Python, we can do something about it. The issue is that we called `unwrap` anywhere we could, and therefore any panic from PyO3 will be directly forwarded to the end user. Let's modify the code performing the type conversion to give a helpful error message to the Python user: We used in our `get_results` method the following call that performs the type conversion: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::attach(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::attach(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::attach(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` Let's break it down in order to perform better error handling: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::attach(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::attach(|py| { # let py_model = self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::attach(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` By doing so, you catch the result of the Python computation and check its type in order to be able to deliver a better error message before performing the unwrapping. Of course, it does not cover all the possible wrong outputs: the user could return a list of strings instead of a list of floats. In this case, a runtime panic would still occur due to PyO3, but with an error message much more difficult to decipher for non-rust user. It is up to the developer exposing the rust code to decide how much effort to invest into Python type error handling and improved error messages. ## The final code Now let's expose the `solve()` function to make it available from Python. It is not possible to directly expose the `solve` function to Python, as the type conversion cannot be performed. It requires an object implementing the `Model` trait as input. However, the `UserModel` already implements this trait. Because of this, we can write a function wrapper that takes the `UserModel`--which has already been exposed to Python--as an argument in order to call the core function `solve`. It is also required to make the struct public. ```rust,no_run # #![allow(dead_code)] # fn main() {} use pyo3::prelude::*; use pyo3::types::PyList; pub trait Model { fn set_variables(&mut self, var: &Vec); fn get_results(&self) -> Vec; fn compute(&mut self); } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } #[pyfunction] #[pyo3(name = "solve")] pub fn solve_wrapper(model: &mut UserModel) { solve(model); } #[pyclass] pub struct UserModel { model: Py, } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { Model::compute(self) } } #[pymodule] mod trait_exposure { #[pymodule_export] use super::{UserModel, solve_wrapper}; } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::attach(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::attach(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::attach(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` pyo3-0.27.2/guide/src/type-stub.md000064400000000000000000000063431046102023000147560ustar 00000000000000# Type stub generation (`*.pyi` files) and introspection *This feature is still in active development. See [the related issue](https://github.com/PyO3/pyo3/issues/5137).* *For documentation on type stubs and how to use them with stable PyO3, refer to [this page](python-typing-hints.md)* PyO3 has a work in progress support to generate [type stub files](https://typing.python.org/en/latest/spec/distributing.html#stub-files). It works using: 1. PyO3 macros (`#[pyclass]`) that generate constant JSON strings that are then included in the built binaries by rustc if the `experimental-inspect` feature is enabled. 2. The `pyo3-introspection` crate that can parse the generated binaries, extract the JSON strings and build stub files from it. 3. \[Not done yet\] Build tools like `maturin` exposing `pyo3-introspection` features in their CLI API. For example, the following Rust code ```rust #[pymodule] pub mod example { use pyo3::prelude::*; #[pymodule_export] pub const CONSTANT: &str = "FOO"; #[pyclass(eq)] #[derive(Eq)] struct Class { value: usize } #[pymethods] impl Class { #[new] fn new(value: usize) -> Self { Self { value } } #[getter] fn value(&self) -> usize { self.value } } #[pyfunction] #[pyo3(signature = (arg: "list[int]") -> "list[int]")] fn list_of_int_identity(arg: Bound<'_, PyAny>) -> Bound<'_, PyAny> { arg } } ``` will generate the following stub file: ```python import typing CONSTANT: typing.Final = "FOO" class Class: def __init__(self, value: int) -> None: ... @property def value(self) -> int: ... def __eq__(self, other: Class) -> bool: ... def __ne__(self, other: Class) -> bool: ... def list_of_int_identity(arg: list[int]) -> list[int]: ... ``` The only piece of added syntax is that the `#[pyo3(signature = ...)]` attribute can now contain type annotations like `#[pyo3(signature = (arg: "list[int]") -> "list[int]")]` (note the `""` around type annotations). This is useful when PyO3 is not able to derive proper type annotations by itself. ## Constraints and limitations - The `experimental-inspect` feature is required to generate the introspection fragments. - Lots of features are not implemented yet. See [the related issue](https://github.com/PyO3/pyo3/issues/5137) for a list of them. - Introspection only works with Python modules declared with an inline Rust module. Modules declared using a function are not supported. - `FromPyObject::INPUT_TYPE` and `IntoPyObject::OUTPUT_TYPE` must be implemented for PyO3 to get the proper input/output type annotations to use. - Because `FromPyObject::INPUT_TYPE` and `IntoPyObject::OUTPUT_TYPE` are `const` it is not possible to build yet smart generic annotations for containers like `concat!("list[", T::OUTPUT_TYPE, "]")`. See [this tracking issue](https://github.com/rust-lang/rust/issues/76560). - PyO3 is not able to introspect the content of `#[pymodule]` and `#[pymodule_init]` functions. If they are present, the module is tagged as incomplete using a fake `def __getattr__(name: str) -> Incomplete: ...` function [following best practices](https://typing.python.org/en/latest/guides/writing_stubs.html#incomplete-stubs). pyo3-0.27.2/guide/src/types.md000064400000000000000000000422031046102023000141610ustar 00000000000000# Python object types PyO3 offers two main sets of types to interact with Python objects. This section of the guide expands into detail about these types and how to choose which to use. The first set of types are the [smart pointers][smart-pointers] which all Python objects are wrapped in. These are `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`. The [first section below](#pyo3s-smart-pointers) expands on each of these in detail and why there are three of them. The second set of types are types which fill in the generic parameter `T` of the smart pointers. The most common is `PyAny`, which represents any Python object (similar to Python's `typing.Any`). There are also concrete types for many Python built-in types, such as `PyList`, `PyDict`, and `PyTuple`. User defined `#[pyclass]` types also fit this category. The [second section below](#concrete-python-types) expands on how to use these types. ## PyO3's smart pointers PyO3's API offers three generic smart pointers: `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>`. For each of these the type parameter `T` will be filled by a [concrete Python type](#concrete-python-types). For example, a Python list object can be represented by `Py`, `Bound<'py, PyList>`, and `Borrowed<'a, 'py, PyList>`. These smart pointers behave differently due to their lifetime parameters. `Py` has no lifetime parameters, `Bound<'py, T>` has [the `'py` lifetime](./python-from-rust.md#the-py-lifetime) as a parameter, and `Borrowed<'a, 'py, T>` has the `'py` lifetime plus an additional lifetime `'a` to denote the lifetime it is borrowing data for. (You can read more about these lifetimes in the subsections below). Python objects are reference counted, like [`std::sync::Arc`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html). A major reason for these smart pointers is to bring Python's reference counting to a Rust API. The recommendation of when to use each of these smart pointers is as follows: - Use `Bound<'py, T>` for as much as possible, as it offers the most efficient and complete API. - Use `Py` mostly just for storage inside Rust `struct`s which do not want to or can't add a lifetime parameter for `Bound<'py, T>`. - `Borrowed<'a, 'py, T>` is almost never used. It is occasionally present at the boundary between Rust and the Python interpreter, for example when borrowing data from Python tuples (which is safe because they are immutable). The sections below also explain these smart pointers in a little more detail. ### `Py` [`Py`][Py] is the foundational smart pointer in PyO3's API. The type parameter `T` denotes the type of the Python object. Very frequently this is `PyAny`, meaning any Python object. Because `Py` is not bound to [the `'py` lifetime](./python-from-rust.md#the-py-lifetime), it is the type to use when storing a Python object inside a Rust `struct` or `enum` which do not want to have a lifetime parameter. In particular, [`#[pyclass]`][pyclass] types are not permitted to have a lifetime, so `Py` is the correct type to store Python objects inside them. The lack of binding to the `'py` lifetime also carries drawbacks: - Almost all methods on `Py` require a `Python<'py>` token as the first argument - Other functionality, such as [`Drop`][Drop], needs to check at runtime for attachment to the Python interpreter, at a small performance cost Because of the drawbacks `Bound<'py, T>` is preferred for many of PyO3's APIs. In particular, `Bound<'py, T>` is better for function arguments. To convert a `Py` into a `Bound<'py, T>`, the `Py::bind` and `Py::into_bound` methods are available. `Bound<'py, T>` can be converted back into `Py` using [`Bound::unbind`]. ### `Bound<'py, T>` [`Bound<'py, T>`][Bound] is the counterpart to `Py` which is also bound to the `'py` lifetime. It can be thought of as equivalent to the Rust tuple `(Python<'py>, Py)`. By having the binding to the `'py` lifetime, `Bound<'py, T>` can offer the complete PyO3 API at maximum efficiency. This means that `Bound<'py, T>` should usually be used whenever carrying this lifetime is acceptable, and `Py` otherwise. `Bound<'py, T>` engages in Python reference counting. This means that `Bound<'py, T>` owns a Python object. Rust code which just wants to borrow a Python object should use a shared reference `&Bound<'py, T>`. Just like `std::sync::Arc`, using `.clone()` and `drop()` will cheaply increment and decrement the reference count of the object (just in this case, the reference counting is implemented by the Python interpreter itself). To give an example of how `Bound<'py, T>` is PyO3's primary API type, consider the following Python code: ```python def example(): x = list() # create a Python list x.append(1) # append the integer 1 to it y = x # create a second reference to the list del x # delete the original reference ``` Using PyO3's API, and in particular `Bound<'py, PyList>`, this code translates into the following Rust code: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example<'py>(py: Python<'py>) -> PyResult<()> { let x: Bound<'py, PyList> = PyList::empty(py); x.append(1)?; let y: Bound<'py, PyList> = x.clone(); // y is a new reference to the same list drop(x); // release the original reference x Ok(()) } # Python::attach(example).unwrap(); ``` Or, without the type annotations: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example(py: Python<'_>) -> PyResult<()> { let x = PyList::empty(py); x.append(1)?; let y = x.clone(); drop(x); Ok(()) } # Python::attach(example).unwrap(); ``` #### Function argument lifetimes Because the `'py` lifetime often appears in many function arguments as part of the `Bound<'py, T>` smart pointer, the Rust compiler will often require annotations of input and output lifetimes. This occurs when the function output has at least one lifetime, and there is more than one lifetime present on the inputs. To demonstrate, consider this function which takes accepts Python objects and applies the [Python `+` operation][PyAnyMethods::add] to them: ```rust,compile_fail # use pyo3::prelude::*; fn add(left: &'_ Bound<'_, PyAny>, right: &'_ Bound<'_, PyAny>) -> PyResult> { left.add(right) } ``` Because the Python `+` operation might raise an exception, this function returns `PyResult>`. It doesn't need ownership of the inputs, so it takes `&Bound<'_, PyAny>` shared references. To demonstrate the point, all lifetimes have used the wildcard `'_` to allow the Rust compiler to attempt to infer them. Because there are four input lifetimes (two lifetimes of the shared references, and two `'py` lifetimes unnamed inside the `Bound<'_, PyAny>` pointers), the compiler cannot reason about which must be connected to the output. The correct way to solve this is to add the `'py` lifetime as a parameter for the function, and name all the `'py` lifetimes inside the `Bound<'py, PyAny>` smart pointers. For the shared references, it's also fine to reduce `&'_` to just `&`. The working end result is below: ```rust # use pyo3::prelude::*; fn add<'py>( left: &Bound<'py, PyAny>, right: &Bound<'py, PyAny>, ) -> PyResult> { left.add(right) } # Python::attach(|py| { # let s = pyo3::types::PyString::new(py, "s"); # assert!(add(&s, &s).unwrap().eq("ss").unwrap()); # }) ``` If naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `Py`, which has no lifetime. The cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]: ```rust # use pyo3::prelude::*; fn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult> { let output: Bound<'_, PyAny> = left.add(right)?; Ok(output.unbind()) } # Python::attach(|py| { # let s = pyo3::types::PyString::new(py, "s"); # assert!(add(&s, &s).unwrap().bind(py).eq("ss").unwrap()); # }) ``` ### `Borrowed<'a, 'py, T>` [`Borrowed<'a, 'py, T>`][Borrowed] is an advanced type used just occasionally at the edge of interaction with the Python interpreter. It can be thought of as analogous to the shared reference `&'a Bound<'py, T>`. The difference is that `Borrowed<'a, 'py, T>` is just a smart pointer rather than a reference-to-a-smart-pointer, which is a helpful reduction in indirection in specific interactions with the Python interpreter. `Borrowed<'a, 'py, T>` dereferences to `Bound<'py, T>`, so all methods on `Bound<'py, T>` are available on `Borrowed<'a, 'py, T>`. An example where `Borrowed<'a, 'py, T>` is used is in [`PyTupleMethods::get_borrowed_item`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html#tymethod.get_item): ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // Create a new tuple with the elements (0, 1, 2) let t = PyTuple::new(py, [0, 1, 2])?; for i in 0..=2 { let entry: Borrowed<'_, 'py, PyAny> = t.get_borrowed_item(i)?; // `PyAnyMethods::extract` is available on `Borrowed` // via the dereference to `Bound` let value: usize = entry.extract()?; assert_eq!(i, value); } # Ok(()) # } # Python::attach(example).unwrap(); ``` ### Casting between smart pointer types To convert between `Py` and `Bound<'py, T>` use the `bind()` / `into_bound()` methods. Use the `as_unbound()` / `unbind()` methods to go back from `Bound<'py, T>` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyAny> = obj.bind(py); let bound: Bound<'py, PyAny> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ``` To convert between `Bound<'py, T>` and `Borrowed<'a, 'py, T>` use the `as_borrowed()` method. `Borrowed<'a, 'py, T>` has a deref coercion to `Bound<'py, T>`. Use the `to_owned()` method to increment the Python reference count and to create a new `Bound<'py, T>` from the `Borrowed<'a, 'py, T>`. ```rust,ignore let bound: Bound<'py, PyAny> = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // deref coercion let bound: &Bound<'py, PyAny> = &borrowed; // create a new Bound by increase the Python reference count let bound: Bound<'py, PyAny> = borrowed.to_owned(); ``` To convert between `Py` and `Borrowed<'a, 'py, T>` use the `bind_borrowed()` method. Use either `as_unbound()` or `.to_owned().unbind()` to go back to `Py` from `Borrowed<'a, 'py, T>`, via `Bound<'py, T>`. ```rust,ignore let obj: Py = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // via deref coercion to Bound and then using Bound::as_unbound let obj: &Py = borrowed.as_unbound(); // via a new Bound by increasing the Python reference count, and unbind it let obj: Py = borrowed.to_owned().unbind(). ``` ## Concrete Python types In all of `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`, the type parameter `T` denotes the type of the Python object referred to by the smart pointer. This parameter `T` can be filled by: - [`PyAny`][PyAny], which represents any Python object, - Native Python types such as `PyList`, `PyTuple`, and `PyDict`, and - [`#[pyclass]`][pyclass] types defined from Rust The following subsections covers some further detail about how to work with these types: - the APIs that are available for these concrete types, - how to cast `Bound<'py, T>` to a specific concrete type, and - how to get Rust data out of a `Bound<'py, T>`. ### Using APIs for concrete Python types Each concrete Python type such as `PyAny`, `PyTuple` and `PyDict` exposes its API on the corresponding bound smart pointer `Bound<'py, PyAny>`, `Bound<'py, PyTuple>` and `Bound<'py, PyDict>`. Each type's API is exposed as a trait: [`PyAnyMethods`], [`PyTupleMethods`], [`PyDictMethods`], and so on for all concrete types. Using traits rather than associated methods on the `Bound` smart pointer is done for a couple of reasons: - Clarity of documentation: each trait gets its own documentation page in the PyO3 API docs. If all methods were on the `Bound` smart pointer directly, the vast majority of PyO3's API would be on a single, extremely long, documentation page. - Consistency: downstream code implementing Rust APIs for existing Python types can also follow this pattern of using a trait. Downstream code would not be allowed to add new associated methods directly on the `Bound` type. - Future design: it is hoped that a future Rust with [arbitrary self types](https://github.com/rust-lang/rust/issues/44874) will remove the need for these traits in favour of placing the methods directly on `PyAny`, `PyTuple`, `PyDict`, and so on. These traits are all included in the `pyo3::prelude` module, so with the glob import `use pyo3::prelude::*` the full PyO3 API is made available to downstream code. The following function accesses the first item in the input Python list, using the `.get_item()` method from the `PyListMethods` trait: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn get_first_item<'py>(list: &Bound<'py, PyList>) -> PyResult> { list.get_item(0) } # Python::attach(|py| { # let l = PyList::new(py, ["hello world"]).unwrap(); # assert!(get_first_item(&l).unwrap().eq("hello world").unwrap()); # }) ``` ### Casting between Python object types To cast `Bound<'py, T>` smart pointers to some other type, use the [`.cast()`][Bound::cast] family of functions. This converts `&Bound<'py, T>` to a different `&Bound<'py, U>`, without transferring ownership. There is also [`.cast_into()`][Bound::cast_into] to convert `Bound<'py, T>` to `Bound<'py, U>` with transfer of ownership. These methods are available for all types `T` which implement the [`PyTypeCheck`] trait. Casting to `Bound<'py, PyAny>` can be done with `.as_any()` or `.into_any()`. For example, the following snippet shows how to cast `Bound<'py, PyAny>` to `Bound<'py, PyTuple>`: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::empty(py).into_any(); // use `.cast()` to cast to `PyTuple` without transferring ownership let _: &Bound<'py, PyTuple> = obj.cast()?; // use `.cast_into()` to cast to `PyTuple` with transfer of ownership let _: Bound<'py, PyTuple> = obj.cast_into()?; # Ok(()) # } # Python::attach(example).unwrap() ``` Custom [`#[pyclass]`][pyclass] types implement [`PyTypeCheck`], so `.cast()` also works for these types. The snippet below is the same as the snippet above casting instead to a custom type `MyClass`: ```rust use pyo3::prelude::*; #[pyclass] struct MyClass {} # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = Bound::new(py, MyClass {})?.into_any(); // use `.cast()` to cast to `MyClass` without transferring ownership let _: &Bound<'py, MyClass> = obj.cast()?; // use `.cast_into()` to cast to `MyClass` with transfer of ownership let _: Bound<'py, MyClass> = obj.cast_into()?; # Ok(()) # } # Python::attach(example).unwrap() ``` ### Extracting Rust data from Python objects To extract Rust data from Python objects, use [`.extract()`][PyAnyMethods::extract] instead of `.cast()`. This method is available for all types which implement the [`FromPyObject`] trait. For example, the following snippet extracts a Rust tuple of integers from a Python tuple: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::new(py, [1, 2, 3])?.into_any(); // extracting the Python `tuple` to a rust `(i32, i32, i32)` tuple let (x, y, z) = obj.extract::<(i32, i32, i32)>()?; assert_eq!((x, y, z), (1, 2, 3)); # Ok(()) # } # Python::attach(example).unwrap() ``` To avoid copying data, [`#[pyclass]`][pyclass] types can directly reference Rust data stored within the Python objects without needing to `.extract()`. See the [corresponding documentation in the class section of the guide](./class.md#bound-and-interior-mutability) for more detail. [Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`Bound::unbind`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.unbind [Py]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [PyAnyMethods::add]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.add [PyAnyMethods::extract]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.extract [Bound::cast]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.cast [Bound::cast_into]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.cast_into [`PyTypeCheck`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeCheck.html [`PyAnyMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html [`PyDictMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyDictMethods.html [`PyTupleMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html [pyclass]: class.md [Borrowed]: {{#PYO3_DOCS_URL}}/pyo3/struct.Borrowed.html [Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html [PyAny]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html pyo3-0.27.2/guide/theme/tabs.css000064400000000000000000000006271046102023000144550ustar 00000000000000.mdbook-tabs { display: flex; } .mdbook-tab { background-color: var(--table-alternate-bg); padding: 0.5rem 1rem; cursor: pointer; border: none; font-size: 1.6rem; line-height: 1.45em; } .mdbook-tab.active { background-color: var(--table-header-bg); font-weight: bold; } .mdbook-tab-content { padding: 1rem 0rem; } .mdbook-tab-content table { margin: unset; } pyo3-0.27.2/guide/theme/tabs.js000064400000000000000000000045021046102023000142750ustar 00000000000000/** * Change active tab of tabs. * * @param {Element} container * @param {string} name */ const changeTab = (container, name) => { for (const child of container.children) { if (!(child instanceof HTMLElement)) { continue; } if (child.classList.contains('mdbook-tabs')) { for (const tab of child.children) { if (!(tab instanceof HTMLElement)) { continue; } if (tab.dataset.tabname === name) { tab.classList.add('active'); } else { tab.classList.remove('active'); } } } else if (child.classList.contains('mdbook-tab-content')) { if (child.dataset.tabname === name) { child.classList.remove('hidden'); } else { child.classList.add('hidden'); } } } }; document.addEventListener('DOMContentLoaded', () => { const tabs = document.querySelectorAll('.mdbook-tab'); for (const tab of tabs) { tab.addEventListener('click', () => { if (!(tab instanceof HTMLElement)) { return; } if (!tab.parentElement || !tab.parentElement.parentElement) { return; } const container = tab.parentElement.parentElement; const name = tab.dataset.tabname; const global = container.dataset.tabglobal; changeTab(container, name); if (global) { localStorage.setItem(`mdbook-tabs-${global}`, name); const globalContainers = document.querySelectorAll( `.mdbook-tabs-container[data-tabglobal="${global}"]` ); for (const globalContainer of globalContainers) { changeTab(globalContainer, name); } } }); } const containers = document.querySelectorAll('.mdbook-tabs-container[data-tabglobal]'); for (const container of containers) { const global = container.dataset.tabglobal; const name = localStorage.getItem(`mdbook-tabs-${global}`); if (name && document.querySelector(`.mdbook-tab[data-tabname=${name}]`)) { changeTab(container, name); } } }); pyo3-0.27.2/newsfragments/.gitignore000064400000000000000000000000001046102023000154470ustar 00000000000000pyo3-0.27.2/pyo3-runtime/LICENSE-APACHE000064400000000000000000000231171046102023000151110ustar 00000000000000Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS pyo3-0.27.2/pyo3-runtime/LICENSE-MIT000064400000000000000000000021231046102023000146130ustar 00000000000000Copyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-0.27.2/pyo3-runtime/README.md000064400000000000000000000000151046102023000144340ustar 00000000000000Coming soon! pyo3-0.27.2/pyo3-runtime/pyproject.toml000064400000000000000000000016661046102023000161060ustar 00000000000000[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "pyo3-runtime" dynamic = ["version"] description = '' readme = "README.md" requires-python = ">=3.7" license = "MIT OR Apache-2.0" keywords = [] authors = [ { name = "David Hewitt", email = "1939362+davidhewitt@users.noreply.github.com" }, ] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] dependencies = [] [project.urls] Homepage = "https://github.com/PyO3/pyo3" [tool.hatch.version] path = "src/pyo3_runtime/__init__.py" pyo3-0.27.2/pyo3-runtime/src/pyo3_runtime/__init__.py000064400000000000000000000000261046102023000205140ustar 00000000000000__version__ = "0.0.1" pyo3-0.27.2/pyo3-runtime/tests/__init__.py000064400000000000000000000000001046102023000164220ustar 00000000000000pyo3-0.27.2/src/buffer.rs000064400000000000000000001100701046102023000132130ustar 00000000000000#![cfg(any(not(Py_LIMITED_API), Py_3_11))] // Copyright (c) 2017 Daniel Grunwald // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //! `PyBuffer` implementation use crate::{err, exceptions::PyBufferError, ffi, FromPyObject, PyAny, PyResult, Python}; use crate::{Borrowed, Bound, PyErr}; use std::ffi::{ c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong, c_ushort, c_void, }; use std::marker::{PhantomData, PhantomPinned}; use std::pin::Pin; use std::{cell, mem, ptr, slice}; use std::{ffi::CStr, fmt::Debug}; /// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`. #[repr(transparent)] pub struct PyBuffer( // It is common for exporters filling `Py_buffer` struct to make it self-referential, e.g. see // implementation of // [`PyBuffer_FillInfo`](https://github.com/python/cpython/blob/2fd43a1ffe4ff1f6c46f6045bc327d6085c40fbf/Objects/abstract.c#L798-L802). // // Therefore we use `Pin>` to ensure that the memory address of the `Py_buffer` is stable Pin>, PhantomData, ); /// Wrapper around `ffi::Py_buffer` to be `!Unpin`. #[repr(transparent)] struct RawBuffer(ffi::Py_buffer, PhantomPinned); // PyBuffer is thread-safe: the shape of the buffer is immutable while a Py_buffer exists. unsafe impl Send for PyBuffer {} unsafe impl Sync for PyBuffer {} impl Debug for PyBuffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let raw = self.raw(); f.debug_struct("PyBuffer") .field("buf", &raw.buf) .field("obj", &raw.obj) .field("len", &raw.len) .field("itemsize", &raw.itemsize) .field("readonly", &raw.readonly) .field("ndim", &raw.ndim) .field("format", &self.format()) .field("shape", &self.shape()) .field("strides", &self.strides()) .field("suboffsets", &self.suboffsets()) .field("internal", &raw.internal) .finish() } } /// Represents the type of a Python buffer element. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ElementType { /// 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. Float { /// The width of the float in bytes. bytes: usize, }, /// An unknown type. This may occur when parsing has failed. Unknown, } impl ElementType { /// Determines the `ElementType` from a Python `struct` module format string. /// /// See for more information /// about struct format strings. pub fn from_format(format: &CStr) -> ElementType { match format.to_bytes() { [size] | [b'@', size] => native_element_type_from_type_char(*size), [b'=' | b'<' | b'>' | b'!', size] => standard_element_type_from_type_char(*size), _ => ElementType::Unknown, } } } fn native_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' => UnsignedInteger { bytes: mem::size_of::(), }, b'b' => SignedInteger { bytes: mem::size_of::(), }, b'B' => UnsignedInteger { bytes: mem::size_of::(), }, b'?' => Bool, b'h' => SignedInteger { bytes: mem::size_of::(), }, b'H' => UnsignedInteger { bytes: mem::size_of::(), }, b'i' => SignedInteger { bytes: mem::size_of::(), }, b'I' => UnsignedInteger { bytes: mem::size_of::(), }, b'l' => SignedInteger { bytes: mem::size_of::(), }, b'L' => UnsignedInteger { bytes: mem::size_of::(), }, b'q' => SignedInteger { bytes: mem::size_of::(), }, b'Q' => UnsignedInteger { bytes: mem::size_of::(), }, b'n' => SignedInteger { bytes: mem::size_of::(), }, b'N' => UnsignedInteger { bytes: mem::size_of::(), }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } fn standard_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' | b'B' => UnsignedInteger { bytes: 1 }, b'b' => SignedInteger { bytes: 1 }, b'?' => Bool, b'h' => SignedInteger { bytes: 2 }, b'H' => UnsignedInteger { bytes: 2 }, b'i' | b'l' => SignedInteger { bytes: 4 }, b'I' | b'L' => UnsignedInteger { bytes: 4 }, b'q' => SignedInteger { bytes: 8 }, b'Q' => UnsignedInteger { bytes: 8 }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } #[cfg(target_endian = "little")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' } #[cfg(target_endian = "big")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' || c == b'!' } /// Trait implemented for possible element types of `PyBuffer`. /// /// # Safety /// /// This trait must only be implemented for types which represent valid elements of Python buffers. pub unsafe trait Element: Copy { /// Gets whether the element specified in the format string is potentially compatible. /// Alignment and size are checked separately from this function. fn is_compatible_format(format: &CStr) -> bool; } impl FromPyObject<'_, '_> for PyBuffer { type Error = PyErr; fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result, Self::Error> { Self::get(&obj) } } impl PyBuffer { /// Gets the underlying buffer from the specified python object. pub fn get(obj: &Bound<'_, PyAny>) -> PyResult> { // TODO: use nightly API Box::new_uninit() once our MSRV is 1.82 let mut buf = Box::new(mem::MaybeUninit::::uninit()); let buf: Box = { err::error_on_minusone(obj.py(), unsafe { ffi::PyObject_GetBuffer( obj.as_ptr(), // SAFETY: RawBuffer is `#[repr(transparent)]` around FFI struct buf.as_mut_ptr().cast::(), ffi::PyBUF_FULL_RO, ) })?; // Safety: buf is initialized by PyObject_GetBuffer. // TODO: use nightly API Box::assume_init() once our MSRV is 1.82 unsafe { mem::transmute(buf) } }; // Create PyBuffer immediately so that if validation checks fail, the PyBuffer::drop code // will call PyBuffer_Release (thus avoiding any leaks). let buf = PyBuffer(Pin::from(buf), PhantomData); let raw = buf.raw(); if raw.shape.is_null() { Err(PyBufferError::new_err("shape is null")) } else if raw.strides.is_null() { Err(PyBufferError::new_err("strides is null")) } else if mem::size_of::() != buf.item_size() || !T::is_compatible_format(buf.format()) { Err(PyBufferError::new_err(format!( "buffer contents are not compatible with {}", std::any::type_name::() ))) } else if raw.buf.align_offset(mem::align_of::()) != 0 { Err(PyBufferError::new_err(format!( "buffer contents are insufficiently aligned for {}", std::any::type_name::() ))) } else { Ok(buf) } } } impl PyBuffer { /// Gets the pointer to the start of the buffer memory. /// /// Warning: the buffer memory can be mutated by other code (including /// other Python functions, if the GIL is released, or other extension /// modules even if the GIL is held). You must either access memory /// atomically, or ensure there are no data races yourself. See /// [this blog post] for more details. /// /// [this blog post]: https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/ #[inline] pub fn buf_ptr(&self) -> *mut c_void { self.raw().buf } /// Gets a pointer to the specified item. /// /// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension. pub fn get_ptr(&self, indices: &[usize]) -> *mut c_void { let shape = &self.shape()[..indices.len()]; for i in 0..indices.len() { assert!(indices[i] < shape[i]); } unsafe { ffi::PyBuffer_GetPointer( #[cfg(Py_3_11)] self.raw(), #[cfg(not(Py_3_11))] { self.raw() as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { indices.as_ptr().cast() }, #[cfg(not(Py_3_11))] { indices.as_ptr() as *mut ffi::Py_ssize_t }, ) } } /// Gets whether the underlying buffer is read-only. #[inline] pub fn readonly(&self) -> bool { self.raw().readonly != 0 } /// Gets the size of a single element, in bytes. /// Important exception: when requesting an unformatted buffer, item_size still has the value #[inline] pub fn item_size(&self) -> usize { self.raw().itemsize as usize } /// Gets the total number of items. #[inline] pub fn item_count(&self) -> usize { (self.raw().len as usize) / (self.raw().itemsize as usize) } /// `item_size() * item_count()`. /// For contiguous arrays, this is the length of the underlying memory block. /// For non-contiguous arrays, it is the length that the logical structure would have if it were copied to a contiguous representation. #[inline] pub fn len_bytes(&self) -> usize { self.raw().len as usize } /// Gets the number of dimensions. /// /// May be 0 to indicate a single scalar value. #[inline] pub fn dimensions(&self) -> usize { self.raw().ndim as usize } /// Returns an array of length `dimensions`. `shape()[i]` is the length of the array in dimension number `i`. /// /// May return None for single-dimensional arrays or scalar values (`dimensions() <= 1`); /// You can call `item_count()` to get the length of the single dimension. /// /// Despite Python using an array of signed integers, the values are guaranteed to be non-negative. /// However, dimensions of length 0 are possible and might need special attention. #[inline] pub fn shape(&self) -> &[usize] { unsafe { slice::from_raw_parts(self.raw().shape.cast(), self.raw().ndim as usize) } } /// Returns an array that holds, for each dimension, the number of bytes to skip to get to the next element in the dimension. /// /// Stride values can be any integer. For regular arrays, strides are usually positive, /// but a consumer MUST be able to handle the case `strides[n] <= 0`. #[inline] pub fn strides(&self) -> &[isize] { unsafe { slice::from_raw_parts(self.raw().strides, self.raw().ndim as usize) } } /// An array of length ndim. /// If `suboffsets[n] >= 0`, the values stored along the nth dimension are pointers and the suboffset value dictates how many bytes to add to each pointer after de-referencing. /// A suboffset value that is negative indicates that no de-referencing should occur (striding in a contiguous memory block). /// /// If all suboffsets are negative (i.e. no de-referencing is needed), then this field must be NULL (the default value). #[inline] pub fn suboffsets(&self) -> Option<&[isize]> { unsafe { if self.raw().suboffsets.is_null() { None } else { Some(slice::from_raw_parts( self.raw().suboffsets, self.raw().ndim as usize, )) } } } /// A NUL terminated string in struct module style syntax describing the contents of a single item. #[inline] pub fn format(&self) -> &CStr { if self.raw().format.is_null() { ffi::c_str!("B") } else { unsafe { CStr::from_ptr(self.raw().format) } } } /// Gets whether the buffer is contiguous in C-style order (last index varies fastest when visiting items in order of memory address). #[inline] pub fn is_c_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(self.raw(), b'C' as std::ffi::c_char) != 0 } } /// Gets whether the buffer is contiguous in Fortran-style order (first index varies fastest when visiting items in order of memory address). #[inline] pub fn is_fortran_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(self.raw(), b'F' as std::ffi::c_char) != 0 } } fn raw(&self) -> &ffi::Py_buffer { &self.0 .0 } } impl PyBuffer { /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.raw().buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.raw().buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if mem::size_of::() == self.item_size() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.raw().buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.raw().buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'C') } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_fortran_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'F') } fn _copy_to_slice(&self, py: Python<'_>, target: &mut [T], fort: u8) -> PyResult<()> { if mem::size_of_val(target) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy to (of length {}) does not match buffer length of {}", target.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( target.as_mut_ptr().cast(), #[cfg(Py_3_11)] self.raw(), #[cfg(not(Py_3_11))] { self.raw() as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.raw().len, fort as std::ffi::c_char, ) }) } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'C') } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_fortran_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'F') } fn _to_vec(&self, py: Python<'_>, fort: u8) -> PyResult> { let item_count = self.item_count(); let mut vec: Vec = Vec::with_capacity(item_count); // Copy the buffer into the uninitialized space in the vector. // Due to T:Copy, we don't need to be concerned with Drop impls. err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( vec.as_ptr() as *mut c_void, #[cfg(Py_3_11)] self.raw(), #[cfg(not(Py_3_11))] { self.raw() as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.raw().len, fort as std::ffi::c_char, ) })?; // set vector length to mark the now-initialized space as usable unsafe { vec.set_len(item_count) }; Ok(vec) } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in C-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'C') } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in Fortran-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_fortran_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'F') } fn _copy_from_slice(&self, py: Python<'_>, source: &[T], fort: u8) -> PyResult<()> { if self.readonly() { return Err(PyBufferError::new_err("cannot write to read-only buffer")); } else if mem::size_of_val(source) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy from (of length {}) does not match buffer length of {}", source.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_FromContiguous( #[cfg(Py_3_11)] self.raw(), #[cfg(not(Py_3_11))] { self.raw() as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { source.as_ptr().cast() }, #[cfg(not(Py_3_11))] { source.as_ptr() as *mut c_void }, self.raw().len, fort as std::ffi::c_char, ) }) } /// Releases the buffer object, freeing the reference to the Python object /// which owns the buffer. /// /// This will automatically be called on drop. pub fn release(self, _py: Python<'_>) { // First move self into a ManuallyDrop, so that PyBuffer::drop will // never be called. (It would attach to the interpreter and call PyBuffer_Release // again.) let mut mdself = mem::ManuallyDrop::new(self); unsafe { // Next, make the actual PyBuffer_Release call. // Fine to get a mutable reference to the inner ffi::Py_buffer here, as we're destroying it. mdself.0.release(); // Finally, drop the contained Pin> in place, to free the // Box memory. ptr::drop_in_place::>>(&mut mdself.0); } } } impl RawBuffer { /// Release the contents of this pinned buffer. /// /// # Safety /// /// - The buffer must not be used after calling this function. /// - This function can only be called once. /// - Must be attached to the interpreter. /// unsafe fn release(self: &mut Pin>) { unsafe { ffi::PyBuffer_Release(&mut Pin::get_unchecked_mut(self.as_mut()).0); } } } impl Drop for PyBuffer { fn drop(&mut self) { fn inner(buf: &mut Pin>) { if Python::try_attach(|_| unsafe { buf.release() }).is_none() && crate::internal::state::is_in_gc_traversal() { eprintln!("Warning: PyBuffer dropped while in GC traversal, this is a bug and will leak memory."); } // If `try_attach` failed and `is_in_gc_traversal()` is false, then probably the interpreter has // already finalized and we can just assume that the underlying memory has already been freed. // // So we don't handle that case here. } inner(&mut self.0); } } /// Like [std::cell::Cell], but only provides read-only access to the data. /// /// `&ReadOnlyCell` is basically a safe version of `*const T`: /// The data cannot be modified through the reference, but other references may /// be modifying the data. #[repr(transparent)] pub struct ReadOnlyCell(cell::UnsafeCell); impl ReadOnlyCell { /// Returns a copy of the current value. #[inline] pub fn get(&self) -> T { unsafe { *self.0.get() } } /// Returns a pointer to the current value. #[inline] pub fn as_ptr(&self) -> *const T { self.0.get() } } macro_rules! impl_element( ($t:ty, $f:ident) => { unsafe impl Element for $t { fn is_compatible_format(format: &CStr) -> bool { let slice = format.to_bytes(); if slice.len() > 1 && !is_matching_endian(slice[0]) { return false; } ElementType::from_format(format) == ElementType::$f { bytes: mem::size_of::<$t>() } } } } ); impl_element!(u8, UnsignedInteger); impl_element!(u16, UnsignedInteger); impl_element!(u32, UnsignedInteger); impl_element!(u64, UnsignedInteger); impl_element!(usize, UnsignedInteger); impl_element!(i8, SignedInteger); impl_element!(i16, SignedInteger); impl_element!(i32, SignedInteger); impl_element!(i64, SignedInteger); impl_element!(isize, SignedInteger); impl_element!(f32, Float); impl_element!(f64, Float); #[cfg(test)] mod tests { use super::*; use crate::ffi; use crate::types::any::PyAnyMethods; use crate::types::PyBytes; use crate::Python; #[test] fn test_debug() { Python::attach(|py| { let bytes = PyBytes::new(py, b"abcde"); let buffer: PyBuffer = PyBuffer::get(&bytes).unwrap(); let expected = format!( concat!( "PyBuffer {{ buf: {:?}, obj: {:?}, ", "len: 5, itemsize: 1, readonly: 1, ", "ndim: 1, format: \"B\", shape: [5], ", "strides: [1], suboffsets: None, internal: {:?} }}", ), buffer.raw().buf, buffer.raw().obj, buffer.raw().internal ); let debug_repr = format!("{:?}", buffer); assert_eq!(debug_repr, expected); }); } #[test] fn test_element_type_from_format() { use super::ElementType::*; use std::mem::size_of; for (cstr, expected) in [ // @ prefix goes to native_element_type_from_type_char ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@c"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@B"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@?"), Bool), ( ffi::c_str!("@h"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@H"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@i"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@I"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@l"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@L"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@q"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@Q"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@n"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@N"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@e"), Float { bytes: 2 }), (ffi::c_str!("@f"), Float { bytes: 4 }), (ffi::c_str!("@d"), Float { bytes: 8 }), (ffi::c_str!("@z"), Unknown), // = prefix goes to standard_element_type_from_type_char (ffi::c_str!("=b"), SignedInteger { bytes: 1 }), (ffi::c_str!("=c"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=B"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=?"), Bool), (ffi::c_str!("=h"), SignedInteger { bytes: 2 }), (ffi::c_str!("=H"), UnsignedInteger { bytes: 2 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=I"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=L"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=q"), SignedInteger { bytes: 8 }), (ffi::c_str!("=Q"), UnsignedInteger { bytes: 8 }), (ffi::c_str!("=e"), Float { bytes: 2 }), (ffi::c_str!("=f"), Float { bytes: 4 }), (ffi::c_str!("=d"), Float { bytes: 8 }), (ffi::c_str!("=z"), Unknown), (ffi::c_str!("=0"), Unknown), // unknown prefix -> Unknown (ffi::c_str!(":b"), Unknown), ] { assert_eq!( ElementType::from_format(cstr), expected, "element from format &Cstr: {cstr:?}", ); } } #[test] fn test_compatible_size() { // for the cast in PyBuffer::shape() assert_eq!( std::mem::size_of::(), std::mem::size_of::() ); } #[test] fn test_bytes_buffer() { Python::attach(|py| { let bytes = PyBytes::new(py, b"abcde"); let buffer = PyBuffer::get(&bytes).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 5); assert_eq!(buffer.format().to_str().unwrap(), "B"); assert_eq!(buffer.shape(), [5]); // single-dimensional buffer is always contiguous assert!(buffer.is_c_contiguous()); assert!(buffer.is_fortran_contiguous()); let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 5); assert_eq!(slice[0].get(), b'a'); assert_eq!(slice[2].get(), b'c'); assert_eq!(unsafe { *(buffer.get_ptr(&[1]) as *mut u8) }, b'b'); assert!(buffer.as_mut_slice(py).is_none()); assert!(buffer.copy_to_slice(py, &mut [0u8]).is_err()); let mut arr = [0; 5]; buffer.copy_to_slice(py, &mut arr).unwrap(); assert_eq!(arr, b"abcde" as &[u8]); assert!(buffer.copy_from_slice(py, &[0u8; 5]).is_err()); assert_eq!(buffer.to_vec(py).unwrap(), b"abcde"); }); } #[test] fn test_array_buffer() { Python::attach(|py| { let array = py .import("array") .unwrap() .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None) .unwrap(); let buffer = PyBuffer::get(&array).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 4); assert_eq!(buffer.format().to_str().unwrap(), "f"); assert_eq!(buffer.shape(), [4]); // array creates a 1D contiguous buffer, so it's both C and F contiguous. This would // be more interesting if we can come up with a 2D buffer but I think it would need a // third-party lib or a custom class. // C-contiguous fns let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[0].get(), 1.0); assert_eq!(slice[3].get(), 2.5); let mut_slice = buffer.as_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[0].get(), 1.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); // F-contiguous fns let buffer = PyBuffer::get(&array).unwrap(); let slice = buffer.as_fortran_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[1].get(), 11.0); let mut_slice = buffer.as_fortran_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[2].get(), 12.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_fortran_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_fortran_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); }); } } pyo3-0.27.2/src/call.rs000064400000000000000000000230601046102023000126570ustar 00000000000000//! Defines how Python calls are dispatched, see [`PyCallArgs`].for more information. use crate::ffi_ptr_ext::FfiPtrExt as _; use crate::types::{PyAnyMethods as _, PyDict, PyString, PyTuple}; use crate::{ffi, Borrowed, Bound, IntoPyObjectExt as _, Py, PyAny, PyResult}; pub(crate) mod private { use super::*; pub trait Sealed {} impl Sealed for () {} impl Sealed for Bound<'_, PyTuple> {} impl Sealed for &'_ Bound<'_, PyTuple> {} impl Sealed for Py {} impl Sealed for &'_ Py {} impl Sealed for Borrowed<'_, '_, PyTuple> {} pub struct Token; } /// This trait marks types that can be used as arguments to Python function /// calls. /// /// This trait is currently implemented for Rust tuple (up to a size of 12), /// [`Bound<'py, PyTuple>`] and [`Py`]. Custom types that are /// convertable to `PyTuple` via `IntoPyObject` need to do so before passing it /// to `call`. /// /// This trait is not intended to used by downstream crates directly. As such it /// has no publicly available methods and cannot be implemented outside of /// `pyo3`. The corresponding public API is available through [`call`] /// ([`call0`], [`call1`] and friends) on [`PyAnyMethods`]. /// /// # What is `PyCallArgs` used for? /// `PyCallArgs` is used internally in `pyo3` to dispatch the Python calls in /// the most optimal way for the current build configuration. Certain types, /// such as Rust tuples, do allow the usage of a faster calling convention of /// the Python interpreter (if available). More types that may take advantage /// from this may be added in the future. /// /// [`call0`]: crate::types::PyAnyMethods::call0 /// [`call1`]: crate::types::PyAnyMethods::call1 /// [`call`]: crate::types::PyAnyMethods::call /// [`PyAnyMethods`]: crate::types::PyAnyMethods #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot used as a Python `call` argument", note = "`PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py`", note = "if your type is convertable to `PyTuple` via `IntoPyObject`, call `.into_pyobject(py)` manually", note = "if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(,)`" ) )] pub trait PyCallArgs<'py>: Sized + private::Sealed { #[doc(hidden)] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult>; #[doc(hidden)] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult>; #[doc(hidden)] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, PyString>, _: private::Token, ) -> PyResult> { object .getattr(method_name) .and_then(|method| method.call1(self)) } } impl<'py> PyCallArgs<'py> for () { fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { let args = self.into_pyobject_or_pyerr(function.py())?; args.call(function, kwargs, token) } fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { let args = self.into_pyobject_or_pyerr(function.py())?; args.call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Bound<'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.as_borrowed().call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.as_borrowed().call_positional(function, token) } } impl<'py> PyCallArgs<'py> for &'_ Bound<'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.as_borrowed().call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.as_borrowed().call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Py { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call_positional(function, token) } } impl<'py> PyCallArgs<'py> for &'_ Py { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Borrowed<'_, 'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, _: private::Token, ) -> PyResult> { unsafe { ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), kwargs.as_ptr()) .assume_owned_or_err(function.py()) } } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, _: private::Token, ) -> PyResult> { unsafe { ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), std::ptr::null_mut()) .assume_owned_or_err(function.py()) } } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use crate::{ pyfunction, types::{PyDict, PyTuple}, Py, }; #[pyfunction(signature = (*args, **kwargs), crate = "crate")] fn args_kwargs( args: Py, kwargs: Option>, ) -> (Py, Option>) { (args, kwargs) } #[test] fn test_call() { use crate::{ types::{IntoPyDict, PyAnyMethods, PyDict, PyTuple}, wrap_pyfunction, Py, Python, }; Python::attach(|py| { let f = wrap_pyfunction!(args_kwargs, py).unwrap(); let args = PyTuple::new(py, [1, 2, 3]).unwrap(); let kwargs = &[("foo", 1), ("bar", 2)].into_py_dict(py).unwrap(); macro_rules! check_call { ($args:expr, $kwargs:expr) => { let (a, k): (Py, Py) = f .call(args.clone(), Some(kwargs)) .unwrap() .extract() .unwrap(); assert!(a.is(&args)); assert!(k.is(kwargs)); }; } // Bound<'py, PyTuple> check_call!(args.clone(), kwargs); // &Bound<'py, PyTuple> check_call!(&args, kwargs); // Py check_call!(args.clone().unbind(), kwargs); // &Py check_call!(&args.as_unbound(), kwargs); // Borrowed<'_, '_, PyTuple> check_call!(args.as_borrowed(), kwargs); }) } #[test] fn test_call_positional() { use crate::{ types::{PyAnyMethods, PyNone, PyTuple}, wrap_pyfunction, Py, Python, }; Python::attach(|py| { let f = wrap_pyfunction!(args_kwargs, py).unwrap(); let args = PyTuple::new(py, [1, 2, 3]).unwrap(); macro_rules! check_call { ($args:expr, $kwargs:expr) => { let (a, k): (Py, Py) = f.call1(args.clone()).unwrap().extract().unwrap(); assert!(a.is(&args)); assert!(k.is_none(py)); }; } // Bound<'py, PyTuple> check_call!(args.clone(), kwargs); // &Bound<'py, PyTuple> check_call!(&args, kwargs); // Py check_call!(args.clone().unbind(), kwargs); // &Py check_call!(args.as_unbound(), kwargs); // Borrowed<'_, '_, PyTuple> check_call!(args.as_borrowed(), kwargs); }) } } pyo3-0.27.2/src/conversion.rs000064400000000000000000000570411046102023000141370ustar 00000000000000//! Defines conversions between Rust and Python types. use crate::err::PyResult; use crate::impl_::pyclass::ExtractPyClassWithClone; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::pyclass::boolean_struct::False; use crate::pyclass::{PyClassGuardError, PyClassGuardMutError}; use crate::types::PyTuple; use crate::{ Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyClassGuard, PyErr, PyRef, PyRefMut, Python, }; use std::convert::Infallible; #[cfg(return_position_impl_trait_in_traits)] use std::marker::PhantomData; /// Defines a conversion from a Rust type to a Python object, which may fail. /// /// This trait has `#[derive(IntoPyObject)]` to automatically implement it for simple types and /// `#[derive(IntoPyObjectRef)]` to implement the same for references. /// /// It functions similarly to std's [`TryInto`] trait, but requires a [`Python<'py>`] token /// as an argument. /// /// The [`into_pyobject`][IntoPyObject::into_pyobject] method is designed for maximum flexibility and efficiency; it /// - allows for a concrete Python type to be returned (the [`Target`][IntoPyObject::Target] associated type) /// - allows for the smart pointer containing the Python object to be either `Bound<'py, Self::Target>` or `Borrowed<'a, 'py, Self::Target>` /// to avoid unnecessary reference counting overhead /// - allows for a custom error type to be returned in the event of a conversion error to avoid /// unnecessarily creating a Python exception /// /// # See also /// /// - The [`IntoPyObjectExt`] trait, which provides convenience methods for common usages of /// `IntoPyObject` which erase type information and convert errors to `PyErr`. #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", note = "`IntoPyObject` is automatically implemented by the `#[pyclass]` macro", note = "if you do not wish to have a corresponding Python type, implement it manually", note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`" ) )] pub trait IntoPyObject<'py>: Sized { /// The Python output type type Target; /// The smart pointer type to use. /// /// This will usually be [`Bound<'py, Target>`], but in special cases [`Borrowed<'a, 'py, Target>`] can be /// used to minimize reference counting overhead. type Output: BoundObject<'py, Self::Target>; /// The type returned in the event of a conversion error. type Error: Into; /// Extracts the type hint information for this type when it appears as a return value. /// /// For example, `Vec` would return `List[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`FromPyObject::INPUT_TYPE`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: &'static str = "typing.Any"; /// Performs the conversion. fn into_pyobject(self, py: Python<'py>) -> Result; /// Extracts the type hint information for this type when it appears as a return value. /// /// For example, `Vec` would return `List[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Any } /// Converts sequence of Self into a Python object. Used to specialize `Vec`, `[u8; N]` /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object. #[doc(hidden)] fn owned_sequence_into_pyobject( iter: I, py: Python<'py>, _: private::Token, ) -> Result, PyErr> where I: IntoIterator + AsRef<[Self]>, I::IntoIter: ExactSizeIterator, { let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py)); let list = crate::types::list::try_new_from_iter(py, &mut iter); list.map(Bound::into_any) } /// Converts sequence of Self into a Python object. Used to specialize `&[u8]` and `Cow<[u8]>` /// as a sequence of bytes into a `bytes` object. #[doc(hidden)] fn borrowed_sequence_into_pyobject( iter: I, py: Python<'py>, _: private::Token, ) -> Result, PyErr> where Self: private::Reference, I: IntoIterator + AsRef<[::BaseType]>, I::IntoIter: ExactSizeIterator, { let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py)); let list = crate::types::list::try_new_from_iter(py, &mut iter); list.map(Bound::into_any) } } pub(crate) mod private { pub struct Token; pub trait Reference { type BaseType; } impl Reference for &'_ T { type BaseType = T; } } impl<'py, T> IntoPyObject<'py> for Bound<'py, T> { type Target = T; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Bound<'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.as_borrowed()) } } impl<'a, 'py, T> IntoPyObject<'py> for Borrowed<'a, 'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self) } } impl<'a, 'py, T> IntoPyObject<'py> for &Borrowed<'a, 'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(*self) } } impl<'py, T> IntoPyObject<'py> for Py { type Target = T; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.into_bound(py)) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Py { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.bind_borrowed(py)) } } impl<'a, 'py, T> IntoPyObject<'py> for &&'a T where &'a T: IntoPyObject<'py>, { type Target = <&'a T as IntoPyObject<'py>>::Target; type Output = <&'a T as IntoPyObject<'py>>::Output; type Error = <&'a T as IntoPyObject<'py>>::Error; #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: &'static str = <&'a T as IntoPyObject<'py>>::OUTPUT_TYPE; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } mod into_pyobject_ext { pub trait Sealed {} impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {} } /// Convenience methods for common usages of [`IntoPyObject`]. Every type that implements /// [`IntoPyObject`] also implements this trait. /// /// These methods: /// - Drop type information from the output, returning a `PyAny` object. /// - Always convert the `Error` type to `PyErr`, which may incur a performance penalty but it /// more convenient in contexts where the `?` operator would produce a `PyErr` anyway. pub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed { /// Converts `self` into an owned Python object, dropping type information. #[inline] fn into_bound_py_any(self, py: Python<'py>) -> PyResult> { match self.into_pyobject(py) { Ok(obj) => Ok(obj.into_any().into_bound()), Err(err) => Err(err.into()), } } /// Converts `self` into an owned Python object, dropping type information and unbinding it /// from the `'py` lifetime. #[inline] fn into_py_any(self, py: Python<'py>) -> PyResult> { match self.into_pyobject(py) { Ok(obj) => Ok(obj.into_any().unbind()), Err(err) => Err(err.into()), } } /// Converts `self` into a Python object. /// /// This is equivalent to calling [`into_pyobject`][IntoPyObject::into_pyobject] followed /// with `.map_err(Into::into)` to convert the error type to [`PyErr`]. This is helpful /// for generic code which wants to make use of the `?` operator. #[inline] fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult { match self.into_pyobject(py) { Ok(obj) => Ok(obj), Err(err) => Err(err.into()), } } } impl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {} /// Extract a type from a Python object. /// /// /// Normal usage is through the `extract` methods on [`Bound`], [`Borrowed`] and [`Py`], which /// forward to this trait. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// # fn main() -> PyResult<()> { /// Python::attach(|py| { /// // Calling `.extract()` on a `Bound` smart pointer /// let obj: Bound<'_, PyString> = PyString::new(py, "blah"); /// let s: String = obj.extract()?; /// # assert_eq!(s, "blah"); /// /// // Calling `.extract(py)` on a `Py` smart pointer /// let obj: Py = obj.unbind(); /// let s: String = obj.extract(py)?; /// # assert_eq!(s, "blah"); /// # Ok(()) /// }) /// # } /// ``` /// /// Note: Depending on the Python version and implementation, some [`FromPyObject`] implementations /// may produce a result that borrows into the Python type. This is described by the input lifetime /// `'a` of `obj`. /// /// Types that must not borrow from the input can use [`FromPyObjectOwned`] as a restriction. This /// is most often the case for collection types. See its documentation for more details. /// /// # How to implement [`FromPyObject`]? /// ## `#[derive(FromPyObject)]` /// The simplest way to implement [`FromPyObject`] for a custom type is to make use of our derive /// macro. /// ```rust,no_run /// # #![allow(dead_code)] /// use pyo3::prelude::*; /// /// #[derive(FromPyObject)] /// struct MyObject { /// msg: String, /// list: Vec /// } /// # fn main() {} /// ``` /// By default this will try to extract each field from the Python object by attribute access, but /// this can be customized. For more information about the derive macro, its configuration as well /// as its working principle for other types, take a look at the [guide]. /// /// In case the derive macro is not sufficient or can not be used for some other reason, /// [`FromPyObject`] can be implemented manually. In the following types without lifetime parameters /// are handled first, because they are a little bit simpler. Types with lifetime parameters are /// explained below. /// /// ## Manual implementation for types without lifetime /// Types that do not contain lifetime parameters are unable to borrow from the Python object, so /// the lifetimes of [`FromPyObject`] can be elided: /// ```rust,no_run /// # #![allow(dead_code)] /// use pyo3::prelude::*; /// /// struct MyObject { /// msg: String, /// list: Vec /// } /// /// impl FromPyObject<'_, '_> for MyObject { /// type Error = PyErr; /// /// fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result { /// Ok(MyObject { /// msg: obj.getattr("msg")?.extract()?, /// list: obj.getattr("list")?.extract()?, /// }) /// } /// } /// /// # fn main() {} /// ``` /// This is basically what the derive macro above expands to. /// /// ## Manual implementation for types with lifetime paramaters /// For types that contain lifetimes, these lifetimes need to be bound to the corresponding /// [`FromPyObject`] lifetime. This is roughly how the extraction of a typed [`Bound`] is /// implemented within PyO3. /// /// ```rust,no_run /// # #![allow(dead_code)] /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// struct MyObject<'py>(Bound<'py, PyString>); /// /// impl<'py> FromPyObject<'_, 'py> for MyObject<'py> { /// type Error = PyErr; /// /// fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result { /// Ok(MyObject(obj.cast()?.to_owned())) /// } /// } /// /// # fn main() {} /// ``` /// /// # Details /// [`Cow<'a, str>`] is an example of an output type that may or may not borrow from the input /// lifetime `'a`. Which variant will be produced depends on the runtime type of the Python object. /// For a Python byte string, the existing string data can be borrowed for `'a` into a /// [`Cow::Borrowed`]. For a Python Unicode string, the data may have to be reencoded to UTF-8, and /// copied into a [`Cow::Owned`]. It does _not_ depend on the Python lifetime `'py`. /// /// The output type may also depend on the Python lifetime `'py`. This allows the output type to /// keep interacting with the Python interpreter. See also [`Bound<'py, T>`]. /// /// [`Cow<'a, str>`]: std::borrow::Cow /// [`Cow::Borrowed`]: std::borrow::Cow::Borrowed /// [`Cow::Owned`]: std::borrow::Cow::Owned /// [guide]: https://pyo3.rs/latest/conversions/traits.html#deriving-frompyobject pub trait FromPyObject<'a, 'py>: Sized { /// The type returned in the event of a conversion error. /// /// For most use cases defaulting to [PyErr] here is perfectly acceptable. Using a custom error /// type can be used to avoid having to create a Python exception object in the case where that /// exception never reaches Python. This may lead to slightly better performance under certain /// conditions. /// /// # Note /// Unfortunately `Try` and thus `?` is based on [`From`], not [`Into`], so implementations may /// need to use `.map_err(Into::into)` sometimes to convert a generic `Error` into a [`PyErr`]. type Error: Into; /// Provides the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would be `collections.abc.Sequence[int]`. /// The default value is `typing.Any`, which is correct for any type. #[cfg(feature = "experimental-inspect")] const INPUT_TYPE: &'static str = "typing.Any"; /// Extracts `Self` from the bound smart pointer `obj`. /// /// Users are advised against calling this method directly: instead, use this via /// [`Bound<'_, PyAny>::extract`](crate::types::any::PyAnyMethods::extract) or [`Py::extract`]. fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result; /// Extracts the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would return `Sequence[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`, /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any } /// Specialization hook for extracting sequences for types like `Vec` and `[u8; N]`, /// where the bytes can be directly copied from some python objects without going through /// iteration. #[doc(hidden)] #[inline(always)] #[cfg(return_position_impl_trait_in_traits)] fn sequence_extractor( _obj: Borrowed<'_, 'py, PyAny>, _: private::Token, ) -> Option> { struct NeverASequence(PhantomData); impl FromPyObjectSequence for NeverASequence { type Target = T; fn to_vec(&self) -> Vec { unreachable!() } fn to_array(&self) -> PyResult<[Self::Target; N]> { unreachable!() } } Option::>::None } /// Equivalent to the above for MSRV < 1.75, which pays an additional allocation cost. #[doc(hidden)] #[inline(always)] #[cfg(not(return_position_impl_trait_in_traits))] fn sequence_extractor<'b>( _obj: Borrowed<'b, 'b, PyAny>, _: private::Token, ) -> Option + 'b>> { None } /// Helper used to make a specialized path in extracting `DateTime` where `Tz` is /// `chrono::Local`, which will accept "naive" datetime objects as being in the local timezone. #[cfg(feature = "chrono-local")] #[inline] fn as_local_tz(_: private::Token) -> Option { None } } mod from_py_object_sequence { use crate::PyResult; /// Private trait for implementing specialized sequence extraction for `Vec` and `[u8; N]` #[doc(hidden)] pub trait FromPyObjectSequence { type Target; fn to_vec(&self) -> Vec; #[cfg(return_position_impl_trait_in_traits)] fn to_array(&self) -> PyResult<[Self::Target; N]>; /// Fills an uninit slice with values from the object. /// /// on success, `out` is fully initialized, on failure, `out` should be considered uninitialized. #[cfg(not(return_position_impl_trait_in_traits))] fn fill_slice(&self, out: &mut [std::mem::MaybeUninit]) -> PyResult<()>; } } // Only reachable / implementable inside PyO3 itself. pub(crate) use from_py_object_sequence::FromPyObjectSequence; /// A data structure that can be extracted without borrowing any data from the input. /// /// This is primarily useful for trait bounds. For example a [`FromPyObject`] implementation of a /// wrapper type may be able to borrow data from the input, but a [`FromPyObject`] implementation of /// a collection type may only extract owned data. /// /// For example [`PyList`] will not hand out references tied to its own lifetime, but "owned" /// references independent of it. (Similar to [`Vec>`] where you clone the [`Arc`] out). /// This makes it impossible to collect borrowed types in a collection, since they would not borrow /// from the original [`PyList`], but the much shorter lived element reference. See the example /// below. /// /// ```,no_run /// # use pyo3::prelude::*; /// # #[allow(dead_code)] /// pub struct MyWrapper(T); /// /// impl<'a, 'py, T> FromPyObject<'a, 'py> for MyWrapper /// where /// T: FromPyObject<'a, 'py> /// { /// type Error = T::Error; /// /// fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { /// obj.extract().map(MyWrapper) /// } /// } /// /// # #[allow(dead_code)] /// pub struct MyVec(Vec); /// /// impl<'py, T> FromPyObject<'_, 'py> for MyVec /// where /// T: FromPyObjectOwned<'py> // 👈 can only extract owned values, because each `item` below /// // is a temporary short lived owned reference /// { /// type Error = PyErr; /// /// fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result { /// let mut v = MyVec(Vec::new()); /// for item in obj.try_iter()? { /// v.0.push(item?.extract::().map_err(Into::into)?); /// } /// Ok(v) /// } /// } /// ``` /// /// [`PyList`]: crate::types::PyList /// [`Arc`]: std::sync::Arc pub trait FromPyObjectOwned<'py>: for<'a> FromPyObject<'a, 'py> {} impl<'py, T> FromPyObjectOwned<'py> for T where T: for<'a> FromPyObject<'a, 'py> {} impl<'a, 'py, T> FromPyObject<'a, 'py> for T where T: PyClass + Clone + ExtractPyClassWithClone, { type Error = PyClassGuardError<'a, 'py>; #[cfg(feature = "experimental-inspect")] const INPUT_TYPE: &'static str = ::TYPE_NAME; fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { Ok(obj.extract::>()?.clone()) } } impl<'a, 'py, T> FromPyObject<'a, 'py> for PyRef<'py, T> where T: PyClass, { type Error = PyClassGuardError<'a, 'py>; #[cfg(feature = "experimental-inspect")] const INPUT_TYPE: &'static str = ::TYPE_NAME; fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { obj.cast::() .map_err(|e| PyClassGuardError(Some(e)))? .try_borrow() .map_err(|_| PyClassGuardError(None)) } } impl<'a, 'py, T> FromPyObject<'a, 'py> for PyRefMut<'py, T> where T: PyClass, { type Error = PyClassGuardMutError<'a, 'py>; #[cfg(feature = "experimental-inspect")] const INPUT_TYPE: &'static str = ::TYPE_NAME; fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { obj.cast::() .map_err(|e| PyClassGuardMutError(Some(e)))? .try_borrow_mut() .map_err(|_| PyClassGuardMutError(None)) } } impl<'py> IntoPyObject<'py> for () { type Target = PyTuple; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyTuple::empty(py)) } } /// ```rust,compile_fail /// use pyo3::prelude::*; /// /// #[pyclass] /// struct TestClass { /// num: u32, /// } /// /// let t = TestClass { num: 10 }; /// /// Python::attach(|py| { /// let pyvalue = Py::new(py, t).unwrap().to_object(py); /// let t: TestClass = pyvalue.extract(py).unwrap(); /// }) /// ``` mod test_no_clone {} #[cfg(test)] mod tests { #[test] #[cfg(feature = "macros")] fn test_pyclass_skip_from_py_object() { use crate::{types::PyAnyMethods, FromPyObject, IntoPyObject, PyErr, Python}; #[crate::pyclass(crate = "crate", skip_from_py_object)] #[derive(Clone)] struct Foo(i32); impl<'py> FromPyObject<'_, 'py> for Foo { type Error = PyErr; fn extract(obj: crate::Borrowed<'_, 'py, crate::PyAny>) -> Result { if let Ok(obj) = obj.cast::() { Ok(obj.borrow().clone()) } else { obj.extract::().map(Self) } } } Python::attach(|py| { let foo1 = 42i32.into_pyobject(py)?; assert_eq!(foo1.extract::()?.0, 42); let foo2 = Foo(0).into_pyobject(py)?; assert_eq!(foo2.extract::()?.0, 0); Ok::<_, PyErr>(()) }) .unwrap(); } #[test] #[cfg(feature = "macros")] fn test_pyclass_from_py_object() { use crate::{types::PyAnyMethods, IntoPyObject, PyErr, Python}; #[crate::pyclass(crate = "crate", from_py_object)] #[derive(Clone)] struct Foo(i32); Python::attach(|py| { let foo1 = 42i32.into_pyobject(py)?; assert!(foo1.extract::().is_err()); let foo2 = Foo(0).into_pyobject(py)?; assert_eq!(foo2.extract::()?.0, 0); Ok::<_, PyErr>(()) }) .unwrap(); } } pyo3-0.27.2/src/conversions/anyhow.rs000064400000000000000000000152661046102023000156320ustar 00000000000000#![cfg(feature = "anyhow")] //! A conversion from [anyhow]’s [`Error`][anyhow-error] type to [`PyErr`]. //! //! Use of an error handling library like [anyhow] is common in application code and when you just //! want error handling to be easy. If you are writing a library or you need more control over your //! errors you might want to design your own error type instead. //! //! When the inner error is a [`PyErr`] without source, it will be extracted out. //! Otherwise a Python [`RuntimeError`] will be created. //! You might find that you need to map the error from your Rust code into another Python exception. //! See [`PyErr::new`] for more information about that. //! //! For information about error handling in general, see the [Error handling] chapter of the Rust //! book. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! anyhow = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"anyhow\"] }")] //! ``` //! //! Note that you must use compatible versions of anyhow and PyO3. //! The required anyhow version may vary based on the version of PyO3. //! //! # Example: Propagating a `PyErr` into [`anyhow::Error`] //! //! ```rust //! use pyo3::prelude::*; //! use std::path::PathBuf; //! //! // A wrapper around a Rust function. //! // The pyfunction macro performs the conversion to a PyErr //! #[pyfunction] //! fn py_open(filename: PathBuf) -> anyhow::Result> { //! let data = std::fs::read(filename)?; //! Ok(data) //! } //! //! fn main() { //! let error = Python::attach(|py| -> PyResult> { //! let fun = wrap_pyfunction!(py_open, py)?; //! let text = fun.call1(("foo.txt",))?.extract::>()?; //! Ok(text) //! }).unwrap_err(); //! //! println!("{}", error); //! } //! ``` //! //! # Example: Using `anyhow` in general //! //! Note that you don't need this feature to convert a [`PyErr`] into an [`anyhow::Error`], because //! it can already convert anything that implements [`Error`](std::error::Error): //! //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::PyBytes; //! //! // An example function that must handle multiple error types. //! // //! // To do this you usually need to design your own error type or use //! // `Box`. `anyhow` is a convenient alternative for this. //! pub fn decompress(bytes: &[u8]) -> anyhow::Result { //! // An arbitrary example of a Python api you //! // could call inside an application... //! // This might return a `PyErr`. //! let res = Python::attach(|py| { //! let zlib = PyModule::import(py, "zlib")?; //! let decompress = zlib.getattr("decompress")?; //! let bytes = PyBytes::new(py, bytes); //! let value = decompress.call1((bytes,))?; //! value.extract::>() //! })?; //! //! // This might be a `FromUtf8Error`. //! let text = String::from_utf8(res)?; //! //! Ok(text) //! } //! //! fn main() -> anyhow::Result<()> { //! let bytes: &[u8] = b"x\x9c\x8b\xcc/U(\xce\xc8/\xcdIQ((\xcaOJL\xca\xa9T\ //! (-NU(\xc9HU\xc8\xc9LJ\xcbI,IUH.\x02\x91\x99y\xc5%\ //! \xa9\x89)z\x00\xf2\x15\x12\xfe"; //! let text = decompress(bytes)?; //! //! println!("The text is \"{}\"", text); //! # assert_eq!(text, "You should probably use the libflate crate instead."); //! Ok(()) //! } //! ``` //! //! [anyhow]: https://docs.rs/anyhow/ "A trait object based error system for easy idiomatic error handling in Rust applications." //! [anyhow-error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html "Anyhows `Error` type, a wrapper around a dynamic error type" //! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError "Built-in Exceptions — Python documentation" //! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html "Recoverable Errors with Result - The Rust Programming Language" use crate::exceptions::PyRuntimeError; use crate::PyErr; impl From for PyErr { fn from(mut error: anyhow::Error) -> Self { // Errors containing a PyErr without chain or context are returned as the underlying error if error.source().is_none() { error = match error.downcast::() { Ok(py_err) => return py_err, Err(error) => error, }; } PyRuntimeError::new_err(format!("{error:?}")) } } #[cfg(test)] mod test_anyhow { use crate::exceptions::{PyRuntimeError, PyValueError}; use crate::types::IntoPyDict; use crate::{ffi, prelude::*}; use anyhow::{anyhow, bail, Context, Result}; fn f() -> Result<()> { use std::io; bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); } fn g() -> Result<()> { f().context("f failed") } fn h() -> Result<()> { g().context("g failed") } #[test] fn test_pyo3_exception_contents() { let err = h().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::attach(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } fn k() -> Result<()> { Err(anyhow!("Some sort of error")) } #[test] fn test_pyo3_exception_contents2() { let err = k().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::attach(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } #[test] fn test_pyo3_unwrap_simple_err() { let origin_exc = PyValueError::new_err("Value Error"); let err: anyhow::Error = origin_exc.into(); let converted: PyErr = err.into(); assert!(Python::attach( |py| converted.is_instance_of::(py) )) } #[test] fn test_pyo3_unwrap_complex_err() { let origin_exc = PyValueError::new_err("Value Error"); let mut err: anyhow::Error = origin_exc.into(); err = err.context("Context"); let converted: PyErr = err.into(); assert!(Python::attach( |py| converted.is_instance_of::(py) )) } } pyo3-0.27.2/src/conversions/bigdecimal.rs000064400000000000000000000176411046102023000164040ustar 00000000000000#![cfg(feature = "bigdecimal")] //! Conversions to and from [bigdecimal](https://docs.rs/bigdecimal)'s [`BigDecimal`] type. //! //! This is useful for converting Python's decimal.Decimal into and from a native Rust type. //! //! # Setup //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"bigdecimal\"] }")] //! bigdecimal = "0.4" //! ``` //! //! Note that you must use a compatible version of bigdecimal and PyO3. //! The required bigdecimal version may vary based on the version of PyO3. //! //! # Example //! //! Rust code to create a function that adds one to a BigDecimal //! //! ```rust //! use bigdecimal::BigDecimal; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(d: BigDecimal) -> BigDecimal { //! d + 1 //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality //! //! //! ```python //! from my_module import add_one //! from decimal import Decimal //! //! d = Decimal("2") //! value = add_one(d) //! //! assert d + 1 == value //! ``` use std::str::FromStr; use crate::types::PyTuple; use crate::{ exceptions::PyValueError, sync::PyOnceLock, types::{PyAnyMethods, PyStringMethods, PyType}, Borrowed, Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, PyResult, Python, }; use bigdecimal::BigDecimal; use num_bigint::Sign; fn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static DECIMAL_CLS: PyOnceLock> = PyOnceLock::new(); DECIMAL_CLS.import(py, "decimal", "Decimal") } fn get_invalid_operation_error_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static INVALID_OPERATION_CLS: PyOnceLock> = PyOnceLock::new(); INVALID_OPERATION_CLS.import(py, "decimal", "InvalidOperation") } impl FromPyObject<'_, '_> for BigDecimal { type Error = PyErr; fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult { let py_str = &obj.str()?; let rs_str = &py_str.to_cow()?; BigDecimal::from_str(rs_str).map_err(|e| PyValueError::new_err(e.to_string())) } } impl<'py> IntoPyObject<'py> for BigDecimal { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let cls = get_decimal_cls(py)?; let (bigint, scale) = self.into_bigint_and_scale(); if scale == 0 { return cls.call1((bigint,)); } let exponent = scale.checked_neg().ok_or_else(|| { get_invalid_operation_error_cls(py) .map_or_else(|err| err, |cls| PyErr::from_type(cls.clone(), ())) })?; let (sign, digits) = bigint.to_radix_be(10); let signed = matches!(sign, Sign::Minus).into_pyobject(py)?; let digits = PyTuple::new(py, digits)?; cls.call1(((signed, digits, exponent),)) } } #[cfg(test)] mod test_bigdecimal { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; use std::ffi::CString; use crate::ffi; use bigdecimal::{One, Zero}; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; macro_rules! convert_constants { ($name:ident, $rs:expr, $py:literal) => { #[test] fn $name() { Python::attach(|py| { let rs_orig = $rs; let rs_dec = rs_orig.clone().into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); // Checks if BigDecimal -> Python Decimal conversion is correct py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec", $py )) .unwrap(), None, Some(&locals), ) .unwrap(); // Checks if Python Decimal -> BigDecimal conversion is correct let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let py_result: BigDecimal = py_dec.extract().unwrap(); assert_eq!(rs_orig, py_result); }) } }; } convert_constants!(convert_zero, BigDecimal::zero(), "0"); convert_constants!(convert_one, BigDecimal::one(), "1"); convert_constants!(convert_neg_one, -BigDecimal::one(), "-1"); convert_constants!(convert_two, BigDecimal::from(2), "2"); convert_constants!(convert_ten, BigDecimal::from_str("10").unwrap(), "10"); convert_constants!( convert_one_hundred_point_one, BigDecimal::from_str("100.1").unwrap(), "100.1" ); convert_constants!( convert_one_thousand, BigDecimal::from_str("1000").unwrap(), "1000" ); convert_constants!( convert_scientific, BigDecimal::from_str("1e10").unwrap(), "1e10" ); #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_roundtrip( number in 0..28u32 ) { let num = BigDecimal::from(number); Python::attach(|py| { let rs_dec = num.clone().into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal(\"{num}\")\nassert py_dec == rs_dec")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: BigDecimal = rs_dec.extract().unwrap(); assert_eq!(num, roundtripped); }) } #[test] fn test_integers(num in any::()) { Python::attach(|py| { let py_num = num.into_pyobject(py).unwrap(); let roundtripped: BigDecimal = py_num.extract().unwrap(); let rs_dec = BigDecimal::from(num); assert_eq!(rs_dec, roundtripped); }) } } #[test] fn test_nan() { Python::attach(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"NaN\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } #[test] fn test_infinity() { Python::attach(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"Infinity\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } #[test] fn test_no_precision_loss() { Python::attach(|py| { let src = "1e4"; let expected = get_decimal_cls(py) .unwrap() .call1((src,)) .unwrap() .call_method0("as_tuple") .unwrap(); let actual = src .parse::() .unwrap() .into_pyobject(py) .unwrap() .call_method0("as_tuple") .unwrap(); assert!(actual.eq(expected).unwrap()); }); } } pyo3-0.27.2/src/conversions/bytes.rs000064400000000000000000000074121046102023000154450ustar 00000000000000#![cfg(feature = "bytes")] //! Conversions to and from [bytes](https://docs.rs/bytes/latest/bytes/)'s [`Bytes`]. //! //! This is useful for efficiently converting Python's `bytes` types efficiently. //! While `bytes` will be directly borrowed, converting from `bytearray` will result in a copy. //! //! When converting `Bytes` back into Python, this will do a copy, just like `&[u8]` and `Vec`. //! //! # When to use `Bytes` //! //! Unless you specifically need [`Bytes`] for ref-counted ownership and sharing, //! you may find that using `&[u8]`, `Vec`, [`Bound`], or [`PyBackedBytes`] //! is simpler for most use cases. //! //! # Setup //! //! To use this feature, add in your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! bytes = "1.10" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"bytes\"] }")] //! ``` //! //! Note that you must use compatible versions of bytes and PyO3. //! //! # Example //! //! Rust code to create functions which return `Bytes` or take `Bytes` as arguments: //! //! ```rust,no_run //! use pyo3::prelude::*; //! use bytes::Bytes; //! //! #[pyfunction] //! fn get_message_bytes() -> Bytes { //! Bytes::from_static(b"Hello Python!") //! } //! //! #[pyfunction] //! fn num_bytes(bytes: Bytes) -> usize { //! bytes.len() //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(get_message_bytes, m)?)?; //! m.add_function(wrap_pyfunction!(num_bytes, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that calls these functions: //! //! ```python //! from my_module import get_message_bytes, num_bytes //! //! message = get_message_bytes() //! assert message == b"Hello Python!" //! //! size = num_bytes(message) //! assert size == 13 //! ``` use bytes::Bytes; use crate::conversion::IntoPyObject; use crate::instance::Bound; use crate::pybacked::PyBackedBytes; use crate::types::PyBytes; use crate::{Borrowed, CastError, FromPyObject, PyAny, PyErr, Python}; impl<'a, 'py> FromPyObject<'a, 'py> for Bytes { type Error = CastError<'a, 'py>; fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { Ok(Bytes::from_owner(obj.extract::()?)) } } impl<'py> IntoPyObject<'py> for Bytes { type Target = PyBytes; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyBytes::new(py, &self)) } } impl<'py> IntoPyObject<'py> for &Bytes { type Target = PyBytes; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyBytes::new(py, self)) } } #[cfg(test)] mod tests { use super::*; use crate::types::{PyAnyMethods, PyByteArray, PyByteArrayMethods, PyBytes}; use crate::Python; #[test] fn test_bytes() { Python::attach(|py| { let py_bytes = PyBytes::new(py, b"foobar"); let bytes: Bytes = py_bytes.extract().unwrap(); assert_eq!(&*bytes, b"foobar"); let bytes = Bytes::from_static(b"foobar").into_pyobject(py).unwrap(); assert!(bytes.is_instance_of::()); }); } #[test] fn test_bytearray() { Python::attach(|py| { let py_bytearray = PyByteArray::new(py, b"foobar"); let bytes: Bytes = py_bytearray.extract().unwrap(); assert_eq!(&*bytes, b"foobar"); // Editing the bytearray should not change extracted Bytes unsafe { py_bytearray.as_bytes_mut()[0] = b'x' }; assert_eq!(&bytes, "foobar"); assert_eq!(&py_bytearray.extract::>().unwrap(), b"xoobar"); }); } } pyo3-0.27.2/src/conversions/chrono.rs000064400000000000000000001511311046102023000156050ustar 00000000000000#![cfg(feature = "chrono")] //! Conversions to and from [chrono](https://docs.rs/chrono/)’s `Duration`, //! `NaiveDate`, `NaiveTime`, `DateTime`, `FixedOffset`, and `Utc`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! chrono = "0.4" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"chrono\"] }")] //! ``` //! //! Note that you must use compatible versions of chrono and PyO3. //! The required chrono version may vary based on the version of PyO3. //! //! # Example: Convert a `datetime.datetime` to chrono's `DateTime` //! //! ```rust //! use chrono::{DateTime, Duration, TimeZone, Utc}; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! Python::initialize(); //! Python::attach(|py| { //! // Build some chrono values //! let chrono_datetime = Utc.with_ymd_and_hms(2022, 1, 1, 12, 0, 0).unwrap(); //! let chrono_duration = Duration::seconds(1); //! // Convert them to Python //! let py_datetime = chrono_datetime.into_pyobject(py)?; //! let py_timedelta = chrono_duration.into_pyobject(py)?; //! // Do an operation in Python //! let py_sum = py_datetime.call_method1("__add__", (py_timedelta,))?; //! // Convert back to Rust //! let chrono_sum: DateTime = py_sum.extract()?; //! println!("DateTime: {}", chrono_datetime); //! Ok(()) //! }) //! } //! ``` use crate::conversion::{FromPyObjectOwned, IntoPyObject}; use crate::exceptions::{PyTypeError, PyUserWarning, PyValueError}; use crate::intern; use crate::types::any::PyAnyMethods; use crate::types::PyNone; use crate::types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess}; #[cfg(not(Py_LIMITED_API))] use crate::types::{PyDateAccess, PyDeltaAccess, PyTimeAccess}; #[cfg(feature = "chrono-local")] use crate::{ exceptions::PyRuntimeError, sync::PyOnceLock, types::{PyString, PyStringMethods}, Py, }; use crate::{ffi, Borrowed, Bound, FromPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python}; use chrono::offset::{FixedOffset, Utc}; #[cfg(feature = "chrono-local")] use chrono::Local; use chrono::{ DateTime, Datelike, Duration, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike, }; impl<'py> IntoPyObject<'py> for Duration { type Target = PyDelta; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { // Total number of days let days = self.num_days(); // Remainder of seconds let secs_dur = self - Duration::days(days); let secs = secs_dur.num_seconds(); // Fractional part of the microseconds let micros = (secs_dur - Duration::seconds(secs_dur.num_seconds())) .num_microseconds() // This should never panic since we are just getting the fractional // part of the total microseconds, which should never overflow. .unwrap(); // We do not need to check the days i64 to i32 cast from rust because // python will panic with OverflowError. // We pass true as the `normalize` parameter since we'd need to do several checks here to // avoid that, and it shouldn't have a big performance impact. // The seconds and microseconds cast should never overflow since it's at most the number of seconds per day PyDelta::new( py, days.try_into().unwrap_or(i32::MAX), secs.try_into()?, micros.try_into()?, true, ) } } impl<'py> IntoPyObject<'py> for &Duration { type Target = PyDelta; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for Duration { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { let delta = ob.cast::()?; // Python size are much lower than rust size so we do not need bound checks. // 0 <= microseconds < 1000000 // 0 <= seconds < 3600*24 // -999999999 <= days <= 999999999 #[cfg(not(Py_LIMITED_API))] let (days, seconds, microseconds) = { ( delta.get_days().into(), delta.get_seconds().into(), delta.get_microseconds().into(), ) }; #[cfg(Py_LIMITED_API)] let (days, seconds, microseconds) = { let py = delta.py(); ( delta.getattr(intern!(py, "days"))?.extract()?, delta.getattr(intern!(py, "seconds"))?.extract()?, delta.getattr(intern!(py, "microseconds"))?.extract()?, ) }; Ok( Duration::days(days) + Duration::seconds(seconds) + Duration::microseconds(microseconds), ) } } impl<'py> IntoPyObject<'py> for NaiveDate { type Target = PyDate; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let DateArgs { year, month, day } = (&self).into(); PyDate::new(py, year, month, day) } } impl<'py> IntoPyObject<'py> for &NaiveDate { type Target = PyDate; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for NaiveDate { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { let date = &*ob.cast::()?; py_date_to_naive_date(date) } } impl<'py> IntoPyObject<'py> for NaiveTime { type Target = PyTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let TimeArgs { hour, min, sec, micro, truncated_leap_second, } = (&self).into(); let time = PyTime::new(py, hour, min, sec, micro, None)?; if truncated_leap_second { warn_truncated_leap_second(&time); } Ok(time) } } impl<'py> IntoPyObject<'py> for &NaiveTime { type Target = PyTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for NaiveTime { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { let time = &*ob.cast::()?; py_time_to_naive_time(time) } } impl<'py> IntoPyObject<'py> for NaiveDateTime { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let DateArgs { year, month, day } = (&self.date()).into(); let TimeArgs { hour, min, sec, micro, truncated_leap_second, } = (&self.time()).into(); let datetime = PyDateTime::new(py, year, month, day, hour, min, sec, micro, None)?; if truncated_leap_second { warn_truncated_leap_second(&datetime); } Ok(datetime) } } impl<'py> IntoPyObject<'py> for &NaiveDateTime { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for NaiveDateTime { type Error = PyErr; fn extract(dt: Borrowed<'_, '_, PyAny>) -> Result { let dt = &*dt.cast::()?; // If the user tries to convert a timezone aware datetime into a naive one, // we return a hard error. We could silently remove tzinfo, or assume local timezone // and do a conversion, but better leave this decision to the user of the library. let has_tzinfo = dt.get_tzinfo().is_some(); if has_tzinfo { return Err(PyTypeError::new_err("expected a datetime without tzinfo")); } let dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?); Ok(dt) } } impl<'py, Tz: TimeZone> IntoPyObject<'py> for DateTime where Tz: IntoPyObject<'py>, { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } impl<'py, Tz: TimeZone> IntoPyObject<'py> for &DateTime where Tz: IntoPyObject<'py>, { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let tz = self.timezone().into_bound_py_any(py)?.cast_into()?; let DateArgs { year, month, day } = (&self.naive_local().date()).into(); let TimeArgs { hour, min, sec, micro, truncated_leap_second, } = (&self.naive_local().time()).into(); let fold = matches!( self.timezone().offset_from_local_datetime(&self.naive_local()), LocalResult::Ambiguous(_, latest) if self.offset().fix() == latest.fix() ); let datetime = PyDateTime::new_with_fold( py, year, month, day, hour, min, sec, micro, Some(&tz), fold, )?; if truncated_leap_second { warn_truncated_leap_second(&datetime); } Ok(datetime) } } impl<'py, Tz> FromPyObject<'_, 'py> for DateTime where Tz: TimeZone + FromPyObjectOwned<'py>, { type Error = PyErr; fn extract(dt: Borrowed<'_, 'py, PyAny>) -> Result { let dt = &*dt.cast::()?; let tzinfo = dt.get_tzinfo(); let tz = if let Some(tzinfo) = tzinfo { tzinfo.extract().map_err(Into::into)? } else { // Special case: allow naive `datetime` objects for `DateTime`, interpreting them as local time. #[cfg(feature = "chrono-local")] if let Some(tz) = Tz::as_local_tz(crate::conversion::private::Token) { return py_datetime_to_datetime_with_timezone(dt, tz); } return Err(PyTypeError::new_err( "expected a datetime with non-None tzinfo", )); }; py_datetime_to_datetime_with_timezone(dt, tz) } } impl<'py> IntoPyObject<'py> for FixedOffset { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let seconds_offset = self.local_minus_utc(); let td = PyDelta::new(py, 0, seconds_offset, 0, true)?; PyTzInfo::fixed_offset(py, td) } } impl<'py> IntoPyObject<'py> for &FixedOffset { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for FixedOffset { type Error = PyErr; /// Convert python tzinfo to rust [`FixedOffset`]. /// /// Note that the conversion will result in precision lost in microseconds as chrono offset /// does not supports microseconds. fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { let ob = ob.cast::()?; // Passing Python's None to the `utcoffset` function will only // work for timezones defined as fixed offsets in Python. // Any other timezone would require a datetime as the parameter, and return // None if the datetime is not provided. // Trying to convert None to a PyDelta in the next line will then fail. let py_timedelta = ob.call_method1(intern!(ob.py(), "utcoffset"), (PyNone::get(ob.py()),))?; if py_timedelta.is_none() { return Err(PyTypeError::new_err(format!( "{ob:?} is not a fixed offset timezone" ))); } let total_seconds: Duration = py_timedelta.extract()?; // This cast is safe since the timedelta is limited to -24 hours and 24 hours. let total_seconds = total_seconds.num_seconds() as i32; FixedOffset::east_opt(total_seconds) .ok_or_else(|| PyValueError::new_err("fixed offset out of bounds")) } } impl<'py> IntoPyObject<'py> for Utc { type Target = PyTzInfo; type Output = Borrowed<'static, 'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { PyTzInfo::utc(py) } } impl<'py> IntoPyObject<'py> for &Utc { type Target = PyTzInfo; type Output = Borrowed<'static, 'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for Utc { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { let py_utc = PyTzInfo::utc(ob.py())?; if ob.eq(py_utc)? { Ok(Utc) } else { Err(PyValueError::new_err("expected datetime.timezone.utc")) } } } #[cfg(feature = "chrono-local")] impl<'py> IntoPyObject<'py> for Local { type Target = PyTzInfo; type Output = Borrowed<'static, 'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { static LOCAL_TZ: PyOnceLock> = PyOnceLock::new(); let tz = LOCAL_TZ .get_or_try_init(py, || { let iana_name = iana_time_zone::get_timezone().map_err(|e| { PyRuntimeError::new_err(format!("Could not get local timezone: {e}")) })?; PyTzInfo::timezone(py, iana_name).map(Bound::unbind) })? .bind_borrowed(py); Ok(tz) } } #[cfg(feature = "chrono-local")] impl<'py> IntoPyObject<'py> for &Local { type Target = PyTzInfo; type Output = Borrowed<'static, 'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } #[cfg(feature = "chrono-local")] impl FromPyObject<'_, '_> for Local { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult { let local_tz = Local.into_pyobject(ob.py())?; if ob.eq(local_tz)? { Ok(Local) } else { let name = local_tz.getattr("key")?.cast_into::()?; Err(PyValueError::new_err(format!( "expected local timezone {}", name.to_cow()? ))) } } #[inline] fn as_local_tz(_: crate::conversion::private::Token) -> Option { Some(Local) } } struct DateArgs { year: i32, month: u8, day: u8, } impl From<&NaiveDate> for DateArgs { fn from(value: &NaiveDate) -> Self { Self { year: value.year(), month: value.month() as u8, day: value.day() as u8, } } } struct TimeArgs { hour: u8, min: u8, sec: u8, micro: u32, truncated_leap_second: bool, } impl From<&NaiveTime> for TimeArgs { fn from(value: &NaiveTime) -> Self { let ns = value.nanosecond(); let checked_sub = ns.checked_sub(1_000_000_000); let truncated_leap_second = checked_sub.is_some(); let micro = checked_sub.unwrap_or(ns) / 1000; Self { hour: value.hour() as u8, min: value.minute() as u8, sec: value.second() as u8, micro, truncated_leap_second, } } } fn warn_truncated_leap_second(obj: &Bound<'_, PyAny>) { let py = obj.py(); if let Err(e) = PyErr::warn( py, &py.get_type::(), ffi::c_str!("ignored leap-second, `datetime` does not support leap-seconds"), 0, ) { e.write_unraisable(py, Some(obj)) }; } #[cfg(not(Py_LIMITED_API))] fn py_date_to_naive_date( py_date: impl std::ops::Deref, ) -> PyResult { NaiveDate::from_ymd_opt( py_date.get_year(), py_date.get_month().into(), py_date.get_day().into(), ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range date")) } #[cfg(Py_LIMITED_API)] fn py_date_to_naive_date(py_date: &Bound<'_, PyAny>) -> PyResult { NaiveDate::from_ymd_opt( py_date.getattr(intern!(py_date.py(), "year"))?.extract()?, py_date.getattr(intern!(py_date.py(), "month"))?.extract()?, py_date.getattr(intern!(py_date.py(), "day"))?.extract()?, ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range date")) } #[cfg(not(Py_LIMITED_API))] fn py_time_to_naive_time( py_time: impl std::ops::Deref, ) -> PyResult { NaiveTime::from_hms_micro_opt( py_time.get_hour().into(), py_time.get_minute().into(), py_time.get_second().into(), py_time.get_microsecond(), ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range time")) } #[cfg(Py_LIMITED_API)] fn py_time_to_naive_time(py_time: &Bound<'_, PyAny>) -> PyResult { NaiveTime::from_hms_micro_opt( py_time.getattr(intern!(py_time.py(), "hour"))?.extract()?, py_time .getattr(intern!(py_time.py(), "minute"))? .extract()?, py_time .getattr(intern!(py_time.py(), "second"))? .extract()?, py_time .getattr(intern!(py_time.py(), "microsecond"))? .extract()?, ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range time")) } fn py_datetime_to_datetime_with_timezone( dt: &Bound<'_, PyDateTime>, tz: Tz, ) -> PyResult> { let naive_dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?); match naive_dt.and_local_timezone(tz) { LocalResult::Single(value) => Ok(value), LocalResult::Ambiguous(earliest, latest) => { #[cfg(not(Py_LIMITED_API))] let fold = dt.get_fold(); #[cfg(Py_LIMITED_API)] let fold = dt.getattr(intern!(dt.py(), "fold"))?.extract::()? > 0; if fold { Ok(latest) } else { Ok(earliest) } } LocalResult::None => Err(PyValueError::new_err(format!( "The datetime {dt:?} contains an incompatible timezone" ))), } } #[cfg(test)] mod tests { use super::*; use crate::{test_utils::assert_warnings, types::PyTuple, BoundObject}; use std::{cmp::Ordering, panic}; #[test] // Only Python>=3.9 has the zoneinfo package // We skip the test on windows too since we'd need to install // tzdata there to make this work. #[cfg(all(Py_3_9, not(target_os = "windows")))] fn test_zoneinfo_is_not_fixed_offset() { use crate::ffi; use crate::types::any::PyAnyMethods; use crate::types::dict::PyDictMethods; Python::attach(|py| { let locals = crate::types::PyDict::new(py); py.run( ffi::c_str!("import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')"), None, Some(&locals), ) .unwrap(); let result: PyResult = locals.get_item("zi").unwrap().unwrap().extract(); assert!(result.is_err()); let res = result.err().unwrap(); // Also check the error message is what we expect let msg = res.value(py).repr().unwrap().to_string(); assert_eq!(msg, "TypeError(\"zoneinfo.ZoneInfo(key='Europe/London') is not a fixed offset timezone\")"); }); } #[test] fn test_timezone_aware_to_naive_fails() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::attach(|py| { let py_datetime = new_py_datetime_ob(py, "datetime", (2022, 1, 1, 1, 0, 0, 0, python_utc(py))); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult = py_datetime.extract(); assert_eq!( res.unwrap_err().value(py).repr().unwrap().to_string(), "TypeError('expected a datetime without tzinfo')" ); }); } #[test] fn test_naive_to_timezone_aware_fails() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::attach(|py| { let py_datetime = new_py_datetime_ob(py, "datetime", (2022, 1, 1, 1, 0, 0, 0)); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult> = py_datetime.extract(); assert_eq!( res.unwrap_err().value(py).repr().unwrap().to_string(), "TypeError('expected a datetime with non-None tzinfo')" ); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult> = py_datetime.extract(); assert_eq!( res.unwrap_err().value(py).repr().unwrap().to_string(), "TypeError('expected a datetime with non-None tzinfo')" ); }); } #[test] fn test_invalid_types_fail() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::attach(|py| { let none = py.None().into_bound(py); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'timedelta'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'tzinfo'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "ValueError: expected datetime.timezone.utc" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'time'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'date'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'datetime'" ); assert_eq!( none.extract::>().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be cast as 'datetime'" ); assert_eq!( none.extract::>() .unwrap_err() .to_string(), "TypeError: 'NoneType' object cannot be cast as 'datetime'" ); }); } #[test] fn test_pyo3_timedelta_into_pyobject() { // Utility function used to check different durations. // The `name` parameter is used to identify the check in case of a failure. let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| { Python::attach(|py| { let delta = delta.into_pyobject(py).unwrap(); let py_delta = new_py_datetime_ob(py, "timedelta", (py_days, py_seconds, py_ms)); assert!( delta.eq(&py_delta).unwrap(), "{name}: {delta} != {py_delta}" ); }); }; let delta = Duration::days(-1) + Duration::seconds(1) + Duration::microseconds(-10); check("delta normalization", delta, -1, 1, -10); // Check the minimum value allowed by PyDelta, which is different // from the minimum value allowed in Duration. This should pass. let delta = Duration::seconds(-86399999913600); // min check("delta min value", delta, -999999999, 0, 0); // Same, for max value let delta = Duration::seconds(86399999999999) + Duration::nanoseconds(999999000); // max check("delta max value", delta, 999999999, 86399, 999999); // Also check that trying to convert an out of bound value errors. Python::attach(|py| { // min_value and max_value were deprecated in chrono 0.4.39 #[allow(deprecated)] { assert!(Duration::min_value().into_pyobject(py).is_err()); assert!(Duration::max_value().into_pyobject(py).is_err()); } }); } #[test] fn test_pyo3_timedelta_frompyobject() { // Utility function used to check different durations. // The `name` parameter is used to identify the check in case of a failure. let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| { Python::attach(|py| { let py_delta = new_py_datetime_ob(py, "timedelta", (py_days, py_seconds, py_ms)); let py_delta: Duration = py_delta.extract().unwrap(); assert_eq!(py_delta, delta, "{name}: {py_delta} != {delta}"); }) }; // Check the minimum value allowed by PyDelta, which is different // from the minimum value allowed in Duration. This should pass. check( "min py_delta value", Duration::seconds(-86399999913600), -999999999, 0, 0, ); // Same, for max value check( "max py_delta value", Duration::seconds(86399999999999) + Duration::microseconds(999999), 999999999, 86399, 999999, ); // This check is to assert that we can't construct every possible Duration from a PyDelta // since they have different bounds. Python::attach(|py| { let low_days: i32 = -1000000000; // This is possible assert!(panic::catch_unwind(|| Duration::days(low_days as i64)).is_ok()); // This panics on PyDelta::new assert!(panic::catch_unwind(|| { let py_delta = new_py_datetime_ob(py, "timedelta", (low_days, 0, 0)); if let Ok(_duration) = py_delta.extract::() { // So we should never get here } }) .is_err()); let high_days: i32 = 1000000000; // This is possible assert!(panic::catch_unwind(|| Duration::days(high_days as i64)).is_ok()); // This panics on PyDelta::new assert!(panic::catch_unwind(|| { let py_delta = new_py_datetime_ob(py, "timedelta", (high_days, 0, 0)); if let Ok(_duration) = py_delta.extract::() { // So we should never get here } }) .is_err()); }); } #[test] fn test_pyo3_date_into_pyobject() { let eq_ymd = |name: &'static str, year, month, day| { Python::attach(|py| { let date = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .into_pyobject(py) .unwrap(); let py_date = new_py_datetime_ob(py, "date", (year, month, day)); assert_eq!( date.compare(&py_date).unwrap(), Ordering::Equal, "{name}: {date} != {py_date}" ); }) }; eq_ymd("past date", 2012, 2, 29); eq_ymd("min date", 1, 1, 1); eq_ymd("future date", 3000, 6, 5); eq_ymd("max date", 9999, 12, 31); } #[test] fn test_pyo3_date_frompyobject() { let eq_ymd = |name: &'static str, year, month, day| { Python::attach(|py| { let py_date = new_py_datetime_ob(py, "date", (year, month, day)); let py_date: NaiveDate = py_date.extract().unwrap(); let date = NaiveDate::from_ymd_opt(year, month, day).unwrap(); assert_eq!(py_date, date, "{name}: {date} != {py_date}"); }) }; eq_ymd("past date", 2012, 2, 29); eq_ymd("min date", 1, 1, 1); eq_ymd("future date", 3000, 6, 5); eq_ymd("max date", 9999, 12, 31); } #[test] fn test_pyo3_datetime_into_pyobject_utc() { Python::attach(|py| { let check_utc = |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| { let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, ms) .unwrap() .and_utc(); let datetime = datetime.into_pyobject(py).unwrap(); let py_datetime = new_py_datetime_ob( py, "datetime", ( year, month, day, hour, minute, second, py_ms, python_utc(py), ), ); assert_eq!( datetime.compare(&py_datetime).unwrap(), Ordering::Equal, "{name}: {datetime} != {py_datetime}" ); }; check_utc("regular", 2014, 5, 6, 7, 8, 9, 999_999, 999_999); assert_warnings!( py, check_utc("leap second", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] fn test_pyo3_datetime_into_pyobject_fixed_offset() { Python::attach(|py| { let check_fixed_offset = |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| { let offset = FixedOffset::east_opt(3600).unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, ms) .unwrap() .and_local_timezone(offset) .unwrap(); let datetime = datetime.into_pyobject(py).unwrap(); let py_tz = offset.into_pyobject(py).unwrap(); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, py_ms, py_tz), ); assert_eq!( datetime.compare(&py_datetime).unwrap(), Ordering::Equal, "{name}: {datetime} != {py_datetime}" ); }; check_fixed_offset("regular", 2014, 5, 6, 7, 8, 9, 999_999, 999_999); assert_warnings!( py, check_fixed_offset("leap second", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] #[cfg(all(Py_3_9, feature = "chrono-tz", not(windows)))] fn test_pyo3_datetime_into_pyobject_tz() { Python::attach(|py| { let datetime = NaiveDate::from_ymd_opt(2024, 12, 11) .unwrap() .and_hms_opt(23, 3, 13) .unwrap() .and_local_timezone(chrono_tz::Tz::Europe__London) .unwrap(); let datetime = datetime.into_pyobject(py).unwrap(); let py_datetime = new_py_datetime_ob( py, "datetime", ( 2024, 12, 11, 23, 3, 13, 0, python_zoneinfo(py, "Europe/London"), ), ); assert_eq!(datetime.compare(&py_datetime).unwrap(), Ordering::Equal); }) } #[test] fn test_pyo3_datetime_frompyobject_utc() { Python::attach(|py| { let year = 2014; let month = 5; let day = 6; let hour = 7; let minute = 8; let second = 9; let micro = 999_999; let tz_utc = PyTzInfo::utc(py).unwrap(); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, tz_utc), ); let py_datetime: DateTime = py_datetime.extract().unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, micro) .unwrap() .and_utc(); assert_eq!(py_datetime, datetime,); }) } #[test] #[cfg(feature = "chrono-local")] fn test_pyo3_naive_datetime_frompyobject_local() { Python::attach(|py| { let year = 2014; let month = 5; let day = 6; let hour = 7; let minute = 8; let second = 9; let micro = 999_999; let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro), ); let py_datetime: DateTime = py_datetime.extract().unwrap(); let expected_datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, micro) .unwrap() .and_local_timezone(Local) .unwrap(); assert_eq!(py_datetime, expected_datetime); }) } #[test] fn test_pyo3_datetime_frompyobject_fixed_offset() { Python::attach(|py| { let year = 2014; let month = 5; let day = 6; let hour = 7; let minute = 8; let second = 9; let micro = 999_999; let offset = FixedOffset::east_opt(3600).unwrap(); let py_tz = offset.into_pyobject(py).unwrap(); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, py_tz), ); let datetime_from_py: DateTime = py_datetime.extract().unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, micro) .unwrap(); let datetime = datetime.and_local_timezone(offset).unwrap(); assert_eq!(datetime_from_py, datetime); assert!( py_datetime.extract::>().is_err(), "Extracting Utc from nonzero FixedOffset timezone will fail" ); let utc = python_utc(py); let py_datetime_utc = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, utc), ); assert!( py_datetime_utc.extract::>().is_ok(), "Extracting FixedOffset from Utc timezone will succeed" ); }) } #[test] fn test_pyo3_offset_fixed_into_pyobject() { Python::attach(|py| { // Chrono offset let offset = FixedOffset::east_opt(3600) .unwrap() .into_pyobject(py) .unwrap(); // Python timezone from timedelta let td = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_timedelta = new_py_datetime_ob(py, "timezone", (td,)); // Should be equal assert!(offset.eq(py_timedelta).unwrap()); // Same but with negative values let offset = FixedOffset::east_opt(-3600) .unwrap() .into_pyobject(py) .unwrap(); let td = new_py_datetime_ob(py, "timedelta", (0, -3600, 0)); let py_timedelta = new_py_datetime_ob(py, "timezone", (td,)); assert!(offset.eq(py_timedelta).unwrap()); }) } #[test] fn test_pyo3_offset_fixed_frompyobject() { Python::attach(|py| { let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_tzinfo = new_py_datetime_ob(py, "timezone", (py_timedelta,)); let offset: FixedOffset = py_tzinfo.extract().unwrap(); assert_eq!(FixedOffset::east_opt(3600).unwrap(), offset); }) } #[test] fn test_pyo3_offset_utc_into_pyobject() { Python::attach(|py| { let utc = Utc.into_pyobject(py).unwrap(); let py_utc = python_utc(py); assert!(utc.is(&py_utc)); }) } #[test] fn test_pyo3_offset_utc_frompyobject() { Python::attach(|py| { let py_utc = python_utc(py); let py_utc: Utc = py_utc.extract().unwrap(); assert_eq!(Utc, py_utc); let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 0, 0)); let py_timezone_utc = new_py_datetime_ob(py, "timezone", (py_timedelta,)); let py_timezone_utc: Utc = py_timezone_utc.extract().unwrap(); assert_eq!(Utc, py_timezone_utc); let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_timezone = new_py_datetime_ob(py, "timezone", (py_timedelta,)); assert!(py_timezone.extract::().is_err()); }) } #[test] fn test_pyo3_time_into_pyobject() { Python::attach(|py| { let check_time = |name: &'static str, hour, minute, second, ms, py_ms| { let time = NaiveTime::from_hms_micro_opt(hour, minute, second, ms) .unwrap() .into_pyobject(py) .unwrap(); let py_time = new_py_datetime_ob(py, "time", (hour, minute, second, py_ms)); assert!(time.eq(&py_time).unwrap(), "{name}: {time} != {py_time}"); }; check_time("regular", 3, 5, 7, 999_999, 999_999); assert_warnings!( py, check_time("leap second", 3, 5, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] fn test_pyo3_time_frompyobject() { let hour = 3; let minute = 5; let second = 7; let micro = 999_999; Python::attach(|py| { let py_time = new_py_datetime_ob(py, "time", (hour, minute, second, micro)); let py_time: NaiveTime = py_time.extract().unwrap(); let time = NaiveTime::from_hms_micro_opt(hour, minute, second, micro).unwrap(); assert_eq!(py_time, time); }) } fn new_py_datetime_ob<'py, A>(py: Python<'py>, name: &str, args: A) -> Bound<'py, PyAny> where A: IntoPyObject<'py, Target = PyTuple>, { py.import("datetime") .unwrap() .getattr(name) .unwrap() .call1( args.into_pyobject(py) .map_err(Into::into) .unwrap() .into_bound(), ) .unwrap() } fn python_utc(py: Python<'_>) -> Bound<'_, PyAny> { py.import("datetime") .unwrap() .getattr("timezone") .unwrap() .getattr("utc") .unwrap() } #[cfg(all(Py_3_9, feature = "chrono-tz", not(windows)))] fn python_zoneinfo<'py>(py: Python<'py>, timezone: &str) -> Bound<'py, PyAny> { py.import("zoneinfo") .unwrap() .getattr("ZoneInfo") .unwrap() .call1((timezone,)) .unwrap() } #[cfg(not(any(target_arch = "wasm32")))] mod proptests { use super::*; use crate::test_utils::CatchWarnings; use crate::types::IntoPyDict; use proptest::prelude::*; use std::ffi::CString; proptest! { // Range is limited to 1970 to 2038 due to windows limitations #[test] fn test_pyo3_offset_fixed_frompyobject_created_in_python(timestamp in 0..(i32::MAX as i64), timedelta in -86399i32..=86399i32) { Python::attach(|py| { let globals = [("datetime", py.import("datetime").unwrap())].into_py_dict(py).unwrap(); let code = format!("datetime.datetime.fromtimestamp({timestamp}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={timedelta})))"); let t = py.eval(&CString::new(code).unwrap(), Some(&globals), None).unwrap(); // Get ISO 8601 string from python let py_iso_str = t.call_method0("isoformat").unwrap(); // Get ISO 8601 string from rust let t = t.extract::>().unwrap(); // Python doesn't print the seconds of the offset if they are 0 let rust_iso_str = if timedelta % 60 == 0 { t.format("%Y-%m-%dT%H:%M:%S%:z").to_string() } else { t.format("%Y-%m-%dT%H:%M:%S%::z").to_string() }; // They should be equal assert_eq!(py_iso_str.to_string(), rust_iso_str); }) } #[test] fn test_duration_roundtrip(days in -999999999i64..=999999999i64) { // Test roundtrip conversion rust->python->rust for all allowed // python values of durations (from -999999999 to 999999999 days), Python::attach(|py| { let dur = Duration::days(days); let py_delta = dur.into_pyobject(py).unwrap(); let roundtripped: Duration = py_delta.extract().expect("Round trip"); assert_eq!(dur, roundtripped); }) } #[test] fn test_fixed_offset_roundtrip(secs in -86399i32..=86399i32) { Python::attach(|py| { let offset = FixedOffset::east_opt(secs).unwrap(); let py_offset = offset.into_pyobject(py).unwrap(); let roundtripped: FixedOffset = py_offset.extract().expect("Round trip"); assert_eq!(offset, roundtripped); }) } #[test] fn test_naive_date_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32 ) { // Test roundtrip conversion rust->python->rust for all allowed // python dates (from year 1 to year 9999) Python::attach(|py| { // We use to `from_ymd_opt` constructor so that we only test valid `NaiveDate`s. // This is to skip the test if we are creating an invalid date, like February 31. if let Some(date) = NaiveDate::from_ymd_opt(year, month, day) { let py_date = date.into_pyobject(py).unwrap(); let roundtripped: NaiveDate = py_date.extract().expect("Round trip"); assert_eq!(date, roundtripped); } }) } #[test] fn test_naive_time_roundtrip( hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32 ) { // Test roundtrip conversion rust->python->rust for naive times. // Python time has a resolution of microseconds, so we only test // NaiveTimes with microseconds resolution, even if NaiveTime has nanosecond // resolution. Python::attach(|py| { if let Some(time) = NaiveTime::from_hms_micro_opt(hour, min, sec, micro) { // Wrap in CatchWarnings to avoid to_object firing warning for truncated leap second let py_time = CatchWarnings::enter(py, |_| time.into_pyobject(py)).unwrap(); let roundtripped: NaiveTime = py_time.extract().expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); assert_eq!(expected_roundtrip_time, roundtripped); } }) } #[test] fn test_naive_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=24u32, min in 0u32..=60u32, sec in 0u32..=60u32, micro in 0u32..=999_999u32 ) { Python::attach(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt = NaiveDateTime::new(date, time); let pydt = dt.into_pyobject(py).unwrap(); let roundtripped: NaiveDateTime = pydt.extract().expect("Round trip"); assert_eq!(dt, roundtripped); } }) } #[test] fn test_utc_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32 ) { Python::attach(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt: DateTime = NaiveDateTime::new(date, time).and_utc(); // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap(); let roundtripped: DateTime = py_dt.extract().expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); let expected_roundtrip_dt: DateTime = NaiveDateTime::new(date, expected_roundtrip_time).and_utc(); assert_eq!(expected_roundtrip_dt, roundtripped); } }) } #[test] fn test_fixed_offset_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32, offset_secs in -86399i32..=86399i32 ) { Python::attach(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); let offset = FixedOffset::east_opt(offset_secs).unwrap(); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt: DateTime = NaiveDateTime::new(date, time).and_local_timezone(offset).unwrap(); // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap(); let roundtripped: DateTime = py_dt.extract().expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); let expected_roundtrip_dt: DateTime = NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(offset).unwrap(); assert_eq!(expected_roundtrip_dt, roundtripped); } }) } #[test] #[cfg(all(feature = "chrono-local", not(target_os = "windows")))] fn test_local_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32, ) { Python::attach(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dts = match NaiveDateTime::new(date, time).and_local_timezone(Local) { LocalResult::None => return, LocalResult::Single(dt) => [Some((dt, false)), None], LocalResult::Ambiguous(dt1, dt2) => [Some((dt1, false)), Some((dt2, true))], }; for (dt, fold) in dts.iter().filter_map(|input| *input) { // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap(); let roundtripped: DateTime = py_dt.extract().expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); let expected_roundtrip_dt: DateTime = if fold { NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(Local).latest() } else { NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(Local).earliest() }.unwrap(); assert_eq!(expected_roundtrip_dt, roundtripped); } } }) } } } } pyo3-0.27.2/src/conversions/chrono_tz.rs000064400000000000000000000147261046102023000163320ustar 00000000000000#![cfg(all(Py_3_9, feature = "chrono-tz"))] //! Conversions to and from [chrono-tz](https://docs.rs/chrono-tz/)’s `Tz`. //! //! This feature requires at least Python 3.9. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! chrono-tz = "0.8" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"chrono-tz\"] }")] //! ``` //! //! Note that you must use compatible versions of chrono, chrono-tz and PyO3. //! The required chrono version may vary based on the version of PyO3. //! //! # Example: Convert a `zoneinfo.ZoneInfo` to chrono-tz's `Tz` //! //! ```rust,no_run //! use chrono_tz::Tz; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! Python::initialize(); //! Python::attach(|py| { //! // Convert to Python //! let py_tzinfo = Tz::Europe__Paris.into_pyobject(py)?; //! // Convert back to Rust //! assert_eq!(py_tzinfo.extract::()?, Tz::Europe__Paris); //! Ok(()) //! }) //! } //! ``` use crate::conversion::IntoPyObject; use crate::exceptions::PyValueError; use crate::pybacked::PyBackedStr; use crate::types::{any::PyAnyMethods, PyTzInfo}; use crate::{intern, Borrowed, Bound, FromPyObject, PyAny, PyErr, Python}; use chrono_tz::Tz; use std::str::FromStr; impl<'py> IntoPyObject<'py> for Tz { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { PyTzInfo::timezone(py, self.name()) } } impl<'py> IntoPyObject<'py> for &Tz { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_, '_> for Tz { type Error = PyErr; fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result { Tz::from_str( &ob.getattr(intern!(ob.py(), "key"))? .extract::()?, ) .map_err(|e| PyValueError::new_err(e.to_string())) } } #[cfg(all(test, not(windows)))] // Troubles loading timezones on Windows mod tests { use super::*; use crate::prelude::PyAnyMethods; use crate::types::IntoPyDict; use crate::types::PyTzInfo; use crate::Bound; use crate::Python; use chrono::offset::LocalResult; use chrono::NaiveDate; use chrono::{DateTime, Utc}; use chrono_tz::Tz; #[test] fn test_frompyobject() { Python::attach(|py| { assert_eq!( new_zoneinfo(py, "Europe/Paris").extract::().unwrap(), Tz::Europe__Paris ); assert_eq!(new_zoneinfo(py, "UTC").extract::().unwrap(), Tz::UTC); assert_eq!( new_zoneinfo(py, "Etc/GMT-5").extract::().unwrap(), Tz::Etc__GMTMinus5 ); }); } #[test] fn test_ambiguous_datetime_to_pyobject() { let dates = [ DateTime::::from_str("2020-10-24 23:00:00 UTC").unwrap(), DateTime::::from_str("2020-10-25 00:00:00 UTC").unwrap(), DateTime::::from_str("2020-10-25 01:00:00 UTC").unwrap(), ]; let dates = dates.map(|dt| dt.with_timezone(&Tz::Europe__London)); assert_eq!( dates.map(|dt| dt.to_string()), [ "2020-10-25 00:00:00 BST", "2020-10-25 01:00:00 BST", "2020-10-25 01:00:00 GMT" ] ); let dates = Python::attach(|py| { let pydates = dates.map(|dt| dt.into_pyobject(py).unwrap()); assert_eq!( pydates .clone() .map(|dt| dt.getattr("hour").unwrap().extract::().unwrap()), [0, 1, 1] ); assert_eq!( pydates .clone() .map(|dt| dt.getattr("fold").unwrap().extract::().unwrap() > 0), [false, false, true] ); pydates.map(|dt| dt.extract::>().unwrap()) }); assert_eq!( dates.map(|dt| dt.to_string()), [ "2020-10-25 00:00:00 BST", "2020-10-25 01:00:00 BST", "2020-10-25 01:00:00 GMT" ] ); } #[test] fn test_nonexistent_datetime_from_pyobject() { // Pacific_Apia skipped the 30th of December 2011 entirely let naive_dt = NaiveDate::from_ymd_opt(2011, 12, 30) .unwrap() .and_hms_opt(2, 0, 0) .unwrap(); let tz = Tz::Pacific__Apia; // sanity check assert_eq!(naive_dt.and_local_timezone(tz), LocalResult::None); Python::attach(|py| { // create as a Python object manually let py_tz = tz.into_pyobject(py).unwrap(); let py_dt_naive = naive_dt.into_pyobject(py).unwrap(); let py_dt = py_dt_naive .call_method( "replace", (), Some(&[("tzinfo", py_tz)].into_py_dict(py).unwrap()), ) .unwrap(); // now try to extract let err = py_dt.extract::>().unwrap_err(); assert_eq!(err.to_string(), "ValueError: The datetime datetime.datetime(2011, 12, 30, 2, 0, tzinfo=zoneinfo.ZoneInfo(key='Pacific/Apia')) contains an incompatible timezone"); }); } #[test] #[cfg(not(Py_GIL_DISABLED))] // https://github.com/python/cpython/issues/116738#issuecomment-2404360445 fn test_into_pyobject() { Python::attach(|py| { let assert_eq = |l: Bound<'_, PyTzInfo>, r: Bound<'_, PyTzInfo>| { assert!(l.eq(&r).unwrap(), "{l:?} != {r:?}"); }; assert_eq( Tz::Europe__Paris.into_pyobject(py).unwrap(), new_zoneinfo(py, "Europe/Paris"), ); assert_eq(Tz::UTC.into_pyobject(py).unwrap(), new_zoneinfo(py, "UTC")); assert_eq( Tz::Etc__GMTMinus5.into_pyobject(py).unwrap(), new_zoneinfo(py, "Etc/GMT-5"), ); }); } fn new_zoneinfo<'py>(py: Python<'py>, name: &str) -> Bound<'py, PyTzInfo> { PyTzInfo::timezone(py, name).unwrap() } } pyo3-0.27.2/src/conversions/either.rs000064400000000000000000000127211046102023000155760ustar 00000000000000#![cfg(feature = "either")] //! Conversion to/from //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s //! [`Either`] type to a union of two Python types. //! //! Use of a generic sum type like [either] is common when you want to either accept one of two possible //! types as an argument or return one of two possible types from a function, without having to define //! a helper type manually yourself. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! either = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"either\"] }")] //! ``` //! //! Note that you must use compatible versions of either and PyO3. //! The required either version may vary based on the version of PyO3. //! //! # Example: Convert a `int | str` to `Either`. //! //! ```rust //! use either::Either; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! Python::initialize(); //! Python::attach(|py| { //! // Create a string and an int in Python. //! let py_str = "crab".into_pyobject(py)?; //! let py_int = 42i32.into_pyobject(py)?; //! // Now convert it to an Either. //! let either_str: Either = py_str.extract()?; //! let either_int: Either = py_int.extract()?; //! Ok(()) //! }) //! } //! ``` //! //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ exceptions::PyTypeError, Borrowed, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, Python, }; use either::Either; #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'py, L, R> IntoPyObject<'py> for Either where L: IntoPyObject<'py>, R: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { match self { Either::Left(l) => l.into_bound_py_any(py), Either::Right(r) => r.into_bound_py_any(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'a, 'py, L, R> IntoPyObject<'py> for &'a Either where &'a L: IntoPyObject<'py>, &'a R: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { match self { Either::Left(l) => l.into_bound_py_any(py), Either::Right(r) => r.into_bound_py_any(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'a, 'py, L, R> FromPyObject<'a, 'py> for Either where L: FromPyObject<'a, 'py>, R: FromPyObject<'a, 'py>, { type Error = PyErr; #[inline] fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { if let Ok(l) = obj.extract::() { Ok(Either::Left(l)) } else if let Ok(r) = obj.extract::() { Ok(Either::Right(r)) } else { // TODO: it might be nice to use the `type_input()` name here once `type_input` // is not experimental, rather than the Rust type names. let err_msg = format!( "failed to convert the value to 'Union[{}, {}]'", std::any::type_name::(), std::any::type_name::() ); Err(PyTypeError::new_err(err_msg)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::union_of(&[L::type_input(), R::type_input()]) } } #[cfg(test)] mod tests { use std::borrow::Cow; use crate::exceptions::PyTypeError; use crate::{IntoPyObject, Python}; use crate::types::PyAnyMethods; use either::Either; #[test] fn test_either_conversion() { type E = Either; type E1 = Either; type E2 = Either; Python::attach(|py| { let l = E::Left(42); let obj_l = (&l).into_pyobject(py).unwrap(); assert_eq!(obj_l.extract::().unwrap(), 42); assert_eq!(obj_l.extract::().unwrap(), l); let r = E::Right("foo".to_owned()); let obj_r = (&r).into_pyobject(py).unwrap(); assert_eq!(obj_r.extract::>().unwrap(), "foo"); assert_eq!(obj_r.extract::().unwrap(), r); let obj_s = "foo".into_pyobject(py).unwrap(); let err = obj_s.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); assert_eq!( err.to_string(), "TypeError: failed to convert the value to 'Union[i32, f32]'" ); let obj_i = 42i32.into_pyobject(py).unwrap(); assert_eq!(obj_i.extract::().unwrap(), E1::Left(42)); assert_eq!(obj_i.extract::().unwrap(), E2::Left(42.0)); let obj_f = 42.0f64.into_pyobject(py).unwrap(); assert_eq!(obj_f.extract::().unwrap(), E1::Right(42.0)); assert_eq!(obj_f.extract::().unwrap(), E2::Left(42.0)); }); } } pyo3-0.27.2/src/conversions/eyre.rs000064400000000000000000000155271046102023000152710ustar 00000000000000#![cfg(feature = "eyre")] //! A conversion from //! [eyre](https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications.")’s //! [`Report`] type to [`PyErr`]. //! //! Use of an error handling library like [eyre] is common in application code and when you just //! want error handling to be easy. If you are writing a library or you need more control over your //! errors you might want to design your own error type instead. //! //! When the inner error is a [`PyErr`] without source, it will be extracted out. //! Otherwise a Python [`RuntimeError`] will be created. //! You might find that you need to map the error from your Rust code into another Python exception. //! See [`PyErr::new`] for more information about that. //! //! For information about error handling in general, see the [Error handling] chapter of the Rust //! book. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! eyre = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"eyre\"] }")] //! ``` //! //! Note that you must use compatible versions of eyre and PyO3. //! The required eyre version may vary based on the version of PyO3. //! //! # Example: Propagating a `PyErr` into [`eyre::Report`] //! //! ```rust //! use pyo3::prelude::*; //! use std::path::PathBuf; //! //! // A wrapper around a Rust function. //! // The pyfunction macro performs the conversion to a PyErr //! #[pyfunction] //! fn py_open(filename: PathBuf) -> eyre::Result> { //! let data = std::fs::read(filename)?; //! Ok(data) //! } //! //! fn main() { //! let error = Python::attach(|py| -> PyResult> { //! let fun = wrap_pyfunction!(py_open, py)?; //! let text = fun.call1(("foo.txt",))?.extract::>()?; //! Ok(text) //! }).unwrap_err(); //! //! println!("{}", error); //! } //! ``` //! //! # Example: Using `eyre` in general //! //! Note that you don't need this feature to convert a [`PyErr`] into an [`eyre::Report`], because //! it can already convert anything that implements [`Error`](std::error::Error): //! //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::PyBytes; //! //! // An example function that must handle multiple error types. //! // //! // To do this you usually need to design your own error type or use //! // `Box`. `eyre` is a convenient alternative for this. //! pub fn decompress(bytes: &[u8]) -> eyre::Result { //! // An arbitrary example of a Python api you //! // could call inside an application... //! // This might return a `PyErr`. //! let res = Python::attach(|py| { //! let zlib = PyModule::import(py, "zlib")?; //! let decompress = zlib.getattr("decompress")?; //! let bytes = PyBytes::new(py, bytes); //! let value = decompress.call1((bytes,))?; //! value.extract::>() //! })?; //! //! // This might be a `FromUtf8Error`. //! let text = String::from_utf8(res)?; //! //! Ok(text) //! } //! //! fn main() -> eyre::Result<()> { //! let bytes: &[u8] = b"x\x9c\x8b\xcc/U(\xce\xc8/\xcdIQ((\xcaOJL\xca\xa9T\ //! (-NU(\xc9HU\xc8\xc9LJ\xcbI,IUH.\x02\x91\x99y\xc5%\ //! \xa9\x89)z\x00\xf2\x15\x12\xfe"; //! let text = decompress(bytes)?; //! //! println!("The text is \"{}\"", text); //! # assert_eq!(text, "You should probably use the libflate crate instead."); //! Ok(()) //! } //! ``` //! //! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications." //! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError "Built-in Exceptions — Python documentation" //! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html "Recoverable Errors with Result - The Rust Programming Language" use crate::exceptions::PyRuntimeError; use crate::PyErr; use eyre::Report; /// Converts [`eyre::Report`] to a [`PyErr`] containing a [`PyRuntimeError`]. /// /// If you want to raise a different Python exception you will have to do so manually. See /// [`PyErr::new`] for more information about that. impl From for PyErr { fn from(mut error: Report) -> Self { // Errors containing a PyErr without chain or context are returned as the underlying error if error.source().is_none() { error = match error.downcast::() { Ok(py_err) => return py_err, Err(error) => error, }; } PyRuntimeError::new_err(format!("{error:?}")) } } #[cfg(test)] mod tests { use crate::exceptions::{PyRuntimeError, PyValueError}; use crate::types::IntoPyDict; use crate::{ffi, prelude::*}; use eyre::{bail, eyre, Report, Result, WrapErr}; fn f() -> Result<()> { use std::io; bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); } fn g() -> Result<()> { f().wrap_err("f failed") } fn h() -> Result<()> { g().wrap_err("g failed") } #[test] fn test_pyo3_exception_contents() { let err = h().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::attach(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } fn k() -> Result<()> { Err(eyre!("Some sort of error")) } #[test] fn test_pyo3_exception_contents2() { let err = k().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::attach(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } #[test] fn test_pyo3_unwrap_simple_err() { let origin_exc = PyValueError::new_err("Value Error"); let report: Report = origin_exc.into(); let converted: PyErr = report.into(); assert!(Python::attach( |py| converted.is_instance_of::(py) )) } #[test] fn test_pyo3_unwrap_complex_err() { let origin_exc = PyValueError::new_err("Value Error"); let mut report: Report = origin_exc.into(); report = report.wrap_err("Wrapped"); let converted: PyErr = report.into(); assert!(Python::attach( |py| converted.is_instance_of::(py) )) } } pyo3-0.27.2/src/conversions/hashbrown.rs000064400000000000000000000144331046102023000163130ustar 00000000000000#![cfg(feature = "hashbrown")] //! Conversions to and from [hashbrown](https://docs.rs/hashbrown/)’s //! `HashMap` and `HashSet`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! hashbrown = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"hashbrown\"] }")] //! ``` //! //! Note that you must use compatible versions of hashbrown and PyO3. //! The required hashbrown version may vary based on the version of PyO3. use crate::{ conversion::{FromPyObjectOwned, IntoPyObject}, types::{ any::PyAnyMethods, dict::PyDictMethods, frozenset::PyFrozenSetMethods, set::{try_new_from_iter, PySetMethods}, PyDict, PyFrozenSet, PySet, }, Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, Python, }; use std::{cmp, hash}; impl<'py, K, V, H> IntoPyObject<'py> for hashbrown::HashMap where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a hashbrown::HashMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'py, K, V, S> FromPyObject<'_, 'py> for hashbrown::HashMap where K: FromPyObjectOwned<'py> + cmp::Eq + hash::Hash, V: FromPyObjectOwned<'py>, S: hash::BuildHasher + Default, { type Error = PyErr; fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result { let dict = ob.cast::()?; let mut ret = hashbrown::HashMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict.iter() { ret.insert( k.extract().map_err(Into::into)?, v.extract().map_err(Into::into)?, ); } Ok(ret) } } impl<'py, K, H> IntoPyObject<'py> for hashbrown::HashSet where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, H: hash::BuildHasher, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } } impl<'a, 'py, K, H> IntoPyObject<'py> for &'a hashbrown::HashSet where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, H: hash::BuildHasher, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } } impl<'py, K, S> FromPyObject<'_, 'py> for hashbrown::HashSet where K: FromPyObjectOwned<'py> + cmp::Eq + hash::Hash, S: hash::BuildHasher + Default, { type Error = PyErr; fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { match ob.cast::() { Ok(set) => set .iter() .map(|any| any.extract().map_err(Into::into)) .collect(), Err(err) => { if let Ok(frozen_set) = ob.cast::() { frozen_set .iter() .map(|any| any.extract().map_err(Into::into)) .collect() } else { Err(PyErr::from(err)) } } } } } #[cfg(test)] mod tests { use super::*; use crate::types::IntoPyDict; use std::collections::hash_map::RandomState; #[test] fn test_hashbrown_hashmap_into_pyobject() { Python::attach(|py| { let mut map = hashbrown::HashMap::::with_hasher(RandomState::new()); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert_eq!(py_map.len(), 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_hashbrown_hashmap_into_dict() { Python::attach(|py| { let mut map = hashbrown::HashMap::::with_hasher(RandomState::new()); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_extract_hashbrown_hashset() { Python::attach(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_hashbrown_hashset_into_pyobject() { Python::attach(|py| { let hs: hashbrown::HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso = hs.clone().into_pyobject(py).unwrap(); assert_eq!(hs, hso.extract().unwrap()); }); } } pyo3-0.27.2/src/conversions/indexmap.rs000064400000000000000000000154341046102023000161270ustar 00000000000000#![cfg(feature = "indexmap")] //! Conversions to and from [indexmap](https://docs.rs/indexmap/)’s //! `IndexMap`. //! //! [`indexmap::IndexMap`] is a hash table that is closely compatible with the standard [`std::collections::HashMap`], //! with the difference that it preserves the insertion order when iterating over keys. It was inspired //! by Python's 3.6+ dict implementation. //! //! Dictionary order is guaranteed to be insertion order in Python, hence IndexMap is a good candidate //! for maintaining an equivalent behaviour in Rust. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! indexmap = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"indexmap\"] }")] //! ``` //! //! Note that you must use compatible versions of indexmap and PyO3. //! The required indexmap version may vary based on the version of PyO3. //! //! # Examples //! //! Using [indexmap](https://docs.rs/indexmap) to return a dictionary with some statistics //! about a list of numbers. Because of the insertion order guarantees, the Python code will //! always print the same result, matching users' expectations about Python's dict. //! ```rust //! use indexmap::{indexmap, IndexMap}; //! use pyo3::prelude::*; //! //! fn median(data: &Vec) -> f32 { //! let sorted_data = data.clone().sort(); //! let mid = data.len() / 2; //! if data.len() % 2 == 0 { //! data[mid] as f32 //! } //! else { //! (data[mid] + data[mid - 1]) as f32 / 2.0 //! } //! } //! //! fn mean(data: &Vec) -> f32 { //! data.iter().sum::() as f32 / data.len() as f32 //! } //! fn mode(data: &Vec) -> f32 { //! let mut frequency = IndexMap::new(); // we can use IndexMap as any hash table //! //! for &element in data { //! *frequency.entry(element).or_insert(0) += 1; //! } //! //! frequency //! .iter() //! .max_by(|a, b| a.1.cmp(&b.1)) //! .map(|(k, _v)| *k) //! .unwrap() as f32 //! } //! //! #[pyfunction] //! fn calculate_statistics(data: Vec) -> IndexMap<&'static str, f32> { //! indexmap! { //! "median" => median(&data), //! "mean" => mean(&data), //! "mode" => mode(&data), //! } //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(calculate_statistics, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import calculate_statistics //! //! data = [1, 1, 1, 3, 4, 5] //! print(calculate_statistics(data)) //! # always prints {"median": 2.0, "mean": 2.5, "mode": 1.0} in the same order //! # if another hash table was used, the order could be random //! ``` use crate::conversion::{FromPyObjectOwned, IntoPyObject}; use crate::types::*; use crate::{Borrowed, Bound, FromPyObject, PyErr, Python}; use std::{cmp, hash}; impl<'py, K, V, H> IntoPyObject<'py> for indexmap::IndexMap where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a indexmap::IndexMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'py, K, V, S> FromPyObject<'_, 'py> for indexmap::IndexMap where K: FromPyObjectOwned<'py> + cmp::Eq + hash::Hash, V: FromPyObjectOwned<'py>, S: hash::BuildHasher + Default, { type Error = PyErr; fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result { let dict = ob.cast::()?; let mut ret = indexmap::IndexMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict.iter() { ret.insert( k.extract().map_err(Into::into)?, v.extract().map_err(Into::into)?, ); } Ok(ret) } } #[cfg(test)] mod test_indexmap { use crate::types::*; use crate::{IntoPyObject, Python}; #[test] fn test_indexmap_indexmap_into_pyobject() { Python::attach(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert_eq!(py_map.len(), 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!( map, py_map.extract::>().unwrap() ); }); } #[test] fn test_indexmap_indexmap_into_dict() { Python::attach(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_indexmap_indexmap_insertion_order_round_trip() { Python::attach(|py| { let n = 20; let mut map = indexmap::IndexMap::::new(); for i in 1..=n { if i % 2 == 1 { map.insert(i, i); } else { map.insert(n - i, i); } } let py_map = (&map).into_py_dict(py).unwrap(); let trip_map = py_map.extract::>().unwrap(); for (((k1, v1), (k2, v2)), (k3, v3)) in map.iter().zip(py_map.iter()).zip(trip_map.iter()) { let k2 = k2.extract::().unwrap(); let v2 = v2.extract::().unwrap(); assert_eq!((k1, v1), (&k2, &v2)); assert_eq!((k1, v1), (k3, v3)); assert_eq!((&k2, &v2), (k3, v3)); } }); } } pyo3-0.27.2/src/conversions/jiff.rs000064400000000000000000001246221046102023000152400ustar 00000000000000#![cfg(feature = "jiff-02")] //! Conversions to and from [jiff](https://docs.rs/jiff/)’s `Span`, `SignedDuration`, `TimeZone`, //! `Offset`, `Date`, `Time`, `DateTime`, `Zoned`, and `Timestamp`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! jiff = "0.2" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"jiff-02\"] }")] //! ``` //! //! Note that you must use compatible versions of jiff and PyO3. //! The required jiff version may vary based on the version of PyO3. //! //! # Example: Convert a `datetime.datetime` to jiff `Zoned` //! //! ```rust //! # #![cfg_attr(windows, allow(unused_imports))] //! # use jiff_02 as jiff; //! use jiff::{Zoned, SignedDuration, ToSpan}; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! # #[cfg(windows)] //! # fn main() -> () {} //! # #[cfg(not(windows))] //! fn main() -> PyResult<()> { //! Python::initialize(); //! Python::attach(|py| { //! // Build some jiff values //! let jiff_zoned = Zoned::now(); //! let jiff_span = 1.second(); //! // Convert them to Python //! let py_datetime = jiff_zoned.into_pyobject(py)?; //! let py_timedelta = SignedDuration::try_from(jiff_span)?.into_pyobject(py)?; //! // Do an operation in Python //! let py_sum = py_datetime.call_method1("__add__", (py_timedelta,))?; //! // Convert back to Rust //! let jiff_sum: Zoned = py_sum.extract()?; //! println!("Zoned: {}", jiff_sum); //! Ok(()) //! }) //! } //! ``` use crate::exceptions::{PyTypeError, PyValueError}; use crate::pybacked::PyBackedStr; use crate::types::{PyAnyMethods, PyNone}; use crate::types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess}; #[cfg(not(Py_LIMITED_API))] use crate::types::{PyDateAccess, PyDeltaAccess, PyTimeAccess}; use crate::{intern, Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python}; use jiff::civil::{Date, DateTime, ISOWeekDate, Time}; use jiff::tz::{Offset, TimeZone}; use jiff::{SignedDuration, Span, Timestamp, Zoned}; #[cfg(feature = "jiff-02")] use jiff_02 as jiff; fn datetime_to_pydatetime<'py>( py: Python<'py>, datetime: &DateTime, fold: bool, timezone: Option<&TimeZone>, ) -> PyResult> { PyDateTime::new_with_fold( py, datetime.year().into(), datetime.month().try_into()?, datetime.day().try_into()?, datetime.hour().try_into()?, datetime.minute().try_into()?, datetime.second().try_into()?, (datetime.subsec_nanosecond() / 1000).try_into()?, timezone .map(|tz| tz.into_pyobject(py)) .transpose()? .as_ref(), fold, ) } #[cfg(not(Py_LIMITED_API))] fn pytime_to_time(time: &impl PyTimeAccess) -> PyResult