Jan Dittberner
09180938f1
* make code PEP8 clean (addresses #18) * add copyright information to all python files git-svn-id: file:///home/www/usr01/svn/gnuviechadmin/trunk@257 a67ec6bc-e5d5-0310-a910-815c51eb3124
225 lines
8 KiB
Python
225 lines
8 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
# USA.
|
|
#
|
|
# Version: $Id$
|
|
import getopt
|
|
import sys
|
|
import logging
|
|
from gnuviechadmin.exceptions import GnuviechadminError
|
|
|
|
|
|
class CliCommand:
|
|
"""Base class for command line interface.
|
|
|
|
A specific implementation class must define the fields name,
|
|
description and _optionmap.
|
|
|
|
The field name is the name of the subcommand.
|
|
|
|
The field description is a short, one line description of the
|
|
command.
|
|
|
|
The field _optionmap is a map which maps the subcommand names to
|
|
lists of tuples. Each tuple consists of four elements. The first
|
|
element is a list of command line arguments, short arguments start
|
|
with dash, long arguments with a double dash. The second element
|
|
is the name of the field in the data map of the command, it will
|
|
directly be sent to the underlying entity. The third field is a
|
|
description for the group of command line options in field
|
|
one. The fourth field is True for mandatory fields and False
|
|
otherwise.
|
|
"""
|
|
|
|
def _usage(self):
|
|
"""This method shows usage information. The implementation
|
|
relies on the information in the fields name, description and
|
|
_optionmap in the implementation classes."""
|
|
print """GNUViechAdmin command line interface
|
|
|
|
Subcommand: %(command)s
|
|
|
|
%(description)s
|
|
|
|
Usage:
|
|
|
|
%(called)s %(command)s -h|--help
|
|
|
|
gives this usage information.
|
|
|
|
Common options:
|
|
|
|
%(option)s
|
|
%(mandatory)s %(optiondesc)s
|
|
""" % {'called': sys.argv[0],
|
|
'command': self.name,
|
|
'description': self.description,
|
|
'option': '-v, --verbose',
|
|
'optiondesc': 'verbose operation',
|
|
'mandatory': " "}
|
|
for commandname in self._optionmap.keys():
|
|
cmdl = "%(called)s %(command)s %(subcommand)s [-v|--verbose]" % {
|
|
'called': sys.argv[0],
|
|
'command': self.name,
|
|
'subcommand': commandname}
|
|
desc = """
|
|
%s
|
|
""" % (self._optionmap[commandname][0])
|
|
for (options, field, optiondesc, mandatory) in \
|
|
self._optionmap[commandname][1]:
|
|
cmd = " "
|
|
pairs = []
|
|
for option in options:
|
|
if field:
|
|
if option.startswith("--"):
|
|
pairs.append("%s=<%s>" % (option, field))
|
|
else:
|
|
pairs.append("%s <%s>" % (option, field))
|
|
else:
|
|
pairs.append(option)
|
|
if not mandatory:
|
|
cmd = cmd + "["
|
|
cmd = cmd + "|".join(pairs)
|
|
if not mandatory:
|
|
cmd = cmd + "]"
|
|
descmap = {
|
|
'option': ", ".join(pairs),
|
|
'optiondesc': optiondesc,
|
|
'mandatory': ' '}
|
|
if mandatory:
|
|
descmap['mandatory'] = '*'
|
|
desc = desc + """ %(option)s
|
|
%(mandatory)s %(optiondesc)s
|
|
""" % descmap
|
|
if (len(cmdl) + len(cmd)) > 79:
|
|
print cmdl
|
|
cmdl = cmd
|
|
else:
|
|
cmdl = cmdl + cmd
|
|
print cmdl
|
|
print desc
|
|
print "Mandatory options are marked with *"
|
|
|
|
def _subcommands(self):
|
|
"""Convenience method for retrieving the subcommand names from
|
|
the _optionmap field."""
|
|
return self._optionmap.keys()
|
|
|
|
def _longopts(self, subcommand):
|
|
"""This method retrieves available long options in a format
|
|
valid for getopt.gnu_getopt(...) from the _optionmap field."""
|
|
longopts = []
|
|
for cur in [(option[0], option[1]) for option in \
|
|
self._optionmap[subcommand][1]]:
|
|
for command in cur[0]:
|
|
if command.startswith("--"):
|
|
if cur[1]:
|
|
longopts.append(command[2:] + "=")
|
|
else:
|
|
longopts.append(command[2:])
|
|
return longopts
|
|
|
|
def _shortopts(self, subcommand):
|
|
"""This method retrieves available short options in a format
|
|
valid for getopt.gnu_getopt(...) from the _optionmap field."""
|
|
shortopts = ""
|
|
for cur in [(option[0], option[1]) for option in \
|
|
self._optionmap[subcommand][1]]:
|
|
for command in cur[0]:
|
|
if not command.startswith("--"):
|
|
if cur[1]:
|
|
shortopts = shortopts + command[1:] + ":"
|
|
else:
|
|
shortopts = shortopts + command[1:]
|
|
return shortopts
|
|
|
|
def _checkrequired(self, subcommand):
|
|
"""Checks whether the required fields of the given subcommand
|
|
are set."""
|
|
reqcheck = [True, []]
|
|
for req in [option for option in \
|
|
self._optionmap[subcommand][1] if option[3]]:
|
|
if not req[1] in self._data:
|
|
reqcheck[0] = False
|
|
reqcheck[1].append(""" %s
|
|
* %s""" % (", ".join(req[0]), req[2]))
|
|
return reqcheck
|
|
|
|
def _handleoption(self, subcommand, o, a):
|
|
"""Handles a command line option by assigning it to the
|
|
matching key as defined in the _optionmap property of the
|
|
implementation class."""
|
|
optionmap = [(option[0], option[1]) for option in \
|
|
self._optionmap[subcommand][1]]
|
|
if optionmap:
|
|
for (options, datakey) in optionmap:
|
|
if o in options:
|
|
self._data[datakey] = a
|
|
|
|
def _execute(self, subcommand):
|
|
"""This method is called when the subcommand of the command is
|
|
executed."""
|
|
raise NotImplementedError
|
|
|
|
def _parseopts(self, subcommand, args):
|
|
"""This method parses the options given on the command line."""
|
|
longopts = ["help", "verbose"]
|
|
longopts.extend(self._longopts(subcommand))
|
|
try:
|
|
opts, args = getopt.gnu_getopt(
|
|
args,
|
|
"hv" + self._shortopts(subcommand),
|
|
longopts)
|
|
except getopt.GetoptError:
|
|
self._usage()
|
|
sys.exit(2)
|
|
self._verbose = False
|
|
for o, a in opts:
|
|
if o in ("-v", "--verbose"):
|
|
self._verbose = True
|
|
if o in ("-h", "--help"):
|
|
self._usage()
|
|
sys.exit()
|
|
self._handleoption(subcommand, o, a)
|
|
|
|
def __init__(self, args):
|
|
"""This initializes the command with the given command line
|
|
arguments and executes it."""
|
|
self.logger = logging.getLogger("%s.%s" % (
|
|
self.__class__.__module__, self.__class__.__name__))
|
|
self._data = {}
|
|
if len(args) > 0:
|
|
if args[0] in self._subcommands():
|
|
self._parseopts(args[0], args[1:])
|
|
reqcheck = self._checkrequired(args[0])
|
|
if reqcheck[0]:
|
|
try:
|
|
self._execute(args[0])
|
|
except GnuviechadminError, e:
|
|
print e
|
|
else:
|
|
self._usage()
|
|
print """
|
|
the following required arguments are missing:
|
|
"""
|
|
print "\n".join(reqcheck[1])
|
|
else:
|
|
self._usage()
|
|
print "invalid sub command"
|
|
else:
|
|
self._usage()
|