summaryrefslogtreecommitdiff
path: root/logilab/common/clcommands.py
diff options
context:
space:
mode:
Diffstat (limited to 'logilab/common/clcommands.py')
-rw-r--r--logilab/common/clcommands.py126
1 files changed, 77 insertions, 49 deletions
diff --git a/logilab/common/clcommands.py b/logilab/common/clcommands.py
index 4778b99..f89a4b4 100644
--- a/logilab/common/clcommands.py
+++ b/logilab/common/clcommands.py
@@ -42,6 +42,7 @@ class BadCommandUsage(Exception):
Trigger display of command usage.
"""
+
class CommandError(Exception):
"""Raised when a command can't be processed and we want to display it and
exit, without traceback nor usage displayed.
@@ -50,6 +51,7 @@ class CommandError(Exception):
# command line access point ####################################################
+
class CommandLine(dict):
"""Usage:
@@ -77,9 +79,17 @@ class CommandLine(dict):
* `logger`, logger to propagate to commands, default to
`logging.getLogger(self.pgm))`
"""
- def __init__(self, pgm=None, doc=None, copyright=None, version=None,
- rcfile=None, logthreshold=logging.ERROR,
- check_duplicated_command=True):
+
+ def __init__(
+ self,
+ pgm=None,
+ doc=None,
+ copyright=None,
+ version=None,
+ rcfile=None,
+ logthreshold=logging.ERROR,
+ check_duplicated_command=True,
+ ):
if pgm is None:
pgm = basename(sys.argv[0])
self.pgm = pgm
@@ -93,8 +103,9 @@ class CommandLine(dict):
def register(self, cls, force=False):
"""register the given :class:`Command` subclass"""
- assert not self.check_duplicated_command or force or not cls.name in self, \
- 'a command %s is already defined' % cls.name
+ assert not self.check_duplicated_command or force or not cls.name in self, (
+ "a command %s is already defined" % cls.name
+ )
self[cls.name] = cls
return cls
@@ -107,20 +118,22 @@ class CommandLine(dict):
Terminate by :exc:`SystemExit`
"""
- init_log(debug=True, # so that we use StreamHandler
- logthreshold=self.logthreshold,
- logformat='%(levelname)s: %(message)s')
+ init_log(
+ debug=True, # so that we use StreamHandler
+ logthreshold=self.logthreshold,
+ logformat="%(levelname)s: %(message)s",
+ )
try:
arg = args.pop(0)
except IndexError:
self.usage_and_exit(1)
- if arg in ('-h', '--help'):
+ if arg in ("-h", "--help"):
self.usage_and_exit(0)
- if self.version is not None and arg in ('--version'):
+ if self.version is not None and arg in ("--version"):
print(self.version)
sys.exit(0)
rcfile = self.rcfile
- if rcfile is not None and arg in ('-C', '--rc-file'):
+ if rcfile is not None and arg in ("-C", "--rc-file"):
try:
rcfile = args.pop(0)
arg = args.pop(0)
@@ -129,19 +142,19 @@ class CommandLine(dict):
try:
command = self.get_command(arg)
except KeyError:
- print('ERROR: no %s command' % arg)
+ print("ERROR: no %s command" % arg)
print()
self.usage_and_exit(1)
try:
sys.exit(command.main_run(args, rcfile))
except KeyboardInterrupt as exc:
- print('Interrupted', end=' ')
+ print("Interrupted", end=" ")
if str(exc):
- print(': %s' % exc, end=' ')
+ print(": %s" % exc, end=" ")
print()
sys.exit(4)
except BadCommandUsage as err:
- print('ERROR:', err)
+ print("ERROR:", err)
print()
print(command.help())
sys.exit(1)
@@ -166,32 +179,44 @@ class CommandLine(dict):
"""display usage for the main program (i.e. when no command supplied)
and exit
"""
- print('usage:', self.pgm, end=' ')
+ print("usage:", self.pgm, end=" ")
if self.rcfile:
- print('[--rc-file=<configuration file>]', end=' ')
- print('<command> [options] <command argument>...')
+ print("[--rc-file=<configuration file>]", end=" ")
+ print("<command> [options] <command argument>...")
if self.doc:
- print('\n%s' % self.doc)
- print('''
+ print("\n%s" % self.doc)
+ print(
+ """
Type "%(pgm)s <command> --help" for more information about a specific
-command. Available commands are :\n''' % self.__dict__)
+command. Available commands are :\n"""
+ % self.__dict__
+ )
max_len = max([len(cmd) for cmd in self])
- padding = ' ' * max_len
+ padding = " " * max_len
for cmdname, cmd in sorted(self.items()):
if not cmd.hidden:
- print(' ', (cmdname + padding)[:max_len], cmd.short_description())
+ print(" ", (cmdname + padding)[:max_len], cmd.short_description())
if self.rcfile:
- print('''
+ print(
+ """
Use --rc-file=<configuration file> / -C <configuration file> before the command
to specify a configuration file. Default to %s.
-''' % self.rcfile)
- print('''%(pgm)s -h/--help
- display this usage information and exit''' % self.__dict__)
+"""
+ % self.rcfile
+ )
+ print(
+ """%(pgm)s -h/--help
+ display this usage information and exit"""
+ % self.__dict__
+ )
if self.version:
- print('''%(pgm)s -v/--version
- display version configuration and exit''' % self.__dict__)
+ print(
+ """%(pgm)s -v/--version
+ display version configuration and exit"""
+ % self.__dict__
+ )
if self.copyright:
- print('\n', self.copyright)
+ print("\n", self.copyright)
def usage_and_exit(self, status):
self.usage()
@@ -200,6 +225,7 @@ to specify a configuration file. Default to %s.
# base command classes #########################################################
+
class Command(Configuration):
"""Base class for command line commands.
@@ -219,8 +245,8 @@ class Command(Configuration):
* `options`, options list, as allowed by :mod:configuration
"""
- arguments = ''
- name = ''
+ arguments = ""
+ name = ""
# hidden from help ?
hidden = False
# max/min args, None meaning unspecified
@@ -229,24 +255,23 @@ class Command(Configuration):
@classmethod
def description(cls):
- return cls.__doc__.replace(' ', '')
+ return cls.__doc__.replace(" ", "")
@classmethod
def short_description(cls):
- return cls.description().split('.')[0]
+ return cls.description().split(".")[0]
def __init__(self, logger):
- usage = '%%prog %s %s\n\n%s' % (self.name, self.arguments,
- self.description())
+ usage = "%%prog %s %s\n\n%s" % (self.name, self.arguments, self.description())
Configuration.__init__(self, usage=usage)
self.logger = logger
def check_args(self, args):
"""check command's arguments are provided"""
if self.min_args is not None and len(args) < self.min_args:
- raise BadCommandUsage('missing argument')
+ raise BadCommandUsage("missing argument")
if self.max_args is not None and len(args) > self.max_args:
- raise BadCommandUsage('too many arguments')
+ raise BadCommandUsage("too many arguments")
def main_run(self, args, rcfile=None):
"""Run the command and return status 0 if everything went fine.
@@ -275,8 +300,9 @@ class Command(Configuration):
class ListCommandsCommand(Command):
"""list available commands, useful for bash completion."""
- name = 'listcommands'
- arguments = '[command]'
+
+ name = "listcommands"
+ arguments = "[command]"
hidden = True
def run(self, args):
@@ -285,8 +311,8 @@ class ListCommandsCommand(Command):
command = args.pop()
cmd = _COMMANDS[command]
for optname, optdict in cmd.options:
- print('--help')
- print('--' + optname)
+ print("--help")
+ print("--" + optname)
else:
commands = sorted(_COMMANDS.keys())
for command in commands:
@@ -299,17 +325,19 @@ class ListCommandsCommand(Command):
_COMMANDS = CommandLine()
-DEFAULT_COPYRIGHT = '''\
+DEFAULT_COPYRIGHT = """\
Copyright (c) 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
+http://www.logilab.fr/ -- mailto:contact@logilab.fr"""
+
-@deprecated('use cls.register(cli)')
+@deprecated("use cls.register(cli)")
def register_commands(commands):
"""register existing commands"""
for command_klass in commands:
_COMMANDS.register(command_klass)
-@deprecated('use args.pop(0)')
+
+@deprecated("use args.pop(0)")
def main_run(args, doc=None, copyright=None, version=None):
"""command line tool: run command specified by argument list (without the
program name). Raise SystemExit with status 0 if everything went fine.
@@ -321,7 +349,8 @@ def main_run(args, doc=None, copyright=None, version=None):
_COMMANDS.version = version
_COMMANDS.run(args)
-@deprecated('use args.pop(0)')
+
+@deprecated("use args.pop(0)")
def pop_arg(args_list, expected_size_after=None, msg="Missing argument"):
"""helper function to get and check command line arguments"""
try:
@@ -329,6 +358,5 @@ def pop_arg(args_list, expected_size_after=None, msg="Missing argument"):
except IndexError:
raise BadCommandUsage(msg)
if expected_size_after is not None and len(args_list) > expected_size_after:
- raise BadCommandUsage('too many arguments')
+ raise BadCommandUsage("too many arguments")
return value
-