diff -r be1e015a8405 Lib/test/test_datetime_strptime.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_datetime_strptime.py Tue Mar 18 21:21:18 2014 +0100 @@ -0,0 +1,31 @@ +from test import test_support +import unittest +import threading + +from datetime import datetime + +class StressDateTimeStrptime(threading.Thread): + def run(self): + self.error_raised=False + try: + for m in range(1, 13): + for d in range(1,29): + datetime.strptime("2010%02d%02d"%(m,d),"%Y%m%d") + except AttributeError: + self.error_raised=True + +class TestStrptimeAttributeInThread(unittest.TestCase): + def test_run_in_thread(self): + threads=[StressDateTimeStrptime() for _ in range(10)] + for t in threads: + t.start() + for t in threads: + t.join() + self.assertFalse(t.error_raised, + 'should not raise AttributeError for strptime') + +def test_main(): + test_support.run_unittest(TestStrptimeAttributeInThread) + +if __name__ == "__main__": + test_main() diff -r be1e015a8405 Lib/test/test_time_strptime.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_time_strptime.py Tue Mar 18 21:21:18 2014 +0100 @@ -0,0 +1,30 @@ +from test import test_support +import time +import unittest +import threading + +class StressTimeStrptime(threading.Thread): + def run(self): + self.error_raised=False + try: + for m in range(1, 13): + for d in range(1,29): + time.strptime("2010%02d%02d"%(m,d),"%Y%m%d") + except AttributeError: + self.error_raised=True + +class TestStrptimeAttributeInThread(unittest.TestCase): + def test_run_in_thread(self): + threads=[StressTimeStrptime() for _ in range(10)] + for t in threads: + t.start() + for t in threads: + t.join() + self.assertFalse(t.error_raised, + 'should not raise AttributeError for strptime') + +def test_main(): + test_support.run_unittest(TestStrptimeAttributeInThread) + +if __name__ == "__main__": + test_main() diff -r be1e015a8405 Modules/datetimemodule.c --- a/Modules/datetimemodule.c Tue Mar 18 09:18:53 2014 -0500 +++ b/Modules/datetimemodule.c Tue Mar 18 21:21:18 2014 +0100 @@ -105,6 +105,9 @@ static PyTypeObject PyDateTime_TimeType; static PyTypeObject PyDateTime_TZInfoType; +/* Single reference to the _strptime module, set in module init method */ +static PyObject *strptime_module = NULL; + /* --------------------------------------------------------------------------- * Math utilities. */ @@ -3928,21 +3931,17 @@ static PyObject * datetime_strptime(PyObject *cls, PyObject *args) { - static PyObject *module = NULL; PyObject *result = NULL, *obj, *st = NULL, *frac = NULL; const char *string, *format; if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format)) return NULL; - if (module == NULL && - (module = PyImport_ImportModuleNoBlock("_strptime")) == NULL) - return NULL; - /* _strptime._strptime returns a two-element tuple. The first element is a time.struct_time object. The second is the microseconds (which are not defined for time.struct_time). */ - obj = PyObject_CallMethod(module, "_strptime", "ss", string, format); + obj = PyObject_CallMethod(strptime_module, "_strptime", "ss", string, + format); if (obj != NULL) { int i, good_timetuple = 1; long int ia[7]; @@ -4916,6 +4915,11 @@ us_per_week = PyLong_FromDouble(604800000000.0); if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) return; + + strptime_module = PyImport_ImportModuleNoBlock("_strptime"); + if (strptime_module == NULL) + return; + Py_INCREF(strptime_module); } /* --------------------------------------------------------------------------- diff -r be1e015a8405 Modules/timemodule.c --- a/Modules/timemodule.c Tue Mar 18 09:18:53 2014 -0500 +++ b/Modules/timemodule.c Tue Mar 18 21:21:18 2014 +0100 @@ -98,6 +98,9 @@ /* For Y2K check */ static PyObject *moddict = NULL; +/* Single reference to the _strptime module, set in module init method */ +static PyObject *strptime_module = NULL; + /* Exposed in timefuncs.h. */ time_t _PyTime_DoubleToTimet(double x) @@ -540,11 +543,8 @@ static PyObject * time_strptime(PyObject *self, PyObject *args) { - PyObject *strptime_module = PyImport_ImportModuleNoBlock("_strptime"); PyObject *strptime_result; - if (!strptime_module) - return NULL; strptime_result = PyObject_CallMethod(strptime_module, "_strptime_time", "O", args); Py_DECREF(strptime_module); @@ -885,6 +885,12 @@ } Py_INCREF(&StructTimeType); PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType); + + strptime_module = PyImport_ImportModuleNoBlock("_strptime"); + if (strptime_module == NULL) + return; + Py_INCREF(strptime_module); + initialized = 1; }