(args: &[PyObjectRef], vm: &VirtualMachine)
| 297 | } |
| 298 | |
| 299 | fn make_parameters_from_slice(args: &[PyObjectRef], vm: &VirtualMachine) -> PyTupleRef { |
| 300 | let mut parameters: Vec<PyObjectRef> = Vec::with_capacity(args.len()); |
| 301 | |
| 302 | for arg in args { |
| 303 | // We don't want __parameters__ descriptor of a bare Python class. |
| 304 | if arg.class().is(vm.ctx.types.type_type) { |
| 305 | continue; |
| 306 | } |
| 307 | |
| 308 | // Check for __typing_subst__ attribute |
| 309 | if arg.get_attr(identifier!(vm, __typing_subst__), vm).is_ok() { |
| 310 | if tuple_index(¶meters, arg).is_none() { |
| 311 | parameters.push(arg.clone()); |
| 312 | } |
| 313 | } else if let Ok(subparams) = arg.get_attr(identifier!(vm, __parameters__), vm) |
| 314 | && let Ok(sub_params) = subparams.try_to_ref::<PyTuple>(vm) |
| 315 | { |
| 316 | for sub_param in sub_params { |
| 317 | if tuple_index(¶meters, sub_param).is_none() { |
| 318 | parameters.push(sub_param.clone()); |
| 319 | } |
| 320 | } |
| 321 | } else if arg.try_to_ref::<PyTuple>(vm).is_ok() || arg.try_to_ref::<PyList>(vm).is_ok() { |
| 322 | // Recursively extract parameters from lists/tuples (ParamSpec args) |
| 323 | let items: Vec<PyObjectRef> = if let Ok(t) = arg.try_to_ref::<PyTuple>(vm) { |
| 324 | t.as_slice().to_vec() |
| 325 | } else { |
| 326 | let list = arg.downcast_ref::<PyList>().unwrap(); |
| 327 | list.borrow_vec().to_vec() |
| 328 | }; |
| 329 | let sub = make_parameters_from_slice(&items, vm); |
| 330 | for sub_param in sub.iter() { |
| 331 | if tuple_index(¶meters, sub_param).is_none() { |
| 332 | parameters.push(sub_param.clone()); |
| 333 | } |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | PyTuple::new_ref(parameters, &vm.ctx) |
| 339 | } |
| 340 | |
| 341 | #[inline] |
| 342 | fn tuple_index(vec: &[PyObjectRef], item: &PyObject) -> Option<usize> { |
no test coverage detected