|  | @@ -1,13 +1,5 @@
 | 
	
		
			
				|  |  | -import errno
 | 
	
		
			
				|  |  | -import os
 | 
	
		
			
				|  |  | -import shlex
 | 
	
		
			
				|  |  | -import signal
 | 
	
		
			
				|  |  | -import socket
 | 
	
		
			
				|  |  | -import sys
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -from celery.utils.compat import defaultdict
 | 
	
		
			
				|  |  | +"""
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -EXAMPLES = """
 | 
	
		
			
				|  |  |  Some examples:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # The "start" command just prints the commands needed to start the workers.
 | 
	
	
		
			
				|  | @@ -70,7 +62,188 @@ Some examples:
 | 
	
		
			
				|  |  |      celeryd -n bar.myhost -c 10
 | 
	
		
			
				|  |  |      celeryd -n baz.myhost -c 10
 | 
	
		
			
				|  |  |      celeryd -n xuzzy.myhost -c 3
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  """
 | 
	
		
			
				|  |  | +import errno
 | 
	
		
			
				|  |  | +import os
 | 
	
		
			
				|  |  | +import shlex
 | 
	
		
			
				|  |  | +import signal
 | 
	
		
			
				|  |  | +import socket
 | 
	
		
			
				|  |  | +import sys
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +from subprocess import Popen
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +from celery.utils.compat import defaultdict
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +SIGNAMES = set(sig for sig in dir(signal)
 | 
	
		
			
				|  |  | +                        if sig.startswith("SIG") and "_" not in sig)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def main():
 | 
	
		
			
				|  |  | +    sys.exit(MultiTool()(sys.argv[1:]))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class MultiTool(object):
 | 
	
		
			
				|  |  | +    retcode = 0  # Final exit code.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __init__(self):
 | 
	
		
			
				|  |  | +        self.commands = {"start": self.start,
 | 
	
		
			
				|  |  | +                         "stop": self.stop,
 | 
	
		
			
				|  |  | +                         "detach": self.detach,
 | 
	
		
			
				|  |  | +                         "names": self.names,
 | 
	
		
			
				|  |  | +                         "expand": self.expand,
 | 
	
		
			
				|  |  | +                         "get": self.get,
 | 
	
		
			
				|  |  | +                         "help": self.help}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __call__(self, argv, cmd="celeryd"):
 | 
	
		
			
				|  |  | +        if len(argv) == 0 or argv[0][0] == "-":
 | 
	
		
			
				|  |  | +            return self.error()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Reserve the --quite|-q/--verbose options.
 | 
	
		
			
				|  |  | +        self.quiet = False
 | 
	
		
			
				|  |  | +        self.verbose = False
 | 
	
		
			
				|  |  | +        if "--quiet" in argv:
 | 
	
		
			
				|  |  | +            self.quiet = argv.pop(argv.index("--quiet"))
 | 
	
		
			
				|  |  | +        if "-q" in argv:
 | 
	
		
			
				|  |  | +            self.quiet = argv.pop(argv.index("-q"))
 | 
	
		
			
				|  |  | +        if "--verbose" in argv:
 | 
	
		
			
				|  |  | +            self.verbose = argv.pop(argv.index("--verbose"))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            self.commands[argv[0]](argv[1:], cmd)
 | 
	
		
			
				|  |  | +        except KeyError:
 | 
	
		
			
				|  |  | +            self.error("Invalid command: %s" % argv[0])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.retcode
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def names(self, argv, cmd):
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | +        print("\n".join(hostname
 | 
	
		
			
				|  |  | +                        for hostname, _, _ in multi_args(p, cmd)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def get(self, argv, cmd):
 | 
	
		
			
				|  |  | +        wanted = argv[0]
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv[1:])
 | 
	
		
			
				|  |  | +        for name, worker, _ in multi_args(p, cmd):
 | 
	
		
			
				|  |  | +            if name == wanted:
 | 
	
		
			
				|  |  | +                print(" ".join(worker))
 | 
	
		
			
				|  |  | +                return
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def start(self, argv, cmd):
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | +        print("\n".join(" ".join(worker)
 | 
	
		
			
				|  |  | +                        for _, worker, _ in multi_args(p, cmd)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def detach(self, argv, cmd):
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | +        p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
	
		
			
				|  |  | +        p.options.setdefault("--logfile", "celeryd@%n.log")
 | 
	
		
			
				|  |  | +        p.options.setdefault("--cmd", "-m celery.bin.celeryd_detach")
 | 
	
		
			
				|  |  | +        retcodes = []
 | 
	
		
			
				|  |  | +        for nodename, argv, _ in multi_args(p, cmd):
 | 
	
		
			
				|  |  | +            self.note("> Starting node %s..." % (nodename, ))
 | 
	
		
			
				|  |  | +            retcodes.append(self.waitexec(argv))
 | 
	
		
			
				|  |  | +        self.retcode = not any(retcodes)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def stop(self, argv, cmd):
 | 
	
		
			
				|  |  | +        from celery import platforms
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | +        restargs = p.args[len(p.values):]
 | 
	
		
			
				|  |  | +        sig = findsig(restargs)
 | 
	
		
			
				|  |  | +        pidfile_template = p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for nodename, _, expander in multi_args(p, cmd):
 | 
	
		
			
				|  |  | +            pidfile = expander(pidfile_template)
 | 
	
		
			
				|  |  | +            try:
 | 
	
		
			
				|  |  | +                pid = platforms.read_pid_from_pidfile(pidfile)
 | 
	
		
			
				|  |  | +            except ValueError:
 | 
	
		
			
				|  |  | +                pass
 | 
	
		
			
				|  |  | +            if pid:
 | 
	
		
			
				|  |  | +                self.note("> Stopping node %s (%s)..." % (nodename, pid))
 | 
	
		
			
				|  |  | +                try:
 | 
	
		
			
				|  |  | +                    os.kill(pid, sig)
 | 
	
		
			
				|  |  | +                except OSError, exc:
 | 
	
		
			
				|  |  | +                    if exc.errno != errno.ESRCH:
 | 
	
		
			
				|  |  | +                        raise
 | 
	
		
			
				|  |  | +                    self.note("Could not stop pid %s: No such process." % pid)
 | 
	
		
			
				|  |  | +            else:
 | 
	
		
			
				|  |  | +                self.note("> Skipping node %s: not alive." % (nodename, ))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def expand(self, argv, cmd=None):
 | 
	
		
			
				|  |  | +        template = argv[0]
 | 
	
		
			
				|  |  | +        p = NamespacedOptionParser(argv[1:])
 | 
	
		
			
				|  |  | +        for _, _, expander in multi_args(p, cmd):
 | 
	
		
			
				|  |  | +            print(expander(template))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def help(self, argv, cmd=None):
 | 
	
		
			
				|  |  | +        say(__doc__)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def usage(self):
 | 
	
		
			
				|  |  | +        say("Please use one of the following commands: %s" % (
 | 
	
		
			
				|  |  | +            ", ".join(self.commands.keys())))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def waitexec(self, argv, path=sys.executable):
 | 
	
		
			
				|  |  | +        pipe = Popen(shlex.split(" ".join([path] + argv)))
 | 
	
		
			
				|  |  | +        self.info("  %s" % " ".join([path] + argv))
 | 
	
		
			
				|  |  | +        retcode = pipe.wait()
 | 
	
		
			
				|  |  | +        if retcode < 0:
 | 
	
		
			
				|  |  | +            self.note("* Child was terminated by signal %s" % (-retcode, ))
 | 
	
		
			
				|  |  | +        elif retcode > 0:
 | 
	
		
			
				|  |  | +            self.note("* Child terminated with failure code %s" % (retcode, ))
 | 
	
		
			
				|  |  | +        return retcode == 0
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def error(self, msg=None):
 | 
	
		
			
				|  |  | +        if msg:
 | 
	
		
			
				|  |  | +            say(msg)
 | 
	
		
			
				|  |  | +        self.usage()
 | 
	
		
			
				|  |  | +        self.retcode = 1
 | 
	
		
			
				|  |  | +        return 1
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def info(self, msg):
 | 
	
		
			
				|  |  | +        if self.verbose:
 | 
	
		
			
				|  |  | +            self.note(msg)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def note(self, msg):
 | 
	
		
			
				|  |  | +        if not self.quiet:
 | 
	
		
			
				|  |  | +            say(msg)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def multi_args(p, cmd="celeryd", append="", prefix="", suffix=""):
 | 
	
		
			
				|  |  | +    names = p.values
 | 
	
		
			
				|  |  | +    options = dict(p.options)
 | 
	
		
			
				|  |  | +    ranges = len(names) == 1
 | 
	
		
			
				|  |  | +    if ranges:
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            noderange = int(names[0])
 | 
	
		
			
				|  |  | +        except ValueError:
 | 
	
		
			
				|  |  | +            pass
 | 
	
		
			
				|  |  | +        else:
 | 
	
		
			
				|  |  | +            names = map(str, range(1, int(names[0]) + 1))
 | 
	
		
			
				|  |  | +            prefix = "celery"
 | 
	
		
			
				|  |  | +    cmd = options.pop("--cmd", cmd)
 | 
	
		
			
				|  |  | +    append = options.pop("--append", append)
 | 
	
		
			
				|  |  | +    hostname = options.pop("--hostname",
 | 
	
		
			
				|  |  | +                   options.pop("-n", socket.gethostname()))
 | 
	
		
			
				|  |  | +    prefix = options.pop("--prefix", prefix) or ""
 | 
	
		
			
				|  |  | +    suffix = options.pop("--suffix", suffix) or "." + hostname
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for ns_name, ns_opts in p.namespaces.items():
 | 
	
		
			
				|  |  | +        if "," in ns_name or (ranges and "-" in ns_name):
 | 
	
		
			
				|  |  | +            for subns in parse_ns_range(ns_name, ranges):
 | 
	
		
			
				|  |  | +                p.namespaces[subns].update(ns_opts)
 | 
	
		
			
				|  |  | +            p.namespaces.pop(ns_name)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for name in names:
 | 
	
		
			
				|  |  | +        this_name = options["-n"] = prefix + name + suffix
 | 
	
		
			
				|  |  | +        expand = abbreviations({"%h": this_name,
 | 
	
		
			
				|  |  | +                                "%n": name})
 | 
	
		
			
				|  |  | +        argv = ([expand(cmd)] +
 | 
	
		
			
				|  |  | +                [format_opt(opt, expand(value))
 | 
	
		
			
				|  |  | +                        for opt, value in p.optmerge(name, options).items()])
 | 
	
		
			
				|  |  | +        if append:
 | 
	
		
			
				|  |  | +            argv.append(expand(append))
 | 
	
		
			
				|  |  | +        yield this_name, argv, expand
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class NamespacedOptionParser(object):
 | 
	
	
		
			
				|  | @@ -159,160 +332,22 @@ def abbreviations(map):
 | 
	
		
			
				|  |  |      return expand
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def multi_args(p, cmd="celeryd", append="", prefix="", suffix=""):
 | 
	
		
			
				|  |  | -    names = p.values
 | 
	
		
			
				|  |  | -    options = dict(p.options)
 | 
	
		
			
				|  |  | -    ranges = len(names) == 1
 | 
	
		
			
				|  |  | -    if ranges:
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            noderange = int(names[0])
 | 
	
		
			
				|  |  | -        except ValueError:
 | 
	
		
			
				|  |  | -            pass
 | 
	
		
			
				|  |  | -        else:
 | 
	
		
			
				|  |  | -            names = map(str, range(1, int(names[0]) + 1))
 | 
	
		
			
				|  |  | -            prefix = "celery"
 | 
	
		
			
				|  |  | -    cmd = options.pop("--cmd", cmd)
 | 
	
		
			
				|  |  | -    append = options.pop("--append", append)
 | 
	
		
			
				|  |  | -    hostname = options.pop("--hostname",
 | 
	
		
			
				|  |  | -                   options.pop("-n", socket.gethostname()))
 | 
	
		
			
				|  |  | -    prefix = options.pop("--prefix", prefix) or ""
 | 
	
		
			
				|  |  | -    suffix = options.pop("--suffix", suffix) or "." + hostname
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for ns_name, ns_opts in p.namespaces.items():
 | 
	
		
			
				|  |  | -        if "," in ns_name or (ranges and "-" in ns_name):
 | 
	
		
			
				|  |  | -            for subns in parse_ns_range(ns_name, ranges):
 | 
	
		
			
				|  |  | -                p.namespaces[subns].update(ns_opts)
 | 
	
		
			
				|  |  | -            p.namespaces.pop(ns_name)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for name in names:
 | 
	
		
			
				|  |  | -        this_name = options["-n"] = prefix + name + suffix
 | 
	
		
			
				|  |  | -        expand = abbreviations({"%h": this_name,
 | 
	
		
			
				|  |  | -                                "%n": name})
 | 
	
		
			
				|  |  | -        line = expand(cmd) + " " + " ".join(
 | 
	
		
			
				|  |  | -                format_opt(opt, expand(value))
 | 
	
		
			
				|  |  | -                    for opt, value in p.optmerge(name, options).items())
 | 
	
		
			
				|  |  | -        if append:
 | 
	
		
			
				|  |  | -            line += " %s" % expand(append)
 | 
	
		
			
				|  |  | -        yield this_name, line, expand
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  def say(m):
 | 
	
		
			
				|  |  |      sys.stderr.write("%s\n" % (m, ))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def detach_worker(argv, path=sys.executable):
 | 
	
		
			
				|  |  | -    if os.fork() == 0:
 | 
	
		
			
				|  |  | -        os.execv(path, [path] + argv)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class MultiTool(object):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def __init__(self):
 | 
	
		
			
				|  |  | -        self.commands = {"start": self.start,
 | 
	
		
			
				|  |  | -                         "stop": self.stop,
 | 
	
		
			
				|  |  | -                         "detach": self.detach,
 | 
	
		
			
				|  |  | -                         "names": self.names,
 | 
	
		
			
				|  |  | -                         "expand": self.expand,
 | 
	
		
			
				|  |  | -                         "get": self.get,
 | 
	
		
			
				|  |  | -                         "help": self.help}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def __call__(self, argv, cmd="celeryd"):
 | 
	
		
			
				|  |  | -        if len(argv) == 0 or argv[0][0] == "-":
 | 
	
		
			
				|  |  | -            self.usage()
 | 
	
		
			
				|  |  | -            sys.exit(0)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            return self.commands[argv[0]](argv[1:], cmd)
 | 
	
		
			
				|  |  | -        except KeyError:
 | 
	
		
			
				|  |  | -            say("Invalid command: %s" % argv[0])
 | 
	
		
			
				|  |  | -            self.usage()
 | 
	
		
			
				|  |  | -            sys.exit(1)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def names(self, argv, cmd):
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | -        print("\n".join(hostname
 | 
	
		
			
				|  |  | -                        for hostname, _, _ in multi_args(p, cmd)))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def get(self, argv, cmd):
 | 
	
		
			
				|  |  | -        wanted = argv[0]
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv[1:])
 | 
	
		
			
				|  |  | -        for name, worker, _ in multi_args(p, cmd):
 | 
	
		
			
				|  |  | -            if name == wanted:
 | 
	
		
			
				|  |  | -                print(worker)
 | 
	
		
			
				|  |  | -                return
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def start(self, argv, cmd):
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | -        print("\n".join(worker
 | 
	
		
			
				|  |  | -                        for _, worker, _ in multi_args(p, cmd)))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def detach(self, argv, cmd):
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | -        p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
	
		
			
				|  |  | -        p.options.setdefault("--logfile", "celeryd@%n.log")
 | 
	
		
			
				|  |  | -        p.options.setdefault("--cmd", "-m celery.bin.celeryd_detach")
 | 
	
		
			
				|  |  | -        for nodename, argv, _ in multi_args(p, cmd):
 | 
	
		
			
				|  |  | -            print("> Starting node %s..." % (nodename, ))
 | 
	
		
			
				|  |  | -            print(argv)
 | 
	
		
			
				|  |  | -            detach_worker(shlex.split(argv))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def stop(self, argv, cmd):
 | 
	
		
			
				|  |  | -        from celery import platforms
 | 
	
		
			
				|  |  | -        signames = set(sig for sig in dir(signal)
 | 
	
		
			
				|  |  | -                            if sig.startswith("SIG") and "_" not in sig)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def findsig(args, default=signal.SIGTERM):
 | 
	
		
			
				|  |  | -            for arg in reversed(args):
 | 
	
		
			
				|  |  | -                if len(arg) == 2 and arg[0] == "-" and arg[1].isdigit():
 | 
	
		
			
				|  |  | -                    try:
 | 
	
		
			
				|  |  | -                        return int(arg[1])
 | 
	
		
			
				|  |  | -                    except ValueError:
 | 
	
		
			
				|  |  | -                        pass
 | 
	
		
			
				|  |  | -                if arg[0] == "-":
 | 
	
		
			
				|  |  | -                    maybe_sig = "SIG" + arg[1:]
 | 
	
		
			
				|  |  | -                    if maybe_sig in signames:
 | 
	
		
			
				|  |  | -                        return getattr(signal, maybe_sig)
 | 
	
		
			
				|  |  | -            return default
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv)
 | 
	
		
			
				|  |  | -        restargs = p.args[len(p.values):]
 | 
	
		
			
				|  |  | -        sig = findsig(restargs)
 | 
	
		
			
				|  |  | -        pidfile_template = p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        for nodename, _, expander in multi_args(p, cmd):
 | 
	
		
			
				|  |  | -            pidfile = expander(pidfile_template)
 | 
	
		
			
				|  |  | +def findsig(args, default=signal.SIGTERM):
 | 
	
		
			
				|  |  | +    for arg in reversed(args):
 | 
	
		
			
				|  |  | +        if len(arg) == 2 and arg[0] == "-" and arg[1].isdigit():
 | 
	
		
			
				|  |  |              try:
 | 
	
		
			
				|  |  | -                pid = platforms.read_pid_from_pidfile(pidfile)
 | 
	
		
			
				|  |  | +                return int(arg[1])
 | 
	
		
			
				|  |  |              except ValueError:
 | 
	
		
			
				|  |  |                  pass
 | 
	
		
			
				|  |  | -            if pid:
 | 
	
		
			
				|  |  | -                print("> Stopping node %s (%s)..." % (nodename, pid))
 | 
	
		
			
				|  |  | -                try:
 | 
	
		
			
				|  |  | -                    os.kill(pid, sig)
 | 
	
		
			
				|  |  | -                except OSError, exc:
 | 
	
		
			
				|  |  | -                    if exc.errno != errno.ESRCH:
 | 
	
		
			
				|  |  | -                        raise
 | 
	
		
			
				|  |  | -                    print("Could not stop pid %s: No such process." % pid)
 | 
	
		
			
				|  |  | -            else:
 | 
	
		
			
				|  |  | -                print("> Skipping node %s: not alive." % (nodename, ))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def expand(self, argv, cmd=None):
 | 
	
		
			
				|  |  | -        template = argv[0]
 | 
	
		
			
				|  |  | -        p = NamespacedOptionParser(argv[1:])
 | 
	
		
			
				|  |  | -        for _, _, expander in multi_args(p, cmd):
 | 
	
		
			
				|  |  | -            print(expander(template))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def help(self, argv, cmd=None):
 | 
	
		
			
				|  |  | -        say(EXAMPLES)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def usage(self):
 | 
	
		
			
				|  |  | -        say("Please use one of the following commands: %s" % (
 | 
	
		
			
				|  |  | -            ", ".join(self.commands.keys())))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def main():
 | 
	
		
			
				|  |  | -    MultiTool()(sys.argv[1:])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        if arg[0] == "-":
 | 
	
		
			
				|  |  | +            maybe_sig = "SIG" + arg[1:]
 | 
	
		
			
				|  |  | +            if maybe_sig in SIGNAMES:
 | 
	
		
			
				|  |  | +                return getattr(signal, maybe_sig)
 | 
	
		
			
				|  |  | +    return default
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  if __name__ == "__main__":              # pragma: no cover
 | 
	
		
			
				|  |  |      main()
 |