handlers.py
author Tero Marttila <terom@fixme.fi>
Wed, 11 Feb 2009 03:04:35 +0200
changeset 96 d30c88e89a7e
parent 87 39915772f090
child 108 d0aca7894fc5
permissions -rw-r--r--
move the LogSearchIndex open from handlers to log_search, and make it lazy
"""
    Our URL action handlers
"""

import datetime, calendar, pytz

from qmsk.web import http, template

import urls, channels, helpers
import preferences as prefs
from preferences import preferences
import config, log_search

# load templates from here
templates = template.TemplateLoader("templates",
    _helper_class   = helpers.Helpers,
    urls            = urls,
    channel_list    = config.LOG_CHANNELS,
    config          = config,
)

def index (request) :
    """
        The topmost index page, display a list of available channels, perhaps some general stats
    """
    
    return templates.render_to_response("index",
        req             = request,
    )

# XXX: fix this namespace crap
@preferences.handler()
def preferences_ (request) :
    """
        Preferences editor
    """

    # POST?
    if request.is_post() :
        # update any modified preferences
        for pref in preferences.pref_list :
            # get+parse new POST'd value
            # XXX: this doesn't postprocess
            new_value = pref.parse(request.get_post(pref.name))

            # update if changed
            if new_value != request.prefs[pref] :
                request.prefs.set(pref.name, new_value)

    # render
    return templates.render_to_response("preferences",
        req             = request,
        prefs           = request.prefs,
        preferences     = prefs,
        timezones       = pytz.common_timezones,
    )

def channel_select (request, channel) :
    """
        Redirect to the appropriate channel_view
    """
   
    return http.Redirect(urls.channel.build(request, channel=channel))

@preferences.handler(prefs.formatter)
def channel_last (request, channel, count, formatter, type=None) :
    """
        The main channel view page, displaying the most recent lines
    """
 
    # get latest events
    lines = channel.source.get_latest(count)
   
    # we can render in various modes...
    if not type :
        # normal HTML
        lines = formatter.format_html(lines)

        return templates.render_to_response("channel_last",
            req             = request,
            prefs           = request.prefs,
            channel         = channel,
            count           = count,
            lines           = lines,
        )
    
    elif type == 'txt' :
        # plaintext
        lines = formatter.format_txt(lines)

        # build data
        data = '\n'.join(data for line, data in lines)

        return http.Response(data, 'text/plain')

    elif type == 'png' :
        # PNG image
        png_data = formatter.format_png(lines)

        return http.Response(png_data, 'image/png', charset=None)
    
    elif type == 'rss' :
        # RSS feed
        rss_data = formatter.format_rss(lines)

        return http.Response(rss_data, 'application/rss+xml')

    else :
        raise http.ResponseError("Unrecognized type: %r" % (type, ))

@preferences.handler(prefs.formatter, prefs.timezone, prefs.count)
def channel_link (request, channel, timestamp, formatter, timezone, count) :
    """
        Display channel_date for specific UTC timestamp
    """

    # convert timestamp to user's timezone
    timestamp = timestamp.astimezone(timezone)

    # get correct day's correct page of lines
    page, max, lines = channel.source.get_date_paged(timestamp, count)

    # lines
    lines = formatter.format_html(lines)

    # render
    return templates.render_to_response("channel_date",
        req             = request,
        prefs           = request.prefs,
        channel         = channel,
        date            = timestamp,
        page            = page,
        count           = count,
        max             = max,
        lines           = lines,
    )

@preferences.handler(prefs.timezone)
def channel_calendar (request, channel, year, month, timezone) :
    """
        Display a list of avilable logs for some month
    """

    # current date as default
    now = timezone.localize(datetime.datetime.now())

    # target year/month
    target = timezone.localize(datetime.datetime(
        year    = year if year else now.year,
        month   = month if month else now.month,
        day     = 1
    ))

    # get set of days available
    days = set(channel.source.get_month_days(target))

    # display calendar
    return templates.render_to_response("channel_calendar",
        req             = request,
        prefs           = request.prefs,
        channel         = channel,
        calendar        = calendar.Calendar(),
        month           = target.date(),
        days            = days,
    )

@preferences.handler(prefs.formatter, prefs.timezone, prefs.count)
def channel_date (request, channel, date, formatter, timezone, count, page=1) :
    """
        Display all log data for the given date
    """

    # fix date timezone
    date = date.replace(tzinfo=timezone)

    # get that day's events, either paged or not
    if page :
        page, max, lines = channel.source.get_date_paged(date, count, page)
        
    else :
        lines = channel.source.get_date(date)
        max = None

    # lines
    lines = formatter.format_html(lines)

    # render
    return templates.render_to_response("channel_date",
        req             = request,
        prefs           = request.prefs,
        channel         = channel,
        date            = date,
        page            = page,
        count           = count,
        max             = max,
        lines           = lines,
    )

@preferences.handler(prefs.formatter, prefs.count)
def channel_search (request, channel, formatter, count, q=None, page=1, max=1) :
    """
        Display the search form for the channel for GET, or do the search for POST.
    """

    # calculate skip offset from page/count
    skip = (page - 1) * count

    # got a search query?
    if q :
        try :
            # do search
            lines = log_search.get_index().search_simple(channel, q, count, skip)

            # update max?
            if max and page > max :
                max = page
        
        except log_search.NoResultsFound :
            # no lines
            lines = None

        else :
            # format
            lines = formatter.format_html(lines, full_timestamps=True)

    else :
        lines = None
    
    # render
    return templates.render_to_response("channel_search",
        req             = request,
        prefs           = request.prefs,
        channel         = channel,
        search_query    = q,
        count           = count,
        page            = page,
        skip            = skip,
        max             = max,
        lines           = lines,
    )