Skip to content

Commit ebf95bd

Browse files
authored
move PyTypeInfo::NAME and ::MODULE into #[pyclass] machinery (#5579)
* move `PyTypeInfo::NAME` and `::MODULE` into `#[pyclass]` machinery * newsfragments * fixup guide code block
1 parent d2d36b4 commit ebf95bd

File tree

13 files changed

+59
-21
lines changed

13 files changed

+59
-21
lines changed

guide/src/class.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,17 +1409,19 @@ unsafe impl pyo3::type_object::PyTypeInfo for MyClass {
14091409
.unwrap_or_else(|e| pyo3::impl_::pyclass::type_object_init_failed(
14101410
py,
14111411
e,
1412-
<Self as pyo3::type_object::PyTypeInfo>::NAME
1412+
<Self as pyo3::PyClass>::NAME
14131413
))
14141414
.as_type_ptr()
14151415
}
14161416
}
14171417

14181418
impl pyo3::PyClass for MyClass {
1419+
const NAME: &str = "MyClass";
14191420
type Frozen = pyo3::pyclass::boolean_struct::False;
14201421
}
14211422

14221423
impl pyo3::impl_::pyclass::PyClassImpl for MyClass {
1424+
const MODULE: Option<&str> = None;
14231425
const IS_BASETYPE: bool = false;
14241426
const IS_SUBCLASS: bool = false;
14251427
const IS_MAPPING: bool = false;

newsfragments/5579.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `PyClass::NAME`.

newsfragments/5579.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecate `PyTypeInfo::NAME` and `PyTypeInfo::MODULE`.

pyo3-macros-backend/src/method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ impl<'a> FnSpec<'a> {
709709
};
710710
let python_name = &self.python_name;
711711
let qualname_prefix = match cls {
712-
Some(cls) => quote!(Some(<#cls as #pyo3_path::PyTypeInfo>::NAME)),
712+
Some(cls) => quote!(Some(<#cls as #pyo3_path::PyClass>::NAME)),
713713
None => quote!(None),
714714
};
715715
let arg_names = (0..args.len())

pyo3-macros-backend/src/params.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub fn impl_arg_params(
131131
};
132132

133133
let cls_name = if let Some(cls) = self_ {
134-
quote! { ::std::option::Option::Some(<#cls as #pyo3_path::type_object::PyTypeInfo>::NAME) }
134+
quote! { ::std::option::Option::Some(<#cls as #pyo3_path::PyClass>::NAME) }
135135
} else {
136136
quote! { ::std::option::Option::None }
137137
};

pyo3-macros-backend/src/pyclass.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,13 +1951,6 @@ fn descriptors_to_items(
19511951

19521952
fn impl_pytypeinfo(cls: &syn::Ident, attr: &PyClassArgs, ctx: &Ctx) -> TokenStream {
19531953
let Ctx { pyo3_path, .. } = ctx;
1954-
let cls_name = get_class_python_name(cls, attr).to_string();
1955-
1956-
let module = if let Some(ModuleAttribute { value, .. }) = &attr.options.module {
1957-
quote! { ::core::option::Option::Some(#value) }
1958-
} else {
1959-
quote! { ::core::option::Option::None }
1960-
};
19611954

19621955
#[cfg(feature = "experimental-inspect")]
19631956
let type_hint = {
@@ -1966,11 +1959,14 @@ fn impl_pytypeinfo(cls: &syn::Ident, attr: &PyClassArgs, ctx: &Ctx) -> TokenStre
19661959
};
19671960
#[cfg(not(feature = "experimental-inspect"))]
19681961
let type_hint = quote! {};
1962+
#[cfg(not(feature = "experimental-inspect"))]
1963+
let _ = attr;
19691964

19701965
quote! {
19711966
unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls {
1972-
const NAME: &'static str = #cls_name;
1973-
const MODULE: ::std::option::Option<&'static str> = #module;
1967+
1968+
const NAME: &str = <Self as #pyo3_path::PyClass>::NAME;
1969+
const MODULE: ::std::option::Option<&str> = <Self as #pyo3_path::impl_::pyclass::PyClassImpl>::MODULE;
19741970

19751971
#type_hint
19761972

@@ -1982,7 +1978,7 @@ fn impl_pytypeinfo(cls: &syn::Ident, attr: &PyClassArgs, ctx: &Ctx) -> TokenStre
19821978
.unwrap_or_else(|e| #pyo3_path::impl_::pyclass::type_object_init_failed(
19831979
py,
19841980
e,
1985-
<Self as #pyo3_path::type_object::PyTypeInfo>::NAME
1981+
<Self as #pyo3_path::PyClass>::NAME
19861982
))
19871983
.as_type_ptr()
19881984
}
@@ -2328,6 +2324,8 @@ impl<'a> PyClassImplsBuilder<'a> {
23282324
let Ctx { pyo3_path, .. } = ctx;
23292325
let cls = self.cls;
23302326

2327+
let cls_name = get_class_python_name(cls, self.attr).to_string();
2328+
23312329
let frozen = if self.attr.options.frozen.is_some() {
23322330
quote! { #pyo3_path::pyclass::boolean_struct::True }
23332331
} else {
@@ -2336,6 +2334,7 @@ impl<'a> PyClassImplsBuilder<'a> {
23362334

23372335
quote! {
23382336
impl #pyo3_path::PyClass for #cls {
2337+
const NAME: &str = #cls_name;
23392338
type Frozen = #frozen;
23402339
}
23412340
}
@@ -2378,6 +2377,13 @@ impl<'a> PyClassImplsBuilder<'a> {
23782377
.doc
23792378
.as_ref()
23802379
.map_or(c"".to_token_stream(), PythonDoc::to_token_stream);
2380+
2381+
let module = if let Some(ModuleAttribute { value, .. }) = &self.attr.options.module {
2382+
quote! { ::core::option::Option::Some(#value) }
2383+
} else {
2384+
quote! { ::core::option::Option::None }
2385+
};
2386+
23812387
let is_basetype = self.attr.options.subclass.is_some();
23822388
let base = match &self.attr.options.extends {
23832389
Some(extends_attr) => extends_attr.value.clone(),
@@ -2562,6 +2568,7 @@ impl<'a> PyClassImplsBuilder<'a> {
25622568
#pyclass_base_type_impl
25632569

25642570
impl #pyo3_path::impl_::pyclass::PyClassImpl for #cls {
2571+
const MODULE: ::std::option::Option<&str> = #module;
25652572
const IS_BASETYPE: bool = #is_basetype;
25662573
const IS_SUBCLASS: bool = #is_subclass;
25672574
const IS_MAPPING: bool = #is_mapping;

src/impl_/pyclass.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ unsafe impl Sync for PyClassItems {}
157157
/// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail
158158
/// and may be changed at any time.
159159
pub trait PyClassImpl: Sized + 'static {
160+
/// Module which the class will be associated with.
161+
///
162+
/// (Currently defaults to `builtins` if unset, this will likely be improved in the future, it
163+
/// may also be removed when passing module objects in class init.)
164+
const MODULE: Option<&'static str>;
165+
160166
/// #[pyclass(subclass)]
161167
const IS_BASETYPE: bool = false;
162168

src/impl_/pyclass/doc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{ffi::CStr, marker::PhantomData};
22

3-
use crate::{impl_::pyclass::PyClassImpl, PyClass, PyTypeInfo};
3+
use crate::{impl_::pyclass::PyClassImpl, PyClass};
44

55
/// Trait implemented by classes with a known text signature for instantiation.
66
///
@@ -26,7 +26,7 @@ pub struct PyClassDocGenerator<
2626

2727
impl<ClassT: PyClass + PyClassNewTextSignature> PyClassDocGenerator<ClassT, true> {
2828
pub const DOC_PIECES: &'static [&'static [u8]] = &[
29-
<ClassT as PyTypeInfo>::NAME.as_bytes(),
29+
<ClassT as PyClass>::NAME.as_bytes(),
3030
ClassT::TEXT_SIGNATURE.as_bytes(),
3131
b"\n--\n\n",
3232
<ClassT as PyClassImpl>::RAW_DOC.to_bytes_with_nul(),

src/impl_/pyclass/lazy_type_object.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,12 @@ impl<T: PyClass> LazyTypeObject<T> {
6969

7070
#[cold]
7171
fn try_init<'py>(&self, py: Python<'py>) -> PyResult<&Bound<'py, PyType>> {
72-
self.0
73-
.get_or_try_init(py, create_type_object::<T>, T::NAME, T::items_iter())
72+
self.0.get_or_try_init(
73+
py,
74+
create_type_object::<T>,
75+
<T as PyClass>::NAME,
76+
T::items_iter(),
77+
)
7478
}
7579
}
7680

src/pyclass.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ pub use self::guard::{
1818
/// The `#[pyclass]` attribute implements this trait for your Rust struct -
1919
/// you shouldn't implement this trait directly.
2020
pub trait PyClass: PyTypeInfo + PyClassImpl {
21+
/// Name of the class.
22+
///
23+
/// This can be set via `#[pyclass(name = "...")]`, otherwise it defaults to the Rust type name.
24+
const NAME: &'static str;
25+
2126
/// Whether the pyclass is frozen.
2227
///
2328
/// This can be enabled via `#[pyclass(frozen)]`.

0 commit comments

Comments
 (0)