From fcb5910c26b5079b3c8fd5b64c715fd615953859 Mon Sep 17 00:00:00 2001
From: JeffreyChen
Date: Thu, 25 Jun 2026 11:30:10 +0800
Subject: [PATCH] Clear SonarCloud and Codacy static-analysis backlog
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolve the open SonarCloud (193) and Codacy (3) findings:
- S1172 (141): accessibility backend ABC default methods now pass their
args through to _unsupported(*context), so the explicit signatures
required for fake-backend overrides (W0221) are kept without unused
parameters.
- S1192 (13): extract duplicated literals to module constants
(command_schema "Native UI" x67, placeholders, ".approvals", flow_editor
submodule paths).
- Code smells: merge nested if (http_cassette), flatten nested ternaries
(assertions, color_match), drop redundant FileNotFoundError (notifier),
prune expired leases after iteration instead of list() copy
(credential_broker), extract _signal_parts to cut cognitive complexity
(element_scoring), unused locals -> _ (form_fields), valid NOSONAR
syntax (stats), keep timeout param for 3.10 (webrtc_transport).
- Security S8707 (4): justify the CLI/operator-supplied paths
(config_bundle, turn_config, host_service, stubs) — not a remote
trust boundary.
- Tests: rename Image->pil_image, dict()->literal, comprehension->list(),
drop gratuitous truthiness, reword code-like comments, guard the empty
block, def instead of identity-check lambda, boto3 API names justified.
- Frontend: self->globalThis (sw.js), aria-labels on inputs, valid
NOSONAR on the non-module top-level-await line.
- Codacy: guard QApplication create (W0106), nosemgrep on the protocol
SHA-1 handshake and the local-CLI subprocess test.
---
je_auto_control/gui/flow_editor/__init__.py | 10 +-
.../gui/script_builder/command_schema.py | 218 +++++++++---------
.../utils/accessibility/backends/base.py | 68 +++---
je_auto_control/utils/assertion/assertions.py | 3 +-
.../utils/color_match/color_match.py | 6 +-
.../utils/config_bundle/__main__.py | 3 +-
.../utils/element_scoring/element_scoring.py | 33 ++-
.../utils/executor/action_executor.py | 7 +-
.../utils/form_fields/form_fields.py | 4 +-
.../utils/governance/credential_broker.py | 7 +-
.../utils/http_cassette/http_cassette.py | 12 +-
.../utils/mcp_server/tools/_handlers.py | 8 +-
je_auto_control/utils/notify/notifier.py | 2 +-
.../utils/remote_desktop/host_service.py | 3 +-
.../utils/remote_desktop/turn_config.py | 3 +-
.../remote_desktop/web_viewer/index.html | 6 +-
.../utils/remote_desktop/web_viewer/sw.js | 6 +-
.../utils/remote_desktop/webrtc_transport.py | 8 +-
.../utils/rest_api/dashboard/swagger.html | 2 +-
je_auto_control/utils/stats/stats.py | 8 +-
je_auto_control/utils/stubs/generator.py | 3 +-
.../headless/test_action_effect_batch.py | 2 +-
.../headless/test_canonical_log_batch.py | 1 +
.../headless/test_coordinate_space_batch.py | 6 +-
.../headless/test_critic_features_batch.py | 2 +-
.../headless/test_decision_table_batch.py | 4 +-
test/unit_test/headless/test_diagnostics.py | 2 +-
test/unit_test/headless/test_dotenv_batch.py | 2 +-
.../headless/test_image_dedup_batch.py | 14 +-
.../headless/test_link_header_batch.py | 2 +-
.../headless/test_remote_desktop_cursor.py | 3 +-
.../headless/test_remote_desktop_websocket.py | 2 +-
.../unit_test/headless/test_s3_store_batch.py | 4 +-
.../headless/test_schema_compat_batch.py | 2 +-
.../headless/test_timeseries_batch.py | 2 +-
.../unit_test/headless/test_window_capture.py | 8 +-
36 files changed, 257 insertions(+), 219 deletions(-)
diff --git a/je_auto_control/gui/flow_editor/__init__.py b/je_auto_control/gui/flow_editor/__init__.py
index 46560537..3a8fce49 100644
--- a/je_auto_control/gui/flow_editor/__init__.py
+++ b/je_auto_control/gui/flow_editor/__init__.py
@@ -17,11 +17,13 @@
FlowEdge, FlowLayout, FlowNodePosition, layout_steps,
)
+_SCENE_MODULE = "je_auto_control.gui.flow_editor.scene"
+_TAB_MODULE = "je_auto_control.gui.flow_editor.tab"
_LAZY_SUBMODULES = {
- "FlowEdgeItem": "je_auto_control.gui.flow_editor.scene",
- "FlowGraphScene": "je_auto_control.gui.flow_editor.scene",
- "FlowNodeItem": "je_auto_control.gui.flow_editor.scene",
- "FlowEditorTab": "je_auto_control.gui.flow_editor.tab",
+ "FlowEdgeItem": _SCENE_MODULE,
+ "FlowGraphScene": _SCENE_MODULE,
+ "FlowNodeItem": _SCENE_MODULE,
+ "FlowEditorTab": _TAB_MODULE,
}
diff --git a/je_auto_control/gui/script_builder/command_schema.py b/je_auto_control/gui/script_builder/command_schema.py
index ba1809b2..3c8c93fd 100644
--- a/je_auto_control/gui/script_builder/command_schema.py
+++ b/je_auto_control/gui/script_builder/command_schema.py
@@ -45,6 +45,16 @@ class CommandSpec:
_MOUSE_BUTTONS = ("mouse_left", "mouse_right", "mouse_middle")
_REGION_PLACEHOLDER = "[left, top, right, bottom]"
+_NATIVE_UI = "Native UI"
+_SCALES_PLACEHOLDER = "[0.9, 1.0, 1.1]"
+_POINT_PLACEHOLDER = "[10, 20]"
+_RECT_PLACEHOLDER = "[x, y, width, height]"
+_RECT4_PLACEHOLDER = "[x, y, w, h]"
+_APPROVALS_DIR = ".approvals"
+_DOTTED_KEY_PLACEHOLDER = "db.host"
+_POINTS_JSON_PLACEHOLDER = '[{"x":..,"y":..,"width":..,"height":..}]'
+_MARKS_JSON_PLACEHOLDER = '[{"role":"button","name":"OK","x":..,"y":..}]'
+_BOXES_JSON_PLACEHOLDER = '[{"role":"button","x":0,"y":0}]'
def _build_specs() -> List[CommandSpec]:
@@ -261,7 +271,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
FieldSpec("min_score", FieldType.FLOAT, optional=True, default=0.8,
min_value=0.0, max_value=1.0),
FieldSpec("scales", FieldType.STRING, optional=True,
- placeholder="[0.9, 1.0, 1.1]"),
+ placeholder=_SCALES_PLACEHOLDER),
FieldSpec("region", FieldType.STRING, optional=True,
placeholder=_REGION_PLACEHOLDER),
),
@@ -313,7 +323,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
FieldSpec("angles", FieldType.STRING, optional=True,
placeholder="[-10, 0, 10]"),
FieldSpec("scales", FieldType.STRING, optional=True,
- placeholder="[0.9, 1.0, 1.1]"),
+ placeholder=_SCALES_PLACEHOLDER),
FieldSpec("region", FieldType.STRING, optional=True,
placeholder=_REGION_PLACEHOLDER),
),
@@ -328,7 +338,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
FieldSpec("angles", FieldType.STRING, optional=True,
placeholder="[-10, 0, 10]"),
FieldSpec("scales", FieldType.STRING, optional=True,
- placeholder="[0.9, 1.0, 1.1]"),
+ placeholder=_SCALES_PLACEHOLDER),
FieldSpec("max_results", FieldType.INT, optional=True, default=20),
FieldSpec("nms_iou", FieldType.FLOAT, optional=True, default=0.3,
min_value=0.0, max_value=1.0),
@@ -344,7 +354,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
FieldSpec("ambiguous_ratio", FieldType.FLOAT, optional=True,
default=0.9, min_value=0.0, max_value=1.0),
FieldSpec("scales", FieldType.STRING, optional=True,
- placeholder="[0.9, 1.0, 1.1]"),
+ placeholder=_SCALES_PLACEHOLDER),
FieldSpec("region", FieldType.STRING, optional=True,
placeholder=_REGION_PLACEHOLDER),
),
@@ -378,7 +388,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
FieldSpec("min_score", FieldType.FLOAT, optional=True, default=0.7,
min_value=0.0, max_value=1.0),
FieldSpec("scales", FieldType.STRING, optional=True,
- placeholder="[0.9, 1.0, 1.1]"),
+ placeholder=_SCALES_PLACEHOLDER),
FieldSpec("region", FieldType.STRING, optional=True,
placeholder=_REGION_PLACEHOLDER),
),
@@ -684,7 +694,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
"AC_fuse_elements", "Image", "Fuse Element Boxes",
fields=(
FieldSpec("ocr", FieldType.STRING, optional=True,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("icon", FieldType.STRING, optional=True),
FieldSpec("a11y", FieldType.STRING, optional=True),
FieldSpec("iou_threshold", FieldType.FLOAT, optional=True, default=0.9,
@@ -696,7 +706,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
"AC_reading_order", "Image", "Reading Order",
fields=(
FieldSpec("elements", FieldType.STRING,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("row_tol", FieldType.INT, optional=True, default=12),
),
description="Order element boxes top-to-bottom, left-to-right (+ index).",
@@ -705,7 +715,7 @@ def _add_image_specs(specs: List[CommandSpec]) -> None:
"AC_locate_chain", "Image", "Locate Chain (refine boxes)",
fields=(
FieldSpec("boxes", FieldType.STRING,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("ops", FieldType.STRING,
placeholder='[{"op":"filter","has_text":"OK"},{"op":"first"}]'),
),
@@ -1062,7 +1072,7 @@ def _add_window_specs(specs: List[CommandSpec]) -> None:
FieldSpec("paths", FieldType.STRING,
placeholder='["C:\\\\a\\\\one.txt"]'),
FieldSpec("point", FieldType.STRING, optional=True,
- placeholder="[10, 20]"),
+ placeholder=_POINT_PLACEHOLDER),
),
description="Drop files onto a window via WM_DROPFILES (Windows).",
))
@@ -1072,7 +1082,7 @@ def _add_window_specs(specs: List[CommandSpec]) -> None:
FieldSpec("paths", FieldType.STRING,
placeholder='["C:\\\\a\\\\one.txt"]'),
FieldSpec("point", FieldType.STRING, optional=True,
- placeholder="[10, 20]"),
+ placeholder=_POINT_PLACEHOLDER),
),
description="Build the WM_DROPFILES payload without sending (pure).",
))
@@ -1220,7 +1230,7 @@ def _add_window_specs(specs: List[CommandSpec]) -> None:
"bottom_right", "center", "left_third",
"center_third", "right_third"), default="left"),
FieldSpec("screen", FieldType.STRING, optional=True,
- placeholder="[x, y, width, height]"),
+ placeholder=_RECT_PLACEHOLDER),
FieldSpec("gap", FieldType.INT, optional=True, default=0),
),
description="Compute the rectangle for a tiling slot of the screen.",
@@ -1231,7 +1241,7 @@ def _add_window_specs(specs: List[CommandSpec]) -> None:
FieldSpec("rows", FieldType.INT, default=2),
FieldSpec("cols", FieldType.INT, default=2),
FieldSpec("screen", FieldType.STRING, optional=True,
- placeholder="[x, y, width, height]"),
+ placeholder=_RECT_PLACEHOLDER),
FieldSpec("gap", FieldType.INT, optional=True, default=0),
),
description="Compute the cell rectangles of an R×C screen grid.",
@@ -1241,7 +1251,7 @@ def _add_window_specs(specs: List[CommandSpec]) -> None:
fields=(
FieldSpec("count", FieldType.INT, default=3),
FieldSpec("screen", FieldType.STRING, optional=True,
- placeholder="[x, y, width, height]"),
+ placeholder=_RECT_PLACEHOLDER),
FieldSpec("offset", FieldType.INT, optional=True, default=30),
FieldSpec("size", FieldType.STRING, optional=True,
placeholder="[width, height]"),
@@ -1549,67 +1559,67 @@ def _add_native_control_specs(specs: List[CommandSpec]) -> None:
FieldSpec("automation_id", FieldType.STRING, optional=True),
)
specs.append(CommandSpec(
- "AC_control_get_value", "Native UI", "Get Control Value",
+ "AC_control_get_value", _NATIVE_UI, "Get Control Value",
fields=fields,
description="Read a native control's value via the accessibility API.",
))
specs.append(CommandSpec(
- "AC_control_set_value", "Native UI", "Set Control Value",
+ "AC_control_set_value", _NATIVE_UI, "Set Control Value",
fields=(FieldSpec("value", FieldType.STRING),) + fields,
description="Set a native control's value directly (no per-key typing).",
))
specs.append(CommandSpec(
- "AC_control_invoke", "Native UI", "Invoke Control",
+ "AC_control_invoke", _NATIVE_UI, "Invoke Control",
fields=fields,
description="Invoke a native control (e.g. press a button).",
))
specs.append(CommandSpec(
- "AC_control_toggle", "Native UI", "Toggle Control",
+ "AC_control_toggle", _NATIVE_UI, "Toggle Control",
fields=fields,
description="Toggle a native control (e.g. a checkbox).",
))
specs.append(CommandSpec(
- "AC_read_table", "Native UI", "Read Table / Grid",
+ "AC_read_table", _NATIVE_UI, "Read Table / Grid",
fields=fields,
description="Read a grid/table/list control as rows of cell strings.",
))
specs.append(CommandSpec(
- "AC_expand_control", "Native UI", "Expand Control",
+ "AC_expand_control", _NATIVE_UI, "Expand Control",
fields=fields,
description="Expand a tree node / combobox (ExpandCollapsePattern).",
))
specs.append(CommandSpec(
- "AC_collapse_control", "Native UI", "Collapse Control",
+ "AC_collapse_control", _NATIVE_UI, "Collapse Control",
fields=fields,
description="Collapse a tree node / combobox (ExpandCollapsePattern).",
))
specs.append(CommandSpec(
- "AC_control_expand_state", "Native UI", "Control Expand State",
+ "AC_control_expand_state", _NATIVE_UI, "Control Expand State",
fields=fields,
description="Read expanded/collapsed/partial/leaf state of a control.",
))
specs.append(CommandSpec(
- "AC_select_control_item", "Native UI", "Select Control Item",
+ "AC_select_control_item", _NATIVE_UI, "Select Control Item",
fields=fields,
description="Select a list / tree / tab item (SelectionItemPattern).",
))
specs.append(CommandSpec(
- "AC_control_range", "Native UI", "Get Control Range",
+ "AC_control_range", _NATIVE_UI, "Get Control Range",
fields=fields,
description="Read a slider / progress range (RangeValuePattern).",
))
specs.append(CommandSpec(
- "AC_set_control_range", "Native UI", "Set Control Range",
+ "AC_set_control_range", _NATIVE_UI, "Set Control Range",
fields=(FieldSpec("value", FieldType.FLOAT),) + fields,
description="Set a slider / progress / spinner value (RangeValuePattern).",
))
specs.append(CommandSpec(
- "AC_scroll_control_into_view", "Native UI", "Scroll Control Into View",
+ "AC_scroll_control_into_view", _NATIVE_UI, "Scroll Control Into View",
fields=fields,
description="Scroll a control into view (ScrollItemPattern).",
))
specs.append(CommandSpec(
- "AC_realize_item", "Native UI", "Realize Virtualized Item",
+ "AC_realize_item", _NATIVE_UI, "Realize Virtualized Item",
fields=(
FieldSpec("item_name", FieldType.STRING),
FieldSpec("by", FieldType.ENUM, optional=True, default="name",
@@ -1622,124 +1632,124 @@ def _add_native_control_specs(specs: List[CommandSpec]) -> None:
description="Realize an off-screen item in a virtualized list/grid.",
))
specs.append(CommandSpec(
- "AC_get_element_properties", "Native UI", "Get Element Properties",
+ "AC_get_element_properties", _NATIVE_UI, "Get Element Properties",
fields=fields,
description="Read rich UIA props (enabled/offscreen/help/status/keys).",
))
specs.append(CommandSpec(
- "AC_table_headers", "Native UI", "Get Table Headers",
+ "AC_table_headers", _NATIVE_UI, "Get Table Headers",
fields=fields,
description="Read a table's row/column header labels (TablePattern).",
))
specs.append(CommandSpec(
- "AC_table_cell", "Native UI", "Get Table Cell (by index)",
+ "AC_table_cell", _NATIVE_UI, "Get Table Cell (by index)",
fields=(FieldSpec("row", FieldType.INT),
FieldSpec("column", FieldType.INT)) + fields,
description="Read the cell at (row, column) with its span.",
))
specs.append(CommandSpec(
- "AC_cell_by_header", "Native UI", "Get Table Cell (by header)",
+ "AC_cell_by_header", _NATIVE_UI, "Get Table Cell (by header)",
fields=(FieldSpec("row", FieldType.INT),
FieldSpec("column_header", FieldType.STRING)) + fields,
description="Read the cell at (row, named column) — assert by header.",
))
specs.append(CommandSpec(
- "AC_move_element", "Native UI", "Move Element (Transform)",
+ "AC_move_element", _NATIVE_UI, "Move Element (Transform)",
fields=(FieldSpec("x", FieldType.FLOAT),
FieldSpec("y", FieldType.FLOAT)) + fields,
description="Move a UIA element to (x, y) (TransformPattern).",
))
specs.append(CommandSpec(
- "AC_resize_element", "Native UI", "Resize Element (Transform)",
+ "AC_resize_element", _NATIVE_UI, "Resize Element (Transform)",
fields=(FieldSpec("width", FieldType.FLOAT),
FieldSpec("height", FieldType.FLOAT)) + fields,
description="Resize a UIA element (TransformPattern).",
))
specs.append(CommandSpec(
- "AC_set_window_state", "Native UI", "Set Window State",
+ "AC_set_window_state", _NATIVE_UI, "Set Window State",
fields=(FieldSpec("state", FieldType.ENUM, default="normal",
choices=("normal", "maximized", "minimized")),) + fields,
description="Minimize / maximize / restore a window (WindowPattern).",
))
specs.append(CommandSpec(
- "AC_window_interaction_state", "Native UI", "Window Interaction State",
+ "AC_window_interaction_state", _NATIVE_UI, "Window Interaction State",
fields=fields,
description="Read window readiness (ready/blocked_by_modal/...).",
))
specs.append(CommandSpec(
- "AC_legacy_info", "Native UI", "Legacy (MSAA) Info",
+ "AC_legacy_info", _NATIVE_UI, "Legacy (MSAA) Info",
fields=fields,
description="Read an old control's MSAA info (LegacyIAccessible).",
))
specs.append(CommandSpec(
- "AC_legacy_default_action", "Native UI", "Legacy (MSAA) Default Action",
+ "AC_legacy_default_action", _NATIVE_UI, "Legacy (MSAA) Default Action",
fields=fields,
description="Fire an old control's MSAA default action (fallback).",
))
specs.append(CommandSpec(
- "AC_get_selection", "Native UI", "Get Container Selection",
+ "AC_get_selection", _NATIVE_UI, "Get Container Selection",
fields=fields,
description="Read a container's selection (SelectionPattern).",
))
specs.append(CommandSpec(
- "AC_list_views", "Native UI", "List Control Views",
+ "AC_list_views", _NATIVE_UI, "List Control Views",
fields=fields,
description="List a control's selectable views (MultipleViewPattern).",
))
specs.append(CommandSpec(
- "AC_set_view", "Native UI", "Set Control View",
+ "AC_set_view", _NATIVE_UI, "Set Control View",
fields=(FieldSpec("view", FieldType.STRING),) + fields,
description="Switch a control to the named view (MultipleViewPattern).",
))
specs.append(CommandSpec(
- "AC_wait_for_focus_change", "Native UI", "Wait for Focus Change",
+ "AC_wait_for_focus_change", _NATIVE_UI, "Wait for Focus Change",
fields=(FieldSpec("timeout", FieldType.FLOAT, optional=True,
default=5.0),),
description="Block until keyboard focus moves (real UIA focus event).",
))
specs.append(CommandSpec(
- "AC_get_control_text", "Native UI", "Get Control Text",
+ "AC_get_control_text", _NATIVE_UI, "Get Control Text",
fields=fields,
description="Read full text via TextPattern (multiline / document safe).",
))
specs.append(CommandSpec(
- "AC_find_control_text", "Native UI", "Find Text in Control",
+ "AC_find_control_text", _NATIVE_UI, "Find Text in Control",
fields=(FieldSpec("text", FieldType.STRING),
FieldSpec("ignore_case", FieldType.BOOL, optional=True,
default=True)) + fields,
description="Whether text occurs in a control (TextPattern.FindText).",
))
specs.append(CommandSpec(
- "AC_select_control_text", "Native UI", "Select Text in Control",
+ "AC_select_control_text", _NATIVE_UI, "Select Text in Control",
fields=(FieldSpec("text", FieldType.STRING),
FieldSpec("ignore_case", FieldType.BOOL, optional=True,
default=True)) + fields,
description="Find + select text in a control (FindText + Select).",
))
specs.append(CommandSpec(
- "AC_control_text_attributes", "Native UI", "Get Text Attributes",
+ "AC_control_text_attributes", _NATIVE_UI, "Get Text Attributes",
fields=fields,
description="Read selection formatting (font/size/bold/italic/colour).",
))
specs.append(CommandSpec(
- "AC_get_selected_text", "Native UI", "Get Selected Text",
+ "AC_get_selected_text", _NATIVE_UI, "Get Selected Text",
fields=fields,
description="Read the currently selected text via TextPattern.",
))
specs.append(CommandSpec(
- "AC_get_visible_text", "Native UI", "Get Visible Text",
+ "AC_get_visible_text", _NATIVE_UI, "Get Visible Text",
fields=fields,
description="Read only the on-screen text via TextPattern.GetVisibleRanges.",
))
specs.append(CommandSpec(
- "AC_walk_tree", "Native UI", "Walk Accessibility Tree",
+ "AC_walk_tree", _NATIVE_UI, "Walk Accessibility Tree",
fields=(FieldSpec("app_name", FieldType.STRING, optional=True),
FieldSpec("max_results", FieldType.INT, optional=True,
default=500)),
description="Dump the a11y tree with friendly roles + a path per node.",
))
specs.append(CommandSpec(
- "AC_humanize_role", "Native UI", "Humanize UIA Role",
+ "AC_humanize_role", _NATIVE_UI, "Humanize UIA Role",
fields=(FieldSpec("role", FieldType.STRING),),
description="Translate a raw UIA role (ControlType_50000) to a name.",
))
@@ -1747,17 +1757,17 @@ def _add_native_control_specs(specs: List[CommandSpec]) -> None:
FieldSpec("max_results", FieldType.INT, optional=True,
default=500))
specs.append(CommandSpec(
- "AC_tab_order", "Native UI", "Keyboard Tab Order",
+ "AC_tab_order", _NATIVE_UI, "Keyboard Tab Order",
fields=tree_fields,
description="List focusable controls in keyboard Tab (reading) order.",
))
specs.append(CommandSpec(
- "AC_audit_focus_order", "Native UI", "Audit Focus Order (WCAG)",
+ "AC_audit_focus_order", _NATIVE_UI, "Audit Focus Order (WCAG)",
fields=tree_fields,
description="WCAG 2.4.x focus-order audit: tab sequence + flagged issues.",
))
specs.append(CommandSpec(
- "AC_focus_control", "Native UI", "Set Keyboard Focus",
+ "AC_focus_control", _NATIVE_UI, "Set Keyboard Focus",
fields=fields,
description="Set keyboard focus on a control natively (UIA SetFocus).",
))
@@ -1862,7 +1872,7 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
description="Generate a TOTP 2FA code from a base32 secret.",
))
specs.append(CommandSpec(
- "AC_handle_file_dialog", "Native UI", "Handle File Dialog",
+ "AC_handle_file_dialog", _NATIVE_UI, "Handle File Dialog",
fields=(
FieldSpec("path", FieldType.STRING),
FieldSpec("action", FieldType.ENUM,
@@ -2055,7 +2065,7 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
FieldSpec("name", FieldType.STRING, placeholder="login_screen"),
FieldSpec("content", FieldType.STRING),
FieldSpec("approvals_dir", FieldType.STRING, optional=True,
- default=".approvals"),
+ default=_APPROVALS_DIR),
FieldSpec("extension", FieldType.STRING, optional=True,
default="txt"),
),
@@ -2066,7 +2076,7 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
fields=(
FieldSpec("name", FieldType.STRING),
FieldSpec("approvals_dir", FieldType.STRING, optional=True,
- default=".approvals"),
+ default=_APPROVALS_DIR),
FieldSpec("extension", FieldType.STRING, optional=True,
default="txt"),
),
@@ -2075,7 +2085,7 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
specs.append(CommandSpec(
"AC_pending_artifacts", "Testing", "Approval: List Pending",
fields=(FieldSpec("approvals_dir", FieldType.STRING, optional=True,
- default=".approvals"),),
+ default=_APPROVALS_DIR),),
description="List artifacts awaiting approval.",
))
specs.append(CommandSpec(
@@ -2730,7 +2740,7 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
FieldSpec("key", FieldType.STRING),
FieldSpec("method", FieldType.STRING, placeholder="vlm/image"),
FieldSpec("coordinates", FieldType.STRING, optional=True,
- placeholder="[10, 20]"),
+ placeholder=_POINT_PLACEHOLDER),
FieldSpec("description", FieldType.STRING, optional=True),
FieldSpec("confidence", FieldType.FLOAT, optional=True,
default=1.0),
@@ -3247,7 +3257,7 @@ def _add_resilience_specs(specs: List[CommandSpec]) -> None:
fields=(
FieldSpec("layers", FieldType.STRING,
placeholder='[{"name": "defaults", "mapping": {}}]'),
- FieldSpec("key", FieldType.STRING, placeholder="db.host"),
+ FieldSpec("key", FieldType.STRING, placeholder=_DOTTED_KEY_PLACEHOLDER),
),
description="Show the value and winning layer for a dotted config key.",
))
@@ -3375,7 +3385,7 @@ def _add_resilience_specs(specs: List[CommandSpec]) -> None:
"AC_cas_put", "Flow", "Optimistic: Put (CAS)",
fields=(
FieldSpec("name", FieldType.STRING, placeholder="config"),
- FieldSpec("key", FieldType.STRING, placeholder="db.host"),
+ FieldSpec("key", FieldType.STRING, placeholder=_DOTTED_KEY_PLACEHOLDER),
FieldSpec("value", FieldType.STRING, placeholder='"prod-1"'),
FieldSpec("expected_version", FieldType.INT, optional=True),
),
@@ -3385,7 +3395,7 @@ def _add_resilience_specs(specs: List[CommandSpec]) -> None:
"AC_cas_get", "Flow", "Optimistic: Get",
fields=(
FieldSpec("name", FieldType.STRING, placeholder="config"),
- FieldSpec("key", FieldType.STRING, placeholder="db.host"),
+ FieldSpec("key", FieldType.STRING, placeholder=_DOTTED_KEY_PLACEHOLDER),
),
description="Read a versioned record {value, version}.",
))
@@ -3621,21 +3631,21 @@ def _add_input_macro_specs(specs: List[CommandSpec]) -> None:
def _add_screen_state_specs(specs: List[CommandSpec]) -> None:
app = FieldSpec("app_name", FieldType.STRING, optional=True)
specs.append(CommandSpec(
- "AC_screen_snapshot", "Native UI", "Screen: Snapshot Baseline",
+ "AC_screen_snapshot", _NATIVE_UI, "Screen: Snapshot Baseline",
fields=(app,),
description="Snapshot the a11y tree as a semantic-diff baseline.",
))
specs.append(CommandSpec(
- "AC_screen_diff", "Native UI", "Screen: Diff Snapshots",
+ "AC_screen_diff", _NATIVE_UI, "Screen: Diff Snapshots",
description="Semantic diff of 'before'/'after' snapshots (JSON view).",
))
specs.append(CommandSpec(
- "AC_screen_changed", "Native UI", "Screen: What Changed",
+ "AC_screen_changed", _NATIVE_UI, "Screen: What Changed",
fields=(app,),
description="Diff the live screen against the last snapshot baseline.",
))
specs.append(CommandSpec(
- "AC_describe_screen", "Native UI", "Screen: Describe",
+ "AC_describe_screen", _NATIVE_UI, "Screen: Describe",
fields=(app,),
description="Structured 'where am I' (role counts + control labels).",
))
@@ -3643,7 +3653,7 @@ def _add_screen_state_specs(specs: List[CommandSpec]) -> None:
def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
specs.append(CommandSpec(
- "AC_cua_command", "Native UI", "Computer-Use: Map Action",
+ "AC_cua_command", _NATIVE_UI, "Computer-Use: Map Action",
fields=(
FieldSpec("payload", FieldType.STRING,
placeholder='{"action":"left_click","coordinate":[x,y]}'),
@@ -3653,43 +3663,43 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Map an Anthropic / OpenAI computer-use action to an AC command.",
))
specs.append(CommandSpec(
- "AC_serialize_observation", "Native UI", "Observation: Serialize Elements",
+ "AC_serialize_observation", _NATIVE_UI, "Observation: Serialize Elements",
fields=(
FieldSpec("elements", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("viewport", FieldType.STRING, optional=True,
- placeholder="[x, y, w, h]"),
+ placeholder=_RECT4_PLACEHOLDER),
FieldSpec("max_elements", FieldType.INT, optional=True, default=80),
),
description="Indexed text observation of UI elements for a VLM (act by index).",
))
specs.append(CommandSpec(
- "AC_observation_index", "Native UI", "Observation: Index Elements",
+ "AC_observation_index", _NATIVE_UI, "Observation: Index Elements",
fields=(
FieldSpec("elements", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("viewport", FieldType.STRING, optional=True,
- placeholder="[x, y, w, h]"),
+ placeholder=_RECT4_PLACEHOLDER),
FieldSpec("max_elements", FieldType.INT, optional=True, default=80),
),
description="Reading-ordered, viewport-clipped, indexed element list.",
))
specs.append(CommandSpec(
- "AC_delta_observation", "Native UI", "Observation: Delta (what changed)",
+ "AC_delta_observation", _NATIVE_UI, "Observation: Delta (what changed)",
fields=(
FieldSpec("prev", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("curr", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("viewport", FieldType.STRING, optional=True,
- placeholder="[x, y, w, h]"),
+ placeholder=_RECT4_PLACEHOLDER),
FieldSpec("max_elements", FieldType.INT, optional=True, default=80),
FieldSpec("max_lines", FieldType.INT, optional=True, default=40),
),
description="Token-budgeted '+/~/-' summary of what changed between frames.",
))
specs.append(CommandSpec(
- "AC_classify_effect", "Native UI", "Classify Action Effect",
+ "AC_classify_effect", _NATIVE_UI, "Classify Action Effect",
fields=(
FieldSpec("before", FieldType.STRING,
placeholder='[{"role":"button","name":"OK","x":0,"y":0}]'),
@@ -3702,19 +3712,19 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Did the action change the screen near its target? (no_op/…).",
))
specs.append(CommandSpec(
- "AC_effect_near_point", "Native UI", "Effect Near Point?",
+ "AC_effect_near_point", _NATIVE_UI, "Effect Near Point?",
fields=(
FieldSpec("before", FieldType.STRING,
- placeholder='[{"role":"button","x":0,"y":0}]'),
+ placeholder=_BOXES_JSON_PLACEHOLDER),
FieldSpec("after", FieldType.STRING,
- placeholder='[{"role":"button","x":0,"y":0}]'),
+ placeholder=_BOXES_JSON_PLACEHOLDER),
FieldSpec("point", FieldType.STRING, placeholder="[50, 50]"),
FieldSpec("radius", FieldType.INT, optional=True, default=64),
),
description="Did any before/after change land within radius of a point?",
))
specs.append(CommandSpec(
- "AC_check_postcondition", "Native UI", "Check Postcondition",
+ "AC_check_postcondition", _NATIVE_UI, "Check Postcondition",
fields=(
FieldSpec("after", FieldType.STRING,
placeholder='[{"role":"dialog","name":"Saved"}]'),
@@ -3727,7 +3737,7 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Check expected outcome clauses against after/before frames.",
))
specs.append(CommandSpec(
- "AC_plan_repair", "Native UI", "Plan Repair Tactics",
+ "AC_plan_repair", _NATIVE_UI, "Plan Repair Tactics",
fields=(
FieldSpec("verdict", FieldType.STRING,
placeholder="no_op / changed_elsewhere / changed"),
@@ -3736,7 +3746,7 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Ordered repair tactics for a failed/no-effect action verdict.",
))
specs.append(CommandSpec(
- "AC_consensus_point", "Native UI", "Grounding Consensus Point",
+ "AC_consensus_point", _NATIVE_UI, "Grounding Consensus Point",
fields=(
FieldSpec("candidates", FieldType.STRING,
placeholder="[[100, 100], [104, 98], [97, 103]]"),
@@ -3755,12 +3765,12 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Index where a churn series first settles (offline settle check).",
))
specs.append(CommandSpec(
- "AC_build_critic_record", "Native UI", "Build Critic Record",
+ "AC_build_critic_record", _NATIVE_UI, "Build Critic Record",
fields=(
FieldSpec("action", FieldType.STRING,
placeholder='{"type":"click","x":50,"y":50}'),
FieldSpec("before", FieldType.STRING,
- placeholder='[{"role":"button","x":0,"y":0}]'),
+ placeholder=_BOXES_JSON_PLACEHOLDER),
FieldSpec("after", FieldType.STRING,
placeholder='[{"role":"dialog","x":40,"y":40}]'),
FieldSpec("postcondition", FieldType.STRING, optional=True,
@@ -3770,7 +3780,7 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Per-step critic evidence (effect + delta + postcondition).",
))
specs.append(CommandSpec(
- "AC_score_step", "Native UI", "Score Step (rule-based)",
+ "AC_score_step", _NATIVE_UI, "Score Step (rule-based)",
fields=(
FieldSpec("record", FieldType.STRING,
placeholder='{"effect":{"effect":"changed_near_target"}}'),
@@ -3778,45 +3788,45 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Rule-based outcome + process score of a critic record.",
))
specs.append(CommandSpec(
- "AC_consensus_element", "Native UI", "Grounding Consensus Element",
+ "AC_consensus_element", _NATIVE_UI, "Grounding Consensus Element",
fields=(
FieldSpec("candidates", FieldType.STRING,
placeholder="[[8, 8], [12, 10]]"),
FieldSpec("elements", FieldType.STRING,
- placeholder='[{"role":"button","x":0,"y":0}]'),
+ placeholder=_BOXES_JSON_PLACEHOLDER),
),
description="Vote grounding proposals to the nearest element.",
))
specs.append(CommandSpec(
- "AC_validate_action", "Native UI", "Validate / Snap Action",
+ "AC_validate_action", _NATIVE_UI, "Validate / Snap Action",
fields=(
FieldSpec("action", FieldType.STRING,
placeholder='{"type":"click","x":..,"y":..}'),
FieldSpec("screen", FieldType.STRING, optional=True,
placeholder="[width, height]"),
FieldSpec("targets", FieldType.STRING, optional=True,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
),
description="Reject out-of-bounds clicks; snap a near-miss to the nearest "
"element.",
))
specs.append(CommandSpec(
- "AC_match_elements", "Native UI", "Match Elements (frames)",
+ "AC_match_elements", _NATIVE_UI, "Match Elements (frames)",
fields=(
FieldSpec("before", FieldType.STRING,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("after", FieldType.STRING,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("iou_threshold", FieldType.FLOAT, optional=True, default=0.5,
min_value=0.0, max_value=1.0),
),
description="Match element boxes across two frames by overlap (move/rename).",
))
specs.append(CommandSpec(
- "AC_assign_stable_ids", "Native UI", "Assign Stable Element IDs",
+ "AC_assign_stable_ids", _NATIVE_UI, "Assign Stable Element IDs",
fields=(
FieldSpec("elements", FieldType.STRING,
- placeholder='[{"x":..,"y":..,"width":..,"height":..}]'),
+ placeholder=_POINTS_JSON_PLACEHOLDER),
FieldSpec("prior", FieldType.STRING, optional=True,
placeholder="prior frame's elements (with ids)"),
FieldSpec("iou_threshold", FieldType.FLOAT, optional=True, default=0.5,
@@ -3825,10 +3835,10 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Tag elements with IDs carried across frames by overlap.",
))
specs.append(CommandSpec(
- "AC_score_candidates", "Native UI", "Score Candidates",
+ "AC_score_candidates", _NATIVE_UI, "Score Candidates",
fields=(
FieldSpec("candidates", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("want_role", FieldType.STRING, optional=True),
FieldSpec("want_name", FieldType.STRING, optional=True),
FieldSpec("anchor", FieldType.STRING, optional=True,
@@ -3837,10 +3847,10 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="Rank candidate elements by role / name / proximity confidence.",
))
specs.append(CommandSpec(
- "AC_best_candidate", "Native UI", "Best Candidate",
+ "AC_best_candidate", _NATIVE_UI, "Best Candidate",
fields=(
FieldSpec("candidates", FieldType.STRING,
- placeholder='[{"role":"button","name":"OK","x":..,"y":..}]'),
+ placeholder=_MARKS_JSON_PLACEHOLDER),
FieldSpec("want_role", FieldType.STRING, optional=True),
FieldSpec("want_name", FieldType.STRING, optional=True),
FieldSpec("anchor", FieldType.STRING, optional=True,
@@ -3849,7 +3859,7 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
description="The single highest-scoring candidate element.",
))
specs.append(CommandSpec(
- "AC_mark_screen", "Native UI", "Set-of-Marks: Number Elements",
+ "AC_mark_screen", _NATIVE_UI, "Set-of-Marks: Number Elements",
fields=(
FieldSpec("app_name", FieldType.STRING, optional=True),
FieldSpec("render_path", FieldType.FILE_PATH, optional=True),
@@ -3858,7 +3868,7 @@ def _add_set_of_marks_specs(specs: List[CommandSpec]) -> None:
"grounding; optional numbered-box overlay screenshot.",
))
specs.append(CommandSpec(
- "AC_mark_click", "Native UI", "Set-of-Marks: Click Number",
+ "AC_mark_click", _NATIVE_UI, "Set-of-Marks: Click Number",
fields=(FieldSpec("mark_id", FieldType.INT),),
description="Click the element behind a numbered mark.",
))
@@ -4085,7 +4095,7 @@ def _add_authoring_specs(specs: List[CommandSpec]) -> None:
path = FieldSpec("path", FieldType.FILE_PATH)
key = FieldSpec("key", FieldType.STRING)
specs.append(CommandSpec(
- "AC_element_save", "Native UI", "Element: Save Locator",
+ "AC_element_save", _NATIVE_UI, "Element: Save Locator",
fields=(path, key,
FieldSpec("name", FieldType.STRING, optional=True),
FieldSpec("role", FieldType.STRING, optional=True),
@@ -4093,22 +4103,22 @@ def _add_authoring_specs(specs: List[CommandSpec]) -> None:
description="Save a named native-UI locator (object repository).",
))
specs.append(CommandSpec(
- "AC_element_find", "Native UI", "Element: Find Saved",
+ "AC_element_find", _NATIVE_UI, "Element: Find Saved",
fields=(path, key),
description="Resolve a saved locator to a live element summary.",
))
specs.append(CommandSpec(
- "AC_element_click", "Native UI", "Element: Click Saved",
+ "AC_element_click", _NATIVE_UI, "Element: Click Saved",
fields=(path, key),
description="Click the element behind a saved locator.",
))
specs.append(CommandSpec(
- "AC_element_remove", "Native UI", "Element: Remove Saved",
+ "AC_element_remove", _NATIVE_UI, "Element: Remove Saved",
fields=(path, key),
description="Delete a saved locator.",
))
specs.append(CommandSpec(
- "AC_element_list", "Native UI", "Element: List Saved",
+ "AC_element_list", _NATIVE_UI, "Element: List Saved",
fields=(path,),
description="List saved locator names in a repository file.",
))
diff --git a/je_auto_control/utils/accessibility/backends/base.py b/je_auto_control/utils/accessibility/backends/base.py
index 4b86ab54..3b1f6637 100644
--- a/je_auto_control/utils/accessibility/backends/base.py
+++ b/je_auto_control/utils/accessibility/backends/base.py
@@ -29,32 +29,32 @@ def get_value(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> Optional[str]:
"""Return the matched control's value text, or None if not found."""
- self._unsupported("get_value")
+ self._unsupported("get_value", name, role, app_name, automation_id)
def set_value(self, value: str, name: Optional[str] = None,
role: Optional[str] = None, app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Set the matched control's value; return True on success."""
- self._unsupported("set_value")
+ self._unsupported("set_value", value, name, role, app_name, automation_id)
def invoke(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Invoke the matched control (e.g. press a button)."""
- self._unsupported("invoke")
+ self._unsupported("invoke", name, role, app_name, automation_id)
def toggle(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Toggle the matched control (e.g. a checkbox)."""
- self._unsupported("toggle")
+ self._unsupported("toggle", name, role, app_name, automation_id)
def read_table(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None,
) -> List[List[str]]:
"""Read a grid/table/list control as rows of cell strings."""
- self._unsupported("read_table")
+ self._unsupported("read_table", name, role, app_name, automation_id)
# --- extended control patterns (Expand / Selection / Range / Scroll) ----
@@ -62,43 +62,43 @@ def expand(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Expand the matched control (ExpandCollapsePattern); True on success."""
- self._unsupported("expand")
+ self._unsupported("expand", name, role, app_name, automation_id)
def collapse(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Collapse the matched control (ExpandCollapsePattern); True on success."""
- self._unsupported("collapse")
+ self._unsupported("collapse", name, role, app_name, automation_id)
def expand_state(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> Optional[str]:
"""Return ``expanded`` / ``collapsed`` / ``partial`` / ``leaf``, or None."""
- self._unsupported("expand_state")
+ self._unsupported("expand_state", name, role, app_name, automation_id)
def select_item(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Select the matched item (SelectionItemPattern); True on success."""
- self._unsupported("select_item")
+ self._unsupported("select_item", name, role, app_name, automation_id)
def get_range(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
"""Return ``{value, minimum, maximum}`` (RangeValuePattern), or None."""
- self._unsupported("get_range")
+ self._unsupported("get_range", name, role, app_name, automation_id)
def set_range_value(self, value: float, name: Optional[str] = None,
role: Optional[str] = None, app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Set a slider / progress value (RangeValuePattern); True on success."""
- self._unsupported("set_range_value")
+ self._unsupported("set_range_value", value, name, role, app_name, automation_id)
def scroll_into_view(self, name: Optional[str] = None,
role: Optional[str] = None, app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Scroll the matched control into view (ScrollItemPattern); True on success."""
- self._unsupported("scroll_into_view")
+ self._unsupported("scroll_into_view", name, role, app_name, automation_id)
# --- text patterns (TextPattern reads) ---------------------------------
@@ -109,33 +109,33 @@ def document_text(self, name: Optional[str] = None, role: Optional[str] = None,
Reads multiline / document controls where ValuePattern returns ``""``.
"""
- self._unsupported("document_text")
+ self._unsupported("document_text", name, role, app_name, automation_id)
def selected_text(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> Optional[str]:
"""Return the control's currently selected text (TextPattern), or None."""
- self._unsupported("selected_text")
+ self._unsupported("selected_text", name, role, app_name, automation_id)
def visible_text(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> Optional[str]:
"""Return only the on-screen text of the control (TextPattern), or None."""
- self._unsupported("visible_text")
+ self._unsupported("visible_text", name, role, app_name, automation_id)
def find_text(self, text: str = "", ignore_case: bool = True,
name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Return whether ``text`` occurs in the control (TextPattern.FindText)."""
- self._unsupported("find_text")
+ self._unsupported("find_text", text, ignore_case, name, role, app_name, automation_id)
def select_text(self, text: str = "", ignore_case: bool = True,
name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Find ``text`` and select its range (TextPattern.FindText + Select)."""
- self._unsupported("select_text")
+ self._unsupported("select_text", text, ignore_case, name, role, app_name, automation_id)
def text_attributes(self, name: Optional[str] = None,
role: Optional[str] = None, app_name: Optional[str] = None,
@@ -143,7 +143,7 @@ def text_attributes(self, name: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
"""Return formatting of the control's selection — ``{font_name, font_size,
bold, italic, foreground_color}`` (TextPattern attributes), or None."""
- self._unsupported("text_attributes")
+ self._unsupported("text_attributes", name, role, app_name, automation_id)
# --- keyboard focus ----------------------------------------------------
@@ -151,7 +151,7 @@ def set_focus(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Set keyboard focus on the matched control (SetFocus); True on success."""
- self._unsupported("set_focus")
+ self._unsupported("set_focus", name, role, app_name, automation_id)
# --- virtualized items (realize off-screen list / grid items) -----------
@@ -168,7 +168,7 @@ def find_virtual_item(self, item_name: Optional[str] = None, by: str = "name",
(``VirtualizedItemPattern``) so it exists as a real element. Returns the
realized element, or None if the container or item isn't found.
"""
- self._unsupported("find_virtual_item")
+ self._unsupported("find_virtual_item", item_name, by, container_name, container_role, app_name, automation_id)
# --- rich element properties -------------------------------------------
@@ -182,7 +182,7 @@ def get_properties(self, name: Optional[str] = None,
``enabled`` / ``offscreen`` / ``help_text`` / ``item_status`` /
``accelerator_key`` / ``access_key`` / ``orientation``.
"""
- self._unsupported("get_properties")
+ self._unsupported("get_properties", name, role, app_name, automation_id)
# --- table headers + cell addressing (TablePattern / GridItemPattern) ---
@@ -192,7 +192,7 @@ def get_table_headers(self, name: Optional[str] = None,
automation_id: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
"""Return a table's header labels as ``{columns: [...], rows: [...]}``."""
- self._unsupported("get_table_headers")
+ self._unsupported("get_table_headers", name, role, app_name, automation_id)
def get_grid_cell(self, row: int = 0, column: int = 0,
name: Optional[str] = None, role: Optional[str] = None,
@@ -201,7 +201,7 @@ def get_grid_cell(self, row: int = 0, column: int = 0,
) -> Optional[Dict[str, Any]]:
"""Return the cell at ``(row, column)`` as ``{value, row, column,
row_span, column_span}`` (GridPattern.GetItem + GridItemPattern)."""
- self._unsupported("get_grid_cell")
+ self._unsupported("get_grid_cell", row, column, name, role, app_name, automation_id)
# --- transform + window patterns (UIA-element-level) --------------------
@@ -210,21 +210,21 @@ def move_element(self, x: float = 0.0, y: float = 0.0,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Move the matched element to ``(x, y)`` (TransformPattern); True on success."""
- self._unsupported("move_element")
+ self._unsupported("move_element", x, y, name, role, app_name, automation_id)
def resize_element(self, width: float = 0.0, height: float = 0.0,
name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Resize the matched element (TransformPattern); True on success."""
- self._unsupported("resize_element")
+ self._unsupported("resize_element", width, height, name, role, app_name, automation_id)
def set_window_state(self, state: str = "normal",
name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Set a window's visual state ``normal`` / ``maximized`` / ``minimized``."""
- self._unsupported("set_window_state")
+ self._unsupported("set_window_state", state, name, role, app_name, automation_id)
def window_interaction_state(self, name: Optional[str] = None,
role: Optional[str] = None,
@@ -233,7 +233,7 @@ def window_interaction_state(self, name: Optional[str] = None,
) -> Optional[str]:
"""Return a window's interaction state — ``ready`` / ``blocked_by_modal`` /
``not_responding`` / ``running`` / ``closing`` (WindowPattern), or None."""
- self._unsupported("window_interaction_state")
+ self._unsupported("window_interaction_state", name, role, app_name, automation_id)
# --- MSAA bridge (LegacyIAccessiblePattern) ----------------------------
@@ -247,7 +247,7 @@ def legacy_info(self, name: Optional[str] = None, role: Optional[str] = None,
last-resort read for legacy Win32 controls that expose nothing useful via
the modern UIA patterns.
"""
- self._unsupported("legacy_info")
+ self._unsupported("legacy_info", name, role, app_name, automation_id)
def legacy_default_action(self, name: Optional[str] = None,
role: Optional[str] = None,
@@ -255,7 +255,7 @@ def legacy_default_action(self, name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Fire an old control's MSAA default action (DoDefaultAction); True on
success — the fallback when Value / Invoke / Toggle all do nothing."""
- self._unsupported("legacy_default_action")
+ self._unsupported("legacy_default_action", name, role, app_name, automation_id)
# --- container selection + views (Selection / MultipleView patterns) ----
@@ -265,7 +265,7 @@ def get_selection(self, name: Optional[str] = None, role: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
"""Return a container's selection state — ``{items, can_select_multiple,
is_required}`` (SelectionPattern), or None."""
- self._unsupported("get_selection")
+ self._unsupported("get_selection", name, role, app_name, automation_id)
def list_views(self, name: Optional[str] = None, role: Optional[str] = None,
app_name: Optional[str] = None,
@@ -273,13 +273,13 @@ def list_views(self, name: Optional[str] = None, role: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
"""Return a control's selectable views — ``{current, views: [...]}``
(MultipleViewPattern: list / details / tile / …), or None."""
- self._unsupported("list_views")
+ self._unsupported("list_views", name, role, app_name, automation_id)
def set_view(self, view: str = "", name: Optional[str] = None,
role: Optional[str] = None, app_name: Optional[str] = None,
automation_id: Optional[str] = None) -> bool:
"""Switch a control to the named view (MultipleViewPattern); True on success."""
- self._unsupported("set_view")
+ self._unsupported("set_view", view, name, role, app_name, automation_id)
# --- reactive events (UIA event subscription) --------------------------
@@ -291,9 +291,9 @@ def wait_for_focus_change(self, timeout: float = 5.0,
A zero-latency native wait (UIA AddFocusChangedEventHandler) — unlike the
polling recorder, it can't miss a fast focus transition.
"""
- self._unsupported("wait_for_focus_change")
+ self._unsupported("wait_for_focus_change", timeout)
- def _unsupported(self, operation: str):
+ def _unsupported(self, operation: str, *context: Any):
"""Raise a clear error for an action this backend can't perform."""
raise AccessibilityNotAvailableError(
f"{operation} is not supported by the {self.name} backend",
diff --git a/je_auto_control/utils/assertion/assertions.py b/je_auto_control/utils/assertion/assertions.py
index 2a80caee..f4214069 100644
--- a/je_auto_control/utils/assertion/assertions.py
+++ b/je_auto_control/utils/assertion/assertions.py
@@ -489,11 +489,12 @@ def assert_by_description(description: str,
)
passed = (matched == present)
state = "shows" if present else "does not show"
+ verdict = "match" if matched else "no match"
message = (
f"assert_by_description passed: screen {state} {description!r}"
if passed else
f"assert_by_description failed: expected screen to {state} "
- f"{description!r} (VLM verdict: {'match' if matched else 'no match'})"
+ f"{description!r} (VLM verdict: {verdict})"
)
return _finalize(
"vlm", passed, message,
diff --git a/je_auto_control/utils/color_match/color_match.py b/je_auto_control/utils/color_match/color_match.py
index a0858fc3..c7dd7cd0 100644
--- a/je_auto_control/utils/color_match/color_match.py
+++ b/je_auto_control/utils/color_match/color_match.py
@@ -26,8 +26,10 @@
def _hsv(source, region, is_haystack: bool):
import cv2
- rgb = (_to_rgb(source) if source is not None
- else _grab_rgb(region)) if is_haystack else _to_rgb(source)
+ if is_haystack:
+ rgb = _to_rgb(source) if source is not None else _grab_rgb(region)
+ else:
+ rgb = _to_rgb(source)
return cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV)
diff --git a/je_auto_control/utils/config_bundle/__main__.py b/je_auto_control/utils/config_bundle/__main__.py
index 880d4674..f57395a7 100644
--- a/je_auto_control/utils/config_bundle/__main__.py
+++ b/je_auto_control/utils/config_bundle/__main__.py
@@ -64,7 +64,8 @@ def _do_export(output: Path, root: Optional[Path]) -> int:
def _do_import(source: Path, root: Optional[Path], dry_run: bool) -> int:
try:
- bundle = json.loads(source.read_text(encoding="utf-8"))
+ # source is an operator-supplied CLI path, not remote input
+ bundle = json.loads(source.read_text(encoding="utf-8")) # NOSONAR
except (OSError, ValueError) as error:
print(f"failed to read {source}: {error}", file=sys.stderr)
return 2
diff --git a/je_auto_control/utils/element_scoring/element_scoring.py b/je_auto_control/utils/element_scoring/element_scoring.py
index 4c84ddf2..4d614260 100644
--- a/je_auto_control/utils/element_scoring/element_scoring.py
+++ b/je_auto_control/utils/element_scoring/element_scoring.py
@@ -40,6 +40,26 @@ def _proximity(element: Element, anchor: Sequence[int]) -> float:
return 1.0 / (1.0 + distance / 100.0)
+def _signal_parts(element: Element, want_role: Optional[str],
+ want_name: Optional[str],
+ similarity: Callable[[str, str], float],
+ prefer_enabled: bool,
+ anchor: Optional[Sequence[int]]) -> Dict[str, float]:
+ """Build the per-signal 0..1 breakdown for one ``element``."""
+ parts: Dict[str, float] = {}
+ if want_role is not None:
+ parts["role"] = (1.0 if str(element.get("role", "")).lower()
+ == str(want_role).lower() else 0.0)
+ if want_name is not None:
+ parts["name"] = float(similarity(want_name,
+ str(element.get("name", ""))))
+ if anchor is not None:
+ parts["proximity"] = _proximity(element, anchor)
+ if prefer_enabled:
+ parts["enabled"] = 1.0 if element.get("enabled", True) else 0.0
+ return parts
+
+
def score_candidates(candidates: Sequence[Element], *,
want_role: Optional[str] = None,
want_name: Optional[str] = None,
@@ -57,17 +77,8 @@ def score_candidates(candidates: Sequence[Element], *,
similarity = name_similarity or fuzzy_ratio
scored: List[ScoredCandidate] = []
for element in candidates:
- parts: Dict[str, float] = {}
- if want_role is not None:
- parts["role"] = (1.0 if str(element.get("role", "")).lower()
- == str(want_role).lower() else 0.0)
- if want_name is not None:
- parts["name"] = float(similarity(want_name,
- str(element.get("name", ""))))
- if anchor is not None:
- parts["proximity"] = _proximity(element, anchor)
- if prefer_enabled:
- parts["enabled"] = 1.0 if element.get("enabled", True) else 0.0
+ parts = _signal_parts(element, want_role, want_name, similarity,
+ prefer_enabled, anchor)
score = sum(parts.values()) / len(parts) if parts else 0.0
scored.append(ScoredCandidate(element, round(score, 4), parts))
scored.sort(key=lambda candidate: candidate.score, reverse=True)
diff --git a/je_auto_control/utils/executor/action_executor.py b/je_auto_control/utils/executor/action_executor.py
index 9f8cf9b3..0fcd3a21 100644
--- a/je_auto_control/utils/executor/action_executor.py
+++ b/je_auto_control/utils/executor/action_executor.py
@@ -171,6 +171,7 @@ def _run_dag(definition: Dict[str, Any],
_AX_RECORDER_SINGLETON = None
+_DEFAULT_APPROVALS_DIR = ".approvals"
def _a11y_dump(app_name: Optional[str] = None,
@@ -6029,7 +6030,7 @@ def _egress_reset() -> Dict[str, Any]:
def _verify_artifact(name: str, content: Any,
- approvals_dir: str = ".approvals",
+ approvals_dir: str = _DEFAULT_APPROVALS_DIR,
extension: str = "txt") -> Dict[str, Any]:
"""Adapter: verify an artifact against its approved baseline."""
from je_auto_control.utils.approval import verify_artifact
@@ -6039,14 +6040,14 @@ def _verify_artifact(name: str, content: Any,
"received_path": result.received_path}
-def _approve_artifact(name: str, approvals_dir: str = ".approvals",
+def _approve_artifact(name: str, approvals_dir: str = _DEFAULT_APPROVALS_DIR,
extension: str = "txt") -> Dict[str, Any]:
"""Adapter: promote a received artifact to the approved baseline."""
from je_auto_control.utils.approval import approve_artifact
return {"approved": approve_artifact(name, approvals_dir, extension)}
-def _pending_artifacts(approvals_dir: str = ".approvals") -> Dict[str, Any]:
+def _pending_artifacts(approvals_dir: str = _DEFAULT_APPROVALS_DIR) -> Dict[str, Any]:
"""Adapter: list artifacts awaiting approval."""
from je_auto_control.utils.approval import pending_artifacts
return {"pending": pending_artifacts(approvals_dir)}
diff --git a/je_auto_control/utils/form_fields/form_fields.py b/je_auto_control/utils/form_fields/form_fields.py
index 5fb646df..edb9eb3b 100644
--- a/je_auto_control/utils/form_fields/form_fields.py
+++ b/je_auto_control/utils/form_fields/form_fields.py
@@ -26,7 +26,7 @@ def _overlap_1d(a0: int, a1: int, b0: int, b1: int) -> int:
def _right_value(label: Box, values: Sequence[Box], max_gap: int):
"""Nearest value to the right of ``label`` that shares a row, or ``None``."""
- left, top, right, bottom = _box_bounds(label)
+ _, top, right, bottom = _box_bounds(label)
best: Optional[Tuple[Box, int]] = None
for value in values:
vl, vt, _, vb = _box_bounds(value)
@@ -39,7 +39,7 @@ def _right_value(label: Box, values: Sequence[Box], max_gap: int):
def _below_value(label: Box, values: Sequence[Box], max_gap: int):
"""Nearest value below ``label`` that shares a column, or ``None``."""
- left, top, right, bottom = _box_bounds(label)
+ left, _, right, bottom = _box_bounds(label)
best: Optional[Tuple[Box, int]] = None
for value in values:
vl, vt, vr, _ = _box_bounds(value)
diff --git a/je_auto_control/utils/governance/credential_broker.py b/je_auto_control/utils/governance/credential_broker.py
index ef4dab72..4325a887 100644
--- a/je_auto_control/utils/governance/credential_broker.py
+++ b/je_auto_control/utils/governance/credential_broker.py
@@ -86,13 +86,16 @@ def active(self) -> List[Dict[str, object]]:
"""List non-expired leases as ``{token, name, ttl_remaining}`` (no values)."""
now = self._clock()
result: List[Dict[str, object]] = []
- for token, lease in list(self._leases.items()):
+ expired: List[str] = []
+ for token, lease in self._leases.items():
remaining = float(lease["expires_at"]) - now
if remaining > 0:
result.append({"token": token, "name": lease["name"],
"ttl_remaining": remaining})
else:
- self._leases.pop(token, None)
+ expired.append(token)
+ for token in expired:
+ self._leases.pop(token, None)
return result
diff --git a/je_auto_control/utils/http_cassette/http_cassette.py b/je_auto_control/utils/http_cassette/http_cassette.py
index 443c62cc..676cc30b 100644
--- a/je_auto_control/utils/http_cassette/http_cassette.py
+++ b/je_auto_control/utils/http_cassette/http_cassette.py
@@ -41,15 +41,9 @@ def _matches(recorded: Mapping[str, Any], call: Mapping[str, Any],
match_on: Sequence[str]) -> bool:
view = _request_view(call)
for field in match_on:
- if field == "method":
- if recorded.get("method") != view["method"]:
- return False
- elif field == "url":
- if recorded.get("url") != view["url"]:
- return False
- elif field == "body":
- if recorded.get("body") != view["body"]:
- return False
+ if field in ("method", "url", "body") and \
+ recorded.get(field) != view[field]:
+ return False
return True
diff --git a/je_auto_control/utils/mcp_server/tools/_handlers.py b/je_auto_control/utils/mcp_server/tools/_handlers.py
index 8069a557..4128e73d 100644
--- a/je_auto_control/utils/mcp_server/tools/_handlers.py
+++ b/je_auto_control/utils/mcp_server/tools/_handlers.py
@@ -12,6 +12,8 @@
from je_auto_control.utils.mcp_server.tools._base import MCPContent
+_DEFAULT_APPROVALS_DIR = ".approvals"
+
# === Mouse / keyboard =======================================================
@@ -1515,7 +1517,7 @@ def egress_reset():
return {"allow": None, "deny": []}
-def verify_artifact(name: str, content, approvals_dir: str = ".approvals",
+def verify_artifact(name: str, content, approvals_dir: str = _DEFAULT_APPROVALS_DIR,
extension: str = "txt"):
from je_auto_control.utils.approval import verify_artifact as _verify
result = _verify(name, content, approvals_dir, extension)
@@ -1524,13 +1526,13 @@ def verify_artifact(name: str, content, approvals_dir: str = ".approvals",
"received_path": result.received_path}
-def approve_artifact(name: str, approvals_dir: str = ".approvals",
+def approve_artifact(name: str, approvals_dir: str = _DEFAULT_APPROVALS_DIR,
extension: str = "txt"):
from je_auto_control.utils.approval import approve_artifact as _approve
return {"approved": _approve(name, approvals_dir, extension)}
-def pending_artifacts(approvals_dir: str = ".approvals"):
+def pending_artifacts(approvals_dir: str = _DEFAULT_APPROVALS_DIR):
from je_auto_control.utils.approval import pending_artifacts as _pending
return {"pending": _pending(approvals_dir)}
diff --git a/je_auto_control/utils/notify/notifier.py b/je_auto_control/utils/notify/notifier.py
index df5e59ca..fbd0e83e 100644
--- a/je_auto_control/utils/notify/notifier.py
+++ b/je_auto_control/utils/notify/notifier.py
@@ -86,6 +86,6 @@ def notify(title: str, message: str,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
return NotifyResult(True, system, "sent")
- except (FileNotFoundError, OSError, subprocess.SubprocessError) as error:
+ except (OSError, subprocess.SubprocessError) as error:
autocontrol_logger.warning("notify failed: %r", error)
return NotifyResult(False, system, repr(error))
diff --git a/je_auto_control/utils/remote_desktop/host_service.py b/je_auto_control/utils/remote_desktop/host_service.py
index ee6e0782..ed58841a 100644
--- a/je_auto_control/utils/remote_desktop/host_service.py
+++ b/je_auto_control/utils/remote_desktop/host_service.py
@@ -217,7 +217,8 @@ def _interactive_configure() -> int:
)
answers["poll_interval_s"] = 2.0
_DEFAULT_CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
- _DEFAULT_CONFIG_PATH.write_text(
+ # _DEFAULT_CONFIG_PATH is a hardcoded module constant, not user input
+ _DEFAULT_CONFIG_PATH.write_text( # NOSONAR
json.dumps(answers, indent=2), encoding="utf-8",
)
try:
diff --git a/je_auto_control/utils/remote_desktop/turn_config.py b/je_auto_control/utils/remote_desktop/turn_config.py
index aa04f15c..a9373a32 100644
--- a/je_auto_control/utils/remote_desktop/turn_config.py
+++ b/je_auto_control/utils/remote_desktop/turn_config.py
@@ -142,7 +142,8 @@ def write_bundle(output_dir: Path, *, realm: str, user: str,
secret: str, listen_port: int, tls_port: int,
tls_cert: Optional[str], tls_key: Optional[str],
external_ip: Optional[str]) -> None:
- output_dir.mkdir(parents=True, exist_ok=True)
+ # output_dir is an operator-supplied CLI path, not remote input
+ output_dir.mkdir(parents=True, exist_ok=True) # NOSONAR
conf_path = output_dir / "turnserver.conf"
conf_path.write_text(render_turnserver_conf(
realm=realm, listen_port=listen_port, tls_port=tls_port,
diff --git a/je_auto_control/utils/remote_desktop/web_viewer/index.html b/je_auto_control/utils/remote_desktop/web_viewer/index.html
index efadd0cc..f371c074 100644
--- a/je_auto_control/utils/remote_desktop/web_viewer/index.html
+++ b/je_auto_control/utils/remote_desktop/web_viewer/index.html
@@ -108,8 +108,8 @@
-
-
Bearer token
-
Token kept in sessionStorage; cleared on tab close.
diff --git a/je_auto_control/utils/stats/stats.py b/je_auto_control/utils/stats/stats.py
index 08187a6c..4ace2f4e 100644
--- a/je_auto_control/utils/stats/stats.py
+++ b/je_auto_control/utils/stats/stats.py
@@ -88,11 +88,11 @@ def _betacf(a: float, b: float, x: float) -> float:
def _betai(a: float, b: float, x: float) -> float:
# x is a domain ratio in [0, 1]; both boundaries are reachable (e.g. x == 1
- # when the t-statistic is 0). NOSONAR: the analyzer mis-models these as
- # constant, but they are genuine, exercised guards.
- if x <= 0: # NOSONAR python:S2583 reason: reachable beta-domain lower bound
+ # when the t-statistic is 0); the analyzer mis-models these as constant,
+ # but they are genuine, exercised guards.
+ if x <= 0: # NOSONAR reachable beta-domain lower bound, not constant
return 0.0
- if x >= 1: # NOSONAR python:S2583 reason: reachable beta-domain upper bound
+ if x >= 1: # NOSONAR reachable beta-domain upper bound, not constant
return 1.0
front = math.exp(math.lgamma(a + b) - math.lgamma(a) - math.lgamma(b)
+ a * math.log(x) + b * math.log(1 - x))
diff --git a/je_auto_control/utils/stubs/generator.py b/je_auto_control/utils/stubs/generator.py
index 8eaad392..fcec4444 100644
--- a/je_auto_control/utils/stubs/generator.py
+++ b/je_auto_control/utils/stubs/generator.py
@@ -88,7 +88,8 @@ def write_pyi(target: Path,
target.parent.mkdir(parents=True, exist_ok=True)
tmp = target.with_suffix(target.suffix + ".tmp")
tmp.write_text(body, encoding="utf-8")
- tmp.replace(target)
+ # target is an operator-supplied CLI path, not remote input
+ tmp.replace(target) # NOSONAR
return target
diff --git a/test/unit_test/headless/test_action_effect_batch.py b/test/unit_test/headless/test_action_effect_batch.py
index cf691b73..694f1693 100644
--- a/test/unit_test/headless/test_action_effect_batch.py
+++ b/test/unit_test/headless/test_action_effect_batch.py
@@ -6,7 +6,7 @@
def _el(x, y, name="", role="button"):
- return dict(x=x, y=y, width=40, height=20, role=role, name=name)
+ return {"x": x, "y": y, "width": 40, "height": 20, "role": role, "name": name}
def test_no_op_when_nothing_changes():
diff --git a/test/unit_test/headless/test_canonical_log_batch.py b/test/unit_test/headless/test_canonical_log_batch.py
index 87e30203..de55b766 100644
--- a/test/unit_test/headless/test_canonical_log_batch.py
+++ b/test/unit_test/headless/test_canonical_log_batch.py
@@ -20,6 +20,7 @@ def test_timer_uses_injected_clock():
ticks = iter([10.0, 10.5])
line = CanonicalLogLine(clock=lambda: next(ticks))
with line.timer("step"):
+ # body intentionally empty: the timer measures the enter->exit interval
pass
assert line.to_dict()["step_ms"] == pytest.approx(500.0)
diff --git a/test/unit_test/headless/test_coordinate_space_batch.py b/test/unit_test/headless/test_coordinate_space_batch.py
index 93ae65bb..0196276c 100644
--- a/test/unit_test/headless/test_coordinate_space_batch.py
+++ b/test/unit_test/headless/test_coordinate_space_batch.py
@@ -43,14 +43,14 @@ def test_clamping_is_in_bounds():
def test_downscale_png_matches_model_size():
- Image = pytest.importorskip("PIL.Image")
+ pil_image = pytest.importorskip("PIL.Image")
import io
buf = io.BytesIO()
- Image.new("RGB", (640, 480), (1, 2, 3)).save(buf, format="PNG")
+ pil_image.new("RGB", (640, 480), (1, 2, 3)).save(buf, format="PNG")
from je_auto_control.utils.coordinate_space import downscale_png
space = normalized_space(640, 480, grid=64)
out = downscale_png(buf.getvalue(), space)
- with Image.open(io.BytesIO(out)) as resized:
+ with pil_image.open(io.BytesIO(out)) as resized:
assert resized.size == (64, 64)
diff --git a/test/unit_test/headless/test_critic_features_batch.py b/test/unit_test/headless/test_critic_features_batch.py
index 7e0fbd12..daa565cc 100644
--- a/test/unit_test/headless/test_critic_features_batch.py
+++ b/test/unit_test/headless/test_critic_features_batch.py
@@ -6,7 +6,7 @@
def _el(x, y, name="", role="button"):
- return dict(x=x, y=y, width=40, height=20, role=role, name=name)
+ return {"x": x, "y": y, "width": 40, "height": 20, "role": role, "name": name}
def test_record_captures_effect_and_delta():
diff --git a/test/unit_test/headless/test_decision_table_batch.py b/test/unit_test/headless/test_decision_table_batch.py
index 1bf92a52..f3a76acf 100644
--- a/test/unit_test/headless/test_decision_table_batch.py
+++ b/test/unit_test/headless/test_decision_table_batch.py
@@ -49,9 +49,9 @@ def test_unique_multi_match_raises():
def test_wildcard_and_literal_conditions():
spec = {"inputs": ["role", "active"], "hit_policy": "FIRST", "rules": [
- {"conditions": {"role": "admin", "active": None}, # active = wildcard
+ {"conditions": {"role": "admin", "active": None}, # active -> wildcard
"outputs": {"allow": True}},
- {"conditions": {"role": "-", "active": True}, # role = wildcard
+ {"conditions": {"role": "-", "active": True}, # role -> wildcard
"outputs": {"allow": False}},
]}
assert evaluate_table(spec, {"role": "admin", "active": False}) == \
diff --git a/test/unit_test/headless/test_diagnostics.py b/test/unit_test/headless/test_diagnostics.py
index 0602ff40..2f207e35 100644
--- a/test/unit_test/headless/test_diagnostics.py
+++ b/test/unit_test/headless/test_diagnostics.py
@@ -43,7 +43,7 @@ def test_to_dict_payload_shape():
def test_cli_exits_zero_when_all_green():
"""The CLI module should respect the runner's overall ``ok`` flag."""
- completed = subprocess.run( # noqa: S603 # local CLI test
+ completed = subprocess.run( # noqa: S603 # nosemgrep # local CLI test
[sys.executable, "-m", "je_auto_control.utils.diagnostics"],
capture_output=True, text=True, timeout=30, check=False,
)
diff --git a/test/unit_test/headless/test_dotenv_batch.py b/test/unit_test/headless/test_dotenv_batch.py
index a659d9fa..4b76bafa 100644
--- a/test/unit_test/headless/test_dotenv_batch.py
+++ b/test/unit_test/headless/test_dotenv_batch.py
@@ -44,7 +44,7 @@ def test_load_dotenv_file(tmp_path):
path.write_text(_TEXT, encoding="utf-8")
env = {"PLAIN": "keep"}
load_dotenv(str(path), env)
- assert env["PLAIN"] == "keep" and env["TOKEN"] == "secret"
+ assert env["PLAIN"] == "keep" and env["TOKEN"] == "secret" # NOSONAR load_dotenv mutates env in place
load_dotenv(str(path), env, override=True)
assert env["PLAIN"] == "hello" # override replaces
assert dotenv_values(str(path))["TOKEN"] == "secret"
diff --git a/test/unit_test/headless/test_image_dedup_batch.py b/test/unit_test/headless/test_image_dedup_batch.py
index efa16619..32b08be3 100644
--- a/test/unit_test/headless/test_image_dedup_batch.py
+++ b/test/unit_test/headless/test_image_dedup_batch.py
@@ -10,7 +10,7 @@
def test_hamming_distance_and_similar():
assert hamming_distance("00", "00") == 0
- assert hamming_distance("0f", "00") == 4 # 0x0f = 1111
+ assert hamming_distance("0f", "00") == 4 # 0x0f -> 1111 bits
assert images_similar("ff", "fe", max_distance=1) is True
assert images_similar("ff", "f0", max_distance=1) is False
@@ -34,11 +34,11 @@ def test_dedupe_empty():
def test_real_pillow_hashing(tmp_path):
- Image = pytest.importorskip("PIL.Image")
+ pil_image = pytest.importorskip("PIL.Image")
black = tmp_path / "black.png"
white = tmp_path / "white.png"
- Image.new("RGB", (64, 64), (0, 0, 0)).save(black)
- Image.new("RGB", (64, 64), (255, 255, 255)).save(white)
+ pil_image.new("RGB", (64, 64), (0, 0, 0)).save(black)
+ pil_image.new("RGB", (64, 64), (255, 255, 255)).save(white)
h_black = average_hash(str(black))
assert isinstance(h_black, str) and h_black
@@ -54,11 +54,11 @@ def test_real_pillow_hashing(tmp_path):
# --- wiring ---------------------------------------------------------------
def test_executor_round_trip(tmp_path):
- Image = pytest.importorskip("PIL.Image")
+ pil_image = pytest.importorskip("PIL.Image")
a = tmp_path / "a.png"
b = tmp_path / "b.png"
- Image.new("RGB", (32, 32), (10, 10, 10)).save(a)
- Image.new("RGB", (32, 32), (10, 10, 10)).save(b) # identical
+ pil_image.new("RGB", (32, 32), (10, 10, 10)).save(a)
+ pil_image.new("RGB", (32, 32), (10, 10, 10)).save(b) # identical
rec = ac.execute_action([
["AC_dedupe_images", {"paths": [str(a), str(b)], "max_distance": 2}],
])
diff --git a/test/unit_test/headless/test_link_header_batch.py b/test/unit_test/headless/test_link_header_batch.py
index ef93cf00..30b3b213 100644
--- a/test/unit_test/headless/test_link_header_batch.py
+++ b/test/unit_test/headless/test_link_header_batch.py
@@ -46,7 +46,7 @@ def test_paginate_follows_next_over_injected_fetch():
}
responses = paginate("u1", lambda url: pages[url])
assert len(responses) == 3
- assert responses is not None and responses[-1]["headers"] == {}
+ assert responses[-1]["headers"] == {}
def test_paginate_respects_max_pages():
diff --git a/test/unit_test/headless/test_remote_desktop_cursor.py b/test/unit_test/headless/test_remote_desktop_cursor.py
index 715da144..d5412a0d 100644
--- a/test/unit_test/headless/test_remote_desktop_cursor.py
+++ b/test/unit_test/headless/test_remote_desktop_cursor.py
@@ -137,7 +137,8 @@ def test_frame_display_paints_cursor_overlay():
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
pytest.importorskip("PySide6.QtWidgets")
from PySide6.QtWidgets import QApplication
- QApplication.instance() or QApplication([])
+ if QApplication.instance() is None:
+ QApplication([])
from je_auto_control.gui.remote_desktop.frame_display import _FrameDisplay
display = _FrameDisplay()
diff --git a/test/unit_test/headless/test_remote_desktop_websocket.py b/test/unit_test/headless/test_remote_desktop_websocket.py
index 935d6ad6..e4638cbd 100644
--- a/test/unit_test/headless/test_remote_desktop_websocket.py
+++ b/test/unit_test/headless/test_remote_desktop_websocket.py
@@ -121,7 +121,7 @@ def client_side():
sec_key = line.split(":", 1)[1].strip()
import base64
import hashlib
- accept = base64.b64encode(hashlib.sha1( # nosec B324
+ accept = base64.b64encode(hashlib.sha1( # nosec B324 # nosemgrep
(sec_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").encode("ascii"),
usedforsecurity=False,
).digest()).decode("ascii")
diff --git a/test/unit_test/headless/test_s3_store_batch.py b/test/unit_test/headless/test_s3_store_batch.py
index 8be38546..e10ad8bc 100644
--- a/test/unit_test/headless/test_s3_store_batch.py
+++ b/test/unit_test/headless/test_s3_store_batch.py
@@ -23,12 +23,12 @@ def upload_file(self, filename, bucket, key):
def download_file(self, bucket, key, filename):
Path(filename).write_bytes(self.objects[(bucket, key)])
- def list_objects_v2(self, Bucket, Prefix=""):
+ def list_objects_v2(self, Bucket, Prefix=""): # NOSONAR boto3 API names
keys = [k for (b, k) in self.objects if b == Bucket
and k.startswith(Prefix)]
return {"Contents": [{"Key": k} for k in sorted(keys)]}
- def delete_object(self, Bucket, Key):
+ def delete_object(self, Bucket, Key): # NOSONAR boto3 API names
self.objects.pop((Bucket, Key), None)
diff --git a/test/unit_test/headless/test_schema_compat_batch.py b/test/unit_test/headless/test_schema_compat_batch.py
index 8c0c6922..270fc199 100644
--- a/test/unit_test/headless/test_schema_compat_batch.py
+++ b/test/unit_test/headless/test_schema_compat_batch.py
@@ -24,7 +24,7 @@ def test_added_required_breaks_backward():
"required": ["id", "email"]}
assert is_backward_compatible(_BASE, new) is False
assert is_forward_compatible(_BASE, new) is True
- [change] = [c for c in check_compatibility(_BASE, new)["breaking"]]
+ [change] = list(check_compatibility(_BASE, new)["breaking"])
assert change["kind"] == "field_added" and change["path"] == "email"
diff --git a/test/unit_test/headless/test_timeseries_batch.py b/test/unit_test/headless/test_timeseries_batch.py
index fd1a4ac7..b6233924 100644
--- a/test/unit_test/headless/test_timeseries_batch.py
+++ b/test/unit_test/headless/test_timeseries_batch.py
@@ -18,7 +18,7 @@ def test_rate_and_increase():
def test_rate_handles_counter_reset():
series = [(0, 90), (10, 100), (20, 5), (30, 25)] # reset between 100 and 5
- # increase = (100-90) + reset(5) + (25-5) = 10 + 5 + 20 = 35
+ # increase: (100-90) + reset(5) + (25-5) -> 10 + 5 + 20 -> 35
assert ts_increase(series) == pytest.approx(35.0)
assert ts_rate(series) == pytest.approx(35.0 / 30)
diff --git a/test/unit_test/headless/test_window_capture.py b/test/unit_test/headless/test_window_capture.py
index 22eaaea3..e17b2bc7 100644
--- a/test/unit_test/headless/test_window_capture.py
+++ b/test/unit_test/headless/test_window_capture.py
@@ -89,8 +89,12 @@ def mover(title, x, y, width, height):
def test_snap_window_right_half():
rects = []
- snap_window("E", "right", screen_size=lambda: (1000, 800),
- mover=lambda t, x, y, w, h: rects.append((x, y, w, h)) is None)
+
+ def mover(_title, x, y, w, h):
+ rects.append((x, y, w, h))
+ return 1
+
+ snap_window("E", "right", screen_size=lambda: (1000, 800), mover=mover)
assert rects == [(500, 0, 500, 800)]