comparison roundup/htmltemplate.py @ 651:6257d4e49d2a

Ran it through pychecker, made fixes
author Richard Jones <richard@users.sourceforge.net>
date Wed, 27 Feb 2002 04:14:31 +0000
parents 7dd13fd5d8ea
children d92e06a3a56e
comparison
equal deleted inserted replaced
650:9b2575610953 651:6257d4e49d2a
13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
17 # 17 #
18 # $Id: htmltemplate.py,v 1.82 2002-02-21 23:11:45 richard Exp $ 18 # $Id: htmltemplate.py,v 1.83 2002-02-27 04:14:31 richard Exp $
19 19
20 __doc__ = """ 20 __doc__ = """
21 Template engine. 21 Template engine.
22 """ 22 """
23 23
24 import os, re, StringIO, urllib, cgi, errno, types 24 import os, re, StringIO, urllib, cgi, errno, types
25 25
26 import hyperdb, date, password 26 import hyperdb, date
27 from i18n import _ 27 from i18n import _
28 28
29 # This imports the StructureText functionality for the do_stext function 29 # This imports the StructureText functionality for the do_stext function
30 # get it from http://dev.zope.org/Members/jim/StructuredTextWiki/NGReleases 30 # get it from http://dev.zope.org/Members/jim/StructuredTextWiki/NGReleases
31 try: 31 try:
32 from StructuredText.StructuredText import HTML as StructuredText 32 from StructuredText.StructuredText import HTML as StructuredText
33 except ImportError: 33 except ImportError:
34 StructuredText = None 34 StructuredText = None
35 35
36 class MissingTemplateError(ValueError): 36 class MissingTemplateError(ValueError):
37 '''Error raised when a template file is missing
38 '''
37 pass 39 pass
38 40
39 class TemplateFunctions: 41 class TemplateFunctions:
42 '''Defines the templating functions that are used in the HTML templates
43 of the roundup web interface.
44 '''
40 def __init__(self): 45 def __init__(self):
41 self.form = None 46 self.form = None
42 self.nodeid = None 47 self.nodeid = None
43 self.filterspec = None 48 self.filterspec = None
44 self.globals = {} 49 self.globals = {}
45 for key in TemplateFunctions.__dict__.keys(): 50 for key in TemplateFunctions.__dict__.keys():
46 if key[:3] == 'do_': 51 if key[:3] == 'do_':
47 self.globals[key[3:]] = getattr(self, key) 52 self.globals[key[3:]] = getattr(self, key)
48 53
54 # These are added by the subclass where appropriate
55 self.client = None
56 self.instance = None
57 self.templates = None
58 self.classname = None
59 self.db = None
60 self.cl = None
61 self.properties = None
62
49 def do_plain(self, property, escape=0): 63 def do_plain(self, property, escape=0):
50 ''' display a String property directly; 64 ''' display a String property directly;
51 65
52 display a Date property in a specified time zone with an option to 66 display a Date property in a specified time zone with an option to
53 omit the time from the date stamp; 67 omit the time from the date stamp;
59 return _('[Field: not called from item]') 73 return _('[Field: not called from item]')
60 propclass = self.properties[property] 74 propclass = self.properties[property]
61 if self.nodeid: 75 if self.nodeid:
62 # make sure the property is a valid one 76 # make sure the property is a valid one
63 # TODO: this tests, but we should handle the exception 77 # TODO: this tests, but we should handle the exception
64 prop_test = self.cl.getprops()[property] 78 dummy = self.cl.getprops()[property]
65 79
66 # get the value for this property 80 # get the value for this property
67 try: 81 try:
68 value = self.cl.get(self.nodeid, property) 82 value = self.cl.get(self.nodeid, property)
69 except KeyError: 83 except KeyError:
96 elif isinstance(propclass, hyperdb.Multilink): 110 elif isinstance(propclass, hyperdb.Multilink):
97 linkcl = self.db.classes[propclass.classname] 111 linkcl = self.db.classes[propclass.classname]
98 k = linkcl.labelprop() 112 k = linkcl.labelprop()
99 value = ', '.join(value) 113 value = ', '.join(value)
100 else: 114 else:
101 s = _('Plain: bad propclass "%(propclass)s"')%locals() 115 value = _('Plain: bad propclass "%(propclass)s"')%locals()
102 if escape: 116 if escape:
103 value = cgi.escape(value) 117 value = cgi.escape(value)
104 return value 118 return value
105 119
106 def do_stext(self, property, escape=0): 120 def do_stext(self, property, escape=0):
536 if len(args) == 3: 550 if len(args) == 3:
537 linkcl, linkid, key = args 551 linkcl, linkid, key = args
538 arg_s += '<a href="%s%s">%s%s %s</a>'%(linkcl, linkid, 552 arg_s += '<a href="%s%s">%s%s %s</a>'%(linkcl, linkid,
539 linkcl, linkid, key) 553 linkcl, linkid, key)
540 else: 554 else:
541 arg_s = str(arg) 555 arg_s = str(args)
542 556
543 elif action == 'unlink' and type(args) == type(()): 557 elif action == 'unlink' and type(args) == type(()):
544 if len(args) == 3: 558 if len(args) == 3:
545 linkcl, linkid, key = args 559 linkcl, linkid, key = args
546 arg_s += '<a href="%s%s">%s%s %s</a>'%(linkcl, linkid, 560 arg_s += '<a href="%s%s">%s%s %s</a>'%(linkcl, linkid,
547 linkcl, linkid, key) 561 linkcl, linkid, key)
548 else: 562 else:
549 arg_s = str(arg) 563 arg_s = str(args)
550 564
551 elif type(args) == type({}): 565 elif type(args) == type({}):
552 cell = [] 566 cell = []
553 for k in args.keys(): 567 for k in args.keys():
554 # try to get the relevant property and treat it 568 # try to get the relevant property and treat it
562 isinstance(prop, hyperdb.Link)): 576 isinstance(prop, hyperdb.Link)):
563 # figure what the link class is 577 # figure what the link class is
564 classname = prop.classname 578 classname = prop.classname
565 try: 579 try:
566 linkcl = self.db.classes[classname] 580 linkcl = self.db.classes[classname]
567 except KeyError, message: 581 except KeyError:
568 labelprop = None 582 labelprop = None
569 comments[classname] = _('''The linked class 583 comments[classname] = _('''The linked class
570 %(classname)s no longer exists''')%locals() 584 %(classname)s no longer exists''')%locals()
571 labelprop = linkcl.labelprop() 585 labelprop = linkcl.labelprop()
572 586
672 properties, width, height, label) 686 properties, width, height, label)
673 # 687 #
674 # INDEX TEMPLATES 688 # INDEX TEMPLATES
675 # 689 #
676 class IndexTemplateReplace: 690 class IndexTemplateReplace:
691 '''Regular-expression based parser that turns the template into HTML.
692 '''
677 def __init__(self, globals, locals, props): 693 def __init__(self, globals, locals, props):
678 self.globals = globals 694 self.globals = globals
679 self.locals = locals 695 self.locals = locals
680 self.props = props 696 self.props = props
681 697
688 def __call__(self, m, filter=None, columns=None, sort=None, group=None): 704 def __call__(self, m, filter=None, columns=None, sort=None, group=None):
689 if m.group('name'): 705 if m.group('name'):
690 if m.group('name') in self.props: 706 if m.group('name') in self.props:
691 text = m.group('text') 707 text = m.group('text')
692 replace = IndexTemplateReplace(self.globals, {}, self.props) 708 replace = IndexTemplateReplace(self.globals, {}, self.props)
693 return replace.go(m.group('text')) 709 return replace.go(text)
694 else: 710 else:
695 return '' 711 return ''
696 if m.group('display'): 712 if m.group('display'):
697 command = m.group('command') 713 command = m.group('command')
698 return eval(command, self.globals, self.locals) 714 return eval(command, self.globals, self.locals)
699 print '*** unhandled match', m.groupdict() 715 return '*** unhandled match: %s'%str(m.groupdict())
700 716
701 class IndexTemplate(TemplateFunctions): 717 class IndexTemplate(TemplateFunctions):
718 '''Templating functionality specifically for index pages
719 '''
702 def __init__(self, client, templates, classname): 720 def __init__(self, client, templates, classname):
721 TemplateFunctions.__init__(self)
703 self.client = client 722 self.client = client
704 self.instance = client.instance 723 self.instance = client.instance
705 self.templates = templates 724 self.templates = templates
706 self.classname = classname 725 self.classname = classname
707 726
708 # derived 727 # derived
709 self.db = self.client.db 728 self.db = self.client.db
710 self.cl = self.db.classes[self.classname] 729 self.cl = self.db.classes[self.classname]
711 self.properties = self.cl.getprops() 730 self.properties = self.cl.getprops()
712
713 TemplateFunctions.__init__(self)
714 731
715 col_re=re.compile(r'<property\s+name="([^>]+)">') 732 col_re=re.compile(r'<property\s+name="([^>]+)">')
716 def render(self, filterspec={}, filter=[], columns=[], sort=[], group=[], 733 def render(self, filterspec={}, filter=[], columns=[], sort=[], group=[],
717 show_display_form=1, nodeids=None, show_customization=1): 734 show_display_form=1, nodeids=None, show_customization=1):
718 self.filterspec = filterspec 735 self.filterspec = filterspec
934 w('</tr>\n') 951 w('</tr>\n')
935 952
936 # Grouping 953 # Grouping
937 w(_('<tr><th width="1%" align=right class="location-bar">Grouping</th>\n')) 954 w(_('<tr><th width="1%" align=right class="location-bar">Grouping</th>\n'))
938 for name in names: 955 for name in names:
939 prop = self.properties[name]
940 if name not in all_columns: 956 if name not in all_columns:
941 w('<td>&nbsp;</td>') 957 w('<td>&nbsp;</td>')
942 continue 958 continue
943 if name in group: checked=' checked' 959 if name in group: checked=' checked'
944 else: checked='' 960 else: checked=''
995 1011
996 # 1012 #
997 # ITEM TEMPLATES 1013 # ITEM TEMPLATES
998 # 1014 #
999 class ItemTemplateReplace: 1015 class ItemTemplateReplace:
1016 '''Regular-expression based parser that turns the template into HTML.
1017 '''
1000 def __init__(self, globals, locals, cl, nodeid): 1018 def __init__(self, globals, locals, cl, nodeid):
1001 self.globals = globals 1019 self.globals = globals
1002 self.locals = locals 1020 self.locals = locals
1003 self.cl = cl 1021 self.cl = cl
1004 self.nodeid = nodeid 1022 self.nodeid = nodeid
1018 else: 1036 else:
1019 return '' 1037 return ''
1020 if m.group('display'): 1038 if m.group('display'):
1021 command = m.group('command') 1039 command = m.group('command')
1022 return eval(command, self.globals, self.locals) 1040 return eval(command, self.globals, self.locals)
1023 print '*** unhandled match', m.groupdict() 1041 return '*** unhandled match: %s'%str(m.groupdict())
1024 1042
1025 1043
1026 class ItemTemplate(TemplateFunctions): 1044 class ItemTemplate(TemplateFunctions):
1045 '''Templating functionality specifically for item (node) display
1046 '''
1027 def __init__(self, client, templates, classname): 1047 def __init__(self, client, templates, classname):
1048 TemplateFunctions.__init__(self)
1028 self.client = client 1049 self.client = client
1029 self.instance = client.instance 1050 self.instance = client.instance
1030 self.templates = templates 1051 self.templates = templates
1031 self.classname = classname 1052 self.classname = classname
1032 1053
1033 # derived 1054 # derived
1034 self.db = self.client.db 1055 self.db = self.client.db
1035 self.cl = self.db.classes[self.classname] 1056 self.cl = self.db.classes[self.classname]
1036 self.properties = self.cl.getprops() 1057 self.properties = self.cl.getprops()
1037
1038 TemplateFunctions.__init__(self)
1039 1058
1040 def render(self, nodeid): 1059 def render(self, nodeid):
1041 self.nodeid = nodeid 1060 self.nodeid = nodeid
1042 1061
1043 if (self.properties.has_key('type') and 1062 if (self.properties.has_key('type') and
1055 w(replace.go(s)) 1074 w(replace.go(s))
1056 w('</form>') 1075 w('</form>')
1057 1076
1058 1077
1059 class NewItemTemplate(TemplateFunctions): 1078 class NewItemTemplate(TemplateFunctions):
1079 '''Templating functionality specifically for NEW item (node) display
1080 '''
1060 def __init__(self, client, templates, classname): 1081 def __init__(self, client, templates, classname):
1082 TemplateFunctions.__init__(self)
1061 self.client = client 1083 self.client = client
1062 self.instance = client.instance 1084 self.instance = client.instance
1063 self.templates = templates 1085 self.templates = templates
1064 self.classname = classname 1086 self.classname = classname
1065 1087
1066 # derived 1088 # derived
1067 self.db = self.client.db 1089 self.db = self.client.db
1068 self.cl = self.db.classes[self.classname] 1090 self.cl = self.db.classes[self.classname]
1069 self.properties = self.cl.getprops() 1091 self.properties = self.cl.getprops()
1070
1071 TemplateFunctions.__init__(self)
1072 1092
1073 def render(self, form): 1093 def render(self, form):
1074 self.form = form 1094 self.form = form
1075 w = self.client.write 1095 w = self.client.write
1076 c = self.classname 1096 c = self.classname
1089 w(replace.go(s)) 1109 w(replace.go(s))
1090 w('</form>') 1110 w('</form>')
1091 1111
1092 # 1112 #
1093 # $Log: not supported by cvs2svn $ 1113 # $Log: not supported by cvs2svn $
1114 # Revision 1.82 2002/02/21 23:11:45 richard
1115 # . fixed some problems in date calculations (calendar.py doesn't handle over-
1116 # and under-flow). Also, hour/minute/second intervals may now be more than
1117 # 99 each.
1118 #
1094 # Revision 1.81 2002/02/21 07:21:38 richard 1119 # Revision 1.81 2002/02/21 07:21:38 richard
1095 # docco 1120 # docco
1096 # 1121 #
1097 # Revision 1.80 2002/02/21 07:19:08 richard 1122 # Revision 1.80 2002/02/21 07:19:08 richard
1098 # ... and label, width and height control for extra flavour! 1123 # ... and label, width and height control for extra flavour!

Roundup Issue Tracker: http://roundup-tracker.org/