[pypy-commit] pypy py3.7: Merged in py3.7-time-minor-bpos (pull request #688)

arigo pypy.commits at gmail.com
Mon Dec 30 04:21:17 EST 2019


Author: Armin Rigo <armin.rigo at gmail.com>
Branch: py3.7
Changeset: r98415:8f7bc5f6eb55
Date: 2019-12-30 09:20 +0000
http://bitbucket.org/pypy/pypy/changeset/8f7bc5f6eb55/

Log:	Merged in py3.7-time-minor-bpos (pull request #688)

	Py3.7 time module minor BPOs

diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -10,7 +10,7 @@
     str_decode_locale_surrogateescape, unicode_encode_locale_surrogateescape)
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rlib.rarithmetic import (
-    intmask, r_ulonglong, r_longfloat, r_int64, widen, ovfcheck, ovfcheck_float_to_int)
+    intmask, r_ulonglong, r_longfloat, r_int64, widen, ovfcheck, ovfcheck_float_to_int, INT_MIN)
 from rpython.rlib.rtime import (GETTIMEOFDAY_NO_TZ, TIMEVAL,
                                 HAVE_GETTIMEOFDAY, HAVE_FTIME)
 from rpython.rlib import rposix, rtime
@@ -240,6 +240,8 @@
 HAS_CLOCK_MONOTONIC = rtime.CLOCK_MONOTONIC is not None
 HAS_MONOTONIC = (_WIN or _MACOSX or
                  (HAS_CLOCK_GETTIME and (HAS_CLOCK_HIGHRES or HAS_CLOCK_MONOTONIC)))
+HAS_THREAD_TIME = (_WIN or
+                   (HAS_CLOCK_GETTIME and rtime.CLOCK_PROCESS_CPUTIME_ID is not None))
 tm = cConfig.tm
 glob_buf = lltype.malloc(tm, flavor='raw', zero=True, immortal=True)
 
@@ -647,6 +649,9 @@
         if len(tup_w) >= 11:
             rffi.setintfield(glob_buf, 'c_tm_gmtoff', space.c_int_w(tup_w[10]))
 
+    if (y < INT_MIN + 1900):
+        raise oefmt(space.w_OverflowError, "year out of range")
+
     # tm_wday does not need checking of its upper-bound since taking "%
     #  7" in _gettmarg() automatically restricts the range.
     if rffi.getintfield(glob_buf, 'c_tm_wday') < -1:
