1.1 --- a/EventAggregatorSupport.py Sun Feb 06 02:38:17 2011 +0100
1.2 +++ b/EventAggregatorSupport.py Sat Feb 19 03:06:03 2011 +0100
1.3 @@ -31,7 +31,7 @@
1.4 def escattr(s):
1.5 return escape(s, 1)
1.6
1.7 -__version__ = "0.6.1"
1.8 +__version__ = "0.6.2"
1.9
1.10 # Date labels.
1.11
1.12 @@ -80,9 +80,6 @@
1.13
1.14 # Utility functions.
1.15
1.16 -def isMoin15():
1.17 - return version.release.startswith("1.5.")
1.18 -
1.19 def getCategoryPattern(request):
1.20 global category_regexp
1.21
1.22 @@ -102,6 +99,147 @@
1.23 else:
1.24 return int(x)
1.25
1.26 +def sort_none_first(x, y):
1.27 + if x is None:
1.28 + return -1
1.29 + elif y is None:
1.30 + return 1
1.31 + else:
1.32 + return cmp(x, y)
1.33 +
1.34 +# Utility classes and associated functions.
1.35 +
1.36 +class Form:
1.37 +
1.38 + """
1.39 + A wrapper preserving MoinMoin 1.8.x (and earlier) behaviour in a 1.9.x
1.40 + environment.
1.41 + """
1.42 +
1.43 + def __init__(self, form):
1.44 + self.form = form
1.45 +
1.46 + def get(self, name, default=None):
1.47 + values = self.form.getlist(name)
1.48 + if not values:
1.49 + return default
1.50 + else:
1.51 + return values
1.52 +
1.53 + def __getitem__(self, name):
1.54 + return self.form.getlist(name)
1.55 +
1.56 +class ActionSupport:
1.57 +
1.58 + """
1.59 + Work around disruptive MoinMoin changes in 1.9, and also provide useful
1.60 + convenience methods.
1.61 + """
1.62 +
1.63 + def get_form(self):
1.64 + return get_form(self.request)
1.65 +
1.66 + def _get_selected(self, value, input_value):
1.67 +
1.68 + """
1.69 + Return the HTML attribute text indicating selection of an option (or
1.70 + otherwise) if 'value' matches 'input_value'.
1.71 + """
1.72 +
1.73 + return input_value is not None and value == input_value and 'selected="selected"' or ''
1.74 +
1.75 + def _get_selected_for_list(self, value, input_values):
1.76 +
1.77 + """
1.78 + Return the HTML attribute text indicating selection of an option (or
1.79 + otherwise) if 'value' matches one of the 'input_values'.
1.80 + """
1.81 +
1.82 + return value in input_values and 'selected="selected"' or ''
1.83 +
1.84 + def _get_input(self, form, name, default=None):
1.85 +
1.86 + """
1.87 + Return the input from 'form' having the given 'name', returning either
1.88 + the input converted to an integer or the given 'default' (optional, None
1.89 + if not specified).
1.90 + """
1.91 +
1.92 + value = form.get(name, [None])[0]
1.93 + if not value: # true if 0 obtained
1.94 + return default
1.95 + else:
1.96 + return int(value)
1.97 +
1.98 + def get_month_lists(self, default_as_current=0):
1.99 +
1.100 + """
1.101 + Return two lists of HTML element definitions corresponding to the start
1.102 + and end month selection controls, with months selected according to any
1.103 + values that have been specified via request parameters.
1.104 + """
1.105 +
1.106 + _ = self._
1.107 + form = self.get_form()
1.108 +
1.109 + # Initialise month lists.
1.110 +
1.111 + start_month_list = []
1.112 + end_month_list = []
1.113 +
1.114 + start_month = self._get_input(form, "start-month", default_as_current and getCurrentMonth().month() or None)
1.115 + end_month = self._get_input(form, "end-month", start_month)
1.116 +
1.117 + # Prepare month lists, selecting specified months.
1.118 +
1.119 + if not default_as_current:
1.120 + start_month_list.append('<option value=""></option>')
1.121 + end_month_list.append('<option value=""></option>')
1.122 +
1.123 + for month in range(1, 13):
1.124 + month_label = _(getMonthLabel(month))
1.125 + selected = self._get_selected(month, start_month)
1.126 + start_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label))
1.127 + selected = self._get_selected(month, end_month)
1.128 + end_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label))
1.129 +
1.130 + return start_month_list, end_month_list
1.131 +
1.132 + def get_year_defaults(self, default_as_current=0):
1.133 +
1.134 + "Return defaults for the start and end years."
1.135 +
1.136 + form = self.get_form()
1.137 +
1.138 + start_year_default = form.get("start-year", [default_as_current and getCurrentYear() or ""])[0]
1.139 + end_year_default = form.get("end-year", [default_as_current and start_year_default or ""])[0]
1.140 +
1.141 + return start_year_default, end_year_default
1.142 +
1.143 +def get_form(request):
1.144 +
1.145 + "Work around disruptive MoinMoin changes in 1.9."
1.146 +
1.147 + if hasattr(request, "values"):
1.148 + return Form(request.values)
1.149 + else:
1.150 + return request.form
1.151 +
1.152 +class send_headers:
1.153 +
1.154 + """
1.155 + A wrapper to preserve MoinMoin 1.8.x (and earlier) request behaviour in a
1.156 + 1.9.x environment.
1.157 + """
1.158 +
1.159 + def __init__(self, request):
1.160 + self.request = request
1.161 +
1.162 + def __call__(self, headers):
1.163 + for header in headers:
1.164 + parts = header.split(":")
1.165 + self.request.headers.add(parts[0], ":".join(parts[1:]))
1.166 +
1.167 # Textual representations.
1.168
1.169 def getHTTPTimeString(tmtuple):
1.170 @@ -214,11 +352,7 @@
1.171 """
1.172
1.173 query = search.QueryParser().parse_query('category:%s' % pagename)
1.174 - if isMoin15():
1.175 - results = search.searchPages(request, query)
1.176 - results.sortByPagename()
1.177 - else:
1.178 - results = search.searchPages(request, query, "page_name")
1.179 + results = search.searchPages(request, query, "page_name")
1.180
1.181 cat_pattern = getCategoryPattern(request)
1.182 pages = []
1.183 @@ -249,21 +383,13 @@
1.184
1.185 "Using 'request', return the URL of this page."
1.186
1.187 - page = self.page
1.188 -
1.189 - if isMoin15():
1.190 - return request.getQualifiedURL(page.url(request))
1.191 - else:
1.192 - return request.getQualifiedURL(page.url(request, relative=0))
1.193 + return request.getQualifiedURL(self.page.url(request, relative=0))
1.194
1.195 def getFormat(self):
1.196
1.197 "Get the format used on this page."
1.198
1.199 - if isMoin15():
1.200 - return "wiki" # page.pi_format
1.201 - else:
1.202 - return self.page.pi["format"]
1.203 + return self.page.pi["format"]
1.204
1.205 def getRevisions(self):
1.206
1.207 @@ -658,7 +784,7 @@
1.208 Using 'request', set timestamp details in the details dictionary of each of
1.209 the 'events'.
1.210
1.211 - Retutn the latest timestamp found.
1.212 + Return the latest timestamp found.
1.213 """
1.214
1.215 latest = None
1.216 @@ -728,6 +854,10 @@
1.217
1.218 return min(first, last), last
1.219
1.220 +# NOTE: Support coverage using times within days. This will involve timespan
1.221 +# NOTE: objects which can be compared in such a way that set operations will be
1.222 +# NOTE: able to detect overlapping periods.
1.223 +
1.224 def getCoverage(start, end, events):
1.225
1.226 """
1.227 @@ -737,7 +867,7 @@
1.228 of the form (set of covered days, events).
1.229 """
1.230
1.231 - all_events = []
1.232 + all_events = {}
1.233 full_coverage = set()
1.234
1.235 # Get event details.
1.236 @@ -754,28 +884,39 @@
1.237 event_start = max(event_details["start"], start)
1.238 event_end = min(event_details["end"], end)
1.239 event_coverage = set(event_start.days_until(event_end))
1.240 + event_location = event_details.get("location")
1.241
1.242 # Update the overall coverage.
1.243
1.244 full_coverage.update(event_coverage)
1.245
1.246 - # Try and fit the event into the events list.
1.247 -
1.248 - for i, (coverage, covered_events) in enumerate(all_events):
1.249 -
1.250 - # Where the event does not overlap with the current
1.251 - # element, add it alongside existing events.
1.252 + # Add a new events list for a new location.
1.253 + # Locations can be unspecified, thus None refers to all unlocalised
1.254 + # events.
1.255
1.256 - if not coverage.intersection(event_coverage):
1.257 - covered_events.append(event)
1.258 - all_events[i] = coverage.union(event_coverage), covered_events
1.259 - break
1.260 + if not all_events.has_key(event_location):
1.261 + all_events[event_location] = [(event_coverage, [event])]
1.262
1.263 - # Make a new element in the list if the event cannot be
1.264 - # marked alongside existing events.
1.265 + # Try and fit the event into an events list.
1.266
1.267 else:
1.268 - all_events.append((event_coverage, [event]))
1.269 + slot = all_events[event_location]
1.270 +
1.271 + for i, (coverage, covered_events) in enumerate(slot):
1.272 +
1.273 + # Where the event does not overlap with the current
1.274 + # element, add it alongside existing events.
1.275 +
1.276 + if not coverage.intersection(event_coverage):
1.277 + covered_events.append(event)
1.278 + slot[i] = coverage.union(event_coverage), covered_events
1.279 + break
1.280 +
1.281 + # Make a new element in the list if the event cannot be
1.282 + # marked alongside existing events.
1.283 +
1.284 + else:
1.285 + slot.append((event_coverage, [event]))
1.286
1.287 return full_coverage, all_events
1.288
1.289 @@ -1251,7 +1392,7 @@
1.290 in the 'request'.
1.291 """
1.292
1.293 - return request.form.get(name, [default])[0]
1.294 + return get_form(request).get(name, [default])[0]
1.295
1.296 def getQualifiedParameter(request, calendar_name, argname, default=None):
1.297
1.298 @@ -1333,17 +1474,25 @@
1.299 else:
1.300 return None
1.301
1.302 +def getFullMonthLabel(request, year_month):
1.303 +
1.304 + """
1.305 + Return the full month plus year label using the given 'request' and
1.306 + 'year_month'.
1.307 + """
1.308 +
1.309 + _ = request.getText
1.310 + year, month = year_month.as_tuple()
1.311 + month_label = _(getMonthLabel(month))
1.312 + return "%s %s" % (month_label, year)
1.313 +
1.314 # Page-related functions.
1.315
1.316 def getPrettyPageName(page):
1.317
1.318 "Return a nicely formatted title/name for the given 'page'."
1.319
1.320 - if isMoin15():
1.321 - title = page.split_title(page.request, force=1)
1.322 - else:
1.323 - title = page.split_title(force=1)
1.324 -
1.325 + title = page.split_title(force=1)
1.326 return getPrettyTitle(title)
1.327
1.328 def linkToPage(request, page, text, query_string=None):
1.329 @@ -1354,14 +1503,7 @@
1.330 """
1.331
1.332 text = wikiutil.escape(text)
1.333 -
1.334 - if isMoin15():
1.335 - url = wikiutil.quoteWikinameURL(page.page_name)
1.336 - if query_string is not None:
1.337 - url = "%s?%s" % (url, query_string)
1.338 - return wikiutil.link_tag(request, url, text, getattr(page, "formatter", None))
1.339 - else:
1.340 - return page.link_to_raw(request, text, query_string)
1.341 + return page.link_to_raw(request, text, query_string)
1.342
1.343 def getFullPageName(parent, title):
1.344