(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine)
| 278 | type Args = FuncArgs; |
| 279 | |
| 280 | fn slot_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { |
| 281 | let fields = zelf |
| 282 | .class() |
| 283 | .get_attr(vm.ctx.intern_str("_fields")) |
| 284 | .ok_or_else(|| { |
| 285 | let module = zelf |
| 286 | .class() |
| 287 | .get_attr(vm.ctx.intern_str("__module__")) |
| 288 | .and_then(|obj| obj.try_to_value::<String>(vm).ok()) |
| 289 | .unwrap_or_else(|| "ast".to_owned()); |
| 290 | vm.new_attribute_error(format!( |
| 291 | "type object '{}.{}' has no attribute '_fields'", |
| 292 | module, |
| 293 | zelf.class().name() |
| 294 | )) |
| 295 | })?; |
| 296 | let fields: Vec<PyUtf8StrRef> = fields.try_to_value(vm)?; |
| 297 | let n_args = args.args.len(); |
| 298 | if n_args > fields.len() { |
| 299 | return Err(vm.new_type_error(format!( |
| 300 | "{} constructor takes at most {} positional argument{}", |
| 301 | zelf.class().name(), |
| 302 | fields.len(), |
| 303 | if fields.len() == 1 { "" } else { "s" }, |
| 304 | ))); |
| 305 | } |
| 306 | |
| 307 | // Track which fields were set |
| 308 | let mut set_fields = std::collections::HashSet::new(); |
| 309 | let mut attributes: Option<Vec<PyStrRef>> = None; |
| 310 | |
| 311 | for (name, arg) in fields.iter().zip(args.args) { |
| 312 | zelf.set_attr(name, arg, vm)?; |
| 313 | set_fields.insert(name.as_str().to_owned()); |
| 314 | } |
| 315 | for (key, value) in args.kwargs { |
| 316 | if let Some(pos) = fields.iter().position(|f| f.as_bytes() == key.as_bytes()) |
| 317 | && pos < n_args |
| 318 | { |
| 319 | return Err(vm.new_type_error(format!( |
| 320 | "{} got multiple values for argument '{}'", |
| 321 | zelf.class().name(), |
| 322 | key |
| 323 | ))); |
| 324 | } |
| 325 | |
| 326 | if fields |
| 327 | .iter() |
| 328 | .all(|field| field.as_bytes() != key.as_bytes()) |
| 329 | { |
| 330 | let attrs = if let Some(attrs) = &attributes { |
| 331 | attrs |
| 332 | } else { |
| 333 | let attrs = zelf |
| 334 | .class() |
| 335 | .get_attr(vm.ctx.intern_str("_attributes")) |
| 336 | .and_then(|attr| attr.try_to_value::<Vec<PyStrRef>>(vm).ok()) |
| 337 | .unwrap_or_default(); |
nothing calls this directly
no test coverage detected