paul@0 | 1 | # -*- coding: iso-8859-1 -*- |
paul@0 | 2 | """ |
paul@0 | 3 | MoinMoin - MoinSupport library (derived from EventAggregatorSupport) |
paul@0 | 4 | |
paul@0 | 5 | @copyright: 2008, 2009, 2010, 2011, 2012 by Paul Boddie <paul@boddie.org.uk> |
paul@0 | 6 | @copyright: 2000-2004 Juergen Hermann <jh@web.de>, |
paul@0 | 7 | 2005-2008 MoinMoin:ThomasWaldmann. |
paul@0 | 8 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@0 | 9 | """ |
paul@0 | 10 | |
paul@0 | 11 | from DateSupport import * |
paul@0 | 12 | from MoinMoin import wikiutil |
paul@0 | 13 | import re |
paul@0 | 14 | import time |
paul@0 | 15 | |
paul@0 | 16 | __version__ = "0.1" |
paul@0 | 17 | |
paul@0 | 18 | # Content type parsing. |
paul@0 | 19 | |
paul@0 | 20 | encoding_regexp_str = ur'(?P<content_type>[^\s;]*)(?:;\s*charset=(?P<encoding>[-A-Za-z0-9]+))?' |
paul@0 | 21 | encoding_regexp = re.compile(encoding_regexp_str) |
paul@0 | 22 | |
paul@0 | 23 | # Utility functions. |
paul@0 | 24 | |
paul@0 | 25 | def getContentTypeAndEncoding(content_type): |
paul@0 | 26 | m = encoding_regexp.search(content_type) |
paul@0 | 27 | if m: |
paul@0 | 28 | return m.group("content_type"), m.group("encoding") |
paul@0 | 29 | else: |
paul@0 | 30 | return None, None |
paul@0 | 31 | |
paul@0 | 32 | def int_or_none(x): |
paul@0 | 33 | if x is None: |
paul@0 | 34 | return x |
paul@0 | 35 | else: |
paul@0 | 36 | return int(x) |
paul@0 | 37 | |
paul@0 | 38 | # Utility classes and associated functions. |
paul@0 | 39 | |
paul@0 | 40 | class Form: |
paul@0 | 41 | |
paul@0 | 42 | """ |
paul@0 | 43 | A wrapper preserving MoinMoin 1.8.x (and earlier) behaviour in a 1.9.x |
paul@0 | 44 | environment. |
paul@0 | 45 | """ |
paul@0 | 46 | |
paul@0 | 47 | def __init__(self, form): |
paul@0 | 48 | self.form = form |
paul@0 | 49 | |
paul@0 | 50 | def has_key(self, name): |
paul@0 | 51 | return not not self.form.getlist(name) |
paul@0 | 52 | |
paul@0 | 53 | def get(self, name, default=None): |
paul@0 | 54 | values = self.form.getlist(name) |
paul@0 | 55 | if not values: |
paul@0 | 56 | return default |
paul@0 | 57 | else: |
paul@0 | 58 | return values |
paul@0 | 59 | |
paul@0 | 60 | def __getitem__(self, name): |
paul@0 | 61 | return self.form.getlist(name) |
paul@0 | 62 | |
paul@0 | 63 | class ActionSupport: |
paul@0 | 64 | |
paul@0 | 65 | """ |
paul@0 | 66 | Work around disruptive MoinMoin changes in 1.9, and also provide useful |
paul@0 | 67 | convenience methods. |
paul@0 | 68 | """ |
paul@0 | 69 | |
paul@0 | 70 | def get_form(self): |
paul@0 | 71 | return get_form(self.request) |
paul@0 | 72 | |
paul@0 | 73 | def _get_selected(self, value, input_value): |
paul@0 | 74 | |
paul@0 | 75 | """ |
paul@0 | 76 | Return the HTML attribute text indicating selection of an option (or |
paul@0 | 77 | otherwise) if 'value' matches 'input_value'. |
paul@0 | 78 | """ |
paul@0 | 79 | |
paul@0 | 80 | return input_value is not None and value == input_value and 'selected="selected"' or '' |
paul@0 | 81 | |
paul@0 | 82 | def _get_selected_for_list(self, value, input_values): |
paul@0 | 83 | |
paul@0 | 84 | """ |
paul@0 | 85 | Return the HTML attribute text indicating selection of an option (or |
paul@0 | 86 | otherwise) if 'value' matches one of the 'input_values'. |
paul@0 | 87 | """ |
paul@0 | 88 | |
paul@0 | 89 | return value in input_values and 'selected="selected"' or '' |
paul@0 | 90 | |
paul@0 | 91 | def _get_input(self, form, name, default=None): |
paul@0 | 92 | |
paul@0 | 93 | """ |
paul@0 | 94 | Return the input from 'form' having the given 'name', returning either |
paul@0 | 95 | the input converted to an integer or the given 'default' (optional, None |
paul@0 | 96 | if not specified). |
paul@0 | 97 | """ |
paul@0 | 98 | |
paul@0 | 99 | value = form.get(name, [None])[0] |
paul@0 | 100 | if not value: # true if 0 obtained |
paul@0 | 101 | return default |
paul@0 | 102 | else: |
paul@0 | 103 | return int(value) |
paul@0 | 104 | |
paul@0 | 105 | def get_form(request): |
paul@0 | 106 | |
paul@0 | 107 | "Work around disruptive MoinMoin changes in 1.9." |
paul@0 | 108 | |
paul@0 | 109 | if hasattr(request, "values"): |
paul@0 | 110 | return Form(request.values) |
paul@0 | 111 | else: |
paul@0 | 112 | return request.form |
paul@0 | 113 | |
paul@0 | 114 | class send_headers_cls: |
paul@0 | 115 | |
paul@0 | 116 | """ |
paul@0 | 117 | A wrapper to preserve MoinMoin 1.8.x (and earlier) request behaviour in a |
paul@0 | 118 | 1.9.x environment. |
paul@0 | 119 | """ |
paul@0 | 120 | |
paul@0 | 121 | def __init__(self, request): |
paul@0 | 122 | self.request = request |
paul@0 | 123 | |
paul@0 | 124 | def __call__(self, headers): |
paul@0 | 125 | for header in headers: |
paul@0 | 126 | parts = header.split(":") |
paul@0 | 127 | self.request.headers.add(parts[0], ":".join(parts[1:])) |
paul@0 | 128 | |
paul@0 | 129 | def get_send_headers(request): |
paul@0 | 130 | |
paul@0 | 131 | "Return a function that can send response headers." |
paul@0 | 132 | |
paul@0 | 133 | if hasattr(request, "http_headers"): |
paul@0 | 134 | return request.http_headers |
paul@0 | 135 | elif hasattr(request, "emit_http_headers"): |
paul@0 | 136 | return request.emit_http_headers |
paul@0 | 137 | else: |
paul@0 | 138 | return send_headers_cls(request) |
paul@0 | 139 | |
paul@0 | 140 | def escattr(s): |
paul@0 | 141 | return wikiutil.escape(s, 1) |
paul@0 | 142 | |
paul@0 | 143 | def getPathInfo(request): |
paul@0 | 144 | if hasattr(request, "getPathinfo"): |
paul@0 | 145 | return request.getPathinfo() |
paul@0 | 146 | else: |
paul@0 | 147 | return request.path |
paul@0 | 148 | |
paul@0 | 149 | # Action support functions. |
paul@0 | 150 | |
paul@0 | 151 | def getPageRevision(page): |
paul@0 | 152 | |
paul@0 | 153 | "Return the revision details dictionary for the given 'page'." |
paul@0 | 154 | |
paul@0 | 155 | # From Page.edit_info... |
paul@0 | 156 | |
paul@0 | 157 | if hasattr(page, "editlog_entry"): |
paul@0 | 158 | line = page.editlog_entry() |
paul@0 | 159 | else: |
paul@0 | 160 | line = page._last_edited(page.request) # MoinMoin 1.5.x and 1.6.x |
paul@0 | 161 | |
paul@0 | 162 | # Similar to Page.mtime_usecs behaviour... |
paul@0 | 163 | |
paul@0 | 164 | if line: |
paul@0 | 165 | timestamp = line.ed_time_usecs |
paul@0 | 166 | mtime = wikiutil.version2timestamp(long(timestamp)) # must be long for py 2.2.x |
paul@0 | 167 | comment = line.comment |
paul@0 | 168 | else: |
paul@0 | 169 | mtime = 0 |
paul@0 | 170 | comment = "" |
paul@0 | 171 | |
paul@0 | 172 | # Leave the time zone empty. |
paul@0 | 173 | |
paul@0 | 174 | return {"timestamp" : DateTime(time.gmtime(mtime)[:6] + (None,)), "comment" : comment} |
paul@0 | 175 | |
paul@0 | 176 | # User interface functions. |
paul@0 | 177 | |
paul@0 | 178 | def getParameter(request, name, default=None): |
paul@0 | 179 | |
paul@0 | 180 | """ |
paul@0 | 181 | Using the given 'request', return the value of the parameter with the given |
paul@0 | 182 | 'name', returning the optional 'default' (or None) if no value was supplied |
paul@0 | 183 | in the 'request'. |
paul@0 | 184 | """ |
paul@0 | 185 | |
paul@0 | 186 | return get_form(request).get(name, [default])[0] |
paul@0 | 187 | |
paul@0 | 188 | def getQualifiedParameter(request, prefix, argname, default=None): |
paul@0 | 189 | |
paul@0 | 190 | """ |
paul@0 | 191 | Using the given 'request', 'prefix' and 'argname', retrieve the value of the |
paul@0 | 192 | qualified parameter, returning the optional 'default' (or None) if no value |
paul@0 | 193 | was supplied in the 'request'. |
paul@0 | 194 | """ |
paul@0 | 195 | |
paul@0 | 196 | argname = getQualifiedParameterName(prefix, argname) |
paul@0 | 197 | return getParameter(request, argname, default) |
paul@0 | 198 | |
paul@0 | 199 | def getQualifiedParameterName(prefix, argname): |
paul@0 | 200 | |
paul@0 | 201 | """ |
paul@0 | 202 | Return the qualified parameter name using the given 'prefix' and 'argname'. |
paul@0 | 203 | """ |
paul@0 | 204 | |
paul@0 | 205 | if prefix is None: |
paul@0 | 206 | return argname |
paul@0 | 207 | else: |
paul@0 | 208 | return "%s-%s" % (prefix, argname) |
paul@0 | 209 | |
paul@0 | 210 | # Page-related functions. |
paul@0 | 211 | |
paul@0 | 212 | def getPrettyPageName(page): |
paul@0 | 213 | |
paul@0 | 214 | "Return a nicely formatted title/name for the given 'page'." |
paul@0 | 215 | |
paul@0 | 216 | title = page.split_title(force=1) |
paul@0 | 217 | return getPrettyTitle(title) |
paul@0 | 218 | |
paul@0 | 219 | def linkToPage(request, page, text, query_string=None): |
paul@0 | 220 | |
paul@0 | 221 | """ |
paul@0 | 222 | Using 'request', return a link to 'page' with the given link 'text' and |
paul@0 | 223 | optional 'query_string'. |
paul@0 | 224 | """ |
paul@0 | 225 | |
paul@0 | 226 | text = wikiutil.escape(text) |
paul@0 | 227 | return page.link_to_raw(request, text, query_string) |
paul@0 | 228 | |
paul@0 | 229 | def linkToResource(url, request, text, query_string=None): |
paul@0 | 230 | |
paul@0 | 231 | """ |
paul@0 | 232 | Using 'request', return a link to 'url' with the given link 'text' and |
paul@0 | 233 | optional 'query_string'. |
paul@0 | 234 | """ |
paul@0 | 235 | |
paul@0 | 236 | if query_string: |
paul@0 | 237 | query_string = wikiutil.makeQueryString(query_string) |
paul@0 | 238 | url = "%s?%s" % (url, query_string) |
paul@0 | 239 | |
paul@0 | 240 | formatter = request.page and getattr(request.page, "formatter", None) or request.html_formatter |
paul@0 | 241 | |
paul@0 | 242 | output = [] |
paul@0 | 243 | output.append(formatter.url(1, url)) |
paul@0 | 244 | output.append(formatter.text(text)) |
paul@0 | 245 | output.append(formatter.url(0)) |
paul@0 | 246 | return "".join(output) |
paul@0 | 247 | |
paul@0 | 248 | def getFullPageName(parent, title): |
paul@0 | 249 | |
paul@0 | 250 | """ |
paul@0 | 251 | Return a full page name from the given 'parent' page (can be empty or None) |
paul@0 | 252 | and 'title' (a simple page name). |
paul@0 | 253 | """ |
paul@0 | 254 | |
paul@0 | 255 | if parent: |
paul@0 | 256 | return "%s/%s" % (parent.rstrip("/"), title) |
paul@0 | 257 | else: |
paul@0 | 258 | return title |
paul@0 | 259 | |
paul@0 | 260 | # vim: tabstop=4 expandtab shiftwidth=4 |