From bbc0d4409c4edc43d9f9b38bff089fd63f43734a Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Sat, 13 Nov 2004 16:18:32 +0000 Subject: SF bug 1065388: calendar day/month name lookup too slow __getitem__() methods: compute only the new spellings needed to satisfy the given indexing object. This is purely an optimization (it should have no effect on visible semantics). --- Lib/calendar.py | 26 ++++++++++++++++++-------- Lib/test/test_calendar.py | 14 ++++++-------- Misc/NEWS | 11 +++++++++++ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Lib/calendar.py b/Lib/calendar.py index c2a9775..7081389 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -28,27 +28,37 @@ mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # fresh on each call, in case the user changes locale between calls. class _localized_month: + + _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)] + _months.insert(0, lambda x: "") + def __init__(self, format): self.format = format def __getitem__(self, i): - data = [datetime.date(2001, j, 1).strftime(self.format) - for j in range(1, 13)] - data.insert(0, "") - return data[i] + funcs = self._months[i] + if isinstance(i, slice): + return [f(self.format) for f in funcs] + else: + return funcs(self.format) def __len__(self): return 13 class _localized_day: + + # January 1, 2001, was a Monday. + _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)] + def __init__(self, format): self.format = format def __getitem__(self, i): - # January 1, 2001, was a Monday. - data = [datetime.date(2001, 1, j+1).strftime(self.format) - for j in range(7)] - return data[i] + funcs = self._days[i] + if isinstance(i, slice): + return [f(self.format) for f in funcs] + else: + return funcs(self.format) def __len__(self): return 7 diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index 2dc486f..34d365b 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -37,10 +37,9 @@ class CalendarTestCase(unittest.TestCase): self.assertEqual(len(value), 7) self.assertEqual(len(value[:]), 7) # ensure they're all unique - d = {} - for v in value: - d[v] = 1 - self.assertEqual(len(d), 7) + self.assertEqual(len(set(value)), 7) + # verify it "acts like a sequence" in two forms of iteration + self.assertEqual(value[::-1], list(reversed(value))) def test_months(self): for attr in "month_name", "month_abbr": @@ -49,10 +48,9 @@ class CalendarTestCase(unittest.TestCase): self.assertEqual(len(value[:]), 13) self.assertEqual(value[0], "") # ensure they're all unique - d = {} - for v in value: - d[v] = 1 - self.assertEqual(len(d), 13) + self.assertEqual(len(set(value)), 13) + # verify it "acts like a sequence" in two forms of iteration + self.assertEqual(value[::-1], list(reversed(value))) class MonthCalendarTestCase(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index ddcf030..b55da3e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,17 @@ Library - ``doctest``'s new support for adding ``pdb.set_trace()`` calls to doctests was broken in a dramatic but shallow way. Fixed. +- Bug 1065388: ``calendar``'s ``day_name``, ``day_abbr``, ``month_name``, + and ``month_abbr`` attributes emulate sequences of locale-correct + spellings of month and day names. Because the locale can change at + any time, the correct spelling is recomputed whenever one of these is + indexed. In the worst case, the index may be a slice object, so these + recomputed every day or month name each time they were indexed. This is + much slower than necessary in the usual case, when the index is just an + integer. In that case, only the single spelling needed is recomputed + now; and, when the index is a slice object, only the spellings needed + by the slice are recomputed now. + - Patch 1061679: Added ``__all__`` to pickletools.py. Build -- cgit v0.12