SXXXXXXX_PyInstallerGUIWrapper/tools/spec_editor_demo.py

81 lines
3.1 KiB
Python

"""Demo script showing how to use `pyinstallerguiwrapper.spec_editor` to
inspect and modify a .spec AST.
Usage: run from repository root:
python tools/spec_editor_demo.py
It uses a small embedded sample spec (the same used previously) to show the
API and writes a modified .spec to a temp file named `modified_demo.spec`.
"""
import pathlib
import tempfile
from pyinstallerguiwrapper import spec_editor
SAMPLE_SPEC = '''# sample
block_cipher = None
a = Analysis(
pathex=['pyucc', '.', 'external\\python-tkinter-logger', 'external\\python-resource-monitor'],
binaries=[],
datas=[('PyUcc.ico', '.'), ('external\\python-tkinter-logger\\tkinter_logger.py', '.'), ('external\\python-resource-monitor\\resource_monitor.py', '.')],
hiddenimports=['tkinter_logger','resource_monitor','pyucc.core.differ'],
hookspath=[], runtime_hooks=[], excludes=[], cipher=block_cipher, noarchive=False, scripts=['pyucc\\__main__.py']
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='PyUcc', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, icon='PyUcc.ico', exclude_binaries=True)
coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, upx_exclude=[], name='PyUcc')
'''
def run_demo():
print('Parsing embedded sample spec...')
tree = spec_editor.parse_spec_from_string(SAMPLE_SPEC)
# Note: helper below expects ast.Module; parse_spec_to_ast_from_string returns that
print('Summary before change:')
print(spec_editor.inspect_spec_summary(tree))
# Add a hiddenimport entry (demonstrate modification)
print('\nAdding hiddenimport "my.added.module" to Analysis...')
# Retrieve existing hiddenimports node
analysis_calls = spec_editor.find_calls(tree, 'Analysis')
if analysis_calls:
call = analysis_calls[0]
# Build new hiddenimports list by inspecting existing or creating fresh
existing_node = spec_editor.get_keyword_value(call, 'hiddenimports')
if existing_node is None:
new_list = ['my.added.module']
else:
py_existing = spec_editor.ast_node_to_python(existing_node)
if isinstance(py_existing, list):
new_list = py_existing + ['my.added.module']
else:
new_list = ['my.added.module']
spec_editor.set_call_keyword(tree, 'Analysis', 'hiddenimports', new_list)
print('Modification applied.')
print('\nSummary after change:')
print(spec_editor.inspect_spec_summary(tree))
# Write out modified spec
out_path = pathlib.Path('modified_demo.spec')
src = spec_editor.ast_to_source(tree)
spec_editor.write_source_to_file(src, str(out_path))
print(f'Wrote modified spec to: {out_path.resolve()}')
def ast_unparse(node):
import ast
if hasattr(ast, 'unparse'):
return ast.unparse(node)
else:
try:
import astor
return astor.to_source(node)
except Exception:
return '<unparse unavailable>'
if __name__ == '__main__':
run_demo()