# HG changeset patch # User Tero Marttila # Date 1234017207 -7200 # Node ID 107062ebb6f932ec9b67965dc91683c111316a48 # Parent a86a25a9f75be7e05395fb58db62f3c58b738433 bloat code with even more layers of indirection, split off the filesystem-based stuff into a separate lib.filesystem package (next, move it to sites/www.qmsk.net) diff -r a86a25a9f75b -r 107062ebb6f9 index.cgi --- a/index.cgi Sat Feb 07 06:54:52 2009 +0200 +++ b/index.cgi Sat Feb 07 16:33:27 2009 +0200 @@ -27,19 +27,16 @@ """ try : - from lib import page_tree - - # load page list - page_tree.load() - - # our WSGI app - from lib import wsgi + from lib import wsgi, site # create handler cgi_handler = wsgiref.handlers.CGIHandler() + + # create app + app = wsgi.Application(site.SiteModuleCollection('sites')) # run once - cgi_handler.run(wsgi.app) + cgi_handler.run(app) except : cgi_error() diff -r a86a25a9f75b -r 107062ebb6f9 lib/filesystem/map.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/filesystem/map.py Sat Feb 07 16:33:27 2009 +0200 @@ -0,0 +1,131 @@ + +import os, os.path + +from lib import http, template, map + +import page, page_tree, menu + +class FilesystemMapper (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) : + """ + Create, path is where the pages are stored. The list of pages is loaded from $path/list + """ + + # store + self.path = path + + # 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 PageError("Page not found: %s" % name, status='404 Not Found') + + 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 + p = self._lookup_page(page_name) + + # bind to request + p.bind_request(request) + + # render the template + response_data = template.render("layout", + site_root_url = request.get_script_dir(), + site_page_url = request.get_page_prefix(), + page = p, + menu = menu.Menu(self, p), + ) + + # return the response + return http.Response(response_data) + + diff -r a86a25a9f75b -r 107062ebb6f9 lib/filesystem/menu.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/filesystem/menu.py Sat Feb 07 16:33:27 2009 +0200 @@ -0,0 +1,23 @@ +""" + Handling the list of available pages +""" + +class Menu (object) : + """ + Contains info needed to render the menu + """ + + def __init__ (self, fs, page) : + """ + Gather the menu information for the given page, as part of the given FilesystemMapper + """ + + # the selected page + self.page = fs.tree.get_page(page.url) + + # the selected pagen's inheritance + self.ancestry = self.page.get_ancestry() if self.page else [] + + # list of menu items == root children, since we always show the full menu... + self.items = fs.tree.root.children + diff -r a86a25a9f75b -r 107062ebb6f9 lib/filesystem/page.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/filesystem/page.py Sat Feb 07 16:33:27 2009 +0200 @@ -0,0 +1,132 @@ + +""" + Handling page requests +""" + +# for filesystem ops +import os, os.path +import time + +from lib import http, template, config + +class PageError (http.ResponseError) : + """ + Error looking up/handling a page + """ + + pass + +# XXX: should inherit from PageInfo +class Page (object) : + """ + This object represents the information about our attempt to render some specific page + """ + + def __init__ (self, fs, url, path, basename, url_tail, charset='utf8') : + """ + Initialize the page at the given location + + @param fs the FilesysteMapper + @param url the URL leading to this page + @param path the filesystem path to this page's file + @param basename the filesystem name of this page's file, without the file extension + @param url_trail trailing URL for this page + @param charset file charset + """ + + # store + self.fs = fs + self.url = url + self.path = path + self.basename = basename + self.url_tail = url_tail + self.charset = charset + + # unbound + self.request = None + + # sub-init + self._init() + + def _init (self) : + """ + Do initial data loading, etc + """ + + pass + + def bind_request (self, request) : + """ + Bind this page-render to the given request + """ + + self.request = request + + @property + def title (self) : + """ + Return the page's title + + Defaults to the retreiving the page title from page_list, or basename in Titlecase. + """ + + # lookup in PageTree + page_info = self.fs.tree.get_page(self.url) + + # fallback to titlecase + if page_info : + title = page_info.title + + else : + title = self.basename.title() + + return title + + @property + def content (self) : + """ + Return the page content as a string + """ + + abstract + + @property + def modified (self) : + """ + Returns the page modification timestamp + """ + + # stat + timestamp = os.stat(self.path).st_mtime + + return time.strftime(config.DATETIME_FMT, time.gmtime(timestamp)) + +class HTMLPage (Page) : + """ + A simple .html page that's just passed through directly + """ + + @property + def content (self) : + """ + Opens the .html file, reads and returns contents + """ + + return open(self.path, 'rb').read().decode(self.charset) + +class TemplatePage (Page) : + """ + A template that's rendered using our template library + """ + + @property + def content (self) : + """ + Loads the .tmpl file, and renders it + """ + + return template.render_file(self.path, + request = self.request, + page_tree = self.fs.tree + ) + diff -r a86a25a9f75b -r 107062ebb6f9 lib/filesystem/page_tree.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/filesystem/page_tree.py Sat Feb 07 16:33:27 2009 +0200 @@ -0,0 +1,218 @@ +""" + Implements the tree containing pages and their metadata +""" + +from lib import tree_parse + +class PageTreeError (Exception) : + """ + Error parsing/loading the page tree + """ + + pass + +class PageInfo (object) : + """ + Contains metainformation about a page + """ + + def __init__ (self, parent, name, title, children=None) : + """ + Initialize, children defaults to empty list + """ + + # store + self.parent = parent + self.name = name + self.title = title + self.children = children if children else [] + + # no url get + self._url = None + + def set_parent (self, parent) : + """ + Set a parent where non was set before + """ + + assert self.parent is None + + self.parent = parent + + def add_child (self, child) : + """ + Add a PageInfo child + """ + + self.children.append(child) + + def get_child (self, name) : + """ + Look up a child by name, returning None if not found + """ + + return dict((c.name, c) for c in self.children).get(name) + + def get_ancestry (self) : + """ + Returns a list of this page's parents and the page itself, but not root + """ + + # collect in reverse order + ancestry = [] + + # starting from self + item = self + + # add all items, but not root + while item and item.parent : + ancestry.append(item) + + item = item.parent + + # reverse + ancestry.reverse() + + # done + return ancestry + + @property + def url (self) : + """ + Build this page's URL + """ + + # cached? + if self._url : + return self._url + + segments = [item.name for item in self.get_ancestry()] + + # add empty segment if dir + if self.children : + segments.append('') + + # join + url = '/'.join(segments) + + # cache + self._url = url + + # done + return url + +class PageTree (object) : + """ + The tree of pages, rooted at .root. + + Use load_page_tree to initialize the global page_tree instance, and then use that + """ + + def __init__ (self, path) : + """ + Loads the PageTree root from the given file + """ + + # store + self.path = path + + # load + self._load(path) + + def _load (self, path) : + """ + Processes the lines in the given file + """ + + # parse tree + tree = tree_parse.parse(path, ':') + + if not tree : + raise PageTreeError("No root node found") + + def _create_node (parent, item) : + """ + Creates and returns a PageInfo from the given parent node and (line_number, line, children) tuple item + """ + + # unpack + line_number, line, children = item + + # parse line + url = title = None + + try : + url, title = line.split(':') + + except : + raise PageTreeError("Invalid line: %s:%d: %r" % (path, line_number, line)) + + # remove whitespace + url = url.strip() + title = title.strip() + + # create PageInfo + node = PageInfo(parent, url, title) + + # set node children + node.children = [ + _create_node(node, child_item) for child_item in children + ] + + # return + return node + + # translate + self.root = _create_node(None, tree) + + # *evil cackle* + self.root.children.insert(0, self.root) + + def get_page (self, url) : + """ + Lookup the given page URL, and return the matching PageInfo object, or None, if not found + """ + + # start from root + node = self.root + + # traverse the object tree + for segment in url.split('/') : + if segment : + node = node.get_child(segment) + + if not node : + return None + + # return + return node + + def get_siblings (self, url) : + """ + Get the list of siblings for the given url, including the given page itself + """ + + # look up the page itself + page = self.get_page(url) + + # specialcase root/unknown node + if page and page.parent : + return page.parent.children + + else : + return self.root.children + + def dump (self) : + """ + Returns a string representation of the tree + """ + + def _print_node (indent, node) : + return '\n'.join('%s%s' % (' '*indent, line) for line in [ + "%-15s : %s" % (node.name, node.title) + ] + [ + _print_node(indent + 4, child) for child in node.children if child != node + ]) + + return _print_node(0, self.root) + diff -r a86a25a9f75b -r 107062ebb6f9 lib/handler.py --- a/lib/handler.py Sat Feb 07 06:54:52 2009 +0200 +++ b/lib/handler.py Sat Feb 07 16:33:27 2009 +0200 @@ -2,7 +2,7 @@ The actual application behaviour, i.e. generating a Response from a Request :) """ -class Handler (object) : +class RequestHandler (object) : """ A handler handles a Request, returning a Response """ @@ -15,35 +15,10 @@ def handle_request (self, request) : """ Handle the request, returning a Response object + + XXX: rename to __call__ kplzthx """ return self.func(request, *self.args, **self.kwargs) -# fs handler -import http, page, menu, template - -def handle_request (request) : - """ - Take the Request, and return a Response - """ - - # determine the page name - page_name = request.get_page_name() - - # get the page handler - p = page.lookup(page_name) - # bind to request - p.bind_request(request) - - # render the template - response_data = template.render("layout", - site_root_url = request.get_script_dir(), - site_page_url = request.get_page_prefix(), - page = p, - menu = menu.Menu(p), - ) - - # return the response - return http.Response(response_data) - diff -r a86a25a9f75b -r 107062ebb6f9 lib/map.py --- a/lib/map.py Sat Feb 07 06:54:52 2009 +0200 +++ b/lib/map.py Sat Feb 07 16:33:27 2009 +0200 @@ -13,14 +13,14 @@ def __init__ (self, url) : super(MappingError, self).__init__("URL not found: %s" % (url, ), status='404 Not Found') -class Mapper (object) : +class Mapper (handler.RequestHandler) : """ - Translates requests to handlers + Looks up the handler to use based on the URL """ - def map_request (self, request) : + def handle_request (self, request) : """ - Map the given request, returning a Handler + Map the given request """ abstract @@ -73,40 +73,24 @@ Returns the appropriate handler """ + # find handler to use + handler = None + # just test each mapping in turn for mapping in self.mappings : handler = mapping.test(request) if handler : - return handler - - # fail, not found - raise MappingError(request.get_page_name()) + break -class FilesystemMapper (Mapper) : - """ - Translates requests to handlers based on a filesystem directory containing various kinds of files - """ - - def __init__ (self, path) : - """ - Create, path is where the pages are stored - """ + if not handler : + # fail, not found + raise MappingError(request.get_page_name()) - # store - self.path = path - - def map_request (self, request) : - """ - Looks up the appropriate Page, and then returns a generic Handler - """ - - # XXX: harcoded - return handler.Handler(handler.handle_request) + # passthrough + return handler.handle_request(request) # "friendly" names -fstree = FilesystemMapper - map = SimpleMapping mapre = RegexpMapping diff -r a86a25a9f75b -r 107062ebb6f9 lib/menu.py --- a/lib/menu.py Sat Feb 07 06:54:52 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -""" - Handling the list of available pages -""" - -# for page_list -from page_tree import page_tree - -class Menu (object) : - """ - Contains info needed to render the menu - """ - - def __init__ (self, page) : - """ - Gather the menu information for the given page - """ - - # the selected page - self.page = page_tree.get_page(page.url) - - # the selected pagen's inheritance - self.ancestry = self.page.get_ancestry() if self.page else [] - - # list of menu items == root children, since we always show the full menu... - self.items = page_tree.root.children - diff -r a86a25a9f75b -r 107062ebb6f9 lib/page.py --- a/lib/page.py Sat Feb 07 06:54:52 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ - -""" - Handling page requests -""" - -# for filesystem ops -import os, os.path -import time - -# for ResponseError -import http - -# for TemplatePage -import template - -from page_tree import page_tree -import config - -# path to directory containing the page heirarcy -PAGE_DIR = "pages" - -class PageError (http.ResponseError) : - """ - Error looking up/handling a page - """ - - pass - -# XXX: should inherit from PageInfo -class Page (object) : - """ - This object represents the information about our attempt to render some specific page - """ - - def __init__ (self, url, path, basename, url_tail, charset='utf8') : - """ - Initialize the page at the given location - - @param url the URL leading to this page - @param path the filesystem path to this page's file - @param basename the filesystem name of this page's file, without the file extension - @param url_trail trailing URL for this page - @param charset file charset - """ - - # store - self.url = url - self.path = path - self.basename = basename - self.url_tail = url_tail - self.charset = charset - - # unbound - self.request = None - - # sub-init - self._init() - - def _init (self) : - """ - Do initial data loading, etc - """ - - pass - - def bind_request (self, request) : - """ - Bind this page-render to the given request - """ - - self.request = request - - @property - def title (self) : - """ - Return the page's title - - Defaults to the retreiving the page title from page_list, or basename in Titlecase. - """ - - # lookup in page_list - page_info = page_tree.get_page(self.url) - - # fallback to titlecase - if page_info : - title = page_info.title - - else : - title = self.basename.title() - - return title - - @property - def content (self) : - """ - Return the page content as a string - """ - - abstract - - @property - def modified (self) : - """ - Returns the page modification timestamp - """ - - # stat - timestamp = os.stat(self.path).st_mtime - - return time.strftime(config.DATETIME_FMT, time.gmtime(timestamp)) - -class HTMLPage (Page) : - """ - A simple .html page that's just passed through directly - """ - - @property - def content (self) : - """ - Opens the .html file, reads and returns contents - """ - - return open(self.path, 'rb').read().decode(self.charset) - -class TemplatePage (Page) : - """ - A template that's rendered using our template library - """ - - @property - def content (self) : - """ - Loads the .tmpl file, and renders it - """ - - return template.render_file(self.path, - request = self.request, - page_tree = page_tree - ) - -# list of page handlers, by type -TYPE_HANDLERS = [ - ('html', HTMLPage ), - (template.TEMPLATE_EXT, TemplatePage ), -] - -def _lookup_handler (url, path, filename, basename, extension, tail) : - """ - We found the file that we looked for, now get its handler - """ - - # find appropriate handler - for handler_ext, handler in TYPE_HANDLERS : - # match against file extension? - if handler_ext == extension : - # found handler, return instance - return handler(url, path, basename, tail) - - # no handler found - raise PageError("No handler found for page %r of type %r" % (url, extension)) - -def lookup (name) : - """ - Look up and return a Page object for the given page, or raise an error - """ - - # inital path - path = PAGE_DIR - 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 _lookup_handler('/'.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 PageError("Page not found: %s" % name, status='404 Not Found') - diff -r a86a25a9f75b -r 107062ebb6f9 lib/page_tree.py --- a/lib/page_tree.py Sat Feb 07 06:54:52 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -""" - Implements the tree containing pages and their metadata -""" - -import tree_parse - -# path to file containing the page metadata tree -PAGE_TREE_FILE = "pages/list" - -class PageTreeError (Exception) : - """ - Error parsing/loading the page tree - """ - - pass - -class PageInfo (object) : - """ - Contains metainformation about a page - """ - - def __init__ (self, parent, name, title, children=None) : - """ - Initialize, children defaults to empty list - """ - - # store - self.parent = parent - self.name = name - self.title = title - self.children = children if children else [] - - # no url get - self._url = None - - def set_parent (self, parent) : - """ - Set a parent where non was set before - """ - - assert self.parent is None - - self.parent = parent - - def add_child (self, child) : - """ - Add a PageInfo child - """ - - self.children.append(child) - - def get_child (self, name) : - """ - Look up a child by name, returning None if not found - """ - - return dict((c.name, c) for c in self.children).get(name) - - def get_ancestry (self) : - """ - Returns a list of this page's parents and the page itself, but not root - """ - - # collect in reverse order - ancestry = [] - - # starting from self - item = self - - # add all items, but not root - while item and item.parent : - ancestry.append(item) - - item = item.parent - - # reverse - ancestry.reverse() - - # done - return ancestry - - @property - def url (self) : - """ - Build this page's URL - """ - - # cached? - if self._url : - return self._url - - segments = [item.name for item in self.get_ancestry()] - - # add empty segment if dir - if self.children : - segments.append('') - - # join - url = '/'.join(segments) - - # cache - self._url = url - - # done - return url - -class PageTree (object) : - """ - The tree of pages, rooted at .root. - - Use load_page_tree to initialize the global page_tree instance, and then use that - """ - - def __init__ (self) : - """ - Empty PageList, must call load_page_list to initialize, once - """ - - def _load (self, path) : - """ - Processes the lines in the given file - """ - - # parse tree - tree = tree_parse.parse(path, ':') - - if not tree : - raise PageTreeError("No root node found") - - def _create_node (parent, item) : - """ - Creates and returns a PageInfo from the given parent node and (line_number, line, children) tuple item - """ - - # unpack - line_number, line, children = item - - # parse line - url = title = None - - try : - url, title = line.split(':') - - except : - raise PageTreeError("Invalid line: %s:%d: %r" % (path, line_number, line)) - - # remove whitespace - url = url.strip() - title = title.strip() - - # create PageInfo - node = PageInfo(parent, url, title) - - # set node children - node.children = [ - _create_node(node, child_item) for child_item in children - ] - - # return - return node - - # translate - self.root = _create_node(None, tree) - - # *evil cackle* - self.root.children.insert(0, self.root) - - def get_page (self, url) : - """ - Lookup the given page URL, and return the matching PageInfo object, or None, if not found - """ - - # start from root - node = self.root - - # traverse the object tree - for segment in url.split('/') : - if segment : - node = node.get_child(segment) - - if not node : - return None - - # return - return node - - def get_siblings (self, url) : - """ - Get the list of siblings for the given url, including the given page itself - """ - - # look up the page itself - page = self.get_page(url) - - # specialcase root/unknown node - if page and page.parent : - return page.parent.children - - else : - return self.root.children - - def dump (self) : - """ - Returns a string representation of the tree - """ - - def _print_node (indent, node) : - return '\n'.join('%s%s' % (' '*indent, line) for line in [ - "%-15s : %s" % (node.name, node.title) - ] + [ - _print_node(indent + 4, child) for child in node.children if child != node - ]) - - return _print_node(0, self.root) - -# global singleton PageList instance -page_tree = PageTree() - -def load () : - """ - Load the global singleton PageInfo instance - """ - - page_tree._load(PAGE_TREE_FILE) - diff -r a86a25a9f75b -r 107062ebb6f9 lib/site.py --- a/lib/site.py Sat Feb 07 06:54:52 2009 +0200 +++ b/lib/site.py Sat Feb 07 16:33:27 2009 +0200 @@ -4,53 +4,82 @@ import imp -SITE_DIR = "sites" +import handler -class Site (object) : +class Site (handler.RequestHandler) : """ A site is a website and its configuration + + XXX: need to somehow communicate the site name to our downstream handler """ - def __init__ (self, name) : + def __init__ (self, name, handler) : """ The given name must be like a valid hostname, e.g. 'www.qmsk.net' """ # store self.name = name + self.handler = handler - # load the site - self._load() - - def _load (self) : + def handle_request (self, request) : """ - Loads this site, as a python module (i.e. dir with __init__.py) + Map the request through our handler... """ - # first, we need to find it - file, pathname, description = imp.find_module(self.name, [SITE_DIR]) + return self.handler.handle_request(request) - # then, we can load it - self.module = imp.load_module(self.name, file, pathname, description) - - # create our mapper - self.mapper = self.module.build_mapper() +class SiteModule (Site) : + """ + A site, represented as python module/package, with the following module attributes: - def get_mapper (self) : + handler - the RequestHandler to use + """ + + def __init__ (self, name, module) : """ - Return the Mapper for this site + Create the Site based on the given module """ - return self.mapper + super(SiteModule, self).__init__(name, + module.handler + ) -def lookup (request) : +class SiteModuleCollection (handler.RequestHandler) : """ - Lookup and return a Site object for the given request + A collection of SiteModules, looking up the correct site to use based on the request hostname """ - # request hostnmae - hostname = request.env.get('HTTP_POST') + def __init__ (self, path) : + """ + Initialize to load site modules from the given path + """ - # XXX: hardcoded for now - return Site("www.qmsk.net") + self.path = path + self.site_cache = dict() + def handle_request (self, request) : + """ + Lookup and return a Site object for the given request + """ + + # request hostnmae + name = request.env.get('HTTP_HOST') + + # already loaded? + if name in self.site_cache : + site = self.site_cache[name] + + else : + # first, we need to find it + file, pathname, description = imp.find_module(name, [self.path]) + + # then, we can load the module + module = imp.load_module(name, file, pathname, description) + + # then build+cache the SiteModule + site = self.site_cache[name] = SiteModule(name, module) + + # then execute the site's request handler + return site.handle_request(request) + diff -r a86a25a9f75b -r 107062ebb6f9 lib/wsgi.py --- a/lib/wsgi.py Sat Feb 07 06:54:52 2009 +0200 +++ b/lib/wsgi.py Sat Feb 07 16:33:27 2009 +0200 @@ -9,63 +9,60 @@ # for Request/Response import http -# to lookup the Site -from site import lookup as site_lookup - -# for the request -> response bit :) -import handler - -def request_handler (env, start_response) : +class Application (object) : """ - The actual request handling code + Our WSGI application, implements the wsgi __call__ interface """ - # build Request object - request = http.Request(env) - - # lookup site - site = site_lookup(request) - - # mapper... - mapper = site.get_mapper() + def __init__ (self, handler) : + """ + Initialize to use the given handler for requests + """ - # lookup handler - handler = mapper.map_request(request) - - try : - # request -> response - response = handler.handle_request(request) - - except http.ResponseError, err : - # just use the generated response - response = err.get_response() - - # send response - assert response, "No response" + self.handler = handler - # send response status/headers - start_response(response.get_status(), response.get_headers()) - - # send respones data - yield response.get_data() - -def app (env, start_response) : - """ - Wraps request_handler to trap errors - """ + def handle_request (self, env, start_response) : + """ + The actual request handling code + """ - try : - # passthrough request_handler - for chunk in request_handler(env, start_response) : - yield chunk + # build Request object + request = http.Request(env) - except : - # execption info - info = sys.exc_info() + try : + # request -> response using our handler + response = self.handler.handle_request(request) - # try and send 500 ISE to browser, if no headers yet... - start_response("500 Internal Server Error", [('Content-type', "text/plain; charset=utf8")], info) + except http.ResponseError, err : + # just use the generated response + response = err.get_response() - # send traceback - yield traceback.format_exc() + # send response + assert response, "No response" + + # send response status/headers + start_response(response.get_status(), response.get_headers()) + # send respones data + yield response.get_data() + + def __call__ (self, env, start_response) : + """ + Wraps handle_request to trap errors + """ + + try : + # passthrough request_handler + for chunk in self.handle_request(env, start_response) : + yield chunk + + except : + # execption info + info = sys.exc_info() + + # try and send 500 ISE to browser, if no headers yet... + start_response("500 Internal Server Error", [('Content-type', "text/plain; charset=utf8")], info) + + # send traceback + yield traceback.format_exc() + diff -r a86a25a9f75b -r 107062ebb6f9 sites/www.qmsk.net/__init__.py --- a/sites/www.qmsk.net/__init__.py Sat Feb 07 06:54:52 2009 +0200 +++ b/sites/www.qmsk.net/__init__.py Sat Feb 07 16:33:27 2009 +0200 @@ -2,7 +2,8 @@ The www.qmsk.net site is just a simple site with a filesystem-based URL mapping """ -from lib.map import fstree +from lib.filesystem.map import FilesystemMapper as _fstree -build_mapper = lambda: fstree("site/www.qmsk.net") +# global mapper attribute +handler = _fstree("pages")