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

Method setattro

crates/vm/src/stdlib/_ctypes/structure.rs:597–659  ·  view source on GitHub ↗
(
        zelf: &Py<Self>,
        attr_name: &Py<PyStr>,
        value: PySetterValue,
        vm: &VirtualMachine,
    )

Source from the content-addressed store, hash-verified

595
596impl SetAttr for PyCStructType {
597 fn setattro(
598 zelf: &Py<Self>,
599 attr_name: &Py<PyStr>,
600 value: PySetterValue,
601 vm: &VirtualMachine,
602 ) -> PyResult<()> {
603 // Check if _fields_ is being set
604 if attr_name.as_bytes() == b"_fields_" {
605 let pytype: &Py<PyType> = zelf.to_base();
606
607 // Check finalization in separate scope to release read lock before process_fields
608 // This prevents deadlock: process_fields needs write lock on the same RwLock
609 let is_final = {
610 let Some(stg_info) = pytype.get_type_data::<StgInfo>() else {
611 return Err(vm.new_type_error("ctypes state is not initialized"));
612 };
613 stg_info.is_final()
614 }; // Read lock released here
615
616 if is_final {
617 return Err(vm.new_attribute_error("_fields_ is final"));
618 }
619
620 // Process _fields_ and set attribute
621 let PySetterValue::Assign(fields_value) = value else {
622 return Err(vm.new_attribute_error("cannot delete _fields_"));
623 };
624 // Process fields (this will also set DICTFLAG_FINAL)
625 PyCStructType::process_fields(pytype, fields_value.clone(), vm)?;
626 // Set the _fields_ attribute on the type
627 pytype
628 .attributes
629 .write()
630 .insert(vm.ctx.intern_str("_fields_"), fields_value);
631 return Ok(());
632 }
633 // Delegate to PyType's setattro logic for type attributes
634 let attr_name_interned = vm.ctx.intern_str(attr_name.as_wtf8());
635 let pytype: &Py<PyType> = zelf.to_base();
636
637 // Check for data descriptor first
638 if let Some(attr) = pytype.get_class_attr(attr_name_interned) {
639 let descr_set = attr.class().slots.descr_set.load();
640 if let Some(descriptor) = descr_set {
641 return descriptor(&attr, pytype.to_owned().into(), value, vm);
642 }
643 }
644
645 // Store in type's attributes dict
646 if let PySetterValue::Assign(value) = value {
647 pytype.attributes.write().insert(attr_name_interned, value);
648 } else {
649 let prev = pytype.attributes.write().shift_remove(attr_name_interned);
650 if prev.is_none() {
651 return Err(vm.new_attribute_error(format!(
652 "type object '{}' has no attribute '{}'",
653 pytype.name(),
654 attr_name.as_wtf8(),

Callers

nothing calls this directly

Calls 15

descriptorClass · 0.85
is_finalMethod · 0.80
intern_strMethod · 0.80
get_class_attrMethod · 0.80
ErrClass · 0.50
as_bytesMethod · 0.45
to_baseMethod · 0.45
cloneMethod · 0.45
insertMethod · 0.45
writeMethod · 0.45
as_wtf8Method · 0.45
loadMethod · 0.45

Tested by

no test coverage detected