Phase 2: Set all sys.modules values to None and collect weakrefs. No strong refs are kept — modules are freed when removed from sys.modules (if nothing else references them), allowing GC to collect their cycles.
(&self)
| 1315 | /// No strong refs are kept — modules are freed when removed from sys.modules |
| 1316 | /// (if nothing else references them), allowing GC to collect their cycles. |
| 1317 | fn finalize_remove_modules(&self) -> Vec<(String, PyRef<PyWeak>)> { |
| 1318 | let mut module_weakrefs = Vec::new(); |
| 1319 | |
| 1320 | let Ok(modules) = self.sys_module.get_attr(identifier!(self, modules), self) else { |
| 1321 | return module_weakrefs; |
| 1322 | }; |
| 1323 | let Some(modules_dict) = modules.downcast_ref::<PyDict>() else { |
| 1324 | return module_weakrefs; |
| 1325 | }; |
| 1326 | |
| 1327 | let none = self.ctx.none(); |
| 1328 | let items: Vec<_> = modules_dict.into_iter().collect(); |
| 1329 | |
| 1330 | for (key, value) in items { |
| 1331 | let name = key |
| 1332 | .downcast_ref::<PyUtf8Str>() |
| 1333 | .map(|s| s.as_str().to_owned()) |
| 1334 | .unwrap_or_default(); |
| 1335 | |
| 1336 | // Save weakref to module (for later dict clearing) |
| 1337 | if value.downcast_ref::<PyModule>().is_some() |
| 1338 | && let Ok(weak) = value.downgrade(None, self) |
| 1339 | { |
| 1340 | module_weakrefs.push((name, weak)); |
| 1341 | } |
| 1342 | |
| 1343 | // Set the value to None in sys.modules |
| 1344 | let _ = modules_dict.set_item(&*key, none.clone(), self); |
| 1345 | } |
| 1346 | |
| 1347 | module_weakrefs |
| 1348 | } |
| 1349 | |
| 1350 | /// Phase 3: Clear sys.modules dict. |
| 1351 | fn finalize_clear_modules_dict(&self) { |
no test coverage detected