summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: a101d38)
raw | patch | inline | side by side (parent: a101d38)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Thu, 5 Sep 2002 23:39:14 +0000 (23:39 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Thu, 5 Sep 2002 23:39:14 +0000 (23:39 +0000) |
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.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1074 57a73879-2fb5-44c3-a270-3262357dd7e2
Added :required to form handling.
Handle multiple values for single form items with decent error report.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1074 57a73879-2fb5-44c3-a270-3262357dd7e2
diff --git a/TODO.txt b/TODO.txt
index 4407f61f7782b958b3a6edb356b82f42907b841a..b7b3abb0ec6b90298264a61cd41a7a2b1d85eb7b 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
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)
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)
+
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index 22555bbaba852736b6f7bae4b90e22575a9d9b63..663f0c764d429ce0dd22d043b182907768dbbc3a 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $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).
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 = []
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]
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]
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
'%(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([])):
- value = [i.strip() for i in value.value.split(',')]
- else:
+ 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(',')]
link = cl.properties[key].classname
l = []
for entry in map(str, value):
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
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
diff --git a/roundup/init.py b/roundup/init.py
index 7723aba1088499ded89fef1d7c99ca8a4b4fe0c0..0ede7b06f0c697539bb75a2bd9d651e838605628 100644 (file)
--- a/roundup/init.py
+++ b/roundup/init.py
# 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.
# 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)
#
# $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
#
index 4162d5ec670fe99e1cc8e163ad6a0fe34e9baa42..8d65e4170ddc7fe4a52b96672263b58c812de428 100644 (file)
*.pyc
*.pyo
*.cover
+*_htmlbase.py
+*_htmlbase.pyc
index 40e6eec848716b21b5155fe7e7faea97b4eb3ae1..11ea2104188564fbfe628b9acfba5926da15c7f7 100644 (file)
# 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.
"""
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
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)
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:
#
# $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.
#
index 86d1da08a50da9b2d1f46b8403b3f39f856debc3..de8c855886db7cc95569da7234832ef77bc7402e 100644 (file)
# 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.