(
mut f_args: FuncArgs,
vm: &VirtualMachine,
)
| 1469 | |
| 1470 | #[pyfunction] |
| 1471 | fn start_joinable_thread( |
| 1472 | mut f_args: FuncArgs, |
| 1473 | vm: &VirtualMachine, |
| 1474 | ) -> PyResult<PyRef<ThreadHandle>> { |
| 1475 | let given = f_args.args.len() + f_args.kwargs.len(); |
| 1476 | if given > 3 { |
| 1477 | return Err(vm.new_type_error(format!( |
| 1478 | "start_joinable_thread() takes at most 3 arguments ({given} given)" |
| 1479 | ))); |
| 1480 | } |
| 1481 | |
| 1482 | let function_pos = f_args.take_positional(); |
| 1483 | let function_kw = f_args.take_keyword("function"); |
| 1484 | if function_pos.is_some() && function_kw.is_some() { |
| 1485 | return Err(vm.new_type_error( |
| 1486 | "argument for start_joinable_thread() given by name ('function') and position (1)", |
| 1487 | )); |
| 1488 | } |
| 1489 | let Some(function_obj) = function_pos.or(function_kw) else { |
| 1490 | return Err(vm.new_type_error( |
| 1491 | "start_joinable_thread() missing required argument 'function' (pos 1)", |
| 1492 | )); |
| 1493 | }; |
| 1494 | |
| 1495 | let handle_pos = f_args.take_positional(); |
| 1496 | let handle_kw = f_args.take_keyword("handle"); |
| 1497 | if handle_pos.is_some() && handle_kw.is_some() { |
| 1498 | return Err(vm.new_type_error( |
| 1499 | "argument for start_joinable_thread() given by name ('handle') and position (2)", |
| 1500 | )); |
| 1501 | } |
| 1502 | let handle_obj = handle_pos.or(handle_kw); |
| 1503 | |
| 1504 | let daemon_pos = f_args.take_positional(); |
| 1505 | let daemon_kw = f_args.take_keyword("daemon"); |
| 1506 | if daemon_pos.is_some() && daemon_kw.is_some() { |
| 1507 | return Err(vm.new_type_error( |
| 1508 | "argument for start_joinable_thread() given by name ('daemon') and position (3)", |
| 1509 | )); |
| 1510 | } |
| 1511 | let daemon = daemon_pos |
| 1512 | .or(daemon_kw) |
| 1513 | .map_or(Ok(true), |obj| obj.try_to_bool(vm))?; |
| 1514 | |
| 1515 | // Match CPython parser precedence: |
| 1516 | // - required positional/keyword argument errors are raised before |
| 1517 | // unknown keyword errors when `function` is missing. |
| 1518 | if let Some(unexpected) = f_args.kwargs.keys().next() { |
| 1519 | let suggestion = ["function", "handle", "daemon"] |
| 1520 | .iter() |
| 1521 | .filter_map(|candidate| { |
| 1522 | let max_distance = (unexpected.len() + candidate.len() + 3) * MOVE_COST / 6; |
| 1523 | let distance = levenshtein_distance( |
| 1524 | unexpected.as_bytes(), |
| 1525 | candidate.as_bytes(), |
| 1526 | max_distance, |
| 1527 | ); |
| 1528 | (distance <= max_distance).then_some((distance, *candidate)) |
nothing calls this directly
no test coverage detected