Skip to content

Commit cb475eb

Browse files
CPython Devleopersyouknowone
authored andcommitted
Update calendar from CPython 3.14.2
1 parent e4bd795 commit cb475eb

File tree

2 files changed

+123
-8
lines changed

2 files changed

+123
-8
lines changed

Lib/calendar.py

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ def formatyear(self, theyear, w=2, l=1, c=6, m=3):
428428
headers = (header for k in months)
429429
a(formatstring(headers, colwidth, c).rstrip())
430430
a('\n'*l)
431+
431432
# max number of weeks for this row
432433
height = max(len(cal) for cal in row)
433434
for j in range(height):
@@ -646,6 +647,117 @@ def formatmonthname(self, theyear, themonth, withyear=True):
646647
with different_locale(self.locale):
647648
return super().formatmonthname(theyear, themonth, withyear)
648649

650+
651+
class _CLIDemoCalendar(TextCalendar):
652+
def __init__(self, highlight_day=None, *args, **kwargs):
653+
super().__init__(*args, **kwargs)
654+
self.highlight_day = highlight_day
655+
656+
def formatweek(self, theweek, width, *, highlight_day=None):
657+
"""
658+
Returns a single week in a string (no newline).
659+
"""
660+
if highlight_day:
661+
from _colorize import get_colors
662+
663+
ansi = get_colors()
664+
highlight = f"{ansi.BLACK}{ansi.BACKGROUND_YELLOW}"
665+
reset = ansi.RESET
666+
else:
667+
highlight = reset = ""
668+
669+
return ' '.join(
670+
(
671+
f"{highlight}{self.formatday(d, wd, width)}{reset}"
672+
if d == highlight_day
673+
else self.formatday(d, wd, width)
674+
)
675+
for (d, wd) in theweek
676+
)
677+
678+
def formatmonth(self, theyear, themonth, w=0, l=0):
679+
"""
680+
Return a month's calendar string (multi-line).
681+
"""
682+
if (
683+
self.highlight_day
684+
and self.highlight_day.year == theyear
685+
and self.highlight_day.month == themonth
686+
):
687+
highlight_day = self.highlight_day.day
688+
else:
689+
highlight_day = None
690+
w = max(2, w)
691+
l = max(1, l)
692+
s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)
693+
s = s.rstrip()
694+
s += '\n' * l
695+
s += self.formatweekheader(w).rstrip()
696+
s += '\n' * l
697+
for week in self.monthdays2calendar(theyear, themonth):
698+
s += self.formatweek(week, w, highlight_day=highlight_day).rstrip()
699+
s += '\n' * l
700+
return s
701+
702+
def formatyear(self, theyear, w=2, l=1, c=6, m=3):
703+
"""
704+
Returns a year's calendar as a multi-line string.
705+
"""
706+
w = max(2, w)
707+
l = max(1, l)
708+
c = max(2, c)
709+
colwidth = (w + 1) * 7 - 1
710+
v = []
711+
a = v.append
712+
a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())
713+
a('\n'*l)
714+
header = self.formatweekheader(w)
715+
for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):
716+
# months in this row
717+
months = range(m*i+1, min(m*(i+1)+1, 13))
718+
a('\n'*l)
719+
names = (self.formatmonthname(theyear, k, colwidth, False)
720+
for k in months)
721+
a(formatstring(names, colwidth, c).rstrip())
722+
a('\n'*l)
723+
headers = (header for k in months)
724+
a(formatstring(headers, colwidth, c).rstrip())
725+
a('\n'*l)
726+
727+
if (
728+
self.highlight_day
729+
and self.highlight_day.year == theyear
730+
and self.highlight_day.month in months
731+
):
732+
month_pos = months.index(self.highlight_day.month)
733+
else:
734+
month_pos = None
735+
736+
# max number of weeks for this row
737+
height = max(len(cal) for cal in row)
738+
for j in range(height):
739+
weeks = []
740+
for k, cal in enumerate(row):
741+
if j >= len(cal):
742+
weeks.append('')
743+
else:
744+
day = (
745+
self.highlight_day.day if k == month_pos else None
746+
)
747+
weeks.append(
748+
self.formatweek(cal[j], w, highlight_day=day)
749+
)
750+
a(formatstring(weeks, colwidth, c).rstrip())
751+
a('\n' * l)
752+
return ''.join(v)
753+
754+
755+
class _CLIDemoLocaleCalendar(LocaleTextCalendar, _CLIDemoCalendar):
756+
def __init__(self, highlight_day=None, *args, **kwargs):
757+
super().__init__(*args, **kwargs)
758+
self.highlight_day = highlight_day
759+
760+
649761
# Support for old module level interface
650762
c = TextCalendar()
651763

