--- a/lib/handler.py Sat Feb 07 06:05:10 2009 +0200
+++ b/lib/handler.py Sat Feb 07 06:54:52 2009 +0200
@@ -2,6 +2,24 @@
The actual application behaviour, i.e. generating a Response from a Request :)
"""
+class Handler (object) :
+ """
+ A handler handles a Request, returning a Response
+ """
+
+ def __init__ (self, func, *args, **kwargs) :
+ self.func = func
+ self.args = args
+ self.kwargs = kwargs
+
+ def handle_request (self, request) :
+ """
+ Handle the request, returning a Response object
+ """
+
+ return self.func(request, *self.args, **self.kwargs)
+
+# fs handler
import http, page, menu, template
def handle_request (request) :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/map.py Sat Feb 07 06:54:52 2009 +0200
@@ -0,0 +1,112 @@
+"""
+ Handles mapping URLs to request handlers
+"""
+
+import http
+import handler
+
+class MappingError (http.ResponseError) :
+ """
+ URL could not be mapped
+ """
+
+ def __init__ (self, url) :
+ super(MappingError, self).__init__("URL not found: %s" % (url, ), status='404 Not Found')
+
+class Mapper (object) :
+ """
+ Translates requests to handlers
+ """
+
+ def map_request (self, request) :
+ """
+ Map the given request, returning a Handler
+ """
+
+ abstract
+
+class Mapping (object) :
+ """
+ A mapping object for StaticMapping
+ """
+
+ def test (self, request) :
+ """
+ Either return a handler, or None
+ """
+
+ abstract
+
+class RegexpMapping (object) :
+ """
+ A mapping object that uses regular expressions
+ """
+
+ def __init__ (self, regexp, handler) :
+ pass
+
+ def test (self, request) :
+ xxx
+
+class SimpleMapping (object) :
+ """
+ A mapping object that uses simple expressions
+ """
+
+ def __init__ (self, expression, handler) :
+ pass
+
+ def test (self, request) :
+ xxx
+
+class StaticMapping (Mapper) :
+ """
+ Translates requests to handlers using a list of pre-determined Mapping's
+ """
+
+ def __init__ (self, mappings) :
+ # store
+ self.mappings = mappings
+
+ def map_request (self, request) :
+ """
+ Returns the appropriate handler
+ """
+
+ # 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())
+
+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
+ """
+
+ # 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)
+
+# "friendly" names
+fstree = FilesystemMapper
+
+map = SimpleMapping
+mapre = RegexpMapping
+
--- a/lib/site.py Sat Feb 07 06:05:10 2009 +0200
+++ b/lib/site.py Sat Feb 07 06:54:52 2009 +0200
@@ -2,6 +2,8 @@
Per-site stuff
"""
+import imp
+
SITE_DIR = "sites"
class Site (object) :
@@ -9,6 +11,46 @@
A site is a website and its configuration
"""
- pass
+ def __init__ (self, name) :
+ """
+ The given name must be like a valid hostname, e.g. 'www.qmsk.net'
+ """
+ # store
+ self.name = name
+ # load the site
+ self._load()
+
+ def _load (self) :
+ """
+ Loads this site, as a python module (i.e. dir with __init__.py)
+ """
+
+ # first, we need to find it
+ file, pathname, description = imp.find_module(self.name, [SITE_DIR])
+
+ # then, we can load it
+ self.module = imp.load_module(self.name, file, pathname, description)
+
+ # create our mapper
+ self.mapper = self.module.build_mapper()
+
+ def get_mapper (self) :
+ """
+ Return the Mapper for this site
+ """
+
+ return self.mapper
+
+def lookup (request) :
+ """
+ Lookup and return a Site object for the given request
+ """
+
+ # request hostnmae
+ hostname = request.env.get('HTTP_POST')
+
+ # XXX: hardcoded for now
+ return Site("www.qmsk.net")
+
--- a/lib/wsgi.py Sat Feb 07 06:05:10 2009 +0200
+++ b/lib/wsgi.py Sat Feb 07 06:54:52 2009 +0200
@@ -9,6 +9,9 @@
# for Request/Response
import http
+# to lookup the Site
+from site import lookup as site_lookup
+
# for the request -> response bit :)
import handler
@@ -19,6 +22,15 @@
# build Request object
request = http.Request(env)
+
+ # lookup site
+ site = site_lookup(request)
+
+ # mapper...
+ mapper = site.get_mapper()
+
+ # lookup handler
+ handler = mapper.map_request(request)
try :
# request -> response
--- a/sites/irclogs.qmsk.net/__init__.py Sat Feb 07 06:05:10 2009 +0200
+++ b/sites/irclogs.qmsk.net/__init__.py Sat Feb 07 06:54:52 2009 +0200
@@ -3,5 +3,5 @@
"""
# the URL mapper
-from urls import url_mapper
+from urls import build_mapper
--- a/sites/irclogs.qmsk.net/urls.py Sat Feb 07 06:05:10 2009 +0200
+++ b/sites/irclogs.qmsk.net/urls.py Sat Feb 07 06:54:52 2009 +0200
@@ -7,16 +7,16 @@
import handlers
# library stuff
-from lib.map import Mapping, map, mapre
+from lib.map import StaticMapping, map, mapre
-def url_mapper () :
+def build_mapper () :
"""
Construct and return the Mapping object
"""
- return Mapping(
+ return StaticMapping([
map( '/', handlers.index ),
map( '/channel/%s', handlers.channel_view ),
mapre( r'^/channel/(\w+)/last/(\d+)(\.\w+)?', handlers.channel_last ),
- )
+ ])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/www.qmsk.net/__init__.py Sat Feb 07 06:54:52 2009 +0200
@@ -0,0 +1,8 @@
+"""
+ The www.qmsk.net site is just a simple site with a filesystem-based URL mapping
+"""
+
+from lib.map import fstree
+
+build_mapper = lambda: fstree("site/www.qmsk.net")
+