[Python-Dev] RE: test_strptime; test_logging; test_time failure

Brett C. drifty@alum.berkeley.edu
Wed, 23 Jul 2003 13:35:27 -0700


This is a multi-part message in MIME format.
--------------020902050401080502050405
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Brett C. wrote:


<SNIP>
> So this should be solvable by changing some comparison code and what is 
> used to represent the language.  I will have a look and see if I can 
> figure out where this is going wrong.  If I don't have it fixed by the 
> end of today I will rip out the caching code and just leave a fix for 
> 2.3.1 and 2.4 .
> 

Tim (or someone else who can replicate the problem), can you give the 
attached patch a try?  This should fix the problem.  There are new tests 
on top of a proposed fix.  If this doesn't solve it then I am giving up 
on getting the caching to work for this release.

-Brett

--------------020902050401080502050405
Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0";
 name="strptime.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="strptime.diff"

Index: Lib/_strptime.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/_strptime.py,v
retrieving revision 1.21
diff -u -r1.21 _strptime.py
--- Lib/_strptime.py	13 Jul 2003 01:31:38 -0000	1.21
+++ Lib/_strptime.py	23 Jul 2003 20:31:07 -0000
@@ -27,15 +27,7 @@
 
 def _getlang():
     # Figure out what the current language is set to.
-    current_lang = locale.getlocale(locale.LC_TIME)[0]
-    if current_lang:
-        return current_lang
-    else:
-        current_lang = locale.getdefaultlocale()[0]
-        if current_lang:
-            return current_lang
-        else:
-            return ''
+    return locale.getlocale(locale.LC_TIME)
 
 class LocaleTime(object):
     """Stores and handles locale-specific information related to time.
@@ -103,7 +95,10 @@
                 raise TypeError("timezone names must contain 2 items")
             else:
                 self.__timezone = self.__pad(timezone, False)
-        self.__lang = lang
+        if lang:
+            self.__lang = lang
+        else:
+            self.__lang = _getlang()
 
     def __pad(self, seq, front):
         # Add '' to seq to either front (is True), else the back.
@@ -196,13 +191,7 @@
     LC_time = property(__get_LC_time, __set_nothing,
         doc="Format string for locale's time representation ('%X' format)")
 
-    def __get_lang(self):
-        # Fetch self.lang.
-        if not self.__lang:
-            self.__calc_lang()
-        return self.__lang
-
-    lang = property(__get_lang, __set_nothing,
+    lang = property(lambda self: self.__lang, __set_nothing,
                     doc="Language used for instance")
 
     def __calc_weekday(self):
@@ -295,11 +284,6 @@
             time_zones.append(time.tzname[0])
         self.__timezone = self.__pad(time_zones, 0)
 
-    def __calc_lang(self):
-        # Set self.__lang by using __getlang().
-        self.__lang = _getlang()
-
-
 
 class TimeRE(dict):
     """Handle conversion from format directives to regexes."""
@@ -416,10 +400,13 @@
     global _locale_cache
     global _regex_cache
     locale_time = _locale_cache.locale_time
-    # If the language changes, caches are invalidated, so clear them
-    if locale_time.lang != _getlang():
+    # If the language changes, caches are invalidated, so clear them.
+    # Also assume that if we can't figure out locale (as represented by
+    # (None, None)) then we just clear the cache to be safe.
+    if (_getlang() == (None, None)) or (locale_time.lang != _getlang()):
         _locale_cache = TimeRE()
         _regex_cache.clear()
+        locale_time = _locale_cache.locale_time
     format_regex = _regex_cache.get(format)
     if not format_regex:
         # Limit regex cache size to prevent major bloating of the module;
Index: Lib/test/test_strptime.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_strptime.py,v
retrieving revision 1.18
diff -u -r1.18 test_strptime.py
--- Lib/test/test_strptime.py	22 Jul 2003 21:07:16 -0000	1.18
+++ Lib/test/test_strptime.py	23 Jul 2003 20:31:07 -0000
@@ -8,6 +8,11 @@
 
 import _strptime
 
+class getlang_Tests(unittest.TestCase):
+    """Test _getlang"""
+    def test_basic(self):
+        self.failUnlessEqual(_strptime._getlang(), locale.getlocale(locale.LC_TIME))
+
 class LocaleTime_Tests(unittest.TestCase):
     """Tests for _strptime.LocaleTime."""
 
@@ -89,11 +94,9 @@
                                     "empty strings")
 
     def test_lang(self):
-        # Make sure lang is set
-        self.failUnless(self.LT_ins.lang in (locale.getdefaultlocale()[0],
-                                             locale.getlocale(locale.LC_TIME)[0],
-                                             ''),
-                        "Setting of lang failed")
+        # Make sure lang is set to what _getlang() returns
+        # Assuming locale has not changed between now and when self.LT_ins was created
+        self.failUnlessEqual(self.LT_ins.lang, _strptime._getlang())
 
     def test_by_hand_input(self):
         # Test passed-in initialization value checks
@@ -411,14 +414,44 @@
                         "Calculation of day of the week failed;"
                          "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday))
 
+class Cache_Tests(unittest.TestCase):
+    """Make sure handling of cache is correct"""
+    def test_normal_clearing(self):
+        # Make sure the cache is cleared properly when lang value is different
+        time_re = _strptime.TimeRE(locale_time=_strptime.LocaleTime(lang='Ni'))
+        _strptime._locale_cache = time_re
+        _strptime.strptime(time.strftime("%c"), "%c")
+        self.failIfEqual(id(_strptime._locale_cache), id(time_re))
+        self.failUnlessEqual(len(_strptime._regex_cache), 1)
+
+    def test_NoneNone_clearing(self):
+        # Make sure cache changes when lang is set to (None, None)
+        time_re = _strptime.TimeRE(locale_time=_strptime.LocaleTime(lang=(None, None)))
+        _strptime_locale_cache = time_re
+        _strptime.strptime(time.strftime("%c"), "%c")
+        self.failIfEqual(id(time_re), id(_strptime._locale_cache))
+        self.failUnlessEqual(len(_strptime._regex_cache), 1)
+
+    def test_use_new_cache(self):
+        # Make sure that when a new cache value is guaranteed to be created
+        # that it is used
+        time_re = _strptime.TimeRE(locale_time=_strptime.LocaleTime(
+                                    LC_date_time = "%d",
+                                    lang="Ni")
+                                  )
+        _strptime._locale_cache = time_re
+        self.failUnlessRaises(ValueError, _strptime.strptime, "23", "%c")
+
 def test_main():
     test_support.run_unittest(
+        getlang_Tests,
         LocaleTime_Tests,
         TimeRETests,
         StrptimeTests,
         Strptime12AMPMTests,
         JulianTests,
-        CalculationTests
+        CalculationTests,
+        Cache_Tests
     )
 
 

--------------020902050401080502050405--