Release 0.3.4 with external processing indexing.
Add virtual baseconf support for external data processors so reindex can discover and index them alongside regular src-based configurations, and update docs to use generic examples without workspace-specific names.
This commit is contained in:
+116
-2
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
@@ -53,6 +54,7 @@ OBJECT_TYPE_FOLDERS: dict[str, str] = {
|
||||
"XDTOPackages": "XDTOPackage",
|
||||
"Bots": "Bot",
|
||||
"ExternalDataSources": "ExternalDataSource",
|
||||
"ExternalDataProcessors": "ExternalDataProcessor",
|
||||
"Languages": "Language",
|
||||
}
|
||||
|
||||
@@ -92,6 +94,10 @@ TYPE_ALIASES: dict[str, str] = {
|
||||
"dataprocessors": "DataProcessor",
|
||||
"обработка": "DataProcessor",
|
||||
"обработки": "DataProcessor",
|
||||
"externaldataprocessor": "ExternalDataProcessor",
|
||||
"externaldataprocessors": "ExternalDataProcessor",
|
||||
"внешняяобработка": "ExternalDataProcessor",
|
||||
"внешниеобработки": "ExternalDataProcessor",
|
||||
"report": "Report",
|
||||
"reports": "Report",
|
||||
"отчет": "Report",
|
||||
@@ -171,6 +177,8 @@ class ConfigPaths:
|
||||
name: str
|
||||
root: Path
|
||||
src: Path
|
||||
source_kind: str = "src" # src | external_processor
|
||||
external_name: str = ""
|
||||
|
||||
|
||||
def project_root_from_here() -> Path:
|
||||
@@ -210,7 +218,12 @@ def resolve_config_name(name: str) -> str:
|
||||
|
||||
|
||||
def list_config_dirs(project_root: Path) -> list[str]:
|
||||
"""Все каталоги с выгрузкой 1С (<name>/src/) в корне проекта."""
|
||||
"""Все источники индексации в корне проекта.
|
||||
|
||||
Возвращает:
|
||||
- обычные конфигурации/расширения: <name> (если есть <name>/src/)
|
||||
- внешние обработки: <dir>.<Обработка> для каталогов вида <dir>/*.xml + <dir>/<Обработка>/
|
||||
"""
|
||||
if not project_root.is_dir():
|
||||
return []
|
||||
found: list[str] = []
|
||||
@@ -219,9 +232,52 @@ def list_config_dirs(project_root: Path) -> list[str]:
|
||||
continue
|
||||
if (child / "src").is_dir():
|
||||
found.append(child.name)
|
||||
continue
|
||||
if child.name.endswith(".ext"):
|
||||
found.extend(_discover_external_processors(child))
|
||||
return found
|
||||
|
||||
|
||||
_SAFE_NAME_RE = re.compile(r"^[A-Za-zА-Яа-яЁё0-9_]+$")
|
||||
|
||||
|
||||
def _looks_like_external_processor_xml(path: Path) -> bool:
|
||||
try:
|
||||
text = path.read_text(encoding="utf-8", errors="ignore")
|
||||
except OSError:
|
||||
return False
|
||||
probe = text[:8000]
|
||||
return "<ExternalDataProcessor" in probe and "<MetaDataObject" in probe
|
||||
|
||||
|
||||
def _discover_external_processor_entries(root: Path) -> list[tuple[str, str, Path]]:
|
||||
"""Найти внешние обработки под root (включая вложенные папки).
|
||||
|
||||
Возвращает кортежи: (virtual_name, processor_name, processor_root_dir).
|
||||
"""
|
||||
out: list[tuple[str, str, Path]] = []
|
||||
try:
|
||||
xml_files = sorted(root.rglob("*.xml"))
|
||||
except OSError:
|
||||
return out
|
||||
for xml in xml_files:
|
||||
parent = xml.parent
|
||||
name = xml.stem.strip()
|
||||
if not name or not _SAFE_NAME_RE.match(name):
|
||||
continue
|
||||
obj_dir = parent / name
|
||||
if not obj_dir.is_dir():
|
||||
continue
|
||||
if not _looks_like_external_processor_xml(xml):
|
||||
continue
|
||||
out.append((f"{root.name}.{name}", name, parent))
|
||||
return out
|
||||
|
||||
|
||||
def _discover_external_processors(root: Path) -> list[str]:
|
||||
return [name for name, _proc, _parent in _discover_external_processor_entries(root)]
|
||||
|
||||
|
||||
def resolve_object_type(name: str) -> str:
|
||||
raw = name.strip()
|
||||
if raw in FOLDER_BY_TYPE:
|
||||
@@ -240,11 +296,69 @@ def resolve_object_type(name: str) -> str:
|
||||
def discover_configs(project_root: Path, names: list[str] | None = None) -> list[ConfigPaths]:
|
||||
wanted = [resolve_config_name(n) for n in names] if names else list_config_dirs(project_root)
|
||||
found: list[ConfigPaths] = []
|
||||
seen: set[str] = set()
|
||||
|
||||
def _append(cfg: ConfigPaths) -> None:
|
||||
if cfg.name in seen:
|
||||
return
|
||||
seen.add(cfg.name)
|
||||
found.append(cfg)
|
||||
|
||||
for name in wanted:
|
||||
root = project_root / name
|
||||
src = root / "src"
|
||||
if src.is_dir():
|
||||
found.append(ConfigPaths(name=name, root=root, src=src))
|
||||
_append(ConfigPaths(name=name, root=root, src=src))
|
||||
continue
|
||||
# virtual baseconf для внешних обработок:
|
||||
# <dir>.<processor> → ищем <...>/<processor>.xml + <...>/<processor>/
|
||||
if "." in name:
|
||||
base, ext_name = name.rsplit(".", 1)
|
||||
ext_root = project_root / base
|
||||
if ext_root.is_dir():
|
||||
entries = _discover_external_processor_entries(ext_root)
|
||||
for _virtual_name, proc_name, proc_root in entries:
|
||||
if proc_name != ext_name:
|
||||
continue
|
||||
_append(
|
||||
ConfigPaths(
|
||||
name=name,
|
||||
root=proc_root,
|
||||
src=proc_root,
|
||||
source_kind="external_processor",
|
||||
external_name=proc_name,
|
||||
)
|
||||
)
|
||||
break
|
||||
else:
|
||||
# имя может уже быть каноническим virtual name
|
||||
for virtual_name, proc_name, proc_root in entries:
|
||||
if virtual_name != name:
|
||||
continue
|
||||
_append(
|
||||
ConfigPaths(
|
||||
name=virtual_name,
|
||||
root=proc_root,
|
||||
src=proc_root,
|
||||
source_kind="external_processor",
|
||||
external_name=proc_name,
|
||||
)
|
||||
)
|
||||
break
|
||||
if name in seen:
|
||||
continue
|
||||
# если передали только папку (например my-transfer.ext), развернуть все обработки
|
||||
if root.is_dir():
|
||||
for virtual_name, proc_name, proc_root in _discover_external_processor_entries(root):
|
||||
_append(
|
||||
ConfigPaths(
|
||||
name=virtual_name,
|
||||
root=proc_root,
|
||||
src=proc_root,
|
||||
source_kind="external_processor",
|
||||
external_name=proc_name,
|
||||
)
|
||||
)
|
||||
return found
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user