@@ -698,7 +810,7 @@ def timegm(tuple):
698810

699811
def main(args=None):
700812
import argparse
701-
parser = argparse.ArgumentParser()
813+
parser = argparse.ArgumentParser(color=True)
702814
textgroup = parser.add_argument_group('text only arguments')
703815
htmlgroup = parser.add_argument_group('html only arguments')
704816
textgroup.add_argument(
@@ -765,6 +877,7 @@ def main(args=None):
765877
sys.exit(1)
766878

767879
locale = options.locale, options.encoding
880+
today = datetime.date.today()
768881

769882
if options.type == "html":
770883
if options.month:
@@ -781,23 +894,23 @@ def main(args=None):
781894
optdict = dict(encoding=encoding, css=options.css)
782895
write = sys.stdout.buffer.write
783896
if options.year is None:
784-
write(cal.formatyearpage(datetime.date.today().year, **optdict))
897+
write(cal.formatyearpage(today.year, **optdict))
785898
else:
786899
write(cal.formatyearpage(options.year, **optdict))
787900
else:
788901
if options.locale:
789-
cal = LocaleTextCalendar(locale=locale)
902+
cal = _CLIDemoLocaleCalendar(highlight_day=today, locale=locale)
790903
else:
791-
cal = TextCalendar()
904+
cal = _CLIDemoCalendar(highlight_day=today)
792905
cal.setfirstweekday(options.first_weekday)
793906
optdict = dict(w=options.width, l=options.lines)
794907
if options.month is None:
795908
optdict["c"] = options.spacing
796909
optdict["m"] = options.months
797-
if options.month is not None:
910+
else:
798911
_validate_month(options.month)
799912
if options.year is None:
800-
result = cal.formatyear(datetime.date.today().year, **optdict)
913+
result = cal.formatyear(today.year, **optdict)
801914
elif options.month is None:
802915
result = cal.formatyear(options.year, **optdict)
803916
else:

Lib/test/test_calendar.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -987,10 +987,11 @@ def assertFailure(self, *args):
987987
self.assertCLIFails(*args)
988988
self.assertCmdFails(*args)
989989

990+
@support.force_not_colorized
990991
def test_help(self):
991992
stdout = self.run_cmd_ok('-h')
992993
self.assertIn(b'usage:', stdout)
993-
self.assertIn(b'calendar.py', stdout)
994+
self.assertIn(b' -m calendar ', stdout)
994995
self.assertIn(b'--help', stdout)
995996

996997
# special case: stdout but sys.exit()
@@ -1089,6 +1090,7 @@ def test_option_months(self):
10891090
output = run('--months', '1', '2004')
10901091
self.assertIn(conv('\nMo Tu We Th Fr Sa Su\n'), output)
10911092

1093+
@unittest.expectedFailure # TODO: RUSTPYTHON
10921094
def test_option_type(self):
10931095
self.assertFailure('-t')
10941096
self.assertFailure('--type')
@@ -1097,7 +1099,7 @@ def test_option_type(self):
10971099
output = run('--type', 'text', '2004')
10981100
self.assertEqual(output, conv(result_2004_text))
10991101
output = run('--type', 'html', '2004')
1100-
self.assertEqual(output[:6], b'<?xml ')
1102+
self.assertStartsWith(output, b'<?xml ')
11011103
self.assertIn(b'<title>Calendar for 2004</title>', output)
11021104

11031105
def test_html_output_current_year(self):

0 commit comments

Comments
 (0)