Skip to content

Commit 5215967

Browse files
committed
pass test_int
1 parent ca2b3f8 commit 5215967

File tree

5 files changed

+88
-39
lines changed

5 files changed

+88
-39
lines changed

Lib/test/test_int.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,14 @@ def __trunc__(self):
369369
class JustTrunc(base):
370370
def __trunc__(self):
371371
return 42
372-
self.assertEqual(int(JustTrunc()), 42)
372+
with self.assertWarns(DeprecationWarning):
373+
self.assertEqual(int(JustTrunc()), 42)
373374

374375
class ExceptionalTrunc(base):
375376
def __trunc__(self):
376377
1 / 0
377-
with self.assertRaises(ZeroDivisionError):
378+
with self.assertRaises(ZeroDivisionError), \
379+
self.assertWarns(DeprecationWarning):
378380
int(ExceptionalTrunc())
379381

380382
for trunc_result_base in (object, Classic):
@@ -385,7 +387,8 @@ def __index__(self):
385387
class TruncReturnsNonInt(base):
386388
def __trunc__(self):
387389
return Index()
388-
self.assertEqual(int(TruncReturnsNonInt()), 42)
390+
with self.assertWarns(DeprecationWarning):
391+
self.assertEqual(int(TruncReturnsNonInt()), 42)
389392

390393
class Intable(trunc_result_base):
391394
def __int__(self):
@@ -394,7 +397,8 @@ def __int__(self):
394397
class TruncReturnsNonIndex(base):
395398
def __trunc__(self):
396399
return Intable()
397-
self.assertEqual(int(TruncReturnsNonInt()), 42)
400+
with self.assertWarns(DeprecationWarning):
401+
self.assertEqual(int(TruncReturnsNonInt()), 42)
398402

399403
class NonIntegral(trunc_result_base):
400404
def __trunc__(self):
@@ -405,7 +409,8 @@ class TruncReturnsNonIntegral(base):
405409
def __trunc__(self):
406410
return NonIntegral()
407411
try:
408-
int(TruncReturnsNonIntegral())
412+
with self.assertWarns(DeprecationWarning):
413+
int(TruncReturnsNonIntegral())
409414
except TypeError as e:
410415
self.assertEqual(str(e),
411416
"__trunc__ returned non-Integral"
@@ -423,7 +428,8 @@ class TruncReturnsBadInt(base):
423428
def __trunc__(self):
424429
return BadInt()
425430

426-
with self.assertRaises(TypeError):
431+
with self.assertRaises(TypeError), \
432+
self.assertWarns(DeprecationWarning):
427433
int(TruncReturnsBadInt())
428434

429435
def test_int_subclass_with_index(self):
@@ -458,8 +464,6 @@ def __int__(self):
458464
self.assertEqual(my_int, 7)
459465
self.assertRaises(TypeError, int, my_int)
460466

461-
# TODO: RUSTPYTHON
462-
@unittest.expectedFailure
463467
def test_int_returns_int_subclass(self):
464468
class BadIndex:
465469
def __index__(self):
@@ -519,13 +523,16 @@ def __trunc__(self):
519523
self.assertIs(type(n), int)
520524

521525
bad_int = TruncReturnsBadInt()
522-
self.assertRaises(TypeError, int, bad_int)
526+
with self.assertWarns(DeprecationWarning):
527+
self.assertRaises(TypeError, int, bad_int)
523528

524529
good_int = TruncReturnsIntSubclass()
525-
n = int(good_int)
530+
with self.assertWarns(DeprecationWarning):
531+
n = int(good_int)
526532
self.assertEqual(n, 1)
527533
self.assertIs(type(n), int)
528-
n = IntSubclass(good_int)
534+
with self.assertWarns(DeprecationWarning):
535+
n = IntSubclass(good_int)
529536
self.assertEqual(n, 1)
530537
self.assertIs(type(n), IntSubclass)
531538

vm/src/protocol/number.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
builtins::{int, PyByteArray, PyBytes, PyComplex, PyFloat, PyInt, PyIntRef, PyStr},
55
common::lock::OnceCell,
66
function::ArgBytesLike,
7+
stdlib::warnings,
78
AsObject, PyObject, PyPayload, PyRef, PyResult, TryFromBorrowedObject, VirtualMachine,
89
};
910

@@ -119,15 +120,33 @@ impl PyNumber<'_> {
119120
}
120121

121122
if self.obj.class().is(PyInt::class(vm)) {
122-
Ok(unsafe { self.obj.downcast_unchecked_ref::<PyInt>() }.to_owned())
123+
Ok(unsafe { self.obj.to_owned().downcast_unchecked::<PyInt>() })
123124
} else if let Some(f) = self.methods(vm).int {
124-
f(self, vm)
125-
} else if let Some(f) = self.methods(vm).index {
126-
f(self, vm)
125+
let ret = f(self, vm)?;
126+
if !ret.class().is(PyInt::class(vm)) {
127+
warnings::warn(
128+
vm.ctx.exceptions.deprecation_warning.clone(),
129+
format!("__int__ returned non-int (type {})", ret.class()),
130+
1,
131+
vm,
132+
)?
133+
}
134+
Ok(ret)
135+
} else if self.methods(vm).index.is_some() {
136+
self.index(vm)
127137
} else if let Ok(Ok(f)) = vm.get_special_method(self.obj.to_owned(), "__trunc__") {
128-
let r = f.invoke((), vm)?;
129-
PyNumber::from(r.as_ref()).index(vm).map_err(|_| {
130-
vm.new_type_error("__trunc__ returned non-Integral (type NonIntegral)".to_string())
138+
warnings::warn(
139+
vm.ctx.exceptions.deprecation_warning.clone(),
140+
"The delegation of int() to __trunc__ is deprecated.".to_owned(),
141+
1,
142+
vm,
143+
)?;
144+
let ret = f.invoke((), vm)?;
145+
PyNumber::from(ret.as_ref()).index(vm).map_err(|_| {
146+
vm.new_type_error(format!(
147+
"__trunc__ returned non-Integral (type {})",
148+
ret.class()
149+
))
131150
})
132151
} else if let Some(s) = self.obj.payload::<PyStr>() {
133152
try_convert(self.obj, s.as_str().as_bytes(), vm)
@@ -148,9 +167,18 @@ impl PyNumber<'_> {
148167

149168
pub fn index(&self, vm: &VirtualMachine) -> PyResult<PyIntRef> {
150169
if self.obj.class().is(PyInt::class(vm)) {
151-
Ok(unsafe { self.obj.downcast_unchecked_ref::<PyInt>() }.to_owned())
170+
Ok(unsafe { self.obj.to_owned().downcast_unchecked::<PyInt>() })
152171
} else if let Some(f) = self.methods(vm).index {
153-
f(self, vm)
172+
let ret = f(self, vm)?;
173+
if !ret.class().is(PyInt::class(vm)) {
174+
warnings::warn(
175+
vm.ctx.exceptions.deprecation_warning.clone(),
176+
format!("__index__ returned non-int (type {})", ret.class()),
177+
1,
178+
vm,
179+
)?
180+
}
181+
Ok(ret)
154182
} else {
155183
Err(vm.new_type_error(format!(
156184
"'{}' object cannot be interpreted as an integer",

vm/src/stdlib/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod sysconfigdata;
2121
#[cfg(feature = "threading")]
2222
mod thread;
2323
pub mod time;
24-
mod warnings;
24+
pub mod warnings;
2525
mod weakref;
2626

2727
#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]

vm/src/stdlib/warnings.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
pub(crate) use _warnings::make_module;
22

3+
use crate::{builtins::PyTypeRef, PyResult, VirtualMachine};
4+
5+
pub fn warn(
6+
category: PyTypeRef,
7+
message: String,
8+
stack_level: usize,
9+
vm: &VirtualMachine,
10+
) -> PyResult<()> {
11+
// let module = vm.import("warnings", None, 0)?;
12+
// let func = module.get_attr("warn", vm)?;
13+
// vm.invoke(&func, (message, category, stack_level))?;
14+
// TODO
15+
if let Ok(module) = vm.import("warnings", None, 0) {
16+
if let Ok(func) = module.get_attr("warn", vm) {
17+
let _ = vm.invoke(&func, (message, category, stack_level));
18+
}
19+
}
20+
Ok(())
21+
}
22+
323
#[pymodule]
424
mod _warnings {
525
use crate::{

vm/src/types/slot.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -257,30 +257,24 @@ fn as_number_wrapper(zelf: &PyObject, _vm: &VirtualMachine) -> Cow<'static, PyNu
257257
Cow::Owned(PyNumberMethods {
258258
int: then_some_closure!(zelf.class().has_attr("__int__"), |num, vm| {
259259
let ret = vm.call_special_method(num.obj.to_owned(), "__int__", ())?;
260-
if let Some(i) = ret.downcast_ref::<PyInt>() {
261-
Ok(i.to_owned())
262-
} else {
263-
// TODO
264-
Err(vm.new_type_error("".to_string()))
265-
}
260+
ret.downcast::<PyInt>().map_err(|obj| {
261+
vm.new_type_error(format!("__int__ returned non-int (type {})", obj.class()))
262+
})
266263
}),
267264
float: then_some_closure!(zelf.class().has_attr("__float__"), |num, vm| {
268265
let ret = vm.call_special_method(num.obj.to_owned(), "__float__", ())?;
269-
if let Some(f) = ret.downcast_ref::<PyFloat>() {
270-
Ok(f.to_owned())
271-
} else {
272-
// TODO
273-
Err(vm.new_type_error("".to_string()))
274-
}
266+
ret.downcast::<PyFloat>().map_err(|obj| {
267+
vm.new_type_error(format!(
268+
"__float__ returned non-float (type {})",
269+
obj.class()
270+
))
271+
})
275272
}),
276273
index: then_some_closure!(zelf.class().has_attr("__index__"), |num, vm| {
277274
let ret = vm.call_special_method(num.obj.to_owned(), "__index__", ())?;
278-
if let Some(i) = ret.downcast_ref::<PyInt>() {
279-
Ok(i.to_owned())
280-
} else {
281-
// TODO
282-
Err(vm.new_type_error("".to_string()))
283-
}
275+
ret.downcast::<PyInt>().map_err(|obj| {
276+
vm.new_type_error(format!("__index__ returned non-int (type {})", obj.class()))
277+
})
284278
}),
285279
..*PyNumberMethods::not_implemented()
286280
})

0 commit comments

Comments
 (0)