Mercurial > p > roundup > code
changeset 1055:cf72eae57a2c
Fixed instance installation
... moved the htmlbase module into templates and call it
<template>_htmlbase.py ... no more try/except in instance __init__!
Added :required to form handling.
Handle multiple values for single form items with decent error report.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Thu, 05 Sep 2002 23:39:14 +0000 |
| parents | 3d8ea16347aa |
| children | 1c2a2ecc1b03 |
| files | TODO.txt roundup/cgi/client.py roundup/init.py roundup/templates/.cvsignore roundup/templates/builder.py roundup/templates/classic/__init__.py |
| diffstat | 6 files changed, 102 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/TODO.txt Thu Sep 05 05:25:23 2002 +0000 +++ b/TODO.txt Thu Sep 05 23:39:14 2002 +0000 @@ -47,19 +47,14 @@ query values pending web: have roundup.cgi pick up instance config from the environment pending web: UNIX init.d script for roundup-server +pending web: rewritten documentation (can come after the beta though so stuff + is settled) +pending web: modify cgitb to handle PageTemplate errors better (see how + Zope handles __traceback_supplement__ and __traceback_info__) +pending web: title is stoopid -New templating TODO: -. rewritten documentation (can come after the beta though so stuff is settled) -. modify cgitb to handle PageTemplate errors better -. add :required to edit action -active web: title is stoopid -active hyperdb: full-text searching doesn't appear to match stuff in titles, - even though they're supposed to be indexed... - -ongoing: any bugs bug: request.url is incorrect in cgi-bin environments -rejected instance: the use of non-Python configuration files (ConfigParser) done web: Re-enable link backrefs from messages (feature request #568714) (RJ) done web: have the page layout (header/footer) be templatable (RJ) done web: fixing the templating so it works (RJ) @@ -79,7 +74,10 @@ done security: add info from doc/security.txt to design doc (RJ) done security: switch to sessions for web authentication (RJ) done security: implement and use the new logical control mechanisms -done web: saving of named queries (GM) +done web: saving of named queries (GM, RJ) done web: handle "not found", access and item page render errors better (RJ) done web: fix double-submit by having new-item-submit redirect at end (RJ) -done web: daemonify roundup-server (fork, logfile, pidfile) +done web: daemonify roundup-server (fork, logfile, pidfile) (RJ) + +rejected instance: the use of non-Python configuration files (ConfigParser) +
--- a/roundup/cgi/client.py Thu Sep 05 05:25:23 2002 +0000 +++ b/roundup/cgi/client.py Thu Sep 05 23:39:14 2002 +0000 @@ -1,4 +1,4 @@ -# $Id: client.py,v 1.14 2002-09-05 05:25:23 richard Exp $ +# $Id: client.py,v 1.15 2002-09-05 23:39:12 richard Exp $ __doc__ = """ WWW request handler (also used in the stand-alone server). @@ -114,9 +114,15 @@ In some situations, exceptions occur: - HTTP Redirect (generally raised by an action) - SendFile (generally raised by determine_context) + serve up a FileClass "content" property - SendStaticFile (generally raised by determine_context) - - Unauthorised (raised pretty much anywhere it needs to be) - - NotFound (see above... percolates up to the CGI interface) + serve up a file from the tracker "html" directory + - Unauthorised (generally raised by an action) + the action is cancelled, the request is rendered and an error + message is displayed indicating that permission was not + granted for the action to take place + - NotFound (raised wherever it needs to be) + percolates up to the CGI interface that called the client ''' self.content_action = None self.ok_message = [] @@ -581,6 +587,10 @@ Create a file and attach it to the current node's "files" property. Attach the file to the message created from the __note if it's supplied. + + :required=property,property,... + The named properties are required to be filled in the form. + ''' cl = self.db.classes[self.classname] @@ -653,7 +663,8 @@ def newItemAction(self): ''' Add a new item to the database. - This follows the same form as the editItemAction + This follows the same form as the editItemAction, with the same + special form values. ''' cl = self.db.classes[self.classname] @@ -1033,36 +1044,58 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')): - '''Pull properties for the given class out of the form. + ''' Pull properties for the given class out of the form. + + If a ":required" parameter is supplied, then the names property values + must be supplied or a ValueError will be raised. ''' + required = [] + if form.has_key(':required'): + value = form[':required'] + if isinstance(value, type([])): + required = [i.value.strip() for i in value] + else: + required = [i.strip() for i in value.value.split(',')] + props = {} keys = form.keys() for key in keys: if not cl.properties.has_key(key): continue proptype = cl.properties[key] + + # Get the form value. This value may be a MiniFieldStorage or a list + # of MiniFieldStorages. + value = form[key] + + # make sure non-multilinks only get one value + if not isinstance(proptype, hyperdb.Multilink): + if isinstance(value, type([])): + raise ValueError, 'You have submitted more than one value'\ + ' for the %s property'%key + # we've got a MiniFieldStorage, so pull out the value and strip + # surrounding whitespace + value = value.value.strip() + if isinstance(proptype, hyperdb.String): + pass value = form[key].value.strip() elif isinstance(proptype, hyperdb.Password): - value = form[key].value.strip() if not value: # ignore empty password values continue value = password.Password(value) elif isinstance(proptype, hyperdb.Date): - value = form[key].value.strip() if value: value = date.Date(form[key].value.strip()) else: value = None elif isinstance(proptype, hyperdb.Interval): - value = form[key].value.strip() if value: value = date.Interval(form[key].value.strip()) else: value = None elif isinstance(proptype, hyperdb.Link): - value = form[key].value.strip() # see if it's the "no selection" choice if value == '-1': value = None @@ -1077,11 +1110,13 @@ '%(value)s not a %(classname)s')%{'propname':key, 'value': value, 'classname': link} elif isinstance(proptype, hyperdb.Multilink): - value = form[key] - if not isinstance(value, type([])): + if isinstance(value, type([])): + # it's a list of MiniFieldStorages + value = [i.value.strip() for i in value] + else: + # it's a MiniFieldStorage, but may be a comma-separated list + # of values value = [i.strip() for i in value.value.split(',')] - else: - value = [i.value.strip() for i in value] link = cl.properties[key].classname l = [] for entry in map(str, value): @@ -1097,10 +1132,8 @@ l.sort() value = l elif isinstance(proptype, hyperdb.Boolean): - value = form[key].value.strip() props[key] = value = value.lower() in ('yes', 'true', 'on', '1') elif isinstance(proptype, hyperdb.Number): - value = form[key].value.strip() props[key] = value = int(value) # get the old value @@ -1117,6 +1150,15 @@ props[key] = value else: props[key] = value + + # see if all the required properties have been supplied + l = [] + for property in required: + if not props.has_key(property): + l.append(property) + if l: + raise ValueError, 'Required properties %s not supplied'%(', '.join(l)) + return props
--- a/roundup/init.py Thu Sep 05 05:25:23 2002 +0000 +++ b/roundup/init.py Thu Sep 05 23:39:14 2002 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: init.py,v 1.21 2002-08-16 04:25:03 richard Exp $ +# $Id: init.py,v 1.22 2002-09-05 23:39:12 richard Exp $ __doc__ = """ Init (create) a roundup instance. @@ -89,6 +89,7 @@ # first, copy the template dir over from roundup.templates import builder + # copy the roundup.templates.<template> package contents to the instance dir template_dir = os.path.split(__file__)[0] template_name = template template = os.path.join(template_dir, 'templates', template) @@ -114,6 +115,9 @@ # # $Log: not supported by cvs2svn $ +# Revision 1.21 2002/08/16 04:25:03 richard +# cleanup: moved templatebuilder into templates.builder +# # Revision 1.20 2002/07/14 02:05:53 richard # . all storage-specific code (ie. backend) is now implemented by the backends #
--- a/roundup/templates/.cvsignore Thu Sep 05 05:25:23 2002 +0000 +++ b/roundup/templates/.cvsignore Thu Sep 05 23:39:14 2002 +0000 @@ -1,3 +1,5 @@ *.pyc *.pyo *.cover +*_htmlbase.py +*_htmlbase.pyc
--- a/roundup/templates/builder.py Thu Sep 05 05:25:23 2002 +0000 +++ b/roundup/templates/builder.py Thu Sep 05 23:39:14 2002 +0000 @@ -15,8 +15,8 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: builder.py,v 1.1 2002-08-16 04:25:03 richard Exp $ -import errno, re +# $Id: builder.py,v 1.2 2002-09-05 23:39:13 richard Exp $ +import os, sys, glob, errno, re __doc__ = """ Collect template parts and create instance template files. @@ -29,14 +29,19 @@ """ def makeHtmlBase(templateDir): - """ make a htmlbase.py file in the given templateDir, from the - contents of templateDir/html """ - import os, glob, re + ''' make a <template>_htmlbase.py file in rondup.tempaltes, from the + contents of templateDir/html + ''' print "packing up templates in", templateDir + filelist = glob.glob(os.path.join(templateDir, 'html', '*')) filelist = filter(os.path.isfile, filelist) # only want files filelist.sort() - fd = open(os.path.join(templateDir, 'htmlbase.py'), 'w') + + # ok, figure the template name and templates dir + dir, name = os.path.split(templateDir) + + fd = open(os.path.join(dir, '%s_htmlbase.py'%name), 'w') fd.write(preamble) for file in filelist: # skip the backup files created by richard's vim @@ -49,16 +54,16 @@ fd.close() def installHtmlBase(template, installDir): - """ passed a template package and an installDir, unpacks the html files into - the installdir """ - import os,sys,re - - tdir = __import__('roundup.templates.%s.htmlbase'%template).templates - if hasattr(tdir, template): - tmod = getattr(tdir, template) + ''' passed a template name and an installDir, unpacks the html files into + the installdir + ''' + tmod = '%s_htmlbase'%template + tdir = __import__('roundup.templates.'+tmod).templates + if hasattr(tdir, tmod): + htmlbase = getattr(tdir, tmod) else: - raise "TemplateError", "couldn't find roundup.template.%s.htmlbase"%template - htmlbase = tmod.htmlbase + raise "TemplateError", \ + "couldn't find roundup.templates.%s_htmlbase"%template installDir = os.path.join(installDir, 'html') try: os.makedirs(installDir) @@ -76,10 +81,7 @@ data = getattr(htmlbase, mangledfile) outfd.write(data) - - if __name__ == "__main__": - import sys if len(sys.argv) == 2: makeHtmlBase(sys.argv[1]) elif len(sys.argv) == 3: @@ -89,6 +91,9 @@ # # $Log: not supported by cvs2svn $ +# Revision 1.1 2002/08/16 04:25:03 richard +# cleanup: moved templatebuilder into templates.builder +# # Revision 1.14 2002/02/05 09:59:05 grubert # . makeHtmlBase: re.sub under python 2.2 did not replace '.', string.replace does it. #
--- a/roundup/templates/classic/__init__.py Thu Sep 05 05:25:23 2002 +0000 +++ b/roundup/templates/classic/__init__.py Thu Sep 05 23:39:14 2002 +0000 @@ -15,18 +15,18 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.5 2001-08-07 00:24:43 richard Exp $ +# $Id: __init__.py,v 1.6 2002-09-05 23:39:14 richard Exp $ import sys from instance_config import * -try: - from dbinit import * -except: - pass # in install dir (probably :) +from dbinit import * from interfaces import * # # $Log: not supported by cvs2svn $ +# Revision 1.5 2001/08/07 00:24:43 richard +# stupid typo +# # Revision 1.4 2001/08/07 00:15:51 richard # Added the copyright/license notice to (nearly) all files at request of # Bizar Software.
