comparison test/test_templating.py @ 7866:9bbc1d951677

issue2551331 - Fix repeat first/last methods. The first() and last() methods for a variable defined by tal:repeat now work as documented. There is an undocumented same_part() method for repeat. It is called by first/last and can cause them to return true when not at an end of the Iterator sequence. I wrote a treatise on that function and what it does. I have no idea why it does what it does. Added tests for roundup/cgi/ZTUtils/Iterator.py Also fixes issue with roman() found while writing tests. lower wasn't being called and it was printing the lower() method signature. Doc updates in references.txt to come in a future checkin. Clarifying the repeat methods led to finding/fixing this.
author John Rouillard <rouilj@ieee.org>
date Sun, 07 Apr 2024 20:52:17 -0400
parents b080cdb8b199
children 29a666d8a70d
comparison
equal deleted inserted replaced
7865:ee586ff074ed 7866:9bbc1d951677
2 import unittest 2 import unittest
3 import time 3 import time
4 4
5 from roundup.anypy.cgi_ import FieldStorage, MiniFieldStorage 5 from roundup.anypy.cgi_ import FieldStorage, MiniFieldStorage
6 from roundup.cgi.templating import * 6 from roundup.cgi.templating import *
7 from roundup.cgi.ZTUtils.Iterator import Iterator
7 from .test_actions import MockNull, true 8 from .test_actions import MockNull, true
8 from .html_norm import NormalizingHtmlParser 9 from .html_norm import NormalizingHtmlParser
9 10
10 11
11 import pytest 12 import pytest
1117 def test_string_stext(self): 1118 def test_string_stext(self):
1118 p = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'A string with cmeerw@example.com *embedded* \u00df')) 1119 p = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'A string with cmeerw@example.com *embedded* \u00df'))
1119 self.assertEqual(p.stext(), u2s(u'A string with <a href="mailto:cmeerw@example.com">cmeerw@example.com</a> *embedded* \u00df')) 1120 self.assertEqual(p.stext(), u2s(u'A string with <a href="mailto:cmeerw@example.com">cmeerw@example.com</a> *embedded* \u00df'))
1120 1121
1121 1122
1123 class ZUtilsTestcase(TemplatingTestCase):
1124
1125 def test_Iterator(self):
1126 """Test all the iterator functions and properties.
1127 """
1128 sequence = ['one', 'two', '3', 4]
1129 i = Iterator(sequence)
1130 for j in [ # element, item, 1st, last, even, odd, number,
1131 # letter, Letter, roman, Roman
1132 (1, "one", 1, 0, True, 0, 1, 'a', 'A', 'i', 'I'),
1133 (1, "two", 0, 0, False, 1, 2, 'b', 'B', 'ii', 'II'),
1134 (1, "3", 0, 0, True, 0, 3, 'c', 'C', 'iii', 'III'),
1135 (1, 4, 0, 1, False, 1, 4, 'd', 'D', 'iv', 'IV'),
1136 # next() fails with 0 when past end of sequence
1137 # everything else is left at end of sequence
1138 (0, 4, 0, 1, False, 1, 4, 'd', 'D', 'iv', 'IV'),
1139
1140
1141 ]:
1142 element = i.next() # returns 1 if next item else 0
1143 print(i.item)
1144 self.assertEqual(element, j[0])
1145 self.assertEqual(i.item, j[1])
1146 self.assertEqual(i.first(), j[2])
1147 self.assertEqual(i.start, j[2])
1148 self.assertEqual(i.last(), j[3])
1149 self.assertEqual(i.end, j[3])
1150 self.assertIs(i.even(), j[4])
1151 self.assertEqual(i.odd(), j[5])
1152 self.assertEqual(i.number(), j[6])
1153 self.assertEqual(i.index, j[6] - 1)
1154 self.assertEqual(i.nextIndex, j[6])
1155 self.assertEqual(i.letter(), j[7])
1156 self.assertEqual(i.Letter(), j[8])
1157 self.assertEqual(i.roman(), j[9])
1158 self.assertEqual(i.Roman(), j[10])
1159
1160 class I:
1161 def __init__(self, name, data):
1162 self.name = name
1163 self.data = data
1164
1165 sequence = [I('Al', 'd'),
1166 I('Bob', 'e'),
1167 I('Bob', 'd'),
1168 I('Chip', 'd')
1169 ]
1170
1171 iterator = iter(sequence)
1172
1173 # Iterator is supposed take both sequence and Python iterator.
1174 for source in [sequence, iterator]:
1175 i = Iterator(source)
1176
1177 element = i.next() # returns 1 if next item else 0
1178 item1 = i.item
1179
1180 # note these can trigger calls by first/last to same_part().
1181 # It can return true for first/last even when there are more
1182 # items in the sequence. I am just testing the current
1183 # implementation. Woe to the person who tries to change
1184 # Iterator.py.
1185
1186 self.assertEqual(element, 1)
1187 # i.start == 1, so it bypasses name check
1188 self.assertEqual(i.first(name='namea'), 1)
1189 self.assertEqual(i.first(name='name'), 1)
1190 # i.end == 0 so it uses name check in object
1191 self.assertEqual(i.last(name='namea'), 0)
1192 self.assertEqual(i.last(name='name'), 0)
1193
1194 element = i.next() # returns 1 if next item else 0
1195 item2 = i.item
1196 self.assertEqual(element, 1)
1197 # i.start == 0 so it uses name check
1198 # between item1 and item2
1199 self.assertEqual(i.first(name='namea'), 0)
1200 self.assertEqual(i.first(name='name'), 0)
1201 # i.end == 0 so it uses name check in object
1202 # between item2 and the next item item3
1203 self.assertEqual(i.last(name='namea'), 0)
1204 self.assertEqual(i.last(name='name'), True)
1205
1206 element = i.next() # returns 1 if next item else 0
1207 item3 = i.item
1208 self.assertEqual(element, 1)
1209 # i.start == 0 so it uses name check
1210 self.assertEqual(i.first(name='namea'), 0)
1211 self.assertEqual(i.first(name='name'), 1)
1212 # i.end == 0 so it uses name check in object
1213 # between item3 and the next item item4
1214 self.assertEqual(i.last(name='namea'), 0)
1215 self.assertEqual(i.last(name='name'), 0)
1216
1217 element = i.next() # returns 1 if next item else 0
1218 item4 = i.item
1219 self.assertEqual(element, 1)
1220 # i.start == 0 so it uses name check
1221 self.assertEqual(i.first(name='namea'), 0)
1222 self.assertEqual(i.first(name='name'), 0)
1223 # i.end == 0 so it uses name check in object
1224 # last two object have same name (1)
1225 self.assertEqual(i.last(name='namea'), 1)
1226 self.assertEqual(i.last(name='name'), 1)
1227
1228 element = i.next() # returns 1 if next item else 0
1229 self.assertEqual(element, 0)
1230
1231 # this is the underlying call for first/last
1232 # when i.start/i.end are 0
1233 # use non-existing attribute name, same item
1234 self.assertIs(i.same_part('namea', item2, item2), False)
1235 # use correct attribute name
1236 self.assertIs(i.same_part('name', item2, item2), True)
1237 # use no attribute name
1238 self.assertIs(i.same_part(None, item2, item2), True)
1239
1240 # use non-existing attribute name, different item
1241 # non-matching names
1242 self.assertIs(i.same_part('namea', item1, item2), False)
1243 # use correct attribute name
1244 self.assertIs(i.same_part('name', item1, item2), False)
1245 # use no attribute name
1246 self.assertIs(i.same_part(None, item1, item2), False)
1247
1248 # use non-existing attribute name, different item
1249 # matching names
1250 self.assertIs(i.same_part('namea', item2, item3), False)
1251 # use correct attribute name
1252 self.assertIs(i.same_part('name', item2, item3), True)
1253 # use no attribute name
1254 self.assertIs(i.same_part(None, item2, item3), False)
1255
1122 r''' 1256 r'''
1123 class HTMLPermissions: 1257 class HTMLPermissions:
1124 def is_edit_ok(self): 1258 def is_edit_ok(self):
1125 def is_view_ok(self): 1259 def is_view_ok(self):
1126 def is_only_view_ok(self): 1260 def is_only_view_ok(self):

Roundup Issue Tracker: http://roundup-tracker.org/