Feature or enhancement
Many functions accept a duration (a timeout, an interval, a delay) or a timestamp, and every one of them converts the argument in the "impl" function. They are declared as object (or double, or a Windows DWORD) and converted with _PyTime_FromSecondsObject(), _PyTime_FromMillisecondsObject(), _PyTime_ObjectToTime_t(), _PyTime_ObjectToTimeval(), _PyTime_ObjectToTimespec() and the corresponding _PyTime_As*() functions.
The conversions differ in several independent aspects:
- the unit of the argument: seconds (most of them) or milliseconds (
select.poll.poll(), select.devpoll.poll());
- the rounding mode:
_PyTime_ROUND_TIMEOUT (select, socket, _thread, faulthandler, time.sleep()), _PyTime_ROUND_CEILING (signal.sigtimedwait(), signal.setitimer(), _queue, _ssl) or _PyTime_ROUND_FLOOR (time.gmtime(), datetime.date.fromtimestamp());
- the type and unit used by the implementation:
PyTime_t (nanoseconds), microseconds or milliseconds as an integer, struct timeval or struct timespec, double seconds, time_t seconds, or Windows DWORD milliseconds;
- the meaning of
None: block forever (select, _queue, _multiprocessing.SemLock), the current time (time.gmtime(), time.localtime(), time.ctime()), not specified (_thread, where the Python default is -1), or not accepted at all (signal.sigtimedwait());
- the range check: no check, or
ValueError with one of several messages -- "timeout must be non-negative", "timeout must be positive or None", "timeout is too large", "timeout value is too large", "timeout must be greater than 0".
The error for a wrong type differs too: select raises "timeout must be a real number or None, not %T", other modules use the message produced by _PyTime_FromSecondsObject().
Timestamps need the same machinery: datetime.date.fromtimestamp() uses _PyTime_ObjectToTime_t(), datetime.datetime.fromtimestamp() uses _PyTime_ObjectToTimeval(), os.utime() uses _PyTime_ObjectToTimespec() for the items of the times tuple, and time.gmtime(), time.localtime() and time.ctime() use a private helper which also treats None as the current time.
Parametrized converters would allow to declare all of them, for example:
timeout: duration(unit='s', out='ms', round='timeout', accept={float, NoneType})
timestamp: timestamp(out='time_t', round='floor')
There are 19 parameters named "timeout" and at least 10 more of the same kind (seconds and interval of signal.setitimer(), the argument of time.sleep(), secs of the time functions, timestamp of the datetime constructors). Unifying them will also unify the error messages, which is a user visible change.
Linked PRs
Feature or enhancement
Many functions accept a duration (a timeout, an interval, a delay) or a timestamp, and every one of them converts the argument in the "impl" function. They are declared as
object(ordouble, or a WindowsDWORD) and converted with_PyTime_FromSecondsObject(),_PyTime_FromMillisecondsObject(),_PyTime_ObjectToTime_t(),_PyTime_ObjectToTimeval(),_PyTime_ObjectToTimespec()and the corresponding_PyTime_As*()functions.The conversions differ in several independent aspects:
select.poll.poll(),select.devpoll.poll());_PyTime_ROUND_TIMEOUT(select,socket,_thread,faulthandler,time.sleep()),_PyTime_ROUND_CEILING(signal.sigtimedwait(),signal.setitimer(),_queue,_ssl) or_PyTime_ROUND_FLOOR(time.gmtime(),datetime.date.fromtimestamp());PyTime_t(nanoseconds), microseconds or milliseconds as an integer,struct timevalorstruct timespec,doubleseconds,time_tseconds, or WindowsDWORDmilliseconds;None: block forever (select,_queue,_multiprocessing.SemLock), the current time (time.gmtime(),time.localtime(),time.ctime()), not specified (_thread, where the Python default is-1), or not accepted at all (signal.sigtimedwait());ValueErrorwith one of several messages -- "timeout must be non-negative", "timeout must be positive or None", "timeout is too large", "timeout value is too large", "timeout must be greater than 0".The error for a wrong type differs too:
selectraises "timeout must be a real number or None, not %T", other modules use the message produced by_PyTime_FromSecondsObject().Timestamps need the same machinery:
datetime.date.fromtimestamp()uses_PyTime_ObjectToTime_t(),datetime.datetime.fromtimestamp()uses_PyTime_ObjectToTimeval(),os.utime()uses_PyTime_ObjectToTimespec()for the items of the times tuple, andtime.gmtime(),time.localtime()andtime.ctime()use a private helper which also treatsNoneas the current time.Parametrized converters would allow to declare all of them, for example:
There are 19 parameters named "timeout" and at least 10 more of the same kind (
secondsandintervalofsignal.setitimer(), the argument oftime.sleep(), secs of thetimefunctions, timestamp of thedatetimeconstructors). Unifying them will also unify the error messages, which is a user visible change.Linked PRs