Attached patch defines a new type struct_timespec for the time module. A new capsule exports the type along with to/from converters - opening a bridge for C, and for example the datetime module.

Your comments welcomed. If people feel this is worth the effort and going the right direction, I should be able to finish doco, unit-tests, whatever else is missing with a bit of guidance and move on other datetime aspects.

Regards,
Matthieu


diff -r 5754f069b123 Include/timemodule.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Include/timemodule.h	Wed Dec 17 18:21:28 2014 -0800
@@ -0,0 +1,56 @@
+#ifndef Py_TIMEMODULE_H
+#define Py_TIMEMODULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+typedef struct timespec _PyTime_timespec;
+#else
+typedef struct {
+    time_t       tv_sec;   /* seconds */
+    long         tv_nsec;  /* nanoseconds */
+} _PyTime_timespec;
+#endif
+
+
+#define PyTime_CAPSULE_NAME "time._C_API"
+
+typedef struct {
+    PyTypeObject *StrucTimespecType;
+    PyObject *(*PyStructTimespecFromCStructTimespec)(_PyTime_timespec *);
+    int (*PyStructTimespecToCStructTimespec)(PyObject*, _PyTime_timespec *);
+} PyTime_C_API;
+
+
+#ifndef TIME_MODULE
+
+static PyTime_C_API *api = NULL;
+
+#define PyStructTimespecFromCStructTimespec \
+ api->PyStructTimespecFromCStructTimespec
+
+#define PyStructTimespecToCStructTimespec \
+ api->PyStructTimespecToCStructTimespec
+
+#define StructTimespec_Check(op) \
+  PyObject_TypeCheck(op, api->StrucTimespecType)
+
+#define StructTimespec_CheckExact(op) \
+  (Py_TYPE(op) == api->StrucTimespecType)
+
+static int
+import_time(void)
+{
+    api = (PyTime_C_API*)PyCapsule_Import(PyTime_CAPSULE_NAME, 0);
+    return (api != NULL) ? 0 : -1;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(Py_TIMEMODULE_H) */
+
diff -r 5754f069b123 Modules/timemodule.c
--- a/Modules/timemodule.c	Sat Nov 22 12:54:57 2014 -0800
+++ b/Modules/timemodule.c	Wed Dec 17 18:21:28 2014 -0800
@@ -30,6 +30,9 @@
 #endif /* MS_WINDOWS */
 #endif /* !__WATCOMC__ || __QNX__ */
 
+#define TIME_MODULE
+#include "timemodule.h"
+
 /* Forward declarations */
 static int floatsleep(double);
 static PyObject* floattime(_Py_clock_info_t *info);
@@ -270,8 +273,25 @@
     9,
 };
 
+static PyStructSequence_Field struct_timespec_type_fields[] = {
+    {"tv_sec", "seconds"},
+    {"tv_nsec", "nanoseconds"},
+    {0}
+};
+
+static PyStructSequence_Desc struct_timespec_type_desc = {
+    "time.struct_timespec",
+    "POSIX.1b structure for a time value.",
+    struct_timespec_type_fields,
+    2,
+};
+
+
 static int initialized;
 static PyTypeObject StructTimeType;
+static PyTypeObject StrucTimespecType;
+#define StructTimespec_Check(op) PyObject_TypeCheck(op, &StrucTimespecType)
+#define StructTimespec_CheckExact(op) (Py_TYPE(op) == &StrucTimespecType)
 
 
 static PyObject *
@@ -1284,13 +1304,13 @@
 PyDoc_STRVAR(module_doc,
 "This module provides various functions to manipulate time values.\n\
 \n\
-There are two standard representations of time.  One is the number\n\
+There are three standard representations of time.  One is the number\n\
 of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an integer\n\
 or a floating point number (to represent fractions of seconds).\n\
 The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
 The actual value can be retrieved by calling gmtime(0).\n\
 \n\
-The other representation is a tuple of 9 integers giving local time.\n\
+Another representation is a tuple of 9 integers giving local time.\n\
 The tuple items are:\n\
   year (including century, e.g. 1998)\n\
   month (1-12)\n\
@@ -1305,6 +1325,11 @@
 if it is 1, the time is given in the DST time zone;\n\
 if it is -1, mktime() should guess based on the date and time.\n\
 \n\
+The other representation is a tuple of 2 integers similar to Posix.1b\n\
+struct timespec. The tuple items are:\n\
+  seconds\n\
+  nanoseconds (0-999999999)\n\
+\n\
 Variables:\n\
 \n\
 timezone -- difference in seconds between UTC and local standard time\n\
@@ -1340,10 +1365,51 @@
     NULL
 };
 
+/*
+ * C API capsule
+ */
+
+static PyObject *
+PyStructTimespecFromCStructTimespec(_PyTime_timespec * ts)
+{
+    PyObject *v = PyStructSequence_New(&StrucTimespecType);
+    if (v == NULL)
+        return NULL;
+
+#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
+    SET(0, ts->tv_sec);
+    SET(1, ts->tv_nsec);
+#undef SET
+    if (PyErr_Occurred()) {
+        Py_XDECREF(v);
+        return NULL;
+    }
+
+    return v;        
+}
+
+int PyStructTimespecToCStructTimespec(PyObject* obj, _PyTime_timespec * ts)
+{
+
+    if (! StructTimespec_Check(obj))
+        return -1;
+
+    ts->tv_sec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,0));
+    ts->tv_nsec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,1));
+
+    return 0;
+}
+
+static PyTime_C_API api = {
+    &StrucTimespecType,
+    &PyStructTimespecFromCStructTimespec,
+    &PyStructTimespecToCStructTimespec
+};
+
 PyMODINIT_FUNC
 PyInit_time(void)
 {
-    PyObject *m;
+    PyObject *m, *c;
     m = PyModule_Create(&timemodule);
     if (m == NULL)
         return NULL;
@@ -1355,14 +1421,25 @@
         if (PyStructSequence_InitType2(&StructTimeType,
                                        &struct_time_type_desc) < 0)
             return NULL;
+        if (PyStructSequence_InitType2(&StrucTimespecType,
+                                       &struct_timespec_type_desc) < 0)
+            return NULL;
     }
     Py_INCREF(&StructTimeType);
+    Py_INCREF(&StrucTimespecType);
 #ifdef HAVE_STRUCT_TM_TM_ZONE
     PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 11);
 #else
     PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9);
 #endif
     PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType);
+    PyModule_AddObject(m, "struct_timespec", (PyObject*) &StrucTimespecType);
+
+    c = PyCapsule_New(&api, PyTime_CAPSULE_NAME, NULL);
+    if (c == NULL)
+        return NULL;
+    PyModule_AddObject(m, "_C_API", c);
+
     initialized = 1;
     return m;
 }
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to