S7_snap7_Stremer_n_Recorder/main copy.spec

268 lines
7.1 KiB
Python

# -*- mode: python ; coding: utf-8 -*-
import os
import sys
block_cipher = None
# Analysis for main application (backend)
a_main = Analysis(
['main.py'],
pathex=[],
binaries=[
# Include snap7.dll - now confirmed to be in project root
('snap7.dll', '.'),
],
datas=[
# Include the entire frontend build
('frontend/dist', 'frontend/dist'),
# Include configuration directories and schemas
('config', 'config'),
# Include core modules
('core', 'core'),
# Include utils
('utils', 'utils'),
# Include translation files
('translation.json', '.'),
('i18n.js', '.'),
],
hiddenimports=[
# Flask and web dependencies
'jinja2.ext',
'flask',
'flask_cors',
'flask_socketio',
'socketio',
'werkzeug',
# JSON Schema validation
'jsonschema',
'jsonschema.validators',
'jsonschema._format',
'jsonschema._types',
# PLC and system dependencies
'snap7',
'psutil._pswindows',
'psutil._psutil_windows',
# Data processing
'pandas',
'numpy',
# Threading and networking
'threading',
'socket',
'json',
'csv',
'datetime',
'pathlib',
# Core modules (explicit imports)
'core.config_manager',
'core.plc_client',
'core.plc_data_streamer',
'core.event_logger',
'core.instance_manager',
'core.schema_manager',
'core.streamer',
'core.plot_manager',
'core.historical_cache',
'core.performance_monitor',
'core.priority_manager',
'core.rotating_logger',
# Utils modules
'utils.csv_validator',
'utils.json_manager',
'utils.symbol_loader',
'utils.symbol_processor',
'utils.instance_manager',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
# Exclude unnecessary packages to reduce size
'matplotlib',
'scipy',
'IPython',
'notebook',
'jupyter',
'tests',
'unittest',
'pydoc',
'doctest',
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
# Analysis for backend manager (watchdog)
a_manager = Analysis(
['backmanager.py'],
pathex=[],
binaries=[],
datas=[
# Include utils for instance management
('utils', 'utils'),
],
hiddenimports=[
# System and monitoring dependencies
'psutil',
'psutil._pswindows',
'psutil._psutil_windows',
'requests',
'subprocess',
'logging',
'json',
# Utils modules needed by manager
'utils.instance_manager',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
# Exclude heavy packages not needed by manager
'matplotlib',
'scipy',
'IPython',
'notebook',
'jupyter',
'flask',
'snap7',
'pandas',
'numpy',
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
# Build PYZ files
pyz_main = PYZ(a_main.pure, a_main.zipped_data, cipher=block_cipher)
pyz_manager = PYZ(a_manager.pure, a_manager.zipped_data, cipher=block_cipher)
# Build main backend executable
exe_main = EXE(
pyz_main,
a_main.scripts,
[],
exclude_binaries=True,
name='S7_Streamer_Logger',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True, # True para ver los logs del servidor en una consola.
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
# Build backend manager executable
exe_manager = EXE(
pyz_manager,
a_manager.scripts,
[],
exclude_binaries=True,
name='Backend_Manager',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
# Collect all files together - Only include executables and shared dependencies
coll = COLLECT(
exe_main,
exe_manager,
a_main.binaries,
a_main.zipfiles,
a_main.datas,
# Don't duplicate manager dependencies since they're minimal
strip=False,
upx=True,
upx_exclude=[],
name='main'
)
# Post-build: Copy config directory to the same level as the executable
import shutil
import os
def copy_config_external():
"""Copy config directory to external location for runtime access"""
try:
# Get absolute paths
current_dir = os.path.abspath('.')
source_config = os.path.join(current_dir, 'config')
dist_main_dir = os.path.join(current_dir, 'dist', 'main')
dest_config = os.path.join(dist_main_dir, 'config')
print(f"Current directory: {current_dir}")
print(f"Source config: {source_config}")
print(f"Destination config: {dest_config}")
# Ensure dist/main directory exists
os.makedirs(dist_main_dir, exist_ok=True)
# Remove existing config if present
if os.path.exists(dest_config):
shutil.rmtree(dest_config)
print(f"Removed existing config at: {dest_config}")
# Copy config directory to dist/main/config
if os.path.exists(source_config):
shutil.copytree(source_config, dest_config)
print(f"✓ Config directory copied to: {dest_config}")
return True
else:
print(f"✗ Source config directory not found: {source_config}")
return False
except Exception as e:
print(f"✗ Error copying config directory: {e}")
return False
# Execute the copy operation
copy_config_external()
def config_path(relative_path):
"""Get path to config file, checking external location first when running as executable"""
if getattr(sys, 'frozen', False):
# Running as executable - config should be at same level as executable
executable_dir = os.path.dirname(sys.executable)
external_config = os.path.join(executable_dir, 'config', relative_path)
if os.path.exists(external_config):
return external_config
# Fallback to internal config within _internal
internal_config = os.path.join(executable_dir, '_internal', 'config', relative_path)
if os.path.exists(internal_config):
return internal_config
raise FileNotFoundError(f"Configuration file not found: {relative_path}")
else:
# Running as script - use standard path
base_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(base_dir)
return os.path.join(project_root, 'config', relative_path)