Load EDT form elements on demand
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-21 06:57:06 +03:00
parent 7d4d9917dd
commit 8b9a076d86
4 changed files with 209 additions and 9 deletions
@@ -1,7 +1,7 @@
from __future__ import annotations
import hashlib
from pathlib import Path
from pathlib import Path, PurePosixPath
import re
import xml.etree.ElementTree as ET
@@ -362,13 +362,13 @@ def _walk_xml_objects(
if right is not None:
result.append(right)
elif object_kind is not None:
name = _xml_name(element)
name = _xml_name(element, source_path=source_path)
if name:
xml_object = OneCXmlObject(
source_path=source_path,
object_kind=object_kind,
name=name,
qualified_name=_xml_qualified_name(element, name, object_kind, parent_qualified_name),
qualified_name=_xml_qualified_name(element, name, object_kind, parent_qualified_name, source_path),
attributes=_xml_attributes(element),
)
result.append(xml_object)
@@ -1332,7 +1332,7 @@ def _xml_type_name(element: ET.Element) -> str:
return ""
def _xml_name(element: ET.Element) -> str:
def _xml_name(element: ET.Element, *, source_path: str = "") -> str:
for key in ("name", "Name", "Имя"):
if key in element.attrib:
return element.attrib[key]
@@ -1340,6 +1340,9 @@ def _xml_name(element: ET.Element) -> str:
if _local_name(child.tag).lower() in {"name", "имя"} and child.text:
return child.text.strip()
tag = _local_name(element.tag).lower()
edt_form = _edt_form_context_from_path(source_path)
if tag == "form" and edt_form is not None:
return edt_form[0]
fallback_keys = {
"urltemplate": ("template", "url", "path", "Шаблон", "URL"),
"urltemplates": ("template", "url", "path", "Шаблон", "URL"),
@@ -1388,6 +1391,7 @@ def _xml_qualified_name(
name: str,
object_kind: str,
parent_qualified_name: str | None,
source_path: str = "",
) -> str:
for key in ("qualifiedName", "QualifiedName", "ПолноеИмя"):
if key in element.attrib:
@@ -1395,6 +1399,10 @@ def _xml_qualified_name(
for child in _xml_property_children(element):
if _local_name(child.tag).lower() in {"qualifiedname", "полноеимя"} and child.text:
return child.text.strip()
if object_kind == "FORM" and parent_qualified_name is None:
edt_form = _edt_form_context_from_path(source_path)
if edt_form is not None:
return edt_form[1]
if parent_qualified_name:
if object_kind in _ROOT_METADATA_OBJECT_KINDS and object_kind not in {"PROJECT", "ROLE"}:
prefix = _QUALIFIED_PREFIX_BY_KIND.get(object_kind, object_kind)
@@ -1407,6 +1415,48 @@ def _xml_qualified_name(
return name
_EDT_OWNER_PREFIX_BY_DIRECTORY = {
"AccountingRegisters": "РегистрБухгалтерии",
"AccumulationRegisters": "РегистрНакопления",
"BusinessProcesses": "БизнесПроцесс",
"CalculationRegisters": "РегистрРасчета",
"Catalogs": "Справочник",
"ChartsOfAccounts": "ПланСчетов",
"ChartsOfCalculationTypes": "ПланВидовРасчета",
"ChartsOfCharacteristicTypes": "ПланВидовХарактеристик",
"DataProcessors": "Обработка",
"DocumentJournals": "ЖурналДокументов",
"Documents": "Документ",
"Enums": "Перечисление",
"ExchangePlans": "ПланОбмена",
"ExternalDataSources": "ВнешнийИсточникДанных",
"InformationRegisters": "РегистрСведений",
"Reports": "Отчет",
"Tasks": "Задача",
}
def _edt_form_context_from_path(source_path: str) -> tuple[str, str] | None:
if not source_path or PurePosixPath(source_path).name.casefold() != "form.form":
return None
parts = PurePosixPath(source_path).parts
try:
forms_index = parts.index("Forms")
except ValueError:
forms_index = -1
if forms_index > 1 and forms_index + 1 < len(parts):
owner_directory = parts[forms_index - 2]
owner_name = parts[forms_index - 1]
form_name = parts[forms_index + 1]
owner_prefix = _EDT_OWNER_PREFIX_BY_DIRECTORY.get(owner_directory)
if owner_prefix:
return form_name, f"{owner_prefix}.{owner_name}.{form_name}"
if len(parts) >= 3 and parts[-3] == "CommonForms":
form_name = parts[-2]
return form_name, f"ОбщаяФорма.{form_name}"
return None
def _xml_attributes(element: ET.Element) -> dict:
attributes = dict(element.attrib)
for key, value in element.attrib.items():
@@ -1445,10 +1495,18 @@ def _xml_nested_text_value(element: ET.Element) -> str:
return localized.get("ru") or localized.get("ru_RU") or next(iter(localized.values()))
if _local_name(element.tag).lower() == "value":
return _element_text_content(element)
path_segments = [
_element_text_content(child)
for child in element
if _local_name(child.tag).lower() in {"segment", "segments", "pathsegment"}
]
path_segments = [value for value in path_segments if value]
if path_segments:
return ".".join(path_segments)
values = [
_element_text_content(child)
for child in element
if _local_name(child.tag).lower() in {"value", "text", "строка", "представление"}
if _local_name(child.tag).lower() in {"value", "text", "строка", "представление", "caption"}
]
values = [value for value in values if value]
if values: