Stabilize declarative modules (#4257)

This commit is contained in:
Alex Gaynor 2024-06-16 21:28:20 -04:00 committed by GitHub
parent baae9291cc
commit ddff8bea25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 4 additions and 36 deletions

View File

@ -75,9 +75,6 @@ experimental-async = ["macros", "pyo3-macros/experimental-async"]
# and IntoPy traits # and IntoPy traits
experimental-inspect = [] experimental-inspect = []
# Enables annotating Rust inline modules with #[pymodule] to build Python modules declaratively
experimental-declarative-modules = ["pyo3-macros/experimental-declarative-modules", "macros"]
# Enables macros: #[pyclass], #[pymodule], #[pyfunction] etc. # Enables macros: #[pyclass], #[pymodule], #[pyfunction] etc.
macros = ["pyo3-macros", "indoc", "unindent"] macros = ["pyo3-macros", "indoc", "unindent"]
@ -125,7 +122,6 @@ full = [
"chrono-tz", "chrono-tz",
"either", "either",
"experimental-async", "experimental-async",
"experimental-declarative-modules",
"experimental-inspect", "experimental-inspect",
"eyre", "eyre",
"hashbrown", "hashbrown",

View File

@ -57,12 +57,6 @@ 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. 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-declarative-modules`
This feature allows to declare Python modules using `#[pymodule] mod my_module { ... }` syntax.
The feature has some unfinished refinements and edge cases. To help finish this off, see [issue #3900](https://github.com/PyO3/pyo3/issues/3900).
### `experimental-inspect` ### `experimental-inspect`
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 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.

View File

@ -106,14 +106,12 @@ submodules by using `from parent_module import child_module`. For more informati
It is not necessary to add `#[pymodule]` on nested modules, which is only required on the top-level module. It is not necessary to add `#[pymodule]` on nested modules, which is only required on the top-level module.
## Declarative modules (experimental) ## Declarative modules
Another syntax based on Rust inline modules is also available to declare modules. Another syntax based on Rust inline modules is also available to declare modules.
The `experimental-declarative-modules` feature must be enabled to use it.
For example: For example:
```rust ```rust
# #[cfg(feature = "experimental-declarative-modules")]
# mod declarative_module_test { # mod declarative_module_test {
use pyo3::prelude::*; use pyo3::prelude::*;
@ -157,7 +155,6 @@ For nested modules, the name of the parent module is automatically added.
In the following example, the `Unit` class will have for `module` `my_extension.submodule` because it is properly nested In the following example, the `Unit` class will have for `module` `my_extension.submodule` because it is properly nested
but the `Ext` class will have for `module` the default `builtins` because it not nested. but the `Ext` class will have for `module` the default `builtins` because it not nested.
```rust ```rust
# #[cfg(feature = "experimental-declarative-modules")]
# mod declarative_module_module_attr_test { # mod declarative_module_module_attr_test {
use pyo3::prelude::*; use pyo3::prelude::*;
@ -184,7 +181,3 @@ mod my_extension {
``` ```
It is possible to customize the `module` value for a `#[pymodule]` with the `#[pyo3(module = "MY_MODULE")]` option. It is possible to customize the `module` value for a `#[pymodule]` with the `#[pyo3(module = "MY_MODULE")]` option.
Some changes are planned to this feature before stabilization, like automatically
filling submodules into `sys.modules` to allow easier imports (see [issue #759](https://github.com/PyO3/pyo3/issues/759)).
Macro names might also change.
See [issue #3900](https://github.com/PyO3/pyo3/issues/3900) to track this feature progress.

View File

@ -0,0 +1 @@
The `experimental-declarative-modules` feature is now stabilized and available by default

View File

@ -16,7 +16,6 @@ proc-macro = true
[features] [features]
multiple-pymethods = [] multiple-pymethods = []
experimental-async = ["pyo3-macros-backend/experimental-async"] experimental-async = ["pyo3-macros-backend/experimental-async"]
experimental-declarative-modules = []
gil-refs = ["pyo3-macros-backend/gil-refs"] gil-refs = ["pyo3-macros-backend/gil-refs"]
[dependencies] [dependencies]

View File

@ -37,14 +37,7 @@ use syn::{parse::Nothing, parse_macro_input, Item};
pub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream { pub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream {
parse_macro_input!(args as Nothing); parse_macro_input!(args as Nothing);
match parse_macro_input!(input as Item) { match parse_macro_input!(input as Item) {
Item::Mod(module) => if cfg!(feature = "experimental-declarative-modules") { Item::Mod(module) => pymodule_module_impl(module),
pymodule_module_impl(module)
} else {
Err(syn::Error::new_spanned(
module,
"#[pymodule] requires the 'experimental-declarative-modules' feature to be used on Rust modules.",
))
},
Item::Fn(function) => pymodule_function_impl(function), Item::Fn(function) => pymodule_function_impl(function),
unsupported => Err(syn::Error::new_spanned( unsupported => Err(syn::Error::new_spanned(
unsupported, unsupported,

View File

@ -13,7 +13,6 @@ fn module_fn_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> {
Ok(()) Ok(())
} }
#[cfg(feature = "experimental-declarative-modules")]
#[pymodule] #[pymodule]
mod module_mod_with_functions { mod module_mod_with_functions {
#[pymodule_export] #[pymodule_export]
@ -27,7 +26,6 @@ fn test_module_append_to_inittab() {
append_to_inittab!(module_fn_with_functions); append_to_inittab!(module_fn_with_functions);
#[cfg(feature = "experimental-declarative-modules")]
append_to_inittab!(module_mod_with_functions); append_to_inittab!(module_mod_with_functions);
Python::with_gil(|py| { Python::with_gil(|py| {
@ -43,7 +41,6 @@ assert module_fn_with_functions.foo() == 123
.unwrap(); .unwrap();
}); });
#[cfg(feature = "experimental-declarative-modules")]
Python::with_gil(|py| { Python::with_gil(|py| {
py.run_bound( py.run_bound(
r#" r#"

View File

@ -52,13 +52,9 @@ fn test_compile_errors() {
t.compile_fail("tests/ui/not_send2.rs"); t.compile_fail("tests/ui/not_send2.rs");
t.compile_fail("tests/ui/get_set_all.rs"); t.compile_fail("tests/ui/get_set_all.rs");
t.compile_fail("tests/ui/traverse.rs"); t.compile_fail("tests/ui/traverse.rs");
#[cfg(feature = "experimental-declarative-modules")]
t.compile_fail("tests/ui/invalid_pymodule_in_root.rs"); t.compile_fail("tests/ui/invalid_pymodule_in_root.rs");
#[cfg(feature = "experimental-declarative-modules")]
t.compile_fail("tests/ui/invalid_pymodule_glob.rs"); t.compile_fail("tests/ui/invalid_pymodule_glob.rs");
#[cfg(feature = "experimental-declarative-modules")]
t.compile_fail("tests/ui/invalid_pymodule_trait.rs"); t.compile_fail("tests/ui/invalid_pymodule_trait.rs");
#[cfg(feature = "experimental-declarative-modules")]
t.compile_fail("tests/ui/invalid_pymodule_two_pymodule_init.rs"); t.compile_fail("tests/ui/invalid_pymodule_two_pymodule_init.rs");
#[cfg(feature = "experimental-async")] #[cfg(feature = "experimental-async")]
#[cfg(any(not(Py_LIMITED_API), Py_3_10))] // to avoid PyFunctionArgument for &str #[cfg(any(not(Py_LIMITED_API), Py_3_10))] // to avoid PyFunctionArgument for &str

View File

@ -1,4 +1,4 @@
#![cfg(feature = "experimental-declarative-modules")] #![cfg(feature = "macros")]
use pyo3::create_exception; use pyo3::create_exception;
use pyo3::exceptions::PyException; use pyo3::exceptions::PyException;

View File

@ -9,7 +9,6 @@ pub fn python_module(_m: &Bound<'_, PyModule>) -> PyResult<()> {
Ok(()) Ok(())
} }
#[cfg(feature = "experimental-declarative-modules")]
/// Some module documentation /// Some module documentation
#[pymodule] #[pymodule]
pub mod declarative_python_module {} pub mod declarative_python_module {}