import os, os.path
from lib import http, template, map
import page, page_tree
class PageMapper (map.Mapper) :
"""
Translates requests to handlers based on a filesystem directory containing various kinds of files
"""
# list of page handlers, by type
PAGE_TYPES = [
('html', page.HTMLPage ),
(template.TEMPLATE_EXT, page.TemplatePage ),
]
def __init__ (self, path, template) :
"""
Create, path is where the pages are stored. The list of pages is loaded from $path/list
"""
# store
self.path = path
self.template = template
# load the page tree
self.tree = page_tree.PageTree(path + '/list')
def _lookup_page_type (self, url, path, filename, basename, extension, tail) :
"""
We found the file that we looked for, now get the correct type
"""
# find appropriate handler
for handler_ext, type in self.PAGE_TYPES :
# match against file extension?
if handler_ext == extension :
# found handler, return instance
return type(self, url, path, basename, tail)
# no handler found
raise PageError("No handler found for page %r of type %r" % (url, extension))
def _lookup_page (self, name) :
"""
Look up and return a Page object for the given page, or raise an error
"""
# inital path
path = self.path
url_segments = []
# name segments
segments = name.split('/')
# iterate through the parts of the page segments
while True :
segment = None
# pop segment
if segments :
segment = segments.pop(0)
url_segments.append(segment)
# translate empty -> index
if not segment :
segment = 'index'
# look for it in the dir
for filename in os.listdir(path) :
# build full file path
file_path = os.path.join(path, filename)
# stat, recurse into subdirectory?
if os.path.isdir(file_path) and filename == segment :
# use new dir
path = file_path
# break for-loop to look at next segment
break
# split into basename + extension
basename, extension = os.path.splitext(filename)
# ...remove that dot
extension = extension.lstrip('.')
# match against requested page name?
if basename == segment :
# found the file we wanted
return self._lookup_page_type('/'.join(url_segments), file_path, filename, basename, extension, '/'.join(segments))
else :
# inspect next file in dir
continue
else :
# did not find any dir or file, break out of while loop
break
# did not find the filename we were looking for in os.listdir
raise map.MapperError(name)
def handle_request (self, request) :
"""
Looks up the appropriate Page, and then renders it
"""
# determine the page name
page_name = request.get_page_name()
# get the page handler
page = self._lookup_page(page_name)
# pass on
return page.handle_request(request)