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