@@ -1217,8 +1222,82 @@
     sum of the kernel and user-space CPU time"""
     return _process_time_impl(space, w_info, True)
 
+if HAS_THREAD_TIME:
+    if _WIN:
+        _GetCurrentThread = rwin32.winexternal('GetCurrentThread', [], rwin32.HANDLE)
+        _GetThreadTimes = rwin32.winexternal('GetThreadTimes', [rwin32.HANDLE,
+                                                                lltype.Ptr(rwin32.FILETIME),
+                                                                lltype.Ptr(rwin32.FILETIME),
+                                                                lltype.Ptr(rwin32.FILETIME),
+                                                                lltype.Ptr(rwin32.FILETIME)],
+                                                               rwin32.BOOL)
+        def _thread_time_impl(space, w_info, return_ns):
+            thread = _GetCurrentThread()
+
+            with lltype.scoped_alloc(rwin32.FILETIME) as creation_time, \
+                 lltype.scoped_alloc(rwin32.FILETIME) as exit_time, \
+                 lltype.scoped_alloc(rwin32.FILETIME) as kernel_time, \
+                 lltype.scoped_alloc(rwin32.FILETIME) as user_time:
+                ok = _GetThreadTimes(thread, creation_time, exit_time,
+                                     kernel_time, user_time)
+                if not ok:
+                    raise wrap_oserror(space,
+                        rwin32.lastSavedWindowsError("GetThreadTimes"))
+                ktime = (kernel_time.c_dwLowDateTime |
+                         r_ulonglong(kernel_time.c_dwHighDateTime) << 32)
+                utime = (user_time.c_dwLowDateTime |
+                         r_ulonglong(user_time.c_dwHighDateTime) << 32)
+            
+            if w_info is not None:
+                _setinfo(space, w_info, "GetThreadTimes()", 1e-7, True, False)
+
+            # ktime and utime have a resolution of 100 nanoseconds
+            if return_ns:
+                return space.newint((r_int64(ktime) + r_int64(utime)) * 10**2)
+            else:
+                return space.newfloat((float(ktime) + float(utime)) * 1e-7)
+    else:
+        def _thread_time_impl(space, w_info, return_ns):
+            clk_id = rtime.CLOCK_THREAD_CPUTIME_ID
+            implementation = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)"
+
+            with lltype.scoped_alloc(TIMESPEC) as timespec:
+                ret = c_clock_gettime(clk_id, timespec)
+                if ret == 0:
+                    if w_info is not None:
+                        with lltype.scoped_alloc(TIMESPEC) as tsres:
+                            ret = c_clock_getres(clk_id, tsres)
+                            if ret == 0:
+                                res = _timespec_to_seconds(tsres)
+                            else:
+                                res = 1e-9
+                        _setinfo(space, w_info,
+                                 implementation, res, True, False)
+                    if return_ns:
+                        return space.newint(_timespec_to_nanoseconds(timespec))
+                    else:
+                        return space.newfloat(_timespec_to_seconds(timespec))
+
+    def thread_time(space, w_info=None):
+        """thread_time() -> float
+
+        Thread time for profiling: sum of the kernel and user-space CPU time."""
+        return _thread_time_impl(space, w_info, False)
+
+    def thread_time_ns(space, w_info=None):
+        """thread_time_ns() -> int
+
+        Thread time for profiling as nanoseconds:
+        sum of the kernel and user-space CPU time."""
+        return _thread_time_impl(space, w_info, True)
+
 _clock = external('clock', [], rposix.CLOCK_T)
 def _clock_impl(space, w_info, return_ns):
+    space.warn(space.newtext(
+        "time.clock has been deprecated in Python 3.3 and will "
+        "be removed from Python 3.8: "
+        "use time.perf_counter or time.process_time "
+        "instead"), space.w_DeprecationWarning)
     if _WIN:
         try:
             return _win_perf_counter_impl(space, w_info, return_ns)
diff --git a/pypy/module/time/moduledef.py b/pypy/module/time/moduledef.py
--- a/pypy/module/time/moduledef.py
+++ b/pypy/module/time/moduledef.py
@@ -1,6 +1,6 @@
 
 from pypy.interpreter.mixedmodule import MixedModule
-from .interp_time import HAS_MONOTONIC
+from .interp_time import HAS_MONOTONIC, HAS_THREAD_TIME
 from rpython.rlib import rtime
 import os
 
@@ -39,6 +39,9 @@
     if HAS_MONOTONIC:
         interpleveldefs['monotonic'] = 'interp_time.monotonic'
         interpleveldefs['monotonic_ns'] = 'interp_time.monotonic_ns'
+    if HAS_THREAD_TIME:
+        interpleveldefs['thread_time'] = 'interp_time.thread_time'
+        interpleveldefs['thread_time_ns'] = 'interp_time.thread_time_ns'
     if os.name == "posix":
         interpleveldefs['tzset'] = 'interp_time.tzset'
 
diff --git a/pypy/module/time/test/test_time.py b/pypy/module/time/test/test_time.py
--- a/pypy/module/time/test/test_time.py
+++ b/pypy/module/time/test/test_time.py
@@ -21,8 +21,15 @@
         raises(OverflowError, time.sleep, float('inf'))
 
     def test_clock(self):
-        import time
-        time.clock()
+        import time, warnings
+        warnings.simplefilter("always")
+        with warnings.catch_warnings(record=True) as w:
+            time.clock()
+            assert len(w) == 1
+            assert str(w[0].message).startswith(
+                "time.clock has been deprecated in Python 3.3 and will "
+                "be removed from Python 3.8")
+            assert w[0].category == DeprecationWarning
         assert isinstance(time.clock(), float)
 
     def test_time(self):
@@ -90,6 +97,54 @@
         assert abs(time.clock_gettime(time.CLOCK_MONOTONIC) -
                    time.clock_gettime_ns(time.CLOCK_MONOTONIC) * 1e-9) < 0.1
 
+    def test_clock_gettime(self):
+        import time
+        clock_ids = ['CLOCK_REALTIME',
+                     'CLOCK_REALTIME_COARSE',
+                     'CLOCK_MONOTONIC',
+                     'CLOCK_MONOTONIC_COARSE',
+                     'CLOCK_MONOTONIC_RAW',
+                     'CLOCK_BOOTTIME',
+                     'CLOCK_PROCESS_CPUTIME_ID',
+                     'CLOCK_THREAD_CPUTIME_ID',
+                     'CLOCK_HIGHRES',
+                     'CLOCK_PROF',
+                     'CLOCK_UPTIME',]
+        for clock_id in clock_ids:
+            clock = getattr(time, clock_id, None)
+            if clock is None:
+                continue
+            t1 = time.clock_gettime(clock)
+            assert isinstance(t1, float)
+            time.sleep(time.clock_getres(clock))
+            t2 = time.clock_gettime(clock)
+            assert t1 < t2
+
+    def test_clock_gettime(self):
+        import time
+        clock_ids = ['CLOCK_REALTIME',
+                     'CLOCK_REALTIME_COARSE',
+                     'CLOCK_MONOTONIC',
+                     'CLOCK_MONOTONIC_COARSE',
+                     'CLOCK_MONOTONIC_RAW',
+                     'CLOCK_BOOTTIME',
+                     'CLOCK_PROCESS_CPUTIME_ID',
+                     'CLOCK_THREAD_CPUTIME_ID',
+                     'CLOCK_HIGHRES',
+                     'CLOCK_PROF',
+                     'CLOCK_UPTIME',]
+        for clock_id in clock_ids:
+            clock = getattr(time, clock_id, None)
+            if clock is None:
+                continue
+            t1 = time.clock_gettime_ns(clock)
+            assert isinstance(t1, int)
+            time.sleep(time.clock_getres(clock))
+            t2 = time.clock_gettime_ns(clock)
+            assert t1 < t2
+            assert abs(time.clock_gettime(clock) -
+                       time.clock_gettime_ns(clock) * 1e-9) < 0.1
+
     def test_ctime(self):
         import time
         raises(TypeError, time.ctime, "foo")
@@ -235,6 +290,7 @@
         asc = time.asctime((bigyear, 6, 1) + (0,)*6)
         assert asc[-len(str(bigyear)):] == str(bigyear)
         raises(OverflowError, time.asctime, (bigyear + 1,) + (0,)*8)
+        raises(OverflowError, time.asctime, (-bigyear - 2 + 1900,) + (0,)*8)
 
     def test_struct_time(self):
         import time
@@ -481,6 +537,29 @@
         assert (t2 - t1) < 5 * 10**7
         assert abs(time.process_time() - time.process_time_ns() * 1e-9) < 0.1
 
+    def test_thread_time(self):
+        import time
+        if not hasattr(time, 'thread_time'):
+            skip("need time.thread_time")
+        t1 = time.thread_time()
+        assert isinstance(t1, float)
+        time.sleep(0.1)
+        t2 = time.thread_time()
+        # thread_time_time() should not include time spent during sleep
+        assert (t2 - t1) < 0.05
+
+    def test_thread_time_ns(self):
+        import time
+        if not hasattr(time, 'thread_time_ns'):
+            skip("need time.thread_time_ns")
+        t1 = time.thread_time_ns()
+        assert isinstance(t1, int)
+        time.sleep(0.1)
+        t2 = time.process_time_ns()
+        # process_thread_ns() should not include time spent during sleep
+        assert (t2 - t1) < 5 * 10**7
+        assert abs(time.thread_time() - time.thread_time_ns() * 1e-9) < 0.1
+
     def test_get_clock_info(self):
         import time
         clocks = ['clock', 'perf_counter', 'process_time', 'time']
diff --git a/rpython/rlib/rtime.py b/rpython/rlib/rtime.py
--- a/rpython/rlib/rtime.py
+++ b/rpython/rlib/rtime.py
@@ -83,6 +83,7 @@
                   'CLOCK_THREAD_CPUTIME_ID',
                   'CLOCK_HIGHRES',
                   'CLOCK_PROF',
+                  'CLOCK_UPTIME',
 ]
 for const in constant_names:
     setattr(CConfig, const, rffi_platform.DefinedConstantInteger(const))


More information about the pypy-commit mailing list