view taginthemiddle/handlers.py @ 17:c85d42296c06

make the model almost be real
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 24 May 2010 07:44:39 -0700
parents 5f492a6fbdd1
children
line wrap: on
line source

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

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 GenshiHandler(Handler):

    def __init__(self, app, request):
        Handler.__init__(self, app, request)
        self.data = { 'request': request,
                      'link': self.link }

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

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

class TagCloud(GenshiHandler):
    template = 'cloud.html'
    methods = set(['GET'])

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

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

        # check the path
        if request.path_info.endswith('/%s' % app.tags_url):
            try:
                return cls(app, request)
            except HandlerMatchException:
                return None


class ViewTags(GenshiHandler):
    """
    View for tags on a resource;  for app.tags_url == 'tags':

    /<resource>/tags/mozilla :
    all paths under /<resource> tagged with 'mozilla'

    /<resource>/tags/mozilla+workflow :
    all paths under /<resource> tagged with 'mozilla' and 'workflow'
    (or should it be /<resource>/tags/mozilla/workflow , which would be
    identical to /<resource>/tags/workflow/mozilla ?)

    Also handles RSS:
    /<resource>/tags/mozilla?format=rss

    Maybe this takes care of the TagCloud too?  And/or view as most recent?
    """
    
    template = 'tags.html'
    methods = set(['GET'])

    def __init__(self, app, request):
        GenshiHandler.__init__(self, app, request)
        path = request.path_info.split('/')
        try:
            index = path.index(app.tags_url)
        except ValueError:
            raise HandlerMatchException
        self.tags = path[index+1:]
        if not self.tags:
            raise HandlerMatchException
        self.data['tags'] = self.tags

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

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

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

    def Get(self):
        if self.request.GET.get('format') == 'rss':
            pass # TODO
        return GenshiHandler.Get(self)

class PostTags(Handler):
    methods = set(['POST'])

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

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

        # check auth
        if not request.remote_user:
            return None

        # check the path
        if request.path_info.endswith('/%s' % app.post_url):
            try:
                return cls(app, request)
            except HandlerMatchException:
                return None

    def __call__(self):

        # get the url
        url = self.request.path_info.rsplit('/' + self.app.post_url, 1)[0]

        # add and remove tags
        # TODO

        # redirect to original resource
        return exc.HTTPSeeOther(location=url)