mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
refactor: share PyTime conversions with time.sleep (#9362)
Move the existing conversion helper into the production time module and reuse it from sleep, preserving conversion bodies and internal C-API argument binding. Assisted-by: OpenAI Codex:model version unavailable
This commit is contained in:
1 parent
0dca682e45
commit
1170a337cc
3 files changed
+16
-52
No files matched your search
@@ -1,7 +1,5 @@
|
||||
pub(crate) use _testinternalcapi::module_def;
|
||||
|
||||
mod pytime;
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static RARE_SET_CLASS: AtomicUsize = AtomicUsize::new(0);
|
||||
@@ -28,7 +26,6 @@ pub(crate) fn note_func_modification() {
|
||||
|
||||
#[pymodule]
|
||||
mod _testinternalcapi {
|
||||
use super::pytime::Round;
|
||||
use super::*;
|
||||
use crate::{
|
||||
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
@@ -43,6 +40,7 @@ mod _testinternalcapi {
|
||||
function::{FuncArgs, OptionalArg, PyComparisonValue},
|
||||
object::{Traverse, TraverseFn},
|
||||
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
|
||||
stdlib::time::pytime::{self, Round},
|
||||
types::{
|
||||
AsMapping, AsSequence, Comparable, IterNext, Iterable, PyComparisonOp, PyTypeFlags,
|
||||
SelfIter,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// https://docs.python.org/3/library/time.html
|
||||
|
||||
pub use decl::time;
|
||||
pub(crate) mod pytime;
|
||||
|
||||
pub(crate) use decl::module_def;
|
||||
pub(crate) use decl::perf_counter_ns as profiler_time;
|
||||
@@ -19,7 +20,7 @@ mod decl {
|
||||
use crate::convert::{ToPyException, ToPyObject};
|
||||
use crate::{
|
||||
AsObject, Py, PyObjectRef, PyResult, VirtualMachine,
|
||||
builtins::{PyFloat, PyStr, PyStrRef, PyTypeRef},
|
||||
builtins::{PyStr, PyStrRef, PyTypeRef},
|
||||
class::PyClassDef,
|
||||
common::wtf8::Wtf8Buf,
|
||||
function::{Either, FuncArgs, OptionalArg, OptionalOption},
|
||||
@@ -33,7 +34,6 @@ mod decl {
|
||||
use core::time::Duration;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
use jiff::{Timestamp, Zoned, civil::DateTime, tz::TimeZone};
|
||||
use num_traits::ToPrimitive;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use rustpython_host_env::time::ClockId;
|
||||
#[cfg(any(unix, windows))]
|
||||
@@ -128,43 +128,9 @@ mod decl {
|
||||
fn sleep(object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
vm.audit("time.sleep", || (object.clone(),))?;
|
||||
|
||||
let overflow = || vm.new_overflow_error("timestamp out of range for C PyTime_t");
|
||||
let nanoseconds = if object.number().is_index() {
|
||||
let seconds = object.try_index(vm).map_err(|e| {
|
||||
if e.fast_isinstance(vm.ctx.exceptions.overflow_error) {
|
||||
overflow()
|
||||
} else {
|
||||
e
|
||||
}
|
||||
})?;
|
||||
seconds
|
||||
.as_bigint()
|
||||
.to_i64()
|
||||
.and_then(|seconds| seconds.checked_mul(SEC_TO_NS))
|
||||
.ok_or_else(overflow)?
|
||||
} else {
|
||||
// PyFloat_AsDouble reads float subclasses without calling __float__.
|
||||
let seconds = match object.downcast_ref::<PyFloat>() {
|
||||
Some(value) => value.to_f64(),
|
||||
None => object.try_float(vm)?.to_f64(),
|
||||
};
|
||||
if seconds.is_nan() {
|
||||
return Err(vm.new_value_error("Invalid value NaN (not a number)"));
|
||||
}
|
||||
// _PyTime_ROUND_TIMEOUT rounds away from zero.
|
||||
let nanoseconds = seconds * SEC_TO_NS as f64;
|
||||
let nanoseconds = if nanoseconds >= 0.0 {
|
||||
nanoseconds.ceil()
|
||||
} else {
|
||||
nanoseconds.floor()
|
||||
};
|
||||
let minimum = i64::MIN as f64;
|
||||
// The signed maximum rounds up to 2**63 as a double.
|
||||
if !(minimum..-minimum).contains(&nanoseconds) {
|
||||
return Err(overflow());
|
||||
}
|
||||
nanoseconds as i64
|
||||
};
|
||||
// _PyTime_ROUND_TIMEOUT rounds away from zero.
|
||||
let nanoseconds =
|
||||
super::pytime::from_seconds_object(&object, super::pytime::Round::Up, vm)?;
|
||||
if nanoseconds < 0 {
|
||||
return Err(vm.new_value_error("sleep length must be non-negative"));
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
//! Numeric conversions used by the internal PyTime test helpers.
|
||||
//! Signed nanosecond timestamps and the rounding used by Python's time APIs.
|
||||
|
||||
#![cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
|
||||
@@ -7,9 +7,9 @@ use num_traits::ToPrimitive;
|
||||
use rustpython_host_env::time::SEC_TO_NS;
|
||||
|
||||
#[cfg(any(unix, windows))]
|
||||
pub(super) use rustpython_host_env::time::TimeT;
|
||||
pub(crate) use rustpython_host_env::time::TimeT;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
pub(super) type TimeT = i64;
|
||||
pub(crate) type TimeT = i64;
|
||||
|
||||
const TIME_T_MIN: i64 = TimeT::MIN as _;
|
||||
const TIME_T_MAX: i64 = TimeT::MAX as _;
|
||||
@@ -17,7 +17,7 @@ const PYTIME_OVERFLOW: &str = "timestamp out of range for C PyTime_t";
|
||||
const TIME_T_OVERFLOW: &str = "timestamp out of range for platform time_t";
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum Round {
|
||||
pub(crate) enum Round {
|
||||
Floor,
|
||||
Ceiling,
|
||||
HalfEven,
|
||||
@@ -25,7 +25,7 @@ pub(super) enum Round {
|
||||
}
|
||||
|
||||
impl Round {
|
||||
pub(super) fn from_int(value: i32, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
pub(crate) fn from_int(value: i32, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
match value {
|
||||
0 => Ok(Self::Floor),
|
||||
1 => Ok(Self::Ceiling),
|
||||
@@ -45,7 +45,7 @@ impl Round {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn divide(self, value: i64, divisor: i64) -> i64 {
|
||||
pub(crate) fn divide(self, value: i64, divisor: i64) -> i64 {
|
||||
debug_assert!(divisor > 1);
|
||||
let quotient = value / divisor;
|
||||
let remainder = value % divisor;
|
||||
@@ -65,7 +65,7 @@ impl Round {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn from_seconds(seconds: i32) -> i64 {
|
||||
pub(crate) fn from_seconds(seconds: i32) -> i64 {
|
||||
i64::from(seconds) * SEC_TO_NS
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ fn float_seconds(object: &PyObject, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
Ok(seconds)
|
||||
}
|
||||
|
||||
pub(super) fn from_seconds_object(
|
||||
pub(crate) fn from_seconds_object(
|
||||
object: &PyObject,
|
||||
round: Round,
|
||||
vm: &VirtualMachine,
|
||||
@@ -132,7 +132,7 @@ fn float_to_time_t(seconds: f64, vm: &VirtualMachine) -> PyResult<i64> {
|
||||
Ok(seconds as i64)
|
||||
}
|
||||
|
||||
pub(super) fn object_to_time_t(
|
||||
pub(crate) fn object_to_time_t(
|
||||
object: &PyObject,
|
||||
round: Round,
|
||||
vm: &VirtualMachine,
|
||||
@@ -144,7 +144,7 @@ pub(super) fn object_to_time_t(
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn object_to_denominator(
|
||||
pub(crate) fn object_to_denominator(
|
||||
object: &PyObject,
|
||||
denominator: i64,
|
||||
round: Round,
|
||||
Reference in new issue
Block a user