Skip to content

Commit f68e02b

Browse files
committed
Empty the typing contract's exemption list but for one module
Forty-one modules in one sweep, and the list is now a single line: `gui/remote_desktop/webrtc_panel.py`, blocked on the split its size cap already owes it (recorded in Progress.md). Several were annotations that were simply wrong about what the code returns, and fixing them is what let the callers stop working around it: * `screenshot()` said `-> List[int]` while it returns the captured BGR frame. Every caller that read `.shape` off it was reading through a lie; `screen_record` was the one mypy caught. * `visual_match._nms` was typed for `Match` and reused from `rotated_match`, `edge_match` and `color_match` with their own record types. It takes a `TypeVar` bound to a read-only Protocol of what it actually reads — position, size, score — which is also why the bound had to be properties: the records are frozen dataclasses, and a Protocol attribute demands a writable one. * `logical_frame`'s injectable grabber was typed `Callable[..., Any]` while its own docstring says "ImageGrab-shaped object", so `.grab()` on it was an error. Four fix a `None` the code could really see: `humanize.motion` and `watcher` unpacked `get_mouse_position()` (the Windows backend returns None on a locked desktop), `dag.runner` opened a node's `action_file` without checking a node had one, and `color_match` divided a `None` accumulator when handed no channels. `secret_store._require_unlocked` now returns the `(fernet, vault)` pair it checks, which removed three `type: ignore`s that existed only because the check and the use were separate statements. Two more cv2 names — `VideoWriter_fourcc` and `ORB_create` — join `MSER_create` as present at runtime but absent from the shipped stub.
1 parent d0b49cf commit f68e02b

43 files changed

Lines changed: 210 additions & 160 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎architecture_explore.md‎

Lines changed: 42 additions & 42 deletions
Large diffs are not rendered by default.

‎je_auto_control/__main__.py‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,16 @@ def preprocess_read_str_execute_action(execute_str: str):
5555
"--execute_str",
5656
type=str, help="execute json str"
5757
)
58-
args = parser.parse_args()
59-
args = vars(args)
60-
for key, value in args.items():
61-
if value is not None:
62-
argparse_event_dict.get(key)(value)
63-
if all(value is None for value in args.values()):
58+
parsed = vars(parser.parse_args())
59+
for key, value in parsed.items():
60+
if value is None:
61+
continue
62+
handler = argparse_event_dict.get(key)
63+
if handler is None:
64+
raise AutoControlArgparseException(
65+
argparse_get_wrong_data_error_message)
66+
handler(value)
67+
if all(value is None for value in parsed.values()):
6468
raise AutoControlArgparseException(argparse_get_wrong_data_error_message)
6569
except AutoControlArgparseException as error:
6670
autocontrol_logger.error("argparse failure: %r", error)

‎je_auto_control/cli.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import sys
2727
import threading
2828
import time
29-
from typing import Dict, List, Optional, Sequence
29+
from typing import Callable, Dict, List, Optional, Sequence
3030

