summaryrefslogtreecommitdiffstats
path: root/deluge/ui/console/console.py
blob: f683c749d5fb50eac61435f4652a288f995ab976 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# 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.
#
from __future__ import print_function, unicode_literals

import fnmatch
import logging
import os
import sys

import deluge.common
from deluge.argparserbase import ArgParserBase, DelugeTextHelpFormatter
from deluge.ui.ui import UI

log = logging.getLogger(__name__)

#
# Note: Cannot import from console.main here because it imports the twisted reactor.
# Console is imported from console/__init__.py loaded by the script entry points
# defined in setup.py
#


def load_commands(command_dir):
    def get_command(name):
        command = getattr(
            __import__(
                'deluge.ui.console.cmdline.commands.%s' % name, {}, {}, ['Command']
            ),
            'Command',
        )()
        command._name = name
        return command

    try:
        dir_list = fnmatch.filter(os.listdir(command_dir), '*.py')
    except OSError:
        return {}

    commands = []
    for filename in dir_list:
        if filename.startswith('_'):
            continue
        cmd = get_command(os.path.splitext(filename)[0])
        for cmd_name in [cmd._name] + cmd.aliases:
            commands.append((cmd_name, cmd))
    return dict(commands)


class LogStream(object):
    out = sys.stdout

    def write(self, data):
        self.out.write(data)

    def flush(self):
        self.out.flush()


class Console(UI):

    cmd_description = """Console or command-line user interface"""

    def __init__(self, *args, **kwargs):
        super(Console, self).__init__(
            'console', *args, log_stream=LogStream(), **kwargs
        )

        group = self.parser.add_argument_group(
            _('Console Options'),
            _(
                'These daemon connect options will be '
                'used for commands, or if console ui autoconnect is enabled.'
            ),
        )
        group.add_argument(
            '-d',
            '--daemon',
            metavar='<ip_addr>',
            dest='daemon_addr',
            help=_('Deluge daemon IP address to connect to (default 127.0.0.1)'),
            default='127.0.0.1',
        )
        group.add_argument(
            '-p',
            '--port',
            metavar='<port>',
            dest='daemon_port',
            type=int,
            help=_('Deluge daemon port to connect to (default 58846)'),
            default='58846',
        )
        group.add_argument(
            '-U',
            '--username',
            metavar='<user>',
            dest='daemon_user',
            help=_('Deluge daemon username to use when connecting'),
        )
        group.add_argument(
            '-P',
            '--password',
            metavar='<pass>',
            dest='daemon_pass',
            help=_('Deluge daemon password to use when connecting'),
        )
        # To properly print help message for the console commands ( e.g. deluge-console info -h),
        # we add a subparser for each command which will trigger the help/usage when given
        from deluge.ui.console.parser import (  # import here because (see top)
            ConsoleCommandParser,
        )

        self.console_parser = ConsoleCommandParser(
            parents=[self.parser],
            add_help=False,
            prog=self.parser.prog,
            description='Starts the Deluge console interface',
            formatter_class=lambda prog: DelugeTextHelpFormatter(
                prog, max_help_position=33, width=90
            ),
        )
        self.parser.subparser = self.console_parser
        self.console_parser.base_parser = self.parser
        subparsers = self.console_parser.add_subparsers(
            title=_('Console Commands'),
            help=_('Description'),
            description=_('The following console commands are available:'),
            metavar=_('Command'),
            dest='command',
        )
        from deluge.ui.console import UI_PATH  # Must import here

        self.console_cmds = load_commands(os.path.join(UI_PATH, 'cmdline', 'commands'))
        for cmd in sorted(self.console_cmds):
            self.console_cmds[cmd].add_subparser(subparsers)

    def start(self):
        if self.ui_args is None:
            # Started directly by deluge-console script so must find the UI args manually
            options, remaining = ArgParserBase(common_help=False).parse_known_args()
            self.ui_args = remaining

        i = self.console_parser.find_subcommand(args=self.ui_args)
        self.console_parser.subcommand = False
        self.parser.subcommand = False if i == -1 else True

        super(Console, self).start(self.console_parser)
        from deluge.ui.console.main import ConsoleUI  # import here because (see top)

        def run(options):
            try:
                c = ConsoleUI(self.options, self.console_cmds, self.parser.log_stream)
                return c.start_ui()
            except Exception as ex:
                log.exception(ex)
                raise

        return deluge.common.run_profiled(
            run,
            self.options,
            output_file=self.options.profile,
            do_profile=self.options.profile,
        )