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 &lt;2&gt; 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>&lt;&lt;')
  97         put('AirspeedTemplate: <a href="http://dev.sanityinc.com/airspeed/">airspeed</a> module is not installed')
  98         put('&gt;&gt;</p>\n')
  99         return macro.formatter.rawHTML(''.join(result))
 100     if not template_filename:
 101         put('\n<p>&lt;&lt;')
 102         put('AirspeedTemplate: missing template_filename parameter')
 103         put('&gt;&gt;</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>&lt;&lt;')
 116         put('AirspeedTemplate: file "%s" not in %s directory' %
 117                 (escape(template_filename), escape(template_subdir)))
 118         put('&gt;&gt;</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.
  • [get | view] (2009-02-05 23:00:27, 7.5 KB) [[attachment:AirspeedTemplate.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.