1from distutils.errors import DistutilsOptionError
2
3from setuptools.command.setopt import edit_config, option_base, config_file
4
5
6def shquote(arg):
7    """Quote an argument for later parsing by shlex.split()"""
8    for c in '"', "'", "\\", "#":
9        if c in arg:
10            return repr(arg)
11    if arg.split() != [arg]:
12        return repr(arg)
13    return arg
14
15
16class alias(option_base):
17    """Define a shortcut that invokes one or more commands"""
18
19    description = "define a shortcut to invoke one or more commands"
20    command_consumes_arguments = True
21
22    user_options = [
23        ('remove', 'r', 'remove (unset) the alias'),
24    ] + option_base.user_options
25
26    boolean_options = option_base.boolean_options + ['remove']
27
28    def initialize_options(self):
29        option_base.initialize_options(self)
30        self.args = None
31        self.remove = None
32
33    def finalize_options(self):
34        option_base.finalize_options(self)
35        if self.remove and len(self.args) != 1:
36            raise DistutilsOptionError(
37                "Must specify exactly one argument (the alias name) when "
38                "using --remove"
39            )
40
41    def run(self):
42        aliases = self.distribution.get_option_dict('aliases')
43
44        if not self.args:
45            print("Command Aliases")
46            print("---------------")
47            for alias in aliases:
48                print("setup.py alias", format_alias(alias, aliases))
49            return
50
51        elif len(self.args) == 1:
52            alias, = self.args
53            if self.remove:
54                command = None
55            elif alias in aliases:
56                print("setup.py alias", format_alias(alias, aliases))
57                return
58            else:
59                print("No alias definition found for %r" % alias)
60                return
61        else:
62            alias = self.args[0]
63            command = ' '.join(map(shquote, self.args[1:]))
64
65        edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run)
66
67
68def format_alias(name, aliases):
69    source, command = aliases[name]
70    if source == config_file('global'):
71        source = '--global-config '
72    elif source == config_file('user'):
73        source = '--user-config '
74    elif source == config_file('local'):
75        source = ''
76    else:
77        source = '--filename=%r' % source
78    return source + name + ' ' + command
79