summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1a977aa)
raw | patch | inline | side by side (parent: 1a977aa)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 22 Jan 2002 00:12:07 +0000 (00:12 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 22 Jan 2002 00:12:07 +0000 (00:12 +0000) |
off the implementation of some of the functions so they behave sanely.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@575 57a73879-2fb5-44c3-a270-3262357dd7e2
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@575 57a73879-2fb5-44c3-a270-3262357dd7e2
CHANGES.txt | patch | blob | history | |
roundup/htmltemplate.py | patch | blob | history | |
test/__init__.py | patch | blob | history | |
test/test_htmltemplate.py | patch | blob | history |
diff --git a/CHANGES.txt b/CHANGES.txt
index 10091cff7b4249920199493dc843472ca68ff8a5..8e66a260f021d7587b732659125efd7425265000 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
. modified unit test to check nosy and assignedto when specified as
arguments
. you can now use the roundup-admin tool pack the database
+ . unit tests for html templating (and re-enabled the listbox field for
+ multilinks)
Fixed:
. handle attachments with no name (eg tnef)
index e029d42992e2b7ddba130f692315350d269b9a73..6c59c94b2f00eab55ceb447e5e5b9fc797259258 100644 (file)
--- a/roundup/htmltemplate.py
+++ b/roundup/htmltemplate.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: htmltemplate.py,v 1.64 2002-01-21 03:25:59 richard Exp $
+# $Id: htmltemplate.py,v 1.65 2002-01-22 00:12:06 richard Exp $
__doc__ = """
Template engine.
return s
return StructuredText(s,level=1,header=0)
- def do_field(self, property, size=None, height=None, showid=0):
- ''' display a property like the plain displayer, but in a text field
- to be edited
+ def determine_value(self, property):
+ '''determine the value of a property using the node, form or
+ filterspec
'''
- if not self.nodeid and self.form is None and self.filterspec is None:
- return _('[Field: not called from item]')
propclass = self.properties[property]
- if (isinstance(propclass, hyperdb.Link) or
- isinstance(propclass, hyperdb.Multilink)):
- linkcl = self.db.classes[propclass.classname]
- def sortfunc(a, b, cl=linkcl):
- if cl.getprops().has_key('order'):
- sort_on = 'order'
- else:
- sort_on = cl.labelprop()
- r = cmp(cl.get(a, sort_on), cl.get(b, sort_on))
- return r
if self.nodeid:
value = self.cl.get(self.nodeid, property, None)
- # TODO: remove this from the code ... it's only here for
- # handling schema changes, and they should be handled outside
- # of this code...
if isinstance(propclass, hyperdb.Multilink) and value is None:
- value = []
+ return []
+ return value
elif self.filterspec is not None:
if isinstance(propclass, hyperdb.Multilink):
- value = self.filterspec.get(property, [])
+ return self.filterspec.get(property, [])
else:
- value = self.filterspec.get(property, '')
+ return self.filterspec.get(property, '')
+ # TODO: pull the value from the form
+ if isinstance(propclass, hyperdb.Multilink):
+ return []
else:
- # TODO: pull the value from the form
- if isinstance(propclass, hyperdb.Multilink): value = []
- else: value = ''
+ return ''
+
+ def make_sort_function(self, classname):
+ '''Make a sort function for a given class
+ '''
+ linkcl = self.db.classes[classname]
+ if linkcl.getprops().has_key('order'):
+ sort_on = 'order'
+ else:
+ sort_on = linkcl.labelprop()
+ def sortfunc(a, b, linkcl=linkcl, sort_on=sort_on):
+ return cmp(linkcl.get(a, sort_on), linkcl.get(b, sort_on))
+ return sortfunc
+
+ def do_field(self, property, size=None, showid=0):
+ ''' display a property like the plain displayer, but in a text field
+ to be edited
+
+ Note: if you would prefer an option list style display for
+ link or multilink editing, use menu().
+ '''
+ if not self.nodeid and self.form is None and self.filterspec is None:
+ return _('[Field: not called from item]')
+
+ if size is None:
+ size = 30
+
+ propclass = self.properties[property]
+
+ # get the value
+ value = self.determine_value(property)
+
+ # now display
if (isinstance(propclass, hyperdb.String) or
isinstance(propclass, hyperdb.Date) or
isinstance(propclass, hyperdb.Interval)):
- size = size or 30
if value is None:
value = ''
else:
value = '"'.join(value.split('"'))
s = '<input name="%s" value="%s" size="%s">'%(property, value, size)
elif isinstance(propclass, hyperdb.Password):
- size = size or 30
s = '<input type="password" name="%s" size="%s">'%(property, size)
elif isinstance(propclass, hyperdb.Link):
+ sortfunc = self.make_sort_function(propclass.classname)
+ linkcl = self.db.classes[propclass.classname]
+ options = linkcl.list()
+ options.sort(sortfunc)
+ # TODO: make this a field display, not a menu one!
l = ['<select name="%s">'%property]
k = linkcl.labelprop()
if value is None:
else:
s = ''
l.append(_('<option %svalue="-1">- no selection -</option>')%s)
- options = linkcl.list()
- options.sort(sortfunc)
for optionid in options:
option = linkcl.get(optionid, k)
s = ''
lab = option
if size is not None and len(lab) > size:
lab = lab[:size-3] + '...'
+ lab = cgi.escape(lab)
l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab))
l.append('</select>')
s = '\n'.join(l)
elif isinstance(propclass, hyperdb.Multilink):
+ sortfunc = self.make_sort_function(propclass.classname)
+ linkcl = self.db.classes[propclass.classname]
list = linkcl.list()
list.sort(sortfunc)
l = []
# map the id to the label property
- # TODO: allow reversion to the older <select> box style display
if not showid:
k = linkcl.labelprop()
value = [linkcl.get(v, k) for v in value]
- if size is None:
- size = '10'
- l.insert(0,'<input name="%s" size="%s" value="%s">'%(property,
- size, ','.join(value)))
- s = "<br>\n".join(l)
+ value = cgi.escape(','.join(value))
+ s = '<input name="%s" size="%s" value="%s">'%(property, size, value)
else:
s = _('Plain: bad propclass "%(propclass)s"')%locals()
return s
def do_menu(self, property, size=None, height=None, showid=0):
''' for a Link property, display a menu of the available choices
'''
+ if not self.nodeid and self.form is None and self.filterspec is None:
+ return _('[Field: not called from item]')
+
propclass = self.properties[property]
- if self.nodeid:
- value = self.cl.get(self.nodeid, property)
- else:
- # TODO: pull the value from the form
- if isinstance(propclass, hyperdb.Multilink): value = []
- else: value = None
+
+ # make sure this is a link property
+ if not (isinstance(propclass, hyperdb.Link) or
+ isinstance(propclass, hyperdb.Multilink)):
+ return _('[Menu: not a link]')
+
+ # sort function
+ sortfunc = self.make_sort_function(propclass.classname)
+
+ # get the value
+ value = self.determine_value(property)
+
+ # display
if isinstance(propclass, hyperdb.Link):
linkcl = self.db.classes[propclass.classname]
l = ['<select name="%s">'%property]
if value is None:
s = 'selected '
l.append(_('<option %svalue="-1">- no selection -</option>')%s)
- for optionid in linkcl.list():
+ options = linkcl.list()
+ options.sort(sortfunc)
+ for optionid in options:
option = linkcl.get(optionid, k)
s = ''
if optionid == value:
s = 'selected '
- l.append('<option %svalue="%s">%s</option>'%(s, optionid, option))
+ if showid:
+ lab = '%s%s: %s'%(propclass.classname, optionid, option)
+ else:
+ lab = option
+ if size is not None and len(lab) > size:
+ lab = lab[:size-3] + '...'
+ lab = cgi.escape(lab)
+ l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab))
l.append('</select>')
return '\n'.join(l)
if isinstance(propclass, hyperdb.Multilink):
linkcl = self.db.classes[propclass.classname]
- list = linkcl.list()
- height = height or min(len(list), 7)
+ options = linkcl.list()
+ options.sort(sortfunc)
+ height = height or min(len(options), 7)
l = ['<select multiple name="%s" size="%s">'%(property, height)]
k = linkcl.labelprop()
- for optionid in list:
+ for optionid in options:
option = linkcl.get(optionid, k)
s = ''
if optionid in value:
lab = option
if size is not None and len(lab) > size:
lab = lab[:size-3] + '...'
- l.append('<option %svalue="%s">%s</option>'%(s, optionid, option))
+ lab = cgi.escape(lab)
+ l.append('<option %svalue="%s">%s</option>'%(s, optionid,
+ lab))
l.append('</select>')
return '\n'.join(l)
return _('[Menu: not a link]')
#
# $Log: not supported by cvs2svn $
+# Revision 1.64 2002/01/21 03:25:59 richard
+# oops
+#
# Revision 1.63 2002/01/21 02:59:10 richard
# Fixed up the HTML display of history so valid links are actually displayed.
# Oh for some unit tests! :(
diff --git a/test/__init__.py b/test/__init__.py
index 7501f9891b1b2964098fce7035e89cd753e99c80..f3cf566c91190fd51ccf9acb458f2d882089f3c0 100644 (file)
--- a/test/__init__.py
+++ b/test/__init__.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: __init__.py,v 1.13 2002-01-21 11:05:48 richard Exp $
+# $Id: __init__.py,v 1.14 2002-01-22 00:12:06 richard Exp $
import unittest
import os, tempfile
def go():
suite = unittest.TestSuite((
- test_dates.suite(),
- test_schema.suite(),
- test_db.suite(),
- test_init.suite(),
- test_multipart.suite(),
- test_mailsplit.suite(),
- test_mailgw.suite(),
- test_token.suite(),
+# test_dates.suite(),
+# test_schema.suite(),
+# test_db.suite(),
+# test_init.suite(),
+# test_multipart.suite(),
+# test_mailsplit.suite(),
+# test_mailgw.suite(),
+# test_token.suite(),
test_htmltemplate.suite(),
))
runner = unittest.TextTestRunner()
#
# $Log: not supported by cvs2svn $
+# Revision 1.13 2002/01/21 11:05:48 richard
+# New tests for htmltemplate (well, it's a beginning)
+#
# Revision 1.12 2002/01/14 06:53:28 richard
# had commented out some tests
#
index 3765acaab7977a6d3f209ae30e98e5b4490a71e5..3c7143b352c2c382220f6d6d6e50b311ccf3eee3 100644 (file)
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# $Id: test_htmltemplate.py,v 1.1 2002-01-21 11:05:48 richard Exp $
+# $Id: test_htmltemplate.py,v 1.2 2002-01-22 00:12:07 richard Exp $
import unittest, cgi
from roundup.htmltemplate import TemplateFunctions
from roundup import date
-from roundup.hyperdb import String, Date, Interval, Link, Multilink
+from roundup import password
+from roundup.hyperdb import String, Password, Date, Interval, Link, Multilink
class Class:
def get(self, nodeid, attribute, default=None):
return '1'
elif attribute == 'multilink':
return ['1', '2']
+ elif attribute == 'password':
+ return password.Password('sekrit')
elif attribute == 'key':
return 'the key'
elif attribute == 'html':
def getprops(self):
return {'string': String(), 'date': Date(), 'interval': Interval(),
'link': Link('other'), 'multilink': Multilink('other'),
- 'html': String(), 'key': String()}
+ 'password': Password(), 'html': String(), 'key': String()}
def labelprop(self):
return 'key'
s = 'Node 1: I am a string'
self.assertEqual(self.tf.do_plain('string'), s)
+ def testPlain_password(self):
+ self.assertEqual(self.tf.do_plain('password'), '*encrypted*')
+
def testPlain_html(self):
s = '<html>hello, I am HTML</html>'
self.assertEqual(self.tf.do_plain('html', escape=0), s)
self.assertEqual(self.tf.do_plain('multilink'), '1, 2')
-# def do_field(self, property, size=None, height=None, showid=0):
+# def do_field(self, property, size=None, showid=0):
def testField_string(self):
self.assertEqual(self.tf.do_field('string'),
'<input name="string" value="Node 1: I am a string" size="30">')
+ self.assertEqual(self.tf.do_field('string', size=10),
+ '<input name="string" value="Node 1: I am a string" size="10">')
+
+ def testField_password(self):
+ self.assertEqual(self.tf.do_field('password'),
+ '<input type="password" name="password" size="30">')
+ self.assertEqual(self.tf.do_field('password', size=10),
+ '<input type="password" name="password" size="10">')
def testField_html(self):
self.assertEqual(self.tf.do_field('html'), '<input name="html" '
'value="<html>hello, I am HTML</html>" size="30">')
+ self.assertEqual(self.tf.do_field('html', size=10),
+ '<input name="html" value="<html>hello, I am '
+ 'HTML</html>" size="10">')
def testField_date(self):
self.assertEqual(self.tf.do_field('date'),
'<input name="date" value="2000-01-01.00:00:00" size="30">')
+ self.assertEqual(self.tf.do_field('date', size=10),
+ '<input name="date" value="2000-01-01.00:00:00" size="10">')
def testField_interval(self):
self.assertEqual(self.tf.do_field('interval'),
'<input name="interval" value="- 3d" size="30">')
+ self.assertEqual(self.tf.do_field('interval', size=10),
+ '<input name="interval" value="- 3d" size="10">')
def testField_link(self):
self.assertEqual(self.tf.do_field('link'), '''<select name="link">
def testField_multilink(self):
self.assertEqual(self.tf.do_field('multilink'),
+ '<input name="multilink" size="30" value="the key,the key">')
+ self.assertEqual(self.tf.do_field('multilink', size=10),
'<input name="multilink" size="10" value="the key,the key">')
+# def do_menu(self, property, size=None, height=None, showid=0):
+ def testMenu_link(self):
+ self.assertEqual(self.tf.do_menu('link'), '''<select name="link">
+<option value="-1">- no selection -</option>
+<option selected value="1">the key</option>
+<option value="2">the key</option>
+</select>''')
+ self.assertEqual(self.tf.do_menu('link', size=6),
+ '''<select name="link">
+<option value="-1">- no selection -</option>
+<option selected value="1">the...</option>
+<option value="2">the...</option>
+</select>''')
+ self.assertEqual(self.tf.do_menu('link', showid=1),
+ '''<select name="link">
+<option value="-1">- no selection -</option>
+<option selected value="1">other1: the key</option>
+<option value="2">other2: the key</option>
+</select>''')
+
+ def testMenu_multilink(self):
+ self.assertEqual(self.tf.do_menu('multilink', height=10),
+ '''<select multiple name="multilink" size="10">
+<option selected value="1">the key</option>
+<option selected value="2">the key</option>
+</select>''')
+ self.assertEqual(self.tf.do_menu('multilink', size=6, height=10),
+ '''<select multiple name="multilink" size="10">
+<option selected value="1">the...</option>
+<option selected value="2">the...</option>
+</select>''')
+ self.assertEqual(self.tf.do_menu('multilink', showid=1),
+ '''<select multiple name="multilink" size="2">
+<option selected value="1">other1: the key</option>
+<option selected value="2">other2: the key</option>
+</select>''')
+
def suite():
return unittest.makeSuite(NodeCase, 'test')
#
# $Log: not supported by cvs2svn $
+# Revision 1.1 2002/01/21 11:05:48 richard
+# New tests for htmltemplate (well, it's a beginning)
+#
#
#
# vim: set filetype=python ts=4 sw=4 et si