(
zelf: &Py<Self>,
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
)
| 477 | |
| 478 | impl SetAttr for PyCUnionType { |
| 479 | fn setattro( |
| 480 | zelf: &Py<Self>, |
| 481 | attr_name: &Py<PyStr>, |
| 482 | value: PySetterValue, |
| 483 | vm: &VirtualMachine, |
| 484 | ) -> PyResult<()> { |
| 485 | let pytype: &Py<PyType> = zelf.to_base(); |
| 486 | let attr_name_interned = vm.ctx.intern_str(attr_name.as_wtf8()); |
| 487 | |
| 488 | // 1. First, do PyType's setattro (PyType_Type.tp_setattro first) |
| 489 | // Check for data descriptor first |
| 490 | if let Some(attr) = pytype.get_class_attr(attr_name_interned) { |
| 491 | let descr_set = attr.class().slots.descr_set.load(); |
| 492 | if let Some(descriptor) = descr_set { |
| 493 | descriptor(&attr, pytype.to_owned().into(), value.clone(), vm)?; |
| 494 | // After successful setattro, check if _fields_ and call process_fields |
| 495 | if attr_name.as_bytes() == b"_fields_" |
| 496 | && let PySetterValue::Assign(fields_value) = value |
| 497 | { |
| 498 | PyCUnionType::process_fields(pytype, fields_value, vm)?; |
| 499 | } |
| 500 | return Ok(()); |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | // 2. If _fields_, call process_fields (which checks FINAL internally) |
| 505 | // Check BEFORE writing to dict to avoid storing _fields_ when FINAL |
| 506 | if attr_name.as_bytes() == b"_fields_" |
| 507 | && let PySetterValue::Assign(ref fields_value) = value |
| 508 | { |
| 509 | PyCUnionType::process_fields(pytype, fields_value.clone(), vm)?; |
| 510 | } |
| 511 | |
| 512 | // Store in type's attributes dict |
| 513 | match &value { |
| 514 | PySetterValue::Assign(v) => { |
| 515 | pytype |
| 516 | .attributes |
| 517 | .write() |
| 518 | .insert(attr_name_interned, v.clone()); |
| 519 | } |
| 520 | PySetterValue::Delete => { |
| 521 | let prev = pytype.attributes.write().shift_remove(attr_name_interned); |
| 522 | if prev.is_none() { |
| 523 | return Err(vm.new_attribute_error(format!( |
| 524 | "type object '{}' has no attribute '{}'", |
| 525 | pytype.name(), |
| 526 | attr_name.as_wtf8(), |
| 527 | ))); |
| 528 | } |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | Ok(()) |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | /// PyCUnion - base class for Union |
nothing calls this directly
no test coverage detected