[Python-checkins] r63887 - in python/trunk: Lib/test/test_datetime.py Misc/NEWS Modules/datetimemodule.c

gregory.p.smith python-checkins at python.org
Tue Jun 3 20:57:03 CEST 2008


Author: gregory.p.smith
Date: Mon Jun  2 06:05:52 2008
New Revision: 63887

Log:
Fix issue 2782: be less strict about the format string type in strftime.
Accept unicode and anything else ParseTuple "s#" can deal with.  This
matches the time.strftime behavior.


Modified:
   python/trunk/Lib/test/test_datetime.py
   python/trunk/Misc/NEWS
   python/trunk/Modules/datetimemodule.c

Modified: python/trunk/Lib/test/test_datetime.py
==============================================================================
--- python/trunk/Lib/test/test_datetime.py	(original)
+++ python/trunk/Lib/test/test_datetime.py	Mon Jun  2 06:05:52 2008
@@ -850,9 +850,13 @@
         self.assertRaises(TypeError, t.strftime, "one", "two") # too many args
         self.assertRaises(TypeError, t.strftime, 42) # arg wrong type
 
+        # test that unicode input is allowed (issue 2782)
+        self.assertEqual(t.strftime(u"%m"), "03")
+
         # A naive object replaces %z and %Z w/ empty strings.
         self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
 
+
     def test_format(self):
         dt = self.theclass(2007, 9, 10)
         self.assertEqual(dt.__format__(''), str(dt))

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Mon Jun  2 06:05:52 2008
@@ -72,6 +72,9 @@
 Library
 -------
 
+- Issue #2782: The datetime module's strftime methods now accept
+  unicode format strings just as time.strftime always has.
+
 - The sgmllib and htmllib modules have been deprecated for removal
   in Python 3.0.
 

Modified: python/trunk/Modules/datetimemodule.c
==============================================================================
--- python/trunk/Modules/datetimemodule.c	(original)
+++ python/trunk/Modules/datetimemodule.c	Mon Jun  2 06:05:52 2008
@@ -2,6 +2,8 @@
  *  http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
  */
 
+#define PY_SSIZE_T_CLEAN
+
 #include "Python.h"
 #include "modsupport.h"
 #include "structmember.h"
@@ -1152,8 +1154,8 @@
  * needed.
  */
 static PyObject *
-wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
-	      PyObject *tzinfoarg)
+wrap_strftime(PyObject *object, const char *format, size_t format_len,
+		PyObject *timetuple, PyObject *tzinfoarg)
 {
 	PyObject *result = NULL;	/* guilty until proved innocent */
 
@@ -1161,20 +1163,19 @@
 	PyObject *Zreplacement = NULL;	/* py string, replacement for %Z */
 	PyObject *freplacement = NULL;	/* py string, replacement for %f */
 
-	char *pin;	/* pointer to next char in input format */
-	char ch;	/* next char in input format */
+	const char *pin;	/* pointer to next char in input format */
+	char ch;		/* next char in input format */
 
 	PyObject *newfmt = NULL;	/* py string, the output format */
 	char *pnew;	/* pointer to available byte in output format */
-	int totalnew;	/* number bytes total in output format buffer,
-			   exclusive of trailing \0 */
-	int usednew;	/* number bytes used so far in output format buffer */
+	size_t totalnew;	/* number bytes total in output format buffer,
+				   exclusive of trailing \0 */
+	size_t usednew;	/* number bytes used so far in output format buffer */
 
-	char *ptoappend; /* pointer to string to append to output buffer */
-	int ntoappend;	/* # of bytes to append to output buffer */
+	const char *ptoappend;	/* ptr to string to append to output buffer */
+	size_t ntoappend;	/* # of bytes to append to output buffer */
 
 	assert(object && format && timetuple);
-	assert(PyBytes_Check(format));
 
 	/* Give up if the year is before 1900.
 	 * Python strftime() plays games with the year, and different
@@ -1205,13 +1206,13 @@
 	 * a new format.  Since computing the replacements for those codes
 	 * is expensive, don't unless they're actually used.
 	 */
-	totalnew = PyBytes_Size(format) + 1;	/* realistic if no %z/%Z/%f */
+	totalnew = format_len + 1;	/* realistic if no %z/%Z/%f */
 	newfmt = PyBytes_FromStringAndSize(NULL, totalnew);
 	if (newfmt == NULL) goto Done;
 	pnew = PyBytes_AsString(newfmt);
 	usednew = 0;
 
-	pin = PyBytes_AsString(format);
+	pin = format;
 	while ((ch = *pin++) != '\0') {
 		if (ch != '%') {
 			ptoappend = pin - 1;
@@ -1313,7 +1314,7 @@
  		if (ntoappend == 0)
  			continue;
  		while (usednew + ntoappend > totalnew) {
- 			int bigger = totalnew << 1;
+ 			size_t bigger = totalnew << 1;
  			if ((bigger >> 1) != totalnew) { /* overflow */
  				PyErr_NoMemory();
  				goto Done;
@@ -2480,18 +2481,19 @@
 	 * timetuple() method appropriate to self's class.
 	 */
 	PyObject *result;
-	PyObject *format;
 	PyObject *tuple;
+	const char *format;
+	Py_ssize_t format_len;
 	static char *keywords[] = {"format", NULL};
 
-	if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
-					  &PyBytes_Type, &format))
+	if (! PyArg_ParseTupleAndKeywords(args, kw, "s#:strftime", keywords,
+					  &format, &format_len))
 		return NULL;
 
 	tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
 	if (tuple == NULL)
 		return NULL;
-	result = wrap_strftime((PyObject *)self, format, tuple,
+	result = wrap_strftime((PyObject *)self, format, format_len, tuple,
 			       (PyObject *)self);
 	Py_DECREF(tuple);
 	return result;
@@ -3256,12 +3258,13 @@
 time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
 {
 	PyObject *result;
-	PyObject *format;
 	PyObject *tuple;
+	const char *format;
+	Py_ssize_t format_len;
 	static char *keywords[] = {"format", NULL};
 
-	if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
-					  &PyBytes_Type, &format))
+	if (! PyArg_ParseTupleAndKeywords(args, kw, "s#:strftime", keywords,
+					  &format, &format_len))
 		return NULL;
 
 	/* Python's strftime does insane things with the year part of the
@@ -3277,7 +3280,8 @@
 	if (tuple == NULL)
 		return NULL;
 	assert(PyTuple_Size(tuple) == 9);
-	result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
+	result = wrap_strftime((PyObject *)self, format, format_len, tuple,
+			       Py_None);
 	Py_DECREF(tuple);
 	return result;
 }


More information about the Python-checkins mailing list