Returns the clickable element specified in clickdata, if the latter is given. If not, it returns the first clickable element found
(
clickdata: dict[str, str | int] | None, form: FormElement
)
| 227 | |
| 228 | |
| 229 | def _get_clickable( |
| 230 | clickdata: dict[str, str | int] | None, form: FormElement |
| 231 | ) -> tuple[str, str] | None: |
| 232 | """ |
| 233 | Returns the clickable element specified in clickdata, |
| 234 | if the latter is given. If not, it returns the first |
| 235 | clickable element found |
| 236 | """ |
| 237 | clickables = list( |
| 238 | form.xpath( |
| 239 | 'descendant::input[re:test(@type, "^(submit|image)$", "i")]' |
| 240 | '|descendant::button[not(@type) or re:test(@type, "^submit$", "i")]', |
| 241 | namespaces={"re": "http://exslt.org/regular-expressions"}, |
| 242 | ) |
| 243 | ) |
| 244 | if not clickables: |
| 245 | return None |
| 246 | |
| 247 | # If we don't have clickdata, we just use the first clickable element |
| 248 | if clickdata is None: |
| 249 | el = clickables[0] |
| 250 | return (el.get("name"), el.get("value") or "") |
| 251 | |
| 252 | # If clickdata is given, we compare it to the clickable elements to find a |
| 253 | # match. We first look to see if the number is specified in clickdata, |
| 254 | # because that uniquely identifies the element |
| 255 | nr = clickdata.get("nr", None) |
| 256 | if nr is not None: |
| 257 | assert isinstance(nr, int) |
| 258 | try: |
| 259 | el = list(form.inputs)[nr] |
| 260 | except IndexError: |
| 261 | pass |
| 262 | else: |
| 263 | return (cast("str", el.get("name")), el.get("value") or "") |
| 264 | |
| 265 | # We didn't find it, so now we build an XPath expression out of the other |
| 266 | # arguments, because they can be used as such |
| 267 | xpath = ".//*" + "".join(f'[@{k}="{v}"]' for k, v in clickdata.items()) |
| 268 | el = form.xpath(xpath) |
| 269 | if len(el) == 1: |
| 270 | return (el[0].get("name"), el[0].get("value") or "") |
| 271 | if len(el) > 1: |
| 272 | raise ValueError( |
| 273 | f"Multiple elements found ({el!r}) matching the " |
| 274 | f"criteria in clickdata: {clickdata!r}" |
| 275 | ) |
| 276 | raise ValueError(f"No clickable element matching clickdata: {clickdata!r}") |
no test coverage detected