sites/irclogs.qmsk.net/urltree.py
branchsites
changeset 42 5a72c00c4ae4
parent 41 9585441a4bfb
child 43 fc11c4e86a82
--- a/sites/irclogs.qmsk.net/urltree.py	Sun Feb 08 00:29:36 2009 +0200
+++ b/sites/irclogs.qmsk.net/urltree.py	Sun Feb 08 02:29:23 2009 +0200
@@ -93,6 +93,13 @@
         """
 
         abstract
+    
+    def build (self, value_dict) :
+        """
+            Return a string representing this label, using the values in the given value_dict if needed
+        """
+
+        abstract
 
 class EmptyLabel (Label) :
     """
@@ -118,6 +125,9 @@
         # only empty segments
         if value == '' :
             return True
+    
+    def build (self, values) :
+        return str(self)
 
     def __str__ (self) :
         return ''
@@ -156,6 +166,9 @@
         if value == self.name :
             return True
 
+    def build (self, values) :
+        return str(self)
+
     def __str__ (self) :
         return self.name
 
@@ -180,6 +193,21 @@
         """
 
         return isinstance(other, ValueLabel) and self.key == other.key
+    
+    def build (self, values) :
+        """
+            Return either the assigned value from values, our default value, or raise an error
+        """
+
+        value = values.get(self.key)
+        
+        if not value and self.default :
+            value = self.default
+
+        elif not value :
+            raise URLError("No value given for label %r" % (self.key, ))
+
+        return value
 
 class SimpleValueLabel (ValueLabel) :
     """
@@ -273,9 +301,43 @@
         self.handler = handler
         self.defaults = defaults
 
-        # build our labels
+        # query string
+        self.query_args = dict()
+        
+        # parse any query string
+        # XXX: conflicts with regexp syntax
+        if '/?' in url_mask :
+            url_mask, query_mask = url_mask.split('/?')
+        
+        else :
+            query_mask = None
+
+        # build our label path
         self.label_path = [Label.parse(mask, defaults, config.type_dict) for mask in url_mask.split('/')]
-        
+
+        # build our query args list
+        if query_mask :
+            # split into items
+            for query_item in query_mask.split('&') :
+                # parse default
+                if '=' in query_item :
+                    query_item, default = query_item.split('=')
+
+                else :
+                    default = None
+                
+                # parse type
+                if ':' in query_item :
+                    query_item, type = query_item.split(':')
+                else :
+                    type = None
+                
+                # parse key
+                key = query_item
+
+                # add to query_args as (type, default) tuple
+                self.query_args[key] = (self.config.type_dict[type], default)
+         
     def get_label_path (self) :
         """
             Returns a list containing the labels in this url
@@ -295,9 +357,46 @@
         # then add all the values
         for label_value in label_values :
             kwargs[label_value.label.key] = label_value.value
+       
+        # then parse all query args
+        # XXX: catch missing arguments
+        for key, value in request.get_args() :
+            # lookup spec
+            type, default = self.query_args[key]
+
+            # normalize empty value to None
+            if not value :
+                value = None
+
+            else :
+                # process value
+                value = type(value)
+
+            # set default?
+            if not value :
+                if default :
+                    value = default
+
+                if default == '' :
+                    # do not pass key at all
+                    continue
+
+                # otherwise, fail
+                raise URLError("No value given for required argument: %r" % (key, ))
             
+            # set key
+            kwargs[key] = value
+
         # execute the handler
         return self.handler(request, **kwargs)
+    
+    def build (self, request, **values) :
+        """
+            Build an absolute URL pointing to this target, with the given values
+        """
+
+        # build URL from request page prefix and our labels
+        return request.page_prefix + '/'.join(label.build(values) for label in self.label_path)
 
     def __str__ (self) :
         return '/'.join(str(label) for label in self.label_path)