source: package_branches/invirt-web/cherrypy-rebased/code/view.py @ 2723

Last change on this file since 2723 was 2723, checked in by broder, 14 years ago

view.py: double blank lines at toplevel

This is a style convention that makes it easier to see where one
definition ends and the next begins. It's particularly necessary
in this file, because it can separate the CherryPy? glue associated
with one function from the unrelated function below it.

File size: 5.6 KB
RevLine 
[2693]1import os, sys
[2659]2
3import cherrypy
4from mako.template import Template
5from mako.lookup import TemplateLookup
6import simplejson
7import datetime, decimal
[2693]8from StringIO import StringIO
[2669]9from invirt.config import structs as config
10from webcommon import State
[2659]11
[2723]12
[2659]13class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
[2721]14    """Callable which processes a dictionary, returning the rendered body."""
[2659]15   
16    def __init__(self, template, next_handler, content_type='text/html; charset=utf-8'):
17        self.template = template
18        self.next_handler = next_handler
19        self.content_type = content_type
20   
21    def __call__(self):
22        env = globals().copy()
23        env.update(self.next_handler())
24        cherrypy.response.headers['Content-Type'] = self.content_type
25        return self.template.render(**env)
26       
27
28class MakoLoader(object):
29   
30    def __init__(self):
31        self.lookups = {}
[2693]32
33    def get_lookup(self, directories, module_directory=None,
34                     collection_size=-1, imports=[], **kwargs):
[2659]35        # Find the appropriate template lookup.
36        key = (tuple(directories), module_directory)
37        try:
38            lookup = self.lookups[key]
39        except KeyError:
40            lookup = TemplateLookup(directories=directories,
41                                    module_directory=module_directory,
42                                    collection_size=collection_size,
43                                    default_filters=['decode.utf8'],
44                                    input_encoding='utf-8',
45                                    output_encoding='utf-8',
[2673]46                                    imports=imports,
[2659]47                                    )
48            self.lookups[key] = lookup
[2693]49        return lookup
50
51    def __call__(self, filename, directories, module_directory=None,
52                 collection_size=-1, content_type='text/html; charset=utf-8',
53                 imports=[]):
54        cherrypy.request.lookup = lookup = self.get_lookup(directories, module_directory,
55                                                           collection_size, imports)
[2659]56        cherrypy.request.template = t = lookup.get_template(filename)
57        cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler, content_type)
58
[2699]59cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
[2659]60
[2723]61
[2693]62def revertStandardError():
63    """Move stderr to stdout, and return the contents of the old stderr."""
64    errio = sys.stderr
65    if not isinstance(errio, StringIO):
66        return ''
67    sys.stderr = sys.stdout
68    errio.seek(0)
69    return errio.read()
70
[2723]71
[2693]72def catchStderr():
73    old_handler = cherrypy.request.handler
74    def wrapper(*args, **kwargs):
75        sys.stderr = StringIO()
76        ret = old_handler(*args, **kwargs)
77        e = revertStandardError()
78        if e:
79            if isinstance(ret, dict):
80                ret["error_text"] = e
81        return ret
82    if old_handler:
83        cherrypy.request.handler = wrapper
84
85cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
86
[2723]87
[2659]88class JSONEncoder(simplejson.JSONEncoder):
89        def default(self, obj):
90                if isinstance(obj, datetime.datetime):
91                        return str(obj)
92                elif isinstance(obj, decimal.Decimal):
93                        return float(obj)
94                else:
95                        return simplejson.JSONEncoder.default(self, obj)
96
[2723]97
[2659]98def jsonify_tool_callback(*args, **kwargs):
99    if not cherrypy.request.cached:
100        response = cherrypy.response
101        response.headers['Content-Type'] = 'text/javascript'
102        response.body = JSONEncoder().iterencode(response.body)
103
104cherrypy.tools.jsonify = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
105
[2723]106
[2665]107def require_login():
108    """If the user isn't logged in, raise 403 with an error."""
[2712]109    if cherrypy.request.login is False:
[2665]110        raise cherrypy.HTTPError(403,
111            "You are not authorized to access that resource")
112
[2670]113cherrypy.tools.require_login = cherrypy.Tool('on_start_resource', require_login, priority=150)
[2665]114
[2723]115
[2685]116def require_POST():
117    """If the request isn't a POST request, raise 405 Method Not Allowed"""
118    if cherrypy.request.method != "POST":
119        raise cherrypy.HTTPError(405,
120                                 "You must submit this request with POST")
121
122cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource', require_POST, priority=150)
123
[2723]124
[2670]125def remote_user_login():
[2722]126    """Get remote user from SSL or GSSAPI, and store in request object.
[2712]127
[2722]128Get the current user based on environment variables set by SSL or
129GSSAPI, and store it in the attribute cherrpy.request.login.
130
131Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
132the attribute is set to the username on successful login, to False on
133failed login, and is left at None if the user attempted no authentication.
134"""
[2670]135    environ = cherrypy.request.wsgi_environ
136    user = environ.get('REMOTE_USER')
137    if user is None:
138        return
139    if environ.get('AUTH_TYPE') == 'Negotiate':
140        # Convert the krb5 principal into a krb4 username
141        if not user.endswith('@%s' % config.kerberos.realm):
[2722]142            cherrypy.request.login = False # failed to log in
[2670]143        else:
144            cherrypy.request.login = user.split('@')[0].replace('/', '.')
145    else:
146        cherrypy.request.login = user
147
148cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
149
[2723]150
[2669]151def invirtwebstate_init():
152    """Initialize the cherrypy.request.state object from Invirt"""
[2690]153    if not hasattr(cherrypy.request, "state"):
154        cherrypy.request.state = State(cherrypy.request.login)
[2669]155
156cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
157
[2723]158
[2659]159class View(object):
160    _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}
Note: See TracBrowser for help on using the repository browser.