lib/loaders.py
author Tero Marttila <terom@fixme.fi>
Fri, 06 Feb 2009 20:49:29 +0200
changeset 6 5565d94da522
parent 5 site/loaders.py@9ed4c7d2bdd2
permissions -rw-r--r--
start breaking everything

from __future__ import with_statement

# XXX: for _HTMLPage
import page
import templates

from pages import error404

import os.path
import imp

# the page dir
PAGE_DIR_PATH = "pages/"

def build_page_path (*bits) :
    # XXX: fix directory traversal...
    
    return os.path.join(PAGE_DIR_PATH, *bits)

class PageLoader (object) :
    """
        Load Page objects from files under pages/
    """
    
    # file extension, e.g. '.html' or '.py'
    suffix = None

    def __init__ (self, suffix) :
        self.suffix = suffix
        
    def _build_path (self, page_path) :
        """
            Builds a path from base_path + page_path + suffix. Returns None if the path does not exist
        """
        
        path = build_page_path(page_path) + self.suffix

        if os.path.exists(path) :
            return path

        else :
            return None

    def load (self, page_path) :
        """
            Attempts to load the page at the given path, returns the class on success, None on failure
        """
        
        abstract

class _HTMLPage (page.Page) :
    # the path to the .html file
    file_path = None
    
    # parent page
    # parent = None

    def __init__ (self, *args) :
        super(_HTMLPage, self).__init__(*args)

        # open the .html and read in the contents
        with open(self.file_path, "r") as fh :
            self.file_data = fh.read()

    def render_template (self) :
        tpl = self._build_template(templates.layout)
        
        tpl.page_content = self.file_data
        
        return tpl

class HTMLLoader (PageLoader) :
    """
        Static .html files that are inserted into the layout template as-is

        Sub-pages are not supported...
    """

    def __init__ (self) :
        super(HTMLLoader, self).__init__(".html")

    def get_title (self, page_path) :
        head, tail = os.path.split(page_path)

        return tail.title() if tail else "Index"

    def load (self, _page_path) :
        _file_path = self._build_path(_page_path)
        
        # ignore if it doesn't exist
        if not _file_path :
            return
        
        # get page title
        _title = self.get_title(_page_path)

        # create a new class and return it
        class _html_page (_HTMLPage) :
            file_path = _file_path
            title = _title
            name = _title
            path = _page_path
            
        # return it
        return _html_page

class PythonLoader (PageLoader) :
    """
        Dynamic .py files that define a Page class
    """

    def __init__ (self) :
        super(PythonLoader, self).__init__(".py")
    
    def load (self, page_path) :
        path = self._build_path(page_path)

        # ignore if not exists
        if not path :
            return

        # load the module dynamically
        module = imp.load_source("__dyn_%d" % id(path), path)

        # return the Page object
        return module.Page

# our defined loaders
loaders = [
    HTMLLoader(),
    PythonLoader(),
]

def load_page (req) :
    """
        Returns an instance of a Page object corresponding to the given req
    """

    # page path is given in req
    page_path = req.page_path

    # if it's a dir, then add 'index'
    if os.path.isdir(build_page_path(page_path)) :
        page_path = os.path.join(page_path, "index")

    # try each loader in turn
    for loader in loaders :
        page = loader.load(req.page_path)
        
        # found?
        if page :
            break

    # 404 error...
    if not page :
        page = error404.Error404
        
    return page(req, req.page_path)