[Python-checkins] r73043 - in python/branches/py3k: Lib/test/test_time.py Misc/NEWS Modules/timemodule.c PC/pyconfig.h

martin.v.loewis python-checkins at python.org
Sat May 30 08:13:40 CEST 2009


Author: martin.v.loewis
Date: Sat May 30 08:13:40 2009
New Revision: 73043

Log:
Issue #5562: Use wcsftime for time.strftime where available.


Modified:
   python/branches/py3k/Lib/test/test_time.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/timemodule.c
   python/branches/py3k/PC/pyconfig.h

Modified: python/branches/py3k/Lib/test/test_time.py
==============================================================================
--- python/branches/py3k/Lib/test/test_time.py	(original)
+++ python/branches/py3k/Lib/test/test_time.py	Sat May 30 08:13:40 2009
@@ -1,7 +1,7 @@
 from test import support
 import time
 import unittest
-
+import locale
 
 class TimeTestCase(unittest.TestCase):
 
@@ -223,9 +223,24 @@
         t1 = time.mktime(lt1)
         self.assert_(0 <= (t1-t0) < 0.2)
 
-def test_main():
-    support.run_unittest(TimeTestCase)
+class TestLocale(unittest.TestCase):
+    def setUp(self):
+        self.oldloc = locale.setlocale(locale.LC_ALL)
+
+    def tearDown(self):
+        locale.setlocale(locale.LC_ALL, self.oldloc)
 
+    def test_bug_5562(self):
+        try:
+            tmp = locale.setlocale(locale.LC_ALL, "fr_FR")
+        except locale.Error:
+            # skip this test
+            return
+        # This should not cause an exception
+        time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
+
+def test_main():
+    support.run_unittest(TimeTestCase, TestLocale)
 
 if __name__ == "__main__":
     test_main()

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sat May 30 08:13:40 2009
@@ -111,6 +111,8 @@
 Extension Modules
 -----------------
 
+- Issue #5562: Use wcsftime for time.strftime where available.
+
 - Issue #4873: Fix resource leaks in error cases of pwd and grp.
 
 - Issue #6093: Fix off-by-one error in locale.strxfrm.

Modified: python/branches/py3k/Modules/timemodule.c
==============================================================================
--- python/branches/py3k/Modules/timemodule.c	(original)
+++ python/branches/py3k/Modules/timemodule.c	Sat May 30 08:13:40 2009
@@ -417,15 +417,25 @@
 }
 
 #ifdef HAVE_STRFTIME
+#ifdef HAVE_WCSFTIME
+#define time_char wchar_t
+#define format_time wcsftime
+#define time_strlen wcslen
+#else
+#define time_char char
+#define format_time strftime
+#define time_strlen strlen
+#endif
+
 static PyObject *
 time_strftime(PyObject *self, PyObject *args)
 {
 	PyObject *tup = NULL;
 	struct tm buf;
-	const char *fmt;
-	PyObject *format;
+	const time_char *fmt;
+	PyObject *format, *tmpfmt;
 	size_t fmtlen, buflen;
-	char *outbuf = 0;
+	time_char *outbuf = 0;
 	size_t i;
 
 	memset((void *) &buf, '\0', sizeof(buf));
@@ -508,22 +518,38 @@
             return NULL;
         }
 
+#ifdef HAVE_WCSFTIME
+	tmpfmt = PyBytes_FromStringAndSize(NULL,
+					   sizeof(wchar_t) * (PyUnicode_GetSize(format)+1));
+	if (!tmpfmt)
+		return NULL;
+	/* This assumes that PyUnicode_AsWideChar doesn't do any UTF-16
+	   expansion. */
+	if (PyUnicode_AsWideChar((PyUnicodeObject*)format,
+				 (wchar_t*)PyBytes_AS_STRING(tmpfmt),
+				 PyUnicode_GetSize(format)+1) == (size_t)-1)
+		/* This shouldn't fail. */
+		Py_FatalError("PyUnicode_AsWideChar failed");
+	format = tmpfmt;
+	fmt = (wchar_t*)PyBytes_AS_STRING(format);
+#else
 	/* Convert the unicode string to an ascii one */
 	format = PyUnicode_AsEncodedString(format, TZNAME_ENCODING, NULL);
 	if (format == NULL)
 		return NULL;
 	fmt = PyBytes_AS_STRING(format);
+#endif
 
 #ifdef MS_WINDOWS
 	/* check that the format string contains only valid directives */
-	for(outbuf = strchr(fmt, '%');
+	for(outbuf = wcschr(fmt, L'%');
 		outbuf != NULL;
-		outbuf = strchr(outbuf+2, '%'))
+		outbuf = wcschr(outbuf+2, L'%'))
 	{
 		if (outbuf[1]=='#')
 			++outbuf; /* not documented by python, */
 		if (outbuf[1]=='\0' ||
-			!strchr("aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1]))
+			!wcschr(L"aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1]))
 		{
 			PyErr_SetString(PyExc_ValueError, "Invalid format string");
 			return 0;
@@ -531,18 +557,18 @@
 	}
 #endif
 
-	fmtlen = strlen(fmt);
+	fmtlen = time_strlen(fmt);
 
 	/* I hate these functions that presume you know how big the output
 	 * will be ahead of time...
 	 */
 	for (i = 1024; ; i += i) {
-		outbuf = (char *)PyMem_Malloc(i);
+		outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char));
 		if (outbuf == NULL) {
 			Py_DECREF(format);
 			return PyErr_NoMemory();
 		}
-		buflen = strftime(outbuf, i, fmt, &buf);
+		buflen = format_time(outbuf, i, fmt, &buf);
 		if (buflen > 0 || i >= 256 * fmtlen) {
 			/* If the buffer is 256 times as long as the format,
 			   it's probably not failing for lack of room!
@@ -550,8 +576,12 @@
 			   e.g. an empty format, or %Z when the timezone
 			   is unknown. */
 			PyObject *ret;
+#ifdef HAVE_WCSFTIME
+			ret = PyUnicode_FromWideChar(outbuf, buflen);
+#else
 			ret = PyUnicode_Decode(outbuf, buflen,
 					       TZNAME_ENCODING, NULL);
+#endif
 			PyMem_Free(outbuf);
 			Py_DECREF(format);
 			return ret;
@@ -568,6 +598,9 @@
 	}
 }
 
+#undef time_char
+#undef format_time
+
 PyDoc_STRVAR(strftime_doc,
 "strftime(format[, tuple]) -> string\n\
 \n\

Modified: python/branches/py3k/PC/pyconfig.h
==============================================================================
--- python/branches/py3k/PC/pyconfig.h	(original)
+++ python/branches/py3k/PC/pyconfig.h	Sat May 30 08:13:40 2009
@@ -637,6 +637,9 @@
 /* Define if you have waitpid.  */
 /* #undef HAVE_WAITPID */
 
+/* Define to 1 if you have the `wcsftime' function. */
+#define HAVE_WCSFTIME 1
+
 /* Define to 1 if you have the `wcscoll' function. */
 #ifndef MS_WINCE
 #define HAVE_WCSCOLL 1


More information about the Python-checkins mailing list