Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 175ddb5

Browse files
committed
Remove caching of TimeRE (and thus LocaleTime) instance. Error was being
caught when executing test_strptime, test_logging, and test_time in that order when the testing of "%c" occured. Suspect the cache was not being recreated (the test passed when test_logging was forced to re-establish the locale).
1 parent 98741af commit 175ddb5

2 files changed

Lines changed: 23 additions & 48 deletions

File tree

Lib/_strptime.py

Lines changed: 13 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,15 @@
2727

2828
def _getlang():
2929
# Figure out what the current language is set to.
30-
current_lang = locale.getlocale(locale.LC_TIME)[0]
31-
if current_lang:
32-
return current_lang
33-
else:
34-
current_lang = locale.getdefaultlocale()[0]
35-
if current_lang:
36-
return current_lang
37-
else:
38-
return ''
30+
return locale.getlocale(locale.LC_TIME)
3931

4032
class LocaleTime(object):
4133
"""Stores and handles locale-specific information related to time.
4234
35+
This is not thread-safe! Attributes are lazily calculated and no
36+
precaution is taken to check to see if the locale information has changed
37+
since the creation of the instance in use.
38+
4339
ATTRIBUTES (all read-only after instance creation! Instance variables that
4440
store the values have mangled names):
4541
f_weekday -- full weekday names (7-item list)
@@ -103,7 +99,10 @@ def __init__(self, f_weekday=None, a_weekday=None, f_month=None,
10399
raise TypeError("timezone names must contain 2 items")
104100
else:
105101
self.__timezone = self.__pad(timezone, False)
106-
self.__lang = lang
102+
if lang:
103+
self.__lang = lang
104+
else:
105+
self.__lang = _getlang()
107106

108107
def __pad(self, seq, front):
109108
# Add '' to seq to either front (is True), else the back.
@@ -196,13 +195,7 @@ def __get_LC_time(self):
196195
LC_time = property(__get_LC_time, __set_nothing,
197196
doc="Format string for locale's time representation ('%X' format)")
198197

199-
def __get_lang(self):
200-
# Fetch self.lang.
201-
if not self.__lang:
202-
self.__calc_lang()
203-
return self.__lang
204-
205-
lang = property(__get_lang, __set_nothing,
198+
lang = property(lambda self: self.__lang, __set_nothing,
206199
doc="Language used for instance")
207200

208201
def __calc_weekday(self):
@@ -295,11 +288,6 @@ def __calc_timezone(self):
295288
time_zones.append(time.tzname[0])
296289
self.__timezone = self.__pad(time_zones, 0)
297290

298-
def __calc_lang(self):
299-
# Set self.__lang by using __getlang().
300-
self.__lang = _getlang()
301-
302-
303291

304292
class TimeRE(dict):
305293
"""Handle conversion from format directives to regexes."""
@@ -406,28 +394,12 @@ def compile(self, format):
406394
"""Return a compiled re object for the format string."""
407395
return re_compile(self.pattern(format), IGNORECASE)
408396

409-
# Cached TimeRE; probably only need one instance ever so cache it for performance
410-
_locale_cache = TimeRE()
411-
# Cached regex objects; same reason as for TimeRE cache
412-
_regex_cache = dict()
413397

414398
def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
415399
"""Return a time struct based on the input data and the format string."""
416-
global _locale_cache
417-
global _regex_cache
418-
locale_time = _locale_cache.locale_time
419-
# If the language changes, caches are invalidated, so clear them
420-
if locale_time.lang != _getlang():
421-
_locale_cache = TimeRE()
422-
_regex_cache.clear()
423-
format_regex = _regex_cache.get(format)
424-
if not format_regex:
425-
# Limit regex cache size to prevent major bloating of the module;
426-
# The value 5 is arbitrary
427-
if len(_regex_cache) > 5:
428-
_regex_cache.clear()
429-
format_regex = _locale_cache.compile(format)
430-
_regex_cache[format] = format_regex
400+
time_re = TimeRE()
401+
locale_time = time_re.locale_time
402+
format_regex = time_re.compile(format)
431403
found = format_regex.match(data_string)
432404
if not found:
433405
raise ValueError("time data did not match format: data=%s fmt=%s" %

Lib/test/test_strptime.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
import _strptime
1010

11+
class getlang_Tests(unittest.TestCase):
12+
"""Test _getlang"""
13+
def test_basic(self):
14+
self.failUnlessEqual(_strptime._getlang(), locale.getlocale(locale.LC_TIME))
15+
1116
class LocaleTime_Tests(unittest.TestCase):
1217
"""Tests for _strptime.LocaleTime."""
1318

@@ -89,11 +94,9 @@ def test_date_time(self):
8994
"empty strings")
9095

9196
def test_lang(self):
92-
# Make sure lang is set
93-
self.failUnless(self.LT_ins.lang in (locale.getdefaultlocale()[0],
94-
locale.getlocale(locale.LC_TIME)[0],
95-
''),
96-
"Setting of lang failed")
97+
# Make sure lang is set to what _getlang() returns
98+
# Assuming locale has not changed between now and when self.LT_ins was created
99+
self.failUnlessEqual(self.LT_ins.lang, _strptime._getlang())
97100

98101
def test_by_hand_input(self):
99102
# Test passed-in initialization value checks
@@ -410,15 +413,15 @@ def test_day_of_week_calculation(self):
410413
self.failUnless(result.tm_wday == self.time_tuple.tm_wday,
411414
"Calculation of day of the week failed;"
412415
"%s != %s" % (result.tm_wday, self.time_tuple.tm_wday))
413-
414416
def test_main():
415417
test_support.run_unittest(
418+
getlang_Tests,
416419
LocaleTime_Tests,
417420
TimeRETests,
418421
StrptimeTests,
419422
Strptime12AMPMTests,
420423
JulianTests,
421-
CalculationTests
424+
CalculationTests,
422425
)
423426

424427

0 commit comments

Comments
 (0)