From ee563d054a35f934c37811e97d24d946b55c0076 Mon Sep 17 00:00:00 2001 From: Marco Mascheroni Date: Fri, 27 Mar 2015 15:43:10 +0100 Subject: [PATCH] Refactor command line option parsing code --- bin/crab | 49 +-------- src/python/CRABClient/CRABOptParser.py | 109 +++++++++++++++++++ src/python/CRABClient/Commands/SubCommand.py | 54 +++------ 3 files changed, 126 insertions(+), 86 deletions(-) create mode 100644 src/python/CRABClient/CRABOptParser.py diff --git a/bin/crab b/bin/crab index 51d9810e2..3b97ddf8f 100755 --- a/bin/crab +++ b/bin/crab @@ -18,11 +18,10 @@ import pycurl import logging import logging.handlers - from httplib import HTTPException -from optparse import OptionParser, OptionGroup from socket import error as SocketError +from CRABClient.CRABOptParser import CRABOptParser from CRABClient import __version__ as client_version from CRABClient.ClientUtilities import getAvailCommands, logfilter , uploadlogfile, getLoggers, StopExecution from CRABClient.ClientExceptions import ClientException @@ -40,17 +39,6 @@ class MyNullHandler(logging.Handler): pass -class MyParser(OptionParser): - """ - Allows to make OptionParser behave how we prefer - """ - def format_epilog(self, formatter): - """ - do not strip the new lines from the epilog - """ - return self.epilog - - class CRABClient(object): def __init__( self ): """ @@ -58,43 +46,14 @@ class CRABClient(object): at appropriate level """ - self.sub_commands = getAvailCommands() - usage = "usage: %prog [options] COMMAND [command-options] [args]" - epilog = '\nValid commands are: \n' - for k in sorted(self.sub_commands.keys()): - epilog += ' %s' % self.sub_commands[k].name - epilog += ''.join( [' (%s)' % name for name in self.sub_commands[k].shortnames ] ) - epilog += '\n' - epilog += "To get single command help run:\n crab command --help|-h\n" - - epilog += '\nFor more information on how to run CRAB-3 please follow this link:\n' - epilog += 'https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookCRAB3Tutorial\n' - - self.parser = MyParser( usage = usage, - epilog = epilog, - version = "CRAB client v%s" % client_version - ) - - # This is the important bit - self.parser.disable_interspersed_args() - self.parser.add_option( "--quiet", - action = "store_true", - dest = "quiet", - default = False, - help = "don't print any messages to stdout" ) - - self.parser.add_option( "--debug", - action = "store_true", - dest = "debug", - default = False, - help = "print extra messages to stdout" ) + self.subCommands = getAvailCommands() + self.parser = CRABOptParser(self.subCommands) def __call__(self): (options, args) = self.parser.parse_args() - #the default the logfile destination is /crab.log, it will be changed when we have loaded the taskname loglevel = logging.INFO if options.quiet: @@ -158,7 +117,7 @@ class CRABClient(object): sub_cmd = None try: - sub_cmd = next( v for k,v in self.sub_commands.items() if args[0] in v.shortnames or args[0]==v.name) + sub_cmd = next( v for k,v in self.subCommands.items() if args[0] in v.shortnames or args[0]==v.name) except StopIteration: print "'" + str(args[0]) + "' is not a valid command." print self.parser.print_help() diff --git a/src/python/CRABClient/CRABOptParser.py b/src/python/CRABClient/CRABOptParser.py new file mode 100644 index 000000000..32bc68f04 --- /dev/null +++ b/src/python/CRABClient/CRABOptParser.py @@ -0,0 +1,109 @@ +from optparse import OptionParser + +from CRABClient import __version__ as client_version +from CRABClient.ClientUtilities import getAvailCommands +from CRABClient.ClientUtilities import SERVICE_INSTANCES + + +class CRABOptParser(OptionParser): + """ + Allows to make OptionParser behave how we prefer + """ + + def __init__(self, subCommands=None): + """ Initialize the option parser used in the the client. That's only the first step parsing + which basically creates the help and looks for the --debug/--quiet options. Each command + than has its own set of arguments (some are shared, see CRABCmdOptParser ). + + subCommands: if present used to prepare a nice help summary for all the commands + """ + usage = "usage: %prog [options] COMMAND [command-options] [args]" + epilog = "" + if subCommands: + epilog = '\nValid commands are: \n' + for k in sorted(subCommands.keys()): + epilog += ' %s' % subCommands[k].name + epilog += ''.join( [' (%s)' % name for name in subCommands[k].shortnames ] ) + epilog += '\n' + epilog += "To get single command help run:\n crab command --help|-h\n" + + epilog += '\nFor more information on how to run CRAB-3 please follow this link:\n' + epilog += 'https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookCRAB3Tutorial\n' + + OptionParser.__init__(self, usage = usage, epilog = epilog, + version = "CRAB client v%s" % client_version + ) + + # This is the important bit + self.disable_interspersed_args() + + self.add_option( "--quiet", + action = "store_true", + dest = "quiet", + default = False, + help = "don't print any messages to stdout" ) + + self.add_option( "--debug", + action = "store_true", + dest = "debug", + default = False, + help = "print extra messages to stdout" ) + + + def format_epilog(self, formatter): + """ + do not strip the new lines from the epilog + """ + return self.epilog + + + +class CRABCmdOptParser(OptionParser): + """ A class that extract the pieces for parsing the command line arguments + of the CRAB commands. + + """ + + def __init__(self, cmdname, doc, disable_interspersed_args): + """ + doc: the description of the command. Taken from self.__doc__ + disable_interspersed_args: some commands (e.g.: submit) allow to overwrite configuration parameters + """ + usage = "usage: %prog " + cmdname + " [options] [args]" + OptionParser.__init__(self, description = doc, usage = usage, add_help_option = True) + if disable_interspersed_args: + self.disable_interspersed_args() + + + def addCommonOptions(self, cmdconf): + """ + cmdconf: the command configuration from the ClientMapping + """ + self.add_option("--proxy", + dest = "proxy", + default = False, + help = "Use the given proxy. Skip Grid proxy creation and myproxy delegation.") + + if cmdconf['requiresTaskOption']: + self.add_option("-d", "--dir", + dest = "task", + default = None, + help = "Path to the CRAB project directory for which the crab command should be executed.") + self.add_option("-t", "--task", + dest = "oldtask", + default = None, + help = "Deprecated option renamed to -d/--dir in CRAB v3.3.12.") + + if cmdconf['requiresProxyVOOptions']: + self.add_option("--voRole", + dest = "voRole", + default = None) + self.add_option("--voGroup", + dest = "voGroup", + default = None) + + if cmdconf['requiresREST']: + self.add_option("--instance", + dest = "instance", + type = "string", + help = "Running instance of CRAB service. Valid values are %s." % str(SERVICE_INSTANCES.keys())) diff --git a/src/python/CRABClient/Commands/SubCommand.py b/src/python/CRABClient/Commands/SubCommand.py index b27801fae..5a554d9e5 100644 --- a/src/python/CRABClient/Commands/SubCommand.py +++ b/src/python/CRABClient/Commands/SubCommand.py @@ -3,20 +3,21 @@ import imp import json import types -from optparse import OptionParser from ast import literal_eval +from optparse import OptionParser -from CRABClient.ClientUtilities import loadCache, getWorkArea, server_info, createWorkArea -from CRABClient.ClientUtilities import BASEURL, SERVICE_INSTANCES -from CRABClient import SpellChecker import CRABClient.Emulator -from CRABClient.ClientExceptions import ConfigurationException, MissingOptionException, EnvironmentException, UnknownOptionException -from CRABClient.ClientMapping import renamedParams, commandsConfiguration, configParametersInfo, getParamDefaultValue -from CRABClient.CredentialInteractions import CredentialInteractions +from CRABClient import SpellChecker from CRABClient.__init__ import __version__ from CRABClient.ClientUtilities import colors -from WMCore.Credential.Proxy import Proxy +from CRABClient.CRABOptParser import CRABCmdOptParser +from CRABClient.ClientUtilities import BASEURL, SERVICE_INSTANCES +from CRABClient.CredentialInteractions import CredentialInteractions +from CRABClient.ClientUtilities import loadCache, getWorkArea, server_info, createWorkArea +from CRABClient.ClientMapping import renamedParams, commandsConfiguration, configParametersInfo, getParamDefaultValue +from CRABClient.ClientExceptions import ConfigurationException, MissingOptionException, EnvironmentException, UnknownOptionException +from WMCore.Credential.Proxy import Proxy from WMCore.Configuration import loadConfigurationFile, Configuration #if certificates in myproxy expires in less than RENEW_MYPROXY_THRESHOLD days renew them @@ -106,7 +107,7 @@ def _extractReason(self, configname, re): modPath[1], modPath[2]) except Exception, ex: msg = str(ex) - + return msg @@ -232,10 +233,7 @@ def __init__(self, logger, cmdargs = None, disable_interspersed_args = False): self.crab3dic = self.getConfiDict() ## The options parser. - self.usage = "usage: %prog " + self.name + " [options] [args]" - self.parser = OptionParser(description = self.__doc__, usage = self.usage, add_help_option = True) - if disable_interspersed_args: - self.parser.disable_interspersed_args() + self.parser = CRABCmdOptParser(self.name, self.__doc__, disable_interspersed_args) ## Define the command options. self.setSuperOptions() @@ -511,38 +509,12 @@ def setOptions(self): def setSuperOptions(self): try: + #add command related options self.setOptions() except NotImplementedError: pass - self.parser.add_option("--proxy", - dest = "proxy", - default = False, - help = "Use the given proxy. Skip Grid proxy creation and myproxy delegation.") - - if self.cmdconf['requiresTaskOption']: - self.parser.add_option("-d", "--dir", - dest = "task", - default = None, - help = "Path to the CRAB project directory for which the crab command should be executed.") - self.parser.add_option("-t", "--task", - dest = "oldtask", - default = None, - help = "Deprecated option renamed to -d/--dir in CRAB v3.3.12.") - - if self.cmdconf['requiresProxyVOOptions']: - self.parser.add_option("--voRole", - dest = "voRole", - default = None) - self.parser.add_option("--voGroup", - dest = "voGroup", - default = None) - - if self.cmdconf['requiresREST']: - self.parser.add_option("--instance", - dest = "instance", - type = "string", - help = "Running instance of CRAB service. Valid values are %s." % str(SERVICE_INSTANCES.keys())) + self.parser.addCommonOptions(self.cmdconf) def validateOptions(self):