Skip to content

Commit e864ddf

Browse files
refactor(c901): fix 9 src tool files below C901 threshold, remove from grandfather list (#1938)
Claude-Session: https://claude.ai/code/session_01DxGQhYBQg7681uCdr9w9qB Co-authored-by: kingpanther13 <kingpanther13@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 364acb7 commit e864ddf

10 files changed

Lines changed: 702 additions & 444 deletions

File tree

pyproject.toml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -177,21 +177,12 @@ ignore = [
177177
"src/ha_mcp/backup_manager.py" = ["C901"]
178178
"src/ha_mcp/tools/auto_backup.py" = ["C901"]
179179
"src/ha_mcp/tools/backup.py" = ["C901"]
180-
"src/ha_mcp/tools/radio/matter.py" = ["C901"]
181-
"src/ha_mcp/tools/radio/zigbee.py" = ["C901"]
182-
"src/ha_mcp/tools/radio/zwave.py" = ["C901"]
183-
"src/ha_mcp/tools/reference_validator.py" = ["C901"]
184-
"src/ha_mcp/tools/tools_areas.py" = ["C901"]
185180
"src/ha_mcp/tools/tools_config_automations.py" = ["C901"]
186181
"src/ha_mcp/tools/tools_config_scenes.py" = ["C901"]
187182
"src/ha_mcp/tools/tools_config_scripts.py" = ["C901"]
188183
"src/ha_mcp/tools/tools_dev.py" = ["C901"]
189-
"src/ha_mcp/tools/tools_history.py" = ["C901"]
190184
"src/ha_mcp/tools/tools_integrations.py" = ["C901"]
191185
"src/ha_mcp/tools/tools_system.py" = ["C901"]
192-
"src/ha_mcp/tools/tools_zones.py" = ["C901"]
193-
"src/ha_mcp/transforms/categorized_search.py" = ["C901"]
194-
"src/ha_mcp/visibility/resolver.py" = ["C901"]
195186
"tests/src/e2e/conftest.py" = ["C901"]
196187
"tests/src/e2e/error_handling/test_network_errors.py" = ["C901"]
197188
"tests/src/e2e/policy/test_readonly_mode.py" = ["C901"]

src/ha_mcp/tools/radio/matter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ async def handle(client: Any, action: str, args: dict[str, Any]) -> dict[str, An
145145
# Returns setup_pin_code, setup_manual_code, setup_qr_code.
146146
return ok("matter", "share_out", commissioning=commissioning)
147147

148+
return await _handle_matter_more(client, action, args, device_id)
149+
150+
151+
async def _handle_matter_more(
152+
client: Any, action: str, args: dict[str, Any], device_id: Any
153+
) -> dict[str, Any]:
154+
"""Continuation of :func:`handle` for the remaining Matter actions."""
148155
if action == "interview":
149156
result = await ws_call(
150157
client,

src/ha_mcp/tools/radio/zigbee.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ async def handle(client: Any, action: str, args: dict[str, Any]) -> dict[str, An
272272
long_running=True,
273273
)
274274

275+
return await _handle_zigbee_groups(client, action, args, device_id)
276+
277+
278+
async def _handle_zigbee_groups(
279+
client: Any, action: str, args: dict[str, Any], device_id: Any
280+
) -> dict[str, Any]:
281+
"""Continuation of :func:`handle` for Zigbee group and binding actions."""
275282
# --- groups ------------------------------------------------------------ #
276283
if action == "group_add":
277284
group = await ws_call(
@@ -340,6 +347,14 @@ async def handle(client: Any, action: str, args: dict[str, Any]) -> dict[str, An
340347
)
341348
return ok("zigbee", "unbind", result=result)
342349

350+
return await _handle_zigbee_clusters(client, action, args, device_id)
351+
352+
353+
async def _handle_zigbee_clusters(
354+
client: Any, action: str, args: dict[str, Any], device_id: Any
355+
) -> dict[str, Any]:
356+
"""Continuation of :func:`handle` for Zigbee cluster-write and network actions."""
357+
cluster_type = args.get("cluster_type", "in")
343358
# --- cluster writes (service-only) ------------------------------------- #
344359
if action == "cluster_write":
345360
ieee = await _resolve_ieee(client, device_id)

src/ha_mcp/tools/radio/zwave.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ async def handle(client: Any, action: str, args: dict[str, Any]) -> dict[str, An
174174
result = await client.call_service("zwave_js", "ping", {"device_id": device_id})
175175
return ok("zwave", "ping", result=result)
176176

177+
return await _handle_zwave_inclusion(client, action, args, device_id)
178+
179+
180+
async def _handle_zwave_inclusion(
181+
client: Any, action: str, args: dict[str, Any], device_id: Any
182+
) -> dict[str, Any]:
183+
"""Continuation of :func:`handle` for Z-Wave inclusion/exclusion actions."""
177184
if action == "add":
178185
entry_id = await _zwave_entry_id(client)
179186
if not entry_id:
@@ -289,6 +296,13 @@ async def handle(client: Any, action: str, args: dict[str, Any]) -> dict[str, An
289296
long_running=True,
290297
)
291298

299+
return await _handle_zwave_maintenance(client, action, args, device_id)
300+
301+
302+
async def _handle_zwave_maintenance(
303+
client: Any, action: str, args: dict[str, Any], device_id: Any
304+
) -> dict[str, Any]:
305+
"""Continuation of :func:`handle` for Z-Wave node maintenance actions."""
292306
if action == "reinterview":
293307
result = await ws_call(
294308
client,

src/ha_mcp/tools/reference_validator.py

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,55 @@ class ValidationWarning(TypedDict):
6969
reason: str
7070

7171

72+
def _extract_service_ref(
73+
sub_path: str,
74+
value: str,
75+
refs: list[ExtractedRef],
76+
unvalidated_templates: list[int],
77+
) -> None:
78+
"""Record a service ref at *sub_path*, counting templates instead."""
79+
if _is_template(value):
80+
unvalidated_templates[0] += 1
81+
else:
82+
refs.append({"path": sub_path, "value": value, "kind": "service"})
83+
84+
85+
def _extract_entity_refs(
86+
sub_path: str,
87+
value: Any,
88+
refs: list[ExtractedRef],
89+
unvalidated_templates: list[int],
90+
) -> bool:
91+
"""Record entity ref(s) from a str or list *value*; return True if handled.
92+
93+
Returns False when *value* is neither a str nor a list so the caller can
94+
keep recursing into it (an ``entity_id`` mapped to a nested structure).
95+
"""
96+
if isinstance(value, str):
97+
if _is_template(value):
98+
unvalidated_templates[0] += 1
99+
else:
100+
refs.append({"path": sub_path, "value": value, "kind": "entity"})
101+
return True
102+
if isinstance(value, list):
103+
for i, item in enumerate(value):
104+
if not isinstance(item, str):
105+
continue
106+
item_path = f"{sub_path}[{i}]"
107+
if _is_template(item):
108+
unvalidated_templates[0] += 1
109+
else:
110+
refs.append(
111+
{
112+
"path": item_path,
113+
"value": item,
114+
"kind": "entity",
115+
}
116+
)
117+
return True
118+
return False
119+
120+
72121
def extract_refs(config: Any) -> WalkerResult:
73122
"""Pull every literal service/entity reference out of *config*.
74123
@@ -97,43 +146,17 @@ def _walk(node: Any, path: str) -> None:
97146
sub_path = f"{path}.{key}" if path else key
98147

99148
if key in _SERVICE_KEYS and isinstance(value, str):
100-
if _is_template(value):
101-
unvalidated_templates[0] += 1
102-
else:
103-
refs.append(
104-
{"path": sub_path, "value": value, "kind": "service"}
105-
)
149+
_extract_service_ref(sub_path, value, refs, unvalidated_templates)
150+
continue
151+
152+
if key in _ENTITY_KEYS and _extract_entity_refs(
153+
sub_path, value, refs, unvalidated_templates
154+
):
106155
continue
107156

108-
if key in _ENTITY_KEYS:
109-
if isinstance(value, str):
110-
if _is_template(value):
111-
unvalidated_templates[0] += 1
112-
else:
113-
refs.append(
114-
{"path": sub_path, "value": value, "kind": "entity"}
115-
)
116-
continue
117-
if isinstance(value, list):
118-
for i, item in enumerate(value):
119-
if not isinstance(item, str):
120-
continue
121-
item_path = f"{sub_path}[{i}]"
122-
if _is_template(item):
123-
unvalidated_templates[0] += 1
124-
else:
125-
refs.append(
126-
{
127-
"path": item_path,
128-
"value": item,
129-
"kind": "entity",
130-
}
131-
)
132-
continue
133-
134-
# Neither a service nor an entity key: recurse so deeply
135-
# nested action blocks (choose/if/parallel/repeat) still
136-
# get walked.
157+
# Neither a service nor an entity key (or an entity key whose
158+
# value is neither str nor list): recurse so deeply nested
159+
# action blocks (choose/if/parallel/repeat) still get walked.
137160
_walk(value, sub_path)
138161

139162
elif isinstance(node, list):

0 commit comments

Comments
 (0)