--- 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 """<input type="text" name="%(name)s" id="%(name)s" value="%(value)s" />""" % dict(
+ name = opt.name,
+ value = self.build(val),
+ )
+
+ def select (self, opt, val) :
+ return """<select name="%(name)s">
+%(options)s
+</select>""" % dict(
+ name = opt.name,
+ options = '\n'.join(
+ "\t<option %(selected)s>%(value)s</option>" % 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 """<input type="checkbox" name="%(name)s" id="%(name)s" %(checked)s/>""" % 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 """\
+<textarea name="%(name)s" cols="30">\
+%(data)s\
+</textarea>""" % 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 """\
+<div class="param"><label for="%(name)s">%(title)s</label>%(input)s</div>\
+ """ % 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("""\
+<html>
+ <head>
+ <title>Aaltologotin</title>
+ <style type="text/css">
+div#logo {
+ text-align: center;
+ padding: 100px;
+}
+
+img {
+ border: none;
+}
+
+div#info {
+ font-size: small;
+ padding-left: 25px;
+ margin-top: 50px;
+ color: grey;
+}
+
+label {
+ display: block;
+ float: left;
+
+ width: 150px;
+}
+
+div.param {
+ padding: 3px;
+}
+ </style>
+ </head>
+ <body>
+ <div id='logo'>
+ <a href="%(img_url)s"><img src="%(img_url)s" alt="Aaltologo" /></a>
+ </div>
+ <div id='info'>
+ <h1>Aaltologotin</h1>
+ <p>Aaltologotin pulauttaa sulle uuden, sattumanvaraisesti valitun aalto-logon!</p>
+
+ <form action="." method="POST">
+ <fieldset>
+ <legend>Aalto-parameterit</legend>
+%(form_fields)s
+ <input type="submit" value="Logota!" />
+ </fieldset>
+ </form>
+ </div>
+ </body>
+</html>""" % 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' :