1
1
use std:: fmt;
2
2
use std:: hash:: { Hash , Hasher } ;
3
3
4
- use num_bigint:: { BigInt , ToBigInt } ;
4
+ use num_bigint:: BigInt ;
5
5
use num_integer:: Integer ;
6
6
use num_traits:: { Pow , Signed , ToPrimitive , Zero } ;
7
7
8
8
use crate :: format:: FormatSpec ;
9
- use crate :: function:: OptionalArg ;
9
+ use crate :: function:: { OptionalArg , PyFuncArgs } ;
10
10
use crate :: pyobject:: {
11
11
IntoPyObject , PyClassImpl , PyContext , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
12
12
TypeProtocol ,
@@ -510,11 +510,8 @@ fn int_new(cls: PyClassRef, options: IntOptions, vm: &VirtualMachine) -> PyResul
510
510
}
511
511
512
512
// Casting function:
513
- // TODO: this should just call `__int__` on the object
514
513
pub fn to_int ( vm : & VirtualMachine , obj : & PyObjectRef , base : u32 ) -> PyResult < BigInt > {
515
514
match_class ! ( obj. clone( ) ,
516
- i @ PyInt => Ok ( i. as_bigint( ) . clone( ) ) ,
517
- f @ PyFloat => Ok ( f. to_f64( ) . to_bigint( ) . unwrap( ) ) ,
518
515
s @ PyString => {
519
516
i32 :: from_str_radix( s. as_str( ) , base)
520
517
. map( BigInt :: from)
@@ -523,10 +520,21 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<Big
523
520
base, s
524
521
) ) )
525
522
} ,
526
- obj => Err ( vm. new_type_error( format!(
527
- "int() argument must be a string or a number, not '{}'" ,
528
- obj. class( ) . name
529
- ) ) )
523
+ obj => {
524
+ if let Ok ( f) = vm. get_method( obj. clone( ) , "__int__" ) {
525
+ let int_res = vm. invoke( f, PyFuncArgs :: default ( ) ) ?;
526
+ match int_res. payload:: <PyInt >( ) {
527
+ Some ( i) => Ok ( i. as_bigint( ) . clone( ) ) ,
528
+ None => Err ( vm. new_type_error( format!(
529
+ "TypeError: __int__ returned non-int (type '{}')" , int_res. class( ) . name) ) ) ,
530
+ }
531
+ } else {
532
+ Err ( vm. new_type_error( format!(
533
+ "int() argument must be a string or a number, not '{}'" ,
534
+ obj. class( ) . name
535
+ ) ) )
536
+ }
537
+ }
530
538
)
531
539
}
532
540
0 commit comments