root / logilab.pylintinstaller / logilab / common / clcommands.py

Revision 202:d67e86292521, 4.4 kB (checked in by tziade@…, 9 months ago)

added logilab.pylintinstaller

Line 
1# Copyright (c) 2004-2007 LOGILAB S.A. (Paris, FRANCE).
2# http://www.logilab.fr/ -- mailto:contact@logilab.fr
3#
4# This program is free software; you can redistribute it and/or modify it under
5# the terms of the GNU General Public License as published by the Free Software
6# Foundation; either version 2 of the License, or (at your option) any later
7# version.
8#
9# This program is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License along with
14# this program; if not, write to the Free Software Foundation, Inc.,
15# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16"""provides helper functions to handle a command line tool providing more than
17one command
18e.g called as "tool command [options] args..." where <options> and <args> are
19command'specific
20"""
21
22import sys
23from os.path import basename
24
25from logilab.common.configuration import Configuration
26
27
28DEFAULT_COPYRIGHT = '''\
29Copyright (c) 2004-2007 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
30http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
31
32
33class BadCommandUsage(Exception):
34    """Raised when an unknown command is used or when a command is not
35    correctly used
36    """
37
38
39class Command(Configuration):
40    """base class for command line commands"""
41    arguments = ''
42    name = ''
43    # max/min args, None meaning unspecified
44    min_args = None
45    max_args = None
46    def __init__(self, __doc__=None, version=None):
47        if __doc__:
48            usage = __doc__ % (self.name, self.arguments,
49                               self.__doc__.replace('    ', ''))
50        else:
51            usage = self.__doc__.replace('    ', '')
52        Configuration.__init__(self, usage=usage, version=version)
53
54    def check_args(self, args):
55        """check command's arguments are provided"""
56        if self.min_args is not None and len(args) < self.min_args:
57            raise BadCommandUsage('missing argument')
58        if self.max_args is not None and len(args) > self.max_args:
59            raise BadCommandUsage('too many arguments')
60       
61    def run(self, args):
62        """run the command with its specific arguments"""
63        raise NotImplementedError()
64
65
66def pop_arg(args_list, expected_size_after=0, msg="Missing argument"):
67    """helper function to get and check command line arguments"""
68    try:
69        value = args_list.pop(0)
70    except IndexError:
71        raise BadCommandUsage(msg)
72    if expected_size_after is not None and len(args_list) > expected_size_after:
73        raise BadCommandUsage('Too much arguments')
74    return value
75
76
77_COMMANDS = {}
78
79def register_commands(commands):
80    """register existing commands"""
81    for command_klass in commands:
82        _COMMANDS[command_klass.name] = command_klass
83
84
85def main_usage(status=0, __doc__=None, copyright=DEFAULT_COPYRIGHT):
86    """display usage for the main program (ie when no command supplied)
87    and exit
88    """
89    commands = _COMMANDS.keys()
90    commands.sort()
91    doc = __doc__ % ('<command>', '<command arguments>',
92                     '''\
93Type "%prog <command> --help" for more information about a specific
94command. Available commands are :\n''')
95    doc = doc.replace('%prog', basename(sys.argv[0]))
96    print 'usage:', doc
97    max_len = max([len(cmd) for cmd in commands]) # list comprehension for py 2.3 support
98    padding = ' '*max_len
99    for command in commands:
100        cmd = _COMMANDS[command]
101        title = cmd.__doc__.split('.')[0]
102        print ' ', (command+padding)[:max_len], title
103    print '\n', copyright
104    sys.exit(status)
105
106
107def cmd_run(cmdname, *args):
108    try:
109        command = _COMMANDS[cmdname](__doc__='%%prog %s %s\n\n%s')
110    except KeyError:
111        raise BadCommandUsage('no %s command' % cmdname)
112    args = command.load_command_line_configuration(args)
113    command.check_args(args)
114    try:
115        command.run(args)
116    except KeyboardInterrupt:
117        print 'interrupted'
118    except BadCommandUsage, err:
119        print 'ERROR: ', err
120        print command.help()
121
122       
123def main_run(args, doc):
124    """command line tool"""
125    try:
126        arg = args.pop(0)
127    except IndexError:
128        main_usage(status=1, __doc__=doc)
129    if arg in ('-h', '--help'):
130        main_usage(__doc__=doc)
131    try:
132        cmd_run(arg, *args)
133    except BadCommandUsage, err:
134        print 'ERROR: ', err
135        main_usage(1, doc)
Note: See TracBrowser for help on using the browser.