1import calendar 2import unittest 3 4from test import support 5from test.support.script_helper import assert_python_ok, assert_python_failure 6import time 7import locale 8import sys 9import datetime 10import os 11 12# From https://en.wikipedia.org/wiki/Leap_year_starting_on_Saturday 13result_0_02_text = """\ 14 February 0 15Mo Tu We Th Fr Sa Su 16 1 2 3 4 5 6 17 7 8 9 10 11 12 13 1814 15 16 17 18 19 20 1921 22 23 24 25 26 27 2028 29 21""" 22 23result_0_text = """\ 24 0 25 26 January February March 27Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 28 1 2 1 2 3 4 5 6 1 2 3 4 5 29 3 4 5 6 7 8 9 7 8 9 10 11 12 13 6 7 8 9 10 11 12 3010 11 12 13 14 15 16 14 15 16 17 18 19 20 13 14 15 16 17 18 19 3117 18 19 20 21 22 23 21 22 23 24 25 26 27 20 21 22 23 24 25 26 3224 25 26 27 28 29 30 28 29 27 28 29 30 31 3331 34 35 April May June 36Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 37 1 2 1 2 3 4 5 6 7 1 2 3 4 38 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3910 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 4017 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 4124 25 26 27 28 29 30 29 30 31 26 27 28 29 30 42 43 July August September 44Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 45 1 2 1 2 3 4 5 6 1 2 3 46 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10 4710 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17 4817 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24 4924 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30 5031 51 52 October November December 53Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 54 1 1 2 3 4 5 1 2 3 55 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10 56 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17 5716 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24 5823 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 5930 31 60""" 61 62result_2004_01_text = """\ 63 January 2004 64Mo Tu We Th Fr Sa Su 65 1 2 3 4 66 5 6 7 8 9 10 11 6712 13 14 15 16 17 18 6819 20 21 22 23 24 25 6926 27 28 29 30 31 70""" 71 72result_2004_text = """\ 73 2004 74 75 January February March 76Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 77 1 2 3 4 1 1 2 3 4 5 6 7 78 5 6 7 8 9 10 11 2 3 4 5 6 7 8 8 9 10 11 12 13 14 7912 13 14 15 16 17 18 9 10 11 12 13 14 15 15 16 17 18 19 20 21 8019 20 21 22 23 24 25 16 17 18 19 20 21 22 22 23 24 25 26 27 28 8126 27 28 29 30 31 23 24 25 26 27 28 29 29 30 31 82 83 April May June 84Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 85 1 2 3 4 1 2 1 2 3 4 5 6 86 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13 8712 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20 8819 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27 8926 27 28 29 30 24 25 26 27 28 29 30 28 29 30 90 31 91 92 July August September 93Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 94 1 2 3 4 1 1 2 3 4 5 95 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12 9612 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19 9719 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26 9826 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30 99 30 31 100 101 October November December 102Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 103 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 104 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12 10511 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19 10618 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26 10725 26 27 28 29 30 31 29 30 27 28 29 30 31 108""" 109 110 111default_format = dict(year="year", month="month", encoding="ascii") 112 113result_2004_html = """\ 114<?xml version="1.0" encoding="{encoding}"?> 115<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 116<html> 117<head> 118<meta http-equiv="Content-Type" content="text/html; charset={encoding}" /> 119<link rel="stylesheet" type="text/css" href="calendar.css" /> 120<title>Calendar for 2004</title> 121</head> 122<body> 123<table border="0" cellpadding="0" cellspacing="0" class="{year}"> 124<tr><th colspan="3" class="{year}">2004</th></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 125<tr><th colspan="7" class="{month}">January</th></tr> 126<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> 127<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr> 128<tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr> 129<tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr> 130<tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr> 131<tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="sat">31</td><td class="noday"> </td></tr> 132</table> 133</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 134<tr><th colspan="7" class="{month}">February</th></tr> 135<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> 136<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sun">1</td></tr> 137<tr><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td><td class="sun">8</td></tr> 138<tr><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td><td class="sun">15</td></tr> 139<tr><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td><td class="sun">22</td></tr> 140<tr><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td><td class="sun">29</td></tr> 141</table> 142</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 143<tr><th colspan="7" class="{month}">March</th></tr> 144<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> 145<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> 146<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> 147<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> 148<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> 149<tr><td class="mon">29</td><td class="tue">30</td><td class="wed">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr> 150</table> 151</td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 152<tr><th colspan="7" class="{month}">April</th></tr> 153<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> 154<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr> 155<tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr> 156<tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr> 157<tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr> 158<tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="noday"> </td><td class="noday"> </td></tr> 159</table> 160</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 161<tr><th colspan="7" class="{month}">May</th></tr> 162<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> 163<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sat">1</td><td class="sun">2</td></tr> 164<tr><td class="mon">3</td><td class="tue">4</td><td class="wed">5</td><td class="thu">6</td><td class="fri">7</td><td class="sat">8</td><td class="sun">9</td></tr> 165<tr><td class="mon">10</td><td class="tue">11</td><td class="wed">12</td><td class="thu">13</td><td class="fri">14</td><td class="sat">15</td><td class="sun">16</td></tr> 166<tr><td class="mon">17</td><td class="tue">18</td><td class="wed">19</td><td class="thu">20</td><td class="fri">21</td><td class="sat">22</td><td class="sun">23</td></tr> 167<tr><td class="mon">24</td><td class="tue">25</td><td class="wed">26</td><td class="thu">27</td><td class="fri">28</td><td class="sat">29</td><td class="sun">30</td></tr> 168<tr><td class="mon">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr> 169</table> 170</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 171<tr><th colspan="7" class="{month}">June</th></tr> 172<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> 173<tr><td class="noday"> </td><td class="tue">1</td><td class="wed">2</td><td class="thu">3</td><td class="fri">4</td><td class="sat">5</td><td class="sun">6</td></tr> 174<tr><td class="mon">7</td><td class="tue">8</td><td class="wed">9</td><td class="thu">10</td><td class="fri">11</td><td class="sat">12</td><td class="sun">13</td></tr> 175<tr><td class="mon">14</td><td class="tue">15</td><td class="wed">16</td><td class="thu">17</td><td class="fri">18</td><td class="sat">19</td><td class="sun">20</td></tr> 176<tr><td class="mon">21</td><td class="tue">22</td><td class="wed">23</td><td class="thu">24</td><td class="fri">25</td><td class="sat">26</td><td class="sun">27</td></tr> 177<tr><td class="mon">28</td><td class="tue">29</td><td class="wed">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr> 178</table> 179</td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 180<tr><th colspan="7" class="{month}">July</th></tr> 181<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> 182<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr> 183<tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr> 184<tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr> 185<tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr> 186<tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="sat">31</td><td class="noday"> </td></tr> 187</table> 188</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 189<tr><th colspan="7" class="{month}">August</th></tr> 190<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> 191<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sun">1</td></tr> 192<tr><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td><td class="sun">8</td></tr> 193<tr><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td><td class="sun">15</td></tr> 194<tr><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td><td class="sun">22</td></tr> 195<tr><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td><td class="sun">29</td></tr> 196<tr><td class="mon">30</td><td class="tue">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr> 197</table> 198</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 199<tr><th colspan="7" class="{month}">September</th></tr> 200<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> 201<tr><td class="noday"> </td><td class="noday"> </td><td class="wed">1</td><td class="thu">2</td><td class="fri">3</td><td class="sat">4</td><td class="sun">5</td></tr> 202<tr><td class="mon">6</td><td class="tue">7</td><td class="wed">8</td><td class="thu">9</td><td class="fri">10</td><td class="sat">11</td><td class="sun">12</td></tr> 203<tr><td class="mon">13</td><td class="tue">14</td><td class="wed">15</td><td class="thu">16</td><td class="fri">17</td><td class="sat">18</td><td class="sun">19</td></tr> 204<tr><td class="mon">20</td><td class="tue">21</td><td class="wed">22</td><td class="thu">23</td><td class="fri">24</td><td class="sat">25</td><td class="sun">26</td></tr> 205<tr><td class="mon">27</td><td class="tue">28</td><td class="wed">29</td><td class="thu">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr> 206</table> 207</td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 208<tr><th colspan="7" class="{month}">October</th></tr> 209<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> 210<tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="fri">1</td><td class="sat">2</td><td class="sun">3</td></tr> 211<tr><td class="mon">4</td><td class="tue">5</td><td class="wed">6</td><td class="thu">7</td><td class="fri">8</td><td class="sat">9</td><td class="sun">10</td></tr> 212<tr><td class="mon">11</td><td class="tue">12</td><td class="wed">13</td><td class="thu">14</td><td class="fri">15</td><td class="sat">16</td><td class="sun">17</td></tr> 213<tr><td class="mon">18</td><td class="tue">19</td><td class="wed">20</td><td class="thu">21</td><td class="fri">22</td><td class="sat">23</td><td class="sun">24</td></tr> 214<tr><td class="mon">25</td><td class="tue">26</td><td class="wed">27</td><td class="thu">28</td><td class="fri">29</td><td class="sat">30</td><td class="sun">31</td></tr> 215</table> 216</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 217<tr><th colspan="7" class="{month}">November</th></tr> 218<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> 219<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> 220<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> 221<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> 222<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> 223<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> 224</table> 225</td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}"> 226<tr><th colspan="7" class="{month}">December</th></tr> 227<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> 228<tr><td class="noday"> </td><td class="noday"> </td><td class="wed">1</td><td class="thu">2</td><td class="fri">3</td><td class="sat">4</td><td class="sun">5</td></tr> 229<tr><td class="mon">6</td><td class="tue">7</td><td class="wed">8</td><td class="thu">9</td><td class="fri">10</td><td class="sat">11</td><td class="sun">12</td></tr> 230<tr><td class="mon">13</td><td class="tue">14</td><td class="wed">15</td><td class="thu">16</td><td class="fri">17</td><td class="sat">18</td><td class="sun">19</td></tr> 231<tr><td class="mon">20</td><td class="tue">21</td><td class="wed">22</td><td class="thu">23</td><td class="fri">24</td><td class="sat">25</td><td class="sun">26</td></tr> 232<tr><td class="mon">27</td><td class="tue">28</td><td class="wed">29</td><td class="thu">30</td><td class="fri">31</td><td class="noday"> </td><td class="noday"> </td></tr> 233</table> 234</td></tr></table></body> 235</html> 236""" 237 238result_2004_days = [ 239 [[[0, 0, 0, 1, 2, 3, 4], 240 [5, 6, 7, 8, 9, 10, 11], 241 [12, 13, 14, 15, 16, 17, 18], 242 [19, 20, 21, 22, 23, 24, 25], 243 [26, 27, 28, 29, 30, 31, 0]], 244 [[0, 0, 0, 0, 0, 0, 1], 245 [2, 3, 4, 5, 6, 7, 8], 246 [9, 10, 11, 12, 13, 14, 15], 247 [16, 17, 18, 19, 20, 21, 22], 248 [23, 24, 25, 26, 27, 28, 29]], 249 [[1, 2, 3, 4, 5, 6, 7], 250 [8, 9, 10, 11, 12, 13, 14], 251 [15, 16, 17, 18, 19, 20, 21], 252 [22, 23, 24, 25, 26, 27, 28], 253 [29, 30, 31, 0, 0, 0, 0]]], 254 [[[0, 0, 0, 1, 2, 3, 4], 255 [5, 6, 7, 8, 9, 10, 11], 256 [12, 13, 14, 15, 16, 17, 18], 257 [19, 20, 21, 22, 23, 24, 25], 258 [26, 27, 28, 29, 30, 0, 0]], 259 [[0, 0, 0, 0, 0, 1, 2], 260 [3, 4, 5, 6, 7, 8, 9], 261 [10, 11, 12, 13, 14, 15, 16], 262 [17, 18, 19, 20, 21, 22, 23], 263 [24, 25, 26, 27, 28, 29, 30], 264 [31, 0, 0, 0, 0, 0, 0]], 265 [[0, 1, 2, 3, 4, 5, 6], 266 [7, 8, 9, 10, 11, 12, 13], 267 [14, 15, 16, 17, 18, 19, 20], 268 [21, 22, 23, 24, 25, 26, 27], 269 [28, 29, 30, 0, 0, 0, 0]]], 270 [[[0, 0, 0, 1, 2, 3, 4], 271 [5, 6, 7, 8, 9, 10, 11], 272 [12, 13, 14, 15, 16, 17, 18], 273 [19, 20, 21, 22, 23, 24, 25], 274 [26, 27, 28, 29, 30, 31, 0]], 275 [[0, 0, 0, 0, 0, 0, 1], 276 [2, 3, 4, 5, 6, 7, 8], 277 [9, 10, 11, 12, 13, 14, 15], 278 [16, 17, 18, 19, 20, 21, 22], 279 [23, 24, 25, 26, 27, 28, 29], 280 [30, 31, 0, 0, 0, 0, 0]], 281 [[0, 0, 1, 2, 3, 4, 5], 282 [6, 7, 8, 9, 10, 11, 12], 283 [13, 14, 15, 16, 17, 18, 19], 284 [20, 21, 22, 23, 24, 25, 26], 285 [27, 28, 29, 30, 0, 0, 0]]], 286 [[[0, 0, 0, 0, 1, 2, 3], 287 [4, 5, 6, 7, 8, 9, 10], 288 [11, 12, 13, 14, 15, 16, 17], 289 [18, 19, 20, 21, 22, 23, 24], 290 [25, 26, 27, 28, 29, 30, 31]], 291 [[1, 2, 3, 4, 5, 6, 7], 292 [8, 9, 10, 11, 12, 13, 14], 293 [15, 16, 17, 18, 19, 20, 21], 294 [22, 23, 24, 25, 26, 27, 28], 295 [29, 30, 0, 0, 0, 0, 0]], 296 [[0, 0, 1, 2, 3, 4, 5], 297 [6, 7, 8, 9, 10, 11, 12], 298 [13, 14, 15, 16, 17, 18, 19], 299 [20, 21, 22, 23, 24, 25, 26], 300 [27, 28, 29, 30, 31, 0, 0]]] 301] 302 303result_2004_dates = \ 304 [[['12/29/03 12/30/03 12/31/03 01/01/04 01/02/04 01/03/04 01/04/04', 305 '01/05/04 01/06/04 01/07/04 01/08/04 01/09/04 01/10/04 01/11/04', 306 '01/12/04 01/13/04 01/14/04 01/15/04 01/16/04 01/17/04 01/18/04', 307 '01/19/04 01/20/04 01/21/04 01/22/04 01/23/04 01/24/04 01/25/04', 308 '01/26/04 01/27/04 01/28/04 01/29/04 01/30/04 01/31/04 02/01/04'], 309 ['01/26/04 01/27/04 01/28/04 01/29/04 01/30/04 01/31/04 02/01/04', 310 '02/02/04 02/03/04 02/04/04 02/05/04 02/06/04 02/07/04 02/08/04', 311 '02/09/04 02/10/04 02/11/04 02/12/04 02/13/04 02/14/04 02/15/04', 312 '02/16/04 02/17/04 02/18/04 02/19/04 02/20/04 02/21/04 02/22/04', 313 '02/23/04 02/24/04 02/25/04 02/26/04 02/27/04 02/28/04 02/29/04'], 314 ['03/01/04 03/02/04 03/03/04 03/04/04 03/05/04 03/06/04 03/07/04', 315 '03/08/04 03/09/04 03/10/04 03/11/04 03/12/04 03/13/04 03/14/04', 316 '03/15/04 03/16/04 03/17/04 03/18/04 03/19/04 03/20/04 03/21/04', 317 '03/22/04 03/23/04 03/24/04 03/25/04 03/26/04 03/27/04 03/28/04', 318 '03/29/04 03/30/04 03/31/04 04/01/04 04/02/04 04/03/04 04/04/04']], 319 [['03/29/04 03/30/04 03/31/04 04/01/04 04/02/04 04/03/04 04/04/04', 320 '04/05/04 04/06/04 04/07/04 04/08/04 04/09/04 04/10/04 04/11/04', 321 '04/12/04 04/13/04 04/14/04 04/15/04 04/16/04 04/17/04 04/18/04', 322 '04/19/04 04/20/04 04/21/04 04/22/04 04/23/04 04/24/04 04/25/04', 323 '04/26/04 04/27/04 04/28/04 04/29/04 04/30/04 05/01/04 05/02/04'], 324 ['04/26/04 04/27/04 04/28/04 04/29/04 04/30/04 05/01/04 05/02/04', 325 '05/03/04 05/04/04 05/05/04 05/06/04 05/07/04 05/08/04 05/09/04', 326 '05/10/04 05/11/04 05/12/04 05/13/04 05/14/04 05/15/04 05/16/04', 327 '05/17/04 05/18/04 05/19/04 05/20/04 05/21/04 05/22/04 05/23/04', 328 '05/24/04 05/25/04 05/26/04 05/27/04 05/28/04 05/29/04 05/30/04', 329 '05/31/04 06/01/04 06/02/04 06/03/04 06/04/04 06/05/04 06/06/04'], 330 ['05/31/04 06/01/04 06/02/04 06/03/04 06/04/04 06/05/04 06/06/04', 331 '06/07/04 06/08/04 06/09/04 06/10/04 06/11/04 06/12/04 06/13/04', 332 '06/14/04 06/15/04 06/16/04 06/17/04 06/18/04 06/19/04 06/20/04', 333 '06/21/04 06/22/04 06/23/04 06/24/04 06/25/04 06/26/04 06/27/04', 334 '06/28/04 06/29/04 06/30/04 07/01/04 07/02/04 07/03/04 07/04/04']], 335 [['06/28/04 06/29/04 06/30/04 07/01/04 07/02/04 07/03/04 07/04/04', 336 '07/05/04 07/06/04 07/07/04 07/08/04 07/09/04 07/10/04 07/11/04', 337 '07/12/04 07/13/04 07/14/04 07/15/04 07/16/04 07/17/04 07/18/04', 338 '07/19/04 07/20/04 07/21/04 07/22/04 07/23/04 07/24/04 07/25/04', 339 '07/26/04 07/27/04 07/28/04 07/29/04 07/30/04 07/31/04 08/01/04'], 340 ['07/26/04 07/27/04 07/28/04 07/29/04 07/30/04 07/31/04 08/01/04', 341 '08/02/04 08/03/04 08/04/04 08/05/04 08/06/04 08/07/04 08/08/04', 342 '08/09/04 08/10/04 08/11/04 08/12/04 08/13/04 08/14/04 08/15/04', 343 '08/16/04 08/17/04 08/18/04 08/19/04 08/20/04 08/21/04 08/22/04', 344 '08/23/04 08/24/04 08/25/04 08/26/04 08/27/04 08/28/04 08/29/04', 345 '08/30/04 08/31/04 09/01/04 09/02/04 09/03/04 09/04/04 09/05/04'], 346 ['08/30/04 08/31/04 09/01/04 09/02/04 09/03/04 09/04/04 09/05/04', 347 '09/06/04 09/07/04 09/08/04 09/09/04 09/10/04 09/11/04 09/12/04', 348 '09/13/04 09/14/04 09/15/04 09/16/04 09/17/04 09/18/04 09/19/04', 349 '09/20/04 09/21/04 09/22/04 09/23/04 09/24/04 09/25/04 09/26/04', 350 '09/27/04 09/28/04 09/29/04 09/30/04 10/01/04 10/02/04 10/03/04']], 351 [['09/27/04 09/28/04 09/29/04 09/30/04 10/01/04 10/02/04 10/03/04', 352 '10/04/04 10/05/04 10/06/04 10/07/04 10/08/04 10/09/04 10/10/04', 353 '10/11/04 10/12/04 10/13/04 10/14/04 10/15/04 10/16/04 10/17/04', 354 '10/18/04 10/19/04 10/20/04 10/21/04 10/22/04 10/23/04 10/24/04', 355 '10/25/04 10/26/04 10/27/04 10/28/04 10/29/04 10/30/04 10/31/04'], 356 ['11/01/04 11/02/04 11/03/04 11/04/04 11/05/04 11/06/04 11/07/04', 357 '11/08/04 11/09/04 11/10/04 11/11/04 11/12/04 11/13/04 11/14/04', 358 '11/15/04 11/16/04 11/17/04 11/18/04 11/19/04 11/20/04 11/21/04', 359 '11/22/04 11/23/04 11/24/04 11/25/04 11/26/04 11/27/04 11/28/04', 360 '11/29/04 11/30/04 12/01/04 12/02/04 12/03/04 12/04/04 12/05/04'], 361 ['11/29/04 11/30/04 12/01/04 12/02/04 12/03/04 12/04/04 12/05/04', 362 '12/06/04 12/07/04 12/08/04 12/09/04 12/10/04 12/11/04 12/12/04', 363 '12/13/04 12/14/04 12/15/04 12/16/04 12/17/04 12/18/04 12/19/04', 364 '12/20/04 12/21/04 12/22/04 12/23/04 12/24/04 12/25/04 12/26/04', 365 '12/27/04 12/28/04 12/29/04 12/30/04 12/31/04 01/01/05 01/02/05']]] 366 367 368class OutputTestCase(unittest.TestCase): 369 def normalize_calendar(self, s): 370 # Filters out locale dependent strings 371 def neitherspacenordigit(c): 372 return not c.isspace() and not c.isdigit() 373 374 lines = [] 375 for line in s.splitlines(keepends=False): 376 # Drop texts, as they are locale dependent 377 if line and not filter(neitherspacenordigit, line): 378 lines.append(line) 379 return lines 380 381 def check_htmlcalendar_encoding(self, req, res): 382 cal = calendar.HTMLCalendar() 383 format_ = default_format.copy() 384 format_["encoding"] = req or 'utf-8' 385 output = cal.formatyearpage(2004, encoding=req) 386 self.assertEqual( 387 output, 388 result_2004_html.format(**format_).encode(res) 389 ) 390 391 def test_output(self): 392 self.assertEqual( 393 self.normalize_calendar(calendar.calendar(2004)), 394 self.normalize_calendar(result_2004_text) 395 ) 396 self.assertEqual( 397 self.normalize_calendar(calendar.calendar(0)), 398 self.normalize_calendar(result_0_text) 399 ) 400 401 def test_output_textcalendar(self): 402 self.assertEqual( 403 calendar.TextCalendar().formatyear(2004), 404 result_2004_text 405 ) 406 self.assertEqual( 407 calendar.TextCalendar().formatyear(0), 408 result_0_text 409 ) 410 411 def test_output_htmlcalendar_encoding_ascii(self): 412 self.check_htmlcalendar_encoding('ascii', 'ascii') 413 414 def test_output_htmlcalendar_encoding_utf8(self): 415 self.check_htmlcalendar_encoding('utf-8', 'utf-8') 416 417 def test_output_htmlcalendar_encoding_default(self): 418 self.check_htmlcalendar_encoding(None, sys.getdefaultencoding()) 419 420 def test_yeardatescalendar(self): 421 def shrink(cal): 422 return [[[' '.join('{:02d}/{:02d}/{}'.format( 423 d.month, d.day, str(d.year)[-2:]) for d in z) 424 for z in y] for y in x] for x in cal] 425 self.assertEqual( 426 shrink(calendar.Calendar().yeardatescalendar(2004)), 427 result_2004_dates 428 ) 429 430 def test_yeardayscalendar(self): 431 self.assertEqual( 432 calendar.Calendar().yeardayscalendar(2004), 433 result_2004_days 434 ) 435 436 def test_formatweekheader_short(self): 437 self.assertEqual( 438 calendar.TextCalendar().formatweekheader(2), 439 'Mo Tu We Th Fr Sa Su' 440 ) 441 442 def test_formatweekheader_long(self): 443 self.assertEqual( 444 calendar.TextCalendar().formatweekheader(9), 445 ' Monday Tuesday Wednesday Thursday ' 446 ' Friday Saturday Sunday ' 447 ) 448 449 def test_formatmonth(self): 450 self.assertEqual( 451 calendar.TextCalendar().formatmonth(2004, 1), 452 result_2004_01_text 453 ) 454 self.assertEqual( 455 calendar.TextCalendar().formatmonth(0, 2), 456 result_0_02_text 457 ) 458 459 def test_formatmonthname_with_year(self): 460 self.assertEqual( 461 calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=True), 462 '<tr><th colspan="7" class="month">January 2004</th></tr>' 463 ) 464 465 def test_formatmonthname_without_year(self): 466 self.assertEqual( 467 calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=False), 468 '<tr><th colspan="7" class="month">January</th></tr>' 469 ) 470 471 def test_prweek(self): 472 with support.captured_stdout() as out: 473 week = [(1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6)] 474 calendar.TextCalendar().prweek(week, 1) 475 self.assertEqual(out.getvalue(), " 1 2 3 4 5 6 7") 476 477 def test_prmonth(self): 478 with support.captured_stdout() as out: 479 calendar.TextCalendar().prmonth(2004, 1) 480 self.assertEqual(out.getvalue(), result_2004_01_text) 481 482 def test_pryear(self): 483 with support.captured_stdout() as out: 484 calendar.TextCalendar().pryear(2004) 485 self.assertEqual(out.getvalue(), result_2004_text) 486 487 def test_format(self): 488 with support.captured_stdout() as out: 489 calendar.format(["1", "2", "3"], colwidth=3, spacing=1) 490 self.assertEqual(out.getvalue().strip(), "1 2 3") 491 492class CalendarTestCase(unittest.TestCase): 493 def test_isleap(self): 494 # Make sure that the return is right for a few years, and 495 # ensure that the return values are 1 or 0, not just true or 496 # false (see SF bug #485794). Specific additional tests may 497 # be appropriate; this tests a single "cycle". 498 self.assertEqual(calendar.isleap(2000), 1) 499 self.assertEqual(calendar.isleap(2001), 0) 500 self.assertEqual(calendar.isleap(2002), 0) 501 self.assertEqual(calendar.isleap(2003), 0) 502 503 def test_setfirstweekday(self): 504 self.assertRaises(TypeError, calendar.setfirstweekday, 'flabber') 505 self.assertRaises(ValueError, calendar.setfirstweekday, -1) 506 self.assertRaises(ValueError, calendar.setfirstweekday, 200) 507 orig = calendar.firstweekday() 508 calendar.setfirstweekday(calendar.SUNDAY) 509 self.assertEqual(calendar.firstweekday(), calendar.SUNDAY) 510 calendar.setfirstweekday(calendar.MONDAY) 511 self.assertEqual(calendar.firstweekday(), calendar.MONDAY) 512 calendar.setfirstweekday(orig) 513 514 def test_illegal_weekday_reported(self): 515 with self.assertRaisesRegex(calendar.IllegalWeekdayError, '123'): 516 calendar.setfirstweekday(123) 517 518 def test_enumerate_weekdays(self): 519 self.assertRaises(IndexError, calendar.day_abbr.__getitem__, -10) 520 self.assertRaises(IndexError, calendar.day_name.__getitem__, 10) 521 self.assertEqual(len([d for d in calendar.day_abbr]), 7) 522 523 def test_days(self): 524 for attr in "day_name", "day_abbr": 525 value = getattr(calendar, attr) 526 self.assertEqual(len(value), 7) 527 self.assertEqual(len(value[:]), 7) 528 # ensure they're all unique 529 self.assertEqual(len(set(value)), 7) 530 # verify it "acts like a sequence" in two forms of iteration 531 self.assertEqual(value[::-1], list(reversed(value))) 532 533 def test_months(self): 534 for attr in "month_name", "month_abbr": 535 value = getattr(calendar, attr) 536 self.assertEqual(len(value), 13) 537 self.assertEqual(len(value[:]), 13) 538 self.assertEqual(value[0], "") 539 # ensure they're all unique 540 self.assertEqual(len(set(value)), 13) 541 # verify it "acts like a sequence" in two forms of iteration 542 self.assertEqual(value[::-1], list(reversed(value))) 543 544 def test_locale_calendars(self): 545 # ensure that Locale{Text,HTML}Calendar resets the locale properly 546 # (it is still not thread-safe though) 547 old_october = calendar.TextCalendar().formatmonthname(2010, 10, 10) 548 try: 549 cal = calendar.LocaleTextCalendar(locale='') 550 local_weekday = cal.formatweekday(1, 10) 551 local_month = cal.formatmonthname(2010, 10, 10) 552 except locale.Error: 553 # cannot set the system default locale -- skip rest of test 554 raise unittest.SkipTest('cannot set the system default locale') 555 self.assertIsInstance(local_weekday, str) 556 self.assertIsInstance(local_month, str) 557 self.assertEqual(len(local_weekday), 10) 558 self.assertGreaterEqual(len(local_month), 10) 559 cal = calendar.LocaleHTMLCalendar(locale='') 560 local_weekday = cal.formatweekday(1) 561 local_month = cal.formatmonthname(2010, 10) 562 self.assertIsInstance(local_weekday, str) 563 self.assertIsInstance(local_month, str) 564 new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10) 565 self.assertEqual(old_october, new_october) 566 567 def test_locale_html_calendar_custom_css_class_month_name(self): 568 try: 569 cal = calendar.LocaleHTMLCalendar(locale='') 570 local_month = cal.formatmonthname(2010, 10, 10) 571 except locale.Error: 572 # cannot set the system default locale -- skip rest of test 573 raise unittest.SkipTest('cannot set the system default locale') 574 self.assertIn('class="month"', local_month) 575 cal.cssclass_month_head = "text-center month" 576 local_month = cal.formatmonthname(2010, 10, 10) 577 self.assertIn('class="text-center month"', local_month) 578 579 def test_locale_html_calendar_custom_css_class_weekday(self): 580 try: 581 cal = calendar.LocaleHTMLCalendar(locale='') 582 local_weekday = cal.formatweekday(6) 583 except locale.Error: 584 # cannot set the system default locale -- skip rest of test 585 raise unittest.SkipTest('cannot set the system default locale') 586 self.assertIn('class="sun"', local_weekday) 587 cal.cssclasses_weekday_head = ["mon2", "tue2", "wed2", "thu2", "fri2", "sat2", "sun2"] 588 local_weekday = cal.formatweekday(6) 589 self.assertIn('class="sun2"', local_weekday) 590 591 def test_itermonthdays3(self): 592 # ensure itermonthdays3 doesn't overflow after datetime.MAXYEAR 593 list(calendar.Calendar().itermonthdays3(datetime.MAXYEAR, 12)) 594 595 def test_itermonthdays4(self): 596 cal = calendar.Calendar(firstweekday=3) 597 days = list(cal.itermonthdays4(2001, 2)) 598 self.assertEqual(days[0], (2001, 2, 1, 3)) 599 self.assertEqual(days[-1], (2001, 2, 28, 2)) 600 601 def test_itermonthdays(self): 602 for firstweekday in range(7): 603 cal = calendar.Calendar(firstweekday) 604 # Test the extremes, see #28253 and #26650 605 for y, m in [(1, 1), (9999, 12)]: 606 days = list(cal.itermonthdays(y, m)) 607 self.assertIn(len(days), (35, 42)) 608 # Test a short month 609 cal = calendar.Calendar(firstweekday=3) 610 days = list(cal.itermonthdays(2001, 2)) 611 self.assertEqual(days, list(range(1, 29))) 612 613 def test_itermonthdays2(self): 614 for firstweekday in range(7): 615 cal = calendar.Calendar(firstweekday) 616 # Test the extremes, see #28253 and #26650 617 for y, m in [(1, 1), (9999, 12)]: 618 days = list(cal.itermonthdays2(y, m)) 619 self.assertEqual(days[0][1], firstweekday) 620 self.assertEqual(days[-1][1], (firstweekday - 1) % 7) 621 622 623class MonthCalendarTestCase(unittest.TestCase): 624 def setUp(self): 625 self.oldfirstweekday = calendar.firstweekday() 626 calendar.setfirstweekday(self.firstweekday) 627 628 def tearDown(self): 629 calendar.setfirstweekday(self.oldfirstweekday) 630 631 def check_weeks(self, year, month, weeks): 632 cal = calendar.monthcalendar(year, month) 633 self.assertEqual(len(cal), len(weeks)) 634 for i in range(len(weeks)): 635 self.assertEqual(weeks[i], sum(day != 0 for day in cal[i])) 636 637 638class MondayTestCase(MonthCalendarTestCase): 639 firstweekday = calendar.MONDAY 640 641 def test_february(self): 642 # A 28-day february starting on monday (7+7+7+7 days) 643 self.check_weeks(1999, 2, (7, 7, 7, 7)) 644 645 # A 28-day february starting on tuesday (6+7+7+7+1 days) 646 self.check_weeks(2005, 2, (6, 7, 7, 7, 1)) 647 648 # A 28-day february starting on sunday (1+7+7+7+6 days) 649 self.check_weeks(1987, 2, (1, 7, 7, 7, 6)) 650 651 # A 29-day february starting on monday (7+7+7+7+1 days) 652 self.check_weeks(1988, 2, (7, 7, 7, 7, 1)) 653 654 # A 29-day february starting on tuesday (6+7+7+7+2 days) 655 self.check_weeks(1972, 2, (6, 7, 7, 7, 2)) 656 657 # A 29-day february starting on sunday (1+7+7+7+7 days) 658 self.check_weeks(2004, 2, (1, 7, 7, 7, 7)) 659 660 def test_april(self): 661 # A 30-day april starting on monday (7+7+7+7+2 days) 662 self.check_weeks(1935, 4, (7, 7, 7, 7, 2)) 663 664 # A 30-day april starting on tuesday (6+7+7+7+3 days) 665 self.check_weeks(1975, 4, (6, 7, 7, 7, 3)) 666 667 # A 30-day april starting on sunday (1+7+7+7+7+1 days) 668 self.check_weeks(1945, 4, (1, 7, 7, 7, 7, 1)) 669 670 # A 30-day april starting on saturday (2+7+7+7+7 days) 671 self.check_weeks(1995, 4, (2, 7, 7, 7, 7)) 672 673 # A 30-day april starting on friday (3+7+7+7+6 days) 674 self.check_weeks(1994, 4, (3, 7, 7, 7, 6)) 675 676 def test_december(self): 677 # A 31-day december starting on monday (7+7+7+7+3 days) 678 self.check_weeks(1980, 12, (7, 7, 7, 7, 3)) 679 680 # A 31-day december starting on tuesday (6+7+7+7+4 days) 681 self.check_weeks(1987, 12, (6, 7, 7, 7, 4)) 682 683 # A 31-day december starting on sunday (1+7+7+7+7+2 days) 684 self.check_weeks(1968, 12, (1, 7, 7, 7, 7, 2)) 685 686 # A 31-day december starting on thursday (4+7+7+7+6 days) 687 self.check_weeks(1988, 12, (4, 7, 7, 7, 6)) 688 689 # A 31-day december starting on friday (3+7+7+7+7 days) 690 self.check_weeks(2017, 12, (3, 7, 7, 7, 7)) 691 692 # A 31-day december starting on saturday (2+7+7+7+7+1 days) 693 self.check_weeks(2068, 12, (2, 7, 7, 7, 7, 1)) 694 695 696class SundayTestCase(MonthCalendarTestCase): 697 firstweekday = calendar.SUNDAY 698 699 def test_february(self): 700 # A 28-day february starting on sunday (7+7+7+7 days) 701 self.check_weeks(2009, 2, (7, 7, 7, 7)) 702 703 # A 28-day february starting on monday (6+7+7+7+1 days) 704 self.check_weeks(1999, 2, (6, 7, 7, 7, 1)) 705 706 # A 28-day february starting on saturday (1+7+7+7+6 days) 707 self.check_weeks(1997, 2, (1, 7, 7, 7, 6)) 708 709 # A 29-day february starting on sunday (7+7+7+7+1 days) 710 self.check_weeks(2004, 2, (7, 7, 7, 7, 1)) 711 712 # A 29-day february starting on monday (6+7+7+7+2 days) 713 self.check_weeks(1960, 2, (6, 7, 7, 7, 2)) 714 715 # A 29-day february starting on saturday (1+7+7+7+7 days) 716 self.check_weeks(1964, 2, (1, 7, 7, 7, 7)) 717 718 def test_april(self): 719 # A 30-day april starting on sunday (7+7+7+7+2 days) 720 self.check_weeks(1923, 4, (7, 7, 7, 7, 2)) 721 722 # A 30-day april starting on monday (6+7+7+7+3 days) 723 self.check_weeks(1918, 4, (6, 7, 7, 7, 3)) 724 725 # A 30-day april starting on saturday (1+7+7+7+7+1 days) 726 self.check_weeks(1950, 4, (1, 7, 7, 7, 7, 1)) 727 728 # A 30-day april starting on friday (2+7+7+7+7 days) 729 self.check_weeks(1960, 4, (2, 7, 7, 7, 7)) 730 731 # A 30-day april starting on thursday (3+7+7+7+6 days) 732 self.check_weeks(1909, 4, (3, 7, 7, 7, 6)) 733 734 def test_december(self): 735 # A 31-day december starting on sunday (7+7+7+7+3 days) 736 self.check_weeks(2080, 12, (7, 7, 7, 7, 3)) 737 738 # A 31-day december starting on monday (6+7+7+7+4 days) 739 self.check_weeks(1941, 12, (6, 7, 7, 7, 4)) 740 741 # A 31-day december starting on saturday (1+7+7+7+7+2 days) 742 self.check_weeks(1923, 12, (1, 7, 7, 7, 7, 2)) 743 744 # A 31-day december starting on wednesday (4+7+7+7+6 days) 745 self.check_weeks(1948, 12, (4, 7, 7, 7, 6)) 746 747 # A 31-day december starting on thursday (3+7+7+7+7 days) 748 self.check_weeks(1927, 12, (3, 7, 7, 7, 7)) 749 750 # A 31-day december starting on friday (2+7+7+7+7+1 days) 751 self.check_weeks(1995, 12, (2, 7, 7, 7, 7, 1)) 752 753class TimegmTestCase(unittest.TestCase): 754 TIMESTAMPS = [0, 10, 100, 1000, 10000, 100000, 1000000, 755 1234567890, 1262304000, 1275785153,] 756 def test_timegm(self): 757 for secs in self.TIMESTAMPS: 758 tuple = time.gmtime(secs) 759 self.assertEqual(secs, calendar.timegm(tuple)) 760 761class MonthRangeTestCase(unittest.TestCase): 762 def test_january(self): 763 # Tests valid lower boundary case. 764 self.assertEqual(calendar.monthrange(2004,1), (3,31)) 765 766 def test_february_leap(self): 767 # Tests February during leap year. 768 self.assertEqual(calendar.monthrange(2004,2), (6,29)) 769 770 def test_february_nonleap(self): 771 # Tests February in non-leap year. 772 self.assertEqual(calendar.monthrange(2010,2), (0,28)) 773 774 def test_december(self): 775 # Tests valid upper boundary case. 776 self.assertEqual(calendar.monthrange(2004,12), (2,31)) 777 778 def test_zeroth_month(self): 779 # Tests low invalid boundary case. 780 with self.assertRaises(calendar.IllegalMonthError): 781 calendar.monthrange(2004, 0) 782 783 def test_thirteenth_month(self): 784 # Tests high invalid boundary case. 785 with self.assertRaises(calendar.IllegalMonthError): 786 calendar.monthrange(2004, 13) 787 788 def test_illegal_month_reported(self): 789 with self.assertRaisesRegex(calendar.IllegalMonthError, '65'): 790 calendar.monthrange(2004, 65) 791 792class LeapdaysTestCase(unittest.TestCase): 793 def test_no_range(self): 794 # test when no range i.e. two identical years as args 795 self.assertEqual(calendar.leapdays(2010,2010), 0) 796 797 def test_no_leapdays(self): 798 # test when no leap years in range 799 self.assertEqual(calendar.leapdays(2010,2011), 0) 800 801 def test_no_leapdays_upper_boundary(self): 802 # test no leap years in range, when upper boundary is a leap year 803 self.assertEqual(calendar.leapdays(2010,2012), 0) 804 805 def test_one_leapday_lower_boundary(self): 806 # test when one leap year in range, lower boundary is leap year 807 self.assertEqual(calendar.leapdays(2012,2013), 1) 808 809 def test_several_leapyears_in_range(self): 810 self.assertEqual(calendar.leapdays(1997,2020), 5) 811 812 813def conv(s): 814 return s.replace('\n', os.linesep).encode() 815 816class CommandLineTestCase(unittest.TestCase): 817 def run_ok(self, *args): 818 return assert_python_ok('-m', 'calendar', *args)[1] 819 820 def assertFailure(self, *args): 821 rc, stdout, stderr = assert_python_failure('-m', 'calendar', *args) 822 self.assertIn(b'usage:', stderr) 823 self.assertEqual(rc, 2) 824 825 def test_help(self): 826 stdout = self.run_ok('-h') 827 self.assertIn(b'usage:', stdout) 828 self.assertIn(b'calendar.py', stdout) 829 self.assertIn(b'--help', stdout) 830 831 def test_illegal_arguments(self): 832 self.assertFailure('-z') 833 self.assertFailure('spam') 834 self.assertFailure('2004', 'spam') 835 self.assertFailure('-t', 'html', '2004', '1') 836 837 def test_output_current_year(self): 838 stdout = self.run_ok() 839 year = datetime.datetime.now().year 840 self.assertIn((' %s' % year).encode(), stdout) 841 self.assertIn(b'January', stdout) 842 self.assertIn(b'Mo Tu We Th Fr Sa Su', stdout) 843 844 def test_output_year(self): 845 stdout = self.run_ok('2004') 846 self.assertEqual(stdout, conv(result_2004_text)) 847 848 def test_output_month(self): 849 stdout = self.run_ok('2004', '1') 850 self.assertEqual(stdout, conv(result_2004_01_text)) 851 852 def test_option_encoding(self): 853 self.assertFailure('-e') 854 self.assertFailure('--encoding') 855 stdout = self.run_ok('--encoding', 'utf-16-le', '2004') 856 self.assertEqual(stdout, result_2004_text.encode('utf-16-le')) 857 858 def test_option_locale(self): 859 self.assertFailure('-L') 860 self.assertFailure('--locale') 861 self.assertFailure('-L', 'en') 862 lang, enc = locale.getdefaultlocale() 863 lang = lang or 'C' 864 enc = enc or 'UTF-8' 865 try: 866 oldlocale = locale.getlocale(locale.LC_TIME) 867 try: 868 locale.setlocale(locale.LC_TIME, (lang, enc)) 869 finally: 870 locale.setlocale(locale.LC_TIME, oldlocale) 871 except (locale.Error, ValueError): 872 self.skipTest('cannot set the system default locale') 873 stdout = self.run_ok('--locale', lang, '--encoding', enc, '2004') 874 self.assertIn('2004'.encode(enc), stdout) 875 876 def test_option_width(self): 877 self.assertFailure('-w') 878 self.assertFailure('--width') 879 self.assertFailure('-w', 'spam') 880 stdout = self.run_ok('--width', '3', '2004') 881 self.assertIn(b'Mon Tue Wed Thu Fri Sat Sun', stdout) 882 883 def test_option_lines(self): 884 self.assertFailure('-l') 885 self.assertFailure('--lines') 886 self.assertFailure('-l', 'spam') 887 stdout = self.run_ok('--lines', '2', '2004') 888 self.assertIn(conv('December\n\nMo Tu We'), stdout) 889 890 def test_option_spacing(self): 891 self.assertFailure('-s') 892 self.assertFailure('--spacing') 893 self.assertFailure('-s', 'spam') 894 stdout = self.run_ok('--spacing', '8', '2004') 895 self.assertIn(b'Su Mo', stdout) 896 897 def test_option_months(self): 898 self.assertFailure('-m') 899 self.assertFailure('--month') 900 self.assertFailure('-m', 'spam') 901 stdout = self.run_ok('--months', '1', '2004') 902 self.assertIn(conv('\nMo Tu We Th Fr Sa Su\n'), stdout) 903 904 def test_option_type(self): 905 self.assertFailure('-t') 906 self.assertFailure('--type') 907 self.assertFailure('-t', 'spam') 908 stdout = self.run_ok('--type', 'text', '2004') 909 self.assertEqual(stdout, conv(result_2004_text)) 910 stdout = self.run_ok('--type', 'html', '2004') 911 self.assertEqual(stdout[:6], b'<?xml ') 912 self.assertIn(b'<title>Calendar for 2004</title>', stdout) 913 914 def test_html_output_current_year(self): 915 stdout = self.run_ok('--type', 'html') 916 year = datetime.datetime.now().year 917 self.assertIn(('<title>Calendar for %s</title>' % year).encode(), 918 stdout) 919 self.assertIn(b'<tr><th colspan="7" class="month">January</th></tr>', 920 stdout) 921 922 def test_html_output_year_encoding(self): 923 stdout = self.run_ok('-t', 'html', '--encoding', 'ascii', '2004') 924 self.assertEqual(stdout, 925 result_2004_html.format(**default_format).encode('ascii')) 926 927 def test_html_output_year_css(self): 928 self.assertFailure('-t', 'html', '-c') 929 self.assertFailure('-t', 'html', '--css') 930 stdout = self.run_ok('-t', 'html', '--css', 'custom.css', '2004') 931 self.assertIn(b'<link rel="stylesheet" type="text/css" ' 932 b'href="custom.css" />', stdout) 933 934 935class MiscTestCase(unittest.TestCase): 936 def test__all__(self): 937 not_exported = { 938 'mdays', 'January', 'February', 'EPOCH', 'MONDAY', 'TUESDAY', 939 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY', 940 'different_locale', 'c', 'prweek', 'week', 'format', 941 'formatstring', 'main', 'monthlen', 'prevmonth', 'nextmonth'} 942 support.check__all__(self, calendar, not_exported=not_exported) 943 944 945class TestSubClassingCase(unittest.TestCase): 946 947 def setUp(self): 948 949 class CustomHTMLCal(calendar.HTMLCalendar): 950 cssclasses = [style + " text-nowrap" for style in 951 calendar.HTMLCalendar.cssclasses] 952 cssclasses_weekday_head = ["red", "blue", "green", "lilac", 953 "yellow", "orange", "pink"] 954 cssclass_month_head = "text-center month-head" 955 cssclass_month = "text-center month" 956 cssclass_year = "text-italic " 957 cssclass_year_head = "lead " 958 959 self.cal = CustomHTMLCal() 960 961 def test_formatmonthname(self): 962 self.assertIn('class="text-center month-head"', 963 self.cal.formatmonthname(2017, 5)) 964 965 def test_formatmonth(self): 966 self.assertIn('class="text-center month"', 967 self.cal.formatmonth(2017, 5)) 968 969 def test_formatweek(self): 970 weeks = self.cal.monthdays2calendar(2017, 5) 971 self.assertIn('class="wed text-nowrap"', self.cal.formatweek(weeks[0])) 972 973 def test_formatweek_head(self): 974 header = self.cal.formatweekheader() 975 for color in self.cal.cssclasses_weekday_head: 976 self.assertIn('<th class="%s">' % color, header) 977 978 def test_format_year(self): 979 self.assertIn( 980 ('<table border="0" cellpadding="0" cellspacing="0" class="%s">' % 981 self.cal.cssclass_year), self.cal.formatyear(2017)) 982 983 def test_format_year_head(self): 984 self.assertIn('<tr><th colspan="%d" class="%s">%s</th></tr>' % ( 985 3, self.cal.cssclass_year_head, 2017), self.cal.formatyear(2017)) 986 987if __name__ == "__main__": 988 unittest.main() 989