249 img.save(buf, format) |
259 img.save(buf, format) |
250 data = buf.getvalue() |
260 data = buf.getvalue() |
251 |
261 |
252 return data |
262 return data |
253 |
263 |
254 def arg_bool (val) : |
264 class OptionType (object) : |
255 if val.lower() in ('true', 't', '1', 'yes', 'y') : |
265 def parse (self, val) : |
256 return True |
266 """ |
257 elif val.lower() in ('false', 'f', '0', 'no', 'n') : |
267 Unicode value -> object |
258 return False |
268 """ |
259 else : |
269 |
260 raise ValueError(val) |
270 abstract |
261 |
271 |
262 def arg_color (val) : |
272 def build (self, val) : |
263 if val.beginswith('#') : |
273 """ |
264 int(val[1:], 16) |
274 object -> unicode value |
265 |
275 """ |
266 return val |
276 |
267 else : |
277 return unicode(val) |
268 raise ValueError(val) |
278 |
|
279 def input (self, val) : |
|
280 """ |
|
281 HTML input item |
|
282 """ |
|
283 |
|
284 abstract |
|
285 |
|
286 class StringOption (OptionType) : |
|
287 def parse (self, val) : |
|
288 return unicode(val) |
|
289 |
|
290 def build (self, val) : |
|
291 if val is None : |
|
292 return "" |
|
293 |
|
294 else : |
|
295 return val |
|
296 |
|
297 def input (self, opt, val) : |
|
298 return """<input type="text" name="%(name)s" id="%(name)s" value="%(value)s" />""" % dict( |
|
299 name = opt.name, |
|
300 value = self.build(val), |
|
301 ) |
|
302 |
|
303 def select (self, opt, val) : |
|
304 return """<select name="%(name)s"> |
|
305 %(options)s |
|
306 </select>""" % dict( |
|
307 name = opt.name, |
|
308 options = '\n'.join( |
|
309 "\t<option %(selected)s>%(value)s</option>" % dict( |
|
310 value = self.build(optval), |
|
311 selected = 'selected="selected"' if val == optval else "", |
|
312 ) for optval in opt.range |
|
313 ), |
|
314 ) |
|
315 |
|
316 class BoolOption (OptionType) : |
|
317 def parse (self, val) : |
|
318 if val.lower() in ('true', 't', '1', 'yes', 'y') : |
|
319 return True |
|
320 |
|
321 elif val.lower() in ('false', 'f', '0', 'no', 'n') : |
|
322 return False |
|
323 |
|
324 else : |
|
325 raise ValueError(val) |
|
326 |
|
327 def input (self, opt, val) : |
|
328 return """<input type="checkbox" name="%(name)s" id="%(name)s" %(checked)s/>""" % dict( |
|
329 name = opt.name, |
|
330 checked = 'checked="checked"' if val else '', |
|
331 ) |
|
332 |
|
333 class IntOption (StringOption) : |
|
334 def parse (self, val) : |
|
335 return int(val) |
|
336 |
|
337 class FloatOption (StringOption) : |
|
338 def parse (self, val) : |
|
339 return float(val) |
|
340 |
|
341 class ColorOption (StringOption) : |
|
342 def _parse (self, val) : |
|
343 if val.startswith('#') : |
|
344 int(val[1:], 16) |
|
345 |
|
346 return val |
|
347 else : |
|
348 raise ValueError(val) |
|
349 |
269 |
350 |
270 class Option (object) : |
351 class Option (object) : |
271 def __init__ (self, name, is_list, type, default, range) : |
352 def __init__ (self, name, is_list, type, default, range) : |
272 self.name = name |
353 self.name = name |
273 self.is_list = is_list |
354 self.is_list = is_list |
274 self.type = type |
355 self.type = type |
275 self.default = default |
356 self.default = default |
276 self.range = range |
357 self.range = range |
277 |
358 |
278 def parse (self, args) : |
359 def parse (self, args, force_bool=False) : |
279 if self.is_list : |
360 if self.is_list : |
280 if self.name in args : |
361 if self.name in args : |
281 return args.getlist(self.name, self.type) |
362 l = args.getlist(self.name, self.type.parse) |
|
363 |
|
364 # special-case to handle a single param with a newline-separtated list |
|
365 if len(l) == 1 : |
|
366 if not l[0] : |
|
367 return None |
|
368 |
|
369 else : |
|
370 return l[0].split('\r\n') |
|
371 |
|
372 else : |
|
373 return l |
|
374 |
282 else : |
375 else : |
283 return self.default |
376 return self.default |
284 else : |
377 |
285 if self.type == arg_bool and not self.default and self.name in args : |
378 else : |
|
379 if isinstance(self.type, BoolOption) and force_bool : |
|
380 return self.name in args |
|
381 |
|
382 elif isinstance(self.type, BoolOption) and not self.default and self.name in args : |
286 return True |
383 return True |
287 |
384 |
288 else : |
385 else : |
289 return args.get(self.name, self.default, self.type) |
386 return args.get(self.name, self.default, self.type.parse) |
|
387 |
|
388 def build_list (self, value) : |
|
389 if self.is_list and value : |
|
390 return [self.type.build(val) for val in value] |
|
391 |
|
392 else : |
|
393 return [self.type.build(value)] |
|
394 |
|
395 def _build_input (self, value) : |
|
396 if self.is_list : |
|
397 return """\ |
|
398 <textarea name="%(name)s" cols="30">\ |
|
399 %(data)s\ |
|
400 </textarea>""" % dict( |
|
401 name = self.name, |
|
402 data = '\n'.join(self.type.build(val) for val in value) if value else '', |
|
403 ) |
|
404 |
|
405 elif self.range : |
|
406 return self.type.select(self, value) |
|
407 |
|
408 else : |
|
409 return self.type.input(self, value) |
|
410 |
|
411 def build_form (self, opts) : |
|
412 value = opts[self.name] |
|
413 |
|
414 return """\ |
|
415 <div class="param"><label for="%(name)s">%(title)s</label>%(input)s</div>\ |
|
416 """ % dict( |
|
417 name = self.name, |
|
418 title = self.name.title().replace('-', ' '), |
|
419 input = self._build_input(value) |
|
420 ) |
290 |
421 |
291 class Options (object) : |
422 class Options (object) : |
292 def __init__ (self, *options) : |
423 def __init__ (self, *options) : |
293 self.options = options |
424 self.options = list(options) |
294 |
425 self.options_by_name = dict((opt.name, opt) for opt in options) |
295 def parse (self, args) : |
426 |
296 return dict((opt.name, opt.parse(args)) for opt in self.options) |
427 def parse (self, args, **kwargs) : |
|
428 return dict((opt.name, opt.parse(args, **kwargs)) for opt in self.options) |
297 |
429 |
298 OPTIONS = Options( |
430 OPTIONS = Options( |
299 Option('lang', False, str, Defaults.text_lang, TEXT_BY_LANG.keys()), |
431 Option('lang', False, StringOption(), Defaults.text_lang, TEXT_BY_LANG.keys()), |
300 Option('text', True, unicode, None, None), |
432 Option('text', True, StringOption(), None, None), |
301 Option('random-text', False, arg_bool, False, None), |
433 Option('random-text', False, BoolOption(), False, None), |
302 Option('random-text-char', False, arg_bool, False, None), |
434 Option('random-text-char',False,BoolOption(), False, None), |
303 Option('chars', True, unicode, Defaults.chars, None), |
435 Option('chars', True, StringOption(), Defaults.chars, None), |
304 Option('random-chars', False, arg_bool, True, None), |
436 Option('random-chars', False, BoolOption(), True, None), |
305 Option('colors', True, arg_color, Defaults.colors, None), |
437 Option('colors', True, ColorOption(), Defaults.colors, None), |
306 Option('font', False, str, Defaults.font_name, FONTS.keys()), |
438 Option('font', False, StringOption(), Defaults.font_name, FONTS.keys()), |
307 Option('font-size', False, int, Defaults.font_size, None), |
439 Option('font-size', False, IntOption(), Defaults.font_size, None), |
308 Option('bg-color', False, arg_color, Defaults.bg_color, None), |
440 Option('bg-color', False, ColorOption(), Defaults.bg_color, None), |
309 Option('line-spacing', False, int, Defaults.line_spacing, None), |
441 Option('line-spacing', False, IntOption(), Defaults.line_spacing, None), |
310 Option('sharpness', False, float, Defaults.sharpness, None), |
442 Option('sharpness', False, FloatOption(), Defaults.sharpness, None), |
311 Option('image-format', False, str, Defaults.img_format, IMAGE_FORMATS.keys()), |
443 Option('image-format', False, StringOption(), Defaults.img_format, IMAGE_FORMATS.keys()), |
312 Option('seed', False, int, None, None), |
444 Option('seed', False, IntOption(), None, None), |
313 Option('img_width', False, int, None, None), |
445 Option('img_width', False, IntOption(), None, None), |
314 Option('img_height', False, int, None, None), |
446 Option('img_height', False, IntOption(), None, None), |
315 ) |
447 ) |
316 |
448 |
317 def handle_generic (req, img_size=None) : |
449 def handle_generic (req, img_size=None) : |
318 # parse options |
450 # parse options |
319 opts = OPTIONS.parse(req.args) |
451 opts = OPTIONS.parse(req.args) |