Skip to content

Commit a21ad9e

Browse files
authored
Merge pull request #2804 from youknowone/static-metaclass
metaclass support for #[pyclass] macro
2 parents 634a6c2 + 3c649f4 commit a21ad9e

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

derive/src/pyclass.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ fn generate_class_def(
142142
name: &str,
143143
module_name: Option<&str>,
144144
base: Option<String>,
145+
metaclass: Option<String>,
145146
attrs: &[Attribute],
146147
) -> std::result::Result<TokenStream, Diagnostic> {
147148
let doc = if let Some(doc) = attrs.doc() {
@@ -175,20 +176,31 @@ fn generate_class_def(
175176
)
176177
.into());
177178
}
178-
let base = base.map(|name| Ident::new(&name, ident.span()));
179-
180179
let base_class = if is_pystruct {
181180
quote! {
182181
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
183182
use rustpython_vm::StaticType;
184183
rustpython_vm::builtins::PyTuple::static_type()
185184
}
186185
}
187-
} else if let Some(base) = base {
186+
} else if let Some(typ) = base {
187+
let typ = Ident::new(&typ, ident.span());
188188
quote! {
189189
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
190190
use rustpython_vm::StaticType;
191-
#base::static_type()
191+
#typ::static_type()
192+
}
193+
}
194+
} else {
195+
quote!()
196+
};
197+
198+
let meta_class = if let Some(typ) = metaclass {
199+
let typ = Ident::new(&typ, ident.span());
200+
quote! {
201+
fn static_metaclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
202+
use rustpython_vm::StaticType;
203+
#typ::static_type()
192204
}
193205
}
194206
} else {
@@ -211,6 +223,8 @@ fn generate_class_def(
211223
&CELL
212224
}
213225

226+
#meta_class
227+
214228
#base_class
215229
}
216230
};
@@ -227,7 +241,15 @@ pub(crate) fn impl_pyclass(
227241
let class_name = class_meta.class_name()?;
228242
let module_name = class_meta.module()?;
229243
let base = class_meta.base()?;
230-
let class_def = generate_class_def(ident, &class_name, module_name.as_deref(), base, attrs)?;
244+
let metaclass = class_meta.metaclass()?;
245+
let class_def = generate_class_def(
246+
ident,
247+
&class_name,
248+
module_name.as_deref(),
249+
base,
250+
metaclass,
251+
attrs,
252+
)?;
231253

232254
let ret = quote! {
233255
#item

derive/src/util.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl ItemMeta for SimpleItemMeta {
233233
pub(crate) struct ClassItemMeta(ItemMetaInner);
234234

235235
impl ItemMeta for ClassItemMeta {
236-
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name", "base"];
236+
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name", "base", "metaclass"];
237237

238238
fn from_inner(inner: ItemMetaInner) -> Self {
239239
Self(inner)
@@ -272,6 +272,10 @@ impl ClassItemMeta {
272272
self.inner()._optional_str("base")
273273
}
274274

275+
pub fn metaclass(&self) -> Result<Option<String>> {
276+
self.inner()._optional_str("metaclass")
277+
}
278+
275279
pub fn module(&self) -> Result<Option<String>> {
276280
const KEY: &str = "module";
277281
let inner = self.inner();

0 commit comments

Comments
 (0)