sites/irclogs.qmsk.net/urltree.py
branchsites
changeset 42 5a72c00c4ae4
parent 41 9585441a4bfb
child 43 fc11c4e86a82
equal deleted inserted replaced
41:9585441a4bfb 42:5a72c00c4ae4
    91 
    91 
    92             If value is None, this means that only a default value should be returned.
    92             If value is None, this means that only a default value should be returned.
    93         """
    93         """
    94 
    94 
    95         abstract
    95         abstract
       
    96     
       
    97     def build (self, value_dict) :
       
    98         """
       
    99             Return a string representing this label, using the values in the given value_dict if needed
       
   100         """
       
   101 
       
   102         abstract
    96 
   103 
    97 class EmptyLabel (Label) :
   104 class EmptyLabel (Label) :
    98     """
   105     """
    99         An empty label, i.e. just a slash in the URL
   106         An empty label, i.e. just a slash in the URL
   100     """
   107     """
   116             return False
   123             return False
   117         
   124         
   118         # only empty segments
   125         # only empty segments
   119         if value == '' :
   126         if value == '' :
   120             return True
   127             return True
       
   128     
       
   129     def build (self, values) :
       
   130         return str(self)
   121 
   131 
   122     def __str__ (self) :
   132     def __str__ (self) :
   123         return ''
   133         return ''
   124 
   134 
   125 class StaticLabel (Label) :
   135 class StaticLabel (Label) :
   154         
   164         
   155         # match name
   165         # match name
   156         if value == self.name :
   166         if value == self.name :
   157             return True
   167             return True
   158 
   168 
       
   169     def build (self, values) :
       
   170         return str(self)
       
   171 
   159     def __str__ (self) :
   172     def __str__ (self) :
   160         return self.name
   173         return self.name
   161 
   174 
   162 class ValueLabel (Label) :
   175 class ValueLabel (Label) :
   163     """
   176     """
   178         """
   191         """
   179             Compares keys
   192             Compares keys
   180         """
   193         """
   181 
   194 
   182         return isinstance(other, ValueLabel) and self.key == other.key
   195         return isinstance(other, ValueLabel) and self.key == other.key
       
   196     
       
   197     def build (self, values) :
       
   198         """
       
   199             Return either the assigned value from values, our default value, or raise an error
       
   200         """
       
   201 
       
   202         value = values.get(self.key)
       
   203         
       
   204         if not value and self.default :
       
   205             value = self.default
       
   206 
       
   207         elif not value :
       
   208             raise URLError("No value given for label %r" % (self.key, ))
       
   209 
       
   210         return value
   183 
   211 
   184 class SimpleValueLabel (ValueLabel) :
   212 class SimpleValueLabel (ValueLabel) :
   185     """
   213     """
   186         A label that has a name and a simple string value
   214         A label that has a name and a simple string value
   187     """
   215     """
   271         self.config = config
   299         self.config = config
   272         self.url_mask = url_mask
   300         self.url_mask = url_mask
   273         self.handler = handler
   301         self.handler = handler
   274         self.defaults = defaults
   302         self.defaults = defaults
   275 
   303 
   276         # build our labels
   304         # query string
       
   305         self.query_args = dict()
       
   306         
       
   307         # parse any query string
       
   308         # XXX: conflicts with regexp syntax
       
   309         if '/?' in url_mask :
       
   310             url_mask, query_mask = url_mask.split('/?')
       
   311         
       
   312         else :
       
   313             query_mask = None
       
   314 
       
   315         # build our label path
   277         self.label_path = [Label.parse(mask, defaults, config.type_dict) for mask in url_mask.split('/')]
   316         self.label_path = [Label.parse(mask, defaults, config.type_dict) for mask in url_mask.split('/')]
   278         
   317 
       
   318         # build our query args list
       
   319         if query_mask :
       
   320             # split into items
       
   321             for query_item in query_mask.split('&') :
       
   322                 # parse default
       
   323                 if '=' in query_item :
       
   324                     query_item, default = query_item.split('=')
       
   325 
       
   326                 else :
       
   327                     default = None
       
   328                 
       
   329                 # parse type
       
   330                 if ':' in query_item :
       
   331                     query_item, type = query_item.split(':')
       
   332                 else :
       
   333                     type = None
       
   334                 
       
   335                 # parse key
       
   336                 key = query_item
       
   337 
       
   338                 # add to query_args as (type, default) tuple
       
   339                 self.query_args[key] = (self.config.type_dict[type], default)
       
   340          
   279     def get_label_path (self) :
   341     def get_label_path (self) :
   280         """
   342         """
   281             Returns a list containing the labels in this url
   343             Returns a list containing the labels in this url
   282         """
   344         """
   283         
   345         
   293         kwargs = self.defaults.copy()
   355         kwargs = self.defaults.copy()
   294 
   356 
   295         # then add all the values
   357         # then add all the values
   296         for label_value in label_values :
   358         for label_value in label_values :
   297             kwargs[label_value.label.key] = label_value.value
   359             kwargs[label_value.label.key] = label_value.value
       
   360        
       
   361         # then parse all query args
       
   362         # XXX: catch missing arguments
       
   363         for key, value in request.get_args() :
       
   364             # lookup spec
       
   365             type, default = self.query_args[key]
       
   366 
       
   367             # normalize empty value to None
       
   368             if not value :
       
   369                 value = None
       
   370 
       
   371             else :
       
   372                 # process value
       
   373                 value = type(value)
       
   374 
       
   375             # set default?
       
   376             if not value :
       
   377                 if default :
       
   378                     value = default
       
   379 
       
   380                 if default == '' :
       
   381                     # do not pass key at all
       
   382                     continue
       
   383 
       
   384                 # otherwise, fail
       
   385                 raise URLError("No value given for required argument: %r" % (key, ))
   298             
   386             
       
   387             # set key
       
   388             kwargs[key] = value
       
   389 
   299         # execute the handler
   390         # execute the handler
   300         return self.handler(request, **kwargs)
   391         return self.handler(request, **kwargs)
       
   392     
       
   393     def build (self, request, **values) :
       
   394         """
       
   395             Build an absolute URL pointing to this target, with the given values
       
   396         """
       
   397 
       
   398         # build URL from request page prefix and our labels
       
   399         return request.page_prefix + '/'.join(label.build(values) for label in self.label_path)
   301 
   400 
   302     def __str__ (self) :
   401     def __str__ (self) :
   303         return '/'.join(str(label) for label in self.label_path)
   402         return '/'.join(str(label) for label in self.label_path)
   304     
   403     
   305     def __repr__ (self) :
   404     def __repr__ (self) :