(zelf: PyRef<Self>, args: Self::Args, vm: &VirtualMachine)
| 75 | type Args = FuncArgs; |
| 76 | |
| 77 | fn init(zelf: PyRef<Self>, args: Self::Args, vm: &VirtualMachine) -> PyResult<()> { |
| 78 | // SimpleNamespace accepts 0 or 1 positional argument (a mapping) |
| 79 | if args.args.len() > 1 { |
| 80 | return Err(vm.new_type_error(format!( |
| 81 | "{} expected at most 1 positional argument, got {}", |
| 82 | zelf.class().name(), |
| 83 | args.args.len() |
| 84 | ))); |
| 85 | } |
| 86 | |
| 87 | // If there's a positional argument, treat it as a mapping |
| 88 | if let Some(mapping) = args.args.first() { |
| 89 | // Convert to dict if not already |
| 90 | let dict: PyRef<PyDict> = if let Some(d) = mapping.downcast_ref::<PyDict>() { |
| 91 | d.to_owned() |
| 92 | } else { |
| 93 | // Call dict() on the mapping |
| 94 | let dict_type: PyObjectRef = vm.ctx.types.dict_type.to_owned().into(); |
| 95 | dict_type |
| 96 | .call((mapping.clone(),), vm)? |
| 97 | .downcast() |
| 98 | .map_err(|_| vm.new_type_error("dict() did not return a dict"))? |
| 99 | }; |
| 100 | |
| 101 | // Validate keys are strings and set attributes |
| 102 | for (key, value) in dict.into_iter() { |
| 103 | let key_str = key |
| 104 | .downcast_ref::<crate::builtins::PyStr>() |
| 105 | .ok_or_else(|| { |
| 106 | vm.new_type_error(format!( |
| 107 | "keywords must be strings, not '{}'", |
| 108 | key.class().name() |
| 109 | )) |
| 110 | })?; |
| 111 | zelf.as_object().set_attr(key_str, value, vm)?; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Apply keyword arguments (these override positional mapping values) |
| 116 | for (name, value) in args.kwargs { |
| 117 | let name = vm.ctx.new_str(name); |
| 118 | zelf.as_object().set_attr(&name, value, vm)?; |
| 119 | } |
| 120 | Ok(()) |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | impl Comparable for PyNamespace { |
nothing calls this directly
no test coverage detected