Merge pull request #4669 from carlosmiei/update-calendar

Update calendar.py from CPython 3.11
This commit is contained in:
Jim Fasarakis-Hilliard
2023-03-08 23:37:34 +02:00
committed by GitHub
2 changed files with 76 additions and 33 deletions

52
Lib/calendar.py vendored
View File

@@ -15,7 +15,9 @@ __all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
"monthcalendar", "prmonth", "month", "prcal", "calendar",
"timegm", "month_name", "month_abbr", "day_name", "day_abbr",
"Calendar", "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
"LocaleHTMLCalendar", "weekheader"]
"LocaleHTMLCalendar", "weekheader",
"MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY",
"SATURDAY", "SUNDAY"]
# Exception raised for bad input (with string parameter for details)
error = ValueError
@@ -546,71 +548,67 @@ class HTMLCalendar(Calendar):
class different_locale:
def __init__(self, locale):
self.locale = locale
self.oldlocale = None
def __enter__(self):
self.oldlocale = _locale.getlocale(_locale.LC_TIME)
self.oldlocale = _locale.setlocale(_locale.LC_TIME, None)
_locale.setlocale(_locale.LC_TIME, self.locale)
def __exit__(self, *args):
if self.oldlocale is None:
return
_locale.setlocale(_locale.LC_TIME, self.oldlocale)
def _get_default_locale():
locale = _locale.setlocale(_locale.LC_TIME, None)
if locale == "C":
with different_locale(""):
# The LC_TIME locale does not seem to be configured:
# get the user preferred locale.
locale = _locale.setlocale(_locale.LC_TIME, None)
return locale
class LocaleTextCalendar(TextCalendar):
"""
This class can be passed a locale name in the constructor and will return
month and weekday names in the specified locale. If this locale includes
an encoding all strings containing month and weekday names will be returned
as unicode.
month and weekday names in the specified locale.
"""
def __init__(self, firstweekday=0, locale=None):
TextCalendar.__init__(self, firstweekday)
if locale is None:
locale = _locale.getdefaultlocale()
locale = _get_default_locale()
self.locale = locale
def formatweekday(self, day, width):
with different_locale(self.locale):
if width >= 9:
names = day_name
else:
names = day_abbr
name = names[day]
return name[:width].center(width)
return super().formatweekday(day, width)
def formatmonthname(self, theyear, themonth, width, withyear=True):
with different_locale(self.locale):
s = month_name[themonth]
if withyear:
s = "%s %r" % (s, theyear)
return s.center(width)
return super().formatmonthname(theyear, themonth, width, withyear)
class LocaleHTMLCalendar(HTMLCalendar):
"""
This class can be passed a locale name in the constructor and will return
month and weekday names in the specified locale. If this locale includes
an encoding all strings containing month and weekday names will be returned
as unicode.
month and weekday names in the specified locale.
"""
def __init__(self, firstweekday=0, locale=None):
HTMLCalendar.__init__(self, firstweekday)
if locale is None:
locale = _locale.getdefaultlocale()
locale = _get_default_locale()
self.locale = locale
def formatweekday(self, day):
with different_locale(self.locale):
s = day_abbr[day]
return '<th class="%s">%s</th>' % (self.cssclasses[day], s)
return super().formatweekday(day)
def formatmonthname(self, theyear, themonth, withyear=True):
with different_locale(self.locale):
s = month_name[themonth]
if withyear:
s = '%s %s' % (s, theyear)
return '<tr><th colspan="7" class="month">%s</th></tr>' % s
return super().formatmonthname(theyear, themonth, withyear)
# Support for old module level interface
c = TextCalendar()

View File

@@ -564,6 +564,43 @@ class CalendarTestCase(unittest.TestCase):
new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
self.assertEqual(old_october, new_october)
def test_locale_calendar_formatweekday(self):
try:
# formatweekday uses different day names based on the available width.
cal = calendar.LocaleTextCalendar(locale='en_US')
# For short widths, a centered, abbreviated name is used.
self.assertEqual(cal.formatweekday(0, 5), " Mon ")
# For really short widths, even the abbreviated name is truncated.
self.assertEqual(cal.formatweekday(0, 2), "Mo")
# For long widths, the full day name is used.
self.assertEqual(cal.formatweekday(0, 10), " Monday ")
except locale.Error:
raise unittest.SkipTest('cannot set the en_US locale')
def test_locale_html_calendar_custom_css_class_month_name(self):
try:
cal = calendar.LocaleHTMLCalendar(locale='')
local_month = cal.formatmonthname(2010, 10, 10)
except locale.Error:
# cannot set the system default locale -- skip rest of test
raise unittest.SkipTest('cannot set the system default locale')
self.assertIn('class="month"', local_month)
cal.cssclass_month_head = "text-center month"
local_month = cal.formatmonthname(2010, 10, 10)
self.assertIn('class="text-center month"', local_month)
def test_locale_html_calendar_custom_css_class_weekday(self):
try:
cal = calendar.LocaleHTMLCalendar(locale='')
local_weekday = cal.formatweekday(6)
except locale.Error:
# cannot set the system default locale -- skip rest of test
raise unittest.SkipTest('cannot set the system default locale')
self.assertIn('class="sun"', local_weekday)
cal.cssclasses_weekday_head = ["mon2", "tue2", "wed2", "thu2", "fri2", "sat2", "sun2"]
local_weekday = cal.formatweekday(6)
self.assertIn('class="sun2"', local_weekday)
def test_itermonthdays3(self):
# ensure itermonthdays3 doesn't overflow after datetime.MAXYEAR
list(calendar.Calendar().itermonthdays3(datetime.MAXYEAR, 12))
@@ -595,6 +632,14 @@ class CalendarTestCase(unittest.TestCase):
self.assertEqual(days[0][1], firstweekday)
self.assertEqual(days[-1][1], (firstweekday - 1) % 7)
def test_iterweekdays(self):
week0 = list(range(7))
for firstweekday in range(7):
cal = calendar.Calendar(firstweekday)
week = list(cal.iterweekdays())
expected = week0[firstweekday:] + week0[:firstweekday]
self.assertEqual(week, expected)
class MonthCalendarTestCase(unittest.TestCase):
def setUp(self):
@@ -837,7 +882,8 @@ class CommandLineTestCase(unittest.TestCase):
self.assertFailure('-L')
self.assertFailure('--locale')
self.assertFailure('-L', 'en')
lang, enc = locale.getdefaultlocale()
lang, enc = locale.getlocale()
lang = lang or 'C'
enc = enc or 'UTF-8'
try:
@@ -912,11 +958,10 @@ class CommandLineTestCase(unittest.TestCase):
class MiscTestCase(unittest.TestCase):
def test__all__(self):
not_exported = {'mdays', 'January', 'February', 'EPOCH',
'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY',
'SATURDAY', 'SUNDAY', 'different_locale', 'c',
'prweek', 'week', 'format', 'formatstring', 'main',
'monthlen', 'prevmonth', 'nextmonth'}
not_exported = {
'mdays', 'January', 'February', 'EPOCH',
'different_locale', 'c', 'prweek', 'week', 'format',
'formatstring', 'main', 'monthlen', 'prevmonth', 'nextmonth'}
support.check__all__(self, calendar, not_exported=not_exported)