fix(py-порты): ошибки печатать в тот же поток, что и PS

Двадцать один py-порт печатал ошибки в stderr, тогда как их PS-мастера пишут
через Write-Host в stdout. Счётчики совпадали один в один (14↔14, 19↔19,
13↔13) — сообщения были те же, разъехался только поток. Это нарушало
соответствие из docs/python-porting-guide.md, где Write-Host сопоставлен
обычному print.

Это не косметика. Харнесс не чередует потоки, а группирует: сначала весь
stderr, потом весь stdout. Из-за этого в py-порте вердикт «Error dumping
configuration (code: 1)» печатался ПЕРЕД строками, которые его объясняют, а
причина из лога платформы оказывалась в самом низу — причинный порядок вывода
переворачивался. Порт, работающий на macOS, читался хуже того, что работает на
Windows.

Тесты этого не ловили по построению: текст ошибки сверяют только кейсы со
строковым expectError, а он смотрит в stderr — потому такие кейсы есть лишь у
семейства, где потоки сходятся, а в db-* их ноль.

Добавлен гард check-error-streams.mjs: нет записи в stderr в PS-порте — не
должно быть и в py, и симметрично. Он сразу нашёл пять навыков сверх тех, что
я насчитал вручную, и отсеял два ложных срабатывания (в meta-remove слово
Write-Error стоит в комментарии «почему НЕ Write-Error»).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-23 19:03:34 +03:00
co-authored by Claude Opus 5
parent fdeae5c87f
commit 4f61ef77ca
25 changed files with 279 additions and 253 deletions
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# subsystem-info v1.5 — Compact summary of 1C subsystem structure
# subsystem-info v1.6 — Compact summary of 1C subsystem structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -105,7 +105,7 @@ def load_subsystem_xml(xml_path):
doc_root = tree.getroot()
sub = doc_root.find("md:Subsystem", NS)
if sub is None:
print(f"[ERROR] Not a valid subsystem XML: {xml_path}", file=sys.stderr)
print(f"[ERROR] Not a valid subsystem XML: {xml_path}")
sys.exit(1)
return {"Doc": doc_root, "Sub": sub}
@@ -408,7 +408,7 @@ if args.Mode == "tree":
root_dir = subsystem_path
else:
if not os.path.isfile(subsystem_path):
print(f"[ERROR] File not found: {subsystem_path}", file=sys.stderr)
print(f"[ERROR] File not found: {subsystem_path}")
sys.exit(1)
root_xml = subsystem_path
@@ -488,7 +488,7 @@ if args.Mode == "tree":
if args.Name:
xml_files = [f for f in xml_files if os.path.splitext(f)[0] == args.Name]
if not xml_files:
print(f"[ERROR] Subsystem '{args.Name}' not found in {root_dir}", file=sys.stderr)
print(f"[ERROR] Subsystem '{args.Name}' not found in {root_dir}")
sys.exit(1)
for i, fname in enumerate(xml_files):
build_tree_entry(os.path.join(root_dir, fname), "", i == len(xml_files) - 1, True)
@@ -500,7 +500,7 @@ elif args.Mode == "ci":
# Mode: ci -- CommandInterface.xml
# ============================================================
if os.path.isdir(subsystem_path):
print("[ERROR] ci mode requires a subsystem .xml file, not a directory", file=sys.stderr)
print("[ERROR] ci mode requires a subsystem .xml file, not a directory")
sys.exit(1)
# File not found -- check Dir/Name/Name.xml -> Dir/Name.xml
if not os.path.isfile(subsystem_path):
@@ -511,7 +511,7 @@ elif args.Mode == "ci":
if os.path.isfile(c):
subsystem_path = c
if not os.path.isfile(subsystem_path):
print(f"[ERROR] File not found: {subsystem_path}", file=sys.stderr)
print(f"[ERROR] File not found: {subsystem_path}")
sys.exit(1)
parsed = load_subsystem_xml(subsystem_path)
@@ -535,7 +535,7 @@ else:
elif os.path.isfile(sibling):
subsystem_path = sibling
else:
print(f"[ERROR] No {dir_name}.xml found in directory. Use -Mode tree for directory listing.", file=sys.stderr)
print(f"[ERROR] No {dir_name}.xml found in directory. Use -Mode tree for directory listing.")
sys.exit(1)
# File not found -- check Dir/Name/Name.xml -> Dir/Name.xml
@@ -547,7 +547,7 @@ else:
if os.path.isfile(c):
subsystem_path = c
if not os.path.isfile(subsystem_path):
print(f"[ERROR] File not found: {subsystem_path}", file=sys.stderr)
print(f"[ERROR] File not found: {subsystem_path}")
sys.exit(1)
parsed = load_subsystem_xml(subsystem_path)