# -*- mode: python ; coding: utf-8 -*- import os from PyInstaller.utils.hooks import collect_data_files, collect_submodules import glob block_cipher = None # Get the base path base_path = '.' # Collect all Odoo submodules dynamically try: odoo_submodules = collect_submodules('odoo') addon_submodules = collect_submodules('odoo.addons') except Exception: odoo_submodules = [] addon_submodules = [] # Collect data files from various sources try: babel_data = collect_data_files('babel') reportlab_data = collect_data_files('reportlab') except Exception: babel_data = [] reportlab_data = [] # Function to safely add data files that exist def safe_add_data(source_pattern, dest_folder): data_files = [] try: if '*' in source_pattern: # Handle glob patterns matches = glob.glob(os.path.join(base_path, source_pattern)) for match in matches: if os.path.exists(match): rel_path = os.path.relpath(match, base_path) data_files.append((rel_path, dest_folder)) else: # Handle single files/folders full_path = os.path.join(base_path, source_pattern) if os.path.exists(full_path): data_files.append((source_pattern, dest_folder)) except Exception as e: print(f"Warning: Could not add {source_pattern}: {e}") return data_files a = Analysis( ['odoo-bin'], pathex=[base_path], binaries=[], datas=[ # Core Odoo files (only if they exist) ('addons', 'addons'), ('odoo', 'odoo'), ('extra-addons', 'extra-addons'), # Configuration files ('odoo.conf', '.'), # Add other config files if they exist ] + safe_add_data('odoo-*.conf', '.') + [ # GeoIP databases (if they exist) ] + safe_add_data('/root/dev/NextERP/dev/odoo18/resource/GeoLite2-City_20250708/GeoLite2-City.mmdb', 'geoip/') + \ safe_add_data('/root/dev/NextERP/dev/odoo18/resource/GeoLite2-Country_20250708/GeoLite2-Country.mmdb', 'geoip/') + \ babel_data + reportlab_data, hiddenimports=[ # Core Python modules 'pkg_resources.py2_warn', 'pkg_resources', # Database drivers 'psycopg2', 'psycopg2.extensions', 'psycopg2.extras', # Core Odoo dependencies 'lxml', 'lxml.etree', 'lxml.html', 'lxml.html.clean', 'werkzeug', 'werkzeug.serving', 'werkzeug.security', 'babel', 'babel.dates', 'babel.numbers', 'passlib', 'passlib.hash', 'dateutil', 'python_dateutil', 'pytz', 'PIL', 'PIL.Image', 'reportlab', 'openpyxl', 'xlrd', 'xlwt', 'requests', 'urllib3', 'jinja2', 'markupsafe', # Odoo core modules 'odoo', 'odoo.addons', 'odoo.tools', 'odoo.tools.pdf', # Only include PDF modules that actually exist 'odoo.tools.pdf._pypdf', 'odoo.tools.pdf._pypdf2_1', 'odoo.tools.pdf._pypdf2_2', 'odoo.service', 'odoo.service.server', 'odoo.http', 'odoo.cli', 'odoo.cli.server', 'odoo.cli.command', 'odoo.cli.deploy', 'odoo.cli.scaffold', 'odoo.cli.shell', 'odoo.cli.start', # Web framework 'odoo.addons.web', 'odoo.addons.base', # Additional dependencies from your requirements 'gevent', 'greenlet', 'psutil', 'qrcode', 'num2words', 'python_stdnum', 'vobject', 'zeep', 'cryptography', 'cryptography.hazmat', 'cryptography.hazmat.primitives', 'cryptography.hazmat.primitives.kdf', 'cryptography.hazmat.primitives.kdf.hkdf', 'cryptography.hazmat.primitives.hashes', 'cryptography.hazmat.primitives.ciphers', 'cryptography.hazmat.primitives.serialization', 'cryptography.hazmat.backends', 'cryptography.hazmat.backends.openssl', 'cryptography.fernet', 'docutils', 'freezegun', 'geoip2', 'libsass', 'polib', 'pyopenssl', 'pyserial', 'pyusb', 'rjsmin', 'unidecode', 'beautifulsoup4', 'html2text', 'python_docx', 'boto3', 'paramiko', 'openai', 'weasyprint', 'pdfkit', 'pdfminer', 'pdfminer.six', # Reportlab barcode modules - needed for Odoo reports 'reportlab.graphics.barcode', 'reportlab.graphics.barcode.code128', 'reportlab.graphics.barcode.code39', 'reportlab.graphics.barcode.code93', 'reportlab.graphics.barcode.common', 'reportlab.graphics.barcode.eanbc', 'reportlab.graphics.barcode.qr', 'reportlab.graphics.barcode.usps', 'reportlab.graphics.barcode.usps4s', 'reportlab.graphics.barcode.widgets', 'reportlab.graphics.barcode.lto', 'reportlab.graphics.barcode.dmtx', 'reportlab.graphics.barcode.ecc200datamatrix', 'reportlab.graphics.barcode.fourstate', # Babel message modules - needed for translations 'babel.messages', 'babel.messages.pofile', 'babel.messages.catalog', 'babel.messages.extract', 'babel.messages.frontend', 'babel.messages.jslexer', 'babel.messages.mofile', 'babel.messages.plurals', # PyPDF modules (the ones that actually exist) 'PyPDF2', 'PyPDF2.errors', 'PyPDF2.filters', 'PyPDF2.generic', 'pypdf', 'pypdf.errors', 'pypdf.filters', 'pypdf.generic', # Dynamic imports 'email.mime.multipart', 'email.mime.text', 'email.mime.base', 'email.encoders', # Additional modules that might be imported dynamically 'unicodedata', 'locale', 'threading', 'multiprocessing', 'subprocess', 'socket', 'ssl', 'json', 'base64', 'hashlib', 'hmac', 'uuid', 'datetime', 'time', 'timeit', # Add timeit as it's needed by passlib 'calendar', 'math', 'random', 'os', 'sys', 'io', 'tempfile', 'shutil', 're', 'collections', 'itertools', 'functools', 'operator', 'copy', 'pickle', 'csv', 'xml', 'xml.etree', 'xml.etree.ElementTree', 'xml.sax', 'html', 'urllib', 'urllib.parse', 'urllib.request', 'http', 'http.client', # Additional Odoo modules that might be needed 'odoo.modules', 'odoo.modules.registry', 'odoo.modules.loading', 'odoo.modules.migration', 'odoo.modules.module', 'odoo.modules.graph', 'odoo.modules.db', 'odoo.sql_db', 'odoo.pooler', 'odoo.fields', 'odoo.models', 'odoo.api', 'odoo.exceptions', 'odoo.release', 'odoo.netsvc', 'odoo.loglevels', # Passlib specific modules 'passlib.context', 'passlib.registry', 'passlib.ifc', 'passlib.utils', 'passlib.utils.compat', 'passlib.crypto', 'passlib.crypto.digest', 'passlib.handlers', 'passlib.handlers.pbkdf2', 'passlib.handlers.sha2_crypt', 'passlib.handlers.bcrypt', 'passlib.handlers.argon2', # Mail module dependencies 'email.utils', 'email.header', 'email.charset', 'smtplib', 'poplib', 'imaplib', ] + odoo_submodules + addon_submodules, hookspath=[], runtime_hooks=[], excludes=[ # Exclude unnecessary modules to reduce size 'tkinter', 'matplotlib', 'scipy', 'pandas', 'jupyter', 'notebook', 'ipython', 'django', 'flask', 'tornado', 'twisted', 'test', 'tests', 'unittest', 'doctest', 'pdb', 'profile', 'cProfile', 'pstats', 'trace', # 'timeit', # DON'T exclude - needed by passlib # Exclude non-existent PDF modules 'odoo.tools.pdf._pypdf2_3', 'odoo.tools.pdf._pypdf4', ], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, [], exclude_binaries=True, name='odoo18', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, console=True, disable_windowed_traceback=False, target_arch=None, codesign_identity=None, entitlements_file=None, ) coll = COLLECT( exe, a.binaries, a.datas, strip=False, upx=True, upx_exclude=[], name='odoo18', )