mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Backout f8409b3d6449: the PEP 410 is not accepted yet
This commit is contained in:
parent
72476eae5f
commit
4195b5caea
9 changed files with 175 additions and 815 deletions
|
@ -808,16 +808,13 @@ as internal buffering of data.
|
||||||
Availability: Unix.
|
Availability: Unix.
|
||||||
|
|
||||||
|
|
||||||
.. function:: fstat(fd, timestamp=None)
|
.. function:: fstat(fd)
|
||||||
|
|
||||||
Return status for file descriptor *fd*, like :func:`~os.stat`.
|
Return status for file descriptor *fd*, like :func:`~os.stat`.
|
||||||
|
|
||||||
Availability: Unix, Windows.
|
Availability: Unix, Windows.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. function:: fstatat(dirfd, path, flags=0)
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
.. function:: fstatat(dirfd, path, flags=0, timestamp="float")
|
|
||||||
|
|
||||||
Like :func:`stat` but if *path* is relative, it is taken as relative to *dirfd*.
|
Like :func:`stat` but if *path* is relative, it is taken as relative to *dirfd*.
|
||||||
*flags* is optional and may be 0 or :data:`AT_SYMLINK_NOFOLLOW`.
|
*flags* is optional and may be 0 or :data:`AT_SYMLINK_NOFOLLOW`.
|
||||||
|
@ -1699,7 +1696,7 @@ Files and Directories
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. function:: lstat(path, timestamp=None)
|
.. function:: lstat(path)
|
||||||
|
|
||||||
Perform the equivalent of an :c:func:`lstat` system call on the given path.
|
Perform the equivalent of an :c:func:`lstat` system call on the given path.
|
||||||
Similar to :func:`~os.stat`, but does not follow symbolic links. On
|
Similar to :func:`~os.stat`, but does not follow symbolic links. On
|
||||||
|
@ -1709,9 +1706,6 @@ Files and Directories
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
Added support for Windows 6.0 (Vista) symbolic links.
|
Added support for Windows 6.0 (Vista) symbolic links.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
|
||||||
The *timestamp* argument was added.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: lutimes(path[, times])
|
.. function:: lutimes(path[, times])
|
||||||
|
|
||||||
|
@ -1975,7 +1969,7 @@ Files and Directories
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. function:: stat(path, timestamp=None)
|
.. function:: stat(path)
|
||||||
|
|
||||||
Perform the equivalent of a :c:func:`stat` system call on the given path.
|
Perform the equivalent of a :c:func:`stat` system call on the given path.
|
||||||
(This function follows symlinks; to stat a symlink use :func:`lstat`.)
|
(This function follows symlinks; to stat a symlink use :func:`lstat`.)
|
||||||
|
@ -1995,11 +1989,6 @@ Files and Directories
|
||||||
* :attr:`st_ctime` - platform dependent; time of most recent metadata change on
|
* :attr:`st_ctime` - platform dependent; time of most recent metadata change on
|
||||||
Unix, or the time of creation on Windows)
|
Unix, or the time of creation on Windows)
|
||||||
|
|
||||||
:attr:`st_atime`, :attr:`st_mtime` and :attr:`st_ctime` are :class:`float`
|
|
||||||
by default, or :class:`int` if :func:`os.stat_float_times` is ``False``. Set
|
|
||||||
the *timestamp* argument to get another :ref:`timestamp type
|
|
||||||
<timestamp-types>`.
|
|
||||||
|
|
||||||
On some Unix systems (such as Linux), the following attributes may also be
|
On some Unix systems (such as Linux), the following attributes may also be
|
||||||
available:
|
available:
|
||||||
|
|
||||||
|
@ -2055,9 +2044,6 @@ Files and Directories
|
||||||
|
|
||||||
Availability: Unix, Windows.
|
Availability: Unix, Windows.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: stat_float_times([newvalue])
|
.. function:: stat_float_times([newvalue])
|
||||||
|
|
||||||
|
@ -2083,9 +2069,6 @@ Files and Directories
|
||||||
are processed, this application should turn the feature off until the library
|
are processed, this application should turn the feature off until the library
|
||||||
has been corrected.
|
has been corrected.
|
||||||
|
|
||||||
.. deprecated:: 3.3
|
|
||||||
Use *timestamp* argument of stat functions instead.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: statvfs(path)
|
.. function:: statvfs(path)
|
||||||
|
|
||||||
|
@ -2876,39 +2859,27 @@ written in Python, such as a mail server's external command delivery program.
|
||||||
with :const:`P_NOWAIT` return suitable process handles.
|
with :const:`P_NOWAIT` return suitable process handles.
|
||||||
|
|
||||||
|
|
||||||
.. function:: wait3(options[, timestamp=float])
|
.. function:: wait3([options])
|
||||||
|
|
||||||
Similar to :func:`waitpid`, except no process id argument is given and a
|
Similar to :func:`waitpid`, except no process id argument is given and a
|
||||||
3-element tuple containing the child's process id, exit status indication, and
|
3-element tuple containing the child's process id, exit status indication, and
|
||||||
resource usage information is returned. Refer to :mod:`resource`.\
|
resource usage information is returned. Refer to :mod:`resource`.\
|
||||||
:func:`getrusage` for details on resource usage information. The option
|
:func:`getrusage` for details on resource usage information. The option
|
||||||
argument is the same as that provided to :func:`waitpid` and :func:`wait4`.
|
argument is the same as that provided to :func:`waitpid` and :func:`wait4`.
|
||||||
:attr:`ru_utime` and :attr:`ru_stime` attributes of the resource usage are
|
|
||||||
:class:`float` by default, set the *timestamp* argument to get another
|
|
||||||
:ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
Availability: Unix.
|
Availability: Unix.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
|
.. function:: wait4(pid, options)
|
||||||
.. function:: wait4(pid, options[, timestamp=float])
|
|
||||||
|
|
||||||
Similar to :func:`waitpid`, except a 3-element tuple, containing the child's
|
Similar to :func:`waitpid`, except a 3-element tuple, containing the child's
|
||||||
process id, exit status indication, and resource usage information is returned.
|
process id, exit status indication, and resource usage information is returned.
|
||||||
Refer to :mod:`resource`.\ :func:`getrusage` for details on resource usage
|
Refer to :mod:`resource`.\ :func:`getrusage` for details on resource usage
|
||||||
information. The arguments to :func:`wait4` are the same as those provided to
|
information. The arguments to :func:`wait4` are the same as those provided to
|
||||||
:func:`waitpid`.
|
:func:`waitpid`.
|
||||||
:attr:`ru_utime` and :attr:`ru_stime` attributes of the resource usage are
|
|
||||||
:class:`float` by default, set the *timestamp* argument to get another
|
|
||||||
:ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
Availability: Unix.
|
Availability: Unix.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: WNOHANG
|
.. data:: WNOHANG
|
||||||
|
|
||||||
|
|
|
@ -95,14 +95,6 @@ An explanation of some terminology and conventions is in order.
|
||||||
| local time | | |
|
| local time | | |
|
||||||
+-------------------------+-------------------------+-------------------------+
|
+-------------------------+-------------------------+-------------------------+
|
||||||
|
|
||||||
.. _timestamp-types:
|
|
||||||
|
|
||||||
* Python supports the following timestamp types:
|
|
||||||
|
|
||||||
* :class:`int`
|
|
||||||
* :class:`float`
|
|
||||||
* :class:`decimal.Decimal`
|
|
||||||
|
|
||||||
|
|
||||||
The module defines the following functions and data items:
|
The module defines the following functions and data items:
|
||||||
|
|
||||||
|
@ -127,7 +119,7 @@ The module defines the following functions and data items:
|
||||||
trailing newline.
|
trailing newline.
|
||||||
|
|
||||||
|
|
||||||
.. function:: clock(timestamp=float)
|
.. function:: clock()
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: CPU time
|
single: CPU time
|
||||||
|
@ -144,27 +136,16 @@ The module defines the following functions and data items:
|
||||||
:c:func:`QueryPerformanceCounter`. The resolution is typically better than one
|
:c:func:`QueryPerformanceCounter`. The resolution is typically better than one
|
||||||
microsecond.
|
microsecond.
|
||||||
|
|
||||||
Return as a floating point number by default, set the *timestamp* argument
|
|
||||||
to get another :ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. function:: clock_getres(clk_id)
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: clock_getres(clk_id, timestamp=float)
|
|
||||||
|
|
||||||
Return the resolution (precision) of the specified clock *clk_id*.
|
Return the resolution (precision) of the specified clock *clk_id*.
|
||||||
Return a floating point number by default, set the *timestamp* argument to
|
|
||||||
get another :ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
.. function:: clock_gettime(clk_id, timestamp=float)
|
.. function:: clock_gettime(clk_id)
|
||||||
|
|
||||||
Return the time of the specified clock *clk_id*.
|
Return the time of the specified clock *clk_id*.
|
||||||
Return a floating point number by default, set the *timestamp* argument to
|
|
||||||
get another :ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
@ -233,22 +214,19 @@ The module defines the following functions and data items:
|
||||||
flag is set to ``1`` when DST applies to the given time.
|
flag is set to ``1`` when DST applies to the given time.
|
||||||
|
|
||||||
|
|
||||||
.. function:: mktime(t, timestamp=float)
|
.. function:: mktime(t)
|
||||||
|
|
||||||
This is the inverse function of :func:`localtime`. Its argument is the
|
This is the inverse function of :func:`localtime`. Its argument is the
|
||||||
:class:`struct_time` or full 9-tuple (since the dst flag is needed; use ``-1``
|
:class:`struct_time` or full 9-tuple (since the dst flag is needed; use ``-1``
|
||||||
as the dst flag if it is unknown) which expresses the time in *local* time, not
|
as the dst flag if it is unknown) which expresses the time in *local* time, not
|
||||||
It returns a floating point number by default, for compatibility with
|
UTC. It returns a floating point number, for compatibility with :func:`time`.
|
||||||
:func:`time`, set the *timestamp* argument to get another :ref:`timestamp
|
|
||||||
type <timestamp-types>`.
|
|
||||||
|
|
||||||
If the input value cannot be represented as a valid time, either
|
If the input value cannot be represented as a valid time, either
|
||||||
:exc:`OverflowError` or :exc:`ValueError` will be raised (which depends on
|
:exc:`OverflowError` or :exc:`ValueError` will be raised (which depends on
|
||||||
whether the invalid value is caught by Python or the underlying C libraries).
|
whether the invalid value is caught by Python or the underlying C libraries).
|
||||||
The earliest date for which it can generate a time is platform-dependent.
|
The earliest date for which it can generate a time is platform-dependent.
|
||||||
|
|
||||||
|
|
||||||
.. function:: monotonic(timestamp=float)
|
.. function:: monotonic()
|
||||||
|
|
||||||
Monotonic clock. The reference point of the returned value is undefined so
|
Monotonic clock. The reference point of the returned value is undefined so
|
||||||
only the difference of consecutive calls is valid.
|
only the difference of consecutive calls is valid.
|
||||||
|
@ -462,20 +440,15 @@ The module defines the following functions and data items:
|
||||||
:exc:`TypeError` is raised.
|
:exc:`TypeError` is raised.
|
||||||
|
|
||||||
|
|
||||||
.. function:: time(timestamp=float)
|
.. function:: time()
|
||||||
|
|
||||||
Return the time expressed in seconds since the epoch in UTC. Return a
|
Return the time as a floating point number expressed in seconds since the epoch,
|
||||||
floating point number by default, set the *timestamp* argument to get
|
in UTC. Note that even though the time is always returned as a floating point
|
||||||
another :ref:`timestamp type <timestamp-types>`.
|
|
||||||
Note that even though the time is always returned as a floating point
|
|
||||||
number, not all systems provide time with a better precision than 1 second.
|
number, not all systems provide time with a better precision than 1 second.
|
||||||
While this function normally returns non-decreasing values, it can return a
|
While this function normally returns non-decreasing values, it can return a
|
||||||
lower value than a previous call if the system clock has been set back between
|
lower value than a previous call if the system clock has been set back between
|
||||||
the two calls.
|
the two calls.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
|
||||||
Added the *timestamp* argument.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: timezone
|
.. data:: timezone
|
||||||
|
|
||||||
|
@ -573,16 +546,13 @@ The module defines the following functions and data items:
|
||||||
('EET', 'EEST')
|
('EET', 'EEST')
|
||||||
|
|
||||||
|
|
||||||
.. function:: wallclock(timestamp=float)
|
.. function:: wallclock()
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: Wallclock
|
single: Wallclock
|
||||||
single: benchmarking
|
single: benchmarking
|
||||||
|
|
||||||
Return the current time in fractions of a second to the system's best ability.
|
Return the current time in fractions of a second to the system's best ability.
|
||||||
Return a floating point number by default, set the *timestamp* argument to
|
|
||||||
get another :ref:`timestamp type <timestamp-types>`.
|
|
||||||
|
|
||||||
Use this when the most accurate representation of wall-clock is required, i.e.
|
Use this when the most accurate representation of wall-clock is required, i.e.
|
||||||
when "processor time" is inappropriate. The reference point of the returned
|
when "processor time" is inappropriate. The reference point of the returned
|
||||||
value is undefined so only the difference of consecutive calls is valid.
|
value is undefined so only the difference of consecutive calls is valid.
|
||||||
|
|
|
@ -270,42 +270,6 @@ new, more precise information::
|
||||||
'<function C.D.meth at 0x7f46b9fe31e0>'
|
'<function C.D.meth at 0x7f46b9fe31e0>'
|
||||||
|
|
||||||
|
|
||||||
PEP 410: Use decimal.Decimal type for timestamps
|
|
||||||
================================================
|
|
||||||
|
|
||||||
:pep:`410` - Use decimal.Decimal type for timestamps
|
|
||||||
PEP written and implemented by Victor Stinner.
|
|
||||||
|
|
||||||
The following functions have a new optional *timestamp* argument to get a
|
|
||||||
timestamp as a :class:`decimal.Decimal` instead of :class:`int` or
|
|
||||||
:class:`float`:
|
|
||||||
|
|
||||||
* :mod:`time` module: :func:`~time.clock`, :func:`~time.clock_gettime`,
|
|
||||||
:func:`~time.clock_getres`, :func:`~time.monotonic`, :func:`~time.time` and
|
|
||||||
:func:`~time.wallclock`
|
|
||||||
* :mod:`os` module: :func:`~os.fstat`, :func:`~os.fstatat`, :func:`~os.lstat`
|
|
||||||
and :func:`~os.stat` (``st_atime``, ``st_ctime`` and ``st_mtime`` fields of
|
|
||||||
the stat structure)
|
|
||||||
|
|
||||||
:class:`decimal.Decimal` supports a resolution of a nanosecond (10^-9)
|
|
||||||
resolution, whereas :class:`float` has only a resolution of a microsecond
|
|
||||||
(10^-6) in common cases. See the list of available :ref:`timestamp types
|
|
||||||
<timestamp-types>`.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
>>> import decimal, time
|
|
||||||
>>> time.time()
|
|
||||||
1328006975.681211
|
|
||||||
>>> time.time(timestamp=int)
|
|
||||||
1328006979
|
|
||||||
>>> time.time(timestamp=decimal.Decimal)
|
|
||||||
Decimal('1328006983.761119')
|
|
||||||
|
|
||||||
:func:`os.stat_float_times` has been deprecated, use *timestamp* argument of
|
|
||||||
`os.stat` instead.
|
|
||||||
|
|
||||||
|
|
||||||
Other Language Changes
|
Other Language Changes
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
#ifndef Py_PYTIME_H
|
#ifndef Py_PYTIME_H
|
||||||
#define Py_PYTIME_H
|
#define Py_PYTIME_H
|
||||||
|
|
||||||
#include "pyport.h"
|
#include "pyconfig.h" /* include for defines */
|
||||||
#include "object.h"
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Symbols and macros to supply platform-independent interfaces to time related
|
Symbols and macros to supply platform-independent interfaces to time related
|
||||||
|
@ -38,31 +37,6 @@ do { \
|
||||||
((tv_end.tv_sec - tv_start.tv_sec) + \
|
((tv_end.tv_sec - tv_start.tv_sec) + \
|
||||||
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
||||||
|
|
||||||
#if defined(HAVE_LONG_LONG)
|
|
||||||
typedef unsigned PY_LONG_LONG _PyTime_fraction_t;
|
|
||||||
#else
|
|
||||||
typedef size_t _PyTime_fraction_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* timestamp = seconds + numerator / denominator */
|
|
||||||
time_t seconds;
|
|
||||||
_PyTime_fraction_t numerator;
|
|
||||||
/* denominator cannot be zero */
|
|
||||||
_PyTime_fraction_t denominator;
|
|
||||||
/* the timestamp resolution is 1/divisor */
|
|
||||||
} _PyTime_t;
|
|
||||||
|
|
||||||
/* Similar to POSIX gettimeofday. If system gettimeofday
|
|
||||||
fails or is not available, fall back to lower resolution clocks. */
|
|
||||||
PyAPI_FUNC(void) _PyTime_get(_PyTime_t *tp);
|
|
||||||
|
|
||||||
/* Convert a timestamp structure to the specified timestamp type.
|
|
||||||
|
|
||||||
Raise a ValueError if the timestamp type is unknown. */
|
|
||||||
PyAPI_FUNC(PyObject*) _PyTime_Convert(_PyTime_t *ts, PyObject *timestamp);
|
|
||||||
|
|
||||||
/* Dummy to force linking. */
|
/* Dummy to force linking. */
|
||||||
PyAPI_FUNC(void) _PyTime_Init(void);
|
PyAPI_FUNC(void) _PyTime_Init(void);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# does add tests for a few functions which have been determined to be more
|
# does add tests for a few functions which have been determined to be more
|
||||||
# portable than they had been thought to be.
|
# portable than they had been thought to be.
|
||||||
|
|
||||||
import decimal
|
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
import unittest
|
import unittest
|
||||||
|
@ -239,36 +238,6 @@ class StatAttributeTests(unittest.TestCase):
|
||||||
warnings.simplefilter("ignore", DeprecationWarning)
|
warnings.simplefilter("ignore", DeprecationWarning)
|
||||||
self.check_stat_attributes(fname)
|
self.check_stat_attributes(fname)
|
||||||
|
|
||||||
def test_stat_timestamp(self):
|
|
||||||
# test deprecation
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("error", DeprecationWarning)
|
|
||||||
self.assertRaises(DeprecationWarning, os.stat_float_times, False)
|
|
||||||
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore", DeprecationWarning)
|
|
||||||
old_value = os.stat_float_times()
|
|
||||||
try:
|
|
||||||
# test invalid timestamp types
|
|
||||||
self.assertRaises(ValueError, os.stat, self.fname,
|
|
||||||
timestamp="abc")
|
|
||||||
self.assertRaises(ValueError, os.stat, self.fname,
|
|
||||||
timestamp=decimal.Context)
|
|
||||||
|
|
||||||
for float_times in (False, True):
|
|
||||||
os.stat_float_times(float_times)
|
|
||||||
t = os.stat(self.fname).st_mtime
|
|
||||||
if float_times:
|
|
||||||
self.assertIsInstance(t, float)
|
|
||||||
else:
|
|
||||||
self.assertIsInstance(t, int)
|
|
||||||
|
|
||||||
for type in (int, float, decimal.Decimal):
|
|
||||||
t = os.stat(self.fname, timestamp=type).st_mtime
|
|
||||||
self.assertIsInstance(t, type)
|
|
||||||
finally:
|
|
||||||
os.stat_float_times(old_value)
|
|
||||||
|
|
||||||
def test_statvfs_attributes(self):
|
def test_statvfs_attributes(self):
|
||||||
if not hasattr(os, "statvfs"):
|
if not hasattr(os, "statvfs"):
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import locale
|
|
||||||
import platform
|
|
||||||
import sys
|
|
||||||
import sysconfig
|
|
||||||
from test import support
|
from test import support
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
import locale
|
||||||
|
import sysconfig
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
|
|
||||||
# Max year is only limited by the size of C int.
|
# Max year is only limited by the size of C int.
|
||||||
SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
|
SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
|
||||||
|
@ -345,31 +345,6 @@ class TimeTestCase(unittest.TestCase):
|
||||||
self.assertGreater(t2, t1)
|
self.assertGreater(t2, t1)
|
||||||
self.assertAlmostEqual(dt, 0.1, delta=0.2)
|
self.assertAlmostEqual(dt, 0.1, delta=0.2)
|
||||||
|
|
||||||
def test_timestamp(self):
|
|
||||||
import decimal
|
|
||||||
calls = [
|
|
||||||
(time.time,),
|
|
||||||
(time.mktime, time.localtime()),
|
|
||||||
]
|
|
||||||
if hasattr(time, 'monotonic'):
|
|
||||||
calls.append((time.monotonic,))
|
|
||||||
if hasattr(time, 'wallclock'):
|
|
||||||
calls.append((time.wallclock,))
|
|
||||||
if hasattr(time, 'CLOCK_REALTIME'):
|
|
||||||
if hasattr(time, 'clock_gettime'):
|
|
||||||
calls.append((time.clock_gettime, time.CLOCK_REALTIME))
|
|
||||||
if hasattr(time, 'clock_getres'):
|
|
||||||
calls.append((time.clock_getres, time.CLOCK_REALTIME))
|
|
||||||
for call in calls:
|
|
||||||
func, *args = call
|
|
||||||
|
|
||||||
# test invalid timestamp
|
|
||||||
for invalid in ("int", decimal.Context):
|
|
||||||
self.assertRaises(ValueError, func, *args, timestamp=invalid)
|
|
||||||
|
|
||||||
for type in (int, float, decimal.Decimal):
|
|
||||||
self.assertIsInstance(func(*args, timestamp=type), type)
|
|
||||||
|
|
||||||
def test_wallclock(self):
|
def test_wallclock(self):
|
||||||
t1 = time.wallclock()
|
t1 = time.wallclock()
|
||||||
t2 = time.wallclock()
|
t2 = time.wallclock()
|
||||||
|
|
|
@ -1702,12 +1702,6 @@ stat_float_times(PyObject* self, PyObject *args)
|
||||||
int newval = -1;
|
int newval = -1;
|
||||||
if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
|
if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
|
||||||
"os.stat_float_times() has been deprecated, "
|
|
||||||
"use timestamp argument of os.stat() instead",
|
|
||||||
1))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (newval == -1)
|
if (newval == -1)
|
||||||
/* Return old value */
|
/* Return old value */
|
||||||
return PyBool_FromLong(_stat_float_times);
|
return PyBool_FromLong(_stat_float_times);
|
||||||
|
@ -1717,12 +1711,9 @@ stat_float_times(PyObject* self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec,
|
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
|
||||||
int has_nsec, PyObject *timestamp)
|
|
||||||
{
|
{
|
||||||
PyObject *fval,*ival;
|
PyObject *fval,*ival;
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
#if SIZEOF_TIME_T > SIZEOF_LONG
|
||||||
ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
|
ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
|
||||||
#else
|
#else
|
||||||
|
@ -1730,21 +1721,9 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec,
|
||||||
#endif
|
#endif
|
||||||
if (!ival)
|
if (!ival)
|
||||||
return;
|
return;
|
||||||
if (timestamp == NULL && _stat_float_times)
|
if (_stat_float_times) {
|
||||||
timestamp = (PyObject*)&PyFloat_Type;
|
fval = PyFloat_FromDouble(sec + 1e-9*nsec);
|
||||||
if (timestamp != NULL) {
|
} else {
|
||||||
ts.seconds = sec;
|
|
||||||
if (has_nsec) {
|
|
||||||
ts.numerator = nsec;
|
|
||||||
ts.denominator = 1000000000;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ts.numerator = 0;
|
|
||||||
ts.denominator = 1;
|
|
||||||
}
|
|
||||||
fval = _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fval = ival;
|
fval = ival;
|
||||||
Py_INCREF(fval);
|
Py_INCREF(fval);
|
||||||
}
|
}
|
||||||
|
@ -1755,14 +1734,9 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec,
|
||||||
/* pack a system stat C structure into the Python stat tuple
|
/* pack a system stat C structure into the Python stat tuple
|
||||||
(used by posix_stat() and posix_fstat()) */
|
(used by posix_stat() and posix_fstat()) */
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_pystat_fromstructstat(STRUCT_STAT *st, PyObject *timestamp)
|
_pystat_fromstructstat(STRUCT_STAT *st)
|
||||||
{
|
{
|
||||||
unsigned long ansec, mnsec, cnsec;
|
unsigned long ansec, mnsec, cnsec;
|
||||||
int has_nsec;
|
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
|
|
||||||
_PyTime_t ts;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PyObject *v = PyStructSequence_New(&StatResultType);
|
PyObject *v = PyStructSequence_New(&StatResultType);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1794,24 +1768,20 @@ _pystat_fromstructstat(STRUCT_STAT *st, PyObject *timestamp)
|
||||||
ansec = st->st_atim.tv_nsec;
|
ansec = st->st_atim.tv_nsec;
|
||||||
mnsec = st->st_mtim.tv_nsec;
|
mnsec = st->st_mtim.tv_nsec;
|
||||||
cnsec = st->st_ctim.tv_nsec;
|
cnsec = st->st_ctim.tv_nsec;
|
||||||
has_nsec = 1;
|
|
||||||
#elif defined(HAVE_STAT_TV_NSEC2)
|
#elif defined(HAVE_STAT_TV_NSEC2)
|
||||||
ansec = st->st_atimespec.tv_nsec;
|
ansec = st->st_atimespec.tv_nsec;
|
||||||
mnsec = st->st_mtimespec.tv_nsec;
|
mnsec = st->st_mtimespec.tv_nsec;
|
||||||
cnsec = st->st_ctimespec.tv_nsec;
|
cnsec = st->st_ctimespec.tv_nsec;
|
||||||
has_nsec = 1;
|
|
||||||
#elif defined(HAVE_STAT_NSEC)
|
#elif defined(HAVE_STAT_NSEC)
|
||||||
ansec = st->st_atime_nsec;
|
ansec = st->st_atime_nsec;
|
||||||
mnsec = st->st_mtime_nsec;
|
mnsec = st->st_mtime_nsec;
|
||||||
cnsec = st->st_ctime_nsec;
|
cnsec = st->st_ctime_nsec;
|
||||||
has_nsec = 1;
|
|
||||||
#else
|
#else
|
||||||
ansec = mnsec = cnsec = 0;
|
ansec = mnsec = cnsec = 0;
|
||||||
has_nsec = 0;
|
|
||||||
#endif
|
#endif
|
||||||
fill_time(v, 7, st->st_atime, ansec, has_nsec, timestamp);
|
fill_time(v, 7, st->st_atime, ansec);
|
||||||
fill_time(v, 8, st->st_mtime, mnsec, has_nsec, timestamp);
|
fill_time(v, 8, st->st_mtime, mnsec);
|
||||||
fill_time(v, 9, st->st_ctime, cnsec, has_nsec, timestamp);
|
fill_time(v, 9, st->st_ctime, cnsec);
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||||
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
|
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
|
||||||
|
@ -1831,26 +1801,21 @@ _pystat_fromstructstat(STRUCT_STAT *st, PyObject *timestamp)
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
|
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
|
||||||
{
|
{
|
||||||
PyObject *val;
|
PyObject *val;
|
||||||
ts.seconds = (long)st->st_birthtime;
|
unsigned long bsec,bnsec;
|
||||||
|
bsec = (long)st->st_birthtime;
|
||||||
#ifdef HAVE_STAT_TV_NSEC2
|
#ifdef HAVE_STAT_TV_NSEC2
|
||||||
ts.numerator = st->st_birthtimespec.tv_nsec;
|
bnsec = st->st_birthtimespec.tv_nsec;
|
||||||
ts.denominator = 1000000000;
|
|
||||||
#else
|
#else
|
||||||
ts.numerator = 0;
|
bnsec = 0;
|
||||||
ts.denominator = 1;
|
|
||||||
#endif
|
#endif
|
||||||
if (timestamp == NULL) {
|
if (_stat_float_times) {
|
||||||
if (_stat_float_times)
|
val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
|
||||||
val = _PyTime_Convert(&ts, (PyObject*)&PyFloat_Type);
|
} else {
|
||||||
else
|
val = PyLong_FromLong((long)bsec);
|
||||||
val = _PyTime_Convert(&ts, (PyObject*)&PyLong_Type);
|
}
|
||||||
}
|
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
|
||||||
else {
|
val);
|
||||||
val = _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
|
||||||
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
|
|
||||||
val);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
|
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
|
||||||
|
@ -1867,7 +1832,7 @@ _pystat_fromstructstat(STRUCT_STAT *st, PyObject *timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_do_stat(PyObject *self, PyObject *args, PyObject *kw,
|
posix_do_stat(PyObject *self, PyObject *args,
|
||||||
char *format,
|
char *format,
|
||||||
#ifdef __VMS
|
#ifdef __VMS
|
||||||
int (*statfunc)(const char *, STRUCT_STAT *, ...),
|
int (*statfunc)(const char *, STRUCT_STAT *, ...),
|
||||||
|
@ -1877,18 +1842,15 @@ posix_do_stat(PyObject *self, PyObject *args, PyObject *kw,
|
||||||
char *wformat,
|
char *wformat,
|
||||||
int (*wstatfunc)(const wchar_t *, STRUCT_STAT *))
|
int (*wstatfunc)(const wchar_t *, STRUCT_STAT *))
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"path", "timestamp", NULL};
|
|
||||||
STRUCT_STAT st;
|
STRUCT_STAT st;
|
||||||
PyObject *opath;
|
PyObject *opath;
|
||||||
char *path;
|
char *path;
|
||||||
int res;
|
int res;
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
PyObject *po;
|
PyObject *po;
|
||||||
if (PyArg_ParseTupleAndKeywords(args, kw, wformat, kwlist,
|
if (PyArg_ParseTuple(args, wformat, &po)) {
|
||||||
&po, ×tamp)) {
|
|
||||||
wchar_t *wpath = PyUnicode_AsUnicode(po);
|
wchar_t *wpath = PyUnicode_AsUnicode(po);
|
||||||
if (wpath == NULL)
|
if (wpath == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1899,17 +1861,15 @@ posix_do_stat(PyObject *self, PyObject *args, PyObject *kw,
|
||||||
|
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return win32_error_object("stat", po);
|
return win32_error_object("stat", po);
|
||||||
return _pystat_fromstructstat(&st, timestamp);
|
return _pystat_fromstructstat(&st);
|
||||||
}
|
}
|
||||||
/* Drop the argument parsing error as narrow strings
|
/* Drop the argument parsing error as narrow strings
|
||||||
are also valid. */
|
are also valid. */
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
timestamp = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kw, format, kwlist,
|
if (!PyArg_ParseTuple(args, format,
|
||||||
PyUnicode_FSConverter, &opath,
|
PyUnicode_FSConverter, &opath))
|
||||||
×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
if (win32_warn_bytes_api()) {
|
if (win32_warn_bytes_api()) {
|
||||||
|
@ -1930,7 +1890,7 @@ posix_do_stat(PyObject *self, PyObject *args, PyObject *kw,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = _pystat_fromstructstat(&st, timestamp);
|
result = _pystat_fromstructstat(&st);
|
||||||
|
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return result;
|
return result;
|
||||||
|
@ -3421,16 +3381,16 @@ posix_rmdir(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_stat__doc__,
|
PyDoc_STRVAR(posix_stat__doc__,
|
||||||
"stat(path, timestamp=None) -> stat result\n\n\
|
"stat(path) -> stat result\n\n\
|
||||||
Perform a stat system call on the given path.");
|
Perform a stat system call on the given path.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_stat(PyObject *self, PyObject *args, PyObject *kw)
|
posix_stat(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return posix_do_stat(self, args, kw, "O&|O:stat", STAT, "U|O:stat", win32_stat_w);
|
return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_stat_w);
|
||||||
#else
|
#else
|
||||||
return posix_do_stat(self, args, kw, "O&|O:stat", STAT, NULL, NULL);
|
return posix_do_stat(self, args, "O&:stat", STAT, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6158,12 +6118,11 @@ posix_setgroups(PyObject *self, PyObject *groups)
|
||||||
|
|
||||||
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
|
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wait_helper(pid_t pid, int status, struct rusage *ru, PyObject *timestamp)
|
wait_helper(pid_t pid, int status, struct rusage *ru)
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
static PyObject *struct_rusage;
|
static PyObject *struct_rusage;
|
||||||
_Py_IDENTIFIER(struct_rusage);
|
_Py_IDENTIFIER(struct_rusage);
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
return posix_error();
|
return posix_error();
|
||||||
|
@ -6187,17 +6146,10 @@ wait_helper(pid_t pid, int status, struct rusage *ru, PyObject *timestamp)
|
||||||
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
|
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ts.seconds = ru->ru_utime.tv_sec;
|
|
||||||
ts.numerator = ru->ru_utime.tv_usec;
|
|
||||||
ts.denominator = 1000000;
|
|
||||||
PyStructSequence_SET_ITEM(result, 0,
|
PyStructSequence_SET_ITEM(result, 0,
|
||||||
_PyTime_Convert(&ts, timestamp));
|
PyFloat_FromDouble(doubletime(ru->ru_utime)));
|
||||||
|
|
||||||
ts.seconds = ru->ru_stime.tv_sec;
|
|
||||||
ts.numerator = ru->ru_stime.tv_usec;
|
|
||||||
ts.denominator = 1000000;
|
|
||||||
PyStructSequence_SET_ITEM(result, 1,
|
PyStructSequence_SET_ITEM(result, 1,
|
||||||
_PyTime_Convert(&ts, timestamp));
|
PyFloat_FromDouble(doubletime(ru->ru_stime)));
|
||||||
#define SET_INT(result, index, value)\
|
#define SET_INT(result, index, value)\
|
||||||
PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
|
PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
|
||||||
SET_INT(result, 2, ru->ru_maxrss);
|
SET_INT(result, 2, ru->ru_maxrss);
|
||||||
|
@ -6227,55 +6179,51 @@ wait_helper(pid_t pid, int status, struct rusage *ru, PyObject *timestamp)
|
||||||
|
|
||||||
#ifdef HAVE_WAIT3
|
#ifdef HAVE_WAIT3
|
||||||
PyDoc_STRVAR(posix_wait3__doc__,
|
PyDoc_STRVAR(posix_wait3__doc__,
|
||||||
"wait3(options[, timestamp=float]) -> (pid, status, rusage)\n\n\
|
"wait3(options) -> (pid, status, rusage)\n\n\
|
||||||
Wait for completion of a child process.");
|
Wait for completion of a child process.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_wait3(PyObject *self, PyObject *args, PyObject *kwargs)
|
posix_wait3(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"options", "timestamp", NULL};
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int options;
|
int options;
|
||||||
struct rusage ru;
|
struct rusage ru;
|
||||||
WAIT_TYPE status;
|
WAIT_TYPE status;
|
||||||
WAIT_STATUS_INT(status) = 0;
|
WAIT_STATUS_INT(status) = 0;
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:wait3", kwlist, &options, ×tamp))
|
if (!PyArg_ParseTuple(args, "i:wait3", &options))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
pid = wait3(&status, options, &ru);
|
pid = wait3(&status, options, &ru);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru, timestamp);
|
return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAIT3 */
|
#endif /* HAVE_WAIT3 */
|
||||||
|
|
||||||
#ifdef HAVE_WAIT4
|
#ifdef HAVE_WAIT4
|
||||||
PyDoc_STRVAR(posix_wait4__doc__,
|
PyDoc_STRVAR(posix_wait4__doc__,
|
||||||
"wait4(pid, options[, timestamp=float]) -> (pid, status, rusage)\n\n\
|
"wait4(pid, options) -> (pid, status, rusage)\n\n\
|
||||||
Wait for completion of a given child process.");
|
Wait for completion of a given child process.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_wait4(PyObject *self, PyObject *args, PyObject *kwargs)
|
posix_wait4(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"pid", "options", "timestamp", NULL};
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int options;
|
int options;
|
||||||
struct rusage ru;
|
struct rusage ru;
|
||||||
WAIT_TYPE status;
|
WAIT_TYPE status;
|
||||||
WAIT_STATUS_INT(status) = 0;
|
WAIT_STATUS_INT(status) = 0;
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, _Py_PARSE_PID "i|O:wait4", kwlist, &pid, &options, ×tamp))
|
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
pid = wait4(pid, &status, options, &ru);
|
pid = wait4(pid, &status, options, &ru);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru, timestamp);
|
return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAIT4 */
|
#endif /* HAVE_WAIT4 */
|
||||||
|
|
||||||
|
@ -6402,20 +6350,20 @@ posix_wait(PyObject *self, PyObject *noargs)
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_lstat__doc__,
|
PyDoc_STRVAR(posix_lstat__doc__,
|
||||||
"lstat(path, timestamp=None) -> stat result\n\n\
|
"lstat(path) -> stat result\n\n\
|
||||||
Like stat(path), but do not follow symbolic links.");
|
Like stat(path), but do not follow symbolic links.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_lstat(PyObject *self, PyObject *args, PyObject *kw)
|
posix_lstat(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LSTAT
|
#ifdef HAVE_LSTAT
|
||||||
return posix_do_stat(self, args, kw, "O&|O:lstat", lstat, NULL, NULL);
|
return posix_do_stat(self, args, "O&:lstat", lstat, NULL, NULL);
|
||||||
#else /* !HAVE_LSTAT */
|
#else /* !HAVE_LSTAT */
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return posix_do_stat(self, args, kw, "O&|O:lstat", win32_lstat, "U|O:lstat",
|
return posix_do_stat(self, args, "O&:lstat", win32_lstat, "U:lstat",
|
||||||
win32_lstat_w);
|
win32_lstat_w);
|
||||||
#else
|
#else
|
||||||
return posix_do_stat(self, args, "kw, O&|O:lstat", STAT, NULL, NULL);
|
return posix_do_stat(self, args, "O&:lstat", STAT, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
#endif /* !HAVE_LSTAT */
|
#endif /* !HAVE_LSTAT */
|
||||||
}
|
}
|
||||||
|
@ -7374,19 +7322,16 @@ done:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_fstat__doc__,
|
PyDoc_STRVAR(posix_fstat__doc__,
|
||||||
"fstat(fd, timestamp=None) -> stat result\n\n\
|
"fstat(fd) -> stat result\n\n\
|
||||||
Like stat(), but for an open file descriptor.");
|
Like stat(), but for an open file descriptor.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_fstat(PyObject *self, PyObject *args, PyObject *kwargs)
|
posix_fstat(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"fd", "timestamp", NULL};
|
|
||||||
int fd;
|
int fd;
|
||||||
STRUCT_STAT st;
|
STRUCT_STAT st;
|
||||||
int res;
|
int res;
|
||||||
PyObject *timestamp = NULL;
|
if (!PyArg_ParseTuple(args, "i:fstat", &fd))
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:fstat", kwlist,
|
|
||||||
&fd, ×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#ifdef __VMS
|
#ifdef __VMS
|
||||||
/* on OpenVMS we must ensure that all bytes are written to the file */
|
/* on OpenVMS we must ensure that all bytes are written to the file */
|
||||||
|
@ -7405,7 +7350,7 @@ posix_fstat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return _pystat_fromstructstat(&st, timestamp);
|
return _pystat_fromstructstat(&st);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_isatty__doc__,
|
PyDoc_STRVAR(posix_isatty__doc__,
|
||||||
|
@ -9689,25 +9634,22 @@ posix_fchownat(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
#ifdef HAVE_FSTATAT
|
#ifdef HAVE_FSTATAT
|
||||||
PyDoc_STRVAR(posix_fstatat__doc__,
|
PyDoc_STRVAR(posix_fstatat__doc__,
|
||||||
"fstatat(dirfd, path, flags=0, timestamp=None) -> stat result\n\n\
|
"fstatat(dirfd, path, flags=0) -> stat result\n\n\
|
||||||
Like stat() but if path is relative, it is taken as relative to dirfd.\n\
|
Like stat() but if path is relative, it is taken as relative to dirfd.\n\
|
||||||
flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
|
flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
|
||||||
If path is relative and dirfd is the special value AT_FDCWD, then path\n\
|
If path is relative and dirfd is the special value AT_FDCWD, then path\n\
|
||||||
is interpreted relative to the current working directory.");
|
is interpreted relative to the current working directory.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_fstatat(PyObject *self, PyObject *args, PyObject *kwargs)
|
posix_fstatat(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"dirfd", "path", "flags", "timestamp", NULL};
|
|
||||||
PyObject *opath;
|
PyObject *opath;
|
||||||
char *path;
|
char *path;
|
||||||
STRUCT_STAT st;
|
STRUCT_STAT st;
|
||||||
int dirfd, res, flags = 0;
|
int dirfd, res, flags = 0;
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO&|iO:fstatat", kwlist,
|
if (!PyArg_ParseTuple(args, "iO&|i:fstatat",
|
||||||
&dirfd, PyUnicode_FSConverter, &opath,
|
&dirfd, PyUnicode_FSConverter, &opath, &flags))
|
||||||
&flags, ×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
path = PyBytes_AsString(opath);
|
path = PyBytes_AsString(opath);
|
||||||
|
|
||||||
|
@ -9718,7 +9660,7 @@ posix_fstatat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return posix_error();
|
return posix_error();
|
||||||
|
|
||||||
return _pystat_fromstructstat(&st, timestamp);
|
return _pystat_fromstructstat(&st);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -10582,7 +10524,7 @@ static PyMethodDef posix_methods[] = {
|
||||||
#ifdef HAVE_FDOPENDIR
|
#ifdef HAVE_FDOPENDIR
|
||||||
{"flistdir", posix_flistdir, METH_VARARGS, posix_flistdir__doc__},
|
{"flistdir", posix_flistdir, METH_VARARGS, posix_flistdir__doc__},
|
||||||
#endif
|
#endif
|
||||||
{"lstat", (PyCFunction)posix_lstat, METH_VARARGS | METH_KEYWORDS, posix_lstat__doc__},
|
{"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__},
|
||||||
{"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
|
{"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
|
||||||
#ifdef HAVE_NICE
|
#ifdef HAVE_NICE
|
||||||
{"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
|
{"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
|
||||||
|
@ -10602,8 +10544,7 @@ static PyMethodDef posix_methods[] = {
|
||||||
{"rename", posix_rename, METH_VARARGS, posix_rename__doc__},
|
{"rename", posix_rename, METH_VARARGS, posix_rename__doc__},
|
||||||
{"replace", posix_replace, METH_VARARGS, posix_replace__doc__},
|
{"replace", posix_replace, METH_VARARGS, posix_replace__doc__},
|
||||||
{"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
|
{"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
|
||||||
{"stat", (PyCFunction)posix_stat,
|
{"stat", posix_stat, METH_VARARGS, posix_stat__doc__},
|
||||||
METH_VARARGS | METH_KEYWORDS, posix_stat__doc__},
|
|
||||||
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
|
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
|
||||||
#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
|
#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
|
||||||
{"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__},
|
{"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__},
|
||||||
|
@ -10764,12 +10705,10 @@ static PyMethodDef posix_methods[] = {
|
||||||
{"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
|
{"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
|
||||||
#endif /* HAVE_WAIT */
|
#endif /* HAVE_WAIT */
|
||||||
#ifdef HAVE_WAIT3
|
#ifdef HAVE_WAIT3
|
||||||
{"wait3", (PyCFunction)posix_wait3,
|
{"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
|
||||||
METH_VARARGS | METH_KEYWORDS, posix_wait3__doc__},
|
|
||||||
#endif /* HAVE_WAIT3 */
|
#endif /* HAVE_WAIT3 */
|
||||||
#ifdef HAVE_WAIT4
|
#ifdef HAVE_WAIT4
|
||||||
{"wait4", (PyCFunction)posix_wait4,
|
{"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
|
||||||
METH_VARARGS | METH_KEYWORDS, posix_wait4__doc__},
|
|
||||||
#endif /* HAVE_WAIT4 */
|
#endif /* HAVE_WAIT4 */
|
||||||
#if defined(HAVE_WAITID) && !defined(__APPLE__)
|
#if defined(HAVE_WAITID) && !defined(__APPLE__)
|
||||||
{"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__},
|
{"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__},
|
||||||
|
@ -10820,8 +10759,7 @@ static PyMethodDef posix_methods[] = {
|
||||||
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
|
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
|
||||||
posix_sendfile__doc__},
|
posix_sendfile__doc__},
|
||||||
#endif
|
#endif
|
||||||
{"fstat", (PyCFunction)posix_fstat, METH_VARARGS | METH_KEYWORDS,
|
{"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
|
||||||
posix_fstat__doc__},
|
|
||||||
{"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
|
{"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
|
||||||
#ifdef HAVE_PIPE
|
#ifdef HAVE_PIPE
|
||||||
{"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
|
{"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
|
||||||
|
@ -10956,8 +10894,7 @@ static PyMethodDef posix_methods[] = {
|
||||||
{"fchownat", posix_fchownat, METH_VARARGS, posix_fchownat__doc__},
|
{"fchownat", posix_fchownat, METH_VARARGS, posix_fchownat__doc__},
|
||||||
#endif /* HAVE_FCHOWNAT */
|
#endif /* HAVE_FCHOWNAT */
|
||||||
#ifdef HAVE_FSTATAT
|
#ifdef HAVE_FSTATAT
|
||||||
{"fstatat", (PyCFunction)posix_fstatat, METH_VARARGS | METH_KEYWORDS,
|
{"fstatat", posix_fstatat, METH_VARARGS, posix_fstatat__doc__},
|
||||||
posix_fstatat__doc__},
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_FUTIMESAT
|
#ifdef HAVE_FUTIMESAT
|
||||||
{"futimesat", posix_futimesat, METH_VARARGS, posix_futimesat__doc__},
|
{"futimesat", posix_futimesat, METH_VARARGS, posix_futimesat__doc__},
|
||||||
|
|
|
@ -40,30 +40,24 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
|
||||||
# define HAVE_PYCLOCK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static int floatsleep(double);
|
static int floatsleep(double);
|
||||||
|
static double floattime(void);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_time(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_time(PyObject *self, PyObject *unused)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"timestamp", NULL};
|
double secs;
|
||||||
PyObject *timestamp = NULL;
|
secs = floattime();
|
||||||
_PyTime_t ts;
|
if (secs == 0.0) {
|
||||||
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:time", kwlist,
|
|
||||||
×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
_PyTime_get(&ts);
|
return PyFloat_FromDouble(secs);
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(time_doc,
|
PyDoc_STRVAR(time_doc,
|
||||||
"time(timestamp=float) -> floating point number\n\
|
"time() -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Return the current time in seconds since the Epoch.\n\
|
Return the current time in seconds since the Epoch.\n\
|
||||||
Fractions of a second may be present if the system clock provides them.");
|
Fractions of a second may be present if the system clock provides them.");
|
||||||
|
@ -78,91 +72,65 @@ Fractions of a second may be present if the system clock provides them.");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
pyclock(_PyTime_t *ts)
|
pyclock(void)
|
||||||
{
|
{
|
||||||
clock_t processor_time;
|
clock_t value;
|
||||||
processor_time = clock();
|
value = clock();
|
||||||
if (processor_time == (clock_t)-1) {
|
if (value == (clock_t)-1) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"the processor time used is not available "
|
"the processor time used is not available "
|
||||||
"or its value cannot be represented");
|
"or its value cannot be represented");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
ts->seconds = 0;
|
return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC);
|
||||||
assert(sizeof(clock_t) <= sizeof(_PyTime_fraction_t));
|
|
||||||
ts->numerator = Py_SAFE_DOWNCAST(processor_time,
|
|
||||||
clock_t, _PyTime_fraction_t);
|
|
||||||
ts->denominator = CLOCKS_PER_SEC;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_CLOCK */
|
#endif /* HAVE_CLOCK */
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||||
/* Win32 has better clock replacement; we have our own version, due to Mark
|
/* Win32 has better clock replacement; we have our own version, due to Mark
|
||||||
Hammond and Tim Peters */
|
Hammond and Tim Peters */
|
||||||
static int
|
static PyObject *
|
||||||
win32_clock(_PyTime_t *ts, int fallback)
|
win32_clock(int fallback)
|
||||||
{
|
{
|
||||||
static LONGLONG cpu_frequency = 0;
|
static LONGLONG cpu_frequency = 0;
|
||||||
static LONGLONG start;
|
static LONGLONG ctrStart;
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
LONGLONG dt;
|
double diff;
|
||||||
|
|
||||||
if (cpu_frequency == 0) {
|
if (cpu_frequency == 0) {
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(&now);
|
||||||
start = now.QuadPart;
|
ctrStart = now.QuadPart;
|
||||||
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) {
|
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) {
|
||||||
/* Unlikely to happen - this works on all intel
|
/* Unlikely to happen - this works on all intel
|
||||||
machines at least! Revert to clock() */
|
machines at least! Revert to clock() */
|
||||||
if (fallback) {
|
if (fallback)
|
||||||
return pyclock(ts);
|
return pyclock();
|
||||||
}
|
else
|
||||||
else {
|
return PyErr_SetFromWindowsErr(0);
|
||||||
PyErr_SetFromWindowsErr(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cpu_frequency = freq.QuadPart;
|
cpu_frequency = freq.QuadPart;
|
||||||
}
|
}
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(&now);
|
||||||
dt = now.QuadPart - start;
|
diff = (double)(now.QuadPart - ctrStart);
|
||||||
|
return PyFloat_FromDouble(diff / (double)cpu_frequency);
|
||||||
ts->seconds = 0;
|
|
||||||
assert(sizeof(LONGLONG) <= sizeof(_PyTime_fraction_t));
|
|
||||||
ts->numerator = Py_SAFE_DOWNCAST(dt,
|
|
||||||
LONGLONG, _PyTime_fraction_t);
|
|
||||||
ts->denominator = Py_SAFE_DOWNCAST(cpu_frequency,
|
|
||||||
LONGLONG, _PyTime_fraction_t);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_clock(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_clock(PyObject *self, PyObject *unused)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"timestamp", NULL};
|
|
||||||
_PyTime_t ts;
|
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:clock", kwlist,
|
|
||||||
×tamp))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||||
if (win32_clock(&ts, 1) == -1)
|
return win32_clock(1);
|
||||||
return NULL;
|
|
||||||
#else
|
#else
|
||||||
if (pyclock(&ts) == -1)
|
return pyclock();
|
||||||
return NULL;
|
|
||||||
#endif
|
#endif
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(clock_doc,
|
PyDoc_STRVAR(clock_doc,
|
||||||
"clock(timestamp=float) -> floating point number\n\
|
"clock() -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Return the CPU time or real time since the start of the process or since\n\
|
Return the CPU time or real time since the start of the process or since\n\
|
||||||
the first call to clock(). This has as much precision as the system\n\
|
the first call to clock(). This has as much precision as the system\n\
|
||||||
|
@ -171,17 +139,13 @@ records.");
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_clock_gettime(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_clock_gettime(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"clk_id", "timestamp", NULL};
|
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
clockid_t clk_id;
|
clockid_t clk_id;
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:clock_gettime", kwlist,
|
if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id))
|
||||||
&clk_id, ×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = clock_gettime((clockid_t)clk_id, &tp);
|
ret = clock_gettime((clockid_t)clk_id, &tp);
|
||||||
|
@ -189,31 +153,25 @@ time_clock_gettime(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
PyErr_SetFromErrno(PyExc_IOError);
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ts.seconds = tp.tv_sec;
|
|
||||||
ts.numerator = tp.tv_nsec;
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
ts.denominator = 1000000000;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(clock_gettime_doc,
|
PyDoc_STRVAR(clock_gettime_doc,
|
||||||
"clock_gettime(clk_id, timestamp=float) -> floating point number\n\
|
"clock_gettime(clk_id) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Return the time of the specified clock clk_id.");
|
Return the time of the specified clock clk_id.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETRES
|
#ifdef HAVE_CLOCK_GETRES
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_clock_getres(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_clock_getres(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"clk_id", "timestamp", NULL};
|
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
clockid_t clk_id;
|
clockid_t clk_id;
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:clock_getres", kwlist,
|
if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id))
|
||||||
&clk_id, ×tamp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = clock_getres((clockid_t)clk_id, &tp);
|
ret = clock_getres((clockid_t)clk_id, &tp);
|
||||||
|
@ -221,14 +179,12 @@ time_clock_getres(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
PyErr_SetFromErrno(PyExc_IOError);
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ts.seconds = tp.tv_sec;
|
|
||||||
ts.numerator = tp.tv_nsec;
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
ts.denominator = 1000000000;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(clock_getres_doc,
|
PyDoc_STRVAR(clock_getres_doc,
|
||||||
"clock_getres(clk_id, timestamp=float) -> floating point number\n\
|
"clock_getres(clk_id) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Return the resolution (precision) of the specified clock clk_id.");
|
Return the resolution (precision) of the specified clock clk_id.");
|
||||||
#endif
|
#endif
|
||||||
|
@ -751,19 +707,10 @@ not present, current time as returned by localtime() is used.");
|
||||||
|
|
||||||
#ifdef HAVE_MKTIME
|
#ifdef HAVE_MKTIME
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_mktime(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_mktime(PyObject *self, PyObject *tup)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"t", "timestamp", NULL};
|
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
PyObject *tup;
|
|
||||||
struct tm buf;
|
struct tm buf;
|
||||||
time_t tt;
|
time_t tt;
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:mktime", kwlist,
|
|
||||||
&tup, ×tamp))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!gettmarg(tup, &buf))
|
if (!gettmarg(tup, &buf))
|
||||||
return NULL;
|
return NULL;
|
||||||
buf.tm_wday = -1; /* sentinel; original value ignored */
|
buf.tm_wday = -1; /* sentinel; original value ignored */
|
||||||
|
@ -775,10 +722,7 @@ time_mktime(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
"mktime argument out of range");
|
"mktime argument out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ts.seconds = tt;
|
return PyFloat_FromDouble((double)tt);
|
||||||
ts.numerator = 0;
|
|
||||||
ts.denominator = 1;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(mktime_doc,
|
PyDoc_STRVAR(mktime_doc,
|
||||||
|
@ -824,14 +768,12 @@ the local timezone used by methods such as localtime, but this behaviour\n\
|
||||||
should not be relied on.");
|
should not be relied on.");
|
||||||
#endif /* HAVE_WORKING_TZSET */
|
#endif /* HAVE_WORKING_TZSET */
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
pywallclock(_PyTime_t *ts)
|
time_wallclock(PyObject *self, PyObject *unused)
|
||||||
{
|
{
|
||||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||||
return win32_clock(ts, 1);
|
return win32_clock(1);
|
||||||
#else
|
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||||
|
|
||||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
|
||||||
static int clk_index = 0;
|
static int clk_index = 0;
|
||||||
clockid_t clk_ids[] = {
|
clockid_t clk_ids[] = {
|
||||||
#ifdef CLOCK_MONOTONIC_RAW
|
#ifdef CLOCK_MONOTONIC_RAW
|
||||||
|
@ -851,41 +793,20 @@ pywallclock(_PyTime_t *ts)
|
||||||
clockid_t clk_id = clk_ids[clk_index];
|
clockid_t clk_id = clk_ids[clk_index];
|
||||||
ret = clock_gettime(clk_id, &tp);
|
ret = clock_gettime(clk_id, &tp);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
ts->seconds = tp.tv_sec;
|
|
||||||
ts->numerator = tp.tv_nsec;
|
|
||||||
ts->denominator = 1000000000;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clk_index++;
|
clk_index++;
|
||||||
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
||||||
clk_index = -1;
|
clk_index = -1;
|
||||||
}
|
}
|
||||||
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) */
|
return time_time(self, NULL);
|
||||||
|
#else
|
||||||
_PyTime_get(ts);
|
return time_time(self, NULL);
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
time_wallclock(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
static char *kwlist[] = {"timestamp", NULL};
|
|
||||||
PyObject *timestamp = NULL;
|
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:wallclock", kwlist,
|
|
||||||
×tamp))
|
|
||||||
return NULL;
|
|
||||||
if (pywallclock(&ts))
|
|
||||||
return NULL;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(wallclock_doc,
|
PyDoc_STRVAR(wallclock_doc,
|
||||||
"wallclock(timestamp=float)\n\
|
"wallclock() -> float\n\
|
||||||
\n\
|
\n\
|
||||||
Return the current time in fractions of a second to the system's best\n\
|
Return the current time in fractions of a second to the system's best\n\
|
||||||
ability. Use this when the most accurate representation of wall-clock is\n\
|
ability. Use this when the most accurate representation of wall-clock is\n\
|
||||||
|
@ -900,11 +821,11 @@ calls is valid.");
|
||||||
|
|
||||||
#ifdef HAVE_PYTIME_MONOTONIC
|
#ifdef HAVE_PYTIME_MONOTONIC
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_monotonic(PyObject *self, PyObject *args, PyObject *kwargs)
|
time_monotonic(PyObject *self, PyObject *unused)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"timestamp", NULL};
|
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||||
PyObject *timestamp = NULL;
|
return win32_clock(0);
|
||||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
#else
|
||||||
static int clk_index = 0;
|
static int clk_index = 0;
|
||||||
clockid_t clk_ids[] = {
|
clockid_t clk_ids[] = {
|
||||||
#ifdef CLOCK_MONOTONIC_RAW
|
#ifdef CLOCK_MONOTONIC_RAW
|
||||||
|
@ -914,28 +835,12 @@ time_monotonic(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
#endif
|
|
||||||
_PyTime_t ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:monotonic", kwlist,
|
|
||||||
×tamp))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
|
||||||
if (win32_clock(&ts, 0) == -1)
|
|
||||||
return NULL;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
#else
|
|
||||||
while (0 <= clk_index) {
|
while (0 <= clk_index) {
|
||||||
clockid_t clk_id = clk_ids[clk_index];
|
clockid_t clk_id = clk_ids[clk_index];
|
||||||
ret = clock_gettime(clk_id, &tp);
|
ret = clock_gettime(clk_id, &tp);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
ts.seconds = tp.tv_sec;
|
|
||||||
ts.numerator = tp.tv_nsec;
|
|
||||||
ts.denominator = 1000000000;
|
|
||||||
return _PyTime_Convert(&ts, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
clk_index++;
|
clk_index++;
|
||||||
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
||||||
|
@ -1063,19 +968,15 @@ PyInit_timezone(PyObject *m) {
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef time_methods[] = {
|
static PyMethodDef time_methods[] = {
|
||||||
{"time", (PyCFunction)time_time,
|
{"time", time_time, METH_NOARGS, time_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, time_doc},
|
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||||
#ifdef HAVE_PYCLOCK
|
{"clock", time_clock, METH_NOARGS, clock_doc},
|
||||||
{"clock", (PyCFunction)time_clock,
|
|
||||||
METH_VARARGS | METH_KEYWORDS, clock_doc},
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
{"clock_gettime", (PyCFunction)time_clock_gettime,
|
{"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, clock_gettime_doc},
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CLOCK_GETRES
|
#ifdef HAVE_CLOCK_GETRES
|
||||||
{"clock_getres", (PyCFunction)time_clock_getres,
|
{"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, clock_getres_doc},
|
|
||||||
#endif
|
#endif
|
||||||
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
|
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
|
||||||
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
|
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
|
||||||
|
@ -1083,12 +984,10 @@ static PyMethodDef time_methods[] = {
|
||||||
{"asctime", time_asctime, METH_VARARGS, asctime_doc},
|
{"asctime", time_asctime, METH_VARARGS, asctime_doc},
|
||||||
{"ctime", time_ctime, METH_VARARGS, ctime_doc},
|
{"ctime", time_ctime, METH_VARARGS, ctime_doc},
|
||||||
#ifdef HAVE_MKTIME
|
#ifdef HAVE_MKTIME
|
||||||
{"mktime", (PyCFunction)time_mktime,
|
{"mktime", time_mktime, METH_O, mktime_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, mktime_doc},
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_PYTIME_MONOTONIC
|
#ifdef HAVE_PYTIME_MONOTONIC
|
||||||
{"monotonic", (PyCFunction)time_monotonic,
|
{"monotonic", time_monotonic, METH_NOARGS, monotonic_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, monotonic_doc},
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_STRFTIME
|
#ifdef HAVE_STRFTIME
|
||||||
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
|
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
|
||||||
|
@ -1097,8 +996,7 @@ static PyMethodDef time_methods[] = {
|
||||||
#ifdef HAVE_WORKING_TZSET
|
#ifdef HAVE_WORKING_TZSET
|
||||||
{"tzset", time_tzset, METH_NOARGS, tzset_doc},
|
{"tzset", time_tzset, METH_NOARGS, tzset_doc},
|
||||||
#endif
|
#endif
|
||||||
{"wallclock", (PyCFunction)time_wallclock,
|
{"wallclock", time_wallclock, METH_NOARGS, wallclock_doc},
|
||||||
METH_VARARGS | METH_KEYWORDS, wallclock_doc},
|
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1183,6 +1081,15 @@ PyInit_time(void)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
floattime(void)
|
||||||
|
{
|
||||||
|
_PyTime_timeval t;
|
||||||
|
_PyTime_gettimeofday(&t);
|
||||||
|
return (double)t.tv_sec + t.tv_usec*0.000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Implement floatsleep() for various platforms.
|
/* Implement floatsleep() for various platforms.
|
||||||
When interrupted (or when another error occurs), return -1 and
|
When interrupted (or when another error occurs), return -1 and
|
||||||
set an exception; else return 0. */
|
set an exception; else return 0. */
|
||||||
|
|
345
Python/pytime.c
345
Python/pytime.c
|
@ -18,36 +18,24 @@
|
||||||
extern int ftime(struct timeb *);
|
extern int ftime(struct timeb *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MICROSECONDS 1000000
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyTime_get(_PyTime_t *ts)
|
_PyTime_gettimeofday(_PyTime_timeval *tp)
|
||||||
{
|
{
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
FILETIME system_time;
|
FILETIME system_time;
|
||||||
ULARGE_INTEGER large;
|
ULARGE_INTEGER large;
|
||||||
ULONGLONG value;
|
ULONGLONG microseconds;
|
||||||
|
|
||||||
GetSystemTimeAsFileTime(&system_time);
|
GetSystemTimeAsFileTime(&system_time);
|
||||||
large.u.LowPart = system_time.dwLowDateTime;
|
large.u.LowPart = system_time.dwLowDateTime;
|
||||||
large.u.HighPart = system_time.dwHighDateTime;
|
large.u.HighPart = system_time.dwHighDateTime;
|
||||||
/* 116,444,736,000,000,000: number of 100 ns between
|
/* 11,644,473,600,000,000: number of microseconds between
|
||||||
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
|
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
|
||||||
days). */
|
days). */
|
||||||
value = large.QuadPart - 116444736000000000;
|
microseconds = large.QuadPart / 10 - 11644473600000000;
|
||||||
ts->seconds = 0;
|
tp->tv_sec = microseconds / 1000000;
|
||||||
ts->numerator = value;
|
tp->tv_usec = microseconds % 1000000;
|
||||||
ts->denominator = (_PyTime_fraction_t)10000000;
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
|
||||||
struct timeval tv;
|
|
||||||
int err;
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_FTIME)
|
|
||||||
struct timeb t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* There are three ways to get the time:
|
/* There are three ways to get the time:
|
||||||
(1) gettimeofday() -- resolution in microseconds
|
(1) gettimeofday() -- resolution in microseconds
|
||||||
(2) ftime() -- resolution in milliseconds
|
(2) ftime() -- resolution in milliseconds
|
||||||
|
@ -59,324 +47,29 @@ _PyTime_get(_PyTime_t *ts)
|
||||||
|
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
#ifdef GETTIMEOFDAY_NO_TZ
|
#ifdef GETTIMEOFDAY_NO_TZ
|
||||||
err = gettimeofday(&tv);
|
if (gettimeofday(tp) == 0)
|
||||||
#else /* !GETTIMEOFDAY_NO_TZ */
|
|
||||||
err = gettimeofday(&tv, (struct timezone *)NULL);
|
|
||||||
#endif /* !GETTIMEOFDAY_NO_TZ */
|
|
||||||
if (err == 0)
|
|
||||||
{
|
|
||||||
ts->seconds = tv.tv_sec;
|
|
||||||
ts->numerator = tv.tv_usec;
|
|
||||||
ts->denominator = MICROSECONDS;
|
|
||||||
return;
|
return;
|
||||||
}
|
#else /* !GETTIMEOFDAY_NO_TZ */
|
||||||
|
if (gettimeofday(tp, (struct timezone *)NULL) == 0)
|
||||||
|
return;
|
||||||
|
#endif /* !GETTIMEOFDAY_NO_TZ */
|
||||||
#endif /* !HAVE_GETTIMEOFDAY */
|
#endif /* !HAVE_GETTIMEOFDAY */
|
||||||
|
|
||||||
#if defined(HAVE_FTIME)
|
#if defined(HAVE_FTIME)
|
||||||
ftime(&t);
|
{
|
||||||
ts->seconds = t.time;
|
struct timeb t;
|
||||||
ts->numerator = t.millitm;
|
ftime(&t);
|
||||||
ts->denominator = 1000;
|
tp->tv_sec = t.time;
|
||||||
|
tp->tv_usec = t.millitm * 1000;
|
||||||
|
}
|
||||||
#else /* !HAVE_FTIME */
|
#else /* !HAVE_FTIME */
|
||||||
ts->seconds = time(NULL);
|
tp->tv_sec = time(NULL);
|
||||||
ts->numerator = 0;
|
tp->tv_usec = 0;
|
||||||
ts->denominator = 1;
|
|
||||||
#endif /* !HAVE_FTIME */
|
#endif /* !HAVE_FTIME */
|
||||||
|
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_PyTime_gettimeofday(_PyTime_timeval *tv)
|
|
||||||
{
|
|
||||||
_PyTime_t ts;
|
|
||||||
_PyTime_fraction_t k;
|
|
||||||
time_t sec;
|
|
||||||
|
|
||||||
_PyTime_get(&ts);
|
|
||||||
tv->tv_sec = ts.seconds;
|
|
||||||
if (ts.numerator) {
|
|
||||||
if (ts.numerator > ts.denominator) {
|
|
||||||
sec = Py_SAFE_DOWNCAST(ts.numerator / ts.denominator,
|
|
||||||
_PyTime_fraction_t, time_t);
|
|
||||||
/* ignore integer overflow because _PyTime_gettimeofday() has
|
|
||||||
no return value */
|
|
||||||
tv->tv_sec += sec;
|
|
||||||
ts.numerator = ts.numerator % ts.denominator;
|
|
||||||
}
|
|
||||||
if (MICROSECONDS >= ts.denominator) {
|
|
||||||
k = (_PyTime_fraction_t)MICROSECONDS / ts.denominator;
|
|
||||||
tv->tv_usec = (long)(ts.numerator * k);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
k = ts.denominator / (_PyTime_fraction_t)MICROSECONDS;
|
|
||||||
tv->tv_usec = (long)(ts.numerator / k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tv->tv_usec = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
_PyLong_FromTime_t(time_t value)
|
|
||||||
{
|
|
||||||
#if SIZEOF_TIME_T <= SIZEOF_LONG
|
|
||||||
return PyLong_FromLong(value);
|
|
||||||
#else
|
|
||||||
assert(sizeof(time_t) <= sizeof(PY_LONG_LONG));
|
|
||||||
return PyLong_FromLongLong(value);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_LONG_LONG)
|
|
||||||
# define _PyLong_FromTimeFraction_t PyLong_FromLongLong
|
|
||||||
#else
|
|
||||||
# define _PyLong_FromTimeFraction_t PyLong_FromSize_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convert a timestamp to a PyFloat object */
|
|
||||||
static PyObject*
|
|
||||||
_PyTime_AsFloat(_PyTime_t *ts)
|
|
||||||
{
|
|
||||||
double d;
|
|
||||||
d = (double)ts->seconds;
|
|
||||||
d += (double)ts->numerator / (double)ts->denominator;
|
|
||||||
return PyFloat_FromDouble(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert a timestamp to a PyLong object */
|
|
||||||
static PyObject*
|
|
||||||
_PyTime_AsLong(_PyTime_t *ts)
|
|
||||||
{
|
|
||||||
PyObject *a, *b, *c;
|
|
||||||
|
|
||||||
a = _PyLong_FromTime_t(ts->seconds);
|
|
||||||
if (a == NULL)
|
|
||||||
return NULL;
|
|
||||||
b = _PyLong_FromTimeFraction_t(ts->numerator / ts->denominator);
|
|
||||||
if (b == NULL)
|
|
||||||
{
|
|
||||||
Py_DECREF(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
c = PyNumber_Add(a, b);
|
|
||||||
Py_DECREF(a);
|
|
||||||
Py_DECREF(b);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert a timestamp to a decimal.Decimal object */
|
|
||||||
static PyObject*
|
|
||||||
_PyTime_AsDecimal(_PyTime_t *ts)
|
|
||||||
{
|
|
||||||
static PyObject* module = NULL;
|
|
||||||
static PyObject* decimal = NULL;
|
|
||||||
static PyObject* exponent_context = NULL;
|
|
||||||
static PyObject* context = NULL;
|
|
||||||
/* exponent cache, dictionary of:
|
|
||||||
int (denominator) => Decimal (1/denominator) */
|
|
||||||
static PyObject* exponent_cache = NULL;
|
|
||||||
PyObject *t = NULL;
|
|
||||||
PyObject *key, *exponent, *quantized;
|
|
||||||
_Py_IDENTIFIER(quantize);
|
|
||||||
_Py_IDENTIFIER(__truediv__);
|
|
||||||
|
|
||||||
if (!module) {
|
|
||||||
module = PyImport_ImportModuleNoBlock("decimal");
|
|
||||||
if (module == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!decimal) {
|
|
||||||
decimal = PyObject_GetAttrString(module, "Decimal");
|
|
||||||
if (decimal == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context == NULL)
|
|
||||||
{
|
|
||||||
/* Use 12 decimal digits to store 10,000 years in seconds + 9
|
|
||||||
decimal digits for the floating part in nanoseconds + 1 decimal
|
|
||||||
digit to round correctly.
|
|
||||||
|
|
||||||
context = decimal.Context(22, rounding=decimal.ROUND_HALF_EVEN)
|
|
||||||
exponent_context = decimal.Context(1, rounding=decimal.ROUND_HALF_EVEN)
|
|
||||||
*/
|
|
||||||
PyObject *context_class, *rounding;
|
|
||||||
context_class = PyObject_GetAttrString(module, "Context");
|
|
||||||
if (context_class == NULL)
|
|
||||||
return NULL;
|
|
||||||
rounding = PyObject_GetAttrString(module, "ROUND_HALF_EVEN");
|
|
||||||
if (rounding == NULL)
|
|
||||||
{
|
|
||||||
Py_DECREF(context_class);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
context = PyObject_CallFunction(context_class, "iO", 22, rounding);
|
|
||||||
if (context == NULL)
|
|
||||||
{
|
|
||||||
Py_DECREF(context_class);
|
|
||||||
Py_DECREF(rounding);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
exponent_context = PyObject_CallFunction(context_class, "iO", 1, rounding);
|
|
||||||
Py_DECREF(context_class);
|
|
||||||
Py_DECREF(rounding);
|
|
||||||
if (exponent_context == NULL)
|
|
||||||
{
|
|
||||||
Py_CLEAR(context);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* t = decimal.Decimal(value) */
|
|
||||||
if (ts->seconds) {
|
|
||||||
PyObject *f = _PyLong_FromTime_t(ts->seconds);
|
|
||||||
t = PyObject_CallFunction(decimal, "O", f);
|
|
||||||
Py_CLEAR(f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
t = PyObject_CallFunction(decimal, "iO", 0, context);
|
|
||||||
}
|
|
||||||
if (t == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (ts->numerator)
|
|
||||||
{
|
|
||||||
/* t += decimal.Decimal(numerator, ctx) / decimal.Decimal(denominator, ctx) */
|
|
||||||
PyObject *a, *b, *c, *d, *x;
|
|
||||||
|
|
||||||
x = _PyLong_FromTimeFraction_t(ts->numerator);
|
|
||||||
if (x == NULL)
|
|
||||||
goto error;
|
|
||||||
a = PyObject_CallFunction(decimal, "OO", x, context);
|
|
||||||
Py_CLEAR(x);
|
|
||||||
if (a == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
x = _PyLong_FromTimeFraction_t(ts->denominator);
|
|
||||||
if (x == NULL)
|
|
||||||
{
|
|
||||||
Py_DECREF(a);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
b = PyObject_CallFunction(decimal, "OO", x, context);
|
|
||||||
Py_CLEAR(x);
|
|
||||||
if (b == NULL)
|
|
||||||
{
|
|
||||||
Py_DECREF(a);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = _PyObject_CallMethodId(a, &PyId___truediv__, "OO",
|
|
||||||
b, context);
|
|
||||||
Py_DECREF(a);
|
|
||||||
Py_DECREF(b);
|
|
||||||
if (c == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
d = PyNumber_Add(t, c);
|
|
||||||
Py_DECREF(c);
|
|
||||||
if (d == NULL)
|
|
||||||
goto error;
|
|
||||||
Py_DECREF(t);
|
|
||||||
t = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exponent_cache == NULL) {
|
|
||||||
exponent_cache = PyDict_New();
|
|
||||||
if (exponent_cache == NULL)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = _PyLong_FromTimeFraction_t(ts->denominator);
|
|
||||||
if (key == NULL)
|
|
||||||
goto error;
|
|
||||||
exponent = PyDict_GetItem(exponent_cache, key);
|
|
||||||
if (exponent == NULL) {
|
|
||||||
/* exponent = decimal.Decimal(1) / decimal.Decimal(resolution) */
|
|
||||||
PyObject *one, *denominator;
|
|
||||||
|
|
||||||
one = PyObject_CallFunction(decimal, "i", 1);
|
|
||||||
if (one == NULL) {
|
|
||||||
Py_DECREF(key);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
denominator = PyObject_CallFunction(decimal, "O", key);
|
|
||||||
if (denominator == NULL) {
|
|
||||||
Py_DECREF(key);
|
|
||||||
Py_DECREF(one);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
exponent = _PyObject_CallMethodId(one, &PyId___truediv__, "OO",
|
|
||||||
denominator, exponent_context);
|
|
||||||
Py_DECREF(one);
|
|
||||||
Py_DECREF(denominator);
|
|
||||||
if (exponent == NULL) {
|
|
||||||
Py_DECREF(key);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyDict_SetItem(exponent_cache, key, exponent) < 0) {
|
|
||||||
Py_DECREF(key);
|
|
||||||
Py_DECREF(exponent);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Py_DECREF(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* t = t.quantize(exponent, None, context) */
|
|
||||||
quantized = _PyObject_CallMethodId(t, &PyId_quantize, "OOO",
|
|
||||||
exponent, Py_None, context);
|
|
||||||
if (quantized == NULL)
|
|
||||||
goto error;
|
|
||||||
Py_DECREF(t);
|
|
||||||
t = quantized;
|
|
||||||
|
|
||||||
return t;
|
|
||||||
|
|
||||||
error:
|
|
||||||
Py_XDECREF(t);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject*
|
|
||||||
_PyTime_Convert(_PyTime_t *ts, PyObject *format)
|
|
||||||
{
|
|
||||||
assert(ts->denominator != 0);
|
|
||||||
|
|
||||||
if (format == NULL || (PyTypeObject *)format == &PyFloat_Type)
|
|
||||||
return _PyTime_AsFloat(ts);
|
|
||||||
if ((PyTypeObject *)format == &PyLong_Type)
|
|
||||||
return _PyTime_AsLong(ts);
|
|
||||||
|
|
||||||
if (PyType_Check(format))
|
|
||||||
{
|
|
||||||
PyObject *module, *name;
|
|
||||||
_Py_IDENTIFIER(__name__);
|
|
||||||
_Py_IDENTIFIER(__module__);
|
|
||||||
|
|
||||||
module = _PyObject_GetAttrId(format, &PyId___module__);
|
|
||||||
name = _PyObject_GetAttrId(format, &PyId___name__);
|
|
||||||
if (module != NULL && PyUnicode_Check(module)
|
|
||||||
&& name != NULL && PyUnicode_Check(name))
|
|
||||||
{
|
|
||||||
if (PyUnicode_CompareWithASCIIString(module, "decimal") == 0
|
|
||||||
&& PyUnicode_CompareWithASCIIString(name, "Decimal") == 0)
|
|
||||||
return _PyTime_AsDecimal(ts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
PyErr_Format(PyExc_ValueError, "Unknown timestamp format: %R", format);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyTime_Init()
|
_PyTime_Init()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue