| 415 | } |
| 416 | |
| 417 | py::tuple parse_args_and_kwargs( |
| 418 | py::tuple args, py::dict kwargs, const PyArgDescs& descs) { |
| 419 | size_t nr_args = args.size(); |
| 420 | size_t nr_kwargs = kwargs.size(); |
| 421 | size_t nr_items = descs.items.size(); |
| 422 | mgb_assert(nr_args + nr_kwargs <= nr_items, "too many args"); |
| 423 | if (nr_args == nr_items) { |
| 424 | return args; |
| 425 | } |
| 426 | py::tuple ret(nr_items); |
| 427 | for (size_t i = 0; i < nr_args; ++i) { |
| 428 | ret[i] = args[i]; |
| 429 | } |
| 430 | bool has_value[nr_items - nr_args]; |
| 431 | for (size_t i = nr_args; i < nr_items; ++i) { |
| 432 | has_value[i - nr_args] = false; |
| 433 | } |
| 434 | for (auto&& [k, v] : kwargs) { |
| 435 | auto key = py::str(k).cast<std::string>(); |
| 436 | ssize_t index = descs.name2idx(key.c_str()); |
| 437 | mgb_assert(index >= nr_args); |
| 438 | ret[index] = v; |
| 439 | has_value[index - nr_args] = true; |
| 440 | } |
| 441 | for (size_t i = nr_args; i < nr_items; ++i) { |
| 442 | if (!has_value[i - nr_args]) { |
| 443 | ret[i] = descs.items[i].default_value(); |
| 444 | } |
| 445 | } |
| 446 | return ret; |
| 447 | } |
| 448 | |
| 449 | CompNode as_comp_node(const std::string& name) { |
| 450 | thread_local struct { |
no test coverage detected