diff options
Diffstat (limited to 'deluge/ui/console/cmdline/commands/config.py')
-rw-r--r-- | deluge/ui/console/cmdline/commands/config.py | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/deluge/ui/console/cmdline/commands/config.py b/deluge/ui/console/cmdline/commands/config.py new file mode 100644 index 0000000..bd0a1e1 --- /dev/null +++ b/deluge/ui/console/cmdline/commands/config.py @@ -0,0 +1,168 @@ +# -*- 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 unicode_literals + +import logging +import tokenize +from io import StringIO + +import deluge.component as component +import deluge.ui.console.utils.colors as colors +from deluge.ui.client import client + +from . import BaseCommand + +log = logging.getLogger(__name__) + + +def atom(src, token): + """taken with slight modifications from http://effbot.org/zone/simple-iterator-parser.htm""" + if token[1] == '(': + out = [] + token = next(src) + while token[1] != ')': + out.append(atom(src, token)) + token = next(src) + if token[1] == ',': + token = next(src) + return tuple(out) + elif token[0] is tokenize.NUMBER or token[1] == '-': + try: + if token[1] == '-': + return int(token[-1], 0) + else: + if token[1].startswith('0x'): + # Hex number so return unconverted as string. + return token[1].decode('string-escape') + else: + return int(token[1], 0) + except ValueError: + try: + return float(token[-1]) + except ValueError: + return str(token[-1]) + elif token[1].lower() == 'true': + return True + elif token[1].lower() == 'false': + return False + elif token[0] is tokenize.STRING or token[1] == '/': + return token[-1].decode('string-escape') + elif token[1].isalpha(): + # Parse Windows paths e.g. 'C:\\xyz' or 'C:/xyz'. + if next()[1] == ':' and next()[1] in '\\/': + return token[-1].decode('string-escape') + + raise SyntaxError('malformed expression (%s)' % token[1]) + + +def simple_eval(source): + """ evaluates the 'source' string into a combination of primitive python objects + taken from http://effbot.org/zone/simple-iterator-parser.htm""" + src = StringIO(source).readline + src = tokenize.generate_tokens(src) + src = (token for token in src if token[0] is not tokenize.NL) + res = atom(src, next(src)) + return res + + +class Command(BaseCommand): + """Show and set configuration values""" + + usage = _('Usage: config [--set <key> <value>] [<key> [<key>...] ]') + + def add_arguments(self, parser): + set_group = parser.add_argument_group('setting a value') + set_group.add_argument( + '-s', + '--set', + action='store', + metavar='<key>', + help=_('set value for this key'), + ) + set_group.add_argument( + 'values', metavar='<value>', nargs='+', help=_('Value to set') + ) + get_group = parser.add_argument_group('getting values') + get_group.add_argument( + 'keys', + metavar='<keys>', + nargs='*', + help=_('one or more keys separated by space'), + ) + + def handle(self, options): + self.console = component.get('ConsoleUI') + if options.set: + return self._set_config(options) + else: + return self._get_config(options) + + def _get_config(self, options): + def _on_get_config(config): + string = '' + for key in sorted(config): + if key not in options.values: + continue + + color = '{!white,black,bold!}' + value = config[key] + try: + color = colors.type_color[type(value)] + except KeyError: + pass + + # We need to format dicts for printing + if isinstance(value, dict): + import pprint + + value = pprint.pformat(value, 2, 80) + new_value = [] + for line in value.splitlines(): + new_value.append('%s%s' % (color, line)) + value = '\n'.join(new_value) + + string += '%s: %s%s\n' % (key, color, value) + self.console.write(string.strip()) + + return client.core.get_config().addCallback(_on_get_config) + + def _set_config(self, options): + config = component.get('CoreConfig') + key = options.set + val = ' '.join(options.values) + + try: + val = simple_eval(val) + except SyntaxError as ex: + self.console.write('{!error!}%s' % ex) + return + + if key not in config: + self.console.write('{!error!}Invalid key: %s' % key) + return + + if not isinstance(config[key], type(val)): + try: + val = type(config[key])(val) + except TypeError: + self.config.write( + '{!error!}Configuration value provided has incorrect type.' + ) + return + + def on_set_config(result): + self.console.write('{!success!}Configuration value successfully updated.') + + self.console.write('Setting "%s" to: %s' % (key, val)) + return client.core.set_config({key: val}).addCallback(on_set_config) + + def complete(self, text): + return [k for k in component.get('CoreConfig') if k.startswith(text)] |