diff --git a/CLAUDE.md b/CLAUDE.md
index 96f5ecf..a392a5a 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -225,7 +225,7 @@ subdir('PluginName')
- Community: IRC #stormux on irc.stormux.org
### Key Dependencies
-- Python 3.10+, pygobject-3.0, pluggy, gtk+-3.0
+- Python 3.9+, pygobject-3.0, pluggy, gtk+-3.0
- AT-SPI2, ATK for accessibility
- Optional: BrlTTY/BrlAPI (braille), Speech Dispatcher, liblouis, GStreamer
diff --git a/README.md b/README.md
index 70a19d9..95faf18 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ toolkit, OpenOffice/LibreOffice, Gecko, WebKitGtk, and KDE Qt toolkit.
### Core Requirements
-* **Python 3.10+** - Python platform
+* **Python 3.9+** - Python platform
* **pygobject-3.0** - Python bindings for the GObject library
* **gtk+-3.0** - GTK+ toolkit (minimal usage for AT-SPI integration)
* **AT-SPI2** - Assistive Technology Service Provider Interface
diff --git a/build-local.sh b/build-local.sh
index 941de67..85f0af3 100755
--- a/build-local.sh
+++ b/build-local.sh
@@ -6,85 +6,72 @@
set -e # Exit on error
-# Colors for output (only if stdout is a terminal)
-if [[ -t 1 ]]; then
- RED='\033[0;31m'
- GREEN='\033[0;32m'
- YELLOW='\033[1;33m'
- BLUE='\033[0;34m'
- NC='\033[0m' # No Color
-else
- RED=''
- GREEN=''
- YELLOW=''
- BLUE=''
- NC=''
-fi
-
-echo -e "${BLUE}Cthulhu Meson Local Build Script${NC}"
+echo "Cthulhu Meson Local Build Script"
echo "Building and installing Cthulhu to ~/.local"
echo "================================================"
# Check if we're in the right directory
if [[ ! -f "meson.build" ]] || [[ ! -f "src/cthulhu/cthulhu.py" ]]; then
- echo -e "${RED}Error: This script must be run from the Cthulhu source directory${NC}"
+ echo "Error: This script must be run from the Cthulhu source directory"
exit 1
fi
# Check for required dependencies
-echo -e "${YELLOW}Checking dependencies...${NC}"
+echo "Checking dependencies..."
for cmd in meson ninja python3; do
if ! command -v "$cmd" &> /dev/null; then
- echo -e "${RED}Error: $cmd is not installed${NC}"
+ echo "Error: $cmd is not installed"
echo "Please install: meson ninja python"
exit 1
fi
done
# Check for optional dependencies
-missing_optional=()
-for module in gi speech; do
- if ! python3 -c "import $module" 2>/dev/null; then
- missing_optional+=("python-$module")
- fi
-done
+missingOptional=()
+if ! python3 -c "import gi" 2>/dev/null; then
+ missingOptional+=("python-gi")
+fi
-if [[ ${#missing_optional[@]} -gt 0 ]]; then
- echo -e "${YELLOW}Warning: Optional dependencies missing: ${missing_optional[*]}${NC}"
+if [[ ${#missingOptional[@]} -gt 0 ]]; then
+ echo "Warning: Optional dependencies missing: ${missingOptional[*]}"
echo "Cthulhu may not function properly without these."
fi
+# Clean any cached bytecode
+echo "Removing __pycache__ directories..."
+find . -type d -name "__pycache__" -prune -exec rm -rf {} +
+
# Clean any existing build directory
if [[ -d "_build" ]]; then
- echo -e "${YELLOW}Removing existing build directory...${NC}"
+ echo "Removing existing build directory..."
rm -rf _build
fi
# Setup Meson build
-echo -e "${YELLOW}Setting up Meson build...${NC}"
+echo "Setting up Meson build..."
meson setup _build --prefix="$HOME/.local" --buildtype=debugoptimized
# Build
-echo -e "${YELLOW}Building Cthulhu...${NC}"
+echo "Building Cthulhu..."
meson compile -C _build
# Install
-echo -e "${YELLOW}Installing Cthulhu to ~/.local...${NC}"
+echo "Installing Cthulhu to ~/.local..."
meson install -C _build
# Update desktop database and icon cache
if command -v update-desktop-database &> /dev/null; then
- echo -e "${YELLOW}Updating desktop database...${NC}"
+ echo "Updating desktop database..."
update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
fi
if command -v gtk-update-icon-cache &> /dev/null; then
- echo -e "${YELLOW}Updating icon cache...${NC}"
+ echo "Updating icon cache..."
gtk-update-icon-cache -f -t "$HOME/.local/share/icons/hicolor" 2>/dev/null || true
fi
echo
-echo -e "${GREEN}Build completed successfully!${NC}"
+echo "Build completed successfully!"
echo
echo "To run Cthulhu:"
echo " ~/.local/bin/cthulhu"
@@ -93,4 +80,4 @@ echo "To run Cthulhu setup:"
echo " ~/.local/bin/cthulhu -s"
echo
echo "Build artifacts are in: _build/"
-echo -e "${BLUE}To clean build artifacts, run: ${YELLOW}rm -rf _build${NC}"
\ No newline at end of file
+echo "To clean build artifacts, run: rm -rf _build"
diff --git a/meson.build b/meson.build
index 49bc445..53233f1 100644
--- a/meson.build
+++ b/meson.build
@@ -6,7 +6,7 @@ project('cthulhu',
python = import('python')
i18n = import('i18n')
-python_minimum_version = '3.10'
+python_minimum_version = '3.9'
python3 = python.find_installation('python3', required: true)
if not python3.language_version().version_compare(f'>= @python_minimum_version@')
error(f'Python @python_minimum_version@ or newer is required.')
diff --git a/pyproject.toml b/pyproject.toml
index c0911a2..01e59ee 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ name = "cthulhu"
dynamic = ["version"]
description = "Fork of the Orca screen reader"
readme = "README.md"
-requires-python = ">=3.10"
+requires-python = ">=3.9"
license = { text = "LGPL-2.1-or-later" }
dependencies = [
"pygobject>=3.18",
diff --git a/src/cthulhu/action_presenter.py b/src/cthulhu/action_presenter.py
index d3314df..092e385 100644
--- a/src/cthulhu/action_presenter.py
+++ b/src/cthulhu/action_presenter.py
@@ -34,7 +34,7 @@ __copyright__ = "Copyright (c) 2023 Igalia, S.L."
__license__ = "LGPL"
import time
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Union
import gi
@@ -103,7 +103,7 @@ class ActionList(Gtk.Window):
GLib.idle_add(self._presenter._clear_gui_and_restore_focus)
- def populate_actions(self, actions: dict[str, str] | list[str]) -> None:
+ def populate_actions(self, actions: Union[dict[str, str], list[str]]) -> None:
"""Populates the list with accessible actions."""
if isinstance(actions, dict):
diff --git a/src/cthulhu/ax_collection.py b/src/cthulhu/ax_collection.py
index e20aa50..f2957b1 100644
--- a/src/cthulhu/ax_collection.py
+++ b/src/cthulhu/ax_collection.py
@@ -29,6 +29,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2023 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import time
import gi
@@ -48,15 +49,15 @@ class AXCollection:
# pylint: disable=R0913,R0914
@staticmethod
def create_match_rule(
- states: list[str] | None = None,
+ states: Optional[list[str]] = None,
state_match_type: Atspi.CollectionMatchType = Atspi.CollectionMatchType.ALL,
- attributes: list[str] | None = None,
+ attributes: Optional[list[str]] = None,
attribute_match_type: Atspi.CollectionMatchType = Atspi.CollectionMatchType.ALL,
- roles: list[str] | None = None,
+ roles: Optional[list[str]] = None,
role_match_type: Atspi.CollectionMatchType = Atspi.CollectionMatchType.ALL,
- interfaces: list[str] | None = None,
+ interfaces: Optional[list[str]] = None,
interface_match_type: Atspi.CollectionMatchType = Atspi.CollectionMatchType.ALL,
- invert: bool = False) -> Atspi.MatchRule | None:
+ invert: bool = False) -> Optional[Atspi.MatchRule]:
"""Creates a match rule based on the supplied criteria."""
if states is None:
@@ -136,7 +137,7 @@ class AXCollection:
obj: Atspi.Accessible,
rule: Atspi.MatchRule,
order: Atspi.CollectionSortOrder = Atspi.CollectionSortOrder.CANONICAL
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the first object matching the specified rule."""
if not AXObject.supports_collection(obj):
diff --git a/src/cthulhu/ax_component.py b/src/cthulhu/ax_component.py
index ae08da1..c26bf10 100644
--- a/src/cthulhu/ax_component.py
+++ b/src/cthulhu/ax_component.py
@@ -34,6 +34,7 @@ __copyright__ = "Copyright (c) 2024 Igalia, S.L." \
"Copyright (c) 2024 GNOME Foundation Inc."
__license__ = "LGPL"
+from typing import Optional
import functools
import gi
@@ -285,7 +286,7 @@ class AXComponent:
@staticmethod
def _find_descendant_at_point(
obj: Atspi.Accessible, x: int, y: int
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Checks each child to see if it has a descendant at the specified point."""
for child in AXObject.iter_children(obj):
@@ -297,7 +298,7 @@ class AXComponent:
return None
@staticmethod
- def _get_object_at_point(obj: Atspi.Accessible, x: int, y: int) -> Atspi.Accessible | None:
+ def _get_object_at_point(obj: Atspi.Accessible, x: int, y: int) -> Optional[Atspi.Accessible]:
"""Returns the child (or descendant?) of obj at the specified point."""
if not AXObject.supports_component(obj):
@@ -317,7 +318,7 @@ class AXComponent:
@staticmethod
def _get_descendant_at_point(
obj: Atspi.Accessible, x: int, y: int
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the deepest descendant of obj at the specified point."""
child = AXComponent._get_object_at_point(obj, x, y)
@@ -338,7 +339,7 @@ class AXComponent:
@staticmethod
def get_descendant_at_point(
obj: Atspi.Accessible, x: int, y: int
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the deepest descendant of obj at the specified point."""
result = AXComponent._get_descendant_at_point(obj, x, y)
diff --git a/src/cthulhu/ax_event_synthesizer.py b/src/cthulhu/ax_event_synthesizer.py
index 9b55505..bc77c1b 100644
--- a/src/cthulhu/ax_event_synthesizer.py
+++ b/src/cthulhu/ax_event_synthesizer.py
@@ -34,6 +34,7 @@ __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \
"Copyright (c) 2018-2023 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import gi
gi.require_version("Atspi", "2.0")
gi.require_version("Gtk", "3.0")
@@ -60,8 +61,8 @@ class AXEventSynthesizer:
@staticmethod
def _is_scrolled_off_screen(
obj: Atspi.Accessible,
- offset: int | None = None,
- ancestor: Atspi.Accessible | None = None
+ offset: Optional[int] = None,
+ ancestor: Optional[Atspi.Accessible] = None
) -> bool:
"""Returns true if obj, or the caret offset therein, is scrolled off-screen."""
@@ -119,7 +120,7 @@ class AXEventSynthesizer:
return True
@staticmethod
- def _mouse_event_on_character(obj: Atspi.Accessible, offset: int | None, event: str) -> bool:
+ def _mouse_event_on_character(obj: Atspi.Accessible, offset: Optional[int], event: str) -> bool:
"""Performs the specified mouse event on the current character in obj."""
if offset is None:
@@ -164,7 +165,7 @@ class AXEventSynthesizer:
return AXEventSynthesizer._generate_mouse_event(obj, relative_x, relative_y, event)
@staticmethod
- def route_to_character(obj: Atspi.Accessible, offset: int | None = None) -> bool:
+ def route_to_character(obj: Atspi.Accessible, offset: Optional[int] = None) -> bool:
"""Routes the pointer to the current character in obj."""
tokens = [f"AXEventSynthesizer: Attempting to route to offset {offset} in", obj]
@@ -181,7 +182,7 @@ class AXEventSynthesizer:
@staticmethod
def click_character(
- obj: Atspi.Accessible, offset: int | None = None, button: int = 1
+ obj: Atspi.Accessible, offset: Optional[int] = None, button: int = 1
) -> bool:
"""Single click on the current character in obj using the specified button."""
@@ -198,7 +199,7 @@ class AXEventSynthesizer:
@staticmethod
def _scroll_to_location(
obj: Atspi.Accessible, location: Atspi.ScrollType,
- start_offset: int | None = None, end_offset: int | None = None
+ start_offset: Optional[int] = None, end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll to the specified location."""
@@ -220,7 +221,7 @@ class AXEventSynthesizer:
@staticmethod
def _scroll_to_point(
obj: Atspi.Accessible, x_coord: int, y_coord: int,
- start_offset: int | None = None, end_offset: int | None = None
+ start_offset: Optional[int] = None, end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the specified point."""
@@ -242,8 +243,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_into_view(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj into view."""
@@ -253,8 +254,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_center(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the center of its window."""
@@ -272,8 +273,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_top_edge(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the top edge."""
@@ -283,8 +284,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_top_left(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the top left."""
@@ -294,8 +295,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_left_edge(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the left edge."""
@@ -305,8 +306,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_bottom_edge(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the bottom edge."""
@@ -316,8 +317,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_bottom_right(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the bottom right."""
@@ -327,8 +328,8 @@ class AXEventSynthesizer:
@staticmethod
def scroll_to_right_edge(
obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> None:
"""Attempts to scroll obj to the right edge."""
diff --git a/src/cthulhu/ax_hypertext.py b/src/cthulhu/ax_hypertext.py
index 4da6dc6..2222ac9 100644
--- a/src/cthulhu/ax_hypertext.py
+++ b/src/cthulhu/ax_hypertext.py
@@ -32,6 +32,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2024 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import os
import re
from urllib.parse import urlparse
@@ -66,7 +67,7 @@ class AXHypertext:
return count
@staticmethod
- def _get_link_at_index(obj: Atspi.Accessible, index: int) -> Atspi.Hyperlink | None:
+ def _get_link_at_index(obj: Atspi.Accessible, index: int) -> Optional[Atspi.Hyperlink]:
"""Returns the hyperlink object at the specified index."""
if not AXObject.supports_hypertext(obj):
@@ -202,7 +203,7 @@ class AXHypertext:
return basename
@staticmethod
- def find_child_at_offset(obj: Atspi.Accessible, offset: int) -> Atspi.Accessible | None:
+ def find_child_at_offset(obj: Atspi.Accessible, offset: int) -> Optional[Atspi.Accessible]:
"""Attempts to correct for off-by-one brokenness in implementations"""
if child := AXHypertext.get_child_at_offset(obj, offset):
@@ -227,7 +228,7 @@ class AXHypertext:
return None
@staticmethod
- def get_child_at_offset(obj: Atspi.Accessible, offset: int) -> Atspi.Accessible | None:
+ def get_child_at_offset(obj: Atspi.Accessible, offset: int) -> Optional[Atspi.Accessible]:
"""Returns the embedded-object child of obj at the specified offset."""
if not AXObject.supports_hypertext(obj):
diff --git a/src/cthulhu/ax_object.py b/src/cthulhu/ax_object.py
index 362ffca..00137a6 100644
--- a/src/cthulhu/ax_object.py
+++ b/src/cthulhu/ax_object.py
@@ -34,7 +34,7 @@ __license__ = "LGPL"
import re
import threading
import time
-from typing import Callable, Generator
+from typing import Callable, Generator, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -105,7 +105,7 @@ class AXObject:
return name.lower()
@staticmethod
- def get_application(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_application(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the accessible application associated with obj."""
if obj is None:
@@ -313,7 +313,7 @@ class AXObject:
return iface is not None
@staticmethod
- def find_real_app_and_window_for(obj: Atspi.Accessible, app: Atspi.Accessible | None = None):
+ def find_real_app_and_window_for(obj: Atspi.Accessible, app: Optional[Atspi.Accessible] = None):
"""Work around for window events coming from mutter-x11-frames."""
if app is None:
@@ -545,7 +545,7 @@ class AXObject:
return index
@staticmethod
- def get_parent(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_parent(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the accessible parent of obj. See also get_parent_checked."""
if not AXObject.is_valid(obj):
@@ -571,7 +571,7 @@ class AXObject:
return parent
@staticmethod
- def get_parent_checked(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_parent_checked(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the parent of obj, doing checks for tree validity"""
if not AXObject.is_valid(obj):
@@ -619,7 +619,7 @@ class AXObject:
def get_common_ancestor(
obj1: Atspi.Accessible,
obj2: Atspi.Accessible
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the common ancestor of obj1 and obj2."""
tokens = ["AXObject: Looking for common ancestor of", obj1, "and", obj2]
@@ -647,7 +647,7 @@ class AXObject:
def find_ancestor_inclusive(
obj: Atspi.Accessible,
pred: Callable[[Atspi.Accessible], bool]
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns obj, or the ancestor of obj, for which the function pred is true"""
if pred(obj):
@@ -659,7 +659,7 @@ class AXObject:
def find_ancestor(
obj: Atspi.Accessible,
pred: Callable[[Atspi.Accessible], bool]
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the ancestor of obj if the function pred is true"""
if not AXObject.is_valid(obj):
@@ -703,7 +703,7 @@ class AXObject:
return AXObject.find_ancestor(obj, lambda x: x == ancestor) is not None
@staticmethod
- def get_child(obj: Atspi.Accessible, index: int) -> Atspi.Accessible | None:
+ def get_child(obj: Atspi.Accessible, index: int) -> Optional[Atspi.Accessible]:
"""Returns the nth child of obj. See also get_child_checked."""
if not AXObject.is_valid(obj):
@@ -736,7 +736,7 @@ class AXObject:
@staticmethod
def get_child_checked(
obj: Atspi.Accessible, index: int
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the nth child of obj, doing checks for tree validity"""
if not AXObject.is_valid(obj):
@@ -757,7 +757,7 @@ class AXObject:
def get_active_descendant_checked(
container: Atspi.Accessible,
reported_child: Atspi.Accessible
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Checks the reported active descendant and return the real/valid one."""
if not AXObject.has_state(container, Atspi.StateType.MANAGES_DESCENDANTS):
@@ -784,7 +784,7 @@ class AXObject:
def _find_descendant(
obj: Atspi.Accessible,
pred: Callable[[Atspi.Accessible], bool]
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the descendant of obj if the function pred is true"""
if not AXObject.is_valid(obj):
@@ -806,7 +806,7 @@ class AXObject:
def find_descendant(
obj: Atspi.Accessible,
pred: Callable[[Atspi.Accessible], bool]
- ) -> Atspi.Accessible | None:
+ ) -> Optional[Atspi.Accessible]:
"""Returns the descendant of obj if the function pred is true"""
start = time.time()
@@ -816,7 +816,7 @@ class AXObject:
return result
@staticmethod
- def find_deepest_descendant(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def find_deepest_descendant(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the deepest descendant of obj"""
if not AXObject.is_valid(obj):
@@ -831,8 +831,8 @@ class AXObject:
@staticmethod
def _find_all_descendants(
obj: Atspi.Accessible,
- include_if: Callable[[Atspi.Accessible], bool] | None,
- exclude_if: Callable[[Atspi.Accessible], bool] | None,
+ include_if: Optional[Callable[[Atspi.Accessible], bool]],
+ exclude_if: Optional[Callable[[Atspi.Accessible], bool]],
matches: list[Atspi.Accessible]
) -> None:
"""Returns all descendants which match the specified inclusion and exclusion"""
@@ -852,8 +852,8 @@ class AXObject:
@staticmethod
def find_all_descendants(
root: Atspi.Accessible,
- include_if: Callable[[Atspi.Accessible], bool] | None = None,
- exclude_if: Callable[[Atspi.Accessible], bool] | None = None
+ include_if: Optional[Callable[[Atspi.Accessible], bool]] = None,
+ exclude_if: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants which match the specified inclusion and exclusion"""
@@ -1044,7 +1044,7 @@ class AXObject:
@staticmethod
def iter_children(
obj: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> Generator[Atspi.Accessible, None, None]:
"""Generator to iterate through obj's children. If the function pred is
specified, children for which pred is False will be skipped."""
@@ -1068,7 +1068,7 @@ class AXObject:
yield child
@staticmethod
- def get_previous_sibling(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_previous_sibling(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the previous sibling of obj, based on child indices"""
if not AXObject.is_valid(obj):
@@ -1091,7 +1091,7 @@ class AXObject:
return sibling
@staticmethod
- def get_next_sibling(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_next_sibling(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the next sibling of obj, based on child indices"""
if not AXObject.is_valid(obj):
diff --git a/src/cthulhu/ax_selection.py b/src/cthulhu/ax_selection.py
index 903dd5e..ffbd47e 100644
--- a/src/cthulhu/ax_selection.py
+++ b/src/cthulhu/ax_selection.py
@@ -28,6 +28,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2023 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
@@ -60,7 +61,7 @@ class AXSelection:
return count
@staticmethod
- def get_selected_child(obj: Atspi.Accessible, index: int) -> Atspi.Accessible | None:
+ def get_selected_child(obj: Atspi.Accessible, index: int) -> Optional[Atspi.Accessible]:
"""Returns the nth selected child of obj."""
n_children = AXSelection.get_selected_child_count(obj)
diff --git a/src/cthulhu/ax_table.py b/src/cthulhu/ax_table.py
index 7dc4414..97d2975 100644
--- a/src/cthulhu/ax_table.py
+++ b/src/cthulhu/ax_table.py
@@ -35,7 +35,7 @@ __license__ = "LGPL"
import threading
import time
-from typing import Generator
+from typing import Generator, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -62,11 +62,11 @@ class AXTable:
PHYSICAL_SPANS_FROM_TABLE: dict[int, tuple[int, int]] = {}
PHYSICAL_COLUMN_COUNT: dict[int, int] = {}
PHYSICAL_ROW_COUNT: dict[int, int] = {}
- PRESENTABLE_COORDINATES: dict[int, tuple[str | None, str | None]] = {}
+ PRESENTABLE_COORDINATES: dict[int, tuple[Optional[str], Optional[str]]] = {}
PRESENTABLE_COORDINATES_LABELS: dict[int, str] = {}
- PRESENTABLE_SPANS: dict[int, tuple[str | None, str | None]] = {}
- PRESENTABLE_COLUMN_COUNT: dict[int, int | None] = {}
- PRESENTABLE_ROW_COUNT: dict[int, int | None] = {}
+ PRESENTABLE_SPANS: dict[int, tuple[Optional[str], Optional[str]]] = {}
+ PRESENTABLE_COLUMN_COUNT: dict[int, Optional[int]] = {}
+ PRESENTABLE_ROW_COUNT: dict[int, Optional[int]] = {}
COLUMN_HEADERS_FOR_CELL: dict[int, list[Atspi.Accessible]] = {}
ROW_HEADERS_FOR_CELL: dict[int, list[Atspi.Accessible]] = {}
@@ -121,7 +121,7 @@ class AXTable:
AXTable._clear_all_dictionaries(reason)
@staticmethod
- def get_caption(table: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_caption(table: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the accessible object containing the caption of table."""
if not AXObject.supports_table(table):
@@ -171,7 +171,7 @@ class AXTable:
return count
@staticmethod
- def _get_column_count_from_attribute(table: Atspi.Accessible) -> int | None:
+ def _get_column_count_from_attribute(table: Atspi.Accessible) -> Optional[int]:
"""Returns the value of the 'colcount' object attribute or None if not found."""
if hash(table) in AXTable.PRESENTABLE_COLUMN_COUNT:
@@ -217,7 +217,7 @@ class AXTable:
return count
@staticmethod
- def _get_row_count_from_attribute(table: Atspi.Accessible) -> int | None:
+ def _get_row_count_from_attribute(table: Atspi.Accessible) -> Optional[int]:
"""Returns the value of the 'rowcount' object attribute or None if not found."""
if hash(table) in AXTable.PRESENTABLE_ROW_COUNT:
@@ -344,7 +344,7 @@ class AXTable:
return AXTable.get_selected_column_count(table) == cols
@staticmethod
- def get_cell_at(table: Atspi.Accessible, row: int, column: int) -> Atspi.Accessible | None:
+ def get_cell_at(table: Atspi.Accessible, row: int, column: int) -> Optional[Atspi.Accessible]:
"""Returns the cell at the 0-indexed row and column."""
if not AXObject.supports_table(table):
@@ -405,7 +405,7 @@ class AXTable:
@staticmethod
def _get_cell_spans_from_attribute(
cell: Atspi.Accessible
- ) -> tuple[str | None, str | None]:
+ ) -> tuple[Optional[str], Optional[str]]:
"""Returns the row and column spans exposed via object attribute, or None, None."""
if hash(cell) in AXTable.PRESENTABLE_SPANS:
@@ -606,7 +606,7 @@ class AXTable:
@staticmethod
def get_new_row_headers(
cell: Atspi.Accessible,
- old_cell: Atspi.Accessible | None
+ old_cell: Optional[Atspi.Accessible]
) -> list[Atspi.Accessible]:
"""Returns row headers of cell that are not also headers of old_cell. """
@@ -623,7 +623,7 @@ class AXTable:
@staticmethod
def get_new_column_headers(
cell: Atspi.Accessible,
- old_cell: Atspi.Accessible | None
+ old_cell: Optional[Atspi.Accessible]
) -> list[Atspi.Accessible]:
"""Returns column headers of cell that are not also headers of old_cell. """
@@ -880,7 +880,7 @@ class AXTable:
@staticmethod
def _get_cell_coordinates_from_attribute(
cell: Atspi.Accessible
- ) -> tuple[str | None, str | None]:
+ ) -> tuple[Optional[str], Optional[str]]:
"""Returns the 1-based indices for cell exposed via object attribute, or None, None."""
if cell is None:
@@ -941,7 +941,7 @@ class AXTable:
return result
@staticmethod
- def get_table(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_table(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns obj if it is a table, otherwise returns the ancestor table of obj."""
if obj is None:
@@ -981,21 +981,21 @@ class AXTable:
return result
@staticmethod
- def get_first_cell(table: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_first_cell(table: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the first cell in table."""
row, col = 0, 0
return AXTable.get_cell_at(table, row, col)
@staticmethod
- def get_last_cell(table: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_last_cell(table: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the last cell in table."""
row, col = AXTable.get_row_count(table) - 1, AXTable.get_column_count(table) - 1
return AXTable.get_cell_at(table, row, col)
@staticmethod
- def get_cell_above(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_cell_above(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell above cell in table."""
row, col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)
@@ -1003,7 +1003,7 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_cell_below(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_cell_below(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell below cell in table."""
row, col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)
@@ -1011,7 +1011,7 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_cell_on_left(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_cell_on_left(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell to the left."""
row, col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)
@@ -1019,7 +1019,7 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_cell_on_right(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_cell_on_right(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell to the right."""
row, col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)
@@ -1027,14 +1027,14 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_start_of_row(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_start_of_row(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell at the start of cell's row."""
row = AXTable.get_cell_coordinates(cell, prefer_attribute=False)[0]
return AXTable.get_cell_at(AXTable.get_table(cell), row, 0)
@staticmethod
- def get_end_of_row(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_end_of_row(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell at the end of cell's row."""
row = AXTable.get_cell_coordinates(cell, prefer_attribute=False)[0]
@@ -1043,14 +1043,14 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_top_of_column(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_top_of_column(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell at the top of cell's column."""
col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)[1]
return AXTable.get_cell_at(AXTable.get_table(cell), 0, col)
@staticmethod
- def get_bottom_of_column(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_bottom_of_column(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the cell at the bottom of cell's column."""
col = AXTable.get_cell_coordinates(cell, prefer_attribute=False)[1]
@@ -1059,7 +1059,7 @@ class AXTable:
return AXTable.get_cell_at(AXTable.get_table(cell), row, col)
@staticmethod
- def get_cell_formula(cell: Atspi.Accessible) -> str | None:
+ def get_cell_formula(cell: Atspi.Accessible) -> Optional[str]:
"""Returns the formula associated with this cell."""
attrs = AXObject.get_attributes_dict(cell, use_cache=False)
@@ -1192,7 +1192,7 @@ class AXTable:
return result
@staticmethod
- def get_dynamic_row_header(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_dynamic_row_header(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the user-set row header for cell."""
table = AXTable.get_table(cell)
@@ -1207,7 +1207,7 @@ class AXTable:
return AXTable.get_cell_at(table, cell_row, headers_column)
@staticmethod
- def get_dynamic_column_header(cell: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_dynamic_column_header(cell: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the user-set column header for cell."""
table = AXTable.get_table(cell)
diff --git a/src/cthulhu/ax_text.py b/src/cthulhu/ax_text.py
index 610e39b..9cafdbf 100644
--- a/src/cthulhu/ax_text.py
+++ b/src/cthulhu/ax_text.py
@@ -44,7 +44,7 @@ __license__ = "LGPL"
import enum
import locale
import re
-from typing import Generator
+from typing import Generator, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -104,7 +104,7 @@ class AXTextAttribute(enum.Enum):
WRITING_MODE = ("writing-mode", False)
@classmethod
- def from_string(cls, string: str) -> "AXTextAttribute" | None:
+ def from_string(cls, string: str) -> Optional['AXTextAttribute']:
"""Returns the AXTextAttribute for the specified string."""
for attribute in cls:
@@ -114,7 +114,7 @@ class AXTextAttribute(enum.Enum):
return None
@classmethod
- def from_localized_string(cls, string: str) -> "AXTextAttribute" | None:
+ def from_localized_string(cls, string: str) -> Optional['AXTextAttribute']:
"""Returns the AXTextAttribute for the specified localized string."""
for attribute in cls:
@@ -192,7 +192,7 @@ class AXText:
@staticmethod
def get_character_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the (character, start, end) for the current or specified offset."""
@@ -239,7 +239,7 @@ class AXText:
@staticmethod
def get_next_character(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the next (character, start, end) for the current or specified offset."""
@@ -264,7 +264,7 @@ class AXText:
@staticmethod
def get_previous_character(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the previous (character, start, end) for the current or specified offset."""
@@ -291,7 +291,7 @@ class AXText:
@staticmethod
def iter_character(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> Generator[tuple[str, int, int], None, None]:
"""Generator to iterate by character in obj starting with the character at offset."""
@@ -312,7 +312,7 @@ class AXText:
@staticmethod
def get_word_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the (word, start, end) for the current or specified offset."""
@@ -354,7 +354,7 @@ class AXText:
@staticmethod
def get_next_word(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the next (word, start, end) for the current or specified offset."""
@@ -379,7 +379,7 @@ class AXText:
@staticmethod
def get_previous_word(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the previous (word, start, end) for the current or specified offset."""
@@ -406,7 +406,7 @@ class AXText:
@staticmethod
def iter_word(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> Generator[tuple[str, int, int], None, None]:
"""Generator to iterate by word in obj starting with the word at offset."""
@@ -427,7 +427,7 @@ class AXText:
@staticmethod
def get_line_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the (line, start, end) for the current or specified offset."""
@@ -495,7 +495,7 @@ class AXText:
@staticmethod
def get_next_line(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the next (line, start, end) for the current or specified offset."""
@@ -520,7 +520,7 @@ class AXText:
@staticmethod
def get_previous_line(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the previous (line, start, end) for the current or specified offset."""
@@ -549,7 +549,7 @@ class AXText:
@staticmethod
def iter_line(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> Generator[tuple[str, int, int], None, None]:
"""Generator to iterate by line in obj starting with the line at offset."""
@@ -606,7 +606,7 @@ class AXText:
@staticmethod
def _get_sentence_at_offset_fallback(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Fallback sentence detection for broken implementations."""
@@ -633,7 +633,7 @@ class AXText:
@staticmethod
def get_sentence_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the (sentence, start, end) for the current or specified offset."""
@@ -682,7 +682,7 @@ class AXText:
@staticmethod
def get_next_sentence(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the next (sentence, start, end) for the current or specified offset."""
@@ -707,7 +707,7 @@ class AXText:
@staticmethod
def get_previous_sentence(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the previous (sentence, start, end) for the current or specified offset."""
@@ -734,7 +734,7 @@ class AXText:
@staticmethod
def iter_sentence(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> Generator[tuple[str, int, int], None, None]:
"""Generator to iterate by sentence in obj starting with the sentence at offset."""
@@ -759,7 +759,7 @@ class AXText:
@staticmethod
def get_paragraph_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the (paragraph, start, end) for the current or specified offset."""
@@ -801,7 +801,7 @@ class AXText:
@staticmethod
def get_next_paragraph(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the next (paragraph, start, end) for the current or specified offset."""
@@ -826,7 +826,7 @@ class AXText:
@staticmethod
def get_previous_paragraph(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[str, int, int]:
"""Returns the previous (paragraph, start, end) for the current or specified offset."""
@@ -852,7 +852,7 @@ class AXText:
@staticmethod
def iter_paragraph(
- obj: Atspi.Accessible, offset: int | None = None
+ obj: Atspi.Accessible, offset: Optional[int] = None
) -> Generator[tuple[str, int, int], None, None]:
"""Generator to iterate by paragraph in obj starting with the paragraph at offset."""
@@ -1206,7 +1206,7 @@ class AXText:
@staticmethod
def get_text_attributes_at_offset(
obj: Atspi.Accessible,
- offset: int | None = None
+ offset: Optional[int] = None
) -> tuple[dict[str, str], int, int]:
"""Returns a (dict, start, end) tuple for attributes at offset in obj."""
@@ -1303,7 +1303,7 @@ class AXText:
return offset
@staticmethod
- def get_character_rect(obj: Atspi.Accessible, offset: int | None = None) -> Atspi.Rect:
+ def get_character_rect(obj: Atspi.Accessible, offset: Optional[int] = None) -> Atspi.Rect:
"""Returns the Atspi rect of the character at the specified offset in obj."""
if not AXObject.supports_text(obj):
@@ -1487,7 +1487,7 @@ class AXText:
return result
@staticmethod
- def string_has_spelling_error(obj: Atspi.Accessible, offset: int | None = None) -> bool:
+ def string_has_spelling_error(obj: Atspi.Accessible, offset: Optional[int] = None) -> bool:
"""Returns True if the text attributes indicate a spelling error."""
attributes = AXText.get_text_attributes_at_offset(obj, offset)[0]
@@ -1502,7 +1502,7 @@ class AXText:
return False
@staticmethod
- def string_has_grammar_error(obj: Atspi.Accessible, offset: int | None = None) -> bool:
+ def string_has_grammar_error(obj: Atspi.Accessible, offset: Optional[int] = None) -> bool:
"""Returns True if the text attributes indicate a grammar error."""
attributes = AXText.get_text_attributes_at_offset(obj, offset)[0]
@@ -1552,8 +1552,8 @@ class AXText:
obj: Atspi.Accessible,
x: int,
y: int,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> bool:
"""Attempts to scroll obj to the specified point."""
@@ -1583,8 +1583,8 @@ class AXText:
def scroll_substring_to_location(
obj: Atspi.Accessible,
location: Atspi.ScrollType,
- start_offset: int | None = None,
- end_offset: int | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None
) -> bool:
"""Attempts to scroll the substring to the specified Atspi.ScrollType location."""
diff --git a/src/cthulhu/ax_utilities.py b/src/cthulhu/ax_utilities.py
index 5963e4e..4de6e53 100644
--- a/src/cthulhu/ax_utilities.py
+++ b/src/cthulhu/ax_utilities.py
@@ -34,6 +34,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2023-2025 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import functools
import inspect
import queue
@@ -97,7 +98,7 @@ class AXUtilities:
AXUtilities.IS_LAYOUT_ONLY.clear()
@staticmethod
- def clear_all_cache_now(obj: Atspi.Accessible | None = None, reason: str = "") -> None:
+ def clear_all_cache_now(obj: Optional[Atspi.Accessible] = None, reason: str = "") -> None:
"""Clears all cached information immediately."""
AXUtilities._clear_all_dictionaries(reason)
@@ -152,7 +153,7 @@ class AXUtilities:
return True
@staticmethod
- def find_active_window() -> Atspi.Accessible | None:
+ def find_active_window() -> Optional[Atspi.Accessible]:
"""Tries to locate the active window; may or may not succeed."""
candidates = []
@@ -192,7 +193,7 @@ class AXUtilities:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return filtered[0]
- guess: Atspi.Accessible | None = None
+ guess: Optional[Atspi.Accessible] = None
if filtered:
tokens = ["AXUtilities: Still have multiple active windows:", filtered]
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
@@ -266,7 +267,7 @@ class AXUtilities:
return AXObject.find_all_descendants(obj, is_match)
@staticmethod
- def get_default_button(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_default_button(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the default button descendant of obj"""
result = None
@@ -278,7 +279,7 @@ class AXUtilities:
return AXObject.find_descendant(obj, AXUtilitiesRole.is_default_button)
@staticmethod
- def get_focused_object(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_focused_object(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the focused descendant of obj"""
result = None
@@ -290,7 +291,7 @@ class AXUtilities:
return AXObject.find_descendant(obj, AXUtilitiesState.is_focused)
@staticmethod
- def get_info_bar(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_info_bar(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the info bar descendant of obj"""
result = None
@@ -302,7 +303,7 @@ class AXUtilities:
return AXObject.find_descendant(obj, AXUtilitiesRole.is_info_bar)
@staticmethod
- def get_status_bar(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_status_bar(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the status bar descendant of obj"""
result = None
@@ -748,7 +749,7 @@ class AXUtilities:
return len(ancestors)
@staticmethod
- def get_next_object(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_next_object(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the next object (depth first, unless there's a flows-to relation)"""
if not AXObject.is_valid(obj):
@@ -778,7 +779,7 @@ class AXUtilities:
return next_object
@staticmethod
- def get_previous_object(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_previous_object(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the previous object (depth first, unless there's a flows-from relation)"""
if not AXObject.is_valid(obj):
@@ -810,7 +811,7 @@ class AXUtilities:
@staticmethod
def is_on_screen(
obj: Atspi.Accessible,
- bounding_box: Atspi.Rect | None = None
+ bounding_box: Optional[Atspi.Rect] = None
) -> bool:
"""Returns true if obj should be treated as being on screen."""
@@ -887,7 +888,7 @@ class AXUtilities:
def _get_on_screen_objects(
root: Atspi.Accessible,
cancellation_event: threading.Event,
- bounding_box: Atspi.Rect | None = None
+ bounding_box: Optional[Atspi.Rect] = None
) -> list:
tokens = ["AXUtilities: Getting on-screen objects in", root, f"({hex(id(root))})"]
@@ -939,7 +940,7 @@ class AXUtilities:
@staticmethod
def get_on_screen_objects(
root: Atspi.Accessible,
- bounding_box: Atspi.Rect | None = None,
+ bounding_box: Optional[Atspi.Rect] = None,
timeout: float = 5.0
) -> list:
"""Returns a list of onscreen objects in the given root."""
diff --git a/src/cthulhu/ax_utilities_application.py b/src/cthulhu/ax_utilities_application.py
index dbaca2e..df82c48 100644
--- a/src/cthulhu/ax_utilities_application.py
+++ b/src/cthulhu/ax_utilities_application.py
@@ -30,6 +30,7 @@ __copyright__ = "Copyright (c) 2023-2024 Igalia, S.L." \
"Copyright (c) 2024 GNOME Foundation Inc."
__license__ = "LGPL"
+from typing import Optional
import subprocess
import gi
@@ -82,7 +83,7 @@ class AXUtilitiesApplication:
return list(AXObject.iter_children(desktop, pred))
@staticmethod
- def get_application(obj: Atspi.Accessible) -> Atspi.Accessible | None:
+ def get_application(obj: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the accessible application associated with obj"""
if obj is None:
@@ -131,7 +132,7 @@ class AXUtilitiesApplication:
return version
@staticmethod
- def get_application_with_pid(pid: int) -> Atspi.Accessible | None:
+ def get_application_with_pid(pid: int) -> Optional[Atspi.Accessible]:
"""Returns the accessible application with the specified pid"""
applications = AXUtilitiesApplication.get_all_applications()
@@ -144,7 +145,7 @@ class AXUtilitiesApplication:
return None
@staticmethod
- def get_desktop() -> Atspi.Accessible | None:
+ def get_desktop() -> Optional[Atspi.Accessible]:
"""Returns the accessible desktop"""
try:
diff --git a/src/cthulhu/ax_utilities_collection.py b/src/cthulhu/ax_utilities_collection.py
index f4e2c8d..98f4dda 100644
--- a/src/cthulhu/ax_utilities_collection.py
+++ b/src/cthulhu/ax_utilities_collection.py
@@ -32,7 +32,7 @@ __license__ = "LGPL"
import inspect
import time
-from typing import Callable
+from typing import Callable, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -72,7 +72,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
state_list: list[Atspi.StateType],
state_match_type: Atspi.CollectionMatchType,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
if not (root and state_list):
return []
@@ -94,7 +94,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
role_list: list[Atspi.Role],
role_match_type: Atspi.CollectionMatchType,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
if not (root and role_list):
return []
@@ -120,7 +120,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
role_list: list[Atspi.Role],
role_match_type: Atspi.CollectionMatchType,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
def matchesLandmarkRole(acc, role):
if role == Atspi.Role.LANDMARK:
@@ -200,7 +200,7 @@ class AXUtilitiesCollection:
def find_all_with_interfaces(
root: Atspi.Accessible,
interface_list: list[str],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which implement all the specified interfaces"""
@@ -223,7 +223,7 @@ class AXUtilitiesCollection:
def find_all_with_role(
root: Atspi.Accessible,
role_list: list[Atspi.Role],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with any of the specified roles"""
@@ -234,7 +234,7 @@ class AXUtilitiesCollection:
def find_all_without_roles(
root: Atspi.Accessible,
role_list: list[Atspi.Role],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which have none of the specified roles"""
@@ -246,7 +246,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
role_list: list[Atspi.Role],
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with any of the roles, and all the states"""
@@ -273,7 +273,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
role_list: list[Atspi.Role],
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with any of the roles, and any of the states"""
@@ -300,7 +300,7 @@ class AXUtilitiesCollection:
root: Atspi.Accessible,
role_list: list[Atspi.Role],
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with any of the roles, and none of the states"""
@@ -326,7 +326,7 @@ class AXUtilitiesCollection:
def find_all_with_states(
root: Atspi.Accessible,
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which have all of the specified states"""
@@ -337,7 +337,7 @@ class AXUtilitiesCollection:
def find_all_with_any_state(
root: Atspi.Accessible,
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which have any of the specified states"""
@@ -348,7 +348,7 @@ class AXUtilitiesCollection:
def find_all_without_states(
root: Atspi.Accessible,
state_list: list[Atspi.StateType],
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which have none of the specified states"""
@@ -358,7 +358,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_accelerator_labels(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the accelerator label role"""
@@ -368,7 +368,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_alerts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the alert role"""
@@ -378,7 +378,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_animations(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the animation role"""
@@ -388,7 +388,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_arrows(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the arrow role"""
@@ -398,7 +398,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_articles(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the article role"""
@@ -408,7 +408,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_audios(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the audio role"""
@@ -418,7 +418,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_autocompletes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the autocomplete role"""
@@ -428,7 +428,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_block_quotes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the block quote role"""
@@ -438,7 +438,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_buttons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the push- or toggle-button role"""
@@ -448,7 +448,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_calendars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the calendar role"""
@@ -458,7 +458,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_canvases(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the canvas role"""
@@ -468,7 +468,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_captions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the caption role"""
@@ -478,7 +478,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_charts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the chart role"""
@@ -488,7 +488,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_check_boxes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the checkbox role"""
@@ -498,7 +498,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_check_menu_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the check menuitem role"""
@@ -508,7 +508,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_clickables(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all non-focusable descendants of root which support the click action"""
@@ -551,7 +551,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_color_choosers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the color_chooser role"""
@@ -561,7 +561,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_column_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the column header role"""
@@ -571,7 +571,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_combo_boxes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the combobox role"""
@@ -581,7 +581,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_comments(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the comment role"""
@@ -591,7 +591,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_content_deletions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the content deletion role"""
@@ -601,7 +601,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_content_insertions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the content insertion role"""
@@ -611,7 +611,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_date_editors(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the date editor role"""
@@ -621,7 +621,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_definitions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the definition role"""
@@ -631,7 +631,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_description_lists(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the description list role"""
@@ -641,7 +641,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_description_terms(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the description term role"""
@@ -651,7 +651,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_description_values(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the description value role"""
@@ -661,7 +661,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_desktop_frames(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the desktop frame role"""
@@ -671,7 +671,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_desktop_icons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the desktop icon role"""
@@ -681,7 +681,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_dials(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the dial role"""
@@ -691,7 +691,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_dialogs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the dialog role"""
@@ -701,7 +701,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_dialogs_and_alerts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has any dialog or alert role"""
@@ -711,7 +711,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_directory_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the directory pane role"""
@@ -721,7 +721,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_documents(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has any document-related role"""
@@ -731,7 +731,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_emails(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document email role"""
@@ -741,7 +741,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_frames(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document frame role"""
@@ -751,7 +751,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_presentations(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document presentation role"""
@@ -761,7 +761,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_spreadsheets(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document spreadsheet role"""
@@ -771,7 +771,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_texts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document text role"""
@@ -781,7 +781,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_document_webs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the document web role"""
@@ -791,7 +791,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_drawing_areas(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the drawing area role"""
@@ -802,7 +802,7 @@ class AXUtilitiesCollection:
def find_all_editable_objects(
root: Atspi.Accessible,
must_be_focusable: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are editable"""
@@ -814,7 +814,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_editbars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the editbar role"""
@@ -824,7 +824,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_embeddeds(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the embedded role"""
@@ -834,7 +834,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_entries(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the entry role"""
@@ -844,7 +844,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_extendeds(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the extended role"""
@@ -854,7 +854,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_file_choosers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the file chooser role"""
@@ -864,7 +864,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_fillers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the filler role"""
@@ -874,7 +874,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_focusable_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are focusable"""
@@ -884,7 +884,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_focusable_objects_with_click_ancestor(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all focusable descendants of root which support the click-ancestor action"""
@@ -923,7 +923,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_focused_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are focused"""
@@ -933,7 +933,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_focus_traversables(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the focus traversable role"""
@@ -943,7 +943,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_font_choosers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the font chooser role"""
@@ -953,7 +953,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_footers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the footer role"""
@@ -963,7 +963,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_footnotes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the footnote role"""
@@ -973,7 +973,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_forms(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the form role"""
@@ -984,7 +984,7 @@ class AXUtilitiesCollection:
def find_all_form_fields(
root: Atspi.Accessible,
must_be_focusable: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with a form-field-related role"""
@@ -998,7 +998,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_frames(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the frame role"""
@@ -1008,7 +1008,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_glass_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the glass pane role"""
@@ -1018,7 +1018,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_grids(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that are grids"""
@@ -1041,7 +1041,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_grid_cells(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that are grid cells"""
@@ -1068,7 +1068,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_groupings(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the grouping role"""
@@ -1078,7 +1078,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the header role"""
@@ -1088,7 +1088,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_headings(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the heading role"""
@@ -1099,7 +1099,7 @@ class AXUtilitiesCollection:
def find_all_headings_at_level(
root: Atspi.Accessible,
level: int,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the heading role"""
@@ -1121,7 +1121,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_html_containers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the html container role"""
@@ -1131,7 +1131,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_horizontal_scrollbars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a horizontal scrollbar"""
@@ -1142,7 +1142,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_horizontal_separators(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a horizontal separator"""
@@ -1153,7 +1153,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_horizontal_sliders(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a horizontal slider"""
@@ -1164,7 +1164,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_icons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the icon role"""
@@ -1174,7 +1174,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_icons_and_canvases(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the icon or canvas role"""
@@ -1184,7 +1184,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_images(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the image role"""
@@ -1194,7 +1194,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_images_and_canvases(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the image or canvas role"""
@@ -1204,7 +1204,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_images_and_image_maps(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the image or image map role"""
@@ -1214,7 +1214,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_image_maps(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the image map role"""
@@ -1224,7 +1224,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_info_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the info bar role"""
@@ -1234,7 +1234,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_input_method_windows(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the input method window role"""
@@ -1244,7 +1244,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_internal_frames(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the internal frame role"""
@@ -1254,7 +1254,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_labels(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the label role"""
@@ -1264,7 +1264,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_labels_and_captions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the label or caption role"""
@@ -1274,7 +1274,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_landmarks(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the landmark role"""
@@ -1284,7 +1284,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_large_containers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that we consider a large container"""
@@ -1294,7 +1294,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_layered_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the layered pane role"""
@@ -1304,7 +1304,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_level_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the level bar role"""
@@ -1315,7 +1315,7 @@ class AXUtilitiesCollection:
def find_all_links(
root: Atspi.Accessible,
must_be_focusable: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the link role"""
@@ -1329,7 +1329,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_live_regions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that are live regions"""
@@ -1356,7 +1356,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_lists(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None,
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None,
include_description_lists: bool = False,
include_tab_lists: bool = False
) -> list[Atspi.Accessible]:
@@ -1372,7 +1372,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_list_boxes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the list box role"""
@@ -1382,7 +1382,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_list_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None,
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None,
include_description_terms: bool = False,
include_tabs: bool = False
) -> list[Atspi.Accessible]:
@@ -1398,7 +1398,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_logs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the log role"""
@@ -1408,7 +1408,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_marks(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the mark role"""
@@ -1418,7 +1418,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_marquees(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the marquee role"""
@@ -1428,7 +1428,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_maths(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the math role"""
@@ -1438,7 +1438,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_math_fractions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the math fraction role"""
@@ -1448,7 +1448,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_math_roots(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the math root role"""
@@ -1458,7 +1458,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_menus(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the menu role"""
@@ -1468,7 +1468,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_menu_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the menubar role"""
@@ -1478,7 +1478,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_menu_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the menu item role"""
@@ -1488,7 +1488,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_menu_items_of_any_kind(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has any menu item role"""
@@ -1498,7 +1498,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_menu_related_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has any menu-related role"""
@@ -1508,7 +1508,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_modal_dialogs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the alert or dialog role and modal state"""
@@ -1519,7 +1519,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_multi_line_entries(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the entry role and multiline state"""
@@ -1530,7 +1530,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_notifications(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the notification role"""
@@ -1540,7 +1540,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_option_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the option pane role"""
@@ -1550,7 +1550,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_pages(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the page role"""
@@ -1560,7 +1560,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_page_tabs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the page tab role"""
@@ -1570,7 +1570,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_page_tab_lists(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the page tab list role"""
@@ -1580,7 +1580,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_page_tab_list_related_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the page tab or page tab list role"""
@@ -1590,7 +1590,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_panels(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the panel role"""
@@ -1601,7 +1601,7 @@ class AXUtilitiesCollection:
def find_all_paragraphs(
root: Atspi.Accessible,
treat_headings_as_paragraphs: bool = False,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the paragraph role"""
@@ -1613,7 +1613,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_password_texts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the password text role"""
@@ -1623,7 +1623,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_popup_menus(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the popup menu role"""
@@ -1633,7 +1633,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_progress_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the progress bar role"""
@@ -1643,7 +1643,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_push_buttons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the push button role"""
@@ -1653,7 +1653,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_push_button_menus(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the push button menu role"""
@@ -1663,7 +1663,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_radio_buttons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the radio button role"""
@@ -1673,7 +1673,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_radio_menu_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the radio menu item role"""
@@ -1683,7 +1683,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_ratings(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the rating role"""
@@ -1693,7 +1693,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_root_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the root pane role"""
@@ -1703,7 +1703,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_row_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the row header role"""
@@ -1713,7 +1713,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_rulers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the ruler role"""
@@ -1723,7 +1723,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_scroll_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the scrollbar role"""
@@ -1733,7 +1733,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_scroll_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the scroll pane role"""
@@ -1743,7 +1743,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_sections(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the section role"""
@@ -1753,7 +1753,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_selectable_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are selectable"""
@@ -1763,7 +1763,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_selected_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are selected"""
@@ -1773,7 +1773,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_separators(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the separator role"""
@@ -1783,7 +1783,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_set_containers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with a set container role"""
@@ -1793,7 +1793,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_showing_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are showing"""
@@ -1803,7 +1803,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_showing_and_visible_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are showing and visible"""
@@ -1813,7 +1813,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_showing_or_visible_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are showing or visible"""
@@ -1823,7 +1823,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_single_line_entries(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the entry role and multiline state"""
@@ -1834,7 +1834,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_sliders(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the slider role"""
@@ -1844,7 +1844,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_spin_buttons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the spin button role"""
@@ -1854,7 +1854,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_split_panes(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the split pane role"""
@@ -1864,7 +1864,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_statics(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the static role"""
@@ -1874,7 +1874,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_status_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the statusbar role"""
@@ -1884,7 +1884,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_subscripts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the subscript role"""
@@ -1894,7 +1894,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_subscripts_and_superscripts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the subscript or superscript role"""
@@ -1904,7 +1904,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_suggestions(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the suggestion role"""
@@ -1914,7 +1914,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_superscripts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the superscript role"""
@@ -1924,7 +1924,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_action(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the action interface"""
@@ -1934,7 +1934,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_document(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the document interface"""
@@ -1944,7 +1944,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_editable_text(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the editable text interface"""
@@ -1954,7 +1954,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_hypertext(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the hypertext interface"""
@@ -1964,7 +1964,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_hyperlink(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the hyperlink interface"""
@@ -1974,7 +1974,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_selection(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the selection interface"""
@@ -1984,7 +1984,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_table(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the table interface"""
@@ -1994,7 +1994,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_table_cell(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the table cell interface"""
@@ -2004,7 +2004,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_text(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the text interface"""
@@ -2014,7 +2014,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_supports_value(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which support the value interface"""
@@ -2024,7 +2024,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tables(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table role"""
@@ -2051,7 +2051,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_cells(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table cell role"""
@@ -2061,7 +2061,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_cells_and_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table cell or a header-related role"""
@@ -2071,7 +2071,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_column_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table column header role"""
@@ -2081,7 +2081,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has a table header related role"""
@@ -2091,7 +2091,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_related_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None,
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None,
include_caption: bool = False
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has a table related role"""
@@ -2102,7 +2102,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_rows(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table row role"""
@@ -2112,7 +2112,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_table_row_headers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the table row header role"""
@@ -2122,7 +2122,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tearoff_menu_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tearoff menu item role"""
@@ -2132,7 +2132,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_terminals(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the terminal role"""
@@ -2142,7 +2142,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_texts(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the text role"""
@@ -2152,7 +2152,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_text_inputs(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has any role associated with textual input"""
@@ -2162,7 +2162,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_timers(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the timer role"""
@@ -2172,7 +2172,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_title_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the titlebar role"""
@@ -2182,7 +2182,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_toggle_buttons(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the toggle button role"""
@@ -2192,7 +2192,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tool_bars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the toolbar role"""
@@ -2202,7 +2202,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tool_tips(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tooltip role"""
@@ -2212,7 +2212,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_trees(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tree role"""
@@ -2222,7 +2222,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_trees_and_tree_tables(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tree or tree table role"""
@@ -2232,7 +2232,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tree_related_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that has a tree related role"""
@@ -2242,7 +2242,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tree_items(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tree item role"""
@@ -2252,7 +2252,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_tree_tables(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the tree table role"""
@@ -2263,7 +2263,7 @@ class AXUtilitiesCollection:
def find_all_unrelated_labels(
root: Atspi.Accessible,
must_be_showing: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all the descendants of root that have a label role, but no relations"""
@@ -2288,7 +2288,7 @@ class AXUtilitiesCollection:
def find_all_unvisited_links(
root: Atspi.Accessible,
must_be_focusable: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the link role and without the visited state"""
@@ -2302,7 +2302,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_vertical_scrollbars(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a vertical scrollbar"""
@@ -2313,7 +2313,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_vertical_separators(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a vertical separator"""
@@ -2324,7 +2324,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_vertical_sliders(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root that is a vertical slider"""
@@ -2335,7 +2335,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_visible_objects(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root which are visible"""
@@ -2345,7 +2345,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_videos(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the video role"""
@@ -2355,7 +2355,7 @@ class AXUtilitiesCollection:
@staticmethod
def find_all_viewports(
root: Atspi.Accessible,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the viewport role"""
@@ -2366,7 +2366,7 @@ class AXUtilitiesCollection:
def find_all_visited_links(
root: Atspi.Accessible,
must_be_focusable: bool = True,
- pred: Callable[[Atspi.Accessible], bool] | None = None
+ pred: Optional[Callable[[Atspi.Accessible], bool]] = None
) -> list[Atspi.Accessible]:
"""Returns all descendants of root with the link role and focused and visited states"""
@@ -2377,7 +2377,7 @@ class AXUtilitiesCollection:
return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred)
@staticmethod
- def find_default_button(root: Atspi.Accessible) -> Atspi.Accessible | None:
+ def find_default_button(root: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the default button inside root"""
roles = [Atspi.Role.BUTTON]
@@ -2386,7 +2386,7 @@ class AXUtilitiesCollection:
return AXCollection.get_first_match(root, rule)
@staticmethod
- def find_focused_object(root: Atspi.Accessible) -> Atspi.Accessible | None:
+ def find_focused_object(root: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the focused object inside root"""
states = [Atspi.StateType.FOCUSED]
@@ -2394,7 +2394,7 @@ class AXUtilitiesCollection:
return AXCollection.get_first_match(root, rule)
@staticmethod
- def find_info_bar(root: Atspi.Accessible) -> Atspi.Accessible | None:
+ def find_info_bar(root: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the info bar inside root"""
roles = [Atspi.Role.INFO_BAR]
@@ -2403,7 +2403,7 @@ class AXUtilitiesCollection:
return AXCollection.get_first_match(root, rule)
@staticmethod
- def find_status_bar(root: Atspi.Accessible) -> Atspi.Accessible | None:
+ def find_status_bar(root: Atspi.Accessible) -> Optional[Atspi.Accessible]:
"""Returns the status bar inside root"""
roles = [Atspi.Role.STATUS_BAR]
diff --git a/src/cthulhu/ax_utilities_relation.py b/src/cthulhu/ax_utilities_relation.py
index 0947f74..c9cfee4 100644
--- a/src/cthulhu/ax_utilities_relation.py
+++ b/src/cthulhu/ax_utilities_relation.py
@@ -35,6 +35,7 @@ __copyright__ = "Copyright (c) 2024 Igalia, S.L." \
"Copyright (c) 2024 GNOME Foundation Inc."
__license__ = "LGPL"
+from typing import Optional
import threading
import time
@@ -118,7 +119,7 @@ class AXUtilitiesRelation:
def _get_relation(
obj: Atspi.Accessible,
relation_type: Atspi.RelationType
- ) -> Atspi.Relation | None:
+ ) -> Optional[Atspi.Relation]:
"""Returns the specified Atspi.Relation for obj"""
for relation in AXUtilitiesRelation.get_relations(obj):
diff --git a/src/cthulhu/ax_utilities_role.py b/src/cthulhu/ax_utilities_role.py
index e4901d3..269d39d 100644
--- a/src/cthulhu/ax_utilities_role.py
+++ b/src/cthulhu/ax_utilities_role.py
@@ -33,6 +33,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2023 Igalia, S.L."
__license__ = "LGPL"
+from typing import Optional
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
@@ -51,7 +52,7 @@ class AXUtilitiesRole:
return attrs.get("display", "")
@staticmethod
- def _get_tag(obj: Atspi.Accessible) -> str | None:
+ def _get_tag(obj: Atspi.Accessible) -> Optional[str]:
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("tag")
@@ -63,7 +64,7 @@ class AXUtilitiesRole:
@staticmethod
def children_are_presentational(
obj: Atspi.Accessible,
- role: Atspi.Role | None = None
+ role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if the descendants of obj should be ignored. See ARIA spec."""
@@ -307,7 +308,7 @@ class AXUtilitiesRole:
return roles
@staticmethod
- def get_localized_role_name(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> str:
+ def get_localized_role_name(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> str:
"""Returns a string representing the localized role name of obj."""
if role is None:
@@ -455,7 +456,7 @@ class AXUtilitiesRole:
return AXObject.get_role(obj1) == AXObject.get_role(obj2)
@staticmethod
- def is_accelerator_label(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_accelerator_label(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the accelerator label role"""
if role is None:
@@ -463,7 +464,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ACCELERATOR_LABEL
@staticmethod
- def is_alert(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the alert (a type of dialog) role"""
if role is None:
@@ -471,7 +472,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ALERT
@staticmethod
- def is_aria_alert(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_aria_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an ARIA alert (should have notification role)"""
if "alert" not in AXUtilitiesRole._get_xml_roles(obj):
@@ -487,7 +488,7 @@ class AXUtilitiesRole:
return True
@staticmethod
- def is_animation(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_animation(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the animation role"""
if role is None:
@@ -495,7 +496,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ANIMATION
@staticmethod
- def is_application(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_application(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the application role"""
if role is None:
@@ -503,7 +504,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.APPLICATION
@staticmethod
- def is_arrow(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_arrow(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the arrow role"""
if role is None:
@@ -511,7 +512,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ARROW
@staticmethod
- def is_article(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_article(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the article role"""
if role is None:
@@ -519,7 +520,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ARTICLE
@staticmethod
- def is_audio(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_audio(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the audio role"""
if role is None:
@@ -527,7 +528,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.AUDIO
@staticmethod
- def is_autocomplete(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_autocomplete(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the autocomplete role"""
if role is None:
@@ -535,7 +536,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.AUTOCOMPLETE
@staticmethod
- def is_block_quote(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_block_quote(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the block quote role"""
if role is None:
@@ -543,7 +544,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.BLOCK_QUOTE or AXUtilitiesRole._get_tag(obj) == "blockquote"
@staticmethod
- def is_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push- or toggle-button role"""
if role is None:
@@ -551,7 +552,7 @@ class AXUtilitiesRole:
return role in [Atspi.Role.BUTTON, Atspi.Role.TOGGLE_BUTTON]
@staticmethod
- def is_button_with_popup(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_button_with_popup(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push- or toggle-button role and a popup"""
if not AXUtilitiesRole.is_button(obj, role):
@@ -559,7 +560,7 @@ class AXUtilitiesRole:
return AXUtilitiesState.has_popup(obj)
@staticmethod
- def is_calendar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_calendar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the calendar role"""
if role is None:
@@ -567,7 +568,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.CALENDAR
@staticmethod
- def is_canvas(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the canvas role"""
if role is None:
@@ -575,7 +576,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.CANVAS
@staticmethod
- def is_caption(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_caption(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the caption role"""
if role is None:
@@ -583,7 +584,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.CAPTION
@staticmethod
- def is_chart(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_chart(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the chart role"""
if role is None:
@@ -591,7 +592,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.CHART
@staticmethod
- def is_check_box(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_check_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the checkbox role"""
if role is None:
@@ -599,7 +600,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.CHECK_BOX
@staticmethod
- def is_check_menu_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_check_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the check menuitem role"""
if role is None:
@@ -607,14 +608,14 @@ class AXUtilitiesRole:
return role == Atspi.Role.CHECK_MENU_ITEM
@staticmethod
- def is_code(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_code(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the code or code-like role"""
return "code" in AXUtilitiesRole._get_xml_roles(obj) \
or AXUtilitiesRole._get_tag(obj) in ["code", "pre"]
@staticmethod
- def is_color_chooser(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_color_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the color_chooser role"""
if role is None:
@@ -622,7 +623,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.COLOR_CHOOSER
@staticmethod
- def is_column_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_column_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the column header role"""
if role is None:
@@ -630,7 +631,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.COLUMN_HEADER
@staticmethod
- def is_combo_box(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_combo_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the combobox role"""
if role is None:
@@ -638,7 +639,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.COMBO_BOX
@staticmethod
- def is_comment(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_comment(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the comment role"""
if role is None:
@@ -646,7 +647,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.COMMENT or "comment" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_content_deletion(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_content_deletion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the content deletion role"""
if role is None:
@@ -656,7 +657,7 @@ class AXUtilitiesRole:
or "del" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_content_insertion(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_content_insertion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the content insertion role"""
if role is None:
@@ -666,7 +667,7 @@ class AXUtilitiesRole:
or "ins" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_date_editor(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_date_editor(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the date editor role"""
if role is None:
@@ -674,14 +675,14 @@ class AXUtilitiesRole:
return role == Atspi.Role.DATE_EDITOR
@staticmethod
- def is_default_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_default_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button role the is-default state"""
return AXUtilitiesRole.is_push_button(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.IS_DEFAULT)
@staticmethod
- def is_definition(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_definition(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the definition role"""
if role is None:
@@ -689,7 +690,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DEFINITION
@staticmethod
- def is_description_list(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_description_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description list role"""
if role is None:
@@ -698,7 +699,7 @@ class AXUtilitiesRole:
or "dl" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_description_term(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_description_term(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description term role"""
if role is None:
@@ -707,7 +708,7 @@ class AXUtilitiesRole:
or "dt" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_description_value(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_description_value(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description value role"""
if role is None:
@@ -716,7 +717,7 @@ class AXUtilitiesRole:
or "dd" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_desktop_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_desktop_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the desktop frame role"""
if role is None:
@@ -729,7 +730,7 @@ class AXUtilitiesRole:
return False
@staticmethod
- def is_desktop_icon(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_desktop_icon(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the desktop icon role"""
if role is None:
@@ -737,7 +738,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DESKTOP_ICON
@staticmethod
- def is_dial(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_dial(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the dial role"""
if role is None:
@@ -745,7 +746,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DIAL
@staticmethod
- def is_dialog(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_dialog(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the dialog role"""
if role is None:
@@ -753,7 +754,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DIALOG
@staticmethod
- def is_dialog_or_alert(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_dialog_or_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any dialog or alert role"""
roles = AXUtilitiesRole.get_dialog_roles(True)
@@ -762,7 +763,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_dialog_or_window(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_dialog_or_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any dialog or window-related role"""
roles = AXUtilitiesRole.get_dialog_roles(False)
@@ -772,7 +773,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_directory_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_directory_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the directory pane role"""
if role is None:
@@ -780,7 +781,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DIRECTORY_PANE
@staticmethod
- def is_docked_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_docked_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the frame role and is docked."""
if not AXUtilitiesRole.is_frame(obj, role):
@@ -790,7 +791,7 @@ class AXUtilitiesRole:
return attrs.get("window-type") == "dock"
@staticmethod
- def is_document(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any document-related role"""
roles = AXUtilitiesRole.get_document_roles()
@@ -799,7 +800,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_document_email(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_email(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document email role"""
if role is None:
@@ -807,7 +808,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_EMAIL
@staticmethod
- def is_document_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document frame role"""
if role is None:
@@ -815,7 +816,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_FRAME
@staticmethod
- def is_document_presentation(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_presentation(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document presentation role"""
if role is None:
@@ -823,7 +824,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_PRESENTATION
@staticmethod
- def is_document_spreadsheet(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_spreadsheet(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document spreadsheet role"""
if role is None:
@@ -831,7 +832,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_SPREADSHEET
@staticmethod
- def is_document_text(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document text role"""
if role is None:
@@ -839,7 +840,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_TEXT
@staticmethod
- def is_document_web(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_document_web(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document web role"""
if role is None:
@@ -847,7 +848,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DOCUMENT_WEB
@staticmethod
- def is_dpub(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a DPub role."""
roles = AXUtilitiesRole._get_xml_roles(obj)
@@ -855,223 +856,223 @@ class AXUtilitiesRole:
return rv
@staticmethod
- def is_dpub_abstract(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_abstract(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub abstract role."""
return "doc-abstract" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_acknowledgments(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_acknowledgments(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub acknowledgments role."""
return "doc-acknowledgments" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_afterword(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_afterword(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub afterword role."""
return "doc-afterword" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_appendix(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_appendix(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub appendix role."""
return "doc-appendix" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_backlink(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_backlink(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub backlink role."""
return "doc-backlink" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_biblioref(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_biblioref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub biblioref role."""
return "doc-biblioref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_bibliography(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_bibliography(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub bibliography role."""
return "doc-bibliography" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_chapter(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_chapter(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub chapter role."""
return "doc-chapter" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_colophon(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_colophon(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub colophon role."""
return "doc-colophon" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_conclusion(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_conclusion(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub conclusion role."""
return "doc-conclusion" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_cover(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_cover(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub cover role."""
return "doc-cover" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_credit(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_credit(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub credit role."""
return "doc-credit" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_credits(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_credits(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub credits role."""
return "doc-credits" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_dedication(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_dedication(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub dedication role."""
return "doc-dedication" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_endnote(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_endnote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub endnote role."""
return "doc-endnote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_endnotes(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_endnotes(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub endnotes role."""
return "doc-endnotes" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_epigraph(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_epigraph(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub epigraph role."""
return "doc-epigraph" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_epilogue(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_epilogue(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub epilogue role."""
return "doc-epilogue" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_errata(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_errata(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub errata role."""
return "doc-errata" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_example(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_example(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub example role."""
return "doc-example" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_footnote(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_footnote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub footnote role."""
return "doc-footnote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_foreword(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_foreword(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub foreword role."""
return "doc-foreword" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_glossary(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_glossary(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub glossary role."""
return "doc-glossary" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_glossref(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_glossref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub glossref role."""
return "doc-glossref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_index(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_index(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub index role."""
return "doc-index" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_introduction(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_introduction(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub introduction role."""
return "doc-introduction" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_noteref(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_noteref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub noteref role."""
return "doc-noteref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_pagelist(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_pagelist(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pagelist role."""
return "doc-pagelist" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_pagebreak(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_pagebreak(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pagebreak role."""
return "doc-pagebreak" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_part(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_part(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub part role."""
return "doc-part" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_preface(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_preface(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub preface role."""
return "doc-preface" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_prologue(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_prologue(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub prologue role."""
return "doc-prologue" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_pullquote(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_pullquote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pullquote role."""
return "doc-pullquote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_qna(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_qna(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub qna role."""
return "doc-qna" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_subtitle(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_subtitle(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub subtitle role."""
return "doc-subtitle" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_dpub_toc(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_dpub_toc(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub toc role."""
return "doc-toc" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_drawing_area(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_drawing_area(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the drawing area role"""
if role is None:
@@ -1079,7 +1080,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.DRAWING_AREA
@staticmethod
- def is_editable_combo_box(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_editable_combo_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an editable combobox"""
if role is None:
@@ -1091,7 +1092,7 @@ class AXUtilitiesRole:
return bool(AXObject.find_descendant(obj, AXUtilitiesRole.is_text_input))
@staticmethod
- def is_editbar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_editbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the editbar role"""
if role is None:
@@ -1099,7 +1100,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.EDITBAR
@staticmethod
- def is_embedded(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_embedded(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the embedded role"""
if role is None:
@@ -1107,7 +1108,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.EMBEDDED
@staticmethod
- def is_entry(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role"""
if role is None:
@@ -1115,7 +1116,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ENTRY
@staticmethod
- def is_extended(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_extended(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the extended role"""
if role is None:
@@ -1123,13 +1124,13 @@ class AXUtilitiesRole:
return role == Atspi.Role.EXTENDED
@staticmethod
- def is_feed(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_feed(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the feed role"""
return "feed" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_feed_article(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_feed_article(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the article role and descends from a feed."""
if not AXUtilitiesRole.is_article(obj, role):
@@ -1138,14 +1139,14 @@ class AXUtilitiesRole:
return AXObject.find_ancestor(obj, AXUtilitiesRole.is_feed) is not None
@staticmethod
- def is_figure(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_figure(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the figure role or tag."""
return "figure" in AXUtilitiesRole._get_xml_roles(obj) \
or AXUtilitiesRole._get_tag(obj) == "figure"
@staticmethod
- def is_file_chooser(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_file_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the file chooser role"""
if role is None:
@@ -1153,7 +1154,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FILE_CHOOSER
@staticmethod
- def is_filler(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_filler(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the filler role"""
if role is None:
@@ -1161,7 +1162,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FILLER
@staticmethod
- def is_focus_traversable(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_focus_traversable(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the focus traversable role"""
if role is None:
@@ -1169,7 +1170,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FOCUS_TRAVERSABLE
@staticmethod
- def is_font_chooser(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_font_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the font chooser role"""
if role is None:
@@ -1177,7 +1178,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FONT_CHOOSER
@staticmethod
- def is_footer(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_footer(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the footer role"""
if role is None:
@@ -1185,7 +1186,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FOOTER
@staticmethod
- def is_footnote(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_footnote(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the footnote role"""
if role is None:
@@ -1193,7 +1194,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FOOTNOTE
@staticmethod
- def is_form(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_form(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the form role"""
if role is None:
@@ -1201,7 +1202,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FORM
@staticmethod
- def is_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the frame role"""
if role is None:
@@ -1209,7 +1210,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.FRAME
@staticmethod
- def is_glass_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_glass_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the glass pane role"""
if role is None:
@@ -1217,7 +1218,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.GLASS_PANE
@staticmethod
- def is_gui_list(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_gui_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list role but contains UI rather than static text."""
if not AXUtilitiesRole.is_list(obj, role):
@@ -1226,7 +1227,7 @@ class AXUtilitiesRole:
return AXObject.get_toolkit_name(obj) == "gtk"
@staticmethod
- def is_grid(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_grid(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the grid role."""
if not AXUtilitiesRole.is_table(obj, role):
@@ -1235,7 +1236,7 @@ class AXUtilitiesRole:
return "grid" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_grid_cell(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_grid_cell(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the gridcell role or the cell role and is in a grid."""
if not AXUtilitiesRole.is_table_cell(obj, role):
@@ -1249,13 +1250,13 @@ class AXUtilitiesRole:
return False
@staticmethod
- def is_group(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_group(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an ARIA group."""
return "group" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_grouping(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_grouping(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the grouping role"""
if role is None:
@@ -1263,7 +1264,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.GROUPING
@staticmethod
- def is_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the header role"""
if role is None:
@@ -1271,7 +1272,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.HEADER
@staticmethod
- def is_heading(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_heading(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the heading role"""
if role is None:
@@ -1279,7 +1280,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.HEADING
@staticmethod
- def is_html_container(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_html_container(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the html container role"""
if role is None:
@@ -1287,28 +1288,28 @@ class AXUtilitiesRole:
return role == Atspi.Role.HTML_CONTAINER
@staticmethod
- def is_horizontal_scrollbar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_horizontal_scrollbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal scrollbar"""
return AXUtilitiesRole.is_scroll_bar(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
- def is_horizontal_separator(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_horizontal_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal separator"""
return AXUtilitiesRole.is_separator(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
- def is_horizontal_slider(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_horizontal_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal slider"""
return AXUtilitiesRole.is_slider(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
- def is_icon(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_icon(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the icon role"""
if role is None:
@@ -1316,7 +1317,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ICON
@staticmethod
- def is_icon_or_canvas(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_icon_or_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the icon or canvas role"""
if role is None:
@@ -1324,7 +1325,7 @@ class AXUtilitiesRole:
return role in [Atspi.Role.ICON, Atspi.Role.CANVAS]
@staticmethod
- def is_image(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_image(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image role"""
if role is None:
@@ -1332,7 +1333,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.IMAGE
@staticmethod
- def is_image_or_canvas(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_image_or_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image or canvas role"""
if role is None:
@@ -1340,7 +1341,7 @@ class AXUtilitiesRole:
return role in [Atspi.Role.IMAGE, Atspi.Role.CANVAS]
@staticmethod
- def is_image_map(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_image_map(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image map role"""
if role is None:
@@ -1348,7 +1349,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.IMAGE_MAP
@staticmethod
- def is_info_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_info_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the info bar role"""
if role is None:
@@ -1356,7 +1357,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.INFO_BAR
@staticmethod
- def is_inline_internal_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_inline_internal_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the internal frame role and is inline."""
if not AXUtilitiesRole.is_internal_frame(obj, role):
@@ -1365,7 +1366,7 @@ class AXUtilitiesRole:
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
- def is_inline_list_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_inline_list_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list item role and is inline."""
if not AXUtilitiesRole.is_list_item(obj, role):
@@ -1374,7 +1375,7 @@ class AXUtilitiesRole:
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
- def is_inline_suggestion(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_inline_suggestion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the suggestion role and is inline."""
if not AXUtilitiesRole.is_suggestion(obj, role):
@@ -1383,7 +1384,7 @@ class AXUtilitiesRole:
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
- def is_input_method_window(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_input_method_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the input method window role"""
if role is None:
@@ -1391,7 +1392,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.INPUT_METHOD_WINDOW
@staticmethod
- def is_internal_frame(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_internal_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the internal frame role"""
if role is None:
@@ -1399,7 +1400,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.INTERNAL_FRAME or AXUtilitiesRole._get_tag(obj) == "iframe"
@staticmethod
- def is_invalid_role(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_invalid_role(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the invalid role"""
if role is None:
@@ -1407,7 +1408,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.INVALID
@staticmethod
- def is_label(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_label(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the label role"""
if role is None:
@@ -1415,7 +1416,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LABEL
@staticmethod
- def is_label_or_caption(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_label_or_caption(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the label or caption role"""
if role is None:
@@ -1423,7 +1424,7 @@ class AXUtilitiesRole:
return role in [Atspi.Role.LABEL, Atspi.Role.CAPTION]
@staticmethod
- def is_landmark(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_landmark(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the landmark role"""
if role is None:
@@ -1431,57 +1432,57 @@ class AXUtilitiesRole:
return role == Atspi.Role.LANDMARK
@staticmethod
- def is_landmark_banner(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_banner(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the banner landmark role"""
return "banner" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_complementary(
- obj: Atspi.Accessible, _role: Atspi.Role | None = None
+ obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the complementary landmark role"""
return "complementary" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_contentinfo(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_contentinfo(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the contentinfo landmark role"""
return "contentinfo" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_form(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_form(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the form landmark role"""
return "form" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_main(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_main(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the main landmark role"""
return "main" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_navigation(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_navigation(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the navigation landmark role"""
return "navigation" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_region(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_region(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the region landmark role"""
return "region" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_search(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_landmark_search(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the search landmark role"""
return "search" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_landmark_without_type(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_landmark_without_type(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the landmark role but no type"""
if not AXUtilitiesRole.is_landmark(obj, role):
@@ -1491,7 +1492,7 @@ class AXUtilitiesRole:
return not roles
@staticmethod
- def is_large_container(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_large_container(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a large container role"""
if role is None:
@@ -1500,7 +1501,7 @@ class AXUtilitiesRole:
return role in AXUtilitiesRole.get_large_container_roles()
@staticmethod
- def is_layered_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_layered_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the layered pane role"""
if role is None:
@@ -1508,7 +1509,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LAYERED_PANE
@staticmethod
- def is_level_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_level_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the level bar role"""
if role is None:
@@ -1516,7 +1517,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LEVEL_BAR
@staticmethod
- def is_link(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_link(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the link role"""
if role is None:
@@ -1524,7 +1525,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LINK
@staticmethod
- def is_list(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list role"""
if role is None:
@@ -1532,7 +1533,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LIST
@staticmethod
- def is_list_box(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_list_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list box role"""
if role is None:
@@ -1540,7 +1541,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LIST_BOX
@staticmethod
- def is_list_box_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_list_box_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an item in a list box"""
if not AXUtilitiesRole.is_list_item(obj, role):
@@ -1548,7 +1549,7 @@ class AXUtilitiesRole:
return AXObject.find_ancestor(obj, AXUtilitiesRole.is_list_box) is not None
@staticmethod
- def is_list_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_list_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list item role"""
if role is None:
@@ -1556,7 +1557,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.LIST_ITEM
@staticmethod
- def is_log(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_log(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the log role"""
if role is None:
@@ -1564,14 +1565,14 @@ class AXUtilitiesRole:
return role == Atspi.Role.LOG
@staticmethod
- def is_live_region(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_live_region(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a live region."""
attrs = AXObject.get_attributes_dict(obj)
return "container-live" in attrs and attrs.get("container-live") in ["polite", "assertive"]
@staticmethod
- def is_mark(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_mark(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the mark role"""
if role is None:
@@ -1581,7 +1582,7 @@ class AXUtilitiesRole:
or "mark" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_marquee(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_marquee(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the marquee role"""
if role is None:
@@ -1589,7 +1590,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.MARQUEE
@staticmethod
- def is_math(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_math(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math role"""
if role is None:
@@ -1609,7 +1610,7 @@ class AXUtilitiesRole:
return AXUtilitiesRole._get_tag(obj) == "mfenced"
@staticmethod
- def is_math_fraction(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_math_fraction(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math fraction role"""
if role is None:
@@ -1618,7 +1619,7 @@ class AXUtilitiesRole:
@staticmethod
def is_math_fraction_without_bar(
- obj: Atspi.Accessible, role: Atspi.Role | None = None
+ obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the math fraction role and lacks the fraction bar"""
@@ -1649,7 +1650,7 @@ class AXUtilitiesRole:
return AXUtilitiesRole._get_tag(obj) == "mmultiscripts"
@staticmethod
- def is_math_related(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_math_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a math-related role"""
if role is None:
@@ -1698,7 +1699,7 @@ class AXUtilitiesRole:
"munderover"]
@staticmethod
- def is_math_root(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_math_root(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math root role"""
if role is None:
@@ -1742,7 +1743,7 @@ class AXUtilitiesRole:
return AXUtilitiesRole._get_tag(obj) in ["mover", "munder", "munderover"]
@staticmethod
- def is_menu(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menu role"""
if role is None:
@@ -1750,7 +1751,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.MENU
@staticmethod
- def is_menu_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_menu_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menubar role"""
if role is None:
@@ -1758,7 +1759,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.MENU_BAR
@staticmethod
- def is_menu_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menu item role"""
if role is None:
@@ -1766,7 +1767,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.MENU_ITEM
@staticmethod
- def is_menu_item_of_any_kind(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_menu_item_of_any_kind(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any menu item role"""
roles = AXUtilitiesRole.get_menu_item_roles()
@@ -1775,7 +1776,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_menu_related(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_menu_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any menu-related role"""
roles = AXUtilitiesRole.get_menu_related_roles()
@@ -1784,21 +1785,21 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_modal_dialog(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_modal_dialog(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the alert or dialog role and modal state"""
return AXUtilitiesRole.is_dialog_or_alert(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.MODAL)
@staticmethod
- def is_multi_line_entry(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_multi_line_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role and multiline state"""
return AXUtilitiesRole.is_entry(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.MULTI_LINE)
@staticmethod
- def is_notification(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_notification(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the notification role"""
if role is None:
@@ -1806,7 +1807,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.NOTIFICATION
@staticmethod
- def is_option_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_option_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the option pane role"""
if role is None:
@@ -1814,7 +1815,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.OPTION_PANE
@staticmethod
- def is_page(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_page(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page role"""
if role is None:
@@ -1822,7 +1823,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PAGE
@staticmethod
- def is_page_tab(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_page_tab(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab role"""
if role is None:
@@ -1830,7 +1831,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PAGE_TAB
@staticmethod
- def is_page_tab_list(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_page_tab_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab list role"""
if role is None:
@@ -1838,7 +1839,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PAGE_TAB_LIST
@staticmethod
- def is_page_tab_list_related(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_page_tab_list_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab or page tab list role"""
roles = [Atspi.Role.PAGE_TAB_LIST, Atspi.Role.PAGE_TAB]
@@ -1847,7 +1848,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_panel(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_panel(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the panel role"""
if role is None:
@@ -1855,7 +1856,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PANEL
@staticmethod
- def is_paragraph(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_paragraph(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the paragraph role"""
if role is None:
@@ -1863,7 +1864,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PARAGRAPH
@staticmethod
- def is_password_text(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_password_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the password text role"""
if role is None:
@@ -1871,7 +1872,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PASSWORD_TEXT
@staticmethod
- def is_popup_menu(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_popup_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the popup menu role"""
if role is None:
@@ -1879,7 +1880,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.POPUP_MENU
@staticmethod
- def is_progress_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_progress_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the progress bar role"""
if role is None:
@@ -1887,7 +1888,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PROGRESS_BAR
@staticmethod
- def is_push_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_push_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button role"""
if role is None:
@@ -1895,7 +1896,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.BUTTON
@staticmethod
- def is_push_button_menu(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_push_button_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button menu role"""
if role is None:
@@ -1903,7 +1904,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.PUSH_BUTTON_MENU
@staticmethod
- def is_radio_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_radio_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the radio button role"""
if role is None:
@@ -1911,7 +1912,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.RADIO_BUTTON
@staticmethod
- def is_radio_menu_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_radio_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the radio menu item role"""
if role is None:
@@ -1919,7 +1920,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.RADIO_MENU_ITEM
@staticmethod
- def is_rating(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_rating(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the rating role"""
if role is None:
@@ -1927,7 +1928,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.RATING
@staticmethod
- def is_redundant_object_role(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_redundant_object_role(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the redundant object role"""
if role is None:
@@ -1935,7 +1936,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.REDUNDANT_OBJECT
@staticmethod
- def is_root_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_root_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the root pane role"""
if role is None:
@@ -1943,7 +1944,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ROOT_PANE
@staticmethod
- def is_row_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_row_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the row header role"""
if role is None:
@@ -1951,7 +1952,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.ROW_HEADER
@staticmethod
- def is_ruler(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_ruler(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the ruler role"""
if role is None:
@@ -1959,7 +1960,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.RULER
@staticmethod
- def is_scroll_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_scroll_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the scrollbar role"""
if role is None:
@@ -1967,7 +1968,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SCROLL_BAR
@staticmethod
- def is_scroll_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_scroll_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the scroll pane role"""
if role is None:
@@ -1975,7 +1976,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SCROLL_PANE
@staticmethod
- def is_section(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_section(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the section role"""
if role is None:
@@ -1983,7 +1984,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SECTION
@staticmethod
- def is_separator(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the separator role"""
if role is None:
@@ -1992,7 +1993,7 @@ class AXUtilitiesRole:
@staticmethod
def is_single_line_autocomplete_entry(
- obj: Atspi.Accessible, role: Atspi.Role | None = None
+ obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the entry role and single-line state"""
@@ -2002,7 +2003,7 @@ class AXUtilitiesRole:
return AXUtilitiesState.supports_autocompletion(obj)
@staticmethod
- def is_single_line_entry(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_single_line_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role and the single-line state"""
if not AXUtilitiesState.is_single_line(obj):
@@ -2014,7 +2015,7 @@ class AXUtilitiesRole:
return False
@staticmethod
- def is_slider(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the slider role"""
if role is None:
@@ -2022,7 +2023,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SLIDER
@staticmethod
- def is_spin_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_spin_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the spin button role"""
if role is None:
@@ -2030,7 +2031,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SPIN_BUTTON
@staticmethod
- def is_split_pane(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_split_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the split pane role"""
if role is None:
@@ -2038,7 +2039,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.SPLIT_PANE
@staticmethod
- def is_static(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_static(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the static role"""
if role is None:
@@ -2046,7 +2047,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.STATIC
@staticmethod
- def is_status_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_status_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the statusbar role"""
if role is None:
@@ -2054,7 +2055,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.STATUS_BAR
@staticmethod
- def is_subscript(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_subscript(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the subscript role"""
if role is None:
@@ -2063,7 +2064,7 @@ class AXUtilitiesRole:
@staticmethod
def is_subscript_or_superscript(
- obj: Atspi.Accessible, role: Atspi.Role | None = None
+ obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the subscript or superscript role"""
@@ -2073,7 +2074,7 @@ class AXUtilitiesRole:
@staticmethod
def is_subscript_or_superscript_text(
- obj: Atspi.Accessible, role: Atspi.Role | None = None
+ obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the subscript or superscript role and is not math-related"""
@@ -2082,7 +2083,7 @@ class AXUtilitiesRole:
return AXUtilitiesRole.is_subscript_or_superscript(obj, role)
@staticmethod
- def is_suggestion(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_suggestion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the suggestion role"""
if role is None:
@@ -2091,7 +2092,7 @@ class AXUtilitiesRole:
or "suggestion" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_superscript(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_superscript(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the superscript role"""
if role is None:
@@ -2105,7 +2106,7 @@ class AXUtilitiesRole:
return AXUtilitiesRole._get_tag(obj) == "svg"
@staticmethod
- def is_switch(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_switch(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the switch role."""
if role is None:
@@ -2117,7 +2118,7 @@ class AXUtilitiesRole:
return "switch" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
- def is_table(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table role"""
if role is None:
@@ -2125,7 +2126,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TABLE
@staticmethod
- def is_table_cell(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_cell(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table cell role"""
if role is None:
@@ -2133,7 +2134,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TABLE_CELL
@staticmethod
- def is_table_cell_or_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_cell_or_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table cell or a header-related role"""
roles = AXUtilitiesRole.get_table_cell_roles()
@@ -2142,7 +2143,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_table_column_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_column_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table column header role"""
if role is None:
@@ -2150,7 +2151,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TABLE_COLUMN_HEADER
@staticmethod
- def is_table_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a table header related role"""
roles = AXUtilitiesRole.get_table_header_roles()
@@ -2161,7 +2162,7 @@ class AXUtilitiesRole:
@staticmethod
def is_table_related(
obj: Atspi.Accessible,
- role: Atspi.Role | None = None,
+ role: Optional[Atspi.Role] = None,
include_caption: bool = False
) -> bool:
"""Returns True if obj has a table-related role"""
@@ -2172,7 +2173,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_table_row(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_row(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table row role"""
if role is None:
@@ -2180,7 +2181,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TABLE_ROW
@staticmethod
- def is_table_row_header(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_table_row_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table row header role"""
if role is None:
@@ -2188,7 +2189,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TABLE_ROW_HEADER
@staticmethod
- def is_tearoff_menu_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tearoff_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tearoff menu item role"""
if role is None:
@@ -2196,14 +2197,14 @@ class AXUtilitiesRole:
return role == Atspi.Role.TEAROFF_MENU_ITEM
@staticmethod
- def is_terminal(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_terminal(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the terminal role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TERMINAL
@staticmethod
- def is_text(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the text role"""
if role is None:
@@ -2211,7 +2212,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TEXT
@staticmethod
- def is_text_input(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any role associated with textual input"""
roles = [Atspi.Role.ENTRY, Atspi.Role.PASSWORD_TEXT, Atspi.Role.SPIN_BUTTON]
@@ -2226,7 +2227,7 @@ class AXUtilitiesRole:
return False
@staticmethod
- def is_text_input_date(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_date(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a date text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2236,7 +2237,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "date"
@staticmethod
- def is_text_input_email(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_email(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an email text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2246,7 +2247,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "email"
@staticmethod
- def is_text_input_number(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_number(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a numeric text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2256,7 +2257,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "number"
@staticmethod
- def is_text_input_search(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_search(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a telephone text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2284,7 +2285,7 @@ class AXUtilitiesRole:
return False
@staticmethod
- def is_text_input_telephone(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_telephone(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a telephone text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2294,7 +2295,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "telephone"
@staticmethod
- def is_text_input_time(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_time(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a time text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2304,7 +2305,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "time"
@staticmethod
- def is_text_input_url(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_url(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a url text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2314,7 +2315,7 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "url"
@staticmethod
- def is_text_input_week(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_text_input_week(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a week text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
@@ -2324,14 +2325,14 @@ class AXUtilitiesRole:
return attrs.get("text-input-type") == "week"
@staticmethod
- def is_time(obj: Atspi.Accessible, _role: Atspi.Role | None = None) -> bool:
+ def is_time(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the time role"""
return "time" in AXUtilitiesRole._get_xml_roles(obj) \
or "time" == AXUtilitiesRole._get_tag(obj)
@staticmethod
- def is_timer(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_timer(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the timer role"""
if role is None:
@@ -2339,7 +2340,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TIMER
@staticmethod
- def is_title_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_title_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the titlebar role"""
if role is None:
@@ -2347,7 +2348,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TITLE_BAR
@staticmethod
- def is_toggle_button(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_toggle_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the toggle button role"""
if role is None:
@@ -2355,7 +2356,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TOGGLE_BUTTON
@staticmethod
- def is_tool_bar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tool_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the toolbar role"""
if role is None:
@@ -2363,7 +2364,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TOOL_BAR
@staticmethod
- def is_tool_tip(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tool_tip(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tooltip role"""
if role is None:
@@ -2371,7 +2372,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TOOL_TIP
@staticmethod
- def is_tree(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tree(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree role"""
if role is None:
@@ -2379,7 +2380,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TREE
@staticmethod
- def is_tree_or_tree_table(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tree_or_tree_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree or tree table role"""
if role is None:
@@ -2387,7 +2388,7 @@ class AXUtilitiesRole:
return role in [Atspi.Role.TREE, Atspi.Role.TREE_TABLE]
@staticmethod
- def is_tree_related(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tree_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a tree-related role"""
roles = [Atspi.Role.TREE,
@@ -2398,7 +2399,7 @@ class AXUtilitiesRole:
return role in roles
@staticmethod
- def is_tree_item(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tree_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree item role"""
if role is None:
@@ -2406,7 +2407,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TREE_ITEM
@staticmethod
- def is_tree_table(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_tree_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree table role"""
if role is None:
@@ -2414,7 +2415,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.TREE_TABLE
@staticmethod
- def is_unknown(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_unknown(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the unknown role"""
if role is None:
@@ -2422,7 +2423,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.UNKNOWN
@staticmethod
- def is_unknown_or_redundant(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_unknown_or_redundant(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the unknown or redundant object role"""
if role is None:
@@ -2430,28 +2431,28 @@ class AXUtilitiesRole:
return role in [Atspi.Role.UNKNOWN, Atspi.Role.REDUNDANT_OBJECT]
@staticmethod
- def is_vertical_scrollbar(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_vertical_scrollbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical scrollbar"""
return AXUtilitiesRole.is_scroll_bar(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
- def is_vertical_separator(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_vertical_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical separator"""
return AXUtilitiesRole.is_separator(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
- def is_vertical_slider(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_vertical_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical slider"""
return AXUtilitiesRole.is_slider(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
- def is_video(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_video(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the video role"""
if role is None:
@@ -2459,7 +2460,7 @@ class AXUtilitiesRole:
return role == Atspi.Role.VIDEO
@staticmethod
- def is_viewport(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_viewport(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the viewport role"""
if role is None:
@@ -2486,7 +2487,7 @@ class AXUtilitiesRole:
return tag is not None and "-" in tag
@staticmethod
- def is_widget(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_widget(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a widget role"""
if role is None:
@@ -2495,7 +2496,7 @@ class AXUtilitiesRole:
@staticmethod
def is_widget_controlled_by_line_navigation(
- obj: Atspi.Accessible, role: Atspi.Role | None = None
+ obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj is a widget controlled by line navigation"""
@@ -2523,7 +2524,7 @@ class AXUtilitiesRole:
Atspi.Role.SPLIT_PANE]
@staticmethod
- def is_window(obj: Atspi.Accessible, role: Atspi.Role | None = None) -> bool:
+ def is_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the window role"""
if role is None:
diff --git a/src/cthulhu/ax_value.py b/src/cthulhu/ax_value.py
index fdce81d..0308f73 100644
--- a/src/cthulhu/ax_value.py
+++ b/src/cthulhu/ax_value.py
@@ -34,6 +34,7 @@ __copyright__ = "Copyright (c) 2024 Igalia, S.L." \
"Copyright (c) 2024 GNOME Foundation Inc."
__license__ = "LGPL"
+from typing import Optional
import threading
import time
@@ -149,7 +150,7 @@ class AXValue:
return f"{current:.{decimal_places}f}"
@staticmethod
- def get_value_as_percent(obj: Atspi.Accessible) -> int | None:
+ def get_value_as_percent(obj: Atspi.Accessible) -> Optional[int]:
"""Returns the current value as a percent, or None if that is not applicable."""
if not AXObject.supports_value(obj):
diff --git a/src/cthulhu/cthulhu-setup.ui b/src/cthulhu/cthulhu-setup.ui
index 337935f..04dc7fa 100644
--- a/src/cthulhu/cthulhu-setup.ui
+++ b/src/cthulhu/cthulhu-setup.ui
@@ -3571,9 +3571,8 @@
False
True
- - Claude Code (Enhanced)
- - Claude (Anthropic)
- - ChatGPT (OpenAI)
+ - Claude Code (CLI)
+ - Codex (CLI)
- Gemini (Google)
- Ollama (Local - Free)
diff --git a/src/cthulhu/cthulhu_gui_prefs.py b/src/cthulhu/cthulhu_gui_prefs.py
index be79be9..9d86efb 100644
--- a/src/cthulhu/cthulhu_gui_prefs.py
+++ b/src/cthulhu/cthulhu_gui_prefs.py
@@ -57,6 +57,7 @@ from . import cthulhu_state
from . import settings
from . import settings_manager
from . import input_event
+from . import input_event_manager
from . import keybindings
from . import pronunciation_dict
from . import braille
@@ -64,6 +65,7 @@ from . import speech
from . import speechserver
from . import text_attribute_names
from . import sound_theme_manager
+from . import script_manager
from .ax_object import AXObject
_settingsManager = settings_manager.getManager()
@@ -1874,10 +1876,12 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
# Set provider combo
provider = prefs.get("aiProvider", settings.aiProvider)
providerIndex = 0 # Default to Claude Code
- if provider == settings.AI_PROVIDER_GEMINI:
+ if provider == settings.AI_PROVIDER_CODEX:
providerIndex = 1
- elif provider == settings.AI_PROVIDER_OLLAMA:
+ elif provider == settings.AI_PROVIDER_GEMINI:
providerIndex = 2
+ elif provider == settings.AI_PROVIDER_OLLAMA:
+ providerIndex = 3
self.aiProviderCombo.set_active(providerIndex)
# Set API key file
@@ -1947,6 +1951,8 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
# Update labels based on provider
if provider == settings.AI_PROVIDER_CLAUDE_CODE:
self.aiApiKeyEntry.set_placeholder_text("No API key needed - uses Claude Code CLI")
+ elif provider == settings.AI_PROVIDER_CODEX:
+ self.aiApiKeyEntry.set_placeholder_text("No API key needed - uses Codex CLI")
elif provider == settings.AI_PROVIDER_OLLAMA:
self.aiApiKeyEntry.set_placeholder_text("No API key needed - uses local Ollama")
else:
@@ -3065,6 +3071,14 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
self._presentMessage(messages.KB_ENTER_NEW_KEY)
cthulhu_state.capturingKeys = True
+ try:
+ script_manager.get_manager().get_active_script().removeKeyGrabs()
+ except Exception:
+ pass
+ try:
+ input_event_manager.get_manager().unmap_all_modifiers()
+ except Exception:
+ pass
editable.connect('key-press-event', self.kbKeyPressed)
return
@@ -3073,6 +3087,10 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
cthulhu_state.capturingKeys = False
self._capturedKey = []
+ try:
+ script_manager.get_manager().get_active_script().refreshKeyGrabs()
+ except Exception:
+ pass
return
def _processKeyCaptured(self, keyPressedEvent):
@@ -3090,9 +3108,17 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
entries = entries_for_keycode[-1]
eventString = Gdk.keyval_name(entries[0])
eventState = keyPressedEvent.state
+ eventKeyvalName = Gdk.keyval_name(keyPressedEvent.keyval)
cthulhuMods = settings.cthulhuModifierKeys
- if eventString in cthulhuMods:
+ if eventKeyvalName in cthulhuMods:
+ eventString = eventKeyvalName
+ self._capturedKey = ['', keybindings.CTHULHU_MODIFIER_MASK, 0]
+ return False
+ if eventKeyvalName == "KP_0" \
+ and "KP_Insert" in cthulhuMods \
+ and eventState & Gdk.ModifierType.SHIFT_MASK:
+ eventString = "KP_Insert"
self._capturedKey = ['', keybindings.CTHULHU_MODIFIER_MASK, 0]
return False
@@ -3180,6 +3206,10 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
cthulhu_state.capturingKeys = False
self._capturedKey = []
+ try:
+ script_manager.get_manager().get_active_script().refreshKeyGrabs()
+ except Exception:
+ pass
myiter = treeModel.get_iter_from_string(path)
try:
originalBinding = treeModel.get_value(myiter, text)
@@ -3793,7 +3823,12 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
def aiProviderChanged(self, widget):
"""AI Provider combo box changed handler"""
- providers = [settings.AI_PROVIDER_CLAUDE_CODE, settings.AI_PROVIDER_GEMINI, settings.AI_PROVIDER_OLLAMA]
+ providers = [
+ settings.AI_PROVIDER_CLAUDE_CODE,
+ settings.AI_PROVIDER_CODEX,
+ settings.AI_PROVIDER_GEMINI,
+ settings.AI_PROVIDER_OLLAMA
+ ]
activeIndex = widget.get_active()
if 0 <= activeIndex < len(providers):
provider = providers[activeIndex]
@@ -3970,4 +4005,3 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
"""OCR copy to clipboard checkbox toggled handler"""
self.prefsDict["ocrCopyToClipboard"] = widget.get_active()
-
diff --git a/src/cthulhu/dbus_service.py b/src/cthulhu/dbus_service.py
index daf51b3..f77aad5 100644
--- a/src/cthulhu/dbus_service.py
+++ b/src/cthulhu/dbus_service.py
@@ -29,7 +29,7 @@ __license__ = "LGPL"
import enum
import inspect
-from typing import Callable
+from typing import Callable, Optional
try:
from dasbus.connection import SessionMessageBus
@@ -156,7 +156,7 @@ class _HandlerInfo:
description: str,
action: Callable[..., bool],
handler_type: 'HandlerType' = HandlerType.COMMAND,
- parameters: list[tuple[str, str]] | None = None
+ parameters: Optional[list[tuple[str, str]]] = None
):
self.python_function_name: str = python_function_name
self.description: str = description
@@ -548,10 +548,10 @@ class CthulhuRemoteController:
OBJECT_PATH = "/org/stormux/Cthulhu/Service"
def __init__(self) -> None:
- self._dbus_service_interface: CthulhuDBusServiceInterface | None = None
+ self._dbus_service_interface: Optional[CthulhuDBusServiceInterface] = None
self._is_running: bool = False
- self._bus: SessionMessageBus | None = None
- self._event_loop: EventLoop | None = None
+ self._bus: Optional[SessionMessageBus] = None
+ self._event_loop: Optional[EventLoop] = None
self._pending_registrations: dict[str, object] = {}
self._total_commands: int = 0
self._total_getters: int = 0
diff --git a/src/cthulhu/focus_manager.py b/src/cthulhu/focus_manager.py
index 600eaa1..35a0d60 100644
--- a/src/cthulhu/focus_manager.py
+++ b/src/cthulhu/focus_manager.py
@@ -40,7 +40,7 @@ __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \
"Copyright (c) 2016-2023 Igalia, S.L."
__license__ = "LGPL"
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -75,13 +75,13 @@ class FocusManager:
"""Manages the focused object, window, etc."""
def __init__(self) -> None:
- self._window: Atspi.Accessible | None = cthulhu_state.activeWindow
- self._focus: Atspi.Accessible | None = cthulhu_state.locusOfFocus
- self._object_of_interest: Atspi.Accessible | None = cthulhu_state.objOfInterest
- self._active_mode: str | None = cthulhu_state.activeMode
+ self._window: Optional[Atspi.Accessible] = cthulhu_state.activeWindow
+ self._focus: Optional[Atspi.Accessible] = cthulhu_state.locusOfFocus
+ self._object_of_interest: Optional[Atspi.Accessible] = cthulhu_state.objOfInterest
+ self._active_mode: Optional[str] = cthulhu_state.activeMode
self._last_cell_coordinates: tuple[int, int] = (-1, -1)
- self._last_cursor_position: tuple[Atspi.Accessible | None, int] = (None, -1)
- self._penultimate_cursor_position: tuple[Atspi.Accessible | None, int] = (None, -1)
+ self._last_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
+ self._penultimate_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
msg = "FOCUS MANAGER: Registering D-Bus commands."
debug.print_message(debug.LEVEL_INFO, msg, True)
@@ -104,7 +104,7 @@ class FocusManager:
cthulhu_state.objOfInterest = None
cthulhu_state.activeMode = None
- def find_focused_object(self) -> Atspi.Accessible | None:
+ def find_focused_object(self) -> Optional[Atspi.Accessible]:
"""Returns the focused object in the active window."""
result = _get_ax_utilities().get_focused_object(self._window)
@@ -147,9 +147,9 @@ class FocusManager:
def emit_region_changed(
self, obj: Atspi.Accessible,
- start_offset: int | None = None,
- end_offset: int | None = None,
- mode: str | None = None
+ start_offset: Optional[int] = None,
+ end_offset: Optional[int] = None,
+ mode: Optional[str] = None
) -> None:
"""Notifies interested clients that the current region of interest has changed."""
@@ -192,7 +192,7 @@ class FocusManager:
def get_active_mode_and_object_of_interest(
self
- ) -> tuple[str | None, Atspi.Accessible | None]:
+ ) -> tuple[Optional[str], Optional[Atspi.Accessible]]:
"""Returns the current mode and associated object of interest"""
tokens = ["FOCUS MANAGER: Active mode:", self._active_mode,
@@ -200,7 +200,7 @@ class FocusManager:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return self._active_mode, self._object_of_interest
- def get_penultimate_cursor_position(self) -> tuple[Atspi.Accessible | None, int]:
+ def get_penultimate_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
"""Returns the penultimate cursor position as a tuple of (object, offset)."""
obj, offset = self._penultimate_cursor_position
@@ -208,7 +208,7 @@ class FocusManager:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return obj, offset
- def get_last_cursor_position(self) -> tuple[Atspi.Accessible | None, int]:
+ def get_last_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
"""Returns the last cursor position as a tuple of (object, offset)."""
obj, offset = self._last_cursor_position
@@ -216,7 +216,7 @@ class FocusManager:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return obj, offset
- def set_last_cursor_position(self, obj: Atspi.Accessible | None, offset: int) -> None:
+ def set_last_cursor_position(self, obj: Optional[Atspi.Accessible], offset: int) -> None:
"""Sets the last cursor position as a tuple of (object, offset)."""
tokens = ["FOCUS MANAGER: Setting last cursor position to", obj, offset]
@@ -239,7 +239,7 @@ class FocusManager:
debug.print_message(debug.LEVEL_INFO, msg, True)
self._last_cell_coordinates = row, column
- def get_locus_of_focus(self) -> Atspi.Accessible | None:
+ def get_locus_of_focus(self) -> Optional[Atspi.Accessible]:
"""Returns the current locus of focus (i.e. the object with visual focus)."""
tokens = ["FOCUS MANAGER: Locus of focus is", self._focus]
@@ -248,8 +248,8 @@ class FocusManager:
def set_locus_of_focus(
self,
- event: Atspi.Event | None,
- obj: Atspi.Accessible | None,
+ event: Optional[Atspi.Event],
+ obj: Optional[Atspi.Accessible],
notify_script: bool = True,
force: bool = False
) -> None:
@@ -340,7 +340,7 @@ class FocusManager:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return is_active
- def get_active_window(self) -> Atspi.Accessible | None:
+ def get_active_window(self) -> Optional[Atspi.Accessible]:
"""Returns the currently-active window (i.e. without searching or verifying)."""
tokens = ["FOCUS MANAGER: Active window is", self._window]
@@ -349,8 +349,8 @@ class FocusManager:
def set_active_window(
self,
- frame: Atspi.Accessible | None,
- app: Atspi.Accessible | None = None,
+ frame: Optional[Atspi.Accessible],
+ app: Optional[Atspi.Accessible] = None,
set_window_as_focus: bool = False,
notify_script: bool = False
) -> None:
@@ -390,7 +390,7 @@ class FocusManager:
def toggle_presentation_mode(
self,
script: default.Script,
- event: InputEvent | None = None,
+ event: Optional[InputEvent] = None,
notify_user: bool = True
) -> bool:
"""Switches between browse mode and focus mode (web content only)."""
@@ -401,7 +401,7 @@ class FocusManager:
def toggle_layout_mode(
self,
script: default.Script,
- event: InputEvent | None = None,
+ event: Optional[InputEvent] = None,
notify_user: bool = True
) -> bool:
"""Switches between object mode and layout mode for line presentation (web content only)."""
@@ -412,7 +412,7 @@ class FocusManager:
def enable_sticky_browse_mode(
self,
script: default.Script,
- event: InputEvent | None = None,
+ event: Optional[InputEvent] = None,
notify_user: bool = True
) -> bool:
"""Enables sticky browse mode (web content only)."""
@@ -423,7 +423,7 @@ class FocusManager:
def enable_sticky_focus_mode(
self,
script: default.Script,
- event: InputEvent | None = None,
+ event: Optional[InputEvent] = None,
notify_user: bool = True
) -> bool:
"""Enables sticky focus mode (web content only)."""
diff --git a/src/cthulhu/input_event_manager.py b/src/cthulhu/input_event_manager.py
index 6d02cce..0b21d2c 100644
--- a/src/cthulhu/input_event_manager.py
+++ b/src/cthulhu/input_event_manager.py
@@ -39,7 +39,7 @@ __copyright__ = "Copyright (c) 2024 Igalia, S.L." \
"Copyright (c) 2024 GNOME Foundation Inc."
__license__ = "LGPL"
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
import gi
gi.require_version("Atspi", "2.0")
@@ -50,6 +50,7 @@ from . import focus_manager
from . import input_event
from . import script_manager
from . import settings
+from . import cthulhu_state
from .ax_object import AXObject
from .ax_utilities import AXUtilities
@@ -60,9 +61,9 @@ class InputEventManager:
"""Provides utilities for managing input events."""
def __init__(self) -> None:
- self._last_input_event: input_event.InputEvent | None = None
- self._last_non_modifier_key_event: input_event.KeyboardEvent | None = None
- self._device: Atspi.Device | None = None
+ self._last_input_event: Optional[input_event.InputEvent] = None
+ self._last_non_modifier_key_event: Optional[input_event.KeyboardEvent] = None
+ self._device: Optional[Atspi.Device] = None
self._mapped_keycodes: list[int] = []
self._mapped_keysyms: list[int] = []
self._grabbed_bindings: dict[int, keybindings.KeyBinding] = {}
@@ -267,6 +268,10 @@ class InputEventManager:
msg = "INPUT EVENT MANAGER: Keyboard event processing is paused."
debug.print_message(debug.LEVEL_INFO, msg, True)
return False
+ if cthulhu_state.capturingKeys:
+ msg = "INPUT EVENT MANAGER: Capturing keys; ignoring keyboard event."
+ debug.print_message(debug.LEVEL_INFO, msg, True)
+ return False
event = input_event.KeyboardEvent(pressed, keycode, keysym, modifiers, text)
if event in [self._last_input_event, self._last_non_modifier_key_event]:
diff --git a/src/cthulhu/notification_presenter.py b/src/cthulhu/notification_presenter.py
index b7ff978..af6e614 100644
--- a/src/cthulhu/notification_presenter.py
+++ b/src/cthulhu/notification_presenter.py
@@ -38,6 +38,8 @@ import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GObject
from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import Gdk
from . import cmdnames
from . import debug
@@ -275,16 +277,20 @@ class NotificationPresenter:
class NotificationListGUI:
"""The dialog containing the notifications list."""
+ RESPONSE_COPY = 1
+
def __init__(self, script, title, column_headers, rows):
self._script = script
self._model = None
+ self._tree = None
self._gui = self._create_dialog(title, column_headers, rows)
def _create_dialog(self, title, column_headers, rows):
dialog = Gtk.Dialog(title,
None,
Gtk.DialogFlags.MODAL,
- (Gtk.STOCK_CLEAR, Gtk.ResponseType.APPLY,
+ (Gtk.STOCK_COPY, self.RESPONSE_COPY,
+ Gtk.STOCK_CLEAR, Gtk.ResponseType.APPLY,
Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE))
dialog.set_default_size(600, 400)
@@ -315,6 +321,11 @@ class NotificationListGUI:
self._model.set_value(row_iter, i, cell)
tree.set_model(self._model)
+ selection = tree.get_selection()
+ selection.set_mode(Gtk.SelectionMode.SINGLE)
+ if self._model.iter_n_children(None) > 0:
+ selection.select_path(0)
+ self._tree = tree
dialog.connect("response", self.on_response)
return dialog
@@ -325,6 +336,10 @@ class NotificationListGUI:
self._gui.destroy()
return
+ if response == self.RESPONSE_COPY:
+ self._copy_selected_notification()
+ return
+
if response == Gtk.ResponseType.APPLY and self._model is not None:
self._model.clear()
getPresenter().clear_list()
@@ -336,10 +351,39 @@ class NotificationListGUI:
"""Shows the notifications list dialog."""
self._gui.show_all()
- time_stamp = cthulhu_state.lastInputEvent.timestamp
- if time_stamp == 0:
- time_stamp = Gtk.get_current_event_time()
- self._gui.present_with_time(time_stamp)
+ time_stamp = Gtk.get_current_event_time()
+ if not time_stamp or time_stamp > 0xFFFFFFFF:
+ time_stamp = Gdk.CURRENT_TIME
+ self._gui.present_with_time(int(time_stamp))
+
+ def _copy_selected_notification(self):
+ if self._model is None or self._tree is None:
+ return
+
+ selection = self._tree.get_selection()
+ model, paths = selection.get_selected_rows()
+ if not paths and self._model.iter_n_children(None) > 0:
+ selection.select_path(0)
+ model, paths = selection.get_selected_rows()
+
+ if not paths:
+ return
+
+ iter_for_path = model.get_iter(paths[0])
+ if iter_for_path is None:
+ return
+
+ message = model.get_value(iter_for_path, 0)
+ timestamp = model.get_value(iter_for_path, 1)
+ if timestamp:
+ text = f"{message}\t{timestamp}"
+ else:
+ text = f"{message}"
+
+ clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
+ clipboard.set_text(text, -1)
+ clipboard.store()
+ self._script.presentMessage(messages.CLIPBOARD_COPIED_FULL)
_presenter = None
def getPresenter():
diff --git a/src/cthulhu/plugin.py b/src/cthulhu/plugin.py
index 6f7f7fb..257d362 100644
--- a/src/cthulhu/plugin.py
+++ b/src/cthulhu/plugin.py
@@ -59,9 +59,9 @@ class Plugin:
self.plugin_info = plugin_info
if plugin_info:
self.module_name = getattr(plugin_info, 'module_name', '')
- self.name = getattr(plugin_info, 'name', '')
- self.version = getattr(plugin_info, 'version', '')
- self.description = getattr(plugin_info, 'description', '')
+ self.name = plugin_info.get_name()
+ self.version = plugin_info.get_version()
+ self.description = plugin_info.get_description()
@cthulhu_hookimpl
def activate(self, plugin=None):
diff --git a/src/cthulhu/plugin_system_manager.py b/src/cthulhu/plugin_system_manager.py
index e0feb65..c749054 100644
--- a/src/cthulhu/plugin_system_manager.py
+++ b/src/cthulhu/plugin_system_manager.py
@@ -12,6 +12,7 @@ import os
import inspect
import importlib.util
import logging
+import configparser
from enum import IntEnum
# Import pluggy if available
@@ -29,6 +30,12 @@ logger = logging.getLogger(__name__)
if PLUGIN_DEBUG:
logger.setLevel(logging.DEBUG)
+_manager = None
+
+def getManager():
+ """Return the shared PluginSystemManager instance."""
+ return _manager
+
class PluginType(IntEnum):
"""Types of plugins we support."""
SYSTEM = 1
@@ -78,8 +85,10 @@ class PluginSystemManager:
"""Cthulhu Plugin Manager using pluggy."""
def __init__(self, app):
+ global _manager
self.app = app
logger.info("Initializing PluginSystemManager")
+ _manager = self
# Initialize plugin manager
if PLUGGY_AVAILABLE:
@@ -378,15 +387,38 @@ class PluginSystemManager:
if os.path.isfile(metadata_file):
try:
- with open(metadata_file, 'r') as f:
- for line in f:
- line = line.strip()
- if not line or line.startswith('#'):
- continue
+ with open(metadata_file, 'r', encoding='utf-8') as f:
+ contents = f.read()
- if '=' in line:
- key, value = line.split('=', 1)
- metadata[key.strip()] = value.strip()
+ has_section_header = False
+ for line in contents.splitlines():
+ stripped = line.strip()
+ if not stripped or stripped.startswith('#') or stripped.startswith(';'):
+ continue
+ if stripped.startswith('[') and stripped.endswith(']'):
+ has_section_header = True
+ break
+
+ if has_section_header:
+ parser = configparser.ConfigParser()
+ try:
+ parser.read_string(contents)
+ if parser.sections():
+ for section in parser.sections():
+ for key, value in parser[section].items():
+ metadata[key.strip().lower()] = value.strip()
+ return metadata
+ except configparser.Error as e:
+ logger.warning(f"Plugin metadata INI parse failed for {metadata_file}: {e}")
+
+ for line in contents.splitlines():
+ line = line.strip()
+ if not line or line.startswith('#') or line.startswith(';') or line.startswith('['):
+ continue
+
+ if '=' in line:
+ key, value = line.split('=', 1)
+ metadata[key.strip().lower()] = value.strip()
except Exception as e:
logger.error(f"Error loading plugin metadata: {e}")
diff --git a/src/cthulhu/plugins/AIAssistant/ai_providers.py b/src/cthulhu/plugins/AIAssistant/ai_providers.py
index a6af653..9f0d67a 100644
--- a/src/cthulhu/plugins/AIAssistant/ai_providers.py
+++ b/src/cthulhu/plugins/AIAssistant/ai_providers.py
@@ -334,6 +334,172 @@ Keep descriptions informative and well-structured."""
return base_prompt
+class CodexProvider(AIProvider):
+ """Codex CLI provider - uses installed Codex CLI."""
+
+ def __init__(self, codex_path=None, **kwargs):
+ super().__init__(**kwargs)
+ self.codex_path = codex_path or self._resolve_codex_path()
+
+ def describe_screen(self, screenshot_data, accessibility_data):
+ """Generate a description using Codex CLI."""
+ try:
+ prompt = self._build_prompt("describe", None, accessibility_data)
+ return self._call_codex(prompt, screenshot_data)
+ except Exception as e:
+ logger.error(f"Codex describe error: {e}")
+ return f"Error getting screen description: {e}"
+
+ def answer_question(self, question, screenshot_data, accessibility_data):
+ """Answer a question using Codex CLI."""
+ try:
+ prompt = self._build_prompt("question", question, accessibility_data)
+ return self._call_codex(prompt, screenshot_data)
+ except Exception as e:
+ logger.error(f"Codex question error: {e}")
+ return f"Error answering question: {e}"
+
+ def suggest_actions(self, request, screenshot_data, accessibility_data):
+ """Suggest actions using Codex CLI."""
+ try:
+ prompt = self._build_prompt("action", request, accessibility_data)
+ return self._call_codex(prompt, screenshot_data)
+ except Exception as e:
+ logger.error(f"Codex action error: {e}")
+ return f"Error suggesting actions: {e}"
+
+ def analyze_images(self, user_question, screenshot_data, accessibility_data):
+ """Analyze images visible on screen using Codex CLI."""
+ try:
+ prompt = self._build_prompt("image", user_question, accessibility_data)
+ return self._call_codex(prompt, screenshot_data)
+ except Exception as e:
+ logger.error(f"Codex image analysis error: {e}")
+ return f"Error analyzing images: {e}"
+
+ def _build_prompt(self, task_type, user_input, accessibility_data):
+ """Build the complete prompt for Codex CLI."""
+ system_prompt = self._prepare_system_prompt(task_type)
+
+ if task_type == "image":
+ if user_input == "ANALYZE_SINGLE_IMAGE_FILE":
+ prompt = (
+ f"{system_prompt}\n\nAnalyze and describe the single image file provided. "
+ "Focus on visual content only - describe what you see in the image: objects, "
+ "people, scenery, colors, text, composition, and any other visual details."
+ )
+ else:
+ prompt = f"{system_prompt}\n\nCurrent screen context (focus on images):\n"
+ if user_input:
+ prompt += f"User question about images: {user_input}\n\n"
+ prompt += "Analyze and describe any images visible on this screen. Focus on visual content, not UI elements."
+ else:
+ prompt = (
+ f"{system_prompt}\n\nCurrent accessibility information:\n"
+ f"```json\n{json.dumps(accessibility_data, indent=2)}\n```\n\n"
+ )
+
+ if task_type == "describe":
+ prompt += "Please describe what's on this screen."
+ elif task_type == "question":
+ prompt += f"User question: {user_input}"
+ elif task_type == "action":
+ prompt += f"User wants to: {user_input}\n\nProvide the action analysis in the required format."
+
+ return prompt
+
+ def _resolve_codex_path(self):
+ import shutil
+ import os
+
+ codex_path = shutil.which('codex')
+ if not codex_path and os.path.isfile('/usr/bin/codex'):
+ codex_path = '/usr/bin/codex'
+ return codex_path
+
+ def _call_codex(self, prompt, screenshot_data):
+ """Call Codex CLI with the prompt and optional image."""
+ import subprocess
+ import tempfile
+ import os
+ import base64
+
+ if not self.codex_path:
+ return "Codex CLI not found"
+
+ output_path = None
+ image_path = None
+ try:
+ # Write screenshot to a temp file if available
+ if screenshot_data:
+ image_format = screenshot_data.get('format', 'png')
+ suffix = f".{image_format}"
+ with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
+ image_data = base64.b64decode(screenshot_data['data'])
+ temp_file.write(image_data)
+ image_path = temp_file.name
+
+ with tempfile.NamedTemporaryFile(delete=False) as output_file:
+ output_path = output_file.name
+
+ cmd = [
+ self.codex_path,
+ 'exec',
+ '--skip-git-repo-check',
+ '--color',
+ 'never',
+ '--output-last-message',
+ output_path,
+ '-'
+ ]
+
+ if image_path:
+ cmd.extend(['-i', image_path])
+
+ result = subprocess.run(
+ cmd,
+ input=prompt,
+ capture_output=True,
+ text=True,
+ timeout=120
+ )
+
+ if result.returncode != 0:
+ error_msg = result.stderr.strip() or result.stdout.strip() or "Codex CLI error"
+ logger.error(error_msg)
+ return f"Codex CLI error: {error_msg}"
+
+ response_text = ""
+ if output_path and os.path.exists(output_path):
+ with open(output_path, 'r') as f:
+ response_text = f.read().strip()
+
+ if not response_text:
+ response_text = result.stdout.strip()
+
+ return response_text or "No response from Codex"
+
+ except subprocess.TimeoutExpired:
+ error_msg = "Codex CLI timed out"
+ logger.error(error_msg)
+ return error_msg
+ except Exception as e:
+ error_msg = f"Error calling Codex CLI: {e}"
+ logger.error(error_msg)
+ return error_msg
+ finally:
+ if image_path and os.path.exists(image_path):
+ try:
+ os.unlink(image_path)
+ except Exception:
+ pass
+ if output_path and os.path.exists(output_path):
+ try:
+ os.unlink(output_path)
+ except Exception:
+ pass
+
+
class OllamaProvider(AIProvider):
"""Ollama local AI provider."""
@@ -563,9 +729,11 @@ def create_provider(provider_type, **kwargs):
"""Factory function to create AI providers."""
if provider_type == "claude_code":
return ClaudeCodeProvider(**kwargs)
+ elif provider_type == "codex":
+ return CodexProvider(**kwargs)
elif provider_type == "ollama":
return OllamaProvider(**kwargs)
elif provider_type == "gemini":
return GeminiProvider(**kwargs)
else:
- raise ValueError(f"Unknown provider type: {provider_type}")
\ No newline at end of file
+ raise ValueError(f"Unknown provider type: {provider_type}")
diff --git a/src/cthulhu/plugins/AIAssistant/plugin.py b/src/cthulhu/plugins/AIAssistant/plugin.py
index c2ea69a..6bc3a39 100644
--- a/src/cthulhu/plugins/AIAssistant/plugin.py
+++ b/src/cthulhu/plugins/AIAssistant/plugin.py
@@ -204,6 +204,11 @@ class AIAssistant(Plugin):
result = self._check_claude_code_availability()
logger.info(f"Claude Code availability check result: {result}")
return result
+ elif self._provider_type == settings.AI_PROVIDER_CODEX:
+ logger.info("Checking Codex CLI availability")
+ result = self._check_codex_availability()
+ logger.info(f"Codex CLI availability check result: {result}")
+ return result
elif self._provider_type == settings.AI_PROVIDER_GEMINI:
logger.info("Checking Gemini API key")
if not self._api_key:
@@ -258,12 +263,43 @@ class AIAssistant(Plugin):
except Exception as e:
logger.warning(f"Claude Code CLI not available: {e}")
return False
+
+ def _check_codex_availability(self):
+ """Check if Codex CLI is available."""
+ try:
+ import subprocess
+ import shutil
+
+ codex_path = shutil.which('codex')
+ if not codex_path and os.path.isfile('/usr/bin/codex'):
+ codex_path = '/usr/bin/codex'
+
+ if not codex_path:
+ logger.warning("Codex CLI not found in PATH")
+ return False
+
+ result = subprocess.run([codex_path, '--version'],
+ capture_output=True, text=True, timeout=5)
+ if result.returncode == 0:
+ logger.info("Codex CLI is available")
+ return True
+ else:
+ logger.warning(f"Codex CLI not responding: {result.stderr}")
+ return False
+ except subprocess.TimeoutExpired:
+ logger.warning("Codex CLI timeout")
+ return False
+ except Exception as e:
+ logger.warning(f"Codex CLI not available: {e}")
+ return False
def _initialize_ai_provider(self):
"""Initialize the AI provider based on settings."""
try:
if self._provider_type == settings.AI_PROVIDER_CLAUDE_CODE:
self._ai_provider = create_provider("claude_code")
+ elif self._provider_type == settings.AI_PROVIDER_CODEX:
+ self._ai_provider = create_provider("codex")
elif self._provider_type == settings.AI_PROVIDER_OLLAMA:
self._ai_provider = create_provider("ollama", model=self._ollama_model, base_url=self._ollama_endpoint)
elif self._provider_type == settings.AI_PROVIDER_GEMINI:
diff --git a/src/cthulhu/plugins/OCR/meson.build b/src/cthulhu/plugins/OCR/meson.build
index 09fe8ec..4dffac5 100644
--- a/src/cthulhu/plugins/OCR/meson.build
+++ b/src/cthulhu/plugins/OCR/meson.build
@@ -5,10 +5,10 @@ ocrdesktop_python_sources = files([
python3.install_sources(
ocrdesktop_python_sources,
- subdir: 'cthulhu/plugins/OCRDesktop'
+ subdir: 'cthulhu/plugins/OCR'
)
install_data(
'plugin.info',
- install_dir: python3.get_install_dir() / 'cthulhu' / 'plugins' / 'OCRDesktop'
-)
\ No newline at end of file
+ install_dir: python3.get_install_dir() / 'cthulhu' / 'plugins' / 'OCR'
+)
diff --git a/src/cthulhu/plugins/PluginManager/plugin.py b/src/cthulhu/plugins/PluginManager/plugin.py
index 78e4b24..493e172 100644
--- a/src/cthulhu/plugins/PluginManager/plugin.py
+++ b/src/cthulhu/plugins/PluginManager/plugin.py
@@ -223,7 +223,7 @@ class PluginManager(Plugin):
checkbox.connect("toggled", self._on_plugin_toggled, plugin_name)
# Create plugin info label
- info_text = f"{plugin_name}"
+ info_text = f"{plugin_info.get('name', plugin_name)}"
if plugin_info.get('description'):
info_text += f"\n{plugin_info['description']}"
if plugin_info.get('version'):
@@ -257,17 +257,17 @@ class PluginManager(Plugin):
from cthulhu import plugin_system_manager
# Use existing plugin manager to get plugins
- if hasattr(plugin_system_manager, '_manager') and plugin_system_manager._manager:
- manager = plugin_system_manager._manager
+ manager = plugin_system_manager.getManager()
+ if manager:
manager.rescanPlugins()
for plugin_info in manager.plugins:
plugin_name = plugin_info.get_module_name()
plugins[plugin_name] = {
- 'name': plugin_name,
- 'description': getattr(plugin_info, 'description', ''),
- 'version': getattr(plugin_info, 'version', ''),
- 'path': getattr(plugin_info, 'module_dir', '')
+ 'name': plugin_info.get_name(),
+ 'description': plugin_info.get_description(),
+ 'version': plugin_info.get_version(),
+ 'path': plugin_info.get_module_dir()
}
else:
# Fallback: manually scan plugin directories
diff --git a/src/cthulhu/settings.py b/src/cthulhu/settings.py
index 5c7d32b..ab18cb4 100644
--- a/src/cthulhu/settings.py
+++ b/src/cthulhu/settings.py
@@ -210,6 +210,7 @@ CHAT_SPEAK_FOCUSED_CHANNEL = 2
# AI Assistant constants - simplified to providers that don't need complex API key management
AI_PROVIDER_CLAUDE_CODE = "claude_code"
+AI_PROVIDER_CODEX = "codex"
AI_PROVIDER_GEMINI = "gemini"
AI_PROVIDER_OLLAMA = "ollama"
diff --git a/src/cthulhu/speech_history.py b/src/cthulhu/speech_history.py
index 37bf756..cf54dcd 100644
--- a/src/cthulhu/speech_history.py
+++ b/src/cthulhu/speech_history.py
@@ -17,6 +17,7 @@ falls off the end, it may be added again later.
from __future__ import annotations
+from typing import Optional
import threading
from collections import deque
@@ -76,7 +77,7 @@ def is_capture_paused() -> bool:
return _pauseCount > 0
-def add(text: str | None, source: str = "") -> bool:
+def add(text: Optional[str], source: str = "") -> bool:
"""Add text to speech history if it's not already present.
Returns True if the item was added; False otherwise.
@@ -141,7 +142,7 @@ def get_items() -> list[str]:
return list(_historyItems)
-def remove(text: str | None) -> bool:
+def remove(text: Optional[str]) -> bool:
"""Remove an item from the history (if present)."""
if text is None:
return False