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_itermonthdays3(self): 568 # ensure itermonthdays3 doesn't overflow after datetime.MAXYEAR 569 list(calendar.Calendar().itermonthdays3(datetime.MAXYEAR, 12)) 570 571 def test_itermonthdays4(self): 572 cal = calendar.Calendar(firstweekday=3) 573 days = list(cal.itermonthdays4(2001, 2)) 574 self.assertEqual(days[0], (2001, 2, 1, 3)) 575 self.assertEqual(days[-1], (2001, 2, 28, 2)) 576 577 def test_itermonthdays(self): 578 for firstweekday in range(7): 579 cal = calendar.Calendar(firstweekday) 580 # Test the extremes, see #28253 and #26650 581 for y, m in [(1, 1), (9999, 12)]: 582 days = list(cal.itermonthdays(y, m)) 583 self.assertIn(len(days), (35, 42)) 584 # Test a short month 585 cal = calendar.Calendar(firstweekday=3) 586 days = list(cal.itermonthdays(2001, 2)) 587 self.assertEqual(days, list(range(1, 29))) 588 589 def test_itermonthdays2(self): 590 for firstweekday in range(7): 591 cal = calendar.Calendar(firstweekday) 592 # Test the extremes, see #28253 and #26650 593 for y, m in [(1, 1), (9999, 12)]: 594 days = list(cal.itermonthdays2(y, m)) 595 self.assertEqual(days[0][1], firstweekday) 596 self.assertEqual(days[-1][1], (firstweekday - 1) % 7) 597 598 599class MonthCalendarTestCase(unittest.TestCase): 600 def setUp(self): 601 self.oldfirstweekday = calendar.firstweekday() 602 calendar.setfirstweekday(self.firstweekday) 603 604 def tearDown(self): 605 calendar.setfirstweekday(self.oldfirstweekday) 606 607 def check_weeks(self, year, month, weeks): 608 cal = calendar.monthcalendar(year, month) 609 self.assertEqual(len(cal), len(weeks)) 610 for i in range(len(weeks)): 611 self.assertEqual(weeks[i], sum(day != 0 for day in cal[i])) 612 613 614class MondayTestCase(MonthCalendarTestCase): 615 firstweekday = calendar.MONDAY 616 617 def test_february(self): 618 # A 28-day february starting on monday (7+7+7+7 days) 619 self.check_weeks(1999, 2, (7, 7, 7, 7)) 620 621 # A 28-day february starting on tuesday (6+7+7+7+1 days) 622 self.check_weeks(2005, 2, (6, 7, 7, 7, 1)) 623 624 # A 28-day february starting on sunday (1+7+7+7+6 days) 625 self.check_weeks(1987, 2, (1, 7, 7, 7, 6)) 626 627 # A 29-day february starting on monday (7+7+7+7+1 days) 628 self.check_weeks(1988, 2, (7, 7, 7, 7, 1)) 629 630 # A 29-day february starting on tuesday (6+7+7+7+2 days) 631 self.check_weeks(1972, 2, (6, 7, 7, 7, 2)) 632 633 # A 29-day february starting on sunday (1+7+7+7+7 days) 634 self.check_weeks(2004, 2, (1, 7, 7, 7, 7)) 635 636 def test_april(self): 637 # A 30-day april starting on monday (7+7+7+7+2 days) 638 self.check_weeks(1935, 4, (7, 7, 7, 7, 2)) 639 640 # A 30-day april starting on tuesday (6+7+7+7+3 days) 641 self.check_weeks(1975, 4, (6, 7, 7, 7, 3)) 642 643 # A 30-day april starting on sunday (1+7+7+7+7+1 days) 644 self.check_weeks(1945, 4, (1, 7, 7, 7, 7, 1)) 645 646 # A 30-day april starting on saturday (2+7+7+7+7 days) 647 self.check_weeks(1995, 4, (2, 7, 7, 7, 7)) 648 649 # A 30-day april starting on friday (3+7+7+7+6 days) 650 self.check_weeks(1994, 4, (3, 7, 7, 7, 6)) 651 652 def test_december(self): 653 # A 31-day december starting on monday (7+7+7+7+3 days) 654 self.check_weeks(1980, 12, (7, 7, 7, 7, 3)) 655 656 # A 31-day december starting on tuesday (6+7+7+7+4 days) 657 self.check_weeks(1987, 12, (6, 7, 7, 7, 4)) 658 659 # A 31-day december starting on sunday (1+7+7+7+7+2 days) 660 self.check_weeks(1968, 12, (1, 7, 7, 7, 7, 2)) 661 662 # A 31-day december starting on thursday (4+7+7+7+6 days) 663 self.check_weeks(1988, 12, (4, 7, 7, 7, 6)) 664 665 # A 31-day december starting on friday (3+7+7+7+7 days) 666 self.check_weeks(2017, 12, (3, 7, 7, 7, 7)) 667 668 # A 31-day december starting on saturday (2+7+7+7+7+1 days) 669 self.check_weeks(2068, 12, (2, 7, 7, 7, 7, 1)) 670 671 672class SundayTestCase(MonthCalendarTestCase): 673 firstweekday = calendar.SUNDAY 674 675 def test_february(self): 676 # A 28-day february starting on sunday (7+7+7+7 days) 677 self.check_weeks(2009, 2, (7, 7, 7, 7)) 678 679 # A 28-day february starting on monday (6+7+7+7+1 days) 680 self.check_weeks(1999, 2, (6, 7, 7, 7, 1)) 681 682 # A 28-day february starting on saturday (1+7+7+7+6 days) 683 self.check_weeks(1997, 2, (1, 7, 7, 7, 6)) 684 685 # A 29-day february starting on sunday (7+7+7+7+1 days) 686 self.check_weeks(2004, 2, (7, 7, 7, 7, 1)) 687 688 # A 29-day february starting on monday (6+7+7+7+2 days) 689 self.check_weeks(1960, 2, (6, 7, 7, 7, 2)) 690 691 # A 29-day february starting on saturday (1+7+7+7+7 days) 692 self.check_weeks(1964, 2, (1, 7, 7, 7, 7)) 693 694 def test_april(self): 695 # A 30-day april starting on sunday (7+7+7+7+2 days) 696 self.check_weeks(1923, 4, (7, 7, 7, 7, 2)) 697 698 # A 30-day april starting on monday (6+7+7+7+3 days) 699 self.check_weeks(1918, 4, (6, 7, 7, 7, 3)) 700 701 # A 30-day april starting on saturday (1+7+7+7+7+1 days) 702 self.check_weeks(1950, 4, (1, 7, 7, 7, 7, 1)) 703 704 # A 30-day april starting on friday (2+7+7+7+7 days) 705 self.check_weeks(1960, 4, (2, 7, 7, 7, 7)) 706 707 # A 30-day april starting on thursday (3+7+7+7+6 days) 708 self.check_weeks(1909, 4, (3, 7, 7, 7, 6)) 709 710 def test_december(self): 711 # A 31-day december starting on sunday (7+7+7+7+3 days) 712 self.check_weeks(2080, 12, (7, 7, 7, 7, 3)) 713 714 # A 31-day december starting on monday (6+7+7+7+4 days) 715 self.check_weeks(1941, 12, (6, 7, 7, 7, 4)) 716 717 # A 31-day december starting on saturday (1+7+7+7+7+2 days) 718 self.check_weeks(1923, 12, (1, 7, 7, 7, 7, 2)) 719 720 # A 31-day december starting on wednesday (4+7+7+7+6 days) 721 self.check_weeks(1948, 12, (4, 7, 7, 7, 6)) 722 723 # A 31-day december starting on thursday (3+7+7+7+7 days) 724 self.check_weeks(1927, 12, (3, 7, 7, 7, 7)) 725 726 # A 31-day december starting on friday (2+7+7+7+7+1 days) 727 self.check_weeks(1995, 12, (2, 7, 7, 7, 7, 1)) 728 729class TimegmTestCase(unittest.TestCase): 730 TIMESTAMPS = [0, 10, 100, 1000, 10000, 100000, 1000000, 731 1234567890, 1262304000, 1275785153,] 732 def test_timegm(self): 733 for secs in self.TIMESTAMPS: 734 tuple = time.gmtime(secs) 735 self.assertEqual(secs, calendar.timegm(tuple)) 736 737class MonthRangeTestCase(unittest.TestCase): 738 def test_january(self): 739 # Tests valid lower boundary case. 740 self.assertEqual(calendar.monthrange(2004,1), (3,31)) 741 742 def test_february_leap(self): 743 # Tests February during leap year. 744 self.assertEqual(calendar.monthrange(2004,2), (6,29)) 745 746 def test_february_nonleap(self): 747 # Tests February in non-leap year. 748 self.assertEqual(calendar.monthrange(2010,2), (0,28)) 749 750 def test_december(self): 751 # Tests valid upper boundary case. 752 self.assertEqual(calendar.monthrange(2004,12), (2,31)) 753 754 def test_zeroth_month(self): 755 # Tests low invalid boundary case. 756 with self.assertRaises(calendar.IllegalMonthError): 757 calendar.monthrange(2004, 0) 758 759 def test_thirteenth_month(self): 760 # Tests high invalid boundary case. 761 with self.assertRaises(calendar.IllegalMonthError): 762 calendar.monthrange(2004, 13) 763 764 def test_illegal_month_reported(self): 765 with self.assertRaisesRegex(calendar.IllegalMonthError, '65'): 766 calendar.monthrange(2004, 65) 767 768class LeapdaysTestCase(unittest.TestCase): 769 def test_no_range(self): 770 # test when no range i.e. two identical years as args 771 self.assertEqual(calendar.leapdays(2010,2010), 0) 772 773 def test_no_leapdays(self): 774 # test when no leap years in range 775 self.assertEqual(calendar.leapdays(2010,2011), 0) 776 777 def test_no_leapdays_upper_boundary(self): 778 # test no leap years in range, when upper boundary is a leap year 779 self.assertEqual(calendar.leapdays(2010,2012), 0) 780 781 def test_one_leapday_lower_boundary(self): 782 # test when one leap year in range, lower boundary is leap year 783 self.assertEqual(calendar.leapdays(2012,2013), 1) 784 785 def test_several_leapyears_in_range(self): 786 self.assertEqual(calendar.leapdays(1997,2020), 5) 787 788 789def conv(s): 790 return s.replace('\n', os.linesep).encode() 791 792class CommandLineTestCase(unittest.TestCase): 793 def run_ok(self, *args): 794 return assert_python_ok('-m', 'calendar', *args)[1] 795 796 def assertFailure(self, *args): 797 rc, stdout, stderr = assert_python_failure('-m', 'calendar', *args) 798 self.assertIn(b'usage:', stderr) 799 self.assertEqual(rc, 2) 800 801 def test_help(self): 802 stdout = self.run_ok('-h') 803 self.assertIn(b'usage:', stdout) 804 self.assertIn(b'calendar.py', stdout) 805 self.assertIn(b'--help', stdout) 806 807 def test_illegal_arguments(self): 808 self.assertFailure('-z') 809 self.assertFailure('spam') 810 self.assertFailure('2004', 'spam') 811 self.assertFailure('-t', 'html', '2004', '1') 812 813 def test_output_current_year(self): 814 stdout = self.run_ok() 815 year = datetime.datetime.now().year 816 self.assertIn((' %s' % year).encode(), stdout) 817 self.assertIn(b'January', stdout) 818 self.assertIn(b'Mo Tu We Th Fr Sa Su', stdout) 819 820 def test_output_year(self): 821 stdout = self.run_ok('2004') 822 self.assertEqual(stdout, conv(result_2004_text)) 823 824 def test_output_month(self): 825 stdout = self.run_ok('2004', '1') 826 self.assertEqual(stdout, conv(result_2004_01_text)) 827 828 def test_option_encoding(self): 829 self.assertFailure('-e') 830 self.assertFailure('--encoding') 831 stdout = self.run_ok('--encoding', 'utf-16-le', '2004') 832 self.assertEqual(stdout, result_2004_text.encode('utf-16-le')) 833 834 def test_option_locale(self): 835 self.assertFailure('-L') 836 self.assertFailure('--locale') 837 self.assertFailure('-L', 'en') 838 lang, enc = locale.getdefaultlocale() 839 lang = lang or 'C' 840 enc = enc or 'UTF-8' 841 try: 842 oldlocale = locale.getlocale(locale.LC_TIME) 843 try: 844 locale.setlocale(locale.LC_TIME, (lang, enc)) 845 finally: 846 locale.setlocale(locale.LC_TIME, oldlocale) 847 except (locale.Error, ValueError): 848 self.skipTest('cannot set the system default locale') 849 stdout = self.run_ok('--locale', lang, '--encoding', enc, '2004') 850 self.assertIn('2004'.encode(enc), stdout) 851 852 def test_option_width(self): 853 self.assertFailure('-w') 854 self.assertFailure('--width') 855 self.assertFailure('-w', 'spam') 856 stdout = self.run_ok('--width', '3', '2004') 857 self.assertIn(b'Mon Tue Wed Thu Fri Sat Sun', stdout) 858 859 def test_option_lines(self): 860 self.assertFailure('-l') 861 self.assertFailure('--lines') 862 self.assertFailure('-l', 'spam') 863 stdout = self.run_ok('--lines', '2', '2004') 864 self.assertIn(conv('December\n\nMo Tu We'), stdout) 865 866 def test_option_spacing(self): 867 self.assertFailure('-s') 868 self.assertFailure('--spacing') 869 self.assertFailure('-s', 'spam') 870 stdout = self.run_ok('--spacing', '8', '2004') 871 self.assertIn(b'Su Mo', stdout) 872 873 def test_option_months(self): 874 self.assertFailure('-m') 875 self.assertFailure('--month') 876 self.assertFailure('-m', 'spam') 877 stdout = self.run_ok('--months', '1', '2004') 878 self.assertIn(conv('\nMo Tu We Th Fr Sa Su\n'), stdout) 879 880 def test_option_type(self): 881 self.assertFailure('-t') 882 self.assertFailure('--type') 883 self.assertFailure('-t', 'spam') 884 stdout = self.run_ok('--type', 'text', '2004') 885 self.assertEqual(stdout, conv(result_2004_text)) 886 stdout = self.run_ok('--type', 'html', '2004') 887 self.assertEqual(stdout[:6], b'<?xml ') 888 self.assertIn(b'<title>Calendar for 2004</title>', stdout) 889 890 def test_html_output_current_year(self): 891 stdout = self.run_ok('--type', 'html') 892 year = datetime.datetime.now().year 893 self.assertIn(('<title>Calendar for %s</title>' % year).encode(), 894 stdout) 895 self.assertIn(b'<tr><th colspan="7" class="month">January</th></tr>', 896 stdout) 897 898 def test_html_output_year_encoding(self): 899 stdout = self.run_ok('-t', 'html', '--encoding', 'ascii', '2004') 900 self.assertEqual(stdout, 901 result_2004_html.format(**default_format).encode('ascii')) 902 903 def test_html_output_year_css(self): 904 self.assertFailure('-t', 'html', '-c') 905 self.assertFailure('-t', 'html', '--css') 906 stdout = self.run_ok('-t', 'html', '--css', 'custom.css', '2004') 907 self.assertIn(b'<link rel="stylesheet" type="text/css" ' 908 b'href="custom.css" />', stdout) 909 910 911class MiscTestCase(unittest.TestCase): 912 def test__all__(self): 913 blacklist = {'mdays', 'January', 'February', 'EPOCH', 914 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 915 'SATURDAY', 'SUNDAY', 'different_locale', 'c', 916 'prweek', 'week', 'format', 'formatstring', 'main', 917 'monthlen', 'prevmonth', 'nextmonth'} 918 support.check__all__(self, calendar, blacklist=blacklist) 919 920 921class TestSubClassingCase(unittest.TestCase): 922 923 def setUp(self): 924 925 class CustomHTMLCal(calendar.HTMLCalendar): 926 cssclasses = [style + " text-nowrap" for style in 927 calendar.HTMLCalendar.cssclasses] 928 cssclasses_weekday_head = ["red", "blue", "green", "lilac", 929 "yellow", "orange", "pink"] 930 cssclass_month_head = "text-center month-head" 931 cssclass_month = "text-center month" 932 cssclass_year = "text-italic " 933 cssclass_year_head = "lead " 934 935 self.cal = CustomHTMLCal() 936 937 def test_formatmonthname(self): 938 self.assertIn('class="text-center month-head"', 939 self.cal.formatmonthname(2017, 5)) 940 941 def test_formatmonth(self): 942 self.assertIn('class="text-center month"', 943 self.cal.formatmonth(2017, 5)) 944 945 def test_formatweek(self): 946 weeks = self.cal.monthdays2calendar(2017, 5) 947 self.assertIn('class="wed text-nowrap"', self.cal.formatweek(weeks[0])) 948 949 def test_formatweek_head(self): 950 header = self.cal.formatweekheader() 951 for color in self.cal.cssclasses_weekday_head: 952 self.assertIn('<th class="%s">' % color, header) 953 954 def test_format_year(self): 955 self.assertIn( 956 ('<table border="0" cellpadding="0" cellspacing="0" class="%s">' % 957 self.cal.cssclass_year), self.cal.formatyear(2017)) 958 959 def test_format_year_head(self): 960 self.assertIn('<tr><th colspan="%d" class="%s">%s</th></tr>' % ( 961 3, self.cal.cssclass_year_head, 2017), self.cal.formatyear(2017)) 962 963if __name__ == "__main__": 964 unittest.main() 965