python functionality...
--- /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
*/