Mercurial > p > roundup > code
comparison roundup/cgi/templating.py @ 7037:22183e7d1443
flake8 whitepace, indents, var names
address:
B007 Loop control variable 'id' not used within the loop body. If this is intended, start the name with an underscore.
E122 continuation line missing indentation or outdented
E127 continuation line over-indented for visual indent
E128 continuation line under-indented for visual indent
E129 visually indented line with same indent as next logical line
E701 multiple statements on one line (colon)
E703 statement ends with a semicolon
E741 ambiguous variable name 'l'
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 10 Oct 2022 15:43:13 -0400 |
| parents | 7847c9bdb631 |
| children | ca90f7270cd4 2c89bdc88923 |
comparison
equal
deleted
inserted
replaced
| 7036:7847c9bdb631 | 7037:22183e7d1443 |
|---|---|
| 1020 | 1020 |
| 1021 def is_restore_ok(self): | 1021 def is_restore_ok(self): |
| 1022 """ Is the user allowed to restore this item? | 1022 """ Is the user allowed to restore this item? |
| 1023 """ | 1023 """ |
| 1024 perm = self._db.security.hasPermission | 1024 perm = self._db.security.hasPermission |
| 1025 return perm('Web Access', self._client.userid) and perm('Restore', | 1025 return perm('Web Access', self._client.userid) and perm( |
| 1026 self._client.userid, self._classname, itemid=self._nodeid) | 1026 'Restore', self._client.userid, self._classname, |
| 1027 itemid=self._nodeid) | |
| 1027 | 1028 |
| 1028 def is_view_ok(self): | 1029 def is_view_ok(self): |
| 1029 """ Is the user allowed to View this item? | 1030 """ Is the user allowed to View this item? |
| 1030 """ | 1031 """ |
| 1031 perm = self._db.security.hasPermission | 1032 perm = self._db.security.hasPermission |
| 1157 | 1158 |
| 1158 timezone = self._db.getUserTimezone() | 1159 timezone = self._db.getUserTimezone() |
| 1159 l = [] | 1160 l = [] |
| 1160 current = {} | 1161 current = {} |
| 1161 comments = {} | 1162 comments = {} |
| 1162 for id, evt_date, user, action, args in history: | 1163 for _id, evt_date, user, action, args in history: |
| 1163 date_s = str(evt_date.local(timezone)).replace(".", " ") | 1164 date_s = str(evt_date.local(timezone)).replace(".", " ") |
| 1164 arg_s = '' | 1165 arg_s = '' |
| 1165 if action in ['link', 'unlink'] and isinstance(args, tuple): | 1166 if action in ['link', 'unlink'] and isinstance(args, tuple): |
| 1166 if len(args) == 3: | 1167 if len(args) == 3: |
| 1167 linkcl, linkid, key = args | 1168 linkcl, linkid, key = args |
| 1168 arg_s += '<a rel="nofollow noopener" href="%s%s">%s%s %s</a>' % (linkcl, linkid, | 1169 arg_s += '<a rel="nofollow noopener" href="%s%s">%s%s %s</a>' % ( |
| 1169 linkcl, linkid, key) | 1170 linkcl, linkid, linkcl, linkid, key) |
| 1170 else: | 1171 else: |
| 1171 arg_s = str(args) | 1172 arg_s = str(args) |
| 1172 elif isinstance(args, dict): | 1173 elif isinstance(args, dict): |
| 1173 cell = [] | 1174 cell = [] |
| 1174 for k in args.keys(): | 1175 for k in args.keys(): |
| 1181 if prop is None: | 1182 if prop is None: |
| 1182 # property no longer exists | 1183 # property no longer exists |
| 1183 comments['no_exist'] = self._( | 1184 comments['no_exist'] = self._( |
| 1184 "<em>The indicated property no longer exists</em>") | 1185 "<em>The indicated property no longer exists</em>") |
| 1185 cell.append(self._('<em>%s: %s</em>\n') | 1186 cell.append(self._('<em>%s: %s</em>\n') |
| 1186 % (self._(k), str(args[k]))) | 1187 % (self._(k), str(args[k]))) |
| 1187 continue | 1188 continue |
| 1188 | 1189 |
| 1189 # load the current state for the property (if we | 1190 # load the current state for the property (if we |
| 1190 # haven't already) | 1191 # haven't already) |
| 1191 if k not in current: | 1192 if k not in current: |
| 1207 linkid = self._klass.get(self._nodeid, k, None) | 1208 linkid = self._klass.get(self._nodeid, k, None) |
| 1208 current[k] = '<a rel="nofollow noopener" href="%s%s">%s</a>' % ( | 1209 current[k] = '<a rel="nofollow noopener" href="%s%s">%s</a>' % ( |
| 1209 classname, linkid, current[k]) | 1210 classname, linkid, current[k]) |
| 1210 | 1211 |
| 1211 if args[k] and (isinstance(prop, hyperdb.Multilink) or | 1212 if args[k] and (isinstance(prop, hyperdb.Multilink) or |
| 1212 isinstance(prop, hyperdb.Link)): | 1213 isinstance(prop, hyperdb.Link)): |
| 1213 # figure what the link class is | 1214 # figure what the link class is |
| 1214 classname = prop.classname | 1215 classname = prop.classname |
| 1215 try: | 1216 try: |
| 1216 linkcl = self._db.getclass(classname) | 1217 linkcl = self._db.getclass(classname) |
| 1217 except KeyError: | 1218 except KeyError: |
| 1220 "The linked class %(classname)s no longer exists" | 1221 "The linked class %(classname)s no longer exists" |
| 1221 ) % locals() | 1222 ) % locals() |
| 1222 labelprop = linkcl.labelprop(1) | 1223 labelprop = linkcl.labelprop(1) |
| 1223 try: | 1224 try: |
| 1224 template = self._client.selectTemplate(classname, | 1225 template = self._client.selectTemplate(classname, |
| 1225 'item') | 1226 'item') |
| 1226 if template.startswith('_generic.'): | 1227 if template.startswith('_generic.'): |
| 1227 raise NoTemplate('not really...') | 1228 raise NoTemplate('not really...') |
| 1228 hrefable = 1 | 1229 hrefable = 1 |
| 1229 except NoTemplate: | 1230 except NoTemplate: |
| 1230 hrefable = 0 | 1231 hrefable = 0 |
| 1249 # TODO: test for node existence even when | 1250 # TODO: test for node existence even when |
| 1250 # there's no labelprop! | 1251 # there's no labelprop! |
| 1251 try: | 1252 try: |
| 1252 if labelprop is not None and \ | 1253 if labelprop is not None and \ |
| 1253 labelprop != 'id': | 1254 labelprop != 'id': |
| 1254 label = linkcl.get(linkid, labelprop, | 1255 label = linkcl.get( |
| 1255 default=self._( | 1256 linkid, labelprop, |
| 1256 "[label is missing]")) | 1257 default=self._( |
| 1258 "[label is missing]")) | |
| 1257 label = html_escape(label) | 1259 label = html_escape(label) |
| 1258 except IndexError: | 1260 except IndexError: |
| 1259 comments['no_link'] = self._( | 1261 comments['no_link'] = self._( |
| 1260 "<strike>The linked node" | 1262 "<strike>The linked node" |
| 1261 " no longer exists</strike>") | 1263 " no longer exists</strike>") |
| 1262 subml.append('<strike>%s</strike>' % label) | 1264 subml.append('<strike>%s</strike>' % label) |
| 1263 else: | 1265 else: |
| 1264 if hrefable: | 1266 if hrefable: |
| 1265 subml.append('<a rel="nofollow noopener" ' | 1267 subml.append( |
| 1266 'href="%s%s">%s</a>' % ( | 1268 '<a rel="nofollow noopener" ' |
| 1267 classname, linkid, label)) | 1269 'href="%s%s">%s</a>' % ( |
| 1270 classname, linkid, label)) | |
| 1268 elif label is None: | 1271 elif label is None: |
| 1269 subml.append('%s%s' % (classname, | 1272 subml.append('%s%s' % (classname, |
| 1270 linkid)) | 1273 linkid)) |
| 1271 else: | 1274 else: |
| 1272 subml.append(label) | 1275 subml.append(label) |
| 1273 ml.append(sublabel + ', '.join(subml)) | 1276 ml.append(sublabel + ', '.join(subml)) |
| 1274 cell.append('%s:\n %s' % (self._(k), ', '.join(ml))) | 1277 cell.append('%s:\n %s' % (self._(k), ', '.join(ml))) |
| 1275 elif isinstance(prop, hyperdb.Link) and args[k]: | 1278 elif isinstance(prop, hyperdb.Link) and args[k]: |
| 1277 # if we have a label property, try to use it | 1280 # if we have a label property, try to use it |
| 1278 # TODO: test for node existence even when | 1281 # TODO: test for node existence even when |
| 1279 # there's no labelprop! | 1282 # there's no labelprop! |
| 1280 if labelprop is not None and labelprop != 'id': | 1283 if labelprop is not None and labelprop != 'id': |
| 1281 try: | 1284 try: |
| 1282 label = html_escape(linkcl.get(args[k], | 1285 label = html_escape( |
| 1283 labelprop, default=self._( | 1286 linkcl.get(args[k], |
| 1284 "[label is missing]"))) | 1287 labelprop, default=self._( |
| 1288 "[label is missing]"))) | |
| 1285 except IndexError: | 1289 except IndexError: |
| 1286 comments['no_link'] = self._( | 1290 comments['no_link'] = self._( |
| 1287 "<strike>The linked node" | 1291 "<strike>The linked node" |
| 1288 " no longer exists</strike>") | 1292 " no longer exists</strike>") |
| 1289 cell.append(' <strike>%s</strike>,\n' % label) | 1293 cell.append(' <strike>%s</strike>,\n' % label) |
| 1290 # "flag" this is done .... euwww | 1294 # "flag" this is done .... euwww |
| 1291 label = None | 1295 label = None |
| 1292 if label is not None: | 1296 if label is not None: |
| 1293 if hrefable: | 1297 if hrefable: |
| 1294 old = '<a rel="nofollow noopener" href="%s%s">%s</a>' % (classname, | 1298 old = '<a rel="nofollow noopener" href="%s%s">%s</a>' % ( |
| 1295 args[k], label) | 1299 classname, args[k], label) |
| 1296 else: | 1300 else: |
| 1297 old = label; | 1301 old = label |
| 1298 cell.append('%s: %s' % (self._(k), old)) | 1302 cell.append('%s: %s' % (self._(k), old)) |
| 1299 if k in current and current[k] is not None: | 1303 if k in current and current[k] is not None: |
| 1300 cell[-1] += ' -> %s' % current[k] | 1304 cell[-1] += ' -> %s' % current[k] |
| 1301 current[k] = old | 1305 current[k] = old |
| 1302 | 1306 |
| 1303 elif isinstance(prop, hyperdb.Date) and args[k]: | 1307 elif isinstance(prop, hyperdb.Date) and args[k]: |
| 1304 if args[k] is None: | 1308 if args[k] is None: |
| 1305 d = '' | 1309 d = '' |
| 1306 else: | 1310 else: |
| 1307 d = date.Date(args[k], | 1311 d = date.Date( |
| 1312 args[k], | |
| 1308 translator=self._client).local(timezone) | 1313 translator=self._client).local(timezone) |
| 1309 cell.append('%s: %s' % (self._(k), str(d))) | 1314 cell.append('%s: %s' % (self._(k), str(d))) |
| 1310 if k in current and current[k] is not None: | 1315 if k in current and current[k] is not None: |
| 1311 cell[-1] += ' -> %s' % current[k] | 1316 cell[-1] += ' -> %s' % current[k] |
| 1312 current[k] = str(d) | 1317 current[k] = str(d) |
| 1313 | 1318 |
| 1314 elif isinstance(prop, hyperdb.Interval) and args[k]: | 1319 elif isinstance(prop, hyperdb.Interval) and args[k]: |
| 1315 val = str(date.Interval(args[k], | 1320 val = str(date.Interval(args[k], |
| 1316 translator=self._client)) | 1321 translator=self._client)) |
| 1317 cell.append('%s: %s' % (self._(k), val)) | 1322 cell.append('%s: %s' % (self._(k), val)) |
| 1318 if k in current and current[k] is not None: | 1323 if k in current and current[k] is not None: |
| 1319 cell[-1] += ' -> %s' % current[k] | 1324 cell[-1] += ' -> %s' % current[k] |
| 1320 current[k] = val | 1325 current[k] = val |
| 1321 | 1326 |
| 1380 | 1385 |
| 1381 if direction == 'ascending': | 1386 if direction == 'ascending': |
| 1382 l.reverse() | 1387 l.reverse() |
| 1383 | 1388 |
| 1384 l[0:0] = ['<table class="history table table-condensed table-striped">' | 1389 l[0:0] = ['<table class="history table table-condensed table-striped">' |
| 1385 '<tr><th colspan="4" class="header">', | 1390 '<tr><th colspan="4" class="header">', |
| 1386 self._('History'), | 1391 self._('History'), |
| 1387 '</th></tr><tr>', | 1392 '</th></tr><tr>', |
| 1388 self._('<th>Date</th>'), | 1393 self._('<th>Date</th>'), |
| 1389 self._('<th>User</th>'), | 1394 self._('<th>User</th>'), |
| 1390 self._('<th>Action</th>'), | 1395 self._('<th>Action</th>'), |
| 1391 self._('<th>Args</th>'), | 1396 self._('<th>Args</th>'), |
| 1392 '</tr>'] | 1397 '</tr>'] |
| 1393 l.append('</table>') | 1398 l.append('</table>') |
| 1394 | 1399 |
| 1395 self._client.form_wins = orig_form_wins | 1400 self._client.form_wins = orig_form_wins |
| 1396 | 1401 |
| 1397 return '\n'.join(l) | 1402 return '\n'.join(l) |
| 1402 # create a new request and override the specified args | 1407 # create a new request and override the specified args |
| 1403 req = HTMLRequest(self._client) | 1408 req = HTMLRequest(self._client) |
| 1404 req.classname = self._klass.get(self._nodeid, 'klass') | 1409 req.classname = self._klass.get(self._nodeid, 'klass') |
| 1405 name = self._klass.get(self._nodeid, 'name') | 1410 name = self._klass.get(self._nodeid, 'name') |
| 1406 req.updateFromURL(self._klass.get(self._nodeid, 'url') + | 1411 req.updateFromURL(self._klass.get(self._nodeid, 'url') + |
| 1407 '&@queryname=%s' % urllib_.quote(name)) | 1412 '&@queryname=%s' % urllib_.quote(name)) |
| 1408 | 1413 |
| 1409 # new template, using the specified classname and request | 1414 # new template, using the specified classname and request |
| 1410 # [ ] the custom logic for search page doesn't belong to | 1415 # [ ] the custom logic for search page doesn't belong to |
| 1411 # generic templating module (techtonik) | 1416 # generic templating module (techtonik) |
| 1412 tplname = self._client.selectTemplate(req.classname, 'search') | 1417 tplname = self._client.selectTemplate(req.classname, 'search') |
| 1459 """Add ability to check for permissions on users. | 1464 """Add ability to check for permissions on users. |
| 1460 """ | 1465 """ |
| 1461 _marker = [] | 1466 _marker = [] |
| 1462 | 1467 |
| 1463 def hasPermission(self, permission, classname=_marker, | 1468 def hasPermission(self, permission, classname=_marker, |
| 1464 property=None, itemid=None): | 1469 property=None, itemid=None): |
| 1465 """Determine if the user has the Permission. | 1470 """Determine if the user has the Permission. |
| 1466 | 1471 |
| 1467 The class being tested defaults to the template's class, but may | 1472 The class being tested defaults to the template's class, but may |
| 1468 be overidden for this test by suppling an alternate classname. | 1473 be overidden for this test by suppling an alternate classname. |
| 1469 """ | 1474 """ |
| 1470 if classname is self._marker: | 1475 if classname is self._marker: |
| 1471 classname = self._client.classname | 1476 classname = self._client.classname |
| 1472 return self._db.security.hasPermission(permission, | 1477 return self._db.security.hasPermission( |
| 1473 self._nodeid, classname, property, itemid) | 1478 permission, self._nodeid, classname, property, itemid) |
| 1474 | 1479 |
| 1475 def hasRole(self, *rolenames): | 1480 def hasRole(self, *rolenames): |
| 1476 """Determine whether the user has any role in rolenames.""" | 1481 """Determine whether the user has any role in rolenames.""" |
| 1477 return self._db.user.has_role(self._nodeid, *rolenames) | 1482 return self._db.user.has_role(self._nodeid, *rolenames) |
| 1478 | 1483 |
| 1493 _value the value of the property if any | 1498 _value the value of the property if any |
| 1494 | 1499 |
| 1495 A wrapper object which may be stringified for the plain() behaviour. | 1500 A wrapper object which may be stringified for the plain() behaviour. |
| 1496 """ | 1501 """ |
| 1497 def __init__(self, client, classname, nodeid, prop, name, value, | 1502 def __init__(self, client, classname, nodeid, prop, name, value, |
| 1498 anonymous=0): | 1503 anonymous=0): |
| 1499 self._client = client | 1504 self._client = client |
| 1500 self._db = client.db | 1505 self._db = client.db |
| 1501 self._ = client._ | 1506 self._ = client._ |
| 1502 self._classname = classname | 1507 self._classname = classname |
| 1503 self._nodeid = nodeid | 1508 self._nodeid = nodeid |
| 1600 userid = self._client.userid | 1605 userid = self._client.userid |
| 1601 if self._nodeid: | 1606 if self._nodeid: |
| 1602 if not perm('Web Access', userid): | 1607 if not perm('Web Access', userid): |
| 1603 return False | 1608 return False |
| 1604 return perm('Edit', userid, self._classname, self._name, | 1609 return perm('Edit', userid, self._classname, self._name, |
| 1605 self._nodeid) | 1610 self._nodeid) |
| 1606 return perm('Create', userid, self._classname, self._name) or \ | 1611 return perm('Create', userid, self._classname, self._name) or \ |
| 1607 perm('Register', userid, self._classname, self._name) | 1612 perm('Register', userid, self._classname, self._name) |
| 1608 | 1613 |
| 1609 def is_view_ok(self): | 1614 def is_view_ok(self): |
| 1610 """ Is the user allowed to View the current class? | 1615 """ Is the user allowed to View the current class? |
| 1611 """ | 1616 """ |
| 1612 perm = self._db.security.hasPermission | 1617 perm = self._db.security.hasPermission |
| 1613 if perm('Web Access', self._client.userid) and perm('View', | 1618 if perm('Web Access', self._client.userid) and perm( |
| 1614 self._client.userid, self._classname, self._name, self._nodeid): | 1619 'View', self._client.userid, self._classname, |
| 1620 self._name, self._nodeid): | |
| 1615 return 1 | 1621 return 1 |
| 1616 return self.is_edit_ok() | 1622 return self.is_edit_ok() |
| 1617 | 1623 |
| 1618 | 1624 |
| 1619 class StringHTMLProperty(HTMLProperty): | 1625 class StringHTMLProperty(HTMLProperty): |
| 1649 if match.group('url'): | 1655 if match.group('url'): |
| 1650 return self._hyper_repl_url(match, '<a href="%s" rel="nofollow noopener">%s</a>%s') | 1656 return self._hyper_repl_url(match, '<a href="%s" rel="nofollow noopener">%s</a>%s') |
| 1651 elif match.group('email'): | 1657 elif match.group('email'): |
| 1652 return self._hyper_repl_email(match, '<a href="mailto:%s">%s</a>') | 1658 return self._hyper_repl_email(match, '<a href="mailto:%s">%s</a>') |
| 1653 elif len(match.group('id')) < 10: | 1659 elif len(match.group('id')) < 10: |
| 1654 return self._hyper_repl_item(match, | 1660 return self._hyper_repl_item( |
| 1655 '<a href="%(cls)s%(id)s%(fragment)s">%(item)s</a>') | 1661 match, '<a href="%(cls)s%(id)s%(fragment)s">%(item)s</a>') |
| 1656 else: | 1662 else: |
| 1657 # just return the matched text | 1663 # just return the matched text |
| 1658 return match.group(0) | 1664 return match.group(0) |
| 1659 | 1665 |
| 1660 def _hyper_repl_url(self, match, replacement): | 1666 def _hyper_repl_url(self, match, replacement): |
| 1856 if sch in self.valid_schemes: | 1862 if sch in self.valid_schemes: |
| 1857 pass | 1863 pass |
| 1858 else: | 1864 else: |
| 1859 raise | 1865 raise |
| 1860 | 1866 |
| 1861 return u2s(ReStructuredText(s, writer_name="html", | 1867 return u2s(ReStructuredText( |
| 1862 settings_overrides=self.rst_defaults)["html_body"]) | 1868 s, writer_name="html", |
| 1869 settings_overrides=self.rst_defaults)["html_body"]) | |
| 1863 | 1870 |
| 1864 def markdown(self, hyperlink=1): | 1871 def markdown(self, hyperlink=1): |
| 1865 """ Render the value of the property as markdown. | 1872 """ Render the value of the property as markdown. |
| 1866 | 1873 |
| 1867 This requires markdown2 or markdown to be installed separately. | 1874 This requires markdown2 or markdown to be installed separately. |
| 1912 value = '"'.join(value.split('"')) | 1919 value = '"'.join(value.split('"')) |
| 1913 name = self._formname | 1920 name = self._formname |
| 1914 passthrough_args = self.cgi_escape_attrs(**kwargs) | 1921 passthrough_args = self.cgi_escape_attrs(**kwargs) |
| 1915 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' | 1922 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' |
| 1916 ' rows="%(rows)s" cols="%(cols)s">' | 1923 ' rows="%(rows)s" cols="%(cols)s">' |
| 1917 '%(value)s</textarea>') % locals() | 1924 '%(value)s</textarea>') % locals() |
| 1918 | 1925 |
| 1919 def email(self, escape=1): | 1926 def email(self, escape=1): |
| 1920 """ Render the value of the property as an obscured email address | 1927 """ Render the value of the property as an obscured email address |
| 1921 """ | 1928 """ |
| 1922 if not self.is_view_ok(): | 1929 if not self.is_view_ok(): |
| 2100 return self.plain(escape=1) | 2107 return self.plain(escape=1) |
| 2101 | 2108 |
| 2102 value = self._value | 2109 value = self._value |
| 2103 if is_us(value): | 2110 if is_us(value): |
| 2104 value = value.strip().lower() in ('checked', 'yes', 'true', | 2111 value = value.strip().lower() in ('checked', 'yes', 'true', |
| 2105 'on', '1') | 2112 'on', '1') |
| 2106 | 2113 |
| 2107 if (not y_label): | 2114 if (not y_label): |
| 2108 y_label = '<label class="rblabel" for="%s_%s">' % ( | 2115 y_label = '<label class="rblabel" for="%s_%s">' % ( |
| 2109 self._formname, 'yes') | 2116 self._formname, 'yes') |
| 2110 y_label += self._('Yes') | 2117 y_label += self._('Yes') |
| 2117 n_label += '</label>' | 2124 n_label += '</label>' |
| 2118 | 2125 |
| 2119 checked = value and "checked" or "" | 2126 checked = value and "checked" or "" |
| 2120 if value: | 2127 if value: |
| 2121 y_rb = self.input(type="radio", name=self._formname, value="yes", | 2128 y_rb = self.input(type="radio", name=self._formname, value="yes", |
| 2122 checked="checked", id="%s_%s" % ( | 2129 checked="checked", id="%s_%s" % ( |
| 2123 self._formname, 'yes'), **kwargs) | 2130 self._formname, 'yes'), **kwargs) |
| 2124 | 2131 |
| 2125 n_rb = self.input(type="radio", name=self._formname, value="no", | 2132 n_rb = self.input(type="radio", name=self._formname, value="no", |
| 2126 id="%s_%s" % ( | 2133 id="%s_%s" % ( |
| 2127 self._formname, 'no'), **kwargs) | 2134 self._formname, 'no'), **kwargs) |
| 2128 else: | 2135 else: |
| 2129 y_rb = self.input(type="radio", name=self._formname, value="yes", | 2136 y_rb = self.input(type="radio", name=self._formname, value="yes", |
| 2130 id="%s_%s" % (self._formname, 'yes'), **kwargs) | 2137 id="%s_%s" % (self._formname, 'yes'), **kwargs) |
| 2131 | 2138 |
| 2132 n_rb = self.input(type="radio", name=self._formname, value="no", | 2139 n_rb = self.input(type="radio", name=self._formname, value="no", |
| 2133 checked="checked", id="%s_%s" % ( | 2140 checked="checked", id="%s_%s" % ( |
| 2134 self._formname, 'no'), **kwargs) | 2141 self._formname, 'no'), **kwargs) |
| 2135 | 2142 |
| 2136 if (u_label): | 2143 if (u_label): |
| 2137 if (u_label is True): # it was set via u_label=True | 2144 if (u_label is True): # it was set via u_label=True |
| 2138 u_label = '' # make it empty but a string not boolean | 2145 u_label = '' # make it empty but a string not boolean |
| 2139 u_rb = self.input(type="radio", name=self._formname, value="", | 2146 u_rb = self.input(type="radio", name=self._formname, value="", |
| 2140 id="%s_%s" % (self._formname, 'unk'), **kwargs) | 2147 id="%s_%s" % (self._formname, 'unk'), **kwargs) |
| 2141 else: | 2148 else: |
| 2142 # don't generate a trivalue radiobutton. | 2149 # don't generate a trivalue radiobutton. |
| 2143 u_label = '' | 2150 u_label = '' |
| 2144 u_rb = '' | 2151 u_rb = '' |
| 2145 | 2152 |
| 2154 class DateHTMLProperty(HTMLProperty): | 2161 class DateHTMLProperty(HTMLProperty): |
| 2155 | 2162 |
| 2156 _marker = [] | 2163 _marker = [] |
| 2157 | 2164 |
| 2158 def __init__(self, client, classname, nodeid, prop, name, value, | 2165 def __init__(self, client, classname, nodeid, prop, name, value, |
| 2159 anonymous=0, offset=None): | 2166 anonymous=0, offset=None): |
| 2160 HTMLProperty.__init__(self, client, classname, nodeid, prop, name, | 2167 HTMLProperty.__init__(self, client, classname, nodeid, prop, name, |
| 2161 value, anonymous=anonymous) | 2168 value, anonymous=anonymous) |
| 2162 if self._value and not is_us(self._value): | 2169 if self._value and not is_us(self._value): |
| 2163 self._value.setTranslator(self._client.translator) | 2170 self._value.setTranslator(self._client.translator) |
| 2164 self._offset = offset | 2171 self._offset = offset |
| 2165 if self._offset is None: | 2172 if self._offset is None: |
| 2166 self._offset = self._prop.offset(self._db) | 2173 self._offset = self._prop.offset(self._db) |
| 2204 ret = ret + interval | 2211 ret = ret + interval |
| 2205 else: | 2212 else: |
| 2206 ret = ret - interval | 2213 ret = ret - interval |
| 2207 | 2214 |
| 2208 return DateHTMLProperty(self._client, self._classname, self._nodeid, | 2215 return DateHTMLProperty(self._client, self._classname, self._nodeid, |
| 2209 self._prop, self._formname, ret) | 2216 self._prop, self._formname, ret) |
| 2210 | 2217 |
| 2211 def field(self, size=30, default=None, format=_marker, popcal=True, | 2218 def field(self, size=30, default=None, format=_marker, popcal=True, |
| 2212 **kwargs): | 2219 **kwargs): |
| 2213 """Render a form edit field for the property | 2220 """Render a form edit field for the property |
| 2214 | 2221 |
| 2236 elif isinstance(default, date.Date): | 2243 elif isinstance(default, date.Date): |
| 2237 raw_value = default | 2244 raw_value = default |
| 2238 elif isinstance(default, DateHTMLProperty): | 2245 elif isinstance(default, DateHTMLProperty): |
| 2239 raw_value = default._value | 2246 raw_value = default._value |
| 2240 else: | 2247 else: |
| 2241 raise ValueError(self._('default value for ' | 2248 raise ValueError(self._( |
| 2249 'default value for ' | |
| 2242 'DateHTMLProperty must be either DateHTMLProperty ' | 2250 'DateHTMLProperty must be either DateHTMLProperty ' |
| 2243 'or string date representation.')) | 2251 'or string date representation.')) |
| 2244 elif is_us(value): | 2252 elif is_us(value): |
| 2245 # most likely erroneous input to be passed back to user | 2253 # most likely erroneous input to be passed back to user |
| 2246 value = us2s(value) | 2254 value = us2s(value) |
| 2247 s = self.input(name=self._formname, value=value, size=size, | 2255 s = self.input(name=self._formname, value=value, size=size, |
| 2248 **kwargs) | 2256 **kwargs) |
| 2249 if popcal: | 2257 if popcal: |
| 2250 s += self.popcal() | 2258 s += self.popcal() |
| 2251 return s | 2259 return s |
| 2252 else: | 2260 else: |
| 2253 raw_value = value | 2261 raw_value = value |
| 2323 """ | 2331 """ |
| 2324 if not self.is_view_ok(): | 2332 if not self.is_view_ok(): |
| 2325 return self._('[hidden]') | 2333 return self._('[hidden]') |
| 2326 | 2334 |
| 2327 return DateHTMLProperty(self._client, self._classname, self._nodeid, | 2335 return DateHTMLProperty(self._client, self._classname, self._nodeid, |
| 2328 self._prop, self._formname, self._value, offset=offset) | 2336 self._prop, self._formname, self._value, |
| 2337 offset=offset) | |
| 2329 | 2338 |
| 2330 def popcal(self, width=300, height=200, label="(cal)", | 2339 def popcal(self, width=300, height=200, label="(cal)", |
| 2331 form="itemSynopsis"): | 2340 form="itemSynopsis"): |
| 2332 """Generate a link to a calendar pop-up window. | 2341 """Generate a link to a calendar pop-up window. |
| 2333 | 2342 |
| 2334 item: HTMLProperty e.g.: context.deadline | 2343 item: HTMLProperty e.g.: context.deadline |
| 2335 """ | 2344 """ |
| 2336 if self.isset(): | 2345 if self.isset(): |
| 2344 "data-width": width, | 2353 "data-width": width, |
| 2345 "data-height": height | 2354 "data-height": height |
| 2346 } | 2355 } |
| 2347 | 2356 |
| 2348 return ('<a class="classhelp" %s href="javascript:help_window(' | 2357 return ('<a class="classhelp" %s href="javascript:help_window(' |
| 2349 "'%s?@template=calendar&property=%s&form=%s%s', %d, %d)" | 2358 "'%s?@template=calendar&property=%s&form=%s%s', %d, %d)" |
| 2350 '">%s</a>' % (self.cgi_escape_attrs(**data_attr), | 2359 '">%s</a>' % (self.cgi_escape_attrs(**data_attr), |
| 2351 self._classname, self._name, form, date, width, | 2360 self._classname, self._name, form, date, width, |
| 2352 height, label)) | 2361 height, label)) |
| 2353 | 2362 |
| 2354 | 2363 |
| 2355 class IntervalHTMLProperty(HTMLProperty): | 2364 class IntervalHTMLProperty(HTMLProperty): |
| 2356 def __init__(self, client, classname, nodeid, prop, name, value, | 2365 def __init__(self, client, classname, nodeid, prop, name, value, |
| 2357 anonymous=0): | 2366 anonymous=0): |
| 2358 HTMLProperty.__init__(self, client, classname, nodeid, prop, | 2367 HTMLProperty.__init__(self, client, classname, nodeid, prop, |
| 2359 name, value, anonymous) | 2368 name, value, anonymous) |
| 2360 if self._value and not is_us(self._value): | 2369 if self._value and not is_us(self._value): |
| 2361 self._value.setTranslator(self._client.translator) | 2370 self._value.setTranslator(self._client.translator) |
| 2362 | 2371 |
| 2363 def plain(self, escape=0): | 2372 def plain(self, escape=0): |
| 2364 """ Render a "plain" representation of the property | 2373 """ Render a "plain" representation of the property |
| 2526 value = self._value | 2535 value = self._value |
| 2527 elif value == '-1': | 2536 elif value == '-1': |
| 2528 value = None | 2537 value = None |
| 2529 | 2538 |
| 2530 linkcl = self._db.getclass(self._prop.classname) | 2539 linkcl = self._db.getclass(self._prop.classname) |
| 2531 l = ['<select %s>' % self.cgi_escape_attrs(name=self._formname, | 2540 html = ['<select %s>' % self.cgi_escape_attrs(name=self._formname, |
| 2532 **html_kwargs)] | 2541 **html_kwargs)] |
| 2533 k = linkcl.labelprop(1) | 2542 k = linkcl.labelprop(1) |
| 2534 s = '' | 2543 s = '' |
| 2535 if value is None: | 2544 if value is None: |
| 2536 s = 'selected="selected" ' | 2545 s = 'selected="selected" ' |
| 2537 l.append(self._('<option %svalue="-1">- no selection -</option>') % s) | 2546 html.append(self._( |
| 2547 '<option %svalue="-1">- no selection -</option>') % s) | |
| 2538 | 2548 |
| 2539 if sort_on is not None: | 2549 if sort_on is not None: |
| 2540 if not isinstance(sort_on, tuple): | 2550 if not isinstance(sort_on, tuple): |
| 2541 if sort_on[0] in '+-': | 2551 if sort_on[0] in '+-': |
| 2542 sort_on = (sort_on[0], sort_on[1:]) | 2552 sort_on = (sort_on[0], sort_on[1:]) |
| 2544 sort_on = ('+', sort_on) | 2554 sort_on = ('+', sort_on) |
| 2545 else: | 2555 else: |
| 2546 sort_on = ('+', linkcl.orderprop()) | 2556 sort_on = ('+', linkcl.orderprop()) |
| 2547 | 2557 |
| 2548 options = [opt | 2558 options = [opt |
| 2549 for opt in linkcl.filter(None, conditions, sort_on, (None, None)) | 2559 for opt in linkcl.filter( |
| 2550 if self._db.security.hasPermission("View", self._client.userid, | 2560 None, conditions, sort_on, (None, None)) |
| 2551 linkcl.classname, itemid=opt)] | 2561 if self._db.security.hasPermission( |
| 2562 "View", self._client.userid, linkcl.classname, | |
| 2563 itemid=opt)] | |
| 2552 | 2564 |
| 2553 # make sure we list the current value if it's retired | 2565 # make sure we list the current value if it's retired |
| 2554 if value and value not in options: | 2566 if value and value not in options: |
| 2555 options.insert(0, value) | 2567 options.insert(0, value) |
| 2556 | 2568 |
| 2612 # and generate | 2624 # and generate |
| 2613 tr = str | 2625 tr = str |
| 2614 if translate: | 2626 if translate: |
| 2615 tr = self._ | 2627 tr = self._ |
| 2616 lab = html_escape(tr(lab)) | 2628 lab = html_escape(tr(lab)) |
| 2617 l.append('<option %svalue="%s">%s</option>' % (s, optionid, lab)) | 2629 html.append( |
| 2618 l.append('</select>') | 2630 '<option %svalue="%s">%s</option>' % (s, optionid, lab)) |
| 2619 return '\n'.join(l) | 2631 html.append('</select>') |
| 2632 return '\n'.join(html) | |
| 2620 | 2633 |
| 2621 # def checklist(self, ...) | 2634 # def checklist(self, ...) |
| 2622 | 2635 |
| 2623 | 2636 |
| 2624 class MultilinkHTMLProperty(HTMLProperty): | 2637 class MultilinkHTMLProperty(HTMLProperty): |
| 2629 """ | 2642 """ |
| 2630 def __init__(self, *args, **kwargs): | 2643 def __init__(self, *args, **kwargs): |
| 2631 HTMLProperty.__init__(self, *args, **kwargs) | 2644 HTMLProperty.__init__(self, *args, **kwargs) |
| 2632 if self._value: | 2645 if self._value: |
| 2633 display_value = lookupIds(self._db, self._prop, self._value, | 2646 display_value = lookupIds(self._db, self._prop, self._value, |
| 2634 fail_ok=1, do_lookup=False) | 2647 fail_ok=1, do_lookup=False) |
| 2635 keyfun = make_key_function(self._db, self._prop.classname) | 2648 keyfun = make_key_function(self._db, self._prop.classname) |
| 2636 # sorting fails if the value contains | 2649 # sorting fails if the value contains |
| 2637 # items not yet stored in the database | 2650 # items not yet stored in the database |
| 2638 # ignore these errors to preserve user input | 2651 # ignore these errors to preserve user input |
| 2639 try: | 2652 try: |
| 2668 return self.viewableGenerator(self._value) | 2681 return self.viewableGenerator(self._value) |
| 2669 | 2682 |
| 2670 def reverse(self): | 2683 def reverse(self): |
| 2671 """ return the list in reverse order | 2684 """ return the list in reverse order |
| 2672 """ | 2685 """ |
| 2673 l = self._value[:] | 2686 mylist = self._value[:] |
| 2674 l.reverse() | 2687 mylist.reverse() |
| 2675 return self.viewableGenerator(l) | 2688 return self.viewableGenerator(mylist) |
| 2676 | 2689 |
| 2677 def sorted(self, property, reverse=False, NoneFirst=False): | 2690 def sorted(self, property, reverse=False, NoneFirst=False): |
| 2678 """ Return this multilink sorted by the given property | 2691 """ Return this multilink sorted by the given property |
| 2679 | 2692 |
| 2680 Set Nonefirst to True to sort None/unset property | 2693 Set Nonefirst to True to sort None/unset property |
| 2749 label = linkcl.get(v, k, | 2762 label = linkcl.get(v, k, |
| 2750 default=self._("[label is missing]")) | 2763 default=self._("[label is missing]")) |
| 2751 except IndexError: | 2764 except IndexError: |
| 2752 label = None | 2765 label = None |
| 2753 # fall back to designator if label is None | 2766 # fall back to designator if label is None |
| 2754 if label is None: label = '%s%s' % (self._prop.classname, k) | 2767 if label is None: |
| 2768 label = '%s%s' % (self._prop.classname, k) | |
| 2755 else: | 2769 else: |
| 2756 label = v | 2770 label = v |
| 2757 labels.append(label) | 2771 labels.append(label) |
| 2758 value = ', '.join(labels) | 2772 value = ', '.join(labels) |
| 2759 if escape: | 2773 if escape: |
| 2825 sort_on = ('+', sort_on) | 2839 sort_on = ('+', sort_on) |
| 2826 else: | 2840 else: |
| 2827 sort_on = ('+', linkcl.orderprop()) | 2841 sort_on = ('+', linkcl.orderprop()) |
| 2828 | 2842 |
| 2829 options = [opt | 2843 options = [opt |
| 2830 for opt in linkcl.filter(None, conditions, sort_on) | 2844 for opt in linkcl.filter(None, conditions, sort_on) |
| 2831 if self._db.security.hasPermission("View", self._client.userid, | 2845 if self._db.security.hasPermission( |
| 2832 linkcl.classname, itemid=opt)] | 2846 "View", self._client.userid, linkcl.classname, |
| 2847 itemid=opt)] | |
| 2833 | 2848 |
| 2834 # make sure we list the current values if they're retired | 2849 # make sure we list the current values if they're retired |
| 2835 for val in value: | 2850 for val in value: |
| 2836 if val not in options: | 2851 if val not in options: |
| 2837 options.insert(0, val) | 2852 options.insert(0, val) |
| 2840 height = len(options) | 2855 height = len(options) |
| 2841 if value: | 2856 if value: |
| 2842 # The "no selection" option. | 2857 # The "no selection" option. |
| 2843 height += 1 | 2858 height += 1 |
| 2844 height = min(height, 7) | 2859 height = min(height, 7) |
| 2845 l = ['<select multiple %s>' % self.cgi_escape_attrs( | 2860 html = ['<select multiple %s>' % self.cgi_escape_attrs( |
| 2846 name=self._formname, size=height, **html_kwargs)] | 2861 name=self._formname, size=height, **html_kwargs)] |
| 2847 k = linkcl.labelprop(1) | 2862 k = linkcl.labelprop(1) |
| 2848 | 2863 |
| 2849 if value: # FIXME '- no selection -' mark for translation | 2864 if value: # FIXME '- no selection -' mark for translation |
| 2850 l.append('<option value="%s">- no selection -</option>' | 2865 html.append('<option value="%s">- no selection -</option>' |
| 2851 % ','.join(['-' + v for v in value])) | 2866 % ','.join(['-' + v for v in value])) |
| 2852 | 2867 |
| 2853 if additional: | 2868 if additional: |
| 2854 additional_fns = [] | 2869 additional_fns = [] |
| 2855 props = linkcl.getprops() | 2870 props = linkcl.getprops() |
| 2856 for propname in additional: | 2871 for propname in additional: |
| 2892 # and generate | 2907 # and generate |
| 2893 tr = str | 2908 tr = str |
| 2894 if translate: | 2909 if translate: |
| 2895 tr = self._ | 2910 tr = self._ |
| 2896 lab = html_escape(tr(lab)) | 2911 lab = html_escape(tr(lab)) |
| 2897 l.append('<option %svalue="%s">%s</option>' % (s, optionid, | 2912 html.append('<option %svalue="%s">%s</option>' % (s, optionid, |
| 2898 lab)) | 2913 lab)) |
| 2899 l.append('</select>') | 2914 html.append('</select>') |
| 2900 return '\n'.join(l) | 2915 return '\n'.join(html) |
| 2901 | 2916 |
| 2902 | 2917 |
| 2903 # set the propclasses for HTMLItem | 2918 # set the propclasses for HTMLItem |
| 2904 propclasses = [ | 2919 propclasses = [ |
| 2905 (hyperdb.String, StringHTMLProperty), | 2920 (hyperdb.String, StringHTMLProperty), |
| 3109 prop = cls.get_transitive_prop(name) | 3124 prop = cls.get_transitive_prop(name) |
| 3110 fv = self.form[name] | 3125 fv = self.form[name] |
| 3111 if (isinstance(prop, hyperdb.Link) or | 3126 if (isinstance(prop, hyperdb.Link) or |
| 3112 isinstance(prop, hyperdb.Multilink)): | 3127 isinstance(prop, hyperdb.Multilink)): |
| 3113 self.filterspec[name] = lookupIds(db, prop, | 3128 self.filterspec[name] = lookupIds(db, prop, |
| 3114 handleListCGIValue(fv)) | 3129 handleListCGIValue(fv)) |
| 3115 else: | 3130 else: |
| 3116 if isinstance(fv, type([])): | 3131 if isinstance(fv, type([])): |
| 3117 self.filterspec[name] = [v.value for v in fv] | 3132 self.filterspec[name] = [v.value for v in fv] |
| 3118 elif name == 'id': | 3133 elif name == 'id': |
| 3119 # special case "id" property | 3134 # special case "id" property |
| 3120 self.filterspec[name] = handleListCGIValue(fv) | 3135 self.filterspec[name] = handleListCGIValue(fv) |
| 3121 else: | 3136 else: |
| 3122 self.filterspec[name] = fv.value | 3137 self.filterspec[name] = fv.value |
| 3123 self.filterspec = security.filterFilterspec(userid, self.classname, | 3138 self.filterspec = security.filterFilterspec(userid, self.classname, |
| 3124 self.filterspec) | 3139 self.filterspec) |
| 3125 | 3140 |
| 3126 # full-text search argument | 3141 # full-text search argument |
| 3127 self.search_text = None | 3142 self.search_text = None |
| 3128 for name in ':search_text @search_text'.split(): | 3143 for name in ':search_text @search_text'.split(): |
| 3129 if self._form_has_key(name): | 3144 if self._form_has_key(name): |
| 3217 startwith: %(startwith)r | 3232 startwith: %(startwith)r |
| 3218 env: %(env)s | 3233 env: %(env)s |
| 3219 """ % d | 3234 """ % d |
| 3220 | 3235 |
| 3221 def indexargs_form(self, columns=1, sort=1, group=1, filter=1, | 3236 def indexargs_form(self, columns=1, sort=1, group=1, filter=1, |
| 3222 filterspec=1, search_text=1, exclude=[]): | 3237 filterspec=1, search_text=1, exclude=[]): |
| 3223 """ return the current index args as form elements | 3238 """ return the current index args as form elements |
| 3224 | 3239 |
| 3225 This routine generates an html form with hidden elements. | 3240 This routine generates an html form with hidden elements. |
| 3226 If you want to have visible form elements in your tal/jinja | 3241 If you want to have visible form elements in your tal/jinja |
| 3227 generated templates use the exclude aray to list the names for | 3242 generated templates use the exclude aray to list the names for |
| 3228 these elements. This wll prevent the function from creating | 3243 these elements. This wll prevent the function from creating |
| 3229 these elements in its output. | 3244 these elements in its output. |
| 3230 """ | 3245 """ |
| 3231 l = [] | 3246 html = [] |
| 3232 sc = self.special_char | 3247 sc = self.special_char |
| 3233 | 3248 |
| 3234 def add(k, v): | 3249 def add(k, v): |
| 3235 l.append(self.input(type="hidden", name=k, value=v)) | 3250 html.append(self.input(type="hidden", name=k, value=v)) |
| 3236 if columns and self.columns: | 3251 if columns and self.columns: |
| 3237 add(sc+'columns', ','.join(self.columns)) | 3252 add(sc+'columns', ','.join(self.columns)) |
| 3238 if sort: | 3253 if sort: |
| 3239 val = [] | 3254 val = [] |
| 3240 for dir, attr in self.sort: | 3255 for dir, attr in self.sort: |
| 3260 continue | 3275 continue |
| 3261 if isinstance(v, list): | 3276 if isinstance(v, list): |
| 3262 # id's are stored as strings but should be treated | 3277 # id's are stored as strings but should be treated |
| 3263 # as integers in lists. | 3278 # as integers in lists. |
| 3264 if (isinstance(cls.get_transitive_prop(k), hyperdb.String) | 3279 if (isinstance(cls.get_transitive_prop(k), hyperdb.String) |
| 3265 and k != 'id'): | 3280 and k != 'id'): |
| 3266 add(k, ' '.join(v)) | 3281 add(k, ' '.join(v)) |
| 3267 else: | 3282 else: |
| 3268 add(k, ','.join(v)) | 3283 add(k, ','.join(v)) |
| 3269 else: | 3284 else: |
| 3270 add(k, v) | 3285 add(k, v) |
| 3271 if search_text and self.search_text: | 3286 if search_text and self.search_text: |
| 3272 add(sc+'search_text', self.search_text) | 3287 add(sc+'search_text', self.search_text) |
| 3273 add(sc+'pagesize', self.pagesize) | 3288 add(sc+'pagesize', self.pagesize) |
| 3274 add(sc+'startwith', self.startwith) | 3289 add(sc+'startwith', self.startwith) |
| 3275 return '\n'.join(l) | 3290 return '\n'.join(html) |
| 3276 | 3291 |
| 3277 def indexargs_url(self, url, args): | 3292 def indexargs_url(self, url, args): |
| 3278 """ Embed the current index args in a URL | 3293 """ Embed the current index args in a URL |
| 3279 | 3294 |
| 3280 If the value of an arg (in args dict) is None, | 3295 If the value of an arg (in args dict) is None, |
| 3368 """ | 3383 """ |
| 3369 check = self._client.db.security.hasPermission | 3384 check = self._client.db.security.hasPermission |
| 3370 userid = self._client.userid | 3385 userid = self._client.userid |
| 3371 if not check('Web Access', userid): | 3386 if not check('Web Access', userid): |
| 3372 return Batch(self.client, [], self.pagesize, self.startwith, | 3387 return Batch(self.client, [], self.pagesize, self.startwith, |
| 3373 classname=self.classname) | 3388 classname=self.classname) |
| 3374 | 3389 |
| 3375 filterspec = self.filterspec | 3390 filterspec = self.filterspec |
| 3376 sort = self.sort | 3391 sort = self.sort |
| 3377 group = self.group | 3392 group = self.group |
| 3378 | 3393 |
| 3396 )], klass) | 3411 )], klass) |
| 3397 else: | 3412 else: |
| 3398 matches = None | 3413 matches = None |
| 3399 | 3414 |
| 3400 # filter for visibility | 3415 # filter for visibility |
| 3401 l = [id for id in klass.filter(matches, filterspec, sort, group) | 3416 allowed = [id for id in klass.filter(matches, filterspec, sort, group) |
| 3402 if check(permission, userid, self.classname, itemid=id)] | 3417 if check(permission, userid, self.classname, itemid=id)] |
| 3403 | 3418 |
| 3404 # return the batch object, using IDs only | 3419 # return the batch object, using IDs only |
| 3405 return Batch(self.client, l, self.pagesize, self.startwith, | 3420 return Batch(self.client, allowed, self.pagesize, self.startwith, |
| 3406 classname=self.classname) | 3421 classname=self.classname) |
| 3407 | 3422 |
| 3408 | 3423 |
| 3409 # extend the standard ZTUtils Batch object to remove dependency on | 3424 # extend the standard ZTUtils Batch object to remove dependency on |
| 3410 # Acquisition and add a couple of useful methods | 3425 # Acquisition and add a couple of useful methods |
| 3411 class Batch(ZTUtils.Batch): | 3426 class Batch(ZTUtils.Batch): |
| 3431 the batch. | 3446 the batch. |
| 3432 | 3447 |
| 3433 "sequence_length" is the length of the original, unbatched, sequence. | 3448 "sequence_length" is the length of the original, unbatched, sequence. |
| 3434 """ | 3449 """ |
| 3435 def __init__(self, client, sequence, size, start, end=0, orphan=0, | 3450 def __init__(self, client, sequence, size, start, end=0, orphan=0, |
| 3436 overlap=0, classname=None): | 3451 overlap=0, classname=None): |
| 3437 self.client = client | 3452 self.client = client |
| 3438 self.last_index = self.last_item = None | 3453 self.last_index = self.last_item = None |
| 3439 self.current_item = None | 3454 self.current_item = None |
| 3440 self.classname = classname | 3455 self.classname = classname |
| 3441 self.sequence_length = len(sequence) | 3456 self.sequence_length = len(sequence) |
| 3442 ZTUtils.Batch.__init__(self, sequence, size, start, end, orphan, | 3457 ZTUtils.Batch.__init__(self, sequence, size, start, end, orphan, |
| 3443 overlap) | 3458 overlap) |
| 3444 | 3459 |
| 3445 # overwrite so we can late-instantiate the HTMLItem instance | 3460 # overwrite so we can late-instantiate the HTMLItem instance |
| 3446 def __getitem__(self, index): | 3461 def __getitem__(self, index): |
| 3447 if index < 0: | 3462 if index < 0: |
| 3448 if index + self.end < self.first: raise IndexError(index) | 3463 if index + self.end < self.first: |
| 3464 raise IndexError(index) | |
| 3449 return self._sequence[index + self.end] | 3465 return self._sequence[index + self.end] |
| 3450 | 3466 |
| 3451 if index >= self.length: | 3467 if index >= self.length: |
| 3452 raise IndexError(index) | 3468 raise IndexError(index) |
| 3453 | 3469 |
| 3474 return 1 | 3490 return 1 |
| 3475 for property in properties: | 3491 for property in properties: |
| 3476 if property == 'id' or property.endswith('.id')\ | 3492 if property == 'id' or property.endswith('.id')\ |
| 3477 or isinstance(self.last_item[property], list): | 3493 or isinstance(self.last_item[property], list): |
| 3478 if (str(self.last_item[property]) != | 3494 if (str(self.last_item[property]) != |
| 3479 str(self.current_item[property])): | 3495 str(self.current_item[property])): |
| 3480 return 1 | 3496 return 1 |
| 3481 else: | 3497 else: |
| 3482 if (self.last_item[property]._value != | 3498 if (self.last_item[property]._value != |
| 3483 self.current_item[property]._value): | 3499 self.current_item[property]._value): |
| 3484 return 1 | 3500 return 1 |
| 3485 return 0 | 3501 return 0 |
| 3486 | 3502 |
| 3487 # override these 'cos we don't have access to acquisition | 3503 # override these 'cos we don't have access to acquisition |
| 3488 def previous(self): | 3504 def previous(self): |
| 3489 if self.start == 1: | 3505 if self.start == 1: |
| 3490 return None | 3506 return None |
| 3491 return Batch(self.client, self._sequence, self.size, | 3507 return Batch(self.client, self._sequence, self.size, |
| 3492 self.first - self._size + self.overlap, 0, self.orphan, | 3508 self.first - self._size + self.overlap, 0, self.orphan, |
| 3493 self.overlap) | 3509 self.overlap) |
| 3494 | 3510 |
| 3495 def next(self): | 3511 def next(self): |
| 3496 try: | 3512 try: |
| 3497 self._sequence[self.end] | 3513 self._sequence[self.end] |
| 3498 except IndexError: | 3514 except IndexError: |
| 3499 return None | 3515 return None |
| 3500 return Batch(self.client, self._sequence, self.size, | 3516 return Batch(self.client, self._sequence, self.size, |
| 3501 self.end - self.overlap, 0, self.orphan, self.overlap) | 3517 self.end - self.overlap, 0, self.orphan, self.overlap) |
| 3502 | 3518 |
| 3503 | 3519 |
| 3504 class TemplatingUtils: | 3520 class TemplatingUtils: |
| 3505 """ Utilities for templating | 3521 """ Utilities for templating |
| 3506 """ | 3522 """ |
| 3507 def __init__(self, client): | 3523 def __init__(self, client): |
| 3508 self.client = client | 3524 self.client = client |
| 3509 | 3525 |
| 3510 def Batch(self, sequence, size, start, end=0, orphan=0, overlap=0): | 3526 def Batch(self, sequence, size, start, end=0, orphan=0, overlap=0): |
| 3511 return Batch(self.client, sequence, size, start, end, orphan, | 3527 return Batch(self.client, sequence, size, start, end, orphan, |
| 3512 overlap) | 3528 overlap) |
| 3513 | 3529 |
| 3514 def anti_csrf_nonce(self, lifetime=None): | 3530 def anti_csrf_nonce(self, lifetime=None): |
| 3515 return anti_csrf_nonce(self.client, lifetime=lifetime) | 3531 return anti_csrf_nonce(self.client, lifetime=lifetime) |
| 3516 | 3532 |
| 3517 def timestamp(self): | 3533 def timestamp(self): |
| 3600 res.append('<table class="calendar"><tr><td>') | 3616 res.append('<table class="calendar"><tr><td>') |
| 3601 res.append(' <table width="100%" class="calendar_nav"><tr>') | 3617 res.append(' <table width="100%" class="calendar_nav"><tr>') |
| 3602 link = "&display=%s" % date_prev_month | 3618 link = "&display=%s" % date_prev_month |
| 3603 if date_prev_month: | 3619 if date_prev_month: |
| 3604 res.append(' <td><a href="%s&display=%s"><</a></td>' | 3620 res.append(' <td><a href="%s&display=%s"><</a></td>' |
| 3605 % (base_link, date_prev_month)) | 3621 % (base_link, date_prev_month)) |
| 3606 else: | 3622 else: |
| 3607 res.append(' <td></td>') | 3623 res.append(' <td></td>') |
| 3608 res.append(' <td>%s</td>' % calendar.month_name[display.month]) | 3624 res.append(' <td>%s</td>' % calendar.month_name[display.month]) |
| 3609 if date_next_month: | 3625 if date_next_month: |
| 3610 res.append(' <td><a href="%s&display=%s">></a></td>' | 3626 res.append(' <td><a href="%s&display=%s">></a></td>' |
| 3611 % (base_link, date_next_month)) | 3627 % (base_link, date_next_month)) |
| 3612 else: | 3628 else: |
| 3613 res.append(' <td></td>') | 3629 res.append(' <td></td>') |
| 3614 # spacer | 3630 # spacer |
| 3615 res.append(' <td width="100%"></td>') | 3631 res.append(' <td width="100%"></td>') |
| 3616 # year | 3632 # year |
| 3617 if date_prev_year: | 3633 if date_prev_year: |
| 3618 res.append(' <td><a href="%s&display=%s"><</a></td>' | 3634 res.append(' <td><a href="%s&display=%s"><</a></td>' |
| 3619 % (base_link, date_prev_year)) | 3635 % (base_link, date_prev_year)) |
| 3620 else: | 3636 else: |
| 3621 res.append(' <td></td>') | 3637 res.append(' <td></td>') |
| 3622 res.append(' <td>%s</td>' % display.year) | 3638 res.append(' <td>%s</td>' % display.year) |
| 3623 if date_next_year: | 3639 if date_next_year: |
| 3624 res.append(' <td><a href="%s&display=%s">></a></td>' | 3640 res.append(' <td><a href="%s&display=%s">></a></td>' |
| 3625 % (base_link, date_next_year)) | 3641 % (base_link, date_next_year)) |
| 3626 else: | 3642 else: |
| 3627 res.append(' <td></td>') | 3643 res.append(' <td></td>') |
| 3628 res.append(' </tr></table>') | 3644 res.append(' </tr></table>') |
| 3629 res.append(' </td></tr>') | 3645 res.append(' </td></tr>') |
| 3630 | 3646 |
