[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
2002年12月10日 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():

AltStyle によって変換されたページ (->オリジナル) /