options.sources_without_dev)
if len(l_dir_to_suppress) == 0:
- sat_command = ("sat -h clean")
- msg = _("Nothing to suppress, Please specify what you want to suppress.")
- logger.error(msg + "\nsee: '%s'\n" % sat_command)
- return RCO.ReturnCode("KO", "specify what you want to suppress")
+ msg = _("Specify what you want to suppress in clean command.")
+ logger.error(msg + "\n(see: 'sat -h clean')")
+ return RCO.ReturnCode("KO", "to suppress in clean command")
# Check with the user if he really wants to suppress the directories
- if not runner.options.batch:
- msg = _("Remove the following directories ?\n")
- for directory in l_dir_to_suppress:
- msg += " %s\n" % directory
- logger.info(msg)
- rep = input(_("Are you sure you want to continue? [Yes/No] "))
- if rep.upper() != _("YES"):
- return RCO.ReturnCode("OK", "user do not want to continue")
-
+ msg = UTS.red(_("Remove the following directories:\n"))
+ for directory in l_dir_to_suppress:
+ msg += " %s\n" % directory
+ if runner.getAnswer(msg[:-1]) == "No":
+ return RCO.ReturnCode("OK", "user do not want to continue")
+
# Suppress the list of paths
- suppress_directories(l_dir_to_suppress, logger)
-
+ suppress_directories(l_dir_to_suppress, logger)
return RCO.ReturnCode("OK", "clean done")
default_extension_ignored = \
- 'html png txt js xml cmake gif m4 in pyo pyc doctree css'.split()
+ 'html png txt js xml cmake gif m4 in pyo pyc doctree css'.split()
default_files_ignored = \
- '__init__.py Makefile.am VERSION build_configure README AUTHORS NEWS COPYING ChangeLog'.split()
+ '__init__.py Makefile.am VERSION build_configure README AUTHORS NEWS COPYING ChangeLog'.split()
default_directories_ignored = []
products_infos = self.get_products_list(options, config)
# Construct the arguments to pass to the clean, source and patch commands
- args_appli = config.VARS.application + ' '
+ args_appli = config.VARS.application
args_product_opt = '--products '
if options.products:
for p_name in options.products:
logger)
# Construct the final commands arguments
- args_clean = args_appli + args_product_opt_clean + " --sources"
- args_source = args_appli + args_product_opt
- args_patch = args_appli + args_product_opt_patch
+ args_clean = "%s --sources" % (args_product_opt_clean)
+ args_source = "%s" % (args_product_opt)
+ args_patch = "%s" % (args_product_opt_patch)
# If there is no more any product in the command arguments,
# do not call the concerned command
do_clean = not(oExpr.search(args_product_opt_clean))
do_source = not(oExpr.search(args_product_opt))
do_patch = not(oExpr.search(args_product_opt_patch))
-
-
+
# Initialize the results to Ok but nothing done status
res_clean = RCO.ReturnCode("OK", "nothing done")
res_source = RCO.ReturnCode("OK", "nothing done")
res_patch = RCO.ReturnCode("OK", "nothing done")
- # return res_clean + res_source + res_patch
-
# Call the commands using the API
if do_clean:
msg = _("Clean the source directories ...")
- logger.info(msg)
- DBG.tofix("args_clean and TODO remove returns", args_clean, True)
- res_clean = runner.getCommand("clean").run(args_clean)
- return res_clean + res_source + res_patch
+ logger.info(msg + "(%s)" % args_clean)
+ mCmd = self.getMicroCommand("clean", args_appli)
+ res_clean = mCmd.run(args_clean)
+ logger.warning(str(res_clean))
+ return res_clean # TODO debug remove that
+
if do_source:
msg = _("Get the sources of the products ...")
- logger.debug(msg)
- res_source = runner.getCommand("source").run(args_source)
+ logger.info(msg + "(%s)" % args_source)
+ mCmd = self.getMicroCommand("source", args_appli)
+ res_source = mCmd.run(args_source)
+ logger.warning(str(res_source))
+
if do_patch:
msg = _("Patch the product sources (if any) ...")
- logger.debug(msg)
- res_patch = runner.getCommand("patch").run(args_patch)
+ logger.info(msg + "(%s)" % args_patch)
+ mCmd = self.getMicroCommand("patch", args_appli)
+ res_patch = mCmd.run(args_patch)
+ logger.warning(str(res_patch))
return res_clean + res_source + res_patch
except Exception as e:
# error as may be unknown problem
# verbose debug message with traceback if developers
- msg = "Exception raised for execute_cli(%s):\n" % args
+ msg = "Exception raised for execute_cli (%s):\n" % " ".join(args)
logger.critical(DBG.format_color_exception(msg))
logger.close()
sys.exit(KOSYS)
return var
def get_command_line_overrides(self, options, sections):
- """get all the overwrites that are in the command line
+ """get all the overwrites that are in the command line.
+ When there are no options or not the overwrite option,
+ return an empty list
:param options:
The options from salomeTools class initialization
:param sections: (str) The config section to overwrite.
:return: (list) The list of all the overwrites to apply.
"""
- # when there are no options or not the overwrite option,
- # return an empty list
+ # DBG.write("get_command_line_overrides options", options)
if options is None or options.overwrite is None:
return []
cp = cfg.PATHS.APPLICATIONPATH
PYCONF.streamOpener = ConfigOpener(cp)
do_merge = True
- aFile = application + '.pyconf'
+ aFile = application.replace(" ", "") + '.pyconf'
try:
application_cfg = PYCONF.Config(aFile)
except IOError as e:
def log(msg, force=False):
"""elementary log when no logging.Logger yet"""
- prefix = "%s.log: " % _name
+ prefix = "---- %s.log: " % _name
nb = len(prefix)
if _verbose or force:
print(prefix + indent(msg, nb))
def getStrShort(msg):
"""Returns short string for msg (as first caracters without line feed"""
+ # log("getStrShort " + str(msg), True)
res = msg.replace("\n", "//")[0:30]
return res
"""
if self.closed:
raise Exception("logger closed yet: %s" % self)
- log("close stuff logger %s" % self, True) # getStrDirLogger(self)
+ log("close stuff logger %s" % self) # getStrDirLogger(self)
for handl in self.handlers:
- log("close stuff handler %s" % getStrHandler(handl), True)
+ log("close stuff handler %s" % getStrHandler(handl))
handl.close() # Tidy up any resources used by the handler.
# todo etc
self.closed = True # done at end sat, flushed closed xml files.
| use the keyword argument exc_info with a true value
| >> logger.trace("Houston, we have a %s", "long trace to follow")
"""
- log("trace stuff logger %s dateLogger %s", True)
- if self.isEnabledFor(self._TRACE):
- self._log(self._TRACE, msg, args, **kwargs)
+ log("trace stuff logger '%s' msg '%s...'" % (self.name, getStrShort(msg)), True)
+ if self.isEnabledFor(_TRACE):
+ self._log(_TRACE, msg, args, **kwargs)
def xx_isEnabledFor(self, level):
"""
config = self._config
# TODO for degug
- log("XmlHandler to xml file\n%s" % PP.pformat(getListOfStrLogRecord(self.buffer)), True)
+ log("XmlHandler to xml file\n%s" % PP.pformat(getListOfStrLogRecord(self.buffer)))
if os.path.exists(targetFile):
msg = "XmlHandler target file %s existing yet" % targetFile
logger.setLevel(logger.DEBUG)
-def setFileHandler(logger, config):
+def setFileHandler(cmdInstance):
"""
add file handler to logger to set log files
for salometools command.
| ~/LOGS/OUT/micro_20180510_140607_clean_lenovo.txt
| etc.
"""
+ logger = cmdInstance.getLogger()
+ config = cmdInstance.getConfig()
+
#import src.debug as DBG # avoid cross import
- log("setFileHandler %s" % logger, True)
- log("setFileHandler config\n%s" % PP.pformat(dict(config.VARS)), True)
- log("setFileHandler TODO set log_dir config.LOCAL.log_dir", True)
+ log("setFileHandler %s" % logger)
+ log("setFileHandler config\n%s" % PP.pformat(dict(config.VARS)))
+ log("setFileHandler TODO set log_dir config.LOCAL.log_dir")
log_dir = "TMP" # TODO for debug config.LOCAL.log_dir # files xml
log_dir_out = os.path.join(log_dir, "OUT") # files txt
UTS.ensure_path_exists(log_dir_out)
datehour = config.VARS.datehour
cmd = config.VARS.command
+ fullNameCmd = cmdInstance.getFullNameStr()
hostname = config.VARS.hostname
nameFileXml = "%s_%s_%s.xml" % (datehour, cmd, hostname)
nameFileTxt = "%s_%s_%s.txt" % (datehour, cmd, hostname)
fileXml = os.path.join(log_dir, nameFileXml)
fileTxt = os.path.join(log_dir_out, nameFileTxt)
+ # precaution
+ lastCmd = cmdInstance.getFullNameList()[-1]
+ if cmd != lastCmd:
+ msg = "setFileHandler '%s' command name incoherency in config '%s'" % (fullNameCmd, cmd)
+ logger.critical(msg)
+
nbhandl = len(logger.handlers) # number of current handlers
if nbhandl == 1: # first main command
+ log("setFileHandler '%s' main command" % fullNameCmd, True)
# Logging vers file xml
handler = XmlHandler(1000) # log outputs in memory
handler.setFormatter(formatter)
logger.addHandler(handler)
- if nbhandl > 1: # secondary micro command
- log("setFileHandler micro command %s" % config.VARS.command, True)
+ elif nbhandl > 1: # secondary micro command
+ log("TODO setFileHandler '%s' micro command" % fullNameCmd, True)
- log("setFileHandler %s" % logger, True)
+ log("setFileHandler %s" % logger)
def getDefaultLogger():
"""
# supposed never seen, set "config", "prepare"... in inherited commands
- name = "salomeTools"
+ name = "NoName"
def __init__(self, runner):
# runner (as caller) usually as Sat instance
# logger (from caller) usually as Sat instance logger, but sometimes local value
self._logger = runner.logger
self._options = None
+ self._fullName = [] # example '[prepare','clean'] when micro command 'clean' of 'prepare'
+
+ def initFullName(self, parentFullName=[]):
+ """
+ initialize full name of command instance, one call only.
+ parentFullName supposedly as list (as parent full name)
+
+ | example values of self._full name:
+ | ['prepare'] if main command 'prepare'.
+ | ['prepare', 'clean'] if micro command 'clean' from command 'prepare'.
+ """
+ # DBG.write("initFullName", (self._fullName, parentFullName))
+ if len(self._fullName) != 0: # ne call only
+ raise Exception("full name initialized yet '%s'" % self.getFullNameStr())
+ if len(self._fullName) > 10: # Houston problem
+ raise Exception("full name too long '%s'" % self.getFullNameStr())
+ if type(parentFullName) == str:
+ pfn = parentFullName.split("_") # if from string 'prepare_clean'
+ elif type(parentFullName) == list:
+ pfn = list(parentFullName) # make copy precaution
+ else:
+ raise Exception("type parent full name unexpected '%s'" % parentFullName)
+ self._fullName = pfn + [self.name] # make copy precaution
+ DBG.write("initFullName", self._fullName)
+
+ def getFullNameStr(self):
+ """returns 'prepare_clean' when micro command 'clean' of 'prepare'"""
+ return "_".join(self._fullName)
+
+ def getFullNameList(self):
+ """returns precaution copy as list of self._fullName"""
+ return list(self._fullName)
def getClassName(self):
"""
tmp = PP.pformat(self.__dict__)
res = "%s(\n %s)\n" % (self.getClassName(), tmp[1:-1])
return res
+
+ def getMicroCommand(self, nameCommandToLoad, nameAppliToLoad):
+ """
+ get micro command instance from current command instance
+ returns inherited instance of Command(_BaseCmd) for command 'name'
+ if module not loaded yet, load it.
+ """
+ # create/get dynamically the command instance to call its 'run' method
+ runner = self.getRunner()
+ options = runner.getOptions() # generic main options
+
+ # load micro command config
+ cfgMgr = CFGMGR.ConfigManager(self)
+ DBG.write("getMicroCommand nameCommandToLoad '%s'" % nameCommandToLoad, nameAppliToLoad)
+ config = cfgMgr.get_config(nameAppliToLoad, options, nameCommandToLoad, datadir=None)
+
+ cmdInstance = runner.getCommand(nameCommandToLoad)
+
+ # some initialisation stuff
+ cmdInstance.initFullName(self.getFullNameList()) # as micro command
+ cmdInstance.setConfig(config) # micro command config
+ cmdInstance.setOptions(options)
+
+ import src.loggingSat as LOG # avoid cross import
+ LOG.setFileHandler(cmdInstance)
+
+ return cmdInstance
def run(self, cmd_arguments):
"""
"""set logger for run command"""
if self._logger is not None:
# supposed logger.debug for future
- self._logger.warning("change logger for %s, are you sure" % self.getClassName())
+ self._logger.warning("change logger for %s, are you sure" % self.getFullNameStr())
self._logger = logger
def getLogger(self):
if self._logger is None:
- raise Exception("%s instance needs self._logger not None, fix it." % self.getClassName())
+ raise Exception("%s instance needs self._logger not None, fix it." % self.getFullNameStr())
else:
return self._logger
+ def setOptions(self, options):
+ if self._options is None:
+ self._options = options
+ else:
+ raise Exception("%s command instance have options yet, Fix it." % self.getFullName())
+
def getOptions(self):
if self._options is None:
- raise Exception("%s instance needs self._option not None, fix it." % self.getClassName())
+ raise Exception("%s instance needs self._option not None, fix it." % self.getFullNameStr())
else:
return self._options
def getRunner(self):
if self._runner is None:
- raise Exception("%s instance needs self.runner not None, fix it." % self.getClassName())
+ raise Exception("%s instance needs self.runner not None, fix it." % self.getFullNameStr())
else:
return self._runner
- def getConfig(self):
+ def getConfigObsolete(self):
"""
supposedly (for now) no multiply local config(s)
only one config in runner.config
may be some for future...
"""
if self._runner.config is None:
- self._logger.error("%s instance have runner.config None, fix it." % self.getClassName())
+ self._logger.error("%s command instance have runner.config None, Fix it." % self.getFullNameStr())
return self._runner.config
+
+ def getConfig(self):
+ """
+ supposedly multiply local config(s)
+ only one config for each command instance
+ """
+ if self._config is None:
+ raise Exception("%s command instance have config None, Fix it." % self.getFullNameStr())
+ return self._config
+
+ def setConfig(self, config):
+ if self._config is None:
+ self._config = config
+ else:
+ raise Exception("%s command instance have config yet, Fix it." % self.getFullName())
def get_products_list(self, options, config):
return CFGMGR.get_products_list(options, config)
smart parse command arguments skip
first argument name appli to load, if present
"""
+ verb = False
argList = self.assumeAsList(cmd_arguments)
- DBG.write("%s.Command arguments" % self.name, argList)
+ fullName = self.getFullNameStr()
+ DBG.write("%s.Command arguments" % fullName, argList, verb)
commandOptions, remaindersArgs = self.getParser().parse_args(argList)
- DBG.write("%s.Command options" % self.name, commandOptions)
- DBG.write("%s.Command remainders arguments" % self.name, remaindersArgs)
+ DBG.write("%s.Command options" % fullName, commandOptions, verb)
+ DBG.write("%s.Command remainders arguments" % fullName, remaindersArgs, verb)
if remaindersArgs != []:
- self.getLogger().error("%s.Command have unknown remainders arguments:\n%s\n" % \
- (self.name, remaindersArgs))
+ msg = "%s.Command have unknown remainders arguments:\n(%s)" % (fullName, " ".join(remaindersArgs))
+ self.getLogger().error(msg)
return commandOptions, remaindersArgs
def description(self):
# description of the command options
msg += self.getParser().get_help() + "\n"
return msg
+
########################################################################
# Sat class
self.config = None # the config that will be read using pyconf module
self.logger = logger # the logger that will be use
self.arguments = None # args are postfixes options: args[0] is the 'commands' command
- self.options = None # the options passed to salomeTools
+ self.options = None # the main generic options passed to salomeTools
# the directory that contain all the external
# data (like software pyconf and software scripts)
def getConfig(self):
return self.config
+ def getOptions(self):
+ return self.options
+
def assumeAsList(self, strOrList):
return assumeAsList(strOrList)
# if the help option has been called, print command help and returns
if self.options.help:
self.print_help()
- return RCO.ReturnCode("OK", "Option --help")
+ return RCO.ReturnCode("OK", "Option --help") # and returns
self.nameCommandToLoad, self.nameAppliToLoad, self.commandArguments = \
self.getCommandAndAppli(remainderArgs)
- cfgManager = CFGMGR.ConfigManager(self)
- self.config = cfgManager.get_config(
- application=self.nameAppliToLoad,
- options=self.options,
- command=self.nameCommandToLoad,
- datadir=None)
+ cfgMgr = CFGMGR.ConfigManager(self)
+ # as main config
+ config = cfgMgr.get_config(self.nameAppliToLoad, self.options, self.nameCommandToLoad, datadir=None)
+ self.config = config # runner.config main config
# create/get dynamically the command instance to call its 'run' method
cmdInstance = self.getCommand(self.nameCommandToLoad)
+
+ # some initialisation stuff
+ cmdInstance.initFullName() # as main command
+ cmdInstance.setConfig(config)
import src.loggingSat as LOG # avoid cross import
- LOG.setFileHandler(self.getLogger(), self.getConfig())
+ LOG.setFileHandler(cmdInstance)
- # Run the command using the arguments
+ # Run the main command using the remainders command arguments
returnCode = cmdInstance.run(self.commandArguments)
+
return returnCode
def getCommandAndAppli(self, arguments):
+ """
+ returns name command to load and name appli to load
+ and command to load remainders arguments
+ """
args = self.assumeAsList(arguments)
namecmd, nameAppli, remainderArgs = None, None, []
iremain = 0
remainderArgs = args[iremain:]
res = (namecmd, nameAppli, remainderArgs)
DBG.write("getCommandAndAppli", res)
- return res
-
+ return res
def get_help(self):
"""get general help colored string"""
msg = "<header>Version:<reset> " + version
return msg
+ def getConfirmMode(self):
+ return False
+
+ def getBatchMode(self):
+ return True
+
+ def getAnswer(self, msg):
+ """
+ question and user answer (in console) if confirm mode and not batch mode
+ returns 'YES' or 'NO' if confirm mode and not batch mode
+ returns 'YES' if batch mode
+ """
+ if self.getConfirmMode() and not self.getBatchMode():
+ self.getLogger().info(msg)
+ rep = input(_("Are you sure you want to continue? [yes/no]"))
+ if rep.upper() == _("YES"):
+ return "YES"
+ else:
+ return "NO"
+ else:
+ self.getLogger().info(msg)
+ self.getLogger().info("<green>YES<reset> (as automatic answer)")
+ return "YES"
verbose = False #True
+_TRACE = LOGI.INFO - 2 # just below info
+
class LoggerSat(LOGI.Logger):
"""
Elementary prototype for logger sat
see: /usr/lib64/python2.7/logging/xxx__init__.py etc.
"""
- _TRACE = LOGI.INFO - 2 # just below
-
def __init__(self, name, level=LOGI.INFO):
"""
Initialize the logger with a name and an optional level.
"""
super(LoggerSat, self).__init__(name, level)
- LOGI.addLevelName(self._TRACE, "TRACE")
- # LOGI.TRACE = self._TRACE # only for coherency,
+ LOGI.addLevelName(_TRACE, "TRACE")
+ # LOGI.TRACE = _TRACE # only for coherency,
def trace(self, msg, *args, **kwargs):
"""
logger.trace("Houston, we have a %s", "long trace to follow")
"""
- if self.isEnabledFor(self._TRACE):
- self._log(self._TRACE, msg, args, **kwargs)
+ if self.isEnabledFor(_TRACE):
+ self._log(_TRACE, msg, args, **kwargs)
class TestCase(unittest.TestCase):
"Test the debug.py"""