Get arguments for __new__ from __getnewargs_ex__ or __getnewargs__ Returns (args, kwargs) tuple where either can be None
(
obj: &PyObject,
vm: &VirtualMachine,
)
| 577 | /// Get arguments for __new__ from __getnewargs_ex__ or __getnewargs__ |
| 578 | /// Returns (args, kwargs) tuple where either can be None |
| 579 | fn get_new_arguments( |
| 580 | obj: &PyObject, |
| 581 | vm: &VirtualMachine, |
| 582 | ) -> PyResult<(Option<super::PyTupleRef>, Option<super::PyDictRef>)> { |
| 583 | // First try __getnewargs_ex__ |
| 584 | if let Some(getnewargs_ex) = vm.get_special_method(obj, identifier!(vm, __getnewargs_ex__))? { |
| 585 | let newargs = getnewargs_ex.invoke((), vm)?; |
| 586 | |
| 587 | let newargs_tuple: PyRef<super::PyTuple> = newargs.downcast().map_err(|obj| { |
| 588 | vm.new_type_error(format!( |
| 589 | "__getnewargs_ex__ should return a tuple, not '{}'", |
| 590 | obj.class().name() |
| 591 | )) |
| 592 | })?; |
| 593 | |
| 594 | if newargs_tuple.len() != 2 { |
| 595 | return Err(vm.new_value_error(format!( |
| 596 | "__getnewargs_ex__ should return a tuple of length 2, not {}", |
| 597 | newargs_tuple.len() |
| 598 | ))); |
| 599 | } |
| 600 | |
| 601 | let args = newargs_tuple.as_slice()[0].clone(); |
| 602 | let kwargs = newargs_tuple.as_slice()[1].clone(); |
| 603 | |
| 604 | let args_tuple: PyRef<super::PyTuple> = args.downcast().map_err(|obj| { |
| 605 | vm.new_type_error(format!( |
| 606 | "first item of the tuple returned by __getnewargs_ex__ must be a tuple, not '{}'", |
| 607 | obj.class().name() |
| 608 | )) |
| 609 | })?; |
| 610 | |
| 611 | let kwargs_dict: PyRef<super::PyDict> = kwargs.downcast().map_err(|obj| { |
| 612 | vm.new_type_error(format!( |
| 613 | "second item of the tuple returned by __getnewargs_ex__ must be a dict, not '{}'", |
| 614 | obj.class().name() |
| 615 | )) |
| 616 | })?; |
| 617 | |
| 618 | return Ok((Some(args_tuple), Some(kwargs_dict))); |
| 619 | } |
| 620 | |
| 621 | // Fall back to __getnewargs__ |
| 622 | if let Some(getnewargs) = vm.get_special_method(obj, identifier!(vm, __getnewargs__))? { |
| 623 | let args = getnewargs.invoke((), vm)?; |
| 624 | |
| 625 | let args_tuple: PyRef<super::PyTuple> = args.downcast().map_err(|obj| { |
| 626 | vm.new_type_error(format!( |
| 627 | "__getnewargs__ should return a tuple, not '{}'", |
| 628 | obj.class().name() |
| 629 | )) |
| 630 | })?; |
| 631 | |
| 632 | return Ok((Some(args_tuple), None)); |
| 633 | } |
| 634 | |
| 635 | // No __getnewargs_ex__ or __getnewargs__ |
| 636 | Ok((None, None)) |
no test coverage detected