fix(python): add stdout UTF-8 encoding for Windows compatibility

Python on Windows defaults to cp1251 for piped stdout, which cannot
handle Unicode box-drawing characters used in info/analysis output.
Added sys.stdout.reconfigure(encoding="utf-8") to all 59 Python scripts.

Tested on real config data: epf-init, epf-validate, cf-info, cf-validate,
meta-info, form-info, role-info, skd-info, subsystem-info — all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-25 16:29:26 +03:00
co-authored by Claude Opus 4.6
parent 86a959a354
commit d6abb2b651
59 changed files with 31076 additions and 31006 deletions
@@ -138,6 +138,7 @@ def save_xml_bom(tree, path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Edit 1C configuration root (Configuration.xml)", allow_abbrev=False)
parser.add_argument("-ConfigPath", required=True)
parser.add_argument("-DefinitionFile", default=None)
@@ -8,6 +8,8 @@ import sys
from collections import OrderedDict
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# --- Argument parsing ---
parser = argparse.ArgumentParser(description="Analyze 1C configuration structure", allow_abbrev=False)
parser.add_argument("-ConfigPath", required=True, help="Path to Configuration.xml or directory")
@@ -15,6 +15,7 @@ def write_utf8_bom(path, content):
f.write(content)
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Create empty 1C configuration scaffold', allow_abbrev=False)
parser.add_argument('-Name', dest='Name', required=True)
parser.add_argument('-Synonym', dest='Synonym', default=None)
@@ -148,6 +148,7 @@ class Reporter:
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C configuration XML structure', allow_abbrev=False
)
@@ -312,6 +312,7 @@ def new_guid():
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Borrow objects from configuration into extension", allow_abbrev=False)
parser.add_argument("-ExtensionPath", required=True)
parser.add_argument("-ConfigPath", required=True)
@@ -462,6 +462,7 @@ def mode_b(objects, extension_path, config_path):
# --- Main ---
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Analyze and compare 1C configuration extension (CFE)", allow_abbrev=False)
parser.add_argument("-ExtensionPath", required=True, help="Path to extension dump root")
parser.add_argument("-ConfigPath", required=True, help="Path to base config dump root")
@@ -16,6 +16,7 @@ def write_utf8_bom(path, content):
f.write(content)
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Create 1C configuration extension scaffold', allow_abbrev=False)
parser.add_argument('-Name', dest='Name', required=True)
parser.add_argument('-Synonym', dest='Synonym', default=None)
@@ -9,6 +9,7 @@ import xml.etree.ElementTree as ET
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Generate method interceptor for 1C extension (CFE)",
allow_abbrev=False,
@@ -133,6 +133,7 @@ class Reporter:
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C configuration extension XML structure (CFE)', allow_abbrev=False
)
@@ -31,6 +31,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Create 1C information base",
allow_abbrev=False,
@@ -31,6 +31,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Dump 1C configuration to CF file",
allow_abbrev=False,
@@ -33,6 +33,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Dump 1C configuration to XML files",
allow_abbrev=False,
@@ -31,6 +31,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Load 1C configuration from CF file",
allow_abbrev=False,
@@ -55,6 +55,7 @@ def run_git(config_dir, git_args):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Load Git changes into 1C database",
allow_abbrev=False,
@@ -33,6 +33,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Load 1C configuration from XML files",
allow_abbrev=False,
+1
View File
@@ -28,6 +28,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Launch 1C:Enterprise",
allow_abbrev=False,
@@ -31,6 +31,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Update 1C database configuration",
allow_abbrev=False,
@@ -28,6 +28,7 @@ def write_text_with_bom(path, text):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Add managed form to 1C processor", allow_abbrev=False)
parser.add_argument("-ProcessorName", required=True)
parser.add_argument("-FormName", required=True)
@@ -33,6 +33,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Build external data processor or report (EPF/ERF) from XML sources",
allow_abbrev=False,
@@ -33,6 +33,7 @@ def resolve_v8path(v8path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description="Dump external data processor or report (EPF/ERF) to XML sources",
allow_abbrev=False,
+1
View File
@@ -15,6 +15,7 @@ def write_utf8_bom(path, content):
f.write(content)
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Init 1C external data processor scaffold', allow_abbrev=False)
parser.add_argument('-Name', dest='Name', required=True)
parser.add_argument('-Synonym', dest='Synonym', default=None)
@@ -43,6 +43,7 @@ def localname(el):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Validate 1C external data processor/report structure", allow_abbrev=False)
parser.add_argument("-ObjectPath", required=True)
parser.add_argument("-MaxErrors", type=int, default=30)
+1
View File
@@ -15,6 +15,7 @@ def write_utf8_bom(path, content):
f.write(content)
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Init 1C external report scaffold', allow_abbrev=False)
parser.add_argument('-Name', dest='Name', required=True)
parser.add_argument('-Synonym', dest='Synonym', default=None)
@@ -31,6 +31,7 @@ def write_text_with_bom(path, text):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Add managed form to 1C config object", allow_abbrev=False)
parser.add_argument("-ObjectPath", required=True)
parser.add_argument("-FormName", required=True)
@@ -947,6 +947,7 @@ def emit_properties(lines, props, indent):
def main():
sys.stdout.reconfigure(encoding="utf-8")
global _next_id
parser = argparse.ArgumentParser(description='Compile 1C managed form from JSON', allow_abbrev=False)
@@ -8,6 +8,8 @@ import sys
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# ── arg parsing ──────────────────────────────────────────────
parser = argparse.ArgumentParser(allow_abbrev=False)
@@ -332,6 +332,7 @@ def build_tree(child_items_node, prefix, tree_lines):
# --- Main ---
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Analyze 1C managed form structure", allow_abbrev=False)
parser.add_argument("-FormPath", required=True, help="Path to Form.xml")
parser.add_argument("-Limit", type=int, default=150, help="Max lines to show")
@@ -23,6 +23,7 @@ def save_xml_with_bom(tree, path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Remove form from 1C object", allow_abbrev=False)
parser.add_argument("-ObjectName", "-ProcessorName", required=True)
parser.add_argument("-FormName", required=True)
@@ -19,6 +19,7 @@ def localname(el):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Validate 1C managed form", allow_abbrev=False)
parser.add_argument("-FormPath", required=True)
parser.add_argument("-MaxErrors", type=int, default=30)
@@ -27,6 +27,7 @@ def write_text_with_bom(path, text):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Add built-in help to 1C object", allow_abbrev=False)
parser.add_argument("-ObjectName", "-ProcessorName", required=True)
parser.add_argument("-Lang", default="ru")
@@ -10,6 +10,7 @@ so they never overlap with the form and remain readable at any grid density.
"""
import argparse
import os
import sys
from PIL import Image, ImageDraw, ImageFont
MARGIN_TOP = 20
@@ -17,6 +18,7 @@ MARGIN_LEFT = 24
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Overlay numbered grid on image")
parser.add_argument("image", help="Input image path")
parser.add_argument("-c", "--cols", type=int, default=50,
@@ -110,6 +110,7 @@ def find_command_by_name(section, cmd_name):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Edit 1C CommandInterface.xml", allow_abbrev=False)
parser.add_argument("-CIPath", required=True)
parser.add_argument("-DefinitionFile", default=None)
@@ -70,6 +70,7 @@ def find_duplicates(items):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C CommandInterface.xml structure', allow_abbrev=False
)
@@ -10,6 +10,8 @@ import sys
import uuid
import xml.etree.ElementTree as ET
sys.stdout.reconfigure(encoding="utf-8")
# ---------------------------------------------------------------------------
# Inline utilities
# ---------------------------------------------------------------------------
@@ -1971,6 +1971,7 @@ def save_xml(tree, path):
# ============================================================
def main():
sys.stdout.reconfigure(encoding="utf-8")
global xml_tree, xml_root, obj_element, obj_type, md_ns
global properties_el, child_objects_el, obj_name
global add_count, remove_count, modify_count, warn_count
@@ -7,6 +7,8 @@ import sys
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# ── arg parsing ──────────────────────────────────────────────
parser = argparse.ArgumentParser(allow_abbrev=False)
@@ -106,6 +106,7 @@ def save_xml_bom(tree, path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Remove metadata object from 1C configuration dump", allow_abbrev=False)
parser.add_argument("-ConfigDir", required=True)
parser.add_argument("-Object", required=True)
@@ -7,6 +7,8 @@ import sys
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# ── arg parsing ──────────────────────────────────────────────
parser = argparse.ArgumentParser(allow_abbrev=False)
@@ -19,6 +19,7 @@ def write_utf8_bom(path, content):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Compile 1C spreadsheet from JSON', allow_abbrev=False)
parser.add_argument('-JsonPath', type=str, required=True)
parser.add_argument('-OutputPath', type=str, required=True)
@@ -44,6 +44,7 @@ def int_of(node, default=0):
# --- Main ---
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Decompile 1C spreadsheet to JSON", allow_abbrev=False)
parser.add_argument("-TemplatePath", required=True, help="Path to Template.xml")
parser.add_argument("-OutputPath", default=None, help="Output JSON path (stdout if omitted)")
@@ -9,6 +9,8 @@ import re
import sys
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# --- Argument parsing ---
parser = argparse.ArgumentParser(description="Analyze 1C spreadsheet (MXL) structure", allow_abbrev=False)
parser.add_argument("-TemplatePath", default="", help="Path to Template.xml")
@@ -45,6 +45,7 @@ def int_text(node):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C spreadsheet document Template.xml', allow_abbrev=False
)
@@ -431,6 +431,7 @@ def parse_object_entry(entry):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Compile 1C role from JSON', allow_abbrev=False)
parser.add_argument('-JsonPath', type=str, required=True)
parser.add_argument('-OutputDir', type=str, required=True)
@@ -8,6 +8,8 @@ import sys
from collections import OrderedDict
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# --- Argument parsing ---
parser = argparse.ArgumentParser(description="Analyze 1C role rights", allow_abbrev=False)
parser.add_argument("-RightsPath", required=True, help="Path to Rights.xml")
@@ -174,6 +174,7 @@ def get_child_el(parent, local_name, ns):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C role Rights.xml structure', allow_abbrev=False
)
@@ -1317,6 +1317,7 @@ def emit_settings_variants(lines, defn):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Compile 1C DCS from JSON', allow_abbrev=False)
parser.add_argument('-DefinitionFile', type=str, default=None)
parser.add_argument('-Value', type=str, default=None)
@@ -8,6 +8,8 @@ import uuid
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# ── arg parsing ──────────────────────────────────────────────
VALID_OPS = [
@@ -266,6 +266,7 @@ def build_structure_tree(item_node, prefix, is_last, out_lines):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Analyze 1C DCS structure", allow_abbrev=False)
parser.add_argument("-TemplatePath", required=True)
parser.add_argument("-Mode", default="overview",
@@ -6,6 +6,8 @@ import sys
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# ── arg parsing ──────────────────────────────────────────────
parser = argparse.ArgumentParser(allow_abbrev=False)
@@ -45,6 +45,7 @@ def split_camel_case(name):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Compile 1C subsystem from JSON definition', allow_abbrev=False)
parser.add_argument('-DefinitionFile', type=str, default=None)
parser.add_argument('-Value', type=str, default=None)
@@ -129,6 +129,7 @@ def save_xml_bom(tree, path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Edit existing 1C subsystem XML", allow_abbrev=False)
parser.add_argument("-SubsystemPath", required=True)
parser.add_argument("-DefinitionFile", default=None)
@@ -9,6 +9,8 @@ import sys
from collections import OrderedDict
from lxml import etree
sys.stdout.reconfigure(encoding="utf-8")
# --- Argument parsing ---
parser = argparse.ArgumentParser(description="Analyze 1C subsystem structure", allow_abbrev=False)
parser.add_argument("-SubsystemPath", required=True, help="Path to subsystem XML or Subsystems/ directory")
@@ -61,6 +61,7 @@ def find_duplicates(items):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(
description='Validate 1C subsystem XML structure', allow_abbrev=False
)
@@ -36,6 +36,7 @@ def write_text_with_bom(path, text):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Add template to 1C object", allow_abbrev=False)
parser.add_argument("-ObjectName", "-ProcessorName", required=True)
parser.add_argument("-TemplateName", required=True)
@@ -23,6 +23,7 @@ def save_xml_with_bom(tree, path):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description="Remove template from 1C object", allow_abbrev=False)
parser.add_argument("-ObjectName", "-ProcessorName", required=True)
parser.add_argument("-TemplateName", required=True)
@@ -33,6 +33,7 @@ def get_httpd_by_exe(httpd_exe_norm):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Apache & 1C publication status', allow_abbrev=False)
parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)')
args = parser.parse_args()
@@ -60,6 +60,7 @@ def check_port_in_use(port):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Publish 1C infobase via Apache', allow_abbrev=False)
parser.add_argument('-V8Path', type=str, default='', help='Path to 1C platform bin directory (for wsap24.dll)')
parser.add_argument('-InfoBasePath', type=str, default='', help='Path to file infobase')
@@ -43,6 +43,7 @@ def get_all_httpd():
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Stop Apache HTTP Server', allow_abbrev=False)
parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)')
args = parser.parse_args()
@@ -36,6 +36,7 @@ def get_our_httpd(httpd_exe_norm):
def main():
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Remove 1C web publication', allow_abbrev=False)
parser.add_argument('-AppName', type=str, default='', help='Publication name')
parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)')