lib/page.py
changeset 8 0ce1f471e9d7
parent 7 d6a8258bd90e
child 9 2a47b00f60b0
--- a/lib/page.py	Fri Feb 06 21:31:02 2009 +0200
+++ b/lib/page.py	Fri Feb 06 22:48:00 2009 +0200
@@ -3,19 +3,169 @@
     Handling page requests
 """
 
-def handle_html (env) :
-    return "A HTML page"
+# for filesystem ops
+import os, os.path
 
+# for ResponseError
+import http
+
+# for TemplatePage
+import template
+
+# path to directory containing the page heirarcy
+PAGE_DIR = "pages"
+
+class PageError (http.ResponseError) :
+    """
+        Error looking up/handling a page
+    """
+
+    pass
+
+class Page (object) :
+    """
+        This object represents the information about our attempt to render some specific page
+    """
+
+    def __init__ (self, url, path, basename, url_tail) :
+        """
+            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
+        """
+        
+        # store
+        self.url = url
+        self.path = path
+        self.basename = basename
+        self.url_tail = url_tail
+
+        # sub-init
+        self._init()
+
+    def _init (self) :
+        """
+            Do initial data loading, etc
+        """
+        
+        pass
+
+    def get_title (self) :
+        """
+            Return the page's title
+
+            Defaults to the Titlecase'd file basename
+        """
+
+        return self.basename.title()
+
+    def get_content (self) :
+        """
+            Return the page content as a string
+        """
+
+        abstract
+
+class HTMLPage (Page) :
+    """
+        A simple .html page that's just passed through directly
+    """
+
+    def get_content (self) :
+        """
+            Opens the .html file, reads and returns contents
+        """
+
+        return open(self.path, 'rb').read()
+
+class TemplatePage (Page) :
+    """
+        A template that's rendered using our template library
+    """
+
+    def get_content (self) :
+        """
+            Loads the .tmpl file, and renders it
+        """
+
+        return template.render_file(self.path)
 
 # list of page handlers, by type
-type_handlers = [
-    ('.html',   handle_html),
+TYPE_HANDLERS = [
+    ('html',                    HTMLPage        ),
+    (template.TEMPLATE_EXT,     TemplatePage    ),
 ]
 
-def lookup_handler (path) :
+def _lookup_handler (url, path, filename, basename, extension, tail) :
     """
-        Look up and return a handler for the given page, or raise an error
+        We found the file that we looked for, now get its handler
     """
 
-    return handle_html
+    # 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 segments :
+        # pop segment
+        segment = segments.pop(0)
+
+        # add to page url
+        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
+
+    # did not find the filename we were looking for in os.listdir
+    raise PageError("Page not found: %s" % name, status='404 Not Found')
+