summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2021-06-14 23:05:48 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2021-06-14 23:05:48 +0100
commit2eac70786e7034888e43a316f05a39e6063253b6 (patch)
tree8454edf624c4e6b443df4c664435220b969f43b3
parent476a969bd83d94ea80ebce81a6fbb6abc3b9029f (diff)
downloadpsycopg2-2eac70786e7034888e43a316f05a39e6063253b6.tar.gz
Drop support for mx.DateTime objects
They are Python 2 only.
-rw-r--r--NEWS1
-rw-r--r--doc/src/conf.py2
-rw-r--r--doc/src/extensions.rst21
-rw-r--r--doc/src/install.rst1
-rw-r--r--doc/src/usage.rst4
-rw-r--r--lib/extensions.py8
-rw-r--r--psycopg/adapter_mxdatetime.c302
-rw-r--r--psycopg/adapter_mxdatetime.h70
-rw-r--r--psycopg/psycopgmodule.c70
-rw-r--r--psycopg/typecast.c57
-rw-r--r--psycopg/typecast_mxdatetime.c241
-rw-r--r--psycopg2.cproj3
-rw-r--r--setup.cfg6
-rw-r--r--setup.py19
-rwxr-xr-xtests/test_dates.py169
15 files changed, 7 insertions, 967 deletions
diff --git a/NEWS b/NEWS
index b3e1464..51238bf 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ What's new in psycopg 2.9
Other changes:
- Dropped support for Python 2.7, 3.4, 3.5 (:tickets:`#1198, #1000, #1197`).
+- Dropped support for mx.DateTime.
- Build system for Linux/MacOS binary packages moved to GitHub action, now
providing :pep:`600`\-style wheels packages.
diff --git a/doc/src/conf.py b/doc/src/conf.py
index 94f154e..d565c97 100644
--- a/doc/src/conf.py
+++ b/doc/src/conf.py
@@ -128,8 +128,6 @@ rst_epilog = """
.. _transaction isolation level:
https://www.postgresql.org/docs/current/static/transaction-iso.html
-.. _mx.DateTime: https://www.egenix.com/products/python/mxBase/mxDateTime/
-
.. |MVCC| replace:: :abbr:`MVCC (Multiversion concurrency control)`
"""
diff --git a/doc/src/extensions.rst b/doc/src/extensions.rst
index d8c07a4..763910d 100644
--- a/doc/src/extensions.rst
+++ b/doc/src/extensions.rst
@@ -453,13 +453,6 @@ deal with Python objects adaptation:
Specialized adapters for Python datetime objects.
-.. class:: DateFromMx
- TimeFromMx
- TimestampFromMx
- IntervalFromMx
-
- Specialized adapters for `mx.DateTime`_ objects.
-
.. data:: adapters
Dictionary of the currently registered object adapters. Use
@@ -1004,20 +997,6 @@ from the database. See :ref:`unicode-handling` for details.
Typecasters to convert time-related data types to Python `!datetime`
objects.
-.. data:: MXDATE
- MXDATETIME
- MXDATETIMETZ
- MXINTERVAL
- MXTIME
- MXDATEARRAY
- MXDATETIMEARRAY
- MXDATETIMETZARRAY
- MXINTERVALARRAY
- MXTIMEARRAY
-
- Typecasters to convert time-related data types to `mx.DateTime`_ objects.
- Only available if Psycopg was compiled with `!mx` support.
-
.. versionchanged:: 2.2
previously the `DECIMAL` typecaster and the specific time-related
typecasters (`!PY*` and `!MX*`) were not exposed by the `extensions`
diff --git a/doc/src/install.rst b/doc/src/install.rst
index c771c9b..2eb66c8 100644
--- a/doc/src/install.rst
+++ b/doc/src/install.rst
@@ -230,7 +230,6 @@ If you have less standard requirements such as:
- creating a :ref:`debug build <debug-build>`,
- using :program:`pg_config` not in the :envvar:`PATH`,
-- supporting ``mx.DateTime``,
then take a look at the ``setup.cfg`` file.
diff --git a/doc/src/usage.rst b/doc/src/usage.rst
index 335e750..b4ffc85 100644
--- a/doc/src/usage.rst
+++ b/doc/src/usage.rst
@@ -540,7 +540,6 @@ or `!memoryview` (in Python 3).
single: Date objects; Adaptation
single: Time objects; Adaptation
single: Interval objects; Adaptation
- single: mx.DateTime; Adaptation
.. _adapt-date:
@@ -550,8 +549,7 @@ Date/Time objects adaptation
Python builtin `~datetime.datetime`, `~datetime.date`,
`~datetime.time`, `~datetime.timedelta` are converted into PostgreSQL's
:sql:`timestamp[tz]`, :sql:`date`, :sql:`time[tz]`, :sql:`interval` data types.
-Time zones are supported too. The Egenix `mx.DateTime`_ objects are adapted
-the same way::
+Time zones are supported too.
>>> dt = datetime.datetime.now()
>>> dt
diff --git a/lib/extensions.py b/lib/extensions.py
index 1de6607..f941e02 100644
--- a/lib/extensions.py
+++ b/lib/extensions.py
@@ -42,14 +42,6 @@ from psycopg2._psycopg import ( # noqa
ROWIDARRAY, STRINGARRAY, TIME, TIMEARRAY, UNICODE, UNICODEARRAY,
AsIs, Binary, Boolean, Float, Int, QuotedString, )
-try:
- from psycopg2._psycopg import ( # noqa
- MXDATE, MXDATETIME, MXDATETIMETZ, MXINTERVAL, MXTIME, MXDATEARRAY,
- MXDATETIMEARRAY, MXDATETIMETZARRAY, MXINTERVALARRAY, MXTIMEARRAY,
- DateFromMx, TimeFromMx, TimestampFromMx, IntervalFromMx, )
-except ImportError:
- pass
-
from psycopg2._psycopg import ( # noqa
PYDATE, PYDATETIME, PYDATETIMETZ, PYINTERVAL, PYTIME, PYDATEARRAY,
PYDATETIMEARRAY, PYDATETIMETZARRAY, PYINTERVALARRAY, PYTIMEARRAY,
diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c
deleted file mode 100644
index 125bd14..0000000
--- a/psycopg/adapter_mxdatetime.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* adapter_mxdatetime.c - mx date/time objects
- *
- * Copyright (C) 2003-2019 Federico Di Gregorio <fog@debian.org>
- * Copyright (C) 2020 The Psycopg Team
- *
- * This file is part of psycopg.
- *
- * psycopg2 is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link this program with the OpenSSL library (or with
- * modified versions of OpenSSL that use the same license as OpenSSL),
- * and distribute linked combinations including the two.
- *
- * You must obey the GNU Lesser General Public License in all respects for
- * all of the code used other than OpenSSL.
- *
- * psycopg2 is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- */
-
-#define PSYCOPG_MODULE
-#include "psycopg/psycopg.h"
-
-#include "psycopg/adapter_mxdatetime.h"
-#include "psycopg/microprotocols_proto.h"
-
-#include <mxDateTime.h>
-#include <string.h>
-
-
-/* Return 0 on success, -1 on failure, but don't set an exception */
-
-int
-psyco_adapter_mxdatetime_init(void)
-{
- if (mxDateTime_ImportModuleAndAPI()) {
- Dprintf("psyco_adapter_mxdatetime_init: mx.DateTime initialization failed");
- PyErr_Clear();
- return -1;
- }
- return 0;
-}
-
-
-/* mxdatetime_str, mxdatetime_getquoted - return result of quoting */
-
-static PyObject *
-mxdatetime_str(mxdatetimeObject *self)
-{
- mxDateTimeObject *dt;
- mxDateTimeDeltaObject *dtd;
- char buf[128] = { 0, };
-
- switch (self->type) {
-
- case PSYCO_MXDATETIME_DATE:
- dt = (mxDateTimeObject *)self->wrapped;
- if (dt->year >= 1)
- PyOS_snprintf(buf, sizeof(buf) - 1, "'%04ld-%02d-%02d'::date",
- dt->year, (int)dt->month, (int)dt->day);
- else
- PyOS_snprintf(buf, sizeof(buf) - 1, "'%04ld-%02d-%02d BC'::date",
- 1 - dt->year, (int)dt->month, (int)dt->day);
- break;
-
- case PSYCO_MXDATETIME_TIMESTAMP:
- dt = (mxDateTimeObject *)self->wrapped;
- if (dt->year >= 1)
- PyOS_snprintf(buf, sizeof(buf) - 1,
- "'%04ld-%02d-%02dT%02d:%02d:%09.6f'::timestamp",
- dt->year, (int)dt->month, (int)dt->day,
- (int)dt->hour, (int)dt->minute, dt->second);
- else
- PyOS_snprintf(buf, sizeof(buf) - 1,
- "'%04ld-%02d-%02dT%02d:%02d:%09.6f BC'::timestamp",
- 1 - dt->year, (int)dt->month, (int)dt->day,
- (int)dt->hour, (int)dt->minute, dt->second);
- break;
-
- case PSYCO_MXDATETIME_TIME:
- case PSYCO_MXDATETIME_INTERVAL:
- /* given the limitation of the mx.DateTime module that uses the same
- type for both time and delta values we need to do some black magic
- and make sure we're not using an adapt()ed interval as a simple
- time */
- dtd = (mxDateTimeDeltaObject *)self->wrapped;
- if (0 <= dtd->seconds && dtd->seconds < 24*3600) {
- PyOS_snprintf(buf, sizeof(buf) - 1, "'%02d:%02d:%09.6f'::time",
- (int)dtd->hour, (int)dtd->minute, dtd->second);
- } else {
- double ss = dtd->hour*3600.0 + dtd->minute*60.0 + dtd->second;
-
- if (dtd->seconds >= 0)
- PyOS_snprintf(buf, sizeof(buf) - 1, "'%ld days %.6f seconds'::interval",
- dtd->day, ss);
- else
- PyOS_snprintf(buf, sizeof(buf) - 1, "'-%ld days -%.6f seconds'::interval",
- dtd->day, ss);
- }
- break;
- }
-
- return PyString_FromString(buf);
-}
-
-static PyObject *
-mxdatetime_getquoted(mxdatetimeObject *self, PyObject *args)
-{
- return mxdatetime_str(self);
-}
-
-static PyObject *
-mxdatetime_conform(mxdatetimeObject *self, PyObject *args)
-{
- PyObject *res, *proto;
-
- if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
-
- if (proto == (PyObject*)&isqlquoteType)
- res = (PyObject*)self;
- else
- res = Py_None;
-
- Py_INCREF(res);
- return res;
-}
-
-/** the MxDateTime object **/
-
-/* object member list */
-
-static struct PyMemberDef mxdatetimeObject_members[] = {
- {"adapted", T_OBJECT, offsetof(mxdatetimeObject, wrapped), READONLY},
- {"type", T_INT, offsetof(mxdatetimeObject, type), READONLY},
- {NULL}
-};
-
-/* object method table */
-
-static PyMethodDef mxdatetimeObject_methods[] = {
- {"getquoted", (PyCFunction)mxdatetime_getquoted, METH_NOARGS,
- "getquoted() -> wrapped object value as SQL date/time"},
- {"__conform__", (PyCFunction)mxdatetime_conform, METH_VARARGS, NULL},
- {NULL} /* Sentinel */
-};
-
-/* initialization and finalization methods */
-
-static int
-mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type)
-{
- Dprintf("mxdatetime_setup: init mxdatetime object at %p, refcnt = "
- FORMAT_CODE_PY_SSIZE_T,
- self, Py_REFCNT(self)
- );
-
- self->type = type;
- Py_INCREF(obj);
- self->wrapped = obj;
-
- Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = "
- FORMAT_CODE_PY_SSIZE_T,
- self, Py_REFCNT(self)
- );
- return 0;
-}
-
-static void
-mxdatetime_dealloc(PyObject* obj)
-{
- mxdatetimeObject *self = (mxdatetimeObject *)obj;
-
- Py_CLEAR(self->wrapped);
-
- Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = "
- FORMAT_CODE_PY_SSIZE_T,
- obj, Py_REFCNT(obj)
- );
-
- Py_TYPE(obj)->tp_free(obj);
-}
-
-static int
-mxdatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
-{
- PyObject *mx;
- int type = -1; /* raise an error if type was not passed! */
-
- if (!PyArg_ParseTuple(args, "O|i", &mx, &type))
- return -1;
-
- return mxdatetime_setup((mxdatetimeObject *)obj, mx, type);
-}
-
-static PyObject *
-mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- return type->tp_alloc(type, 0);
-}
-
-
-/* object type */
-
-#define mxdatetimeType_doc \
-"MxDateTime(mx, type) -> new mx.DateTime wrapper object"
-
-PyTypeObject mxdatetimeType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "psycopg2._psycopg.MxDateTime",
- sizeof(mxdatetimeObject), 0,
- mxdatetime_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- (reprfunc)mxdatetime_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
- mxdatetimeType_doc, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- mxdatetimeObject_methods, /*tp_methods*/
- mxdatetimeObject_members, /*tp_members*/
- 0, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- mxdatetime_init, /*tp_init*/
- 0, /*tp_alloc*/
- mxdatetime_new, /*tp_new*/
-};
-
-
-/** module-level functions **/
-
-PyObject *
-psyco_DateFromMx(PyObject *self, PyObject *args)
-{
- PyObject *mx;
-
- if (!PyArg_ParseTuple(args, "O!", mxDateTime.DateTime_Type, &mx))
- return NULL;
-
- return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
- PSYCO_MXDATETIME_DATE);
-}
-
-PyObject *
-psyco_TimeFromMx(PyObject *self, PyObject *args)
-{
- PyObject *mx;
-
- if (!PyArg_ParseTuple(args, "O!", mxDateTime.DateTimeDelta_Type, &mx))
- return NULL;
-
- return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
- PSYCO_MXDATETIME_TIME);
-}
-
-PyObject *
-psyco_TimestampFromMx(PyObject *self, PyObject *args)
-{
- PyObject *mx;
-
- if (!PyArg_ParseTuple(args, "O!", mxDateTime.DateTime_Type, &mx))
- return NULL;
-
- return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
- PSYCO_MXDATETIME_TIMESTAMP);
-}
-
-PyObject *
-psyco_IntervalFromMx(PyObject *self, PyObject *args)
-{
- PyObject *mx;
-
- if (!PyArg_ParseTuple(args, "O!", mxDateTime.DateTime_Type, &mx))
- return NULL;
-
- return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
- PSYCO_MXDATETIME_INTERVAL);
-}
diff --git a/psycopg/adapter_mxdatetime.h b/psycopg/adapter_mxdatetime.h
deleted file mode 100644
index 93d5932..0000000
--- a/psycopg/adapter_mxdatetime.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* adapter_mxdatetime.h - definition for the mx date/time types
- *
- * Copyright (C) 2003-2019 Federico Di Gregorio <fog@debian.org>
- * Copyright (C) 2020 The Psycopg Team
- *
- * This file is part of psycopg.
- *
- * psycopg2 is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link this program with the OpenSSL library (or with
- * modified versions of OpenSSL that use the same license as OpenSSL),
- * and distribute linked combinations including the two.
- *
- * You must obey the GNU Lesser General Public License in all respects for
- * all of the code used other than OpenSSL.
- *
- * psycopg2 is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- */
-
-#ifndef PSYCOPG_MXDATETIME_H
-#define PSYCOPG_MXDATETIME_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern HIDDEN PyTypeObject mxdatetimeType;
-
-typedef struct {
- PyObject_HEAD
-
- PyObject *wrapped;
- int type;
-#define PSYCO_MXDATETIME_TIME 0
-#define PSYCO_MXDATETIME_DATE 1
-#define PSYCO_MXDATETIME_TIMESTAMP 2
-#define PSYCO_MXDATETIME_INTERVAL 3
-
-} mxdatetimeObject;
-
-HIDDEN int psyco_adapter_mxdatetime_init(void);
-
-HIDDEN PyObject *psyco_DateFromMx(PyObject *module, PyObject *args);
-#define psyco_DateFromMx_doc \
- "DateFromMx(mx) -> new date"
-
-HIDDEN PyObject *psyco_TimeFromMx(PyObject *module, PyObject *args);
-#define psyco_TimeFromMx_doc \
- "TimeFromMx(mx) -> new time"
-
-HIDDEN PyObject *psyco_TimestampFromMx(PyObject *module, PyObject *args);
-#define psyco_TimestampFromMx_doc \
- "TimestampFromMx(mx) -> new timestamp"
-
-HIDDEN PyObject *psyco_IntervalFromMx(PyObject *module, PyObject *args);
-#define psyco_IntervalFromMx_doc \
- "IntervalFromMx(mx) -> new interval"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !defined(PSYCOPG_MXDATETIME_H) */
diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c
index acb6781..57c56ee 100644
--- a/psycopg/psycopgmodule.c
+++ b/psycopg/psycopgmodule.c
@@ -53,11 +53,6 @@
#include "psycopg/adapter_list.h"
#include "psycopg/typecast_binary.h"
-#ifdef HAVE_MXDATETIME
-#include <mxDateTime.h>
-#include "psycopg/adapter_mxdatetime.h"
-#endif
-
/* some module-level variables, like the datetime module */
#include <datetime.h>
#include "psycopg/adapter_datetime.h"
@@ -358,30 +353,6 @@ adapters_init(PyObject *module)
if (0 > microprotocols_add(PyDateTimeAPI->DeltaType, NULL, obj)) { goto exit; }
Py_CLEAR(obj);
-#ifdef HAVE_MXDATETIME
- /* As above, we use the callable objects from the psycopg module.
- These object are not be available at runtime if mx.DateTime import
- failed (e.g. it was available at build time but not at runtime). */
- if (PyMapping_HasKeyString(dict, "TimestampFromMx")) {
- if (!(obj = PyMapping_GetItemString(dict, "TimestampFromMx"))) {
- goto exit;
- }
- if (0 > microprotocols_add(mxDateTime.DateTime_Type, NULL, obj)) {
- goto exit;
- }
- Py_CLEAR(obj);
-
- /* if we found the above, we have this too. */
- if (!(obj = PyMapping_GetItemString(dict, "TimeFromMx"))) {
- goto exit;
- }
- if (0 > microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, obj)) {
- goto exit;
- }
- Py_CLEAR(obj);
- }
-#endif
-
/* Success! */
rv = 0;
@@ -943,34 +914,6 @@ datetime_init(void)
return 0;
}
-RAISES_NEG static int
-mxdatetime_init(PyObject *module)
-{
- Dprintf("psycopgmodule: initializing mx.DateTime module");
-
-#ifdef HAVE_MXDATETIME
- Py_SET_TYPE(&mxdatetimeType, &PyType_Type);
- if (0 > PyType_Ready(&mxdatetimeType)) { return -1; }
-
- if (mxDateTime_ImportModuleAndAPI()) {
- Dprintf("psycopgmodule: mx.DateTime module import failed");
- PyErr_Clear();
- }
-
- /* If we can't find mx.DateTime objects at runtime,
- * remove them from the module (and, as consequence, from the adapters). */
- if (0 != psyco_adapter_mxdatetime_init()) {
- PyObject *dict;
- if (!(dict = PyModule_GetDict(module))) { return -1; }
- if (0 > PyDict_DelItemString(dict, "DateFromMx")) { return -1; }
- if (0 > PyDict_DelItemString(dict, "TimeFromMx")) { return -1; }
- if (0 > PyDict_DelItemString(dict, "TimestampFromMx")) { return -1; }
- if (0 > PyDict_DelItemString(dict, "IntervalFromMx")) { return -1; }
- }
-#endif
- return 0;
-}
-
/** method table and module initialization **/
static PyMethodDef psycopgMethods[] = {
@@ -1014,18 +957,6 @@ static PyMethodDef psycopgMethods[] = {
{"IntervalFromPy", (PyCFunction)psyco_IntervalFromPy,
METH_VARARGS, psyco_IntervalFromPy_doc},
-#ifdef HAVE_MXDATETIME
- /* to be deleted if not found at import time */
- {"DateFromMx", (PyCFunction)psyco_DateFromMx,
- METH_VARARGS, psyco_DateFromMx_doc},
- {"TimeFromMx", (PyCFunction)psyco_TimeFromMx,
- METH_VARARGS, psyco_TimeFromMx_doc},
- {"TimestampFromMx", (PyCFunction)psyco_TimestampFromMx,
- METH_VARARGS, psyco_TimestampFromMx_doc},
- {"IntervalFromMx", (PyCFunction)psyco_IntervalFromMx,
- METH_VARARGS, psyco_IntervalFromMx_doc},
-#endif
-
{"set_wait_callback", (PyCFunction)psyco_set_wait_callback,
METH_O, psyco_set_wait_callback_doc},
{"get_wait_callback", (PyCFunction)psyco_get_wait_callback,
@@ -1086,7 +1017,6 @@ INIT_MODULE(_psycopg)(void)
if (0 > add_module_constants(module)) { goto exit; }
if (0 > add_module_types(module)) { goto exit; }
if (0 > datetime_init()) { goto exit; }
- if (0 > mxdatetime_init(module)) { goto exit; }
if (0 > encodings_init(module)) { goto exit; }
if (0 > typecast_init(module)) { goto exit; }
if (0 > adapters_init(module)) { goto exit; }
diff --git a/psycopg/typecast.c b/psycopg/typecast.c
index 4f713b1..3ac51e7 100644
--- a/psycopg/typecast.c
+++ b/psycopg/typecast.c
@@ -32,15 +32,6 @@
/* useful function used by some typecasters */
-#ifdef HAVE_MXDATETIME
-static const char *
-skip_until_space(const char *s)
-{
- while (*s && *s != ' ') s++;
- return s;
-}
-#endif
-
static const char *
skip_until_space2(const char *s, Py_ssize_t *len)
{
@@ -82,11 +73,11 @@ typecast_parse_date(const char* s, const char** t, Py_ssize_t* len,
cz += 1;
}
- /* Is this a BC date? If so, adjust the year value. Note that
- * mx.DateTime numbers BC dates from zero rather than one. The
- * Python datetime module does not support BC dates at all. */
+ /* Is this a BC date? If so, adjust the year value. However
+ * Python datetime module does not support BC dates, so this will raise
+ * an exception downstream. */
if (*len >= 2 && s[*len-2] == 'B' && s[*len-1] == 'C')
- *year = 1 - (*year);
+ *year = -(*year);
if (t != NULL) *t = s;
@@ -175,11 +166,6 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
#include "psycopg/typecast_basic.c"
#include "psycopg/typecast_binary.c"
#include "psycopg/typecast_datetime.c"
-
-#ifdef HAVE_MXDATETIME
-#include "psycopg/typecast_mxdatetime.c"
-#endif
-
#include "psycopg/typecast_array.c"
static long int typecast_default_DEFAULT[] = {0};
@@ -218,29 +204,6 @@ static typecastObject_initlist typecast_pydatetime[] = {
{NULL, NULL, NULL}
};
-#ifdef HAVE_MXDATETIME
-#define typecast_MXDATETIMEARRAY_cast typecast_GENERIC_ARRAY_cast
-#define typecast_MXDATETIMETZARRAY_cast typecast_GENERIC_ARRAY_cast
-#define typecast_MXDATEARRAY_cast typecast_GENERIC_ARRAY_cast
-#define typecast_MXTIMEARRAY_cast typecast_GENERIC_ARRAY_cast
-#define typecast_MXINTERVALARRAY_cast typecast_GENERIC_ARRAY_cast
-
-/* a list of initializers, used to make the typecasters accessible anyway */
-static typecastObject_initlist typecast_mxdatetime[] = {
- {"MXDATETIME", typecast_DATETIME_types, typecast_MXDATE_cast},
- {"MXDATETIMETZ", typecast_DATETIMETZ_types, typecast_MXDATE_cast},
- {"MXTIME", typecast_TIME_types, typecast_MXTIME_cast},
- {"MXDATE", typecast_DATE_types, typecast_MXDATE_cast},
- {"MXINTERVAL", typecast_INTERVAL_types, typecast_MXINTERVAL_cast},
- {"MXDATETIMEARRAY", typecast_DATETIMEARRAY_types, typecast_MXDATETIMEARRAY_cast, "MXDATETIME"},
- {"MXDATETIMETZARRAY", typecast_DATETIMETZARRAY_types, typecast_MXDATETIMETZARRAY_cast, "MXDATETIMETZ"},
- {"MXTIMEARRAY", typecast_TIMEARRAY_types, typecast_MXTIMEARRAY_cast, "MXTIME"},
- {"MXDATEARRAY", typecast_DATEARRAY_types, typecast_MXDATEARRAY_cast, "MXDATE"},
- {"MXINTERVALARRAY", typecast_INTERVALARRAY_types, typecast_MXINTERVALARRAY_cast, "MXINTERVAL"},
- {NULL, NULL, NULL}
-};
-#endif
-
/** the type dictionary and associated functions **/
@@ -291,18 +254,6 @@ typecast_init(PyObject *module)
psyco_default_cast = typecast_from_c(&typecast_default, dict);
/* register the date/time typecasters with their original names */
-#ifdef HAVE_MXDATETIME
- if (0 == typecast_mxdatetime_init()) {
- for (i = 0; typecast_mxdatetime[i].name != NULL; i++) {
- t = (typecastObject *)typecast_from_c(&(typecast_mxdatetime[i]), dict);
- if (t == NULL) { goto exit; }
- PyDict_SetItem(dict, t->name, (PyObject *)t);
- Py_DECREF((PyObject *)t);
- t = NULL;
- }
- }
-#endif
-
if (0 > typecast_datetime_init()) { goto exit; }
for (i = 0; typecast_pydatetime[i].name != NULL; i++) {
t = (typecastObject *)typecast_from_c(&(typecast_pydatetime[i]), dict);
diff --git a/psycopg/typecast_mxdatetime.c b/psycopg/typecast_mxdatetime.c
deleted file mode 100644
index d308f13..0000000
--- a/psycopg/typecast_mxdatetime.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* typecast_mxdatetime.c - date and time typecasting functions to mx types
- *
- * Copyright (C) 2001-2019 Federico Di Gregorio <fog@debian.org>
- * Copyright (C) 2020 The Psycopg Team
- *
- * This file is part of psycopg.
- *
- * psycopg2 is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link this program with the OpenSSL library (or with
- * modified versions of OpenSSL that use the same license as OpenSSL),
- * and distribute linked combinations including the two.
- *
- * You must obey the GNU Lesser General Public License in all respects for
- * all of the code used other than OpenSSL.
- *
- * psycopg2 is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- */
-
-#include "mxDateTime.h"
-
-
-/* Return 0 on success, -1 on failure, but don't set an exception */
-
-static int
-typecast_mxdatetime_init(void)
-{
- if (mxDateTime_ImportModuleAndAPI()) {
- Dprintf("typecast_mxdatetime_init: mx.DateTime initialization failed");
- PyErr_Clear();
- return -1;
- }
- return 0;
-}
-
-
-/** DATE - cast a date into mx.DateTime python object **/
-
-static PyObject *
-typecast_MXDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
-{
- int n, y=0, m=0, d=0;
- int hh=0, mm=0, ss=0, us=0, tz=0;
- const char *tp = NULL;
-
- if (str == NULL) { Py_RETURN_NONE; }
-
- Dprintf("typecast_MXDATE_cast: s = %s", str);
-
- /* check for infinity */
- if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
- if (str[0] == '-') {
- return mxDateTime.DateTime_FromDateAndTime(-999998,1,1, 0,0,0);
- }
- else {
- return mxDateTime.DateTime_FromDateAndTime(999999,12,31, 0,0,0);
- }
- }
-
- n = typecast_parse_date(str, &tp, &len, &y, &m, &d);
- Dprintf("typecast_MXDATE_cast: tp = %p n = %d,"
- " len = " FORMAT_CODE_PY_SSIZE_T ","
- " y = %d, m = %d, d = %d", tp, n, len, y, m, d);
- if (n != 3) {
- PyErr_SetString(DataError, "unable to parse date");
- return NULL;
- }
-
- if (len > 0) {
- n = typecast_parse_time(tp, NULL, &len, &hh, &mm, &ss, &us, &tz);
- Dprintf("typecast_MXDATE_cast: n = %d,"
- " len = " FORMAT_CODE_PY_SSIZE_T ","
- " hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
- n, len, hh, mm, ss, us, tz);
- if (n != 0 && (n < 3 || n > 6)) {
- PyErr_SetString(DataError, "unable to parse time");
- return NULL;
- }
- }
-
- Dprintf("typecast_MXDATE_cast: fractionary seconds: %lf",
- (double)ss + (double)us/(double)1000000.0);
- return mxDateTime.DateTime_FromDateAndTime(y, m, d, hh, mm,
- (double)ss + (double)us/(double)1000000.0);
-}
-
-/** TIME - parse time into an mx.DateTime object **/
-
-static PyObject *
-typecast_MXTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
-{
- int n, hh=0, mm=0, ss=0, us=0, tz=0;
-
- if (str == NULL) { Py_RETURN_NONE; }
-
- Dprintf("typecast_MXTIME_cast: s = %s", str);
-
- n = typecast_parse_time(str, NULL, &len, &hh, &mm, &ss, &us, &tz);
- Dprintf("typecast_MXTIME_cast: time parsed, %d components", n);
- Dprintf("typecast_MXTIME_cast: hh = %d, mm = %d, ss = %d, us = %d",
- hh, mm, ss, us);
-
- if (n < 3 || n > 6) {
- PyErr_SetString(DataError, "unable to parse time");
- return NULL;
- }
-
- Dprintf("typecast_MXTIME_cast: fractionary seconds: %lf",
- (double)ss + (double)us/(double)1000000.0);
- return mxDateTime.DateTimeDelta_FromTime(hh, mm,
- (double)ss + (double)us/(double)1000000.0);
-}
-
-/** INTERVAL - parse an interval into an mx.DateTimeDelta **/
-
-static PyObject *
-typecast_MXINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
-{
- long years = 0, months = 0, days = 0, denominator = 1;
- double hours = 0.0, minutes = 0.0, seconds = 0.0, hundredths = 0.0;
- double v = 0.0, sign = 1.0;
- int part = 0;
-
- if (str == NULL) { Py_RETURN_NONE; }
-
- Dprintf("typecast_MXINTERVAL_cast: s = %s", str);
-
- while (*str) {
- switch (*str) {
-
- case '-':
- sign = -1.0;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- v = v * 10.0 + (double)(*str - '0');
- Dprintf("typecast_MXINTERVAL_cast: v = %f", v);
- if (part == 6){
- denominator *= 10;
- Dprintf("typecast_MXINTERVAL_cast: denominator = %ld",
- denominator);
- }
- break;
-
- case 'y':
- if (part == 0) {
- years = (long)(v*sign);
- str = skip_until_space(str);
- Dprintf("typecast_MXINTERVAL_cast: years = %ld, rest = %s",
- years, str);
- v = 0.0; sign = 1.0; part = 1;
- }
- break;
-
- case 'm':
- if (part <= 1) {
- months = (long)(v*sign);
- str = skip_until_space(str);
- Dprintf("typecast_MXINTERVAL_cast: months = %ld, rest = %s",
- months, str);
- v = 0.0; sign = 1.0; part = 2;
- }
- break;
-
- case 'd':
- if (part <= 2) {
- days = (long)(v*sign);
- str = skip_until_space(str);
- Dprintf("typecast_MXINTERVAL_cast: days = %ld, rest = %s",
- days, str);
- v = 0.0; sign = 1.0; part = 3;
- }
- break;
-
- case ':':
- if (part <= 3) {
- hours = v;
- Dprintf("typecast_MXINTERVAL_cast: hours = %f", hours);
- v = 0.0; part = 4;
- }
- else if (part == 4) {
- minutes = v;
- Dprintf("typecast_MXINTERVAL_cast: minutes = %f", minutes);
- v = 0.0; part = 5;
- }
- break;
-
- case '.':
- if (part == 5) {
- seconds = v;
- Dprintf("typecast_MXINTERVAL_cast: seconds = %f", seconds);
- v = 0.0; part = 6;
- }
- break;
-
- default:
- break;
- }
-
- str++;
- }
-
- /* manage last value, be it minutes or seconds or hundredths of a second */
- if (part == 4) {
- minutes = v;
- Dprintf("typecast_MXINTERVAL_cast: minutes = %f", minutes);
- }
- else if (part == 5) {
- seconds = v;
- Dprintf("typecast_MXINTERVAL_cast: seconds = %f", seconds);
- }
- else if (part == 6) {
- hundredths = v;
- Dprintf("typecast_MXINTERVAL_cast: hundredths = %f", hundredths);
- hundredths = hundredths/denominator;
- Dprintf("typecast_MXINTERVAL_cast: fractions = %.20f", hundredths);
- }
-
- /* calculates seconds */
- if (sign < 0.0) {
- seconds = - (hundredths + seconds + minutes*60 + hours*3600);
- }
- else {
- seconds += hundredths + minutes*60 + hours*3600;
- }
-
- /* calculates days */
- days += years*365 + months*30;
-
- Dprintf("typecast_MXINTERVAL_cast: days = %ld, seconds = %f",
- days, seconds);
- return mxDateTime.DateTimeDelta_FromDaysAndSeconds(days, seconds);
-}
diff --git a/psycopg2.cproj b/psycopg2.cproj
index af752d2..4c23278 100644
--- a/psycopg2.cproj
+++ b/psycopg2.cproj
@@ -58,7 +58,6 @@
<None Include="psycopg\adapter_binary.h" />
<None Include="psycopg\adapter_datetime.h" />
<None Include="psycopg\adapter_list.h" />
- <None Include="psycopg\adapter_mxdatetime.h" />
<None Include="psycopg\adapter_pboolean.h" />
<None Include="psycopg\adapter_qstring.h" />
<None Include="psycopg\config.h" />
@@ -166,7 +165,6 @@
<Compile Include="psycopg\adapter_binary.c" />
<Compile Include="psycopg\adapter_datetime.c" />
<Compile Include="psycopg\adapter_list.c" />
- <Compile Include="psycopg\adapter_mxdatetime.c" />
<Compile Include="psycopg\adapter_pboolean.c" />
<Compile Include="psycopg\adapter_qstring.c" />
<Compile Include="psycopg\connection_int.c" />
@@ -187,7 +185,6 @@
<Compile Include="psycopg\typecast_binary.c" />
<Compile Include="psycopg\typecast_builtins.c" />
<Compile Include="psycopg\typecast_datetime.c" />
- <Compile Include="psycopg\typecast_mxdatetime.c" />
<Compile Include="psycopg\utils.c" />
<Compile Include="psycopg\win32_support.c" />
<Compile Include="psycopg\lobject_int.c" />
diff --git a/setup.cfg b/setup.cfg
index 43c61d1..0432855 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,16 +1,12 @@
[build_ext]
# PSYCOPG_DEBUG can be added to enable verbose debug information
-define=
+define=PSYCOPG_DEBUG
# "pg_config" is required to locate PostgreSQL headers and libraries needed to
# build psycopg2. If pg_config is not in the path or is installed under a
# different name set the following option to the pg_config full path.
pg_config=
-# If the build system does not find the mx.DateTime headers, try
-# setting its value to the right path.
-mx_include_dir=
-
# For Windows only:
# Set to 1 if the PostgreSQL library was built with OpenSSL.
# Required to link in OpenSSL libraries and dependencies.
diff --git a/setup.py b/setup.py
index 2cdb7c2..a844db1 100644
--- a/setup.py
+++ b/setup.py
@@ -230,7 +230,6 @@ class psycopg_build_ext(build_ext):
def initialize_options(self):
build_ext.initialize_options(self)
self.pgdir = None
- self.mx_include_dir = None
self.have_ssl = have_ssl
self.static_libpq = static_libpq
self.pg_config = None
@@ -497,24 +496,6 @@ depends = [
parser = configparser.ConfigParser()
parser.read('setup.cfg')
-# check for mx package
-mxincludedir = ''
-if parser.has_option('build_ext', 'mx_include_dir'):
- mxincludedir = parser.get('build_ext', 'mx_include_dir')
-if not mxincludedir:
- # look for mxDateTime.h; prefer one located in venv
- candidate_dirs = [os.path.join(d, 'mx', 'DateTime', 'mxDateTime') for d in sys.path] \
- + [os.path.join(get_python_inc(plat_specific=1), "mx")]
- candidate_dirs = [d for d in candidate_dirs if os.path.exists(os.path.join(d, 'mxDateTime.h'))] or ['']
- mxincludedir = candidate_dirs[0]
-if mxincludedir.strip() and os.path.exists(mxincludedir):
- # Build the support for mx: we will check at runtime if it can be imported
- include_dirs.append(mxincludedir)
- define_macros.append(('HAVE_MXDATETIME', '1'))
- sources.append('adapter_mxdatetime.c')
- depends.extend(['adapter_mxdatetime.h', 'typecast_mxdatetime.c'])
- version_flags.append('mx')
-
# generate a nice version string to avoid confusion when users report bugs
version_flags.append('pq3') # no more a choice
version_flags.append('ext') # no more a choice
diff --git a/tests/test_dates.py b/tests/test_dates.py
index 4ba1455..728bb57 100755
--- a/tests/test_dates.py
+++ b/tests/test_dates.py
@@ -33,12 +33,6 @@ from psycopg2.tz import FixedOffsetTimezone, ZERO
import unittest
from .testutils import ConnectingTestCase, skip_before_postgres, skip_if_crdb
-try:
- from mx.DateTime import Date, Time, DateTime, DateTimeDeltaFrom
-except ImportError:
- # Tests will be skipped
- pass
-
def total_seconds(d):
"""Return total number of seconds of a timedelta as a float."""
@@ -456,169 +450,6 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
self.assertRaises(psycopg2.NotSupportedError, cur.fetchone)
-@unittest.skipUnless(
- hasattr(psycopg2._psycopg, 'MXDATETIME'),
- 'Requires mx.DateTime support'
-)
-class mxDateTimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
- """Tests for the mx.DateTime based date handling in psycopg2."""
-
- def setUp(self):
- ConnectingTestCase.setUp(self)
- self.curs = self.conn.cursor()
- self.DATE = psycopg2._psycopg.MXDATE
- self.TIME = psycopg2._psycopg.MXTIME
- self.DATETIME = psycopg2._psycopg.MXDATETIME
- self.INTERVAL = psycopg2._psycopg.MXINTERVAL
-
- psycopg2.extensions.register_type(self.DATE, self.conn)
- psycopg2.extensions.register_type(self.TIME, self.conn)
- psycopg2.extensions.register_type(self.DATETIME, self.conn)
- psycopg2.extensions.register_type(self.INTERVAL, self.conn)
- psycopg2.extensions.register_type(psycopg2.extensions.MXDATEARRAY, self.conn)
- psycopg2.extensions.register_type(psycopg2.extensions.MXTIMEARRAY, self.conn)
- psycopg2.extensions.register_type(
- psycopg2.extensions.MXDATETIMEARRAY, self.conn)
- psycopg2.extensions.register_type(
- psycopg2.extensions.MXINTERVALARRAY, self.conn)
-
- def tearDown(self):
- self.conn.close()
-
- def test_parse_bc_date(self):
- value = self.DATE('00042-01-01 BC', self.curs)
- self.assert_(value is not None)
- # mx.DateTime numbers BC dates from 0 rather than 1.
- self.assertEqual(value.year, -41)
- self.assertEqual(value.month, 1)
- self.assertEqual(value.day, 1)
-
- def test_parse_bc_datetime(self):
- value = self.DATETIME('00042-01-01 13:30:29 BC', self.curs)
- self.assert_(value is not None)
- # mx.DateTime numbers BC dates from 0 rather than 1.
- self.assertEqual(value.year, -41)
- self.assertEqual(value.month, 1)
- self.assertEqual(value.day, 1)
- self.assertEqual(value.hour, 13)
- self.assertEqual(value.minute, 30)
- self.assertEqual(value.second, 29)
-
- def test_parse_time_microseconds(self):
- value = self.TIME('13:30:29.123456', self.curs)
- self.assertEqual(math.floor(value.second), 29)
- self.assertEqual(
- int((value.second - math.floor(value.second)) * 1000000), 123456)
-
- def test_parse_datetime_microseconds(self):
- value = self.DATETIME('2007-01-01 13:30:29.123456', self.curs)
- self.assertEqual(math.floor(value.second), 29)
- self.assertEqual(
- int((value.second - math.floor(value.second)) * 1000000), 123456)
-
- def test_parse_time_timezone(self):
- # Time zone information is ignored.
- expected = Time(13, 30, 29)
- self.assertEqual(expected, self.TIME("13:30:29+01", self.curs))
- self.assertEqual(expected, self.TIME("13:30:29-01", self.curs))
- self.assertEqual(expected, self.TIME("13:30:29+01:15", self.curs))
- self.assertEqual(expected, self.TIME("13:30:29-01:15", self.curs))
- self.assertEqual(expected, self.TIME("13:30:29+01:15:42", self.curs))
- self.assertEqual(expected, self.TIME("13:30:29-01:15:42", self.curs))
-
- def test_parse_datetime_timezone(self):
- # Time zone information is ignored.
- expected = DateTime(2007, 1, 1, 13, 30, 29)
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29+01", self.curs))
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29-01", self.curs))
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29+01:15", self.curs))
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29-01:15", self.curs))
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29+01:15:42", self.curs))
- self.assertEqual(
- expected, self.DATETIME("2007-01-01 13:30:29-01:15:42", self.curs))
-
- def test_parse_interval(self):
- value = self.INTERVAL('42 days 05:50:05', self.curs)
- self.assert_(value is not None)
- self.assertEqual(value.day, 42)
- self.assertEqual(value.hour, 5)
- self.assertEqual(value.minute, 50)
- self.assertEqual(value.second, 5)
-
- def test_adapt_time(self):
- value = self.execute('select (%s)::time::text',
- [Time(13, 30, 29)])
- self.assertEqual(value, '13:30:29')
-
- def test_adapt_datetime(self):
- value = self.execute('select (%s)::timestamp::text',
- [DateTime(2007, 1, 1, 13, 30, 29.123456)])
- self.assertEqual(value, '2007-01-01 13:30:29.123456')
-
- def test_adapt_bc_datetime(self):
- value = self.execute('select (%s)::timestamp::text',
- [DateTime(-41, 1, 1, 13, 30, 29.123456)])
- # microsecs for BC timestamps look not available in PG < 8.4
- # but more likely it's determined at compile time.
- self.assert_(value in (
- '0042-01-01 13:30:29.123456 BC',
- '0042-01-01 13:30:29 BC'), value)
-
- def test_adapt_timedelta(self):
- value = self.execute('select extract(epoch from (%s)::interval)',
- [DateTimeDeltaFrom(days=42,
- seconds=45296.123456)])
- seconds = math.floor(value)
- self.assertEqual(seconds, 3674096)
- self.assertEqual(int(round((value - seconds) * 1000000)), 123456)
-
- def test_adapt_negative_timedelta(self):
- value = self.execute('select extract(epoch from (%s)::interval)',
- [DateTimeDeltaFrom(days=-42,
- seconds=45296.123456)])
- seconds = math.floor(value)
- self.assertEqual(seconds, -3583504)
- self.assertEqual(int(round((value - seconds) * 1000000)), 123456)
-
- def _test_type_roundtrip(self, o1):
- o2 = self.execute("select %s;", (o1,))
- self.assertEqual(type(o1), type(o2))
-
- def _test_type_roundtrip_array(self, o1):
- o1 = [o1]
- o2 = self.execute("select %s;", (o1,))
- self.assertEqual(type(o1[0]), type(o2[0]))
-
- def test_type_roundtrip_date(self):
- self._test_type_roundtrip(Date(2010, 5, 3))
-
- def test_type_roundtrip_datetime(self):
- self._test_type_roundtrip(DateTime(2010, 5, 3, 10, 20, 30))
-
- def test_type_roundtrip_time(self):
- self._test_type_roundtrip(Time(10, 20, 30))
-
- def test_type_roundtrip_interval(self):
- self._test_type_roundtrip(DateTimeDeltaFrom(seconds=30))
-
- def test_type_roundtrip_date_array(self):
- self._test_type_roundtrip_array(Date(2010, 5, 3))
-
- def test_type_roundtrip_datetime_array(self):
- self._test_type_roundtrip_array(DateTime(2010, 5, 3, 10, 20, 30))
-
- def test_type_roundtrip_time_array(self):
- self._test_type_roundtrip_array(Time(10, 20, 30))
-
- def test_type_roundtrip_interval_array(self):
- self._test_type_roundtrip_array(DateTimeDeltaFrom(seconds=30))
-
-
class FromTicksTestCase(unittest.TestCase):
# bug "TimestampFromTicks() throws ValueError (2-2.0.14)"
# reported by Jozsef Szalay on 2010-05-06