[pypy-commit] pypy stat_ns: implement the st_xtime_ns fields in stat_result()

rlamy pypy.commits at gmail.com
Mon Apr 18 19:45:29 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: stat_ns
Changeset: r83753:ee90d62e302e
Date: 2016-04-19 00:44 +0100
http://bitbucket.org/pypy/pypy/changeset/ee90d62e302e/

Log:	implement the st_xtime_ns fields in stat_result()

diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -36,10 +36,12 @@
 
     # further fields, not accessible by index (the numbers are still needed
     # but not visible because they are no longer consecutive)
-
-    st_atime = structseqfield(15, "time of last access")
-    st_mtime = structseqfield(16, "time of last modification")
-    st_ctime = structseqfield(17, "time of last status change")
+    st_atime = structseqfield(11, "time of last access")
+    st_mtime = structseqfield(12, "time of last modification")
+    st_ctime = structseqfield(13, "time of last change")
+    st_atime_ns = structseqfield(14, "time of last access in nanoseconds")
+    st_mtime_ns = structseqfield(15, "time of last modification in nanoseconds")
+    st_ctime_ns = structseqfield(16, "time of last change in nanoseconds")
 
     if "st_blksize" in posix._statfields:
         st_blksize = structseqfield(20, "blocksize for filesystem I/O")
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -294,44 +294,56 @@
 
 STAT_FIELDS = unrolling_iterable(enumerate(rposix_stat.STAT_FIELDS))
 
-STATVFS_FIELDS = unrolling_iterable(enumerate(rposix_stat.STATVFS_FIELDS))
+N_INDEXABLE_FIELDS = 10
+
+def _time_ns_from_float(ftime):
+    "Convert a floating-point time (in seconds) into a (s, ns) pair of ints"
+    fracpart, intpart = modf(ftime)
+    if fracpart < 0:
+        fracpart += 1.
+        intpart -= 1.
+    return int(intpart), int(fracpart * 1e9)
+
+ at specialize.arg(4)
+def _fill_time(space, lst, index, w_keywords, attrname, ftime):
+    stat_float_times = space.fromcache(StatState).stat_float_times
+    seconds, fractional_ns = _time_ns_from_float(ftime)
+    lst[index] = space.wrap(seconds)
+    if stat_float_times:
+        space.setitem(w_keywords, space.wrap(attrname), space.wrap(ftime))
+    else:
+        space.setitem(w_keywords, space.wrap(attrname), space.wrap(seconds))
+    w_billion = space.wrap(1000000000)
+    w_total_ns = space.add(space.mul(space.wrap(seconds), w_billion),
+                           space.wrap(fractional_ns))
+    space.setitem(w_keywords, space.wrap(attrname + '_ns'), w_total_ns)
+
+STANDARD_FIELDS = unrolling_iterable(enumerate(rposix_stat.STAT_FIELDS[:7]))
+EXTRA_FIELDS = unrolling_iterable(rposix_stat.STAT_FIELDS[10:])
 
 def build_stat_result(space, st):
-    FIELDS = STAT_FIELDS    # also when not translating at all
-    lst = [None] * rposix_stat.N_INDEXABLE_FIELDS
+    lst = [None] * N_INDEXABLE_FIELDS
     w_keywords = space.newdict()
-    stat_float_times = space.fromcache(StatState).stat_float_times
-    for i, (name, TYPE) in FIELDS:
+    for (i, (name, TYPE)) in STANDARD_FIELDS:
         value = getattr(st, name)
-        if name in ('st_atime', 'st_mtime', 'st_ctime'):
-            value = int(value)   # rounded to an integer for indexed access
         w_value = space.wrap(value)
-        if i < rposix_stat.N_INDEXABLE_FIELDS:
-            lst[i] = w_value
-        else:
-            space.setitem(w_keywords, space.wrap(name), w_value)
+        lst[i] = w_value
 
-    # non-rounded values for name-based access
-    if stat_float_times:
-        space.setitem(w_keywords,
-                      space.wrap('st_atime'), space.wrap(st.st_atime))
-        space.setitem(w_keywords,
-                      space.wrap('st_mtime'), space.wrap(st.st_mtime))
-        space.setitem(w_keywords,
-                      space.wrap('st_ctime'), space.wrap(st.st_ctime))
-    else:
-        space.setitem(w_keywords,
-                      space.wrap('st_atime'), space.wrap(int(st.st_atime)))
-        space.setitem(w_keywords,
-                      space.wrap('st_mtime'), space.wrap(int(st.st_mtime)))
-        space.setitem(w_keywords,
-                      space.wrap('st_ctime'), space.wrap(int(st.st_ctime)))
+    _fill_time(space, lst, 7, w_keywords, 'st_atime', st.st_atime)
+    _fill_time(space, lst, 8, w_keywords, 'st_mtime', st.st_mtime)
+    _fill_time(space, lst, 9, w_keywords, 'st_ctime', st.st_ctime)
+
+    for name, TYPE in EXTRA_FIELDS:
+        value = getattr(st, name)
+        w_value = space.wrap(value)
+        space.setitem(w_keywords, space.wrap(name), w_value)
 
     w_tuple = space.newtuple(lst)
     w_stat_result = space.getattr(space.getbuiltinmodule(os.name),
                                   space.wrap('stat_result'))
     return space.call_function(w_stat_result, w_tuple, w_keywords)
 
+STATVFS_FIELDS = unrolling_iterable(enumerate(rposix_stat.STATVFS_FIELDS))
 
 def build_statvfs_result(space, st):
     vals_w = [None] * len(rposix_stat.STATVFS_FIELDS)


More information about the pypy-commit mailing list