Files
Igor20264 510f7e7adf
Python application / build (push) Waiting to run
v0.5.2
Что то сделал
2026-09-08 19:37:54 +03:00

112 lines
3.3 KiB
Python

"""PyInstaller freeze helpers: pin CPython Tcl/Tk, drop Graphviz's copy."""
from __future__ import annotations
import os
import sys
from pathlib import Path
def _python_dll_dir() -> Path | None:
candidates = [
Path(sys.base_prefix) / "DLLs",
Path(sys.prefix) / "DLLs",
Path(sys.executable).resolve().parent / "DLLs",
Path(sys.executable).resolve().parent.parent / "DLLs",
]
for folder in candidates:
if (folder / "tcl86t.dll").is_file() or (folder / "tk86t.dll").is_file():
return folder
return None
def prepare_tcltk_env() -> None:
"""Make Analysis / isolated hook subprocesses see this interpreter's Tcl."""
dll_dir = _python_dll_dir()
prefix = Path(sys.base_prefix)
tcl_lib = prefix / "tcl" / "tcl8.6"
tk_lib = prefix / "tcl" / "tk8.6"
if not tcl_lib.is_dir() and dll_dir is not None:
tcl_lib = dll_dir.parent / "tcl" / "tcl8.6"
tk_lib = dll_dir.parent / "tcl" / "tk8.6"
if tcl_lib.is_dir():
os.environ["TCL_LIBRARY"] = str(tcl_lib)
if tk_lib.is_dir():
os.environ["TK_LIBRARY"] = str(tk_lib)
if dll_dir is not None:
os.environ["PATH"] = str(dll_dir) + os.pathsep + os.environ.get("PATH", "")
def collect_tkinterdnd2():
datas: list = []
hidden: list = ["tkinterdnd2", "tkinterdnd2.TkinterDnD"]
try:
from PyInstaller.utils.hooks import collect_data_files, collect_submodules
datas += collect_data_files("tkinterdnd2")
hidden = list(collect_submodules("tkinterdnd2")) or hidden
except Exception:
pass
return datas, hidden
def _toc_name(item) -> str:
dest = str(item[0]).replace("\\", "/")
return os.path.basename(dest).lower()
def _toc_blob(item) -> str:
dest = str(item[0]).replace("\\", "/").lower()
src = str(item[1]).replace("\\", "/").lower() if len(item) > 1 else ""
return dest + " " + src
def _graphviz_tcl_names() -> set[str]:
try:
from md2gost.dfd import GRAPHVIZ_TCL_DLL_NAMES
return {n.lower() for n in GRAPHVIZ_TCL_DLL_NAMES}
except Exception:
return {
"tcl86t.dll",
"tk86t.dll",
"tcl86.dll",
"tk86.dll",
"tcldot.dll",
"tcldot_builtin.dll",
"tclplan.dll",
"gdtclft.dll",
}
def _is_graphviz_tcl(item) -> bool:
if _toc_name(item) not in _graphviz_tcl_names():
return False
return "graphviz" in _toc_blob(item)
def _wrap_toc(items):
try:
from PyInstaller.building.datastruct import TOC
return TOC(items)
except Exception:
return items
def sanitize_analysis(a):
"""Drop Graphviz Tcl/Tk DLLs and force this CPython's tcl86t/tk86t into the exe."""
a.datas = _wrap_toc([x for x in a.datas if not _is_graphviz_tcl(x)])
binaries = [x for x in a.binaries if not _is_graphviz_tcl(x)]
dll_dir = _python_dll_dir()
pin = ("tcl86t.dll", "tk86t.dll", "zlib1.dll")
if dll_dir is not None:
pin_lower = {n.lower() for n in pin}
binaries = [x for x in binaries if _toc_name(x) not in pin_lower]
for name in pin:
path = dll_dir / name
if path.is_file():
binaries.append((name, str(path), "BINARY"))
a.binaries = _wrap_toc(binaries)
return a