python functionality...
authorTero Marttila <terom@fixme.fi>
Tue, 02 Dec 2008 03:05:04 +0200
changeset 2 ec68a0f75c58
parent 1 0a98cbe5e2eb
child 3 84a149e35cbe
python functionality...
.hgignore
index.html
site/Makefile
site/__init__.py
site/index.py
site/pages/__init__.py
site/pages/about.html
site/request.py
site/templates/__init__.py
site/templates/error_404.tmpl
site/templates/layout.tmpl
site/templates/main.tmpl
style.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,4 @@
+syntax: regexp
+\.[^/]+.sw[op]$
+^site/templates/[^/]+.py$
+
--- a/index.html	Tue Dec 02 00:35:54 2008 +0200
+++ b/index.html	Tue Dec 02 03:05:04 2008 +0200
@@ -2,7 +2,7 @@
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
     <head>
-        <title>qmsk.net - This is a Website</title>
+        <title>qmsk.net</title>
         <link rel="Stylesheet" type="text/css" href="style.css" />
     </head>
     <body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/Makefile	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,6 @@
+
+all: $(patsubst %.tmpl,%.py,$(wildcard templates/*.tmpl))
+
+templates/%.py: templates/%.tmpl
+	@cheetah compile --nobackup $<
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/index.py	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,44 @@
+#!/usr/bin/env python2.5
+
+DEBUG = True
+
+# imports
+if DEBUG :
+    import cgitb; cgitb.enable()
+
+# system modules
+import cgi, os
+
+# my modules/packages
+import request
+import pages
+
+def dump_environ () :
+    print "<!--"
+
+    for k, v in os.environ.iteritems() :
+        print "%25s: %s" % (k, v)
+    
+    print "-->"
+
+# main
+def main (environ) :
+    # load our req
+    req = request.Request(environ, default_page='main')
+
+    # get the page handler
+    page = pages.find(req)
+    
+    # render
+    print "Status: %d\r\n" % page.get_response_code(),
+    print "Content-Type: text/html\r\n",
+    print "\r\n",
+    print "%s\r\n" % page.render_template()
+    
+    # debug output
+    if DEBUG :
+        dump_environ()
+
+if __name__ == '__main__' :
+    main(os.environ)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/pages/__init__.py	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,131 @@
+
+import templates as _templates
+
+class _Page (object) :
+    """
+        A page is kind of like a controller, I guess
+    """
+
+    # the page title, used in the HTML <title>
+    title = None
+
+    # the page name, used in the menu
+    name = None
+
+    # the page path, used in the URL
+    path = None
+
+    def __init__ (self, req, path_suffix) :
+        self.req = req
+        self.path_suffix = path_suffix
+    
+    def _build_template (self, template_class) :
+        tpl = template_class(searchList=[self.req])
+        
+        tpl.page_title = self.title
+        tpl.page_name = self.name
+        tpl.page_path = self.path
+
+        tpl.page_menu = root_menu
+        tpl.page = self
+        tpl.page_children = self.get_children()
+        
+        return tpl
+
+    def get_children (self) :
+        """
+            Returns a list of page objects that are children of this one. May return None if there are none
+        """
+
+        return None
+    
+    def get_response_code (self) :
+        """
+            Returns the HTTP response code to be used
+        """
+
+        return 200
+
+    def render_template (self) :
+        """
+            Returns an instance of Cheetah.Template, prepopulated with whatever variables it needs, ready to be rendered
+        """
+
+        abstract
+
+class StaticHTML (_Page) :
+    # the path to the .html file
+    file_path = None
+
+    def __init__ (self, *args) :
+        super(StaticHTML, self).__init__(*args)
+
+        # open the .html and read in the contents
+        fh = open(self.file_path, "r")
+
+        self.file_data = fh.read()
+
+        fh.close()
+
+    def render_template (self) :
+        tpl = self._build_template(_templates.layout)
+        
+        tpl.page_content = self.file_data
+        
+        return tpl
+
+def html_page (_file_path, _title, _name, _path) :
+    class _anon_html_page (StaticHTML) :
+        file_path = _file_path
+        title = _title
+        name = _name
+        path = _path
+
+    return _anon_html_page
+
+class Main (_Page) :
+    """
+        Main page with simple stuff
+    """
+    
+    title = "Main Page"
+    name = "Main"
+    path = ""
+
+    def render_template (self) :
+        return self._build_template(_templates.main)
+
+
+class Error404 (_Page) :
+    title = "Error 404 - Not Found"
+
+    def get_response_code (self) :
+        return 404
+
+    def render_template (self) :
+        return self._build_template(_templates.error_404)
+
+# load HTML pages
+About = html_page("pages/about.html", "About", "About", "about")
+
+pages = {
+    'main': Main,
+    'about': About,
+}
+
+root_menu = [
+    Main,
+    About
+]
+
+def find (req) :
+    """
+        This finds the page to use for the given req and reuturns an instance of it
+    """
+
+    for prefix, suffix in req.page_name_prefixes() :
+        if prefix in pages :
+            return pages[prefix](req, suffix)
+    
+    return Error404(req, req.page_path)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/pages/about.html	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,4 @@
+<h1>Simple About Page</h1>
+
+<p>This is a simple about page, implemented using plain HTML</p>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/request.py	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,72 @@
+
+import os.path
+
+def get_site_url (script_name) :
+    """
+        Get the URL that points to the site root (i.e. where style.css is) using the given value of SCRIPT_NAME
+
+        /foo/bar/quux.py                -> /foo
+        /~terom/qmsk.net/site/index.py  -> /~terom/qmsk.net
+        None                            -> /
+    """
+    
+    if script_name :
+        return os.path.dirname(os.path.dirname(script_name))
+    else :
+        return "/"
+
+def get_page_path (path_info, default) :
+    """
+        Get the path of the page that was requested, or the given default is empty/invalid.
+        The path will never begin with an /.
+
+        /quux       -> quux
+        /           -> <default>
+        None        -> <default>
+    """
+    
+    if path_info :
+        # remove prefixed slashes
+        path_info = path_info.lstrip('/')
+
+    if path_info :
+        return path_info
+    else :
+        return default
+
+
+class Request (object) :
+    # The name of the site itself, this can be used to reference e.g. style.css
+    site_url = None
+
+    # The page root url, for links to pages
+    page_root = None
+
+    # The full path to the requested page
+    page_path = None
+    
+    def __init__ (self, environ, default_page='main') :
+        self.site_url = get_site_url(environ.get("SCRIPT_NAME"))
+        self.page_root = environ.get("SCRIPT_NAME")
+        self.page_path = get_page_path(environ.get("PATH_INFO"), default_page)
+    
+    def page_name_parts (self) :
+        """
+            Returns a list of page name components
+        """
+
+        return self.page_path.split('/')
+
+    def page_name_prefixes (self) :
+        """
+            Iterate over the components of the page name, yielding (prefix, suffix) pairs
+        """
+        
+        prefix = self.page_name_parts()
+        suffix = []
+
+        while prefix :
+            yield ('/'.join(prefix), '/'.join(suffix))
+
+            suffix.insert(0, prefix.pop(-1))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/templates/__init__.py	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,20 @@
+
+# system imports
+from Cheetah.Template import Template as _CheetahTemplate
+
+# base template
+class _BaseTemplate (_CheetahTemplate) :
+    def __init__ (self, req) :
+        """
+            Blah
+        """
+
+        # XXX: not done
+        pass
+
+
+# import templates
+from layout import layout
+from main import main
+from error_404 import error_404
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/templates/error_404.tmpl	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,10 @@
+#extends layout
+#def page_content
+<h1>Oops! Not Found</h1>
+
+<p>The page you requested does not seem to exist. Perhaps you can find what you're looking for in the menu at the left?</p>
+
+<pre>
+    Requested Path: $page_path
+</pre>
+#end def
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/templates/layout.tmpl	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+#def page_title
+qmsk.net
+#end def
+#def page_content
+<h1>Content Goes Here</h1>
+
+Content goes here.
+#end def
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <head>
+        <title>qmsk.net :: $page_title</title>
+        <link rel="Stylesheet" type="text/css" href="$site_url/style.css" />
+    </head>
+    <body>
+            <div id="header">
+                QMSK.NET
+            </div>
+ 
+            <ul id="nav">
+                #for $menu_page in $page_menu
+                <li><a href="$page_root/$menu_page.path"#if isinstance($page, $menu_page) then ' id="selected-page"' else '' #>$menu_page.name</a></li>
+                #end for
+            </ul>
+
+            <div id="content">
+                $page_content
+            </div>
+    </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/site/templates/main.tmpl	Tue Dec 02 03:05:04 2008 +0200
@@ -0,0 +1,6 @@
+#extends layout
+#def page_content
+<h1>Main Page</h1>
+
+<p>This is the main page...</p>
+#end def
--- a/style.css	Tue Dec 02 00:35:54 2008 +0200
+++ b/style.css	Tue Dec 02 03:05:04 2008 +0200
@@ -70,6 +70,11 @@
     text-decoration: none;
 }
 
+ul#nav li a#selected-page {
+    border-left: 5px solid black;
+    padding-left: 15px;
+}
+
 /*
  * Content
  */