diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2009-05-30 06:13:40 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2009-05-30 06:13:40 (GMT) |
commit | 1b01ccd76a5dfd00efe07af0e942afe0b59de63a (patch) | |
tree | 3b6ef6011febf085aff6d91771ceeabdfbf85cae | |
parent | 3ad05763a6d69a93e58dfef6cc9d84f14edbb29b (diff) | |
download | cpython-1b01ccd76a5dfd00efe07af0e942afe0b59de63a.zip cpython-1b01ccd76a5dfd00efe07af0e942afe0b59de63a.tar.gz cpython-1b01ccd76a5dfd00efe07af0e942afe0b59de63a.tar.bz2 |
Issue #5562: Use wcsftime for time.strftime where available.
-rw-r--r-- | Lib/test/test_time.py | 21 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Modules/timemodule.c | 51 | ||||
-rw-r--r-- | PC/pyconfig.h | 3 |
4 files changed, 65 insertions, 12 deletions
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index c2dfaca..4e21a64 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -1,7 +1,7 @@ from test import support import time import unittest - +import locale class TimeTestCase(unittest.TestCase): @@ -223,9 +223,24 @@ class TimeTestCase(unittest.TestCase): 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() @@ -111,6 +111,8 @@ Installation 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. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 2727297..d524ac5 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -417,15 +417,25 @@ gettmarg(PyObject *args, struct tm *p) } #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 @@ time_strftime(PyObject *self, PyObject *args) 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 @@ time_strftime(PyObject *self, PyObject *args) } #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 @@ time_strftime(PyObject *self, PyObject *args) 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 @@ time_strftime(PyObject *self, PyObject *args) } } +#undef time_char +#undef format_time + PyDoc_STRVAR(strftime_doc, "strftime(format[, tuple]) -> string\n\ \n\ diff --git a/PC/pyconfig.h b/PC/pyconfig.h index e0c9f48..d76846f 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -637,6 +637,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* 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 |