--- a/lib/filesystem/map.py Sat Feb 07 17:07:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-
-import os, os.path
-
-from lib import http, template, map
-
-import page, page_tree
-
-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, 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 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
- page = self._lookup_page(page_name)
-
- # pass on
- return page.handle_request(request)
-
--- a/lib/filesystem/menu.py Sat Feb 07 17:07:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-"""
- 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
-
--- a/lib/filesystem/page.py Sat Feb 07 17:07:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-
-"""
- Handling page requests
-"""
-
-# for filesystem ops
-import os, os.path
-import time
-
-from lib import http, handler, template, config
-
-import menu
-
-class PageError (http.ResponseError) :
- """
- Error looking up/handling a page
- """
-
- pass
-
-# XXX: should inherit from PageInfo
-class Page (handler.RequestHandler) :
- """
- 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
-
- # sub-init
- self._init()
-
- def _init (self) :
- """
- Do initial data loading, etc
- """
-
- pass
-
- @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))
-
- def handle_request (self, request) :
- """
- Renders the fs's layout template with this page + menu
- """
-
- # render the template
- response_data = template.render(self.fs.template,
- request = request,
- site_root_url = request.get_script_dir(),
- site_page_url = request.get_page_prefix(),
- page = self,
- menu = menu.Menu(self.fs, self),
- )
-
- # return the response
- return http.Response(response_data)
-
-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.TemplateLoader.render_file(self.path,
- page_tree = self.fs.tree,
- )
-
--- a/lib/filesystem/page_tree.py Sat Feb 07 17:07:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-"""
- 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)
-
--- a/sites/www.qmsk.net/__init__.py Sat Feb 07 17:07:06 2009 +0200
+++ b/sites/www.qmsk.net/__init__.py Sat Feb 07 17:10:06 2009 +0200
@@ -3,8 +3,8 @@
"""
from lib import template
-from lib.filesystem.map import FilesystemMapper as _fstree
+import map
# global mapper attribute
-handler = _fstree("pages", template=template.TemplateLoader.load("sites/www.qmsk.net/templates/layout.tmpl"))
+handler = map.FilesystemMapper("pages", template=template.TemplateLoader.load("sites/www.qmsk.net/templates/layout.tmpl"))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/www.qmsk.net/map.py Sat Feb 07 17:10:06 2009 +0200
@@ -0,0 +1,120 @@
+
+import os, os.path
+
+from lib import http, template, map
+
+import page, page_tree
+
+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, 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 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
+ page = self._lookup_page(page_name)
+
+ # pass on
+ return page.handle_request(request)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/www.qmsk.net/menu.py Sat Feb 07 17:10:06 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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/www.qmsk.net/page.py Sat Feb 07 17:10:06 2009 +0200
@@ -0,0 +1,140 @@
+
+"""
+ Handling page requests
+"""
+
+# for filesystem ops
+import os, os.path
+import time
+
+from lib import http, handler, template, config
+
+import menu
+
+class PageError (http.ResponseError) :
+ """
+ Error looking up/handling a page
+ """
+
+ pass
+
+# XXX: should inherit from PageInfo
+class Page (handler.RequestHandler) :
+ """
+ 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
+
+ # sub-init
+ self._init()
+
+ def _init (self) :
+ """
+ Do initial data loading, etc
+ """
+
+ pass
+
+ @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))
+
+ def handle_request (self, request) :
+ """
+ Renders the fs's layout template with this page + menu
+ """
+
+ # render the template
+ response_data = template.render(self.fs.template,
+ request = request,
+ site_root_url = request.get_script_dir(),
+ site_page_url = request.get_page_prefix(),
+ page = self,
+ menu = menu.Menu(self.fs, self),
+ )
+
+ # return the response
+ return http.Response(response_data)
+
+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.TemplateLoader.render_file(self.path,
+ page_tree = self.fs.tree,
+ )
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/www.qmsk.net/page_tree.py Sat Feb 07 17:10:06 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)
+