view simplewiki/handlers.py @ 3:56ab6b90cd1a

[mq]: post
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 07 Sep 2010 21:29:57 -0700
parents 2464e2051b78
children dd1c4916cbcd
line wrap: on
line source

"""
request handlers:
these are instantiated for every request, then called
"""

import os
from urlparse import urlparse
from webob import Response, exc

class HandlerMatchException(Exception):
    """the handler doesn't match the request"""

class Handler(object):

    methods = set(['GET']) # methods to listen to
    handler_path = [] # path elements to match        

    @classmethod
    def match(cls, app, request):

        # check the method
        if request.method not in cls.methods:
            return None

        # check the path
        if request.environ['path'][:len(cls.handler_path)] != cls.handler_path:
            return None

        try:
            return cls(app, request)
        except HandlerMatchException:
            return None
    
    def __init__(self, app, request):
        self.app = app
        self.request = request
        self.application_path = urlparse(request.application_url)[2]

    def link(self, path=(), permanant=False):
        if isinstance(path, basestring):
            path = [ path ]
        path = [ i.strip('/') for i in path ]
        if permanant:
            application_url = [ self.request.application_url ]
        else:
            application_url = [ self.application_path ]
        path = application_url + path
        return '/'.join(path)

    def redirect(self, location):
        raise exc.HTTPSeeOther(location=location)

class GenshiRenderer(Handler):

    @classmethod
    def match(cls, app, request):

        # check the method
        if request.method not in cls.methods:
            return None

        # check the path
        path = request.environ['path']
        if not path:
            return None
        if not path[-1].endswith('.html'):
            return None

        
        try:
            return cls(app, request)
        except HandlerMatchException:
            return None

    def __init__(self, app, request):
        Handler.__init__(self, app, request)
        self.template = os.path.join(app.directory, *request.environ['path'])
        if not os.path.exists(self.template):
            raise HandlerMatchException
        self.data = { 'request': request,
                      'link': self.link }

    def __call__(self):
        return getattr(self, self.request.method.title())()

    def Get(self):
        template = self.app.loader.load(self.template)
        return Response(content_type='text/html',
                        body=template.generate(**self.data).render('html'))


class Index(Handler):

    template = 'index.html'

    def __init__(self, app, request):
        Handler.__init__(self, app, request)
        self.directory = os.path.join(app.directory, *request.environ['path'])
        if not os.path.isdir(self.directory):
            raise HandlerMatchException
        path = request.environ['path']
        files = []
        files = os.listdir(self.directory)
        self.data = { 'request': request,
                      'link': self.link,
                      'directory': '/' + '/'.join(path),
                      'files': files }

    def __call__(self):
        return getattr(self, self.request.method.title())()

    def Get(self):
        if not self.request.path_info.endswith('/'):
            self.redirect(self.request.path_info + '/')
        template = self.app.loader.load(self.template)
        return Response(content_type='text/html',
                        body=template.generate(**self.data).render('html'))

class Post(Handler):
    methods = set(['POST']) # methods to listen to

    def __init__(self, app, request):
        Handler.__init__(self, app, request)
        if 'file' not in request.POST:
            raise HandlerMatchException
        self.file = self.request.POST['file']
        if not getattr(self.file, 'filename', None):
            raise HandlerMatchException
        self.location = request.path_info.rstrip('/')
        path = os.path.join(self.app.directory, *self.request.environ['path'])
        if os.path.isdir(path):
            self.directory = path
            self.filename = os.path.join(self.directory, self.file.filename)
            self.location += '/' + self.file.filename
        else:
            self.directory = os.path.dirname(path)
            self.filename = path
        
        f = file(self.filename, 'wb')
        f.write(self.file.file.read())
        f.close()
        
    def __call__(self):
        self.redirect(self.location)