3131
from je_auto_control.utils.exception.exceptions import (
3232
AutoControlActionException,
@@ -215,7 +215,7 @@ def cmd_start_rest(args: argparse.Namespace) -> int:
215215
return 0
216216

217217

218-
def _run_until_signal(shutdown: callable) -> None:
218+
def _run_until_signal(shutdown: Callable[[], None]) -> None:
219219
stopping = {"flag": False}
220220

221221
def _handler(_signum, _frame):

‎je_auto_control/utils/act_modes/act_modes.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def act_with_mode(action: Callable[[List[int]], Any],
5858
point = list(report.point) if report.point is not None else None
5959
base = {"mode": mode, "actionable": report.actionable,
6060
"reason": report.reason, "point": point}
61-
if mode == "trial" or not report.actionable:
61+
target = report.point
62+
if mode == "trial" or not report.actionable or target is None:
6263
return {**base, "acted": False, "result": None}
63-
return {**base, "acted": True, "result": action(report.point)}
64+
return {**base, "acted": True, "result": action(target)}

‎je_auto_control/utils/annotate/annotate.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ def _draw_arrow(draw: ImageDraw.ImageDraw, ann: Dict[str, Any]) -> None:
7777

7878

7979
def _draw_text(draw: ImageDraw.ImageDraw, ann: Dict[str, Any]) -> None:
80-
pos = tuple(int(v) for v in ann["position"])
80+
raw = ann["position"]
81+
pos = (float(raw[0]), float(raw[1]))
8182
draw.text(pos, str(ann.get("text", "")), fill=_color(ann.get("color")))
8283

8384

@@ -101,7 +102,7 @@ def annotate_screenshot(source: ImageSource,
101102
draw = ImageDraw.Draw(base)
102103
dispatch = {"box": _draw_box, "arrow": _draw_arrow, "text": _draw_text}
103104
for ann in annotations:
104-
handler = dispatch.get(ann.get("type"))
105+
handler = dispatch.get(str(ann.get("type", "")))
105106
if handler is not None:
106107
handler(draw, ann)
107108
out = Path(output_path)

‎je_auto_control/utils/change_localize/change_localize.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def rank_changes(scored_boxes: Sequence[Any], *,
3535
is ``True`` when the score is at or above ``threshold``.
3636
"""
3737
limit = float(threshold)
38-
result = [
38+
result: List[Dict[str, Any]] = [
3939
{"box": [int(value) for value in box],
4040
"score": round(float(score), 4),
4141
"changed": float(score) >= limit}

‎je_auto_control/utils/codegen/codegen.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ def _action_to_call(action: Sequence, event_dict: dict, public: set) -> str:
4242
name = action[0]
4343
params = action[1] if len(action) == 2 else None
4444
func = event_dict.get(name)
45-
direct = func is not None and getattr(func, "__name__", "") in public
45+
public_name = getattr(func, "__name__", "") if func is not None else ""
46+
direct = public_name in public
4647
if direct and (params is None or isinstance(params, dict)):
4748
if params:
4849
kwargs = ", ".join(
4950
f"{key}={value!r}" for key, value in params.items())
50-
return f"ac.{func.__name__}({kwargs})"
51-
return f"ac.{func.__name__}()"
51+
return f"ac.{public_name}({kwargs})"
52+
return f"ac.{public_name}()"
5253
return f"ac.execute_action({[list(action)]!r})"
5354

5455

‎je_auto_control/utils/color_match/color_match.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ def _score_map(template_hsv, haystack_hsv, channels: Sequence[str]):
5050
template_hsv[:, :, index], cv2.TM_SQDIFF_NORMED)
5151
result = np.nan_to_num(result, nan=1.0, posinf=1.0)
5252
accumulator = result if accumulator is None else accumulator + result
53+
if accumulator is None:
54+
raise ValueError("match_color needs at least one channel")
5355
return 1.0 - accumulator / len(channels)
5456

5557

‎je_auto_control/utils/color_stats/color_stats.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ def region_color_stats(source: ImageSource,
7878
"""
7979
image = _load_rgb(source)
8080
if region is not None:
81-
image = image.crop(tuple(int(v) for v in region))
81+
left, top, right, bottom = (int(v) for v in region)
82+
image = image.crop((left, top, right, bottom))
8283
image.thumbnail((128, 128))
8384
pixels: List[RGB] = list(image.getdata())
8485
count = len(pixels)

‎je_auto_control/utils/config_sync/client.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ def merge_buckets(local: ConfigBucket,
9696
local_entry = local_sec.get(entry_id)
9797
remote_entry = remote_sec.get(entry_id)
9898
if local_entry is None:
99-
merged_section[entry_id] = remote_entry
99+
if remote_entry is not None:
100+
merged_section[entry_id] = remote_entry
100101
continue
101102
if remote_entry is None:
102103
merged_section[entry_id] = local_entry

0 commit comments

Comments
 (0)