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 """ |
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) : |