[pypy-commit] pypy py3k-clock_get_info: Commit what I have so far so I can test on windows. Everything added might not work properly. (Tests certainly don't pass)
marky1991
pypy.commits at gmail.com
Fri May 27 21:19:43 EDT 2016
Author: Mark Young <marky1991 at gmail.com>
Branch: py3k-clock_get_info
Changeset: r84755:855624d777e9
Date: 2016-05-17 00:07 -0400
http://bitbucket.org/pypy/pypy/changeset/855624d777e9/
Log: Commit what I have so far so I can test on windows. Everything added
might not work properly. (Tests certainly don't pass)
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -417,7 +417,7 @@
RegrTest('test_threading.py', usemodules="thread", core=True),
RegrTest('test_threading_local.py', usemodules="thread", core=True),
RegrTest('test_threadsignals.py', usemodules="thread"),
- RegrTest('test_time.py', core=True),
+ RegrTest('test_time.py', core=True, usemodules="struct"),
RegrTest('test_timeit.py'),
RegrTest('test_timeout.py'),
RegrTest('test_tk.py'),
diff --git a/pypy/module/time/__init__.py b/pypy/module/time/__init__.py
--- a/pypy/module/time/__init__.py
+++ b/pypy/module/time/__init__.py
@@ -40,6 +40,7 @@
'struct_time': 'app_time.struct_time',
'__doc__': 'app_time.__doc__',
'strptime': 'app_time.strptime',
+ 'get_clock_info': 'app_time.get_clock_info'
}
def startup(self, space):
diff --git a/pypy/module/time/app_time.py b/pypy/module/time/app_time.py
--- a/pypy/module/time/app_time.py
+++ b/pypy/module/time/app_time.py
@@ -1,7 +1,8 @@
# NOT_RPYTHON
from _structseq import structseqtype, structseqfield
-
+from types import SimpleNamespace
+import time
class struct_time(metaclass=structseqtype):
__module__ = 'time'
name = 'time.struct_time'
@@ -26,6 +27,28 @@
import _strptime # from the CPython standard library
return _strptime._strptime_time(string, format)
+def get_clock_info(name):
+ info = SimpleNamespace()
+ info.implementation = ""
+ info.monotonic = 0
+ info.adjustable = 0
+ info.resolution = 1.0
+ print(id(info), "id in app")
+
+ if name == "time":
+ time.time(info)
+ elif name == "monotonic":
+ time.monotonic(info)
+ elif name == "clock":
+ time.clock(info)
+ elif name == "perf_counter":
+ time.perf_counter(info)
+ elif name == "process_time":
+ time.process_time(info)
+ else:
+ raise ValueError("unknown clock")
+ return info
+
__doc__ = """This module provides various functions to manipulate time values.
There are two standard representations of time. One is the number
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
@@ -103,6 +103,14 @@
def get_interrupt_event(self):
return globalState.interrupt_event
+ # Can I just use one of the state classes above?
+ # I don't really get why an instance is better than a plain module
+ # attr, but following advice from armin
+ class TimeState(object):
+ def __init__(self):
+ self.n_overflow = 0
+ self.last_ticks = 0
+ time_state = TimeState()
_includes = ["time.h"]
if _POSIX:
@@ -118,6 +126,7 @@
clock_t = platform.SimpleType("clock_t", rffi.ULONG)
has_gettimeofday = platform.Has('gettimeofday')
has_clock_gettime = platform.Has('clock_gettime')
+ has_gettickcount64 = platform.Has("GetTickCount64")
CLOCK_PROF = platform.DefinedConstantInteger('CLOCK_PROF')
CLOCK_CONSTANTS = ['CLOCK_HIGHRES', 'CLOCK_MONOTONIC', 'CLOCK_MONOTONIC_RAW',
@@ -185,6 +194,7 @@
CLOCKS_PER_SEC = cConfig.CLOCKS_PER_SEC
HAS_CLOCK_GETTIME = cConfig.has_clock_gettime
+HAS_GETTICKCOUNT64 = cConfig.has_gettickcount64
clock_t = cConfig.clock_t
tm = cConfig.tm
glob_buf = lltype.malloc(tm, flavor='raw', zero=True, immortal=True)
@@ -503,18 +513,19 @@
Return the current time in seconds since the Epoch.
Fractions of a second may be present if the system clock provides them."""
-
secs = pytime.time()
return space.wrap(secs)
-def clock(space):
- """clock() -> floating point number
-
- Return the CPU time or real time since the start of the process or since
- the first call to clock(). This has as much precision as the system
- records."""
-
- return space.wrap(pytime.clock())
+# TODO: Remember what this is for...
+def get_time_time_clock_info(space, w_info):
+ # Can't piggy back on time.time because time.time delegates to the
+ # host python's time.time (so we can't see the internals)
+ if HAS_CLOCK_GETTIME:
+ try:
+ res = clock_getres(space, cConfig.CLOCK_REALTIME)
+ except OperationError:
+ res = 1e-9
+ #else: ???
def ctime(space, w_seconds=None):
"""ctime([seconds]) -> string
@@ -717,9 +728,51 @@
if _WIN:
# untested so far
_GetTickCount64 = rwin32.winexternal('GetTickCount64', [], rffi.ULONGLONG)
+ _GetTickCount = rwin32.winexternal('GetTickCount', [], rwin32.DWORD)
+ LPDWORD = rwin32.LPDWORD
+ _GetSystemTimeAdjustment = rwin32.winexternal(
+ 'GetSystemTimeAdjustment',
+ [LPDWORD, LPDWORD, rffi.INTP],
+ rffi.INT)
- def monotonic(space):
- return space.wrap(_GetTickCount64() * 1e-3)
+ def monotonic(space, w_info=None):
+ result = 0
+ if HAS_GETTICKCOUNT64:
+ result = _GetTickCount64() * 1e-3
+ else:
+ ticks = _GetTickCount()
+ if ticks < time_state.last_ticks:
+ time_state.n_overflow += 1
+ time_state.last_ticks = ticks
+ result = math.ldexp(time_state.n_overflow, 32)
+ result = result + ticks
+ result = result * 1e-3
+
+ if w_info is not None:
+ if HAS_GETTICKCOUNT64:
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("GetTickCount64()"))
+ else:
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("GetTickCount()"))
+ resolution = 1e-7
+ with lltype.scoped_alloc(rwin32.LPDWORD) as time_adjustment, \
+ lltype.scoped_alloc(rwin32.LPDWORD) as time_increment, \
+ lltype.scoped_alloc(rwin32.FILETIME) as is_time_adjustment_disabled:
+ ok = _GetSystemTimeAdjustment(time_adjustment,
+ time_increment,
+ is_time_adjustment_disabled)
+ if not ok:
+ # Is this right? Cargo culting...
+ raise wrap_windowserror(space,
+ rwin32.lastSavedWindowsError("GetSystemTimeAdjustment"))
+ resolution = resolution * time_increment
+
+ space.setattr(w_info, space.wrap("monotonic"), space.w_True)
+ space.setattr(w_info, space.wrap("adjustable"), space.w_False)
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(resolution))
+ return space.wrap(result)
elif _MACOSX:
c_mach_timebase_info = external('mach_timebase_info',
@@ -730,13 +783,23 @@
timebase_info = lltype.malloc(cConfig.TIMEBASE_INFO, flavor='raw',
zero=True, immortal=True)
- def monotonic(space):
+ def monotonic(space, w_info=None):
if rffi.getintfield(timebase_info, 'c_denom') == 0:
c_mach_timebase_info(timebase_info)
time = rffi.cast(lltype.Signed, c_mach_absolute_time())
numer = rffi.getintfield(timebase_info, 'c_numer')
denom = rffi.getintfield(timebase_info, 'c_denom')
nanosecs = time * numer / denom
+ if w_info is not None:
+ space.setattr(w_info, space.wrap("monotonic"), space.w_True)
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("mach_absolute_time()"))
+ space.setattr(w_info, space.wrap("adjustable"), space.w_False)
+ space.setattr(w_info, space.wrap("resolution"),
+ #Do I need to convert to float indside the division?
+ # Looking at the C, I would say yes, but nanosecs
+ # doesn't...
+ space.wrap((numer / denom) * 1e-9))
secs = nanosecs / 10**9
rest = nanosecs % 10**9
return space.wrap(float(secs) + float(rest) * 1e-9)
@@ -744,21 +807,49 @@
else:
assert _POSIX
if cConfig.CLOCK_HIGHRES is not None:
- def monotonic(space):
+ def monotonic(space, w_info=None):
+ if w_info is not None:
+ space.setattr(w_info, space.wrap("monotonic"), space.w_True)
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("clock_gettime(CLOCK_HIGHRES)"))
+ space.setattr(w_info, space.wrap("adjustable"), space.w_False)
+ try:
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(clock_getres(space, cConfig.CLOCK_HIGHRES)))
+ except OSError:
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(1e-9))
+
return clock_gettime(space, cConfig.CLOCK_HIGHRES)
else:
- def monotonic(space):
+ def monotonic(space, w_info=None):
+ if w_info is not None:
+ space.setattr(w_info, space.wrap("monotonic"), space.w_True)
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("clock_gettime(CLOCK_MONOTONIC)"))
+ space.setattr(w_info, space.wrap("adjustable"), space.w_False)
+ try:
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(clock_getres(space, cConfig.CLOCK_MONOTONIC)))
+ except OSError:
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(1e-9))
+
return clock_gettime(space, cConfig.CLOCK_MONOTONIC)
+if _WIN:
+ def perf_counter(space, w_info=None):
+ # What if the windows perf counter fails?
+ # Cpython falls back to monotonic and then clock
+ # Shouldn't we?
+ # TODO: Discuss on irc
-if _WIN:
- def perf_counter(space):
+ # TODO: Figure out how to get at the internals of this
return space.wrap(win_perf_counter())
else:
- def perf_counter(space):
- return monotonic(space)
-
+ def perf_counter(space, w_info=None):
+ return monotonic(space, w_info=w_info)
if _WIN:
# untested so far
@@ -810,3 +901,54 @@
cpu_time = float(tms.c_tms_utime + tms.c_tms_stime)
return space.wrap(cpu_time / rposix.CLOCK_TICKS_PER_SECOND)
return clock(space)
+
+if _WIN:
+ def clock(space, w_info=None):
+ """clock() -> floating point number
+
+ Return the CPU time or real time since the start of the process or since
+ the first call to clock(). This has as much precision as the system
+ records."""
+ return space.wrap(win_perf_counter(space, w_info=w_info))
+
+else:
+ _clock = external('clock', [], clock_t)
+ def clock(space, w_info=None):
+ """clock() -> floating point number
+
+ Return the CPU time or real time since the start of the process or since
+ the first call to clock(). This has as much precision as the system
+ records."""
+ value = _clock()
+ #Is this casting correct?
+ if value == rffi.cast(clock_t, -1):
+ raise RunTimeError("the processor time used is not available "
+ "or its value cannot be represented")
+
+ print(w_info, "INFO")
+ if w_info is not None:
+ space.setattr(w_info, space.wrap("implementation"),
+ space.wrap("clock()"))
+ space.setattr(w_info, space.wrap("resolution"),
+ space.wrap(1.0 / CLOCKS_PER_SEC))
+ space.setattr(w_info, space.wrap("monotonic"),
+ space.w_True)
+ space.setattr(w_info, space.wrap("adjustable"),
+ space.w_False)
+ return space.wrap((1.0 * value) / CLOCKS_PER_SEC)
+
+
+def get_clock_info_dict(space, name):
+ if name == "time":
+ return 5#floattime(info)
+ elif name == "monotonic":
+ return monotonic(info)
+ elif name == "clock":
+ return clock(info)
+ elif name == "perf_counter":
+ return perf_counter(info)
+ elif name == "process_time":
+ return 5#process_time(info)
+ else:
+ raise ValueError("unknown clock")
+
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
@@ -379,3 +379,21 @@
t2 = time.process_time()
# process_time() should not include time spent during sleep
assert (t2 - t1) < 0.05
+
+ def test_get_clock_info_monotonic(self):
+ import time
+ clock_info = time.get_clock_info("monotonic")
+ assert clock_info.monotonic
+ assert not clock_info.adjustable
+ # Not really sure what to test about this
+ # At least this tests that the attr exists...
+ assert clock_info.resolution > 0
+
+ def test_get_clock_info_clock(self):
+ import time
+ clock_info = time.get_clock_info("clock")
+ assert clock_info.monotonic
+ assert not clock_info.adjustable
+ # Not really sure what to test about this
+ # At least this tests that the attr exists...
+ assert clock_info.resolution > 0
More information about the pypy-commit
mailing list