Files
llm/plugins/1c/parser/common_command.py
T

90 lines
2.8 KiB
Python

"""Pure reverse index for 1C common-command group membership."""
from __future__ import annotations
import re
from collections.abc import Iterable, Mapping
from typing import Any
from .payload import decode_payload_lossless, parse_brace_text
_GUID_RE = re.compile(
r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
)
def _tree_item_at_path(tree: Any, path: tuple[int, ...]) -> Any | None:
node = tree
for index in path:
if not isinstance(node, dict) or not isinstance(node.get("items"), list):
return None
items = node["items"]
if index < 0 or index >= len(items):
return None
node = items[index]
return node
def _tree_scalar_at_path(tree: Any, path: tuple[int, ...]) -> str:
node = _tree_item_at_path(tree, path)
if isinstance(node, dict) and node.get("type") in {"atom", "string"}:
return str(node.get("value") or "")
return ""
def common_command_group_guid(tree: Any) -> str | None:
"""Return the group GUID stored in an observed CommonCommand Config tree."""
body = _tree_item_at_path(tree, (1, 1, 2))
group_guid = _tree_scalar_at_path(body, (7, 1)).strip().lower()
return group_guid if _GUID_RE.fullmatch(group_guid) else None
def parse_common_command_tree(data: bytes) -> Any | None:
"""Decode a CommonCommand payload without raising on unsupported data."""
try:
decoded = decode_payload_lossless(data)
text = decoded.get("text")
if not text or "{" not in text:
return None
return parse_brace_text(text)
except Exception:
return None
def index_common_command_groups(
commands: Iterable[Mapping[str, Any]],
payloads: Mapping[str, bytes],
) -> dict[str, Any]:
"""Build ``CommandGroup GUID -> CommonCommand rows`` from Config payloads."""
command_rows = [dict(item) for item in commands]
normalized_payloads = {str(key).strip().lower(): value for key, value in payloads.items()}
groups: dict[str, list[dict[str, Any]]] = {}
source_missing = 0
undecodable = 0
unassigned = 0
for item in command_rows:
guid = str(item.get("guid") or "").strip().lower()
data = normalized_payloads.get(guid)
if not data:
source_missing += 1
continue
tree = parse_common_command_tree(data)
if tree is None:
undecodable += 1
continue
group_guid = common_command_group_guid(tree)
if group_guid is None:
unassigned += 1
continue
groups.setdefault(group_guid, []).append(item)
return {
"groups": groups,
"scanned": len(command_rows),
"source_missing": source_missing,
"undecodable": undecodable,
"unassigned": unassigned,
}