Ticket #1974: 0001-Decouple-GUI-selection-from-core.patch
File 0001-Decouple-GUI-selection-from-core.patch, 17.6 KB (added by , 13 years ago) |
---|
-
deluge/main.py
From 3227bdc65af97bb74d383333a32eb6153c065eda Mon Sep 17 00:00:00 2001 From: Jamie Lennox <jamielennox@gmail.com> Date: Sat, 19 Nov 2011 20:20:43 +1100 Subject: [PATCH] Decouple GUI selection from core. Add EntryPoints into setup for each of the UIs and then use this information to determine which client UI to run. --- deluge/main.py | 34 +++++------ deluge/ui/console/__init__.py | 5 +- deluge/ui/console/console.py | 128 +++++++++++++++++++++++++++++++++++++++++ deluge/ui/console/main.py | 91 ----------------------------- deluge/ui/gtkui/__init__.py | 18 ++++++- deluge/ui/gtkui/gtkui.py | 15 ----- deluge/ui/web/__init__.py | 5 +- deluge/ui/web/web.py | 1 + setup.py | 7 ++- 9 files changed, 174 insertions(+), 130 deletions(-) create mode 100644 deluge/ui/console/console.py diff --git a/deluge/main.py b/deluge/main.py index 5797251..4b429e7 100644
a b 44 44 import sys 45 45 import optparse 46 46 import logging 47 import pkg_resources 47 48 48 49 import deluge.log 49 50 import deluge.error … … def start_ui(): 62 63 parser = CommonOptionParser() 63 64 group = optparse.OptionGroup (parser, _("Default Options")) 64 65 65 group.add_option("-u", "--ui", dest="ui", 66 help="""The UI that you wish to launch. The UI choices are:\n 67 \t gtk -- A GTK-based graphical user interface (default)\n 68 \t web -- A web-based interface (http://localhost:8112)\n 69 \t console -- A console or command-line interface""", action="store", type="str") 66 ui_entrypoints = dict([(entrypoint.name, entrypoint.load()) 67 for entrypoint in pkg_resources.iter_entry_points('deluge.ui')]) 68 69 cmd_help = ['The UI that you wish to launch. The UI choices are:'] 70 cmd_help.extend(["%s -- %s" % (k, getattr(v, 'cmdline', "")) for k,v in ui_entrypoints.iteritems()]) 71 72 parser.add_option("-u", "--ui", dest="ui", 73 choices = ui_entrypoints.keys(), help="\n\t ".join(cmd_help), action="store") 70 74 group.add_option("-a", "--args", dest="args", 71 75 help="Arguments to pass to UI, -a '--option args'", action="store", type="str") 72 76 group.add_option("-s", "--set-default-ui", dest="default_ui", … … def start_ui(): 106 110 client_args.extend(args) 107 111 108 112 try: 109 if selected_ui == "gtk": 110 log.info("Starting GtkUI..") 111 from deluge.ui.gtkui.gtkui import Gtk 112 ui = Gtk(skip_common = True) 113 ui.start(client_args) 114 elif selected_ui == "web": 115 log.info("Starting WebUI..") 116 from deluge.ui.web.web import Web 117 ui = Web(skip_common = True) 118 ui.start(client_args) 119 elif selected_ui == "console": 120 log.info("Starting ConsoleUI..") 121 from deluge.ui.console.main import Console 122 ui = Console(skip_common = True) 123 ui.start(client_args) 113 ui = ui_entrypoints[selected_ui](skip_common = True) 114 except KeyError, e: 115 log.error("Unable to find the requested UI: %s. Please select a different UI with the '-u' option or alternatively use the '-s' option to select a different default UI.", selected_ui) 124 116 except ImportError, e: 125 117 import sys 126 118 import traceback … … def start_ui(): 134 126 log.error("There was an error whilst launching the request UI: %s", selected_ui) 135 127 log.error("Look at the traceback above for more information.") 136 128 sys.exit(1) 129 else: 130 ui.start(client_args) 137 131 138 132 def start_daemon(): 139 133 """Entry point for daemon script""" -
deluge/ui/console/__init__.py
diff --git a/deluge/ui/console/__init__.py b/deluge/ui/console/__init__.py index 0747fac..09b2438 100644
a b 33 33 # 34 34 # 35 35 UI_PATH = __path__[0] 36 from main import start 36 from console import Console 37 38 def start(): 39 Console().start() -
new file deluge/ui/console/console.py
diff --git a/deluge/ui/console/console.py b/deluge/ui/console/console.py new file mode 100644 index 0000000..139e789
- + 1 # 2 # main.py 3 # 4 # Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com> 5 # Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com> 6 # 7 # Deluge is free software. 8 # 9 # You may redistribute it and/or modify it under the terms of the 10 # GNU General Public License, as published by the Free Software 11 # Foundation; either version 3 of the License, or (at your option) 12 # any later version. 13 # 14 # deluge is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 # See the GNU General Public License for more details. 18 # 19 # You should have received a copy of the GNU General Public License 20 # along with deluge. If not, write to: 21 # The Free Software Foundation, Inc., 22 # 51 Franklin Street, Fifth Floor 23 # Boston, MA 02110-1301, USA. 24 # 25 # In addition, as a special exception, the copyright holders give 26 # permission to link the code of portions of this program with the OpenSSL 27 # library. 28 # You must obey the GNU General Public License in all respects for all of 29 # the code used other than OpenSSL. If you modify file(s) with this 30 # exception, you may extend this exception to your version of the file(s), 31 # but you are not obligated to do so. If you do not wish to do so, delete 32 # this exception statement from your version. If you delete this exception 33 # statement from all source files in the program, then also delete it here. 34 # 35 # 36 37 import os 38 import sys 39 import optparse 40 from deluge.ui.ui import _UI 41 from deluge.ui.console import UI_PATH 42 43 def load_commands(command_dir, exclude=[]): 44 def get_command(name): 45 return getattr(__import__('deluge.ui.console.commands.%s' % name, {}, {}, ['Command']), 'Command')() 46 47 try: 48 commands = [] 49 for filename in os.listdir(command_dir): 50 if filename.split('.')[0] in exclude or filename.startswith('_'): 51 continue 52 if not (filename.endswith('.py') or filename.endswith('.pyc')): 53 continue 54 cmd = get_command(filename.split('.')[len(filename.split('.')) - 2]) 55 aliases = [ filename.split('.')[len(filename.split('.')) - 2] ] 56 aliases.extend(cmd.aliases) 57 for a in aliases: 58 commands.append((a, cmd)) 59 return dict(commands) 60 except OSError, e: 61 return {} 62 63 class Console(_UI): 64 65 help = """Starts the Deluge console interface""" 66 cmdline = """A console or command-line interface""" 67 68 def __init__(self, *args, **kwargs): 69 super(Console, self).__init__("console", *args, **kwargs) 70 group = optparse.OptionGroup(self.parser, "Console Options","These options control how " 71 "the console connects to the daemon. These options will be " 72 "used if you pass a command, or if you have autoconnect " 73 "enabled for the console ui.") 74 75 group.add_option("-d","--daemon",dest="daemon_addr", 76 action="store",type="str",default="127.0.0.1", 77 help="Set the address of the daemon to connect to." 78 " [default: %default]") 79 group.add_option("-p","--port",dest="daemon_port", 80 help="Set the port to connect to the daemon on. [default: %default]", 81 action="store",type="int",default=58846) 82 group.add_option("-u","--username",dest="daemon_user", 83 help="Set the username to connect to the daemon with. [default: %default]", 84 action="store",type="string") 85 group.add_option("-P","--password",dest="daemon_pass", 86 help="Set the password to connect to the daemon with. [default: %default]", 87 action="store",type="string") 88 self.parser.add_option_group(group) 89 90 self.cmds = load_commands(os.path.join(UI_PATH, 'commands')) 91 class CommandOptionGroup(optparse.OptionGroup): 92 def __init__(self, parser, title, description=None, cmds = None): 93 optparse.OptionGroup.__init__(self,parser,title,description) 94 self.cmds = cmds 95 96 def format_help(self, formatter): 97 result = formatter.format_heading(self.title) 98 formatter.indent() 99 if self.description: 100 result += "%s\n"%formatter.format_description(self.description) 101 for cname in self.cmds: 102 cmd = self.cmds[cname] 103 if cmd.interactive_only or cname in cmd.aliases: continue 104 allnames = [cname] 105 allnames.extend(cmd.aliases) 106 cname = "/".join(allnames) 107 result += formatter.format_heading(" - ".join([cname,cmd.__doc__])) 108 formatter.indent() 109 result += "%*s%s\n" % (formatter.current_indent, "", cmd.usage) 110 formatter.dedent() 111 formatter.dedent() 112 return result 113 cmd_group = CommandOptionGroup(self.parser, "Console Commands", 114 description="The following commands can be issued at the " 115 "command line. Commands should be quoted, so, for example, " 116 "to pause torrent with id 'abc' you would run: '%s " 117 "\"pause abc\"'"%os.path.basename(sys.argv[0]), 118 cmds=self.cmds) 119 self.parser.add_option_group(cmd_group) 120 121 def start(self, args = None): 122 from main import ConsoleUI 123 super(Console, self).start(args) 124 ConsoleUI(self.args,self.cmds,(self.options.daemon_addr, 125 self.options.daemon_port,self.options.daemon_user, 126 self.options.daemon_pass)) 127 128 -
deluge/ui/console/main.py
diff --git a/deluge/ui/console/main.py b/deluge/ui/console/main.py index 1f0467e..bbe5a24 100644
a b 34 34 # 35 35 # 36 36 37 import os38 37 import sys 39 38 import logging 40 39 import optparse … … 51 50 from deluge.ui.console.statusbars import StatusBars 52 51 from deluge.ui.console.eventlog import EventLog 53 52 import colors 54 from deluge.ui.ui import _UI55 from deluge.ui.console import UI_PATH56 57 53 58 54 log = logging.getLogger(__name__) 59 55 60 class Console(_UI):61 62 help = """Starts the Deluge console interface"""63 64 def __init__(self, *args, **kwargs):65 super(Console, self).__init__("console", *args, **kwargs)66 group = optparse.OptionGroup(self.parser, "Console Options","These options control how "67 "the console connects to the daemon. These options will be "68 "used if you pass a command, or if you have autoconnect "69 "enabled for the console ui.")70 71 group.add_option("-d","--daemon",dest="daemon_addr",72 action="store",type="str",default="127.0.0.1",73 help="Set the address of the daemon to connect to."74 " [default: %default]")75 group.add_option("-p","--port",dest="daemon_port",76 help="Set the port to connect to the daemon on. [default: %default]",77 action="store",type="int",default=58846)78 group.add_option("-u","--username",dest="daemon_user",79 help="Set the username to connect to the daemon with. [default: %default]",80 action="store",type="string")81 group.add_option("-P","--password",dest="daemon_pass",82 help="Set the password to connect to the daemon with. [default: %default]",83 action="store",type="string")84 self.parser.add_option_group(group)85 86 self.cmds = load_commands(os.path.join(UI_PATH, 'commands'))87 class CommandOptionGroup(optparse.OptionGroup):88 def __init__(self, parser, title, description=None, cmds = None):89 optparse.OptionGroup.__init__(self,parser,title,description)90 self.cmds = cmds91 92 def format_help(self, formatter):93 result = formatter.format_heading(self.title)94 formatter.indent()95 if self.description:96 result += "%s\n"%formatter.format_description(self.description)97 for cname in self.cmds:98 cmd = self.cmds[cname]99 if cmd.interactive_only or cname in cmd.aliases: continue100 allnames = [cname]101 allnames.extend(cmd.aliases)102 cname = "/".join(allnames)103 result += formatter.format_heading(" - ".join([cname,cmd.__doc__]))104 formatter.indent()105 result += "%*s%s\n" % (formatter.current_indent, "", cmd.usage)106 formatter.dedent()107 formatter.dedent()108 return result109 cmd_group = CommandOptionGroup(self.parser, "Console Commands",110 description="The following commands can be issued at the "111 "command line. Commands should be quoted, so, for example, "112 "to pause torrent with id 'abc' you would run: '%s "113 "\"pause abc\"'"%os.path.basename(sys.argv[0]),114 cmds=self.cmds)115 self.parser.add_option_group(cmd_group)116 117 def start(self, args = None):118 super(Console, self).start(args)119 ConsoleUI(self.args,self.cmds,(self.options.daemon_addr,120 self.options.daemon_port,self.options.daemon_user,121 self.options.daemon_pass))122 123 def start():124 Console().start()125 126 56 class OptionParser(optparse.OptionParser): 127 57 """subclass from optparse.OptionParser so exit() won't exit.""" 128 58 def exit(self, status=0, msg=None): … … def create_parser(self): 172 102 option_list = self.option_list) 173 103 174 104 175 def load_commands(command_dir, exclude=[]):176 def get_command(name):177 return getattr(__import__('deluge.ui.console.commands.%s' % name, {}, {}, ['Command']), 'Command')()178 179 try:180 commands = []181 for filename in os.listdir(command_dir):182 if filename.split('.')[0] in exclude or filename.startswith('_'):183 continue184 if not (filename.endswith('.py') or filename.endswith('.pyc')):185 continue186 cmd = get_command(filename.split('.')[len(filename.split('.')) - 2])187 aliases = [ filename.split('.')[len(filename.split('.')) - 2] ]188 aliases.extend(cmd.aliases)189 for a in aliases:190 commands.append((a, cmd))191 return dict(commands)192 except OSError, e:193 return {}194 195 196 105 class ConsoleUI(component.Component): 197 106 def __init__(self, args=None, cmds = None, daemon = None): 198 107 component.Component.__init__(self, "ConsoleUI", 2) -
deluge/ui/gtkui/__init__.py
diff --git a/deluge/ui/gtkui/__init__.py b/deluge/ui/gtkui/__init__.py index c5a539a..5b3edba 100644
a b 1 from gtkui import start 1 from deluge.ui.ui import _UI 2 3 class Gtk(_UI): 4 5 help = """Starts the Deluge GTK+ interface""" 6 cmdline = """A GTK-based graphical user interface""" 7 8 def __init__(self, *args, **kwargs): 9 super(Gtk, self).__init__("gtk", *args, **kwargs) 10 11 def start(self, args = None): 12 from gtkui import GtkUI 13 super(Gtk, self).start(args) 14 GtkUI(self.args) 15 16 def start(): 17 Gtk().start() -
deluge/ui/gtkui/gtkui.py
diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 634c266..22f55c2 100644
a b 71 71 import deluge.common 72 72 import deluge.error 73 73 74 from deluge.ui.ui import _UI75 76 class Gtk(_UI):77 78 help = """Starts the Deluge GTK+ interface"""79 80 def __init__(self, *args, **kwargs):81 super(Gtk, self).__init__("gtk", *args, **kwargs)82 83 def start(self, args = None):84 super(Gtk, self).start(args)85 GtkUI(self.args)86 87 def start():88 Gtk().start()89 74 90 75 DEFAULT_PREFS = { 91 76 "classic_mode": True, -
deluge/ui/web/__init__.py
diff --git a/deluge/ui/web/__init__.py b/deluge/ui/web/__init__.py index 28f53f2..a1ad237 100644
a b 1 from web import start 2 No newline at end of file 1 from web import Web 2 3 def start(): 4 Web().start() -
deluge/ui/web/web.py
diff --git a/deluge/ui/web/web.py b/deluge/ui/web/web.py index 6ecbdfc..f862ebf 100644
a b def __init__(self, args): 48 48 class Web(_UI): 49 49 50 50 help = """Starts the Deluge web interface""" 51 cmdline = """A web-based interface (http://localhost:8112)""" 51 52 52 53 def __init__(self, *args, **kwargs): 53 54 super(Web, self).__init__("web", *args, **kwargs) -
setup.py
diff --git a/setup.py b/setup.py index 5a55d42..6960ac4 100644
a b def run(self): 515 515 "gui_scripts": [ 516 516 "deluge = deluge.main:start_ui", 517 517 "deluge-gtk = deluge.ui.gtkui:start" 518 ] 518 ], 519 "deluge.ui" : [ 520 "console = deluge.ui.console:Console", 521 "web = deluge.ui.web:Web", 522 "gtk = deluge.ui.gtkui:Gtk", 523 ], 519 524 } 520 525 521 526