(
zelf: &Py<Self>,
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
)
| 2457 | |
| 2458 | impl SetAttr for PyType { |
| 2459 | fn setattro( |
| 2460 | zelf: &Py<Self>, |
| 2461 | attr_name: &Py<PyStr>, |
| 2462 | value: PySetterValue, |
| 2463 | vm: &VirtualMachine, |
| 2464 | ) -> PyResult<()> { |
| 2465 | let attr_name = vm.ctx.intern_str(attr_name.as_wtf8()); |
| 2466 | if zelf.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) { |
| 2467 | return Err(vm.new_type_error(format!( |
| 2468 | "cannot set '{}' attribute of immutable type '{}'", |
| 2469 | attr_name, |
| 2470 | zelf.slot_name() |
| 2471 | ))); |
| 2472 | } |
| 2473 | if let Some(attr) = zelf.get_class_attr(attr_name) { |
| 2474 | let descr_set = attr.class().slots.descr_set.load(); |
| 2475 | if let Some(descriptor) = descr_set { |
| 2476 | return descriptor(&attr, zelf.to_owned().into(), value, vm); |
| 2477 | } |
| 2478 | } |
| 2479 | let assign = value.is_assign(); |
| 2480 | |
| 2481 | // Invalidate inline caches before modifying attributes. |
| 2482 | // This ensures other threads see the version invalidation before |
| 2483 | // any attribute changes, preventing use-after-free of cached descriptors. |
| 2484 | zelf.modified(); |
| 2485 | |
| 2486 | if let PySetterValue::Assign(value) = value { |
| 2487 | zelf.attributes.write().insert(attr_name, value); |
| 2488 | } else { |
| 2489 | let prev_value = zelf.attributes.write().shift_remove(attr_name); // TODO: swap_remove applicable? |
| 2490 | if prev_value.is_none() { |
| 2491 | return Err(vm.new_attribute_error(format!( |
| 2492 | "type object '{}' has no attribute '{}'", |
| 2493 | zelf.name(), |
| 2494 | attr_name, |
| 2495 | ))); |
| 2496 | } |
| 2497 | } |
| 2498 | |
| 2499 | if attr_name.as_wtf8().starts_with("__") && attr_name.as_wtf8().ends_with("__") { |
| 2500 | if assign { |
| 2501 | zelf.update_slot::<true>(attr_name, &vm.ctx); |
| 2502 | } else { |
| 2503 | zelf.update_slot::<false>(attr_name, &vm.ctx); |
| 2504 | } |
| 2505 | } |
| 2506 | Ok(()) |
| 2507 | } |
| 2508 | } |
| 2509 | |
| 2510 | impl Callable for PyType { |
nothing calls this directly
no test coverage detected