# -*- coding: utf-8 -*- """ simplewiki.utils ~~~~~~~~~~~~~~~~ This module implements various utility functions and classes used all over the application. :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details. :license: BSD. """ import difflib import creoleparser from os import path from genshi import Stream from genshi.template import TemplateLoader from werkzeug import BaseRequest, BaseResponse, Local, LocalManager, \ url_encode, url_quote, redirect, cached_property # calculate the path to the templates an create the template loader TEMPLATE_PATH = path.join(path.dirname(__file__), 'templates') template_loader = TemplateLoader(TEMPLATE_PATH, auto_reload=True, variable_lookup='lenient') # context locals. these two objects are use by the application to # bind objects to the current context. A context is defined as the # current thread and the current greenlet if there is greenlet support. local = Local() local_manager = LocalManager([local]) request = local('request') application = local('application') # create a new creole parser creole_parser = creoleparser.Parser( dialect=creoleparser.create_dialect(creoleparser.creole10_base, wiki_links_base_url='', wiki_links_path_func=lambda page_name: href(page_name), wiki_links_space_char='_', no_wiki_monospace=True ), method='html' ) def generate_template(template_name, **context): """Load and generate a template.""" context.update( href=href, format_datetime=format_datetime ) return template_loader.load(template_name).generate(**context) def parse_creole(markup): """Parse some creole markup and create a genshi stream.""" return creole_parser.generate(markup) def href(*args, **kw): """ Simple function for URL generation. Position arguments are used for the URL path and keyword arguments are used for the url parameters. """ result = [(request and request.script_root or '') + '/'] for idx, arg in enumerate(args): result.append((idx and '/' or '') + url_quote(arg)) if kw: result.append('?' + url_encode(kw)) return ''.join(result) def format_datetime(obj): """Format a datetime object.""" return obj.strftime('%Y-%m-%d %H:%M') class Request(BaseRequest): """ Simple request subclass that allows to bind the object to the current context. """ def bind_to_context(self): local.request = self class Response(BaseResponse): """ Encapsulates a WSGI response. Unlike the default response object werkzeug provides, this accepts a genshi stream and will automatically render it to html. This makes it possible to switch to xhtml or html5 easily. """ default_mimetype = 'text/html' def __init__(self, response=None, status=200, headers=None, mimetype=None, content_type=None): if isinstance(response, Stream): response = response.render('html', encoding=None, doctype='html') BaseResponse.__init__(self, response, status, headers, mimetype, content_type) class Pagination(object): """ Paginate a SQLAlchemy query object. """ def __init__(self, query, per_page, page, link): self.query = query self.per_page = per_page self.page = page self.link = link self._count = None @cached_property def entries(self): return self.query.offset((self.page - 1) * self.per_page) \ .limit(self.per_page).all() @property def has_previous(self): return self.page > 1 @property def has_next(self): return self.page < self.pages @property def previous(self): return href(self.link, page=self.page - 1) @property def next(self): return href(self.link, page=self.page + 1) @cached_property def count(self): return self.query.count() @property def pages(self): return max(0, self.count - 1) // self.per_page + 1