mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-140212: Add html for year-month option in Calendar (#140230)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
parent
dcf3cc5796
commit
07912f8632
5 changed files with 68 additions and 11 deletions
|
|
@ -710,8 +710,7 @@ The following options are accepted:
|
||||||
.. option:: month
|
.. option:: month
|
||||||
|
|
||||||
The month of the specified :option:`year` to print the calendar for.
|
The month of the specified :option:`year` to print the calendar for.
|
||||||
Must be a number between 1 and 12,
|
Must be a number between 1 and 12.
|
||||||
and may only be used in text mode.
|
|
||||||
Defaults to printing a calendar for the full year.
|
Defaults to printing a calendar for the full year.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,10 @@ calendar
|
||||||
dark mode and have been migrated to the HTML5 standard for improved accessibility.
|
dark mode and have been migrated to the HTML5 standard for improved accessibility.
|
||||||
(Contributed by Jiahao Li and Hugo van Kemenade in :gh:`137634`.)
|
(Contributed by Jiahao Li and Hugo van Kemenade in :gh:`137634`.)
|
||||||
|
|
||||||
|
* The :mod:`calendar`'s :ref:`command-line <calendar-cli>` HTML output now
|
||||||
|
accepts the year-month option: ``python -m calendar -t html 2009 06``.
|
||||||
|
(Contributed by Pål Grønås Drange in :gh:`140212`.)
|
||||||
|
|
||||||
|
|
||||||
collections
|
collections
|
||||||
-----------
|
-----------
|
||||||
|
|
|
||||||
|
|
@ -574,9 +574,9 @@ def formatyear(self, theyear, width=3):
|
||||||
a('</table>')
|
a('</table>')
|
||||||
return ''.join(v)
|
return ''.join(v)
|
||||||
|
|
||||||
def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):
|
def _format_html_page(self, theyear, content, css, encoding):
|
||||||
"""
|
"""
|
||||||
Return a formatted year as a complete HTML page.
|
Return a complete HTML page with the given content.
|
||||||
"""
|
"""
|
||||||
if encoding is None:
|
if encoding is None:
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
|
|
@ -597,11 +597,25 @@ def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):
|
||||||
a(f'<link rel="stylesheet" href="{css}">\n')
|
a(f'<link rel="stylesheet" href="{css}">\n')
|
||||||
a('</head>\n')
|
a('</head>\n')
|
||||||
a('<body>\n')
|
a('<body>\n')
|
||||||
a(self.formatyear(theyear, width))
|
a(content)
|
||||||
a('</body>\n')
|
a('</body>\n')
|
||||||
a('</html>\n')
|
a('</html>\n')
|
||||||
return ''.join(v).encode(encoding, "xmlcharrefreplace")
|
return ''.join(v).encode(encoding, "xmlcharrefreplace")
|
||||||
|
|
||||||
|
def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):
|
||||||
|
"""
|
||||||
|
Return a formatted year as a complete HTML page.
|
||||||
|
"""
|
||||||
|
content = self.formatyear(theyear, width)
|
||||||
|
return self._format_html_page(theyear, content, css, encoding)
|
||||||
|
|
||||||
|
def formatmonthpage(self, theyear, themonth, width=3, css='calendar.css', encoding=None):
|
||||||
|
"""
|
||||||
|
Return a formatted month as a complete HTML page.
|
||||||
|
"""
|
||||||
|
content = self.formatmonth(theyear, themonth, width)
|
||||||
|
return self._format_html_page(theyear, content, css, encoding)
|
||||||
|
|
||||||
|
|
||||||
class different_locale:
|
class different_locale:
|
||||||
def __init__(self, locale):
|
def __init__(self, locale):
|
||||||
|
|
@ -886,7 +900,7 @@ def main(args=None):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"month",
|
"month",
|
||||||
nargs='?', type=int,
|
nargs='?', type=int,
|
||||||
help="month number (1-12, text only)"
|
help="month number (1-12)"
|
||||||
)
|
)
|
||||||
|
|
||||||
options = parser.parse_args(args)
|
options = parser.parse_args(args)
|
||||||
|
|
@ -899,9 +913,6 @@ def main(args=None):
|
||||||
today = datetime.date.today()
|
today = datetime.date.today()
|
||||||
|
|
||||||
if options.type == "html":
|
if options.type == "html":
|
||||||
if options.month:
|
|
||||||
parser.error("incorrect number of arguments")
|
|
||||||
sys.exit(1)
|
|
||||||
if options.locale:
|
if options.locale:
|
||||||
cal = LocaleHTMLCalendar(locale=locale)
|
cal = LocaleHTMLCalendar(locale=locale)
|
||||||
else:
|
else:
|
||||||
|
|
@ -912,10 +923,14 @@ def main(args=None):
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
optdict = dict(encoding=encoding, css=options.css)
|
optdict = dict(encoding=encoding, css=options.css)
|
||||||
write = sys.stdout.buffer.write
|
write = sys.stdout.buffer.write
|
||||||
|
|
||||||
if options.year is None:
|
if options.year is None:
|
||||||
write(cal.formatyearpage(today.year, **optdict))
|
write(cal.formatyearpage(today.year, **optdict))
|
||||||
else:
|
else:
|
||||||
write(cal.formatyearpage(options.year, **optdict))
|
if options.month:
|
||||||
|
write(cal.formatmonthpage(options.year, options.month, **optdict))
|
||||||
|
else:
|
||||||
|
write(cal.formatyearpage(options.year, **optdict))
|
||||||
else:
|
else:
|
||||||
if options.locale:
|
if options.locale:
|
||||||
cal = _CLIDemoLocaleCalendar(highlight_day=today, locale=locale)
|
cal = _CLIDemoLocaleCalendar(highlight_day=today, locale=locale)
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,34 @@
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
result_2009_6_html = """\
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Calendar for 2009</title>
|
||||||
|
<style>
|
||||||
|
:root { color-scheme: light dark; }
|
||||||
|
table.year { border: solid; }
|
||||||
|
table.year > tbody > tr > td { border: solid; vertical-align: top; }
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="calendar.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table class="month">
|
||||||
|
<tr><th colspan="7" class="month">June 2009</th></tr>
|
||||||
|
<tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
|
||||||
|
<tr><td class="mon">1</td><td class="tue">2</td><td class="wed">3</td><td class="thu">4</td><td class="fri">5</td><td class="sat">6</td><td class="sun">7</td></tr>
|
||||||
|
<tr><td class="mon">8</td><td class="tue">9</td><td class="wed">10</td><td class="thu">11</td><td class="fri">12</td><td class="sat">13</td><td class="sun">14</td></tr>
|
||||||
|
<tr><td class="mon">15</td><td class="tue">16</td><td class="wed">17</td><td class="thu">18</td><td class="fri">19</td><td class="sat">20</td><td class="sun">21</td></tr>
|
||||||
|
<tr><td class="mon">22</td><td class="tue">23</td><td class="wed">24</td><td class="thu">25</td><td class="fri">26</td><td class="sat">27</td><td class="sun">28</td></tr>
|
||||||
|
<tr><td class="mon">29</td><td class="tue">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
result_2004_days = [
|
result_2004_days = [
|
||||||
[[[0, 0, 0, 1, 2, 3, 4],
|
[[[0, 0, 0, 1, 2, 3, 4],
|
||||||
[5, 6, 7, 8, 9, 10, 11],
|
[5, 6, 7, 8, 9, 10, 11],
|
||||||
|
|
@ -506,6 +534,13 @@ def test_format(self):
|
||||||
calendar.format(["1", "2", "3"], colwidth=3, spacing=1)
|
calendar.format(["1", "2", "3"], colwidth=3, spacing=1)
|
||||||
self.assertEqual(out.getvalue().strip(), "1 2 3")
|
self.assertEqual(out.getvalue().strip(), "1 2 3")
|
||||||
|
|
||||||
|
def test_format_html_year_with_month(self):
|
||||||
|
self.assertEqual(
|
||||||
|
calendar.HTMLCalendar().formatmonthpage(2009, 6).decode("ascii"),
|
||||||
|
result_2009_6_html
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CalendarTestCase(unittest.TestCase):
|
class CalendarTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test_deprecation_warning(self):
|
def test_deprecation_warning(self):
|
||||||
|
|
@ -1102,7 +1137,6 @@ def test_illegal_arguments(self):
|
||||||
self.assertFailure('2004', '1', 'spam')
|
self.assertFailure('2004', '1', 'spam')
|
||||||
self.assertFailure('2004', '1', '1')
|
self.assertFailure('2004', '1', '1')
|
||||||
self.assertFailure('2004', '1', '1', 'spam')
|
self.assertFailure('2004', '1', '1', 'spam')
|
||||||
self.assertFailure('-t', 'html', '2004', '1')
|
|
||||||
|
|
||||||
def test_output_current_year(self):
|
def test_output_current_year(self):
|
||||||
for run in self.runners:
|
for run in self.runners:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
Calendar's HTML formatting now accepts year and month as options.
|
||||||
|
Previously, running ``python -m calendar -t html 2025 10`` would result in an
|
||||||
|
error message. It now generates an HTML document displaying the calendar for
|
||||||
|
the specified month.
|
||||||
|
Contributed by Pål Grønås Drange.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue