MCPcopy Index your code
hub / github.com/RustPython/RustPython / impl_pyclass

Function impl_pyclass

crates/derive-impl/src/pyclass.rs:548–713  ·  view source on GitHub ↗
(attr: PunctuatedNestedMeta, item: Item)

Source from the content-addressed store, hash-verified

546}
547
548pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result<TokenStream> {
549 if matches!(item, syn::Item::Use(_)) {
550 return Ok(quote!(#item));
551 }
552 let (ident, attrs) = pyclass_ident_and_attrs(&item)?;
553 let fake_ident = Ident::new("pyclass", item.span());
554 let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?;
555 let class_name = class_meta.class_name()?;
556 let module_name = class_meta.module()?;
557 let base = class_meta.base()?;
558 let metaclass = class_meta.metaclass()?;
559 let unhashable = class_meta.unhashable()?;
560
561 // Validate that if base is specified, the first field must be of the base type
562 if let Some(ref base_path) = base {
563 validate_base_field(&item, base_path)?;
564 }
565
566 let class_def = generate_class_def(
567 ident,
568 &class_name,
569 module_name.as_deref(),
570 base.clone(),
571 metaclass,
572 unhashable,
573 attrs,
574 )?;
575
576 const ALLOWED_TRAVERSE_OPTS: &[&str] = &["manual"];
577 // Generate MaybeTraverse impl with both traverse and clear support
578 //
579 // For traverse:
580 // 1. no `traverse` at all: HAS_TRAVERSE = false, try_traverse does nothing
581 // 2. `traverse = "manual"`: HAS_TRAVERSE = true, but no #[derive(Traverse)]
582 // 3. `traverse`: HAS_TRAVERSE = true, and #[derive(Traverse)]
583 //
584 // For clear (tp_clear):
585 // 1. no `clear`: HAS_CLEAR = HAS_TRAVERSE (default: same as traverse)
586 // 2. `clear` or `clear = true`: HAS_CLEAR = true, try_clear calls Traverse::clear
587 // 3. `clear = false`: HAS_CLEAR = false (rare: traverse without clear)
588 let has_traverse = class_meta.inner()._has_key("traverse")?;
589 let has_clear = if class_meta.inner()._has_key("clear")? {
590 // If clear attribute is present, use its value
591 class_meta.inner()._bool("clear")?
592 } else {
593 // If clear attribute is absent, default to same as traverse
594 has_traverse
595 };
596
597 let derive_trace = if has_traverse {
598 // _optional_str returns Err when key exists without value (e.g., `traverse` vs `traverse = "manual"`)
599 // We want to derive Traverse in that case, so we handle Err as Ok(None)
600 let value = class_meta.inner()._optional_str("traverse").ok().flatten();
601 if let Some(s) = value {
602 if !ALLOWED_TRAVERSE_OPTS.contains(&s.as_str()) {
603 bail_span!(
604 item,
605 "traverse attribute only accept {ALLOWED_TRAVERSE_OPTS:?} as value or no value at all",

Callers 1

pyclassFunction · 0.85

Calls 15

pyclass_ident_and_attrsFunction · 0.85
newFunction · 0.85
validate_base_fieldFunction · 0.85
generate_class_defFunction · 0.85
spanMethod · 0.80
baseMethod · 0.80
metaclassMethod · 0.80
unhashableMethod · 0.80
_has_keyMethod · 0.80
_boolMethod · 0.80
okMethod · 0.80
_optional_strMethod · 0.80

Tested by

no test coverage detected