%PDF- %PDF-
| Direktori : /lib/python3/dist-packages/mechanize/ |
| Current File : //lib/python3/dist-packages/mechanize/_form.py |
from __future__ import absolute_import
import re
from collections import defaultdict
from ._form_controls import HTMLForm, Label
from ._request import Request
from .polyglot import urljoin, is_string, as_unicode
class SkipControl(ValueError):
pass
def normalize_line_endings(text):
return re.sub(as_unicode(r"(?:(?<!\r)\n)|(?:\r(?!\n))"), u"\r\n", text)
def label_text(elem):
ans = []
if elem.text:
ans.append(elem.text)
for child in elem:
if child.tail:
ans.append(child.tail)
return ''.join(ans)
def parse_control(elem, parent_of, default_type='text'):
attrs = dict(elem.attrib)
label_elem = parent_of(elem, 'label')
if label_elem is not None:
lt = label_text(label_elem)
if lt:
attrs["__label"] = lt
ctype = attrs.get('type') or default_type
return ctype, attrs.get('name'), attrs
def parse_input(elem, parent_of, *a):
return parse_control(elem, parent_of)
def parse_button(elem, parent_of, *a):
ctype, name, attrs = parse_control(elem, parent_of, default_type='submit')
ctype += 'button'
return ctype, name, attrs
def parse_option(elem, parent_of, attrs_map):
ctype, name, attrs = parse_control(elem, parent_of)
og = parent_of(elem, 'optgroup')
contents = (elem.text or '').strip()
attrs['contents'] = contents
attrs['value'] = attrs.get('value', contents)
attrs['label'] = attrs.get('label', contents)
if og is not None and og.get('disabled') is not None:
attrs['disabled'] = 'disabled'
sel = parent_of(elem, 'select')
if sel is None:
raise SkipControl()
attrs['__select'] = sel = attrs_map[sel]['__select']
return 'select', sel.get('name'), attrs
def parse_textarea(elem, parent_of, *a):
ctype, name, attrs = parse_control(elem, parent_of)
ctype = 'textarea'
attrs['value'] = normalize_line_endings(elem.text or u'')
return ctype, name, attrs
def parse_select(elem, parent_of, *a):
ctype, name, attrs = parse_control(elem, parent_of)
ctype = 'select'
return ctype, name, {'__select': attrs}
def parse_forms(root, base_url, request_class=None, select_default=False, encoding=None):
if request_class is None:
request_class = Request
global_form = HTMLForm(base_url, encoding=encoding)
forms, labels = [], []
form_elems = []
form_id_map = {}
all_elems = tuple(
e for e in root.iter('*') if is_string(e.tag))
parent_map = {c: p for p in all_elems for c in p}
id_to_labels = defaultdict(list)
for e in all_elems:
q = e.tag.lower()
if q == 'form':
form_elems.append(e)
fid = e.get('id')
if fid:
form_id_map[fid] = e
elif q == 'label':
for_id = e.get('for')
if for_id is not None:
label = Label(label_text(e), for_id)
labels.append(label)
id_to_labels[for_id].append(label)
elif q == 'base':
base_url = e.get('href') or base_url
def parent_of(elem, parent_name):
q = elem
while True:
q = parent_map.get(q)
if q is None:
return
if q.tag.lower() == parent_name:
return q
forms_map = {}
for form_elem in form_elems:
name = form_elem.get('name') or None
action = form_elem.get('action') or None
method = form_elem.get('method') or 'GET'
enctype = form_elem.get(
'enctype') or "application/x-www-form-urlencoded"
if action:
action = urljoin(base_url, action)
else:
action = base_url
form = HTMLForm(action, method, enctype, name, form_elem.attrib,
request_class, forms, labels, id_to_labels, encoding=encoding)
forms_map[form_elem] = form
forms.append(form)
attrs_map = {}
control_names = {
'option': parse_option,
'button': parse_button,
'input': parse_input,
'textarea': parse_textarea,
'select': parse_select,
}
for i, elem in enumerate(all_elems):
q = elem.tag.lower()
cfunc = control_names.get(q)
if cfunc is not None:
fid = elem.get('form')
if fid and fid in form_id_map:
form_elem = form_id_map[fid]
else:
form_elem = parent_of(elem, 'form')
form = forms_map.get(form_elem, global_form)
try:
control_type, control_name, attrs = cfunc(elem, parent_of,
attrs_map)
except SkipControl:
continue
attrs_map[elem] = attrs
form.new_control(
control_type,
control_name,
attrs,
index=i * 10,
select_default=select_default)
for form in forms:
form.fixup()
global_form.fixup()
return forms, global_form