:c:func:`localtime` function. Raise :exc:`OSError` instead of
:exc:`ValueError` on :c:func:`localtime` failure.
+ .. versionchanged:: next
+ Accepts any real number as *timestamp*, not only integer or float.
+
.. classmethod:: date.fromordinal(ordinal)
.. versionchanged:: 3.6
:meth:`fromtimestamp` may return instances with :attr:`.fold` set to 1.
+ .. versionchanged:: next
+ Accepts any real number as *timestamp*, not only integer or float.
+
+
.. classmethod:: datetime.utcfromtimestamp(timestamp)
Return the UTC :class:`.datetime` corresponding to the POSIX timestamp, with
Use :meth:`datetime.fromtimestamp` with :const:`UTC` instead.
+ .. versionchanged:: next
+ Accepts any real number as *timestamp*, not only integer or float.
+
.. classmethod:: datetime.fromordinal(ordinal)
where each member is an int expressing nanoseconds.
- If *times* is not ``None``,
it must be a 2-tuple of the form ``(atime, mtime)``
- where each member is an int or float expressing seconds.
+ where each member is a real number expressing seconds,
+ rounded down to nanoseconds.
- If *times* is ``None`` and *ns* is unspecified,
this is equivalent to specifying ``ns=(atime_ns, mtime_ns)``
where both times are the current time.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
+ .. versionchanged:: next
+ Accepts any real numbers as *times*, not only integers or floats.
+
.. function:: walk(top, topdown=True, onerror=None, followlinks=False)
the timer will fire when the timer's clock
(set by *clockid* in :func:`timerfd_create`) reaches *initial* seconds.
- The timer's interval is set by the *interval* :py:class:`float`.
+ The timer's interval is set by the *interval* real number.
If *interval* is zero, the timer only fires once, on the initial expiration.
If *interval* is greater than zero, the timer fires every time *interval*
seconds have elapsed since the previous expiration.
Empty iterables are allowed, but acceptance of three empty iterables is
platform-dependent. (It is known to work on Unix but not on Windows.) The
- optional *timeout* argument specifies a time-out as a floating-point number
- in seconds. When the *timeout* argument is omitted the function blocks until
+ optional *timeout* argument specifies a time-out in seconds; it may be
+ a non-integer to specify fractions of seconds.
+ When the *timeout* argument is omitted the function blocks until
at least one file descriptor is ready. A time-out value of zero specifies a
poll and never blocks.
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. data:: PIPE_BUF
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. _epoll-objects:
.. method:: epoll.poll(timeout=None, maxevents=-1)
- Wait for events. timeout in seconds (float)
+ Wait for events.
+ If *timeout* is given, it specifies the length of time in seconds
+ (may be non-integer) which the system will wait for events before returning.
.. versionchanged:: 3.5
The function is now retried with a recomputed timeout when interrupted by
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. _poll-objects:
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. _kqueue-objects:
- changelist must be an iterable of kevent objects or ``None``
- max_events must be 0 or a positive integer
- - timeout in seconds (floats possible); the default is ``None``,
+ - timeout in seconds (non-integers are possible); the default is ``None``,
to wait forever
.. versionchanged:: 3.5
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. _kevent-objects:
.. versionadded:: 3.3
-.. function:: setitimer(which, seconds, interval=0.0)
+.. function:: setitimer(which, seconds, interval=0)
Sets given interval timer (one of :const:`signal.ITIMER_REAL`,
:const:`signal.ITIMER_VIRTUAL` or :const:`signal.ITIMER_PROF`) specified
- by *which* to fire after *seconds* (float is accepted, different from
+ by *which* to fire after *seconds* (rounded up to microseconds, different from
:func:`alarm`) and after that every *interval* seconds (if *interval*
is non-zero). The interval timer specified by *which* can be cleared by
setting *seconds* to zero.
:const:`signal.ITIMER_VIRTUAL` sends :const:`SIGVTALRM`,
and :const:`signal.ITIMER_PROF` will deliver :const:`SIGPROF`.
- The old values are returned as a tuple: (delay, interval).
+ The old values are returned as a two-tuple of floats:
+ (``delay``, ``interval``).
Attempting to pass an invalid interval timer will cause an
:exc:`ItimerError`.
.. availability:: Unix.
+ .. versionchanged:: next
+ Accepts any real numbers as *seconds* and *interval*, not only integers
+ or floats.
+
.. function:: getitimer(which)
by a signal not in *sigset* and the signal handler does not raise an
exception (see :pep:`475` for the rationale).
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. _signal-example:
.. function:: setdefaulttimeout(timeout)
- Set the default timeout in seconds (float) for new socket objects. When
+ Set the default timeout in seconds (real number) for new socket objects. When
the socket module is first imported, the default is ``None``. See
:meth:`~socket.settimeout` for possible values and their respective
meanings.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. function:: sethostname(name)
.. method:: socket.settimeout(value)
Set a timeout on blocking socket operations. The *value* argument can be a
- nonnegative floating-point number expressing seconds, or ``None``.
+ nonnegative real number expressing seconds, or ``None``.
If a non-zero value is given, subsequent socket operations will raise a
:exc:`timeout` exception if the timeout period *value* has elapsed before
the operation has completed. If zero is given, the socket is put in
The method no longer toggles :const:`SOCK_NONBLOCK` flag on
:attr:`socket.type`.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. method:: socket.setsockopt(level, optname, value: int)
.. method:: socket.setsockopt(level, optname, value: buffer)
timeout occurs.
When the *timeout* argument is present and not ``None``, it should be a
- floating-point number specifying a timeout for the operation in seconds
+ real number specifying a timeout for the operation in seconds
(or fractions thereof). As :meth:`~Thread.join` always returns ``None``,
you must call :meth:`~Thread.is_alive` after :meth:`~Thread.join` to
decide whether a timeout happened -- if the thread is still alive, the
May raise :exc:`PythonFinalizationError`.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. attribute:: name
A string used for identification purposes only. It has no semantics.
If a call with *blocking* set to ``True`` would block, return ``False``
immediately; otherwise, set the lock to locked and return ``True``.
- When invoked with the floating-point *timeout* argument set to a positive
+ When invoked with the *timeout* argument set to a positive
value, block for at most the number of seconds specified by *timeout*
and as long as the lock cannot be acquired. A *timeout* argument of ``-1``
specifies an unbounded wait. It is forbidden to specify a *timeout*
.. versionchanged:: 3.14
Lock acquisition can now be interrupted by signals on Windows.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. method:: release()
* If no thread owns the lock, acquire the lock and return immediately.
* If another thread owns the lock, block until we are able to acquire
- lock, or *timeout*, if set to a positive float value.
+ lock, or *timeout*, if set to a positive value.
* If the same thread owns the lock, acquire the lock again, and
return immediately. This is the difference between :class:`Lock` and
.. versionchanged:: 3.2
The *timeout* parameter is new.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. method:: release()
occurs. Once awakened or timed out, it re-acquires the lock and returns.
When the *timeout* argument is present and not ``None``, it should be a
- floating-point number specifying a timeout for the operation in seconds
+ real number specifying a timeout for the operation in seconds
(or fractions thereof).
When the underlying lock is an :class:`RLock`, it is not released using
.. versionchanged:: 3.2
The *timeout* parameter is new.
+ .. versionchanged:: next
+ Accepts any real number as *timeout*, not only integer or float.
+
.. method:: release(n=1)
Release a semaphore, incrementing the internal counter by *n*. When it
the internal flag did not become true within the given wait time.
When the timeout argument is present and not ``None``, it should be a
- floating-point number specifying a timeout for the operation in seconds,
+ real number specifying a timeout for the operation in seconds,
or fractions thereof.
.. versionchanged:: 3.1
.. versionadded:: 3.7
-.. function:: clock_settime(clk_id, time: float)
+.. function:: clock_settime(clk_id, time)
Set the time of the specified clock *clk_id*. Currently,
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
.. versionadded:: 3.3
+ .. versionchanged:: next
+ Accepts any real number as *time*, not only integer or float.
+
.. function:: clock_settime_ns(clk_id, time: int)
``asctime(localtime(secs))``. Locale information is not used by
:func:`ctime`.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. function:: get_clock_info(name)
:class:`struct_time` object. See :func:`calendar.timegm` for the inverse of this
function.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. function:: localtime([secs])
:c:func:`gmtime` failure. It's common for this to be restricted to years
between 1970 and 2038.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. function:: mktime(t)
.. function:: sleep(secs)
Suspend execution of the calling thread for the given number of seconds.
- The argument may be a floating-point number to indicate a more precise sleep
- time.
+ The argument may be a non-integer to indicate a more precise sleep time.
If the sleep is interrupted by a signal and no exception is raised by the
signal handler, the sleep is restarted with a recomputed timeout.
.. versionchanged:: 3.13
Raises an auditing event.
+ .. versionchanged:: next
+ Accepts any real number, not only integer or float.
+
.. index::
single: % (percent); datetime format
and ends with a forward slash (``/``).
(Contributed by Serhiy Storchaka in :gh:`134716`.)
+* Functions that take timestamp or timeout arguments now accept any real
+ numbers (such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`),
+ not only integers or floats, although this does not improve precision.
+ (Contributed by Serhiy Storchaka in :gh:`67795`.)
+
New modules
===========
import contextlib
import copy
import decimal
+import fractions
import io
import itertools
import os
expected = time.localtime(ts)
got = self.theclass.fromtimestamp(ts)
self.verify_field_equality(expected, got)
+ got = self.theclass.fromtimestamp(decimal.Decimal(ts))
+ self.verify_field_equality(expected, got)
+ got = self.theclass.fromtimestamp(fractions.Fraction(ts))
+ self.verify_field_equality(expected, got)
def test_fromtimestamp_keyword_arg(self):
import time
with self.assertWarns(DeprecationWarning):
got = self.theclass.utcfromtimestamp(ts)
self.verify_field_equality(expected, got)
+ with self.assertWarns(DeprecationWarning):
+ got = self.theclass.utcfromtimestamp(decimal.Decimal(ts))
+ self.verify_field_equality(expected, got)
+ with self.assertWarns(DeprecationWarning):
+ got = self.theclass.utcfromtimestamp(fractions.Fraction(ts))
+ self.verify_field_equality(expected, got)
# Run with US-style DST rules: DST begins 2 a.m. on second Sunday in
# March (M3.2.0) and ends 2 a.m. on first Sunday in November (M11.1.0).
self.assertEqual(t.second, 0)
self.assertEqual(t.microsecond, 7812)
+ @support.run_with_tz('MSK-03') # Something east of Greenwich
+ def test_microsecond_rounding_decimal(self):
+ D = decimal.Decimal
+ def utcfromtimestamp(*args, **kwargs):
+ with self.assertWarns(DeprecationWarning):
+ return self.theclass.utcfromtimestamp(*args, **kwargs)
+
+ for fts in [self.theclass.fromtimestamp,
+ utcfromtimestamp]:
+ zero = fts(D(0))
+ self.assertEqual(zero.second, 0)
+ self.assertEqual(zero.microsecond, 0)
+ one = fts(D('0.000_001'))
+ try:
+ minus_one = fts(D('-0.000_001'))
+ except OSError:
+ # localtime(-1) and gmtime(-1) is not supported on Windows
+ pass
+ else:
+ self.assertEqual(minus_one.second, 59)
+ self.assertEqual(minus_one.microsecond, 999_999)
+
+ t = fts(D('-0.000_000_1'))
+ self.assertEqual(t, zero)
+ t = fts(D('-0.000_000_9'))
+ self.assertEqual(t, minus_one)
+ t = fts(D(-1)/2**7)
+ self.assertEqual(t.second, 59)
+ self.assertEqual(t.microsecond, 992188)
+
+ t = fts(D('0.000_000_1'))
+ self.assertEqual(t, zero)
+ t = fts(D('0.000_000_5'))
+ self.assertEqual(t, zero)
+ t = fts(D('0.000_000_500_000_000_000_000_1'))
+ self.assertEqual(t, one)
+ t = fts(D('0.000_000_9'))
+ self.assertEqual(t, one)
+ t = fts(D('0.999_999_499_999_999_9'))
+ self.assertEqual(t.second, 0)
+ self.assertEqual(t.microsecond, 999_999)
+ t = fts(D('0.999_999_5'))
+ self.assertEqual(t.second, 1)
+ self.assertEqual(t.microsecond, 0)
+ t = fts(D('0.999_999_9'))
+ self.assertEqual(t.second, 1)
+ self.assertEqual(t.microsecond, 0)
+ t = fts(D(1)/2**7)
+ self.assertEqual(t.second, 0)
+ self.assertEqual(t.microsecond, 7812)
+
+ @support.run_with_tz('MSK-03') # Something east of Greenwich
+ def test_microsecond_rounding_fraction(self):
+ F = fractions.Fraction
+ def utcfromtimestamp(*args, **kwargs):
+ with self.assertWarns(DeprecationWarning):
+ return self.theclass.utcfromtimestamp(*args, **kwargs)
+
+ for fts in [self.theclass.fromtimestamp,
+ utcfromtimestamp]:
+ zero = fts(F(0))
+ self.assertEqual(zero.second, 0)
+ self.assertEqual(zero.microsecond, 0)
+ one = fts(F(1, 1_000_000))
+ try:
+ minus_one = fts(F(-1, 1_000_000))
+ except OSError:
+ # localtime(-1) and gmtime(-1) is not supported on Windows
+ pass
+ else:
+ self.assertEqual(minus_one.second, 59)
+ self.assertEqual(minus_one.microsecond, 999_999)
+
+ t = fts(F(-1, 10_000_000))
+ self.assertEqual(t, zero)
+ t = fts(F(-9, 10_000_000))
+ self.assertEqual(t, minus_one)
+ t = fts(F(-1, 2**7))
+ self.assertEqual(t.second, 59)
+ self.assertEqual(t.microsecond, 992188)
+
+ t = fts(F(1, 10_000_000))
+ self.assertEqual(t, zero)
+ t = fts(F(5, 10_000_000))
+ self.assertEqual(t, zero)
+ t = fts(F(5_000_000_000, 9_999_999_999_999_999))
+ self.assertEqual(t, one)
+ t = fts(F(9, 10_000_000))
+ self.assertEqual(t, one)
+ t = fts(F(9_999_995_000_000_000, 10_000_000_000_000_001))
+ self.assertEqual(t.second, 0)
+ self.assertEqual(t.microsecond, 999_999)
+ t = fts(F(9_999_995, 10_000_000))
+ self.assertEqual(t.second, 1)
+ self.assertEqual(t.microsecond, 0)
+ t = fts(F(9_999_999, 10_000_000))
+ self.assertEqual(t.second, 1)
+ self.assertEqual(t.microsecond, 0)
+ t = fts(F(1, 2**7))
+ self.assertEqual(t.second, 0)
+ self.assertEqual(t.microsecond, 7812)
+
def test_timestamp_limits(self):
with self.subTest("minimum UTC"):
min_dt = self.theclass.min.replace(tzinfo=timezone.utc)
# issue, os.utime() rounds towards minus infinity.
return (ns * 1e-9) + 0.5e-9
+ @staticmethod
+ def ns_to_sec_decimal(ns):
+ # Convert a number of nanosecond (int) to a number of seconds (Decimal).
+ # Round towards infinity by adding 0.5 nanosecond to avoid rounding
+ # issue, os.utime() rounds towards minus infinity.
+ return decimal.Decimal('1e-9') * ns + decimal.Decimal('0.5e-9')
+
+ @staticmethod
+ def ns_to_sec_fraction(ns):
+ # Convert a number of nanosecond (int) to a number of seconds (Fraction).
+ # Round towards infinity by adding 0.5 nanosecond to avoid rounding
+ # issue, os.utime() rounds towards minus infinity.
+ return fractions.Fraction(ns, 10**9) + fractions.Fraction(1, 2*10**9)
+
def test_utime_by_indexed(self):
# pass times as floating-point seconds as the second indexed parameter
def set_time(filename, ns):
os.utime(filename, times=(atime, mtime))
self._test_utime(set_time)
+ def test_utime_decimal(self):
+ # pass times as Decimal seconds
+ def set_time(filename, ns):
+ atime_ns, mtime_ns = ns
+ atime = self.ns_to_sec_decimal(atime_ns)
+ mtime = self.ns_to_sec_decimal(mtime_ns)
+ os.utime(filename, (atime, mtime))
+ self._test_utime(set_time)
+
+ def test_utime_fraction(self):
+ # pass times as Fraction seconds
+ def set_time(filename, ns):
+ atime_ns, mtime_ns = ns
+ atime = self.ns_to_sec_fraction(atime_ns)
+ mtime = self.ns_to_sec_fraction(mtime_ns)
+ os.utime(filename, (atime, mtime))
+ self._test_utime(set_time)
+
@unittest.skipUnless(os.utime in os.supports_follow_symlinks,
"follow_symlinks support for utime required "
"for this test.")
import _thread as thread
import array
import contextlib
+import decimal
import errno
+import fractions
import gc
import io
import itertools
self.assertEqual(s.gettimeout(), None)
# Set the default timeout to 10, and see if it propagates
- with socket_setdefaulttimeout(10):
- self.assertEqual(socket.getdefaulttimeout(), 10)
+ with socket_setdefaulttimeout(10.125):
+ self.assertEqual(socket.getdefaulttimeout(), 10.125)
with socket.socket() as sock:
- self.assertEqual(sock.gettimeout(), 10)
+ self.assertEqual(sock.gettimeout(), 10.125)
+
+ socket.setdefaulttimeout(decimal.Decimal('11.125'))
+ self.assertEqual(socket.getdefaulttimeout(), 11.125)
+ with socket.socket() as sock:
+ self.assertEqual(sock.gettimeout(), 11.125)
+
+ socket.setdefaulttimeout(fractions.Fraction(97, 8))
+ self.assertEqual(socket.getdefaulttimeout(), 12.125)
+ with socket.socket() as sock:
+ self.assertEqual(sock.gettimeout(), 12.125)
# Reset the default timeout to None, and see if it propagates
socket.setdefaulttimeout(None)
from test.support import warnings_helper
import decimal
import enum
+import fractions
import math
import platform
import sys
# Improved exception #81267
with self.assertRaises(TypeError) as errmsg:
time.sleep([])
- self.assertIn("integer or float", str(errmsg.exception))
+ self.assertIn("real number", str(errmsg.exception))
def test_sleep(self):
- for value in [-0.0, 0, 0.0, 1e-100, 1e-9, 1e-6, 1, 1.2]:
+ for value in [-0.0, 0, 0.0, 1e-100, 1e-9, 1e-6, 1, 1.2,
+ decimal.Decimal('0.02'),
+ fractions.Fraction(1, 50)]:
with self.subTest(value=value):
time.sleep(value)
--- /dev/null
+Functions that take timestamp or timeout arguments now accept any real
+numbers (such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`),
+not only integers or floats, although this does not improve precision.
"gotten from a fileno() method call on one of those.\n"
"\n"
"The optional 4th argument specifies a timeout in seconds; it may be\n"
-"a floating-point number to specify fractions of seconds. If it is absent\n"
+"a non-integer to specify fractions of seconds. If it is absent\n"
"or None, the call will never time out.\n"
"\n"
"The return value is a tuple of three lists corresponding to the first three\n"
"Wait for events on the epoll file descriptor.\n"
"\n"
" timeout\n"
-" the maximum time to wait in seconds (as float);\n"
+" the maximum time to wait in seconds (with fractions);\n"
" a timeout of None or -1 makes poll wait indefinitely\n"
" maxevents\n"
" the maximum number of events returned; -1 means no limit\n"
" The maximum number of events that the kernel will return.\n"
" timeout\n"
" The maximum time to wait in seconds, or else None to wait forever.\n"
-" This accepts floats for smaller timeouts, too.");
+" This accepts non-integers for smaller timeouts, too.");
#define SELECT_KQUEUE_CONTROL_METHODDEF \
{"control", _PyCFunction_CAST(select_kqueue_control), METH_FASTCALL, select_kqueue_control__doc__},
#ifndef SELECT_KQUEUE_CONTROL_METHODDEF
#define SELECT_KQUEUE_CONTROL_METHODDEF
#endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */
-/*[clinic end generated code: output=2a66dd831f22c696 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ae54d65938513132 input=a9049054013a1b77]*/
"\n"
"Like sigwaitinfo(), but with a timeout.\n"
"\n"
-"The timeout is specified in seconds, with floating-point numbers allowed.");
+"The timeout is specified in seconds, rounded up to nanoseconds.");
#define SIGNAL_SIGTIMEDWAIT_METHODDEF \
{"sigtimedwait", _PyCFunction_CAST(signal_sigtimedwait), METH_FASTCALL, signal_sigtimedwait__doc__},
#ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF
#define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF
#endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */
-/*[clinic end generated code: output=37ae8ebeae4178fa input=a9049054013a1b77]*/
+/*[clinic end generated code: output=42e20d118435d7fa input=a9049054013a1b77]*/
if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
PyErr_SetString(PyExc_TypeError,
"utime: 'times' must be either"
- " a tuple of two ints or None");
+ " a tuple of two numbers or None");
return NULL;
}
utime.now = 0;
gotten from a fileno() method call on one of those.
The optional 4th argument specifies a timeout in seconds; it may be
-a floating-point number to specify fractions of seconds. If it is absent
+a non-integer to specify fractions of seconds. If it is absent
or None, the call will never time out.
The return value is a tuple of three lists corresponding to the first three
static PyObject *
select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist,
PyObject *xlist, PyObject *timeout_obj)
-/*[clinic end generated code: output=2b3cfa824f7ae4cf input=df20779a9c2f5c1e]*/
+/*[clinic end generated code: output=2b3cfa824f7ae4cf input=b0403de75cd11cc1]*/
{
#ifdef SELECT_USES_HEAP
pylist *rfd2obj, *wfd2obj, *efd2obj;
if (_PyTime_FromSecondsObject(&timeout, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_SetString(PyExc_TypeError,
- "timeout must be a float or None");
+ PyErr_Format(PyExc_TypeError,
+ "timeout must be a real number or None, not %T",
+ timeout_obj);
}
return NULL;
}
if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_SetString(PyExc_TypeError,
- "timeout must be an integer or None");
+ PyErr_Format(PyExc_TypeError,
+ "timeout must be a real number or None, not %T",
+ timeout_obj);
}
return NULL;
}
if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_SetString(PyExc_TypeError,
- "timeout must be an integer or None");
+ PyErr_Format(PyExc_TypeError,
+ "timeout must be a real number or None, not %T",
+ timeout_obj);
}
return NULL;
}
select.epoll.poll
timeout as timeout_obj: object = None
- the maximum time to wait in seconds (as float);
+ the maximum time to wait in seconds (with fractions);
a timeout of None or -1 makes poll wait indefinitely
maxevents: int = -1
the maximum number of events returned; -1 means no limit
static PyObject *
select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj,
int maxevents)
-/*[clinic end generated code: output=e02d121a20246c6c input=33d34a5ea430fd5b]*/
+/*[clinic end generated code: output=e02d121a20246c6c input=deafa7f04a60ebe0]*/
{
int nfds, i;
PyObject *elist = NULL, *etuple = NULL;
if (_PyTime_FromSecondsObject(&timeout, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_SetString(PyExc_TypeError,
- "timeout must be an integer or None");
+ PyErr_Format(PyExc_TypeError,
+ "timeout must be a real number or None, not %T",
+ timeout_obj);
}
return NULL;
}
The maximum number of events that the kernel will return.
timeout as otimeout: object = None
The maximum time to wait in seconds, or else None to wait forever.
- This accepts floats for smaller timeouts, too.
+ This accepts non-integers for smaller timeouts, too.
/
Calls the kernel kevent function.
static PyObject *
select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist,
int maxevents, PyObject *otimeout)
-/*[clinic end generated code: output=81324ff5130db7ae input=59c4e30811209c47]*/
+/*[clinic end generated code: output=81324ff5130db7ae input=be969d2bc6f84205]*/
{
int gotevents = 0;
int nchanges = 0;
if (_PyTime_FromSecondsObject(&timeout,
otimeout, _PyTime_ROUND_TIMEOUT) < 0) {
PyErr_Format(PyExc_TypeError,
- "timeout argument must be a number "
- "or None, got %.200s",
- _PyType_Name(Py_TYPE(otimeout)));
+ "timeout must be a real number or None, not %T",
+ otimeout);
return NULL;
}
Like sigwaitinfo(), but with a timeout.
-The timeout is specified in seconds, with floating-point numbers allowed.
+The timeout is specified in seconds, rounded up to nanoseconds.
[clinic start generated code]*/
static PyObject *
signal_sigtimedwait_impl(PyObject *module, sigset_t sigset,
PyObject *timeout_obj)
-/*[clinic end generated code: output=59c8971e8ae18a64 input=955773219c1596cd]*/
+/*[clinic end generated code: output=59c8971e8ae18a64 input=f89af57d645e48e0]*/
{
PyTime_t timeout;
if (_PyTime_FromSecondsObject(&timeout,
PyDoc_STRVAR(setdefaulttimeout_doc,
"setdefaulttimeout(timeout)\n\
\n\
-Set the default timeout in seconds (float) for new socket objects.\n\
+Set the default timeout in seconds (real number) for new socket objects.\n\
A value of None indicates that new socket objects have no timeout.\n\
When the socket module is first imported, the default is None.");
{
assert(denominator >= 1);
- if (PyFloat_Check(obj)) {
+ if (PyIndex_Check(obj)) {
+ *sec = _PyLong_AsTime_t(obj);
+ *numerator = 0;
+ if (*sec == (time_t)-1 && PyErr_Occurred()) {
+ return -1;
+ }
+ return 0;
+ }
+ else {
double d = PyFloat_AsDouble(obj);
+ if (d == -1 && PyErr_Occurred()) {
+ *numerator = 0;
+ return -1;
+ }
if (isnan(d)) {
*numerator = 0;
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
return pytime_double_to_denominator(d, sec, numerator,
denominator, round);
}
- else {
- *sec = _PyLong_AsTime_t(obj);
- *numerator = 0;
- if (*sec == (time_t)-1 && PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Format(PyExc_TypeError,
- "argument must be int or float, not %T", obj);
- }
- return -1;
- }
- return 0;
- }
}
int
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
{
- if (PyFloat_Check(obj)) {
+ if (PyIndex_Check(obj)) {
+ *sec = _PyLong_AsTime_t(obj);
+ if (*sec == (time_t)-1 && PyErr_Occurred()) {
+ return -1;
+ }
+ return 0;
+ }
+ else {
double intpart;
/* volatile avoids optimization changing how numbers are rounded */
volatile double d;
d = PyFloat_AsDouble(obj);
+ if (d == -1 && PyErr_Occurred()) {
+ return -1;
+ }
if (isnan(d)) {
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
return -1;
*sec = (time_t)intpart;
return 0;
}
- else {
- *sec = _PyLong_AsTime_t(obj);
- if (*sec == (time_t)-1 && PyErr_Occurred()) {
- return -1;
- }
- return 0;
- }
}
pytime_from_object(PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
long unit_to_ns)
{
- if (PyFloat_Check(obj)) {
+ if (PyIndex_Check(obj)) {
+ long long sec = PyLong_AsLongLong(obj);
+ if (sec == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
+ pytime_overflow();
+ }
+ return -1;
+ }
+
+ static_assert(sizeof(long long) <= sizeof(PyTime_t),
+ "PyTime_t is smaller than long long");
+ PyTime_t ns = (PyTime_t)sec;
+ if (pytime_mul(&ns, unit_to_ns) < 0) {
+ pytime_overflow();
+ return -1;
+ }
+
+ *tp = ns;
+ return 0;
+ }
+ else {
double d;
d = PyFloat_AsDouble(obj);
+ if (d == -1 && PyErr_Occurred()) {
+ return -1;
+ }
if (isnan(d)) {
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
return -1;
}
return pytime_from_double(tp, d, round, unit_to_ns);
}
-
- long long sec = PyLong_AsLongLong(obj);
- if (sec == -1 && PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
- pytime_overflow();
- }
- else if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Format(PyExc_TypeError,
- "'%T' object cannot be interpreted as an integer or float",
- obj);
- }
- return -1;
- }
-
- static_assert(sizeof(long long) <= sizeof(PyTime_t),
- "PyTime_t is smaller than long long");
- PyTime_t ns = (PyTime_t)sec;
- if (pytime_mul(&ns, unit_to_ns) < 0) {
- pytime_overflow();
- return -1;
- }
-
- *tp = ns;
- return 0;
}