Commit 9ddf40b4 authored by Tim Peters's avatar Tim Peters

SF patch 876130: add C API to datetime module, from Anthony Tuininga.

The LaTeX is untested (well, so is the new API, for that matter).
Note that I also changed NULL to get spelled consistently in concrete.tex.
If that was a wrong thing to do, Fred should yell at me.
parent 873a277e
This diff is collapsed.
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
#ifndef DATETIME_H #ifndef DATETIME_H
#define DATETIME_H #define DATETIME_H
#ifdef __cplusplus
extern "C" {
#endif
/* Fields are packed into successive bytes, each viewed as unsigned and /* Fields are packed into successive bytes, each viewed as unsigned and
* big-endian, unless otherwise noted: * big-endian, unless otherwise noted:
...@@ -132,6 +135,36 @@ typedef struct ...@@ -132,6 +135,36 @@ typedef struct
(((PyDateTime_Time*)o)->data[4] << 8) | \ (((PyDateTime_Time*)o)->data[4] << 8) | \
((PyDateTime_Time*)o)->data[5]) ((PyDateTime_Time*)o)->data[5])
/* Define structure for C API. */
typedef struct {
/* type objects */
PyTypeObject *DateType;
PyTypeObject *DateTimeType;
PyTypeObject *TimeType;
PyTypeObject *DeltaType;
PyTypeObject *TZInfoType;
/* constructors */
PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*);
PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int,
PyObject*, PyTypeObject*);
PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);
/* constructors for the DB API */
PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*);
PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*);
} PyDateTime_CAPI;
/* "magic" constant used to partially protect against developer mistakes. */
#define DATETIME_API_MAGIC 0x414548d5
#ifdef Py_BUILD_CORE
/* Macros for type checking when building the Python core. */
#define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType) #define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType)
#define PyDate_CheckExact(op) ((op)->ob_type == &PyDateTime_DateType) #define PyDate_CheckExact(op) ((op)->ob_type == &PyDateTime_DateType)
...@@ -147,4 +180,66 @@ typedef struct ...@@ -147,4 +180,66 @@ typedef struct
#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) #define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType)
#define PyTZInfo_CheckExact(op) ((op)->ob_type == &PyDateTime_TZInfoType) #define PyTZInfo_CheckExact(op) ((op)->ob_type == &PyDateTime_TZInfoType)
#else
/* Define global variable for the C API and a macro for setting it. */
static PyDateTime_CAPI *PyDateTimeAPI;
#define PyDateTime_IMPORT \
PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_Import("datetime", \
"datetime_CAPI")
/* This macro would be used if PyCObject_ImportEx() was created.
#define PyDateTime_IMPORT \
PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_ImportEx("datetime", \
"datetime_CAPI", \
DATETIME_API_MAGIC)
*/
/* Macros for type checking when not building the Python core. */
#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType)
#define PyDate_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DateType)
#define PyDateTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateTimeType)
#define PyDateTime_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DateTimeType)
#define PyTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TimeType)
#define PyTime_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->TimeType)
#define PyDelta_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DeltaType)
#define PyDelta_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DeltaType)
#define PyTZInfo_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TZInfoType)
#define PyTZInfo_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->TZInfoType)
/* Macros for accessing constructors in a simplified fashion. */
#define PyDate_FromDate(year, month, day) \
PyDateTimeAPI->Date_FromDate(year, month, day, PyDateTimeAPI->DateType)
#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \
PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, \
min, sec, usec, Py_None, PyDateTimeAPI->DateTimeType)
#define PyTime_FromTime(hour, minute, second, usecond) \
PyDateTimeAPI->Time_FromTime(hour, minute, second, usecond, \
Py_None, PyDateTimeAPI->TimeType)
#define PyDelta_FromDSU(days, seconds, useconds) \
PyDateTimeAPI->Delta_FromDelta(days, seconds, useconds, 1,
PyDateTimeAPI->DeltaType)
/* Macros supporting the DB API. */
#define PyDateTime_FromTimestamp(args) \
PyDateTimeAPI->DateTime_FromTimestamp( \
(PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)
#define PyDate_FromTimestamp(args) \
PyDateTimeAPI->Date_FromTimestamp( \
(PyObject*) (PyDateTimeAPI->DateType), args)
#endif /* Py_BUILD_CORE */
#ifdef __cplusplus
}
#endif
#endif #endif
...@@ -569,6 +569,7 @@ Richard Townsend ...@@ -569,6 +569,7 @@ Richard Townsend
Laurence Tratt Laurence Tratt
John Tromp John Tromp
Jason Trowbridge Jason Trowbridge
Anthony Tuininga
Stephen Turner Stephen Turner
Bill Tutt Bill Tutt
Doobee R. Tzeck Doobee R. Tzeck
......
...@@ -559,6 +559,10 @@ Build ...@@ -559,6 +559,10 @@ Build
C API C API
----- -----
- Thanks to Anthony Tuininga, the datetime module now supplies a C API
containing type-check macros and constructors. See new docs in the
Python/C API Reference Manual for details.
- Private function _PyTime_DoubleToTimet added, to convert a Python - Private function _PyTime_DoubleToTimet added, to convert a Python
timestamp (C double) to platform time_t with some out-of-bounds timestamp (C double) to platform time_t with some out-of-bounds
checking. Declared in new header file timefuncs.h. It would be checking. Declared in new header file timefuncs.h. It would be
......
...@@ -9,7 +9,13 @@ ...@@ -9,7 +9,13 @@
#include <time.h> #include <time.h>
#include "timefuncs.h" #include "timefuncs.h"
/* Differentiate between building the core module and building extension
* modules.
*/
#define Py_BUILD_CORE
#include "datetime.h" #include "datetime.h"
#undef Py_BUILD_CORE
/* We require that C int be at least 32 bits, and use int virtually /* We require that C int be at least 32 bits, and use int virtually
* everywhere. In just a few cases we use a temp long, where a Python * everywhere. In just a few cases we use a temp long, where a Python
...@@ -4520,6 +4526,24 @@ static PyMethodDef module_methods[] = { ...@@ -4520,6 +4526,24 @@ static PyMethodDef module_methods[] = {
{NULL, NULL} {NULL, NULL}
}; };
/* C API. Clients get at this via PyDateTime_IMPORT, defined in
* datetime.h.
*/
static PyDateTime_CAPI CAPI = {
&PyDateTime_DateType,
&PyDateTime_DateTimeType,
&PyDateTime_TimeType,
&PyDateTime_DeltaType,
&PyDateTime_TZInfoType,
new_date_ex,
new_datetime_ex,
new_time_ex,
new_delta_ex,
datetime_fromtimestamp,
date_fromtimestamp
};
PyMODINIT_FUNC PyMODINIT_FUNC
initdatetime(void) initdatetime(void)
{ {
...@@ -4633,6 +4657,12 @@ initdatetime(void) ...@@ -4633,6 +4657,12 @@ initdatetime(void)
Py_INCREF(&PyDateTime_TZInfoType); Py_INCREF(&PyDateTime_TZInfoType);
PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC,
NULL);
if (x == NULL)
return;
PyModule_AddObject(m, "datetime_CAPI", x);
/* A 4-year cycle has an extra leap day over what we'd get from /* A 4-year cycle has an extra leap day over what we'd get from
* pasting together 4 single years. * pasting together 4 single years.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment