Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/websdk/werkzeug/contrib/kickstart.py
diff options
context:
space:
mode:
Diffstat (limited to 'websdk/werkzeug/contrib/kickstart.py')
-rw-r--r--websdk/werkzeug/contrib/kickstart.py288
1 files changed, 288 insertions, 0 deletions
diff --git a/websdk/werkzeug/contrib/kickstart.py b/websdk/werkzeug/contrib/kickstart.py
new file mode 100644
index 0000000..43c0e7c
--- /dev/null
+++ b/websdk/werkzeug/contrib/kickstart.py
@@ -0,0 +1,288 @@
+# -*- coding: utf-8 -*-
+"""
+ werkzeug.contrib.kickstart
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This module provides some simple shortcuts to make using Werkzeug simpler
+ for small scripts.
+
+ These improvements include predefined `Request` and `Response` objects as
+ well as a predefined `Application` object which can be customized in child
+ classes, of course. The `Request` and `Reponse` objects handle URL
+ generation as well as sessions via `werkzeug.contrib.sessions` and are
+ purely optional.
+
+ There is also some integration of template engines. The template loaders
+ are, of course, not neccessary to use the template engines in Werkzeug,
+ but they provide a common interface. Currently supported template engines
+ include Werkzeug's minitmpl and Genshi_. Support for other engines can be
+ added in a trivial way. These loaders provide a template interface
+ similar to the one used by Django_.
+
+ .. _Genshi: http://genshi.edgewall.org/
+ .. _Django: http://www.djangoproject.com/
+
+ :copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
+ :license: BSD, see LICENSE for more details.
+"""
+from os import path
+from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase
+from werkzeug.templates import Template
+from werkzeug.exceptions import HTTPException
+from werkzeug.routing import RequestRedirect
+
+__all__ = ['Request', 'Response', 'TemplateNotFound', 'TemplateLoader',
+ 'GenshiTemplateLoader', 'Application']
+
+from warnings import warn
+warn(DeprecationWarning('werkzeug.contrib.kickstart is deprecated and '
+ 'will be removed in Werkzeug 1.0'))
+
+
+class Request(RequestBase):
+ """A handy subclass of the base request that adds a URL builder.
+ It when supplied a session store, it is also able to handle sessions.
+ """
+
+ def __init__(self, environ, url_map,
+ session_store=None, cookie_name=None):
+ # call the parent for initialization
+ RequestBase.__init__(self, environ)
+ # create an adapter
+ self.url_adapter = url_map.bind_to_environ(environ)
+ # create all stuff for sessions
+ self.session_store = session_store
+ self.cookie_name = cookie_name
+
+ if session_store is not None and cookie_name is not None:
+ if cookie_name in self.cookies:
+ # get the session out of the storage
+ self.session = session_store.get(self.cookies[cookie_name])
+ else:
+ # create a new session
+ self.session = session_store.new()
+
+ def url_for(self, callback, **values):
+ return self.url_adapter.build(callback, values)
+
+
+class Response(ResponseBase):
+ """
+ A subclass of base response which sets the default mimetype to text/html.
+ It the `Request` that came in is using Werkzeug sessions, this class
+ takes care of saving that session.
+ """
+ default_mimetype = 'text/html'
+
+ def __call__(self, environ, start_response):
+ # get the request object
+ request = environ['werkzeug.request']
+
+ if request.session_store is not None:
+ # save the session if neccessary
+ request.session_store.save_if_modified(request.session)
+
+ # set the cookie for the browser if it is not there:
+ if request.cookie_name not in request.cookies:
+ self.set_cookie(request.cookie_name, request.session.sid)
+
+ # go on with normal response business
+ return ResponseBase.__call__(self, environ, start_response)
+
+
+class Processor(object):
+ """A request and response processor - it is what Django calls a
+ middleware, but Werkzeug also includes straight-foward support for real
+ WSGI middlewares, so another name was chosen.
+
+ The code of this processor is derived from the example in the Werkzeug
+ trac, called `Request and Response Processor
+ <http://dev.pocoo.org/projects/werkzeug/wiki/RequestResponseProcessor>`_
+ """
+
+ def process_request(self, request):
+ return request
+
+ def process_response(self, request, response):
+ return response
+
+ def process_view(self, request, view_func, view_args, view_kwargs):
+ """process_view() is called just before the Application calls the
+ function specified by view_func.
+
+ If this returns None, the Application processes the next Processor,
+ and if it returns something else (like a Response instance), that
+ will be returned without any further processing.
+ """
+ return None
+
+ def process_exception(self, request, exception):
+ return None
+
+
+class Application(object):
+ """A generic WSGI application which can be used to start with Werkzeug in
+ an easy, straightforward way.
+ """
+
+ def __init__(self, name, url_map, session=False, processors=None):
+ # save the name and the URL-map, as it'll be needed later on
+ self.name = name
+ self.url_map = url_map
+ # save the list of processors if supplied
+ self.processors = processors or []
+ # create an instance of the storage
+ if session:
+ self.store = session
+ else:
+ self.store = None
+
+ def __call__(self, environ, start_response):
+ # create a request - with or without session support
+ if self.store is not None:
+ request = Request(environ, self.url_map,
+ session_store=self.store, cookie_name='%s_sid' % self.name)
+ else:
+ request = Request(environ, self.url_map)
+
+ # apply the request processors
+ for processor in self.processors:
+ request = processor.process_request(request)
+
+ try:
+ # find the callback to which the URL is mapped
+ callback, args = request.url_adapter.match(request.path)
+ except (HTTPException, RequestRedirect), e:
+ response = e
+ else:
+ # check all view processors
+ for processor in self.processors:
+ action = processor.process_view(request, callback, (), args)
+ if action is not None:
+ # it is overriding the default behaviour, this is
+ # short-circuiting the processing, so it returns here
+ return action(environ, start_response)
+
+ try:
+ response = callback(request, **args)
+ except Exception, exception:
+ # the callback raised some exception, need to process that
+ for processor in reversed(self.processors):
+ # filter it through the exception processor
+ action = processor.process_exception(request, exception)
+ if action is not None:
+ # the exception processor returned some action
+ return action(environ, start_response)
+ # still not handled by a exception processor, so re-raise
+ raise
+
+ # apply the response processors
+ for processor in reversed(self.processors):
+ response = processor.process_response(request, response)
+
+ # return the completely processed response
+ return response(environ, start_response)
+
+
+ def config_session(self, store, expiration='session'):
+ """
+ Configures the setting for cookies. You can also disable cookies by
+ setting store to None.
+ """
+ self.store = store
+ # expiration=session is the default anyway
+ # TODO: add settings to define the expiration date, the domain, the
+ # path any maybe the secure parameter.
+
+
+class TemplateNotFound(IOError, LookupError):
+ """
+ A template was not found by the template loader.
+ """
+
+ def __init__(self, name):
+ IOError.__init__(self, name)
+ self.name = name
+
+
+class TemplateLoader(object):
+ """
+ A simple loader interface for the werkzeug minitmpl
+ template language.
+ """
+
+ def __init__(self, search_path, encoding='utf-8'):
+ self.search_path = path.abspath(search_path)
+ self.encoding = encoding
+
+ def get_template(self, name):
+ """Get a template from a given name."""
+ filename = path.join(self.search_path, *[p for p in name.split('/')
+ if p and p[0] != '.'])
+ if not path.exists(filename):
+ raise TemplateNotFound(name)
+ return Template.from_file(filename, self.encoding)
+
+ def render_to_response(self, *args, **kwargs):
+ """Load and render a template into a response object."""
+ return Response(self.render_to_string(*args, **kwargs))
+
+ def render_to_string(self, *args, **kwargs):
+ """Load and render a template into a unicode string."""
+ try:
+ template_name, args = args[0], args[1:]
+ except IndexError:
+ raise TypeError('name of template required')
+ return self.get_template(template_name).render(*args, **kwargs)
+
+
+class GenshiTemplateLoader(TemplateLoader):
+ """A unified interface for loading Genshi templates. Actually a quite thin
+ wrapper for Genshi's TemplateLoader.
+
+ It sets some defaults that differ from the Genshi loader, most notably
+ auto_reload is active. All imporant options can be passed through to
+ Genshi.
+ The default output type is 'html', but can be adjusted easily by changing
+ the `output_type` attribute.
+ """
+ def __init__(self, search_path, encoding='utf-8', **kwargs):
+ TemplateLoader.__init__(self, search_path, encoding)
+ # import Genshi here, because we don't want a general Genshi
+ # dependency, only a local one
+ from genshi.template import TemplateLoader as GenshiLoader
+ from genshi.template.loader import TemplateNotFound
+
+ self.not_found_exception = TemplateNotFound
+ # set auto_reload to True per default
+ reload_template = kwargs.pop('auto_reload', True)
+ # get rid of default_encoding as this template loaders overwrites it
+ # with the value of encoding
+ kwargs.pop('default_encoding', None)
+
+ # now, all arguments are clean, pass them on
+ self.loader = GenshiLoader(search_path, default_encoding=encoding,
+ auto_reload=reload_template, **kwargs)
+
+ # the default output is HTML but can be overridden easily
+ self.output_type = 'html'
+ self.encoding = encoding
+
+ def get_template(self, template_name):
+ """Get the template which is at the given name"""
+ try:
+ return self.loader.load(template_name, encoding=self.encoding)
+ except self.not_found_exception, e:
+ # catch the exception raised by Genshi, convert it into a werkzeug
+ # exception (for the sake of consistency)
+ raise TemplateNotFound(template_name)
+
+ def render_to_string(self, template_name, context=None):
+ """Load and render a template into an unicode string"""
+ # create an empty context if no context was specified
+ context = context or {}
+ tmpl = self.get_template(template_name)
+ # render the template into a unicode string (None means unicode)
+ return tmpl. \
+ generate(**context). \
+ render(self.output_type, encoding=None)