X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fcgi%2Ftemplating.py;h=cfe998e01dd97b4d149e654d29b8e1581bb57b2d;hb=9f96bccb32cae3de034a552084ddad6c9f94b29a;hp=cd0e615b36ee70adc03a6d1821d85142c4d4492e;hpb=19d94098412a610876ddaf4e1a10cb3b604af721;p=roundup.git diff --git a/roundup/cgi/templating.py b/roundup/cgi/templating.py index cd0e615..cfe998e 100644 --- a/roundup/cgi/templating.py +++ b/roundup/cgi/templating.py @@ -22,111 +22,88 @@ from roundup.cgi.PageTemplates.Expressions import getEngine from roundup.cgi.TAL.TALInterpreter import TALInterpreter from roundup.cgi import ZTUtils -# XXX WAH pagetemplates aren't pickleable :( -#def getTemplate(dir, name, classname=None, request=None): -# ''' Interface to get a template, possibly loading a compiled template. -# ''' -# # source -# src = os.path.join(dir, name) -# -# # see if we can get a compile from the template"c" directory (most -# # likely is "htmlc" -# split = list(os.path.split(dir)) -# split[-1] = split[-1] + 'c' -# cdir = os.path.join(*split) -# split.append(name) -# cpl = os.path.join(*split) -# -# # ok, now see if the source is newer than the compiled (or if the -# # compiled even exists) -# MTIME = os.path.stat.ST_MTIME -# if (not os.path.exists(cpl) or os.stat(cpl)[MTIME] < os.stat(src)[MTIME]): -# # nope, we need to compile -# pt = RoundupPageTemplate() -# pt.write(open(src).read()) -# pt.id = name -# -# # save off the compiled template -# if not os.path.exists(cdir): -# os.makedirs(cdir) -# f = open(cpl, 'wb') -# pickle.dump(pt, f) -# f.close() -# else: -# # yay, use the compiled template -# f = open(cpl, 'rb') -# pt = pickle.load(f) -# return pt - -templates = {} - class NoTemplate(Exception): pass -def precompileTemplates(dir): - ''' Go through a directory and precompile all the templates therein - ''' - for filename in os.listdir(dir): - if os.path.isdir(filename): continue - if '.' in filename: - name, extension = filename.split('.') - getTemplate(dir, name, extension) - else: - getTemplate(dir, filename, None) +class Templates: + templates = {} + + def __init__(self, dir): + self.dir = dir -def getTemplate(dir, name, extension, classname=None, request=None): - ''' Interface to get a template, possibly loading a compiled template. + def precompileTemplates(self): + ''' Go through a directory and precompile all the templates therein + ''' + for filename in os.listdir(self.dir): + if os.path.isdir(filename): continue + if '.' in filename: + name, extension = filename.split('.') + self.getTemplate(name, extension) + else: + self.getTemplate(filename, None) - "name" and "extension" indicate the template we're after, which in - most cases will be "name.extension". If "extension" is None, then - we look for a template just called "name" with no extension. + def get(self, name, extension): + ''' Interface to get a template, possibly loading a compiled template. - If the file "name.extension" doesn't exist, we look for - "_generic.extension" as a fallback. - ''' - # default the name to "home" - if name is None: - name = 'home' + "name" and "extension" indicate the template we're after, which in + most cases will be "name.extension". If "extension" is None, then + we look for a template just called "name" with no extension. - # find the source, figure the time it was last modified - if extension: - filename = '%s.%s'%(name, extension) - else: - filename = name - src = os.path.join(dir, filename) - try: - stime = os.stat(src)[os.path.stat.ST_MTIME] - except os.error, error: - if error.errno != errno.ENOENT: - raise - if not extension: - raise NoTemplate, 'Template file "%s" doesn\'t exist'%name - - # try for a generic template - generic = '_generic.%s'%extension - src = os.path.join(dir, generic) + If the file "name.extension" doesn't exist, we look for + "_generic.extension" as a fallback. + ''' + # default the name to "home" + if name is None: + name = 'home' + + # find the source, figure the time it was last modified + if extension: + filename = '%s.%s'%(name, extension) + else: + filename = name + src = os.path.join(self.dir, filename) try: stime = os.stat(src)[os.path.stat.ST_MTIME] except os.error, error: if error.errno != errno.ENOENT: raise - # nicer error - raise NoTemplate, 'No template file exists for templating '\ - '"%s" with template "%s" (neither "%s" nor "%s")'%(name, - extension, filename, generic) - filename = generic - - key = (dir, filename) - if templates.has_key(key) and stime < templates[key].mtime: - # compiled template is up to date - return templates[key] - - # compile the template - templates[key] = pt = RoundupPageTemplate() - pt.write(open(src).read()) - pt.id = filename - pt.mtime = time.time() - return pt + if not extension: + raise NoTemplate, 'Template file "%s" doesn\'t exist'%name + + # try for a generic template + generic = '_generic.%s'%extension + src = os.path.join(self.dir, generic) + try: + stime = os.stat(src)[os.path.stat.ST_MTIME] + except os.error, error: + if error.errno != errno.ENOENT: + raise + # nicer error + raise NoTemplate, 'No template file exists for templating '\ + '"%s" with template "%s" (neither "%s" nor "%s")'%(name, + extension, filename, generic) + filename = generic + + if self.templates.has_key(filename) and \ + stime < self.templates[filename].mtime: + # compiled template is up to date + return self.templates[filename] + + # compile the template + self.templates[filename] = pt = RoundupPageTemplate() + pt.write(open(src).read()) + pt.id = filename + pt.mtime = time.time() + return pt + + def __getitem__(self, name): + name, extension = os.path.splitext(name) + if extension: + extension = extension[1:] + try: + return self.get(name, extension) + except NoTemplate, message: + raise KeyError, message class RoundupPageTemplate(PageTemplate.PageTemplate): ''' A Roundup-specific PageTemplate. @@ -149,20 +126,21 @@ class RoundupPageTemplate(PageTemplate.PageTemplate): - methods for easy filterspec link generation - *user*, the current user node as an HTMLItem instance - *form*, the current CGI form information as a FieldStorage - *instance* - The current instance + *config* + The current tracker config. *db* - The current database, through which db.config may be reached. + The current database, used to access arbitrary database items. ''' def getContext(self, client, classname, request): c = { 'options': {}, 'nothing': None, 'request': request, - 'content': client.content, 'db': HTMLDatabase(client), - 'instance': client.instance, + 'config': client.instance.config, + 'tracker': client.instance, 'utils': TemplatingUtils(client), + 'templates': Templates(client.instance.config.TEMPLATES), } # add in the item if there is one if client.nodeid: @@ -170,7 +148,7 @@ class RoundupPageTemplate(PageTemplate.PageTemplate): c['context'] = HTMLUser(client, classname, client.nodeid) else: c['context'] = HTMLItem(client, classname, client.nodeid) - else: + elif client.db.classes.has_key(classname): c['context'] = HTMLClass(client, classname) return c @@ -194,7 +172,7 @@ class RoundupPageTemplate(PageTemplate.PageTemplate): # and go output = StringIO.StringIO() - TALInterpreter(self._v_program, self._v_macros, + TALInterpreter(self._v_program, self.macros, getEngine().getContext(c), output, tal=1, strictinsert=0)() return output.getvalue() @@ -229,7 +207,11 @@ def lookupIds(db, prop, ids, num_re=re.compile('-?\d+')): if num_re.match(entry): l.append(entry) else: - l.append(cl.lookup(entry)) + try: + l.append(cl.lookup(entry)) + except KeyError: + # ignore invalid keys + pass return l class HTMLPermissions: @@ -260,9 +242,8 @@ class HTMLClass(HTMLPermissions): # we want classname to be exposed, but _classname gives a # consistent API for extending Class/Item self._classname = self.classname = classname - if classname is not None: - self._klass = self._db.getclass(self.classname) - self._props = self._klass.getprops() + self._klass = self._db.getclass(self.classname) + self._props = self._klass.getprops() def __repr__(self): return ''%(id(self), self.classname) @@ -426,8 +407,8 @@ class HTMLClass(HTMLPermissions): properties.sort() properties = ','.join(properties) return ''\ - '(%s)'%(self.classname, properties, width, height, label) + 'properties=%s\', \'%s\', \'%s\')">(%s)'%( + self.classname, properties, width, height, label) def submit(self, label="Submit New Entry"): ''' Generate a submit button (and action hidden element) @@ -447,7 +428,7 @@ class HTMLClass(HTMLPermissions): req.update(kwargs) # new template, using the specified classname and request - pt = getTemplate(self._db.config.TEMPLATES, self.classname, name) + pt = Templates(self._db.config.TEMPLATES).get(self.classname, name) # use our fabricated request return pt.render(self._client, self.classname, req) @@ -509,7 +490,7 @@ class HTMLItem(HTMLPermissions): # XXX do this return [] - def history(self, direction='descending'): + def history(self, direction='descending', dre=re.compile('\d+')): l = ['' ''%( date_s, user, action, arg_s)) if comments: @@ -666,7 +651,7 @@ class HTMLItem(HTMLPermissions): req.updateFromURL(self._klass.get(self._nodeid, 'url')) # new template, using the specified classname and request - pt = getTemplate(self._db.config.TEMPLATES, req.classname, 'search') + pt = Templates(self._db.config.TEMPLATES).get(req.classname, 'search') # use our fabricated request return pt.render(self._client, req.classname, req) @@ -1440,7 +1425,7 @@ function submit_once() { } function help_window(helpurl, width, height) { - HelpWin = window.open('%s/' + helpurl, 'RoundupHelpWindow', 'scrollbars=yes,resizable=yes,toolbar=no,height='+height+',width='+width); + HelpWin = window.open('%s' + helpurl, 'RoundupHelpWindow', 'scrollbars=yes,resizable=yes,toolbar=no,height='+height+',width='+width); } '''%self.base
', _('History'), @@ -648,6 +629,10 @@ class HTMLItem(HTMLPermissions): handled by the history display!''') arg_s = '' + str(args) + '' date_s = date_s.replace(' ', ' ') + # if the user's an itemid, figure the username (older journals + # have the username) + if dre.match(user): + user = self._db.user.get(user, 'username') l.append('
%s%s%s%s