<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -11,7 +11,7 @@ MNML's core philosophy is that I really love writing Python and want to do that
 * Is strictly WSGI;
 * Provides URL mapping to HTTP response relationship, aka routing;
 * Provides methods for all HTTP method verbs (`PUT` and `DELETE` are supported);
-* Provides flexible regular expression matching for URLs with the ability to reverse said URLs (like Django's `reverse` function);
+* Provides named route matching for URLs with the ability to reverse said URLs (like Django's `reverse` function);
 * Provides the ability to add middleware functions so one can alter the request or response as required;
 * Does not dictate the template or ORM layer you should use--MNML is strictly about URL routing and serving, and tools needed to do so; and mostly
 * Lets the implementer write Python, not a sub-set of Python.</diff>
      <filename>README.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -98,23 +98,23 @@ class HttpResponse(object):
 class WebApplication(object):
     &quot;&quot;&quot;The actual serving of Python code is done here&quot;&quot;&quot;
     def __init__(self, routes):
-        self.routes = tuple((re.compile(a), b) for a,b in routes)
+        self.routes = routes
     
     def __call__(self, environ, start_response):
         request = HttpRequest(environ)
         response = None
         
-        for route in self.routes:
-            url, view = route
-            match = url.match(environ['PATH_INFO'])
-            if match:
+        for pair in self.routes:
+            route, view = pair
+            matches = re.match(route_master(route), environ['PATH_INFO'])
+            if matches:
                 if hasattr(view, '__call__'):
                     to_call = view
                 else:
                     # TODO: do this better
                     to_call = eval(view)
                 try:
-                    response = to_call(request, **match.groupdict())
+                    response = to_call(request, **matches.groupdict())
                 except Exception, error:
                     # either the function failed, or it doesn't exist
                     # TODO: log missing functions
@@ -147,15 +147,54 @@ class WebApplication(object):
         server.serve_forever()
     
 
+def route_master(route):
+    &quot;&quot;&quot;returns a compiled regular expression&quot;&quot;&quot;
+    # chop off leading slash
+    if route.startswith('/'):
+        route = route[1:]
+        
+    trailing_slash = False
+    # check end slash and remember to keep it
+    if route.endswith('/'):
+        route = route[:-1]
+        trailing_slash = True
+        
+    # split into path components
+    bits = route.split('/')
+    
+    # compiled match starts with a slash,
+    #  so we make it a list so we can join later
+    regex = ['']
+    for path_component in bits:
+        if path_component.startswith(':'):
+            # it's a route, so compile
+            name = path_component[1:]
+            # accept only valid URL characters
+            regex.append(r'(?P&lt;%s&gt;[-_a-zA-Z0-9+%%]+)' % name)
+        else:
+            # just a string/static path component
+            regex.append(path_component)
+            
+    # stick the trailing slash back on
+    if trailing_slash:
+        regex.append('')
+        
+    # stitch it back together as a path
+    return '^%s$' % '/'.join(regex)
+
 if __name__ == '__main__':
     &quot;&quot;&quot;run the basic server&quot;&quot;&quot;
     routes = (
-        (r'^/$', 'homepage'),
+        ('/', 'homepage'),
+        ('/myview/:stuff/', 'other_thing')
     )
     
     def homepage(request):
         return HttpResponse('hello world!')
     
+    def other_thing(request, stuff):
+        return HttpResponse('found stuff: %s!' % stuff)
+    
     web_app = WebApplication(routes)
     
     try:</diff>
      <filename>mnml.py</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d50fca799fe90ee88030f016abf7f74ae9168ae5</id>
    </parent>
  </parents>
  <author>
    <name>Bradley Wright</name>
    <email>brad@intranation.com</email>
  </author>
  <url>http://github.com/bradleywright/mnml/commit/879941eef880a3208e245d53039e624c22fc4ea9</url>
  <id>879941eef880a3208e245d53039e624c22fc4ea9</id>
  <committed-date>2009-02-25T14:43:01-08:00</committed-date>
  <authored-date>2009-02-25T14:43:01-08:00</authored-date>
  <message>Switch to simple, name-based routing (`/path/:component/`) style.

* This is far easier to reverse (I had a look at Django's reverse code and it's horrific);
* This is simpler to get started with; and mostly
* Straight regex-matching is realistically beyond what most people (myself include) will need.</message>
  <tree>42b5d0b782dc9dc5434e22de694b3e660a56f6a3</tree>
  <committer>
    <name>Bradley Wright</name>
    <email>brad@intranation.com</email>
  </committer>
</commit>
