diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 3886aae934..9543bd5514 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -155,7 +155,17 @@ def test_conversions(self): def test_sleep(self): self.assertRaises(ValueError, time.sleep, -2) self.assertRaises(ValueError, time.sleep, -1) + self.assertRaises(ValueError, time.sleep, float('nan')) + self.assertRaises(ValueError, time.sleep, float('inf')) + self.assertRaises(ValueError, time.sleep, -float('inf')) + self.assertRaises(ValueError, time.sleep, 1e100) + time.sleep(0) + time.sleep(0.000001) + time.sleep(1e-9) + time.sleep(0.5) time.sleep(1.2) + time.sleep(2) + # TODO: RUSTPYTHON @unittest.expectedFailure diff --git a/vm/src/stdlib/time.rs b/vm/src/stdlib/time.rs index 12a47fca87..92d35a1cc0 100644 --- a/vm/src/stdlib/time.rs +++ b/vm/src/stdlib/time.rs @@ -90,8 +90,22 @@ mod decl { #[cfg(not(unix))] #[pyfunction] - fn sleep(dur: Duration) { - std::thread::sleep(dur); + fn sleep(secs: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + // Try to get as float first, if that fails try as integer + let secs = if let Ok(float_val) = f64::try_from_object(vm, secs.clone()) { + float_val + } else if let Ok(int_val) = i64::try_from_object(vm, secs) { + int_val as f64 + } else { + return Err(vm.new_type_error("sleep() argument must be a number")); + }; + if !secs.is_finite() || secs < 0.0 || secs > (u32::MAX / 1000) as f64 { + return Err(vm.new_value_error("sleep length must be a non-negative finite number")); + } + + let duration = Duration::from_secs_f64(secs); + std::thread::sleep(duration); + Ok(()) } #[cfg(not(target_os = "wasi"))] @@ -527,7 +541,7 @@ mod platform { use crate::{ PyObject, PyRef, PyResult, TryFromBorrowedObject, VirtualMachine, builtins::{PyNamespace, PyStrRef}, - convert::IntoPyException, + convert::{IntoPyException,TryFromObject}, }; use nix::{sys::time::TimeSpec, time::ClockId}; use std::time::Duration; @@ -691,9 +705,20 @@ mod platform { } #[pyfunction] - fn sleep(dur: Duration, vm: &VirtualMachine) -> PyResult<()> { + fn sleep(secs: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { // this is basically std::thread::sleep, but that catches interrupts and we don't want to; - + // Try to get as float first, if that fails try as integer + let secs = if let Ok(float_val) = f64::try_from_object(vm, secs.clone()) { + float_val + } else if let Ok(int_val) = i64::try_from_object(vm, secs) { + int_val as f64 + } else { + return Err(vm.new_type_error("sleep() argument must be a number")); + }; + if !secs.is_finite() || secs < 0.0 || secs > u64::MAX as f64 { + return Err(vm.new_value_error("sleep length must be a non-negative finite number")); + } + let dur = Duration::from_secs_f64(secs); let ts = TimeSpec::from(dur); let res = unsafe { libc::nanosleep(ts.as_ref(), std::ptr::null_mut()) }; let interrupted = res == -1 && nix::Error::last_raw() == libc::EINTR; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy