# # Copyright (C) 2007 Andrew Resch # Copyright (C) 2010 Pedro Algarvio # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. # # The main starting point for the program. This function is called when the # user runs the command 'deluge'. """Main starting point for Deluge""" import argparse import logging import os import sys import pkg_resources import deluge.common import deluge.configmanager from deluge.argparserbase import ArgParserBase from deluge.i18n import setup_translation DEFAULT_PREFS = {'default_ui': 'gtk'} AMBIGUOUS_CMD_ARGS = ('-h', '--help', '-v', '-V', '--version') def start_ui(): """Entry point for ui script""" setup_translation() # Get the registered UI entry points ui_entrypoints = {} for entrypoint in pkg_resources.iter_entry_points('deluge.ui'): try: ui_entrypoints[entrypoint.name] = entrypoint.load() except ImportError: # Unable to load entrypoint so skip adding it. pass ui_titles = sorted(ui_entrypoints) def add_ui_options_group(_parser): """Function to enable reuse of UI Options group""" group = _parser.add_argument_group(_('UI Options')) group.add_argument( '-s', '--set-default-ui', dest='default_ui', choices=ui_titles, help=_('Set the default UI to be run, when no UI is specified'), ) return _parser # Setup parser with Common Options and add UI Options group. parser = add_ui_options_group(ArgParserBase()) # Parse and handle common/process group options options = parser.parse_known_ui_args(sys.argv, withhold=AMBIGUOUS_CMD_ARGS) config = deluge.configmanager.ConfigManager('ui.conf', DEFAULT_PREFS) log = logging.getLogger(__name__) log.info('Deluge ui %s', deluge.common.get_version()) if options.default_ui: config['default_ui'] = options.default_ui config.save() log.info('The default UI has been changed to %s', options.default_ui) sys.exit(0) default_ui = config['default_ui'] config.save() # Save in case config didn't already exist. del config # We have parsed and got the config dir needed to get the default UI # Now create a parser for choosing the UI. We reuse the ui option group for # parsing to succeed and the text displayed to user, but result is not used. parser = add_ui_options_group(ArgParserBase(common_help=True)) # Create subparser for each registered UI. Empty title is used to remove unwanted positional text. subparsers = parser.add_subparsers( dest='selected_ui', metavar='{%s} [UI args]' % ','.join(ui_titles), title=None, help=_('Alternative UI to launch, with optional ui args \n (default UI: *)'), ) for ui in ui_titles: parser_ui = subparsers.add_parser( ui, common_help=False, help=getattr(ui_entrypoints[ui], 'cmd_description', ''), ) parser_ui.add_argument('ui_args', nargs=argparse.REMAINDER) # If the UI is set as default, indicate this in help by prefixing with a star. subactions = subparsers._get_subactions() prefix = '*' if ui == default_ui else ' ' subactions[-1].metavar = f'{prefix} {ui}' # Insert a default UI subcommand unless one of the ambiguous_args are specified parser.set_default_subparser(default_ui, abort_opts=AMBIGUOUS_CMD_ARGS) # Only parse known arguments to leave the UIs to show a help message if parsing fails. options, remaining = parser.parse_known_args() selected_ui = options.selected_ui ui_args = remaining + options.ui_args # Remove the UI argument before launching the UI. sys.argv.remove(selected_ui) try: ui = ui_entrypoints[selected_ui]( prog=f'{os.path.basename(sys.argv[0])} {selected_ui}', ui_args=ui_args ) except KeyError: log.error( 'Unable to find chosen UI: "%s". Please choose a different UI ' 'or use "--set-default-ui" to change default UI.', selected_ui, ) except ImportError as ex: import traceback error_type, error_value, tb = sys.exc_info() stack = traceback.extract_tb(tb) last_frame = stack[-1] if last_frame[0] == __file__: log.error( 'Unable to find chosen UI: "%s". Please choose a different UI ' 'or use "--set-default-ui" to change default UI.', selected_ui, ) else: log.exception(ex) log.error('Encountered an error launching the request UI: %s', selected_ui) sys.exit(1) else: ui.start()