456 lines
15 KiB
Python
Executable File
456 lines
15 KiB
Python
Executable File
# DO NOT EDIT THIS FILE!
|
|
#
|
|
# This file is generated from the CDP specification. If you need to make
|
|
# changes, edit the generator and regenerate all of the modules.
|
|
#
|
|
# CDP domain: Accessibility (experimental)
|
|
from __future__ import annotations
|
|
from .util import event_class, T_JSON_DICT
|
|
from dataclasses import dataclass
|
|
import enum
|
|
import typing
|
|
from . import dom
|
|
from . import runtime
|
|
|
|
|
|
class AXNodeId(str):
|
|
'''
|
|
Unique accessibility node identifier.
|
|
'''
|
|
def to_json(self) -> str:
|
|
return self
|
|
|
|
@classmethod
|
|
def from_json(cls, json: str) -> AXNodeId:
|
|
return cls(json)
|
|
|
|
def __repr__(self):
|
|
return 'AXNodeId({})'.format(super().__repr__())
|
|
|
|
|
|
class AXValueType(enum.Enum):
|
|
'''
|
|
Enum of possible property types.
|
|
'''
|
|
BOOLEAN = "boolean"
|
|
TRISTATE = "tristate"
|
|
BOOLEAN_OR_UNDEFINED = "booleanOrUndefined"
|
|
IDREF = "idref"
|
|
IDREF_LIST = "idrefList"
|
|
INTEGER = "integer"
|
|
NODE = "node"
|
|
NODE_LIST = "nodeList"
|
|
NUMBER = "number"
|
|
STRING = "string"
|
|
COMPUTED_STRING = "computedString"
|
|
TOKEN = "token"
|
|
TOKEN_LIST = "tokenList"
|
|
DOM_RELATION = "domRelation"
|
|
ROLE = "role"
|
|
INTERNAL_ROLE = "internalRole"
|
|
VALUE_UNDEFINED = "valueUndefined"
|
|
|
|
def to_json(self):
|
|
return self.value
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(json)
|
|
|
|
|
|
class AXValueSourceType(enum.Enum):
|
|
'''
|
|
Enum of possible property sources.
|
|
'''
|
|
ATTRIBUTE = "attribute"
|
|
IMPLICIT = "implicit"
|
|
STYLE = "style"
|
|
CONTENTS = "contents"
|
|
PLACEHOLDER = "placeholder"
|
|
RELATED_ELEMENT = "relatedElement"
|
|
|
|
def to_json(self):
|
|
return self.value
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(json)
|
|
|
|
|
|
class AXValueNativeSourceType(enum.Enum):
|
|
'''
|
|
Enum of possible native property sources (as a subtype of a particular AXValueSourceType).
|
|
'''
|
|
FIGCAPTION = "figcaption"
|
|
LABEL = "label"
|
|
LABELFOR = "labelfor"
|
|
LABELWRAPPED = "labelwrapped"
|
|
LEGEND = "legend"
|
|
TABLECAPTION = "tablecaption"
|
|
TITLE = "title"
|
|
OTHER = "other"
|
|
|
|
def to_json(self):
|
|
return self.value
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(json)
|
|
|
|
|
|
@dataclass
|
|
class AXValueSource:
|
|
'''
|
|
A single source for a computed AX property.
|
|
'''
|
|
#: What type of source this is.
|
|
type_: AXValueSourceType
|
|
|
|
#: The value of this property source.
|
|
value: typing.Optional[AXValue] = None
|
|
|
|
#: The name of the relevant attribute, if any.
|
|
attribute: typing.Optional[str] = None
|
|
|
|
#: The value of the relevant attribute, if any.
|
|
attribute_value: typing.Optional[AXValue] = None
|
|
|
|
#: Whether this source is superseded by a higher priority source.
|
|
superseded: typing.Optional[bool] = None
|
|
|
|
#: The native markup source for this value, e.g. a <label> element.
|
|
native_source: typing.Optional[AXValueNativeSourceType] = None
|
|
|
|
#: The value, such as a node or node list, of the native source.
|
|
native_source_value: typing.Optional[AXValue] = None
|
|
|
|
#: Whether the value for this property is invalid.
|
|
invalid: typing.Optional[bool] = None
|
|
|
|
#: Reason for the value being invalid, if it is.
|
|
invalid_reason: typing.Optional[str] = None
|
|
|
|
def to_json(self):
|
|
json = dict()
|
|
json['type'] = self.type_.to_json()
|
|
if self.value is not None:
|
|
json['value'] = self.value.to_json()
|
|
if self.attribute is not None:
|
|
json['attribute'] = self.attribute
|
|
if self.attribute_value is not None:
|
|
json['attributeValue'] = self.attribute_value.to_json()
|
|
if self.superseded is not None:
|
|
json['superseded'] = self.superseded
|
|
if self.native_source is not None:
|
|
json['nativeSource'] = self.native_source.to_json()
|
|
if self.native_source_value is not None:
|
|
json['nativeSourceValue'] = self.native_source_value.to_json()
|
|
if self.invalid is not None:
|
|
json['invalid'] = self.invalid
|
|
if self.invalid_reason is not None:
|
|
json['invalidReason'] = self.invalid_reason
|
|
return json
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(
|
|
type_=AXValueSourceType.from_json(json['type']),
|
|
value=AXValue.from_json(json['value']) if 'value' in json else None,
|
|
attribute=str(json['attribute']) if 'attribute' in json else None,
|
|
attribute_value=AXValue.from_json(json['attributeValue']) if 'attributeValue' in json else None,
|
|
superseded=bool(json['superseded']) if 'superseded' in json else None,
|
|
native_source=AXValueNativeSourceType.from_json(json['nativeSource']) if 'nativeSource' in json else None,
|
|
native_source_value=AXValue.from_json(json['nativeSourceValue']) if 'nativeSourceValue' in json else None,
|
|
invalid=bool(json['invalid']) if 'invalid' in json else None,
|
|
invalid_reason=str(json['invalidReason']) if 'invalidReason' in json else None,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class AXRelatedNode:
|
|
#: The BackendNodeId of the related DOM node.
|
|
backend_dom_node_id: dom.BackendNodeId
|
|
|
|
#: The IDRef value provided, if any.
|
|
idref: typing.Optional[str] = None
|
|
|
|
#: The text alternative of this node in the current context.
|
|
text: typing.Optional[str] = None
|
|
|
|
def to_json(self):
|
|
json = dict()
|
|
json['backendDOMNodeId'] = self.backend_dom_node_id.to_json()
|
|
if self.idref is not None:
|
|
json['idref'] = self.idref
|
|
if self.text is not None:
|
|
json['text'] = self.text
|
|
return json
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(
|
|
backend_dom_node_id=dom.BackendNodeId.from_json(json['backendDOMNodeId']),
|
|
idref=str(json['idref']) if 'idref' in json else None,
|
|
text=str(json['text']) if 'text' in json else None,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class AXProperty:
|
|
#: The name of this property.
|
|
name: AXPropertyName
|
|
|
|
#: The value of this property.
|
|
value: AXValue
|
|
|
|
def to_json(self):
|
|
json = dict()
|
|
json['name'] = self.name.to_json()
|
|
json['value'] = self.value.to_json()
|
|
return json
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(
|
|
name=AXPropertyName.from_json(json['name']),
|
|
value=AXValue.from_json(json['value']),
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class AXValue:
|
|
'''
|
|
A single computed AX property.
|
|
'''
|
|
#: The type of this value.
|
|
type_: AXValueType
|
|
|
|
#: The computed value of this property.
|
|
value: typing.Optional[typing.Any] = None
|
|
|
|
#: One or more related nodes, if applicable.
|
|
related_nodes: typing.Optional[typing.List[AXRelatedNode]] = None
|
|
|
|
#: The sources which contributed to the computation of this property.
|
|
sources: typing.Optional[typing.List[AXValueSource]] = None
|
|
|
|
def to_json(self):
|
|
json = dict()
|
|
json['type'] = self.type_.to_json()
|
|
if self.value is not None:
|
|
json['value'] = self.value
|
|
if self.related_nodes is not None:
|
|
json['relatedNodes'] = [i.to_json() for i in self.related_nodes]
|
|
if self.sources is not None:
|
|
json['sources'] = [i.to_json() for i in self.sources]
|
|
return json
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(
|
|
type_=AXValueType.from_json(json['type']),
|
|
value=json['value'] if 'value' in json else None,
|
|
related_nodes=[AXRelatedNode.from_json(i) for i in json['relatedNodes']] if 'relatedNodes' in json else None,
|
|
sources=[AXValueSource.from_json(i) for i in json['sources']] if 'sources' in json else None,
|
|
)
|
|
|
|
|
|
class AXPropertyName(enum.Enum):
|
|
'''
|
|
Values of AXProperty name:
|
|
- from 'busy' to 'roledescription': states which apply to every AX node
|
|
- from 'live' to 'root': attributes which apply to nodes in live regions
|
|
- from 'autocomplete' to 'valuetext': attributes which apply to widgets
|
|
- from 'checked' to 'selected': states which apply to widgets
|
|
- from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling.
|
|
'''
|
|
BUSY = "busy"
|
|
DISABLED = "disabled"
|
|
EDITABLE = "editable"
|
|
FOCUSABLE = "focusable"
|
|
FOCUSED = "focused"
|
|
HIDDEN = "hidden"
|
|
HIDDEN_ROOT = "hiddenRoot"
|
|
INVALID = "invalid"
|
|
KEYSHORTCUTS = "keyshortcuts"
|
|
SETTABLE = "settable"
|
|
ROLEDESCRIPTION = "roledescription"
|
|
LIVE = "live"
|
|
ATOMIC = "atomic"
|
|
RELEVANT = "relevant"
|
|
ROOT = "root"
|
|
AUTOCOMPLETE = "autocomplete"
|
|
HAS_POPUP = "hasPopup"
|
|
LEVEL = "level"
|
|
MULTISELECTABLE = "multiselectable"
|
|
ORIENTATION = "orientation"
|
|
MULTILINE = "multiline"
|
|
READONLY = "readonly"
|
|
REQUIRED = "required"
|
|
VALUEMIN = "valuemin"
|
|
VALUEMAX = "valuemax"
|
|
VALUETEXT = "valuetext"
|
|
CHECKED = "checked"
|
|
EXPANDED = "expanded"
|
|
MODAL = "modal"
|
|
PRESSED = "pressed"
|
|
SELECTED = "selected"
|
|
ACTIVEDESCENDANT = "activedescendant"
|
|
CONTROLS = "controls"
|
|
DESCRIBEDBY = "describedby"
|
|
DETAILS = "details"
|
|
ERRORMESSAGE = "errormessage"
|
|
FLOWTO = "flowto"
|
|
LABELLEDBY = "labelledby"
|
|
OWNS = "owns"
|
|
|
|
def to_json(self):
|
|
return self.value
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(json)
|
|
|
|
|
|
@dataclass
|
|
class AXNode:
|
|
'''
|
|
A node in the accessibility tree.
|
|
'''
|
|
#: Unique identifier for this node.
|
|
node_id: AXNodeId
|
|
|
|
#: Whether this node is ignored for accessibility
|
|
ignored: bool
|
|
|
|
#: Collection of reasons why this node is hidden.
|
|
ignored_reasons: typing.Optional[typing.List[AXProperty]] = None
|
|
|
|
#: This ``Node``'s role, whether explicit or implicit.
|
|
role: typing.Optional[AXValue] = None
|
|
|
|
#: The accessible name for this ``Node``.
|
|
name: typing.Optional[AXValue] = None
|
|
|
|
#: The accessible description for this ``Node``.
|
|
description: typing.Optional[AXValue] = None
|
|
|
|
#: The value for this ``Node``.
|
|
value: typing.Optional[AXValue] = None
|
|
|
|
#: All other properties
|
|
properties: typing.Optional[typing.List[AXProperty]] = None
|
|
|
|
#: IDs for each of this node's child nodes.
|
|
child_ids: typing.Optional[typing.List[AXNodeId]] = None
|
|
|
|
#: The backend ID for the associated DOM node, if any.
|
|
backend_dom_node_id: typing.Optional[dom.BackendNodeId] = None
|
|
|
|
def to_json(self):
|
|
json = dict()
|
|
json['nodeId'] = self.node_id.to_json()
|
|
json['ignored'] = self.ignored
|
|
if self.ignored_reasons is not None:
|
|
json['ignoredReasons'] = [i.to_json() for i in self.ignored_reasons]
|
|
if self.role is not None:
|
|
json['role'] = self.role.to_json()
|
|
if self.name is not None:
|
|
json['name'] = self.name.to_json()
|
|
if self.description is not None:
|
|
json['description'] = self.description.to_json()
|
|
if self.value is not None:
|
|
json['value'] = self.value.to_json()
|
|
if self.properties is not None:
|
|
json['properties'] = [i.to_json() for i in self.properties]
|
|
if self.child_ids is not None:
|
|
json['childIds'] = [i.to_json() for i in self.child_ids]
|
|
if self.backend_dom_node_id is not None:
|
|
json['backendDOMNodeId'] = self.backend_dom_node_id.to_json()
|
|
return json
|
|
|
|
@classmethod
|
|
def from_json(cls, json):
|
|
return cls(
|
|
node_id=AXNodeId.from_json(json['nodeId']),
|
|
ignored=bool(json['ignored']),
|
|
ignored_reasons=[AXProperty.from_json(i) for i in json['ignoredReasons']] if 'ignoredReasons' in json else None,
|
|
role=AXValue.from_json(json['role']) if 'role' in json else None,
|
|
name=AXValue.from_json(json['name']) if 'name' in json else None,
|
|
description=AXValue.from_json(json['description']) if 'description' in json else None,
|
|
value=AXValue.from_json(json['value']) if 'value' in json else None,
|
|
properties=[AXProperty.from_json(i) for i in json['properties']] if 'properties' in json else None,
|
|
child_ids=[AXNodeId.from_json(i) for i in json['childIds']] if 'childIds' in json else None,
|
|
backend_dom_node_id=dom.BackendNodeId.from_json(json['backendDOMNodeId']) if 'backendDOMNodeId' in json else None,
|
|
)
|
|
|
|
|
|
def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
|
|
'''
|
|
Disables the accessibility domain.
|
|
'''
|
|
cmd_dict: T_JSON_DICT = {
|
|
'method': 'Accessibility.disable',
|
|
}
|
|
json = yield cmd_dict
|
|
|
|
|
|
def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
|
|
'''
|
|
Enables the accessibility domain which causes ``AXNodeId``'s to remain consistent between method calls.
|
|
This turns on accessibility for the page, which can impact performance until accessibility is disabled.
|
|
'''
|
|
cmd_dict: T_JSON_DICT = {
|
|
'method': 'Accessibility.enable',
|
|
}
|
|
json = yield cmd_dict
|
|
|
|
|
|
def get_partial_ax_tree(
|
|
node_id: typing.Optional[dom.NodeId] = None,
|
|
backend_node_id: typing.Optional[dom.BackendNodeId] = None,
|
|
object_id: typing.Optional[runtime.RemoteObjectId] = None,
|
|
fetch_relatives: typing.Optional[bool] = None
|
|
) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[AXNode]]:
|
|
'''
|
|
Fetches the accessibility node and partial accessibility tree for this DOM node, if it exists.
|
|
|
|
**EXPERIMENTAL**
|
|
|
|
:param node_id: *(Optional)* Identifier of the node to get the partial accessibility tree for.
|
|
:param backend_node_id: *(Optional)* Identifier of the backend node to get the partial accessibility tree for.
|
|
:param object_id: *(Optional)* JavaScript object id of the node wrapper to get the partial accessibility tree for.
|
|
:param fetch_relatives: *(Optional)* Whether to fetch this nodes ancestors, siblings and children. Defaults to true.
|
|
:returns: The ``Accessibility.AXNode`` for this DOM node, if it exists, plus its ancestors, siblings and children, if requested.
|
|
'''
|
|
params: T_JSON_DICT = dict()
|
|
if node_id is not None:
|
|
params['nodeId'] = node_id.to_json()
|
|
if backend_node_id is not None:
|
|
params['backendNodeId'] = backend_node_id.to_json()
|
|
if object_id is not None:
|
|
params['objectId'] = object_id.to_json()
|
|
if fetch_relatives is not None:
|
|
params['fetchRelatives'] = fetch_relatives
|
|
cmd_dict: T_JSON_DICT = {
|
|
'method': 'Accessibility.getPartialAXTree',
|
|
'params': params,
|
|
}
|
|
json = yield cmd_dict
|
|
return [AXNode.from_json(i) for i in json['nodes']]
|
|
|
|
|
|
def get_full_ax_tree() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[AXNode]]:
|
|
'''
|
|
Fetches the entire accessibility tree
|
|
|
|
**EXPERIMENTAL**
|
|
|
|
:returns:
|
|
'''
|
|
cmd_dict: T_JSON_DICT = {
|
|
'method': 'Accessibility.getFullAXTree',
|
|
}
|
|
json = yield cmd_dict
|
|
return [AXNode.from_json(i) for i in json['nodes']]
|