import HTMLParser import cgi class FillingParser(HTMLParser.HTMLParser): r""" Fills HTML with default values, as in a form. Examples:: >>> defaults = {'name': 'Bob Jones', ... 'occupation': 'Crazy Cultist', ... 'address': '14 W. Canal\nNew Guinea', ... 'living': 'no', ... 'nice_guy': 0} >>> parser = FillingParser(defaults) >>> parser.feed('\ ... \ ... \ ... ') >>> print parser.text() """ def __init__(self, defaults, errors=None, use_all_keys=False): HTMLParser.HTMLParser.__init__(self) self.content = [] self.source = None self.lines = None self.source_pos = None self.defaults = defaults self.in_textarea = None self.in_select = None self.skip_next = False self.errors = errors or {} self.in_error = None self.skip_error = False self.use_all_keys = use_all_keys self.used_keys = {} self.used_errors = {} def feed(self, data): self.source = data self.lines = data.split('\n') self.source_pos = 1, 0 HTMLParser.HTMLParser.feed(self, data) def close(self): HTTPParser.HTTPParser.close(self) if self.use_all_keys: unused = self.defaults.copy() unused_errors = self.errors.copy() for key in self.used_keys.keys(): if self.unused.has_key(key): del unused[key] for key in self.used_errors.keys(): if self.unused_errors.has_key(key): del unused_errors[key] assert not unused, "These keys from defaults were not used in the form: %s" % unused.keys() assert not unused_errors, "These keys from errors were not used in the form: %s" % unused_errors.keys() def add_key(self, key): self.used_keys[key] = 1 def handle_starttag(self, tag, attrs): self.write_pos() if tag == 'input': self.handle_input(attrs) elif tag == 'textarea': self.handle_textarea(attrs) elif tag == 'select': self.handle_select(attrs) elif tag == 'option': self.handle_option(attrs) elif tag == 'error': self.handle_error(attrs) elif tag == 'iferror': self.handle_iferror(attrs) def handle_misc(self, whatever): self.write_pos() handle_charref = handle_misc handle_entityref = handle_misc handle_data = handle_misc handle_comment = handle_misc handle_decl = handle_misc handle_pi = handle_misc unknown_decl = handle_misc def handle_endtag(self, tag): self.write_pos() if tag == 'textarea': self.handle_end_textarea() elif tag == 'select': self.handle_end_select() elif tag == 'iferror': self.handle_end_iferror() def handle_iferror(self, attrs): name = self.get_attr(attrs, 'name') assert name, "Name attribute in required (%s)" % self.getpos() self.in_error = name if not self.errors.get(name): self.skip_error = True self.skip_next = True def handle_end_iferror(self, attrs): self.in_error = None self.skip_error = False self.skip_next = False def handle_error(self, attr): name = self.get_attr(attrs, 'name') if not name: name = self.in_error assert name, "Name attribute in required if not contained in (%s)" % self.getpos() error = self.errors.get(name, '') self.write_text(error) self.skip_next = True self.used_errors[name] = 1 def handle_input(self, attrs): t = (self.get_attr(attrs, 'type') or 'text').lower() name = self.get_attr(attrs, 'name') value = self.defaults.get(name) if t == 'text': self.set_attr(attrs, 'value', value or '') self.write_tag('input', attrs) self.skip_next = True self.add_key(name) elif t == 'checkbox': if str(value) == self.get_attr(attrs, 'value'): self.set_attr(attrs, 'checked', 'checked') else: self.del_attr(attrs, 'checked') self.write_tag('input', attrs) self.skip_next = True self.add_key(name) elif t == 'radio': if str(value) == self.get_attr(attrs, 'value'): self.set_attr(attrs, 'selected', 'selected') else: self.del_attr(attrs, 'selected') self.write_tag('input', attrs) self.skip_next = True self.add_key(name) elif t in ('file', 'button', 'submit', 'reset'): pass # don't skip next else: assert 0, "I don't know about this kind of : %s (pos: %s)" \ % (t, self.getpos()) def handle_textarea(self, attrs): self.write_tag('textarea', attrs) name = self.get_attr(attrs, 'name') value = self.defaults.get(name, '') self.write_text(cgi.escape(value, 1)) self.write_text('') self.in_textarea = True self.add_key(name) def handle_end_textarea(self): self.in_textarea = False self.skip_next = True def handle_select(self, attrs): self.in_select = self.get_attr(attrs, 'name') def handle_end_select(self): self.in_select = None def handle_option(self, attrs): assert self.in_select, "