Files
Artemis-Eapil/artemis/utils/native_control_state.py
T

70 lines
2.5 KiB
Python

"""Bounded native metadata shared by JSON and XML hierarchy observations."""
import json
import math
from typing import Any
def _finite_number(value: Any) -> bool:
# Android ranges are finite floats. Reject malformed oversized JSON integers
# before conversion, which otherwise raises OverflowError in math.isfinite.
return type(value) in (int, float) and -1e308 <= value <= 1e308 and math.isfinite(value)
def native_control_state(node: dict[str, Any]) -> dict[str, Any]:
state: dict[str, Any] = {}
for key in ("range", "actions"):
value = node.get(key)
if isinstance(value, str) and len(value) <= 8192:
try:
value = json.loads(value)
except ValueError:
value = None
if key == "actions" and isinstance(value, list):
state[key] = [item for item in value[:32] if isinstance(item, str) and len(item) <= 64]
elif key == "range" and isinstance(value, dict):
numbers = [value.get(k) for k in ("min", "max", "current")]
if all(_finite_number(v) for v in numbers):
if numbers[0] <= numbers[2] <= numbers[1]:
state[key] = {k: value[k] for k in ("min", "max", "current")}
state[key]["type"] = value.get("type")
for key in (
"visible",
"enabled",
"scrollable",
"editable",
"password",
"checked",
"checkable",
"selected",
"focused",
):
value = node.get(key)
if isinstance(value, bool) or value in ("true", "false"):
state[key] = value is True or value == "true"
for key in ("selection_start", "selection_end"):
value = node.get(key, node.get(key.replace("_", "-")))
if isinstance(value, str) and len(value) < 12:
digits = value[1:] if value.startswith("-") else value
if digits and digits.isascii() and digits.isdecimal():
value = int(value)
if isinstance(value, int) and not isinstance(value, bool) and -1 <= value <= 2**31 - 1:
state[key] = value
return state
def informative_native_control(state: dict[str, Any]) -> bool:
return bool(
state.get("range")
or state.get("scrollable")
or set(state.get("actions", []))
& {
"click",
"long_click",
"set_progress",
"set_text",
"set_selection",
"ime_enter",
}
)