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)