Update calendar from CPython 3.14.2

This commit is contained in:
CPython Devleopers
2026-01-16 21:13:34 +09:00
committed by Jeong, YunWon
parent d75f272c8b
commit 314a61562c
2 changed files with 123 additions and 8 deletions

125
Lib/calendar.py vendored
View File

@@ -428,6 +428,7 @@ class TextCalendar(Calendar):
headers = (header for k in months)
a(formatstring(headers, colwidth, c).rstrip())
a('\n'*l)
# max number of weeks for this row
height = max(len(cal) for cal in row)
for j in range(height):
@@ -646,6 +647,117 @@ class LocaleHTMLCalendar(HTMLCalendar):
with different_locale(self.locale):
return super().formatmonthname(theyear, themonth, withyear)
class _CLIDemoCalendar(TextCalendar):
def __init__(self, highlight_day=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.highlight_day = highlight_day
def formatweek(self, theweek, width, *, highlight_day=None):
"""
Returns a single week in a string (no newline).
"""
if highlight_day:
from _colorize import get_colors
ansi = get_colors()
highlight = f"{ansi.BLACK}{ansi.BACKGROUND_YELLOW}"
reset = ansi.RESET
else:
highlight = reset = ""
return ' '.join(
(
f"{highlight}{self.formatday(d, wd, width)}{reset}"
if d == highlight_day
else self.formatday(d, wd, width)
)
for (d, wd) in theweek
)
def formatmonth(self, theyear, themonth, w=0, l=0):
"""
Return a month's calendar string (multi-line).
"""
if (
self.highlight_day
and self.highlight_day.year == theyear
and self.highlight_day.month == themonth
):
highlight_day = self.highlight_day.day
else:
highlight_day = None
w = max(2, w)
l = max(1, l)
s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)
s = s.rstrip()
s += '\n' * l
s += self.formatweekheader(w).rstrip()
s += '\n' * l
for week in self.monthdays2calendar(theyear, themonth):
s += self.formatweek(week, w, highlight_day=highlight_day).rstrip()
s += '\n' * l
return s
def formatyear(self, theyear, w=2, l=1, c=6, m=3):
"""
Returns a year's calendar as a multi-line string.
"""
w = max(2, w)
l = max(1, l)
c = max(2, c)
colwidth = (w + 1) * 7 - 1
v = []
a = v.append
a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())
a('\n'*l)
header = self.formatweekheader(w)
for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):
# months in this row
months = range(m*i+1, min(m*(i+1)+1, 13))
a('\n'*l)
names = (self.formatmonthname(theyear, k, colwidth, False)
for k in months)
a(formatstring(names, colwidth, c).rstrip())
a('\n'*l)
headers = (header for k in months)
a(formatstring(headers, colwidth, c).rstrip())
a('\n'*l)
if (
self.highlight_day
and self.highlight_day.year == theyear
and self.highlight_day.month in months
):
month_pos = months.index(self.highlight_day.month)
else:
month_pos = None
# max number of weeks for this row
height = max(len(cal) for cal in row)
for j in range(height):
weeks = []
for k, cal in enumerate(row):
if j >= len(cal):
weeks.append('')
else:
day = (
self.highlight_day.day if k == month_pos else None
)
weeks.append(
self.formatweek(cal[j], w, highlight_day=day)
)
a(formatstring(weeks, colwidth, c).rstrip())
a('\n' * l)
return ''.join(v)
class _CLIDemoLocaleCalendar(LocaleTextCalendar, _CLIDemoCalendar):
def __init__(self, highlight_day=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.highlight_day = highlight_day
# Support for old module level interface
c = TextCalendar()
@@ -698,7 +810,7 @@ def timegm(tuple):
def main(args=None):
import argparse
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(color=True)
textgroup = parser.add_argument_group('text only arguments')
htmlgroup = parser.add_argument_group('html only arguments')
textgroup.add_argument(
@@ -765,6 +877,7 @@ def main(args=None):
sys.exit(1)
locale = options.locale, options.encoding
today = datetime.date.today()
if options.type == "html":
if options.month:
@@ -781,23 +894,23 @@ def main(args=None):
optdict = dict(encoding=encoding, css=options.css)
write = sys.stdout.buffer.write
if options.year is None:
write(cal.formatyearpage(datetime.date.today().year, **optdict))
write(cal.formatyearpage(today.year, **optdict))
else:
write(cal.formatyearpage(options.year, **optdict))
else:
if options.locale:
cal = LocaleTextCalendar(locale=locale)
cal = _CLIDemoLocaleCalendar(highlight_day=today, locale=locale)
else:
cal = TextCalendar()
cal = _CLIDemoCalendar(highlight_day=today)
cal.setfirstweekday(options.first_weekday)
optdict = dict(w=options.width, l=options.lines)
if options.month is None:
optdict["c"] = options.spacing
optdict["m"] = options.months
if options.month is not None:
else:
_validate_month(options.month)
if options.year is None:
result = cal.formatyear(datetime.date.today().year, **optdict)
result = cal.formatyear(today.year, **optdict)
elif options.month is None:
result = cal.formatyear(options.year, **optdict)
else:

View File

@@ -987,10 +987,11 @@ class CommandLineTestCase(unittest.TestCase):
self.assertCLIFails(*args)
self.assertCmdFails(*args)
@support.force_not_colorized
def test_help(self):
stdout = self.run_cmd_ok('-h')
self.assertIn(b'usage:', stdout)
self.assertIn(b'calendar.py', stdout)
self.assertIn(b' -m calendar ', stdout)
self.assertIn(b'--help', stdout)
# special case: stdout but sys.exit()
@@ -1089,6 +1090,7 @@ class CommandLineTestCase(unittest.TestCase):
output = run('--months', '1', '2004')
self.assertIn(conv('\nMo Tu We Th Fr Sa Su\n'), output)
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_option_type(self):
self.assertFailure('-t')
self.assertFailure('--type')
@@ -1097,7 +1099,7 @@ class CommandLineTestCase(unittest.TestCase):
output = run('--type', 'text', '2004')
self.assertEqual(output, conv(result_2004_text))
output = run('--type', 'html', '2004')
self.assertEqual(output[:6], b'<?xml ')
self.assertStartsWith(output, b'<?xml ')
self.assertIn(b'<title>Calendar for 2004</title>', output)
def test_html_output_current_year(self):