[Python-checkins] python/nondist/sandbox/datetime obj_tzinfo.c,NONE,1.1 datetime.c,1.53,1.54 datetime.h,1.13,1.14 doc.txt,1.42,1.43 test_both.py,1.57,1.58 test_datetime.py,1.61,1.62
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Tue, 10 Dec 2002 17:47:23 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv30696
Modified Files:
datetime.c datetime.h doc.txt test_both.py test_datetime.py
Added Files:
obj_tzinfo.c
Log Message:
Gave the tzinfo abstract base class a C implementation, and moved the
tests for it into test_both.
I never tried to implement an abstract base class in C before, and had
lots of problems, mostly cured by poking 0 into type slots. Some Guido
who knows what he's doing here should review obj_tzinfo.c!
--- NEW FILE: obj_tzinfo.c ---
/*
* PyDateTime_TZInfo implementation.
*/
/* This is a pure abstract base class, so doesn't do anything beyond
* raising NotImplemented exceptions. Real tzinfo classes need
* to derive from this. This is mostly for clarity, and for efficiency in
* datetimetz and timetz constructors (their tzinfo arguments need to
* be subclasses of this tzinfo class, which is easy and quick to check).
*/
static PyObject *
tzinfo_nogo(const char* methodname)
{
PyErr_Format(PyExc_NotImplementedError,
"a tzinfo subclass must implement %s()",
methodname);
return NULL;
}
/* Constructors -- you can't actually construct one of these! Well,
* you can, via fooling __new__, but you can't do much with it.
*/
static int
tzinfo_init(PyDateTime_TZInfo *self, PyObject *args, PyObject *kw)
{
(void)tzinfo_nogo("__init__");
return -1;
}
/* Methods. A subclass must implement these. */
static PyObject*
tzinfo_tzname(PyTypeObject *self, PyObject *dt)
{
return tzinfo_nogo("tzname");
}
static PyObject*
tzinfo_utcoffset(PyTypeObject *self, PyObject *dt)
{
return tzinfo_nogo("utcoffset");
}
static PyObject*
tzinfo_dst(PyTypeObject *self, PyObject *dt)
{
return tzinfo_nogo("dst");
}
static PyMethodDef tzinfo_methods[] = {
{"tzname", (PyCFunction)tzinfo_tzname, METH_O,
PyDoc_STR("datetime -> string name of time zone.")},
{"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
PyDoc_STR("datetime -> minutes east of UTC (negative for "
"west of UTC).")},
{"dst", (PyCFunction)tzinfo_dst, METH_O,
PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
{NULL, NULL}
};
static char tzinfo_doc[] =
PyDoc_STR("Abstract base class for time zone info objects.");
statichere PyTypeObject PyDateTime_TZInfoType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
/* XXX When this module is renamed to datetime, change tp_name. */
"_datetime.tzinfo", /* tp_name */
sizeof(PyDateTime_TZInfo), /* tp_basicsize */
0, /* tp_itemsize */
0, /* 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 */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
tzinfo_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
tzinfo_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)tzinfo_init, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
};
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -C2 -d -r1.53 -r1.54
*** datetime.c 10 Dec 2002 02:04:26 -0000 1.53
--- datetime.c 11 Dec 2002 01:47:20 -0000 1.54
***************
*** 72,75 ****
--- 72,76 ----
static PyTypeObject PyDateTime_DeltaType;
static PyTypeObject PyDateTime_TimeType;
+ static PyTypeObject PyDateTime_TZInfoType;
static PyTypeObject PyDateTime_TimeTZType;
***************
*** 665,668 ****
--- 666,670 ----
#include "obj_datetime.c"
#include "obj_time.c"
+ #include "obj_tzinfo.c"
#include "obj_timetz.c"
***************
*** 704,707 ****
--- 706,711 ----
if (PyType_Ready(&PyDateTime_TimeType) < 0)
return;
+ if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
+ return;
if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
return;
***************
*** 802,805 ****
--- 806,812 ----
Py_INCREF(&PyDateTime_TimeType);
PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
+
+ Py_INCREF(&PyDateTime_TZInfoType);
+ PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
Py_INCREF(&PyDateTime_TimeTZType);
Index: datetime.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** datetime.h 10 Dec 2002 02:04:26 -0000 1.13
--- datetime.h 11 Dec 2002 01:47:20 -0000 1.14
***************
*** 67,70 ****
--- 67,75 ----
} PyDateTime_Delta;
+ typedef struct
+ {
+ PyObject_HEAD /* a pure abstract base clase */
+ } PyDateTime_TZInfo;
+
/* Apply for date instances. */
#define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \
Index: doc.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v
retrieving revision 1.42
retrieving revision 1.43
diff -C2 -d -r1.42 -r1.43
*** doc.txt 10 Dec 2002 21:59:51 -0000 1.42
--- doc.txt 11 Dec 2002 01:47:20 -0000 1.43
***************
*** 1,13 ****
TODO/OPEN
=========
- - Implement an abstract base tzinfo class. Variant tzinfo classes must
- subclass from this.
-
- datetimetz needs a C implementation.
- timetz needs a C implementation.
- - tzinfo needs a C implementation.
-
- LaTeXize the docs.
--- 1,8 ----
***************
*** 17,20 ****
--- 12,23 ----
CLOSED
======
+ - tzinfo needs a C implementation.
+ Done.
+
+ - Implement an abstract base tzinfo class. Variant tzinfo classes must
+ subclass from this.
+ Done.
+
+
- Subclass relationships. Currently datetime is a subclass of date.
I like this in practice, and think it's theoretically sound too.
Index: test_both.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_both.py,v
retrieving revision 1.57
retrieving revision 1.58
diff -C2 -d -r1.57 -r1.58
*** test_both.py 9 Dec 2002 19:50:33 -0000 1.57
--- test_both.py 11 Dec 2002 01:47:20 -0000 1.58
***************
*** 41,44 ****
--- 41,45 ----
timedelta = datetime.timedelta
time = datetime.time
+ tzinfo = datetime.tzinfo
MINYEAR = datetime.MINYEAR
MAXYEAR = datetime.MAXYEAR
***************
*** 54,57 ****
--- 55,102 ----
#############################################################################
+ # tzinfo tests
+
+ class NotEnough(tzinfo):
+ def __init__(self, offset, name):
+ self.__offset = offset
+ self.__name = name
+
+ class FixedOffset(tzinfo):
+ def __init__(self, offset, name):
+ self.__offset = offset
+ self.__name = name
+ def __repr__(self):
+ return self.__name.lower()
+ def utcoffset(self, dt):
+ return self.__offset
+ def tzname(self, dt):
+ return self.__name
+ def dst(self, dt):
+ return 0
+
+ class TestTZInfo(unittest.TestCase):
+
+ def test_abstractness(self):
+ self.assertRaises(NotImplementedError, tzinfo)
+
+ def test_subclass_must_override(self):
+ self.failUnless(issubclass(NotEnough, tzinfo))
+ ne = NotEnough(3, "NotByALongShot")
+ self.failUnless(isinstance(ne, tzinfo))
+
+ dt = datetime.datetime.now()
+ self.assertRaises(NotImplementedError, ne.tzname, dt)
+ self.assertRaises(NotImplementedError, ne.utcoffset, dt)
+ self.assertRaises(NotImplementedError, ne.dst, dt)
+
+ def test_normal(self):
+ fo = FixedOffset(3, "Three")
+ self.failUnless(isinstance(fo, tzinfo))
+ for dt in datetime.datetime.now(), None:
+ self.assertEqual(fo.utcoffset(dt), 3)
+ self.assertEqual(fo.tzname(dt), "Three")
+ self.assertEqual(fo.dst(dt), 0)
+
+ #############################################################################
# timedelta tests
***************
*** 1397,1400 ****
--- 1442,1446 ----
allsuites = [unittest.makeSuite(klass, 'test')
for klass in (TestModule,
+ TestTZInfo,
TestTimeDelta,
TestDateOnly,
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.61
retrieving revision 1.62
diff -C2 -d -r1.61 -r1.62
*** test_datetime.py 10 Dec 2002 20:44:24 -0000 1.61
--- test_datetime.py 11 Dec 2002 01:47:20 -0000 1.62
***************
*** 16,24 ****
tzinfo, MINYEAR, MAXYEAR
- class NotEnough(tzinfo):
- def __init__(self, offset, name):
- self.__offset = offset
- self.__name = name
-
class FixedOffset(tzinfo):
def __init__(self, offset, name):
--- 16,19 ----
***************
*** 34,60 ****
return 0
- class TestTZInfo(unittest.TestCase):
-
- def test_abstractness(self):
- self.assertRaises(NotImplementedError, tzinfo)
-
- def test_subclass_must_override(self):
- self.failUnless(issubclass(NotEnough, tzinfo))
- ne = NotEnough(3, "NotByALongShot")
- self.failUnless(isinstance(ne, tzinfo))
-
- dt = datetime.now()
- self.assertRaises(NotImplementedError, ne.tzname, dt)
- self.assertRaises(NotImplementedError, ne.utcoffset, dt)
- self.assertRaises(NotImplementedError, ne.dst, dt)
-
- def test_normal(self):
- fo = FixedOffset(3, "Three")
- self.failUnless(isinstance(fo, tzinfo))
- for dt in datetime.now(), None:
- self.assertEqual(fo.utcoffset(dt), 3)
- self.assertEqual(fo.tzname(dt), "Three")
- self.assertEqual(fo.dst(dt), 0)
-
class TestTimeTZ(unittest.TestCase):
--- 29,32 ----
***************
*** 170,178 ****
def test_suite():
- s3 = unittest.makeSuite(TestTZInfo, 'test')
s4 = unittest.makeSuite(TestTimeTZ, 'test')
s5 = unittest.makeSuite(TestDateTime, 'test')
s6 = unittest.makeSuite(TestDateTimeTZ, 'test')
! return unittest.TestSuite([s3, s4, s5, s6])
def test_main():
--- 142,149 ----
def test_suite():
s4 = unittest.makeSuite(TestTimeTZ, 'test')
s5 = unittest.makeSuite(TestDateTime, 'test')
s6 = unittest.makeSuite(TestDateTimeTZ, 'test')
! return unittest.TestSuite([s4, s5, s6])
def test_main():