Attachment 'AirspeedTemplate.py'
Download 1 # plugin/macro/AirspeedTemplate.py
2 # Copyright 2009 by David Handy, Handy Software and Publishing
3 # http://www.handysoftware.com/cpif/
4 # Released under the Simplified BSD License
5 # http://opensource.org/licenses/bsd-license.php
6 """
7 MoinMoin macro for including an airspeed template in a page.
8
9 Airspeed is a Python clone of the Velocity template engine.
10 Airspeed: http://dev.sanityinc.com/airspeed/
11 Velocity: http://velocity.apache.org/
12
13 Macro parameters:
14 template_filename:
15 (required) The name of the template file to use.
16 Any directory path portion of this name will be ignored, for
17 security reasons. The files are in the "airspeed_templates"
18 subdirectory of the wiki's plugin directory unless the
19 template_subdir parameter is given.
20 context_varname:
21 (optional) The name of the request attribute containing the context.
22 The context is a dictionary whose values become variables available
23 for use in the template. If this request attribute doesn't exist,
24 only the standard variables and functions are added to the context,
25 otherwise this dictionary is added to the context, replacing any
26 standard variables with the same names. Default: 'template_context'
27 template_subdir:
28 (optional) The name of the subdirectory of the plugins directory in
29 which template files will be found. For security purposes, if this
30 parameter is a directory path, only the last component will be used,
31 and '..' is not allowed. The default is "airspeed_templates".
32
33 Standard variables and functions added to the context:
34 request -- MoinMoin request object. $request.script_name to form URIs
35 user -- User object for current user. user.name is login name.
36 session -- MoinMoin session. Use $session.varname to get a session var.
37 env -- CGI environment variables, i.e. $env.HTTP_USER_AGENT
38 form -- GET and POST params. i.e. $form.varname
39 saved_form -- Vars. saved on session by action. See the code.
40 escape -- Function to replace HTML special characters, i.e. with "<"
41 urlquote -- Function to quote URL query parameters
42 len -- Function to return length of list or size of dictionary
43 getitem -- getitem(mylist, 0) -> first item in list, also for dicts
44 clear_saved_form -- $!clear_saved_form() deletes saved_form. See the code.
45
46 Example:
47
48 Contents of plugins/action/fruit_action.py:
49 from MoinMoin.Page import Page
50 def execute(pagename, request):
51 request.template_context = {'apples': 5, 'bananas': '<two>'}
52 return Page(request, pagename).send_page()
53
54 Contents of plugins/airspeed_templates/fruit.html:
55 <b>We have $apples apples and $escape($bananas) bananas.</b>
56
57 Source text of FruitStatus wiki page:
58 Here is the status of our fruit supply:<<BR>>
59 <<AirspeedTemplate(fruit.html)>>
60
61 Result of http://localhost/wiki/FruitStatus?action=fruit_action :
62 Here is the status of our fruit supply:<br>
63 <b>We have 5 apples and <2> bananas.</b>
64 """
65 __version__ = '1.1'
66
67 import os
68 import sys
69 import traceback
70 import urllib
71
72 from MoinMoin.wikiutil import escape
73
74 try:
75 import airspeed
76 except ImportError:
77 airspeed = None
78
79 Dependencies = ['time']
80 generates_headings = False
81
82 def _doit(macro, template_filename, context_varname=None,
83 template_subdir=None):
84 if not context_varname:
85 context_varname = 'template_context'
86 if not template_subdir:
87 template_subdir = 'airspeed_templates'
88 else:
89 template_subdir = os.path.basename(template_subdir)
90 # Plug security hole
91 if template_subdir == '..':
92 template_subdir = '.'
93 result = []
94 put = result.append
95 if not airspeed:
96 put('\n<p><<')
97 put('AirspeedTemplate: <a href="http://dev.sanityinc.com/airspeed/">airspeed</a> module is not installed')
98 put('>></p>\n')
99 return macro.formatter.rawHTML(''.join(result))
100 if not template_filename:
101 put('\n<p><<')
102 put('AirspeedTemplate: missing template_filename parameter')
103 put('>></p>\n')
104 return macro.formatter.rawHTML(''.join(result))
105 # Locate the template file directory relative to the site plugins dir
106 # This method of locating the plugin directory is broken on MoinMoin 1.8+
107 if 0:
108 plugin = __import__(macro.cfg.__module__ + '.plugin').plugin
109 plugin_dir = os.path.dirname(plugin.__file__)
110 plugin_dir = os.path.abspath(
111 os.path.join(os.path.dirname(sys.modules[__name__].__file__), '..'))
112 template_dir = os.path.join(plugin_dir, template_subdir)
113 filename = os.path.join(template_dir, os.path.basename(template_filename))
114 if not os.path.isfile(filename):
115 put('\n<p><<')
116 put('AirspeedTemplate: file "%s" not in %s directory' %
117 (escape(template_filename), escape(template_subdir)))
118 put('>></p>\n')
119 return macro.formatter.rawHTML(''.join(result))
120 f = open(filename, 'r')
121 try:
122 template = airspeed.Template(f.read())
123 finally:
124 f.close()
125 def wrapped_escape(s):
126 if s is None:
127 return None
128 return escape(s)
129 def urlquote(s):
130 if s is None:
131 return None
132 return urllib.quote_plus(s)
133 class FormValueGetter:
134 def __init__(self, moin_form):
135 self.moin_form = moin_form
136 def __getitem__(self, varname):
137 item = self.moin_form[varname]
138 return item[0]
139 def get(self, varname):
140 item = self.moin_form.get(varname, [None])
141 return item[0]
142 def clear_saved_form():
143 if 'saved_form' in macro.request.session:
144 del macro.request.session['saved_form']
145 def wrapped_len(obj):
146 if obj is None:
147 return 0
148 return len(obj)
149 def getitem(obj, index_or_key):
150 if obj is None:
151 return None
152 if index_or_key is None:
153 return None
154 return obj[index_or_key]
155 saved_form = macro.request.session.get('saved_form', {})
156 # Support stand-alone MoinMoin server
157 try:
158 env = macro.request.env
159 except AttributeError:
160 env = {'SCRIPT_NAME': macro.request.script_name,
161 'PATH_INFO': macro.request.getPathinfo()}
162 context = {
163 # Standard variables
164 'request': macro.request,
165 'user': macro.request.user,
166 'session': macro.request.session,
167 'env': env,
168 'script_name': macro.request.script_name,
169 'form': FormValueGetter(macro.form),
170 'saved_form': saved_form,
171 # Standard functions
172 'escape': wrapped_escape,
173 'urlquote': urlquote,
174 'len': wrapped_len,
175 'getitem': getitem,
176 'clear_saved_form': clear_saved_form,
177 }
178 context['keys'] = context.keys
179 if context_varname:
180 additional_context = getattr(macro.request, context_varname, {})
181 # This could raise an exception if the context variable points to
182 # a non-dictionary object.
183 context.update(additional_context)
184 put(template.merge(context))
185 return macro.formatter.rawHTML(''.join(result))
186
187 def macro_AirspeedTemplate(macro, template_filename=unicode,
188 context_varname=unicode,
189 template_subdir=unicode):
190 try:
191 return _doit(macro, template_filename,
192 context_varname=context_varname,
193 template_subdir=template_subdir)
194 except:
195 err = sys.exc_info()[1]
196 traceback.print_exc()
197 return macro.format_error(err)
198
199 # end-of-file
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.