From e4e7e6e51cae0cac3b422e4267bbf8ce67c6fea7 Mon Sep 17 00:00:00 2001
From: mejrs <>
Date: Wed, 22 Jun 2022 01:47:40 +0200
Subject: [PATCH] Add frozen documentation
---
.../docs => guide}/pyclass_parameters.md | 9 +++++++++
guide/src/class.md | 2 +-
pyo3-macros/src/lib.rs | 15 ---------------
src/lib.rs | 13 ++++++++++++-
src/pyclass.rs | 19 +++++++++++--------
5 files changed, 33 insertions(+), 25 deletions(-)
rename {pyo3-macros/docs => guide}/pyclass_parameters.md (79%)
diff --git a/pyo3-macros/docs/pyclass_parameters.md b/guide/pyclass_parameters.md
similarity index 79%
rename from pyo3-macros/docs/pyclass_parameters.md
rename to guide/pyclass_parameters.md
index 145d5ac8..87d81c94 100644
--- a/pyo3-macros/docs/pyclass_parameters.md
+++ b/guide/pyclass_parameters.md
@@ -6,6 +6,7 @@
| `dict` | Gives instances of this class an empty `__dict__` to store custom attributes. |
| `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. |
+| `frozen` | Declares that your pyclass is immutable. It removes the borrowchecker overhead when retrieving a shared reference to the Rust struct, but disables the ability to get a mutable reference. |
| `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. |
@@ -27,3 +28,11 @@ struct MyClass { }
#[pyo3(name = "SomeName", subclass)]
struct MyClass { }
```
+
+[params-1]: ../prelude/struct.PyAny.html
+[params-2]: https://en.wikipedia.org/wiki/Free_list
+[params-3]: std::marker::Send
+[params-4]: std::rc::Rc
+[params-5]: std::sync::Arc
+[params-6]: https://docs.python.org/3/library/weakref.html
+[params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types
\ No newline at end of file
diff --git a/guide/src/class.md b/guide/src/class.md
index 7124114a..cff3c51e 100644
--- a/guide/src/class.md
+++ b/guide/src/class.md
@@ -195,7 +195,7 @@ Python::with_gil(|py|{
## Customizing the class
-{{#include ../../pyo3-macros/docs/pyclass_parameters.md}}
+{{#include ../pyclass_parameters.md}}
[params-1]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.PyAny.html
[params-2]: https://en.wikipedia.org/wiki/Free_list
diff --git a/pyo3-macros/src/lib.rs b/pyo3-macros/src/lib.rs
index 65f85b55..33adcf86 100644
--- a/pyo3-macros/src/lib.rs
+++ b/pyo3-macros/src/lib.rs
@@ -79,21 +79,6 @@ pub fn pyproto(_: TokenStream, input: TokenStream) -> TokenStream {
.into()
}
-/// A proc macro used to expose Rust structs and fieldless enums as Python objects.
-///
-#[cfg_attr(docsrs, cfg_attr(docsrs, doc = include_str!("../docs/pyclass_parameters.md")))]
-///
-/// For more on creating Python classes,
-/// see the [class section of the guide][1].
-///
-/// [1]: https://pyo3.rs/latest/class.html
-/// [params-1]: ../prelude/struct.PyAny.html
-/// [params-2]: https://en.wikipedia.org/wiki/Free_list
-/// [params-3]: std::marker::Send
-/// [params-4]: std::rc::Rc
-/// [params-5]: std::sync::Arc
-/// [params-6]: https://docs.python.org/3/library/weakref.html
-/// [params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types
#[proc_macro_attribute]
pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream {
use syn::Item;
diff --git a/src/lib.rs b/src/lib.rs
index 8f7741ff..ca87bf2c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -405,7 +405,18 @@ pub mod proc_macro {
#[cfg(all(feature = "macros", feature = "pyproto"))]
pub use pyo3_macros::pyproto;
#[cfg(feature = "macros")]
-pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject};
+pub use pyo3_macros::{pyfunction, pymethods, pymodule, FromPyObject};
+
+/// A proc macro used to expose Rust structs and fieldless enums as Python objects.
+///
+#[cfg_attr(docsrs, cfg_attr(docsrs, doc = include_str!("../guide/pyclass_parameters.md")))]
+///
+/// For more on creating Python classes,
+/// see the [class section of the guide][1].
+///
+/// [1]: https://pyo3.rs/latest/class.html
+#[cfg(feature = "macros")]
+pub use pyo3_macros::pyclass;
#[cfg(feature = "macros")]
#[macro_use]
diff --git a/src/pyclass.rs b/src/pyclass.rs
index f7bbb0cd..4272471e 100644
--- a/src/pyclass.rs
+++ b/src/pyclass.rs
@@ -16,15 +16,16 @@ use std::{
ptr,
};
-/// If `PyClass` is implemented for a Rust type `T`, then we can use `T` in the Python
-/// world, via `PyCell`.
+/// Types that can be used as Python classes.
///
-/// The `#[pyclass]` attribute automatically implements this trait for your Rust struct,
-/// so you normally don't have to use this trait directly.
+/// The `#[pyclass]` attribute implements this trait for your Rust struct -
+/// you shouldn't implement this trait directly.
pub trait PyClass:
PyTypeInfo> + PyClassImpl>
{
- /// Frozen or not
+ /// Whether the pyclass is frozen.
+ ///
+ /// This can be enabled via `#[pyclass(frozen)]`.
type Frozen: Frozen;
}
@@ -574,10 +575,11 @@ pub(crate) unsafe extern "C" fn no_constructor_defined(
})
}
-/// A mechanism to have associated True / False values in the absence of
-/// associated const equality.
+/// A workaround for [associated const equality](https://github.com/rust-lang/rust/issues/92827).
+///
+/// This serves to have True / False values in the [`PyClass`] trait's `Frozen` type.
+#[doc(hidden)]
pub mod boolean_struct {
-
pub(crate) mod private {
use super::*;
@@ -593,6 +595,7 @@ pub mod boolean_struct {
}
/// A trait which is used to describe whether a `#[pyclass]` is frozen.
+#[doc(hidden)]
pub trait Frozen: boolean_struct::private::Boolean {}
impl Frozen for boolean_struct::True {}