199 lines
5.5 KiB
RPMSpec
199 lines
5.5 KiB
RPMSpec
# -*- mode: python ; coding: utf-8 -*-
|
||
"""Faster onefile freeze: fonts + plantuml.jar + optional Graphviz + onefile.
|
||
|
||
Keeps matplotlib (system font lookup) and bundles plantuml.jar.
|
||
Graphviz (vendor/) is included when present — for offline DFD.
|
||
Speeds Analysis by pinning the Agg backend, skipping duplicate pygments
|
||
collection (the stock hook already pulls all lexers), and not probing Qt/Gtk.
|
||
"""
|
||
import os
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
from PyInstaller.utils.hooks import (
|
||
collect_data_files,
|
||
collect_dynamic_libs,
|
||
collect_submodules,
|
||
)
|
||
|
||
# Isolated matplotlib hook subprocesses inherit this and skip GUI backend probes.
|
||
os.environ["MPLBACKEND"] = "Agg"
|
||
|
||
ROOT = Path(SPECPATH).resolve()
|
||
sys.path.insert(0, str(ROOT / "scripts"))
|
||
from pyi_bundle import collect_tkinterdnd2, prepare_tcltk_env, sanitize_analysis # noqa: E402
|
||
|
||
prepare_tcltk_env()
|
||
|
||
datas = [
|
||
(str(ROOT / "md2gost" / "Template.docx"), "md2gost"),
|
||
(str(ROOT / "md2gost" / "TitleTemplate.docx"), "md2gost"),
|
||
(str(ROOT / "md2gost" / "mml2omml"), "md2gost"),
|
||
(str(ROOT / "md2gost" / "diagrams"), "md2gost/diagrams"),
|
||
(str(ROOT / "prompts"), "prompts"),
|
||
(str(ROOT / "docs"), "docs"),
|
||
]
|
||
_plantuml = ROOT / "md2gost" / "vendor" / "plantuml.jar"
|
||
if not _plantuml.is_file():
|
||
raise SystemExit(
|
||
"md2gost.fast.spec: нет md2gost/vendor/plantuml.jar — "
|
||
"сначала scripts/fetch_plantuml.py (jar обязателен в portable exe)"
|
||
)
|
||
datas.append((str(_plantuml), "md2gost/vendor"))
|
||
_graphviz = ROOT / "md2gost" / "vendor" / "graphviz"
|
||
if (_graphviz / "bin" / "dot.exe").is_file() or (_graphviz / "bin" / "dot").is_file():
|
||
from md2gost.dfd import strip_graphviz_tcl_libs
|
||
|
||
strip_graphviz_tcl_libs(_graphviz)
|
||
datas.append((str(_graphviz), "md2gost/vendor/graphviz"))
|
||
|
||
binaries = []
|
||
hiddenimports = collect_submodules("md2gost")
|
||
hiddenimports += collect_submodules("word2md")
|
||
try:
|
||
hiddenimports += collect_submodules("data_flow_diagram")
|
||
except Exception:
|
||
pass
|
||
|
||
datas += collect_data_files("certifi")
|
||
datas += collect_data_files("lxml")
|
||
datas += collect_data_files("latex2mathml")
|
||
datas += collect_data_files("docx")
|
||
# Explicit mpl-data so DejaVu + matplotlib font cache files are always in the exe.
|
||
# hook-matplotlib.py also collects this; PyInstaller dedupes by dest path.
|
||
datas += collect_data_files("matplotlib", includes=["mpl-data/**"])
|
||
for _pkg in ("mermaidx", "termaid", "quickjs", "quickjs_ng", "resvg_py", "playwright"):
|
||
try:
|
||
datas += collect_data_files(_pkg)
|
||
except Exception:
|
||
pass
|
||
|
||
for pkg in ("lxml", "freetype", "quickjs", "resvg_py"):
|
||
try:
|
||
binaries += collect_dynamic_libs(pkg)
|
||
except Exception:
|
||
pass
|
||
|
||
hiddenimports += [
|
||
"lxml",
|
||
"lxml.etree",
|
||
"lxml._elementpath",
|
||
"PIL",
|
||
"PIL.Image",
|
||
"PIL.PngImagePlugin",
|
||
"pygments",
|
||
"pygments.lexers",
|
||
"pygments.formatters",
|
||
"freetype",
|
||
"docx",
|
||
"docxcompose",
|
||
"docxcompose.composer",
|
||
"marko",
|
||
"marko.ext.gfm",
|
||
"latex2mathml",
|
||
"latex2mathml.converter",
|
||
"requests",
|
||
"certifi",
|
||
"matplotlib",
|
||
"matplotlib.font_manager",
|
||
"matplotlib.ft2font",
|
||
"tkinter",
|
||
"tkinter.filedialog",
|
||
"tkinter.messagebox",
|
||
"tkinter.ttk",
|
||
"mermaidx",
|
||
"mermaidx.diagram",
|
||
"mermaidx.engines",
|
||
"mermaidx.engines.quickjs_engine",
|
||
"termaid",
|
||
"quickjs",
|
||
"resvg_py",
|
||
"playwright",
|
||
"playwright.sync_api",
|
||
]
|
||
# Do NOT collect_submodules("pygments.lexers") here — hook-pygments.py already
|
||
# collects all lexers/formatters/styles once during Analysis.
|
||
_dnd_datas, _dnd_hidden = collect_tkinterdnd2()
|
||
datas += _dnd_datas
|
||
hiddenimports += _dnd_hidden
|
||
|
||
excludes = [
|
||
"pytest",
|
||
"PyQt5",
|
||
"PyQt6",
|
||
"PySide2",
|
||
"PySide6",
|
||
"IPython",
|
||
"jupyter",
|
||
"notebook",
|
||
"zmq",
|
||
"scipy",
|
||
"pandas",
|
||
"tornado",
|
||
"numpy.tests",
|
||
"matplotlib.tests",
|
||
"matplotlib.testing",
|
||
"matplotlib.backends.qt_compat",
|
||
"matplotlib.backends.backend_qtagg",
|
||
"matplotlib.backends.backend_qtcairo",
|
||
"matplotlib.backends.backend_qt5agg",
|
||
"matplotlib.backends.backend_qt5cairo",
|
||
"matplotlib.backends.backend_qt5",
|
||
"matplotlib.backends.backend_qt",
|
||
"matplotlib.backends.backend_gtk3",
|
||
"matplotlib.backends.backend_gtk3agg",
|
||
"matplotlib.backends.backend_gtk3cairo",
|
||
"matplotlib.backends.backend_gtk4",
|
||
"matplotlib.backends.backend_gtk4agg",
|
||
"matplotlib.backends.backend_gtk4cairo",
|
||
"matplotlib.backends.backend_macosx",
|
||
"matplotlib.backends.backend_tkagg",
|
||
"matplotlib.backends.backend_tkcairo",
|
||
"matplotlib.backends.backend_wx",
|
||
"matplotlib.backends.backend_wxagg",
|
||
"matplotlib.backends.backend_wxcairo",
|
||
"matplotlib.backends.backend_nbagg",
|
||
"matplotlib.backends.backend_webagg",
|
||
"PIL.ImageQt",
|
||
]
|
||
|
||
a = Analysis(
|
||
[str(ROOT / "scripts" / "md2gost_exe.py")],
|
||
pathex=[str(ROOT)],
|
||
binaries=binaries,
|
||
datas=datas,
|
||
hiddenimports=hiddenimports,
|
||
hookspath=[],
|
||
hooksconfig={
|
||
"matplotlib": {"backends": "Agg"},
|
||
},
|
||
runtime_hooks=[
|
||
str(ROOT / "scripts" / "pyi_rth_tcltk.py"),
|
||
str(ROOT / "scripts" / "pyi_rth_mplbackend.py"),
|
||
],
|
||
excludes=excludes,
|
||
noarchive=False,
|
||
)
|
||
sanitize_analysis(a)
|
||
|
||
pyz = PYZ(a.pure)
|
||
|
||
exe = EXE(
|
||
pyz,
|
||
a.scripts,
|
||
a.binaries,
|
||
a.datas,
|
||
[],
|
||
name="md2gost",
|
||
debug=False,
|
||
bootloader_ignore_signals=False,
|
||
strip=False,
|
||
upx=False,
|
||
console=False,
|
||
disable_windowed_traceback=False,
|
||
argv_emulation=False,
|
||
target_arch=None,
|
||
codesign_identity=None,
|
||
entitlements_file=None,
|
||
)
|