From acb14d025cfd698f0a0553d97f57aa48d6ca6b68 Mon Sep 17 00:00:00 2001 From: benexl Date: Wed, 31 Dec 2025 14:42:44 +0300 Subject: [PATCH] fix: enhance menu loading to support PyInstaller compatibility with explicit module listing --- bundle/pyinstaller.spec | 15 +++++++++++ .../cli/interactive/menu/media/__init__.py | 17 ++++++++++++ viu_media/cli/interactive/session.py | 27 +++++++++++-------- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/bundle/pyinstaller.spec b/bundle/pyinstaller.spec index b253f7d..bd7cec3 100644 --- a/bundle/pyinstaller.spec +++ b/bundle/pyinstaller.spec @@ -20,6 +20,21 @@ hiddenimports = [ 'viu_media', 'viu_media.cli.interactive.menu', 'viu_media.cli.interactive.menu.media', + # Explicit menu modules (PyInstaller doesn't always pick these up) + 'viu_media.cli.interactive.menu.media.downloads', + 'viu_media.cli.interactive.menu.media.download_episodes', + 'viu_media.cli.interactive.menu.media.dynamic_search', + 'viu_media.cli.interactive.menu.media.episodes', + 'viu_media.cli.interactive.menu.media.main', + 'viu_media.cli.interactive.menu.media.media_actions', + 'viu_media.cli.interactive.menu.media.media_airing_schedule', + 'viu_media.cli.interactive.menu.media.media_characters', + 'viu_media.cli.interactive.menu.media.media_review', + 'viu_media.cli.interactive.menu.media.player_controls', + 'viu_media.cli.interactive.menu.media.play_downloads', + 'viu_media.cli.interactive.menu.media.provider_search', + 'viu_media.cli.interactive.menu.media.results', + 'viu_media.cli.interactive.menu.media.servers', ] + collect_submodules('viu_media') a = Analysis( diff --git a/viu_media/cli/interactive/menu/media/__init__.py b/viu_media/cli/interactive/menu/media/__init__.py index b5f3b24..6aa02b3 100644 --- a/viu_media/cli/interactive/menu/media/__init__.py +++ b/viu_media/cli/interactive/menu/media/__init__.py @@ -1 +1,18 @@ # Media menu modules +# Explicit module list for PyInstaller compatibility +__all__ = [ + "downloads", + "download_episodes", + "dynamic_search", + "episodes", + "main", + "media_actions", + "media_airing_schedule", + "media_characters", + "media_review", + "player_controls", + "play_downloads", + "provider_search", + "results", + "servers", +] diff --git a/viu_media/cli/interactive/session.py b/viu_media/cli/interactive/session.py index 4e806a4..48a2d09 100644 --- a/viu_media/cli/interactive/session.py +++ b/viu_media/cli/interactive/session.py @@ -314,8 +314,8 @@ class Session: def load_menus_from_folder(self, package: str): """Load menu modules from a subfolder. - Uses pkgutil to discover modules, which works correctly with both - regular Python installations and PyInstaller frozen executables. + Uses pkgutil to discover modules for regular Python, and falls back + to the package's __all__ list for PyInstaller frozen executables. """ full_package_name = f"viu_media.cli.interactive.menu.{package}" logger.debug(f"Loading menus from package '{full_package_name}'...") @@ -327,17 +327,22 @@ class Session: logger.error(f"Failed to import menu package '{full_package_name}': {e}") return - # Use pkgutil to iterate over all modules in the package - # This works with PyInstaller because it respects the module's __path__ + # Try pkgutil first (works in regular Python) package_path = getattr(parent_package, "__path__", None) - if package_path is None: - logger.error(f"Package '{full_package_name}' has no __path__ attribute.") - return - - for importer, module_name, ispkg in pkgutil.iter_modules(package_path): - if ispkg or module_name.startswith("_"): - continue + module_names = [] + + if package_path: + module_names = [ + name for _, name, ispkg in pkgutil.iter_modules(package_path) + if not ispkg and not name.startswith("_") + ] + + # Fallback to __all__ for PyInstaller frozen executables + if not module_names: + module_names = getattr(parent_package, "__all__", []) + logger.debug(f"Using __all__ fallback with {len(module_names)} modules") + for module_name in module_names: full_module_name = f"{full_package_name}.{module_name}" try: # Simply importing the module will execute it,