Files
index/index_1c.py
T
mihailkudravcev a9d1215820 Release 0.2.0: object tree, refs/modules options, docs
Add query object (--clear), modules -n, composite refs labels,
FillChecking/TypeSet parsing, VERSION/CHANGELOG and --version.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-16 16:37:41 +03:00

225 lines
7.8 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Переиндексация метаданных и модулей конфигураций 1С → cache/1c_meta/index.sqlite.
Параметры:
--config, -c файл настроек утилиты (JSON)
--baseconf, -b какие выгрузки 1С индексировать (crm3-26, target, …)
Примеры:
python tools/index/index_1c.py reindex -j 12
python tools/index/index_1c.py reindex --full -j 12
python tools/index/index_1c.py reindex --full -b crm3-26 -j 12
python tools/index/index_1c.py reindex -b target -b ws-rhana -t Documents,Catalogs
python tools/index/index_1c.py status
python tools/index/index_1c.py list
Поиск: python tools/index/query_1c.py …
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
if str(HERE) not in sys.path:
sys.path.insert(0, str(HERE))
from index1c.build import build_project_index, default_workers # noqa: E402
from index1c import read_version_file # noqa: E402
from index1c.cli import ( # noqa: E402
BaseconfError,
add_baseconf_args,
add_tool_args,
handle_baseconf_error,
index_db_missing_message,
resolve_project_root,
validate_baseconfs,
)
from index1c.config import ( # noqa: E402
CONFIG_ALIASES,
DEFAULT_SKIP_TYPES,
cache_dir,
discover_configs,
resolve_object_type,
)
from index1c import db as dbmod # noqa: E402
def _parse_types(raw: str | None) -> set[str] | None:
if not raw:
return None
types: set[str] = set()
for part in raw.replace(";", ",").split(","):
part = part.strip()
if not part:
continue
types.add(resolve_object_type(part))
return types or None
def _select_configs_for_reindex(args: argparse.Namespace, root: Path) -> list:
"""Какие конфигурации 1С индексировать."""
if args.baseconf:
try:
names = validate_baseconfs(root, args.baseconf, require_indexed=False)
except BaseconfError as e:
print(str(e), file=sys.stderr)
sys.exit(e.exit_code)
return discover_configs(root, names)
# без -b: все известные с src/
return discover_configs(root, None)
def cmd_reindex(args: argparse.Namespace) -> int:
root = resolve_project_root(args)
configs = _select_configs_for_reindex(args, root)
if not configs:
print(
"Нет конфигураций для индексации (нужна папка <name>/src/).\n"
"Укажите -b crm3-26 или проверьте: python tools/index/index_1c.py list",
file=sys.stderr,
)
return 1
types = _parse_types(args.types)
skip = set(DEFAULT_SKIP_TYPES)
if args.include_skipped:
skip.clear()
if args.skip_types:
for t in args.skip_types.replace(";", ",").split(","):
t = t.strip()
if t:
skip.add(resolve_object_type(t))
workers = args.workers if args.workers and args.workers > 0 else default_workers()
# --full без -b → пересоздать всю БД
wipe_db = bool(args.full and not args.baseconf)
print(
f"Режим: {'full-wipe' if wipe_db else ('full' if args.full else 'incremental')}, "
f"workers={workers}, baseconf={[c.name for c in configs]}, modules={not args.no_modules}"
)
summary = build_project_index(
configs,
root,
full=args.full or wipe_db,
wipe_db=wipe_db,
types=types,
skip_types=skip,
index_modules=not args.no_modules,
workers=workers,
write_md=args.md,
)
print(
f"Готово: {summary['db']} ({summary['elapsed_sec']}s) "
f"meta+{summary['meta_parsed']}/skip{summary['meta_skipped']} "
f"mod+{summary['modules_parsed']}/skip{summary['modules_skipped']} "
f"removed={summary['files_removed']} err={summary['errors']}"
)
return 0
def cmd_status(args: argparse.Namespace) -> int:
root = resolve_project_root(args)
db_path = dbmod.global_db_path(cache_dir(root))
if not db_path.is_file():
print(index_db_missing_message(root), file=sys.stderr)
return 1
conn = dbmod.connect(db_path, readonly=True)
try:
print(f"БД: {db_path} ({db_path.stat().st_size // (1024 * 1024)} МБ)")
for row in conn.execute("SELECT key, value FROM meta ORDER BY key"):
print(f" meta.{row['key']} = {row['value']}")
print("Конфигурации 1С в индексе (--baseconf):")
for c in dbmod.list_configs(conn):
print(
f"- {c['name']}: objects={c['objects']} fields={c['fields']} "
f"refs={c['refs']} modules={c['modules']} @ {c['updated_at']}"
)
finally:
conn.close()
return 0
def cmd_list_configs(args: argparse.Namespace) -> int:
root = resolve_project_root(args)
found = discover_configs(root, None)
print("Выгрузки 1С в репозитории (для --baseconf / -b):")
for c in found:
aliases = [k for k, v in CONFIG_ALIASES.items() if v == c.name]
alias_s = f" алиасы: {', '.join(aliases)}" if aliases else ""
print(f"- {c.name}{alias_s}")
db_path = dbmod.global_db_path(cache_dir(root))
if db_path.is_file():
conn = dbmod.connect(db_path, readonly=True)
try:
print("\nПроиндексировано (в index.sqlite):")
for c in dbmod.list_configs(conn):
print(f"- {c['name']}")
finally:
conn.close()
else:
print(f"\nИндекс отсутствует. {index_db_missing_message(root)}")
return 0
def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(
description="Построение единого SQLite-индекса метаданных и BSL-модулей 1С.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=(
"Конфигурация 1С: --baseconf (-b). Файл настроек утилиты: --config (-c).\n"
"Алиасы baseconf: target→crm3-26, source→crm3-dev"
),
)
p.add_argument(
"--version",
action="version",
version=f"%(prog)s {read_version_file()}",
)
add_tool_args(p)
sub = p.add_subparsers(dest="cmd", required=True)
r = sub.add_parser("reindex", help="Построить / обновить index.sqlite")
add_baseconf_args(r)
r.add_argument("--types", "-t", help="Только типы: Documents,Catalogs,рс,рн,…")
r.add_argument("--skip-types", help="Дополнительно пропустить типы")
r.add_argument("--include-skipped", action="store_true")
r.add_argument(
"--full",
action="store_true",
help="Полная пересборка (вся БД или только указанные -b)",
)
r.add_argument("--no-modules", action="store_true", help="Не индексировать .bsl")
r.add_argument(
"--workers",
"-j",
type=int,
default=0,
help=f"Потоков (по умолчанию {default_workers()})",
)
r.add_argument("--md", action="store_true", help="Markdown в cache/1c_meta/md/")
r.set_defaults(func=cmd_reindex)
st = sub.add_parser("status", help="Состояние index.sqlite")
st.set_defaults(func=cmd_status)
lc = sub.add_parser("list", help="Выгрузки в репозитории и в индексе")
lc.set_defaults(func=cmd_list_configs)
return p
def main(argv: list[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
return int(args.func(args))
if __name__ == "__main__":
raise SystemExit(main())