"""Return a compiled re object for the format string."""
return re_compile(self.pattern(format), IGNORECASE)
+# Cached TimeRE; probably only need one instance ever so cache it for performance
+_locale_cache = TimeRE()
+# Cached regex objects; same reason as for TimeRE cache
+_regex_cache = dict()
def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
"""Return a time struct based on the input data and the format string."""
- time_re = TimeRE()
- locale_time = time_re.locale_time
- format_regex = time_re.compile(format)
+ 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():
+ _locale_cache = TimeRE()
+ _regex_cache.clear()
+ format_regex = _regex_cache.get(format)
+ if not format_regex:
+ # Limit regex cache size to prevent major bloating of the module;
+ # The value 5 is arbitrary
+ if len(_regex_cache) > 5:
+ _regex_cache.clear()
+ format_regex = _locale_cache.compile(format)
+ _regex_cache[format] = format_regex
found = format_regex.match(data_string)
if not found:
raise ValueError("time data did not match format: data=%s fmt=%s" %
self.failUnless(result.tm_wday == self.time_tuple.tm_wday,
"Calculation of day of the week failed;"
"%s != %s" % (result.tm_wday, self.time_tuple.tm_wday))
+
+class CacheTests(unittest.TestCase):
+ """Test that caching works properly."""
+
+ def test_time_re_recreation(self):
+ # Make sure cache is recreated when current locale does not match what
+ # cached object was created with.
+ _strptime.strptime("10", "%d")
+ _strptime._locale_cache.locale_time = _strptime.LocaleTime(lang="Ni")
+ original_time_re = id(_strptime._locale_cache)
+ _strptime.strptime("10", "%d")
+ self.failIfEqual(original_time_re, id(_strptime._locale_cache))
+
+ def test_regex_cleanup(self):
+ # Make sure cached regexes are discarded when cache becomes "full".
+ try:
+ del _strptime._regex_cache['%d']
+ except KeyError:
+ pass
+ bogus_key = 0
+ while len(_strptime._regex_cache) <= 5:
+ _strptime._regex_cache[bogus_key] = None
+ bogus_key += 1
+ _strptime.strptime("10", "%d")
+ self.failUnlessEqual(len(_strptime._regex_cache), 1)
+
+ def test_new_localetime(self):
+ # A new LocaleTime instance should be created when a new TimeRE object
+ # is created.
+ _strptime._locale_cache.locale_time = _strptime.LocaleTime(lang="Ni")
+ locale_time_id = id(_strptime._locale_cache.locale_time)
+ locale_time_lang = _strptime._locale_cache.locale_time.lang
+ _strptime.strptime("10", "%d")
+ self.failIfEqual(locale_time_id,
+ id(_strptime._locale_cache.locale_time))
+ self.failIfEqual(locale_time_lang,
+ _strptime._locale_cache.locale_time.lang)
+
+
+
def test_main():
test_support.run_unittest(
getlang_Tests,
Strptime12AMPMTests,
JulianTests,
CalculationTests,
+ CacheTests
)