tests/formdata.py
Rama main · réplica de lectura del repositorio original.
"""What a browser would send from a form on a page, read off its HTML."""
from __future__ import annotations
from html.parser import HTMLParser
def as_sent(page: str, action: str) -> dict[str, str | list[str]]:
"""Every field of the form posting to `action`, as a browser submits it: a
checkbox only when ticked, a select as its chosen option, a textarea as
its text, nothing disabled. A name used more than once is a list."""
form = _Form(action)
form.feed(page)
return {name: values[0] if len(values) == 1 else values
for name, values in form.fields.items()}
class _Form(HTMLParser):
def __init__(self, action: str):
super().__init__()
self.action = action
self.fields: dict[str, list[str]] = {}
self.inside = False
self.text_of: str | None = None
self.select: str | None = None
def _add(self, name: str, value: str) -> None:
self.fields.setdefault(name, []).append(value)
def handle_starttag(self, tag, attrs):
a = dict(attrs)
if tag == "form":
self.inside = a.get("action") == self.action
if not self.inside or "disabled" in a:
return
if tag == "input" and a.get("name"):
if a.get("type") not in ("checkbox", "radio") or "checked" in a:
self._add(a["name"], a.get("value") or "")
elif tag == "textarea":
self.text_of = a["name"]
self._add(a["name"], "")
elif tag == "select":
self.select = a["name"]
elif tag == "option" and self.select and "selected" in a:
self._add(self.select, a.get("value") or "")
def handle_endtag(self, tag):
if tag == "form":
self.inside = False
elif tag == "textarea":
self.text_of = None
elif tag == "select":
self.select = None
def handle_data(self, data):
if self.text_of:
self.fields[self.text_of][-1] += data