# HG changeset patch # User Tero Marttila # Date 1241549396 -10800 # Node ID 9234f5ae765b038f301d159cb4c67be38e0b5505 # Parent 707ddd7a7912d7a3b9ac63e19fafb35889534966 add index HTML interface diff -r 707ddd7a7912 -r 9234f5ae765b index.py --- a/index.py Tue May 05 19:39:44 2009 +0300 +++ b/index.py Tue May 05 21:49:56 2009 +0300 @@ -126,7 +126,12 @@ """ data = [] - + + # if no chars given, don't insert any + if not chars : + chars = [] + + # randomize char order across lines? if random_chars : chars = randomize(chars) @@ -135,11 +140,16 @@ continue # pick position to place char - pos = random.randint(1, len(line) - 1) - + if len(line) >= 2 : + pos = random.randint(1, len(line) - 1) + else : + pos = random.randint(0, 1) + + # default color if not color : color = "#000000" - + + # randomize text in some way? if random_text : line = ''.join(randomize(line)) @@ -251,21 +261,92 @@ return data -def arg_bool (val) : - if val.lower() in ('true', 't', '1', 'yes', 'y') : - return True - elif val.lower() in ('false', 'f', '0', 'no', 'n') : - return False - else : - raise ValueError(val) +class OptionType (object) : + def parse (self, val) : + """ + Unicode value -> object + """ -def arg_color (val) : - if val.beginswith('#') : - int(val[1:], 16) + abstract - return val - else : - raise ValueError(val) + def build (self, val) : + """ + object -> unicode value + """ + + return unicode(val) + + def input (self, val) : + """ + HTML input item + """ + + abstract + +class StringOption (OptionType) : + def parse (self, val) : + return unicode(val) + + def build (self, val) : + if val is None : + return "" + + else : + return val + + def input (self, opt, val) : + return """""" % dict( + name = opt.name, + value = self.build(val), + ) + + def select (self, opt, val) : + return """""" % dict( + name = opt.name, + options = '\n'.join( + "\t" % dict( + value = self.build(optval), + selected = 'selected="selected"' if val == optval else "", + ) for optval in opt.range + ), + ) + +class BoolOption (OptionType) : + def parse (self, val) : + if val.lower() in ('true', 't', '1', 'yes', 'y') : + return True + + elif val.lower() in ('false', 'f', '0', 'no', 'n') : + return False + + else : + raise ValueError(val) + + def input (self, opt, val) : + return """""" % dict( + name = opt.name, + checked = 'checked="checked"' if val else '', + ) + +class IntOption (StringOption) : + def parse (self, val) : + return int(val) + +class FloatOption (StringOption) : + def parse (self, val) : + return float(val) + +class ColorOption (StringOption) : + def _parse (self, val) : + if val.startswith('#') : + int(val[1:], 16) + + return val + else : + raise ValueError(val) + class Option (object) : def __init__ (self, name, is_list, type, default, range) : @@ -275,43 +356,94 @@ self.default = default self.range = range - def parse (self, args) : + def parse (self, args, force_bool=False) : if self.is_list : if self.name in args : - return args.getlist(self.name, self.type) + l = args.getlist(self.name, self.type.parse) + + # special-case to handle a single param with a newline-separtated list + if len(l) == 1 : + if not l[0] : + return None + + else : + return l[0].split('\r\n') + + else : + return l + else : return self.default + else : - if self.type == arg_bool and not self.default and self.name in args : + if isinstance(self.type, BoolOption) and force_bool : + return self.name in args + + elif isinstance(self.type, BoolOption) and not self.default and self.name in args : return True else : - return args.get(self.name, self.default, self.type) + return args.get(self.name, self.default, self.type.parse) + + def build_list (self, value) : + if self.is_list and value : + return [self.type.build(val) for val in value] + + else : + return [self.type.build(value)] + + def _build_input (self, value) : + if self.is_list : + return """\ +""" % dict( + name = self.name, + data = '\n'.join(self.type.build(val) for val in value) if value else '', + ) + + elif self.range : + return self.type.select(self, value) + + else : + return self.type.input(self, value) + + def build_form (self, opts) : + value = opts[self.name] + + return """\ +
%(input)s
\ + """ % dict( + name = self.name, + title = self.name.title().replace('-', ' '), + input = self._build_input(value) + ) class Options (object) : def __init__ (self, *options) : - self.options = options + self.options = list(options) + self.options_by_name = dict((opt.name, opt) for opt in options) - def parse (self, args) : - return dict((opt.name, opt.parse(args)) for opt in self.options) + def parse (self, args, **kwargs) : + return dict((opt.name, opt.parse(args, **kwargs)) for opt in self.options) OPTIONS = Options( - Option('lang', False, str, Defaults.text_lang, TEXT_BY_LANG.keys()), - Option('text', True, unicode, None, None), - Option('random-text', False, arg_bool, False, None), - Option('random-text-char', False, arg_bool, False, None), - Option('chars', True, unicode, Defaults.chars, None), - Option('random-chars', False, arg_bool, True, None), - Option('colors', True, arg_color, Defaults.colors, None), - Option('font', False, str, Defaults.font_name, FONTS.keys()), - Option('font-size', False, int, Defaults.font_size, None), - Option('bg-color', False, arg_color, Defaults.bg_color, None), - Option('line-spacing', False, int, Defaults.line_spacing, None), - Option('sharpness', False, float, Defaults.sharpness, None), - Option('image-format', False, str, Defaults.img_format, IMAGE_FORMATS.keys()), - Option('seed', False, int, None, None), - Option('img_width', False, int, None, None), - Option('img_height', False, int, None, None), + Option('lang', False, StringOption(), Defaults.text_lang, TEXT_BY_LANG.keys()), + Option('text', True, StringOption(), None, None), + Option('random-text', False, BoolOption(), False, None), + Option('random-text-char',False,BoolOption(), False, None), + Option('chars', True, StringOption(), Defaults.chars, None), + Option('random-chars', False, BoolOption(), True, None), + Option('colors', True, ColorOption(), Defaults.colors, None), + Option('font', False, StringOption(), Defaults.font_name, FONTS.keys()), + Option('font-size', False, IntOption(), Defaults.font_size, None), + Option('bg-color', False, ColorOption(), Defaults.bg_color, None), + Option('line-spacing', False, IntOption(), Defaults.line_spacing, None), + Option('sharpness', False, FloatOption(), Defaults.sharpness, None), + Option('image-format', False, StringOption(), Defaults.img_format, IMAGE_FORMATS.keys()), + Option('seed', False, IntOption(), None, None), + Option('img_width', False, IntOption(), None, None), + Option('img_height', False, IntOption(), None, None), ) def handle_generic (req, img_size=None) : @@ -374,8 +506,81 @@ def handle_tile (req) : return handle_generic(req, img_size=TILE_SIZE) +def handle_index (options, req) : + # parse options, force booleans if any form data was submitted, as checkboxes work that way + opts = options.parse(req.values, force_bool=bool(req.form)) + + # build query string of req things + qargs = [ + (opt.name, opt.build_list(val)) for opt, val in ( + (options.options_by_name[opt_name], val) for opt_name, val in opts.iteritems() + ) if val != opt.default + ] + + img_url = req.url_root + "logo" + ("?%s" % werkzeug.url_encode(qargs) if qargs else '') + + return werkzeug.Response("""\ + + + Aaltologotin + + + + +
+

Aaltologotin

+

Aaltologotin pulauttaa sulle uuden, sattumanvaraisesti valitun aalto-logon!

+ +
+
+ Aalto-parameterit +%(form_fields)s + +
+
+
+ +""" % dict( + img_url = img_url, + form_fields = "\n".join( + "\t%s" % opt.build_form(opts) for opt in options.options + ), + ), mimetype='text/html') + def handle_request (req) : - if req.path == '/' or req.path.startswith('/logo.') : + if req.path == '/' : + return handle_index(OPTIONS, req) + + elif req.path.startswith('/logo') : return handle_logo(req) elif req.path == '/tile' :