|
| 1 | +# |
| 2 | +# The goal is to finally have a form filler where you pass data for |
| 3 | +# each form, using the algorithm for "Seeding a form with initial values" |
| 4 | +# See http://www.whatwg.org/specs/web-forms/current-work/#seeding |
| 5 | +# |
| 6 | + |
| 7 | +import _base |
| 8 | + |
| 9 | +from html5lib.constants import spaceCharacters |
| 10 | +spaceCharacters = u"".join(spaceCharacters) |
| 11 | + |
| 12 | +class SimpleFilter(_base.Filter): |
| 13 | + def __init__(self, source, fieldStorage): |
| 14 | + _base.Filter.__init__(self, source) |
| 15 | + self.fieldStorage = fieldStorage |
| 16 | + |
| 17 | + def __iter__(self): |
| 18 | + field_indices = {} |
| 19 | + state = None |
| 20 | + field_name = None |
| 21 | + for token in _base.Filter.__iter__(self): |
| 22 | + type = token["type"] |
| 23 | + if type in ("StartTag", "EmptyTag"): |
| 24 | + name = token["name"].lower() |
| 25 | + if name == "input": |
| 26 | + field_name = None |
| 27 | + field_type = None |
| 28 | + input_value_index = -1 |
| 29 | + input_checked_index = -1 |
| 30 | + for i,(n,v) in enumerate(token["data"]): |
| 31 | + n = n.lower() |
| 32 | + if n == "name": |
| 33 | + field_name = v.strip(spaceCharacters) |
| 34 | + elif n == "type": |
| 35 | + field_type = v.strip(spaceCharacters) |
| 36 | + elif n == "checked": |
| 37 | + input_checked_index = i |
| 38 | + elif n == "value": |
| 39 | + input_value_index = i |
| 40 | + |
| 41 | + value_list = self.fieldStorage.getlist(field_name) |
| 42 | + field_index = field_indices.setdefault(field_name, 0) |
| 43 | + if field_index < len(value_list): |
| 44 | + value = value_list[field_index] |
| 45 | + else: |
| 46 | + value = "" |
| 47 | + |
| 48 | + if type in ("checkbox", "radio"): |
| 49 | + if value_list: |
| 50 | + if token["data"][input_value_index] == value: |
| 51 | + if input_checked_index < 0: |
| 52 | + token["data"].append((u"checked", u"")) |
| 53 | + field_indices[field_name] = field_index + 1 |
| 54 | + elif input_checked_index >= 0: |
| 55 | + del token["data"][input_checked_index] |
| 56 | + |
| 57 | + elif type not in ("button", "submit", "reset"): |
| 58 | + if input_value_index >= 0: |
| 59 | + token["data"][input_value_index] = (u"value", value) |
| 60 | + else: |
| 61 | + token["data"].append((u"value", value)) |
| 62 | + field_indices[field_name] = field_index + 1 |
| 63 | + |
| 64 | + field_type = None |
| 65 | + field_name = None |
| 66 | + |
| 67 | + elif name == "textarea": |
| 68 | + field_type = "textarea" |
| 69 | + field_name = dict(reversed(token["data"]))["name"] |
| 70 | + |
| 71 | + elif name == "select": |
| 72 | + field_type = "select" |
| 73 | + attributes = dict(reversed(token["data"])) |
| 74 | + field_name = attributes.get("name") |
| 75 | + is_select_multiple = "multiple" in attributes |
| 76 | + |
| 77 | + elif state == "in_select" and field_name and name == "option": |
| 78 | + option_selected_index = -1 |
| 79 | + option_value = None |
| 80 | + for i,(n,v) in enumerate(token["data"]): |
| 81 | + n = n.lower() |
| 82 | + if n == "selected": |
| 83 | + option_selected_index = i |
| 84 | + elif n == "value": |
| 85 | + option_value = v.strip(spaceCharacters) |
| 86 | + if option_value is None: |
| 87 | + raise NotImplementedError("<option>s must have a value= attribute") |
| 88 | + else: |
| 89 | + value_list = self.fieldStorage.getlist(field_name) |
| 90 | + if value_list: |
| 91 | + field_index = field_indices.setdefault(field_name, 0) |
| 92 | + if field_index < len(value_list): |
| 93 | + value = value_list[field_index] |
| 94 | + else: |
| 95 | + value = "" |
| 96 | + if option_value == value: |
| 97 | + if option_selected_index < 0: |
| 98 | + token["data"].append((u"selected", u"")) |
| 99 | + field_indices[field_name] = field_index + 1 |
| 100 | + elif option_selected_index >= 0: |
| 101 | + del token["data"][option_selected_index] |
| 102 | + |
| 103 | + elif field_type is not None and field_name and type == "EndTag": |
| 104 | + name = token["name"].lower() |
| 105 | + if name == "textarea": |
| 106 | + value_list = self.fieldStorage.getlist(field_name) |
| 107 | + if value_list: |
| 108 | + field_index = field_indices.setdefault(field_name, 0) |
| 109 | + if field_index < len(value_list): |
| 110 | + value = value_list[field_index] |
| 111 | + else: |
| 112 | + value = "" |
| 113 | + yield {"type": "Characters", "data": value} |
| 114 | + |
| 115 | + field_indices[field_name] = field_index + 1 |
| 116 | + field_name = None |
| 117 | + |
| 118 | + elif field_type == "textarea": |
| 119 | + continue # ignore token |
| 120 | + |
| 121 | + yield token |
0 commit comments