From a12fd7af1d5f044b417fbd5a5fb4b45647ca1c00 Mon Sep 17 00:00:00 2001 From: Christian Van Wambeke Date: Thu, 26 Apr 2018 16:50:22 +0200 Subject: [PATCH] add src/catchAll.py --- commands/application.py | 36 ++++---- commands/check.py | 10 +-- commands/compile.py | 18 ++-- commands/config.py | 5 +- commands/configure.py | 10 +-- commands/environ.py | 6 +- commands/find_duplicates.py | 10 +-- commands/generate.py | 19 ++-- commands/init.py | 11 +-- commands/job.py | 4 +- commands/jobs.py | 49 +++++----- commands/launcher.py | 16 ++-- commands/log.py | 73 ++++++++------- commands/make.py | 10 +-- commands/makeinstall.py | 10 +-- commands/package.py | 44 +++++---- commands/patch.py | 4 +- commands/profile.py | 6 +- commands/run.py | 13 ++- commands/script.py | 10 +-- commands/source.py | 9 +- commands/template.py | 13 +-- commands/test.py | 50 +++++------ doc/src/write_command.rst | 4 +- sat | 5 +- src/catchAll.py | 123 +++++++++++++++++++++++++ src/compilation.py | 3 +- src/configManager.py | 4 +- src/returnCode.py | 4 +- src/system.py | 46 ++++++---- src/utilsSat.py | 173 ++++++++++++++++++++++++++++++++++-- src/xmlManager.py | 6 +- src/xsl/LOGO-SAT.png | Bin 6614 -> 87756 bytes test/test_021_catchAll.py | 90 +++++++++++++++++++ 34 files changed, 642 insertions(+), 252 deletions(-) create mode 100644 src/catchAll.py create mode 100644 test/test_021_catchAll.py diff --git a/commands/application.py b/commands/application.py index fbc137f..d9017b0 100644 --- a/commands/application.py +++ b/commands/application.py @@ -92,34 +92,34 @@ NOTICE: this command will ssh to retrieve information to each machine in the l options = self.getOptions() # check for product - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) - application = runner.cfg.VARS.application + application = config.VARS.application logger.info(_("Building application for
%s\n") % application) # if section APPLICATION.virtual_app does not exists create one - if "virtual_app" not in runner.cfg.APPLICATION: + if "virtual_app" not in config.APPLICATION: msg = _("The section APPLICATION.virtual_app is not defined in the product.") logger.error(UTS.red(msg)) return RCO.ReturnCode("KO", msg) # get application dir - target_dir = runner.cfg.APPLICATION.workdir + target_dir = config.APPLICATION.workdir if options.target: target_dir = options.target # set list of modules if options.modules: - runner.cfg.APPLICATION.virtual_app['modules'] = options.modules + config.APPLICATION.virtual_app['modules'] = options.modules # set name and application_name if options.name: - runner.cfg.APPLICATION.virtual_app['name'] = options.name - runner.cfg.APPLICATION.virtual_app['application_name'] = options.name + "_appdir" + config.APPLICATION.virtual_app['name'] = options.name + config.APPLICATION.virtual_app['application_name'] = options.name + "_appdir" - application_name = src.get_cfg_param(runner.cfg.APPLICATION.virtual_app, + application_name = src.get_cfg_param(config.APPLICATION.virtual_app, "application_name", - runner.cfg.APPLICATION.virtual_app.name + "_appdir") + config.APPLICATION.virtual_app.name + "_appdir") appli_dir = os.path.join(target_dir, application_name) fmt = " %s = %s\n" # as " label = value\n" @@ -134,20 +134,20 @@ NOTICE: this command will ssh to retrieve information to each machine in the l # generate catalog for given list of computers catalog_src = options.gencat catalog = generate_catalog(options.gencat.split(","), - runner.cfg,logger) - elif 'catalog' in runner.cfg.APPLICATION.virtual_app: + config,logger) + elif 'catalog' in config.APPLICATION.virtual_app: # use catalog specified in the product - if runner.cfg.APPLICATION.virtual_app.catalog.endswith(".xml"): + if config.APPLICATION.virtual_app.catalog.endswith(".xml"): # catalog as a file - catalog = runner.cfg.APPLICATION.virtual_app.catalog + catalog = config.APPLICATION.virtual_app.catalog else: # catalog as a list of computers - catalog_src = runner.cfg.APPLICATION.virtual_app.catalog + catalog_src = config.APPLICATION.virtual_app.catalog mlist = filter(lambda l: len(l.strip()) > 0, - runner.cfg.APPLICATION.virtual_app.catalog.split(",")) + config.APPLICATION.virtual_app.catalog.split(",")) if len(mlist) > 0: - catalog = generate_catalog(runner.cfg.APPLICATION.virtual_app.catalog.split(","), - runner.cfg, logger) + catalog = generate_catalog(config.APPLICATION.virtual_app.catalog.split(","), + config, logger) # display which catalog is used if len(catalog) > 0: @@ -172,7 +172,7 @@ NOTICE: this command will ssh to retrieve information to each machine in the l # generate the application try: try: # try/except/finally not supported in all version of python - retcode = create_application(runner.cfg, appli_dir, catalog, logger) + retcode = create_application(config, appli_dir, catalog, logger) except Exception as exc: details.append(str(exc)) raise diff --git a/commands/check.py b/commands/check.py index 791e4a1..e664bdf 100644 --- a/commands/check.py +++ b/commands/check.py @@ -71,22 +71,22 @@ Optional: products to configure. # check that the command has been called with an application - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) # Get the list of products to treat - products_infos = get_products_list(options, runner.cfg, logger) + products_infos = get_products_list(options, config, logger) # Print some informations msg = _('Executing the check command in the build directories of the application') - logger.info("%s %s\n" % (msg, UTS.label(runner.cfg.VARS.application))) + logger.info("%s %s\n" % (msg, UTS.label(config.VARS.application))) info = [(_("BUILD directory"), - os.path.join(runner.cfg.APPLICATION.workdir, 'BUILD'))] + os.path.join(config.APPLICATION.workdir, 'BUILD'))] UTS.logger_info_tuples(logger, info) # Call the function that will loop over all the products and execute # the right command(s) - res = check_all_products(runner.cfg, products_infos, logger) + res = check_all_products(config, products_infos, logger) # Print the final state nb_products = len(products_infos) diff --git a/commands/compile.py b/commands/compile.py index 4593b12..e0f6e0b 100644 --- a/commands/compile.py +++ b/commands/compile.py @@ -118,12 +118,12 @@ class Command(_BaseCommand): return 0 # check that the command has been called with an application - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) # Print some informations - nameApp = str(runner.cfg.VARS.application) - srcDir = os.path.join(runner.cfg.APPLICATION.workdir, 'SOURCES') - buildDir = os.path.join(runner.cfg.APPLICATION.workdir, 'BUILD') + nameApp = str(config.VARS.application) + srcDir = os.path.join(config.APPLICATION.workdir, 'SOURCES') + buildDir = os.path.join(config.APPLICATION.workdir, 'BUILD') msg = _("Application %s, executing compile commands in build directories of products.\n" logger.info(msg % UTS.label(nameApp)) @@ -133,23 +133,23 @@ class Command(_BaseCommand): UTS.logger_info_tuples(logger, info) # Get the list of products to treat - products_infos = get_products_list(options, runner.cfg, logger) + products_infos = get_products_list(options, config, logger) if options.fathers: # Extend the list with all recursive dependencies of the given products - products_infos = extend_with_fathers(runner.cfg, products_infos) + products_infos = extend_with_fathers(config, products_infos) if options.children: # Extend the list with all products that use the given products - products_infos = extend_with_children(runner.cfg, products_infos) + products_infos = extend_with_children(config, products_infos) # Sort the list regarding the dependencies of the products - products_infos = sort_products(runner.cfg, products_infos) + products_infos = sort_products(config, products_infos) # Call the function that will loop over all the products and execute # the right command(s) - res = compile_all_products(runner, runner.cfg, options, products_infos, logger) + res = compile_all_products(runner, config, options, products_infos, logger) # Print the final state nb_products = len(products_infos) diff --git a/commands/config.py b/commands/config.py index fe44157..2f063e8 100644 --- a/commands/config.py +++ b/commands/config.py @@ -23,6 +23,7 @@ import src.debug as DBG import src.returnCode as RCO from src.salomeTools import _BaseCommand import src.configManager as CFGMGR +import src.system as SYSS ######################################################################## @@ -122,14 +123,14 @@ If a name is given the new config file takes the given name.""")) 'open_application' not in config): # edit user pyconf usercfg = os.path.join(config.VARS.personalDir, 'SAT.pyconf') logger.info(_("Opening %s\n") % usercfg) - src.system.show_in_editor(editor, usercfg, logger) + SYSS.show_in_editor(editor, usercfg, logger) else: # search for file .pyconf and open it for path in config.PATHS.APPLICATIONPATH: pyconf_path = os.path.join(path, config.VARS.application + ".pyconf") if os.path.exists(pyconf_path): logger.info(_("Opening %s\n") % pyconf_path) - src.system.show_in_editor(editor, pyconf_path, logger) + SYSS.show_in_editor(editor, pyconf_path, logger) break # case : give information about the product in parameter diff --git a/commands/configure.py b/commands/configure.py index 21a2665..5987571 100644 --- a/commands/configure.py +++ b/commands/configure.py @@ -75,24 +75,24 @@ class Command(_BaseCommand): # check that the command has been called with an application - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) # Get the list of products to treat - products_infos = get_products_list(options, runner.cfg, logger) + products_infos = get_products_list(options, config, logger) # Print some informations logger.info(_('Configuring the sources of the application %s\n') % - UTS.label(runner.cfg.VARS.application)) + UTS.label(config.VARS.application)) info = [(_("BUILD directory"), - os.path.join(runner.cfg.APPLICATION.workdir, 'BUILD'))] + os.path.join(config.APPLICATION.workdir, 'BUILD'))] UTS.logger_info_tuples(logger, info) # Call the function that will loop over all the products and execute # the right command(s) if options.option is None: options.option = "" - res = configure_all_products(runner.cfg, products_infos, options.option, logger) + res = configure_all_products(config, products_infos, options.option, logger) # Print the final state nb_products = len(products_infos) diff --git a/commands/environ.py b/commands/environ.py index 5bd1aaf..0a1de0a 100644 --- a/commands/environ.py +++ b/commands/environ.py @@ -78,7 +78,7 @@ class Command(_BaseCommand): options = self.getOptions() # check that the command was called with an application - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) if options.products is None: environ_info = None @@ -86,7 +86,7 @@ class Command(_BaseCommand): # add products specified by user (only products # included in the application) environ_info = filter(lambda l: - l in runner.cfg.APPLICATION.products.keys(), + l in config.APPLICATION.products.keys(), options.products) if options.shell == []: @@ -100,7 +100,7 @@ class Command(_BaseCommand): if out_dir: out_dir = os.path.abspath(out_dir) - write_all_source_files(runner.cfg, logger, out_dir=out_dir, shells=shell, + write_all_source_files(config, logger, out_dir=out_dir, shells=shell, prefix=options.prefix, env_info=environ_info) logger.info("\n") #TODO return code diff --git a/commands/find_duplicates.py b/commands/find_duplicates.py index e3dbf61..494212e 100644 --- a/commands/find_duplicates.py +++ b/commands/find_duplicates.py @@ -109,15 +109,13 @@ class Command(_BaseCommand): if options.path: l_dir_path = options.path else: - src.check_config_has_application(runner.cfg) + src.check_config_has_application(config) if options.sources: - l_dir_path = [os.path.join(runner.cfg.APPLICATION.workdir, - "SOURCES")] + l_dir_path = [os.path.join(config.APPLICATION.workdir, "SOURCES")] else: # find all installation paths - all_products = runner.cfg.APPLICATION.products.keys() - l_product_cfg = src.product.get_products_infos(all_products, - runner.cfg) + all_products = config.APPLICATION.products.keys() + l_product_cfg = src.product.get_products_infos(all_products, config) l_dir_path = [pi.install_dir for __, pi in l_product_cfg] # Get the files to ignore during the searching diff --git a/commands/generate.py b/commands/generate.py index a230397..99edea1 100644 --- a/commands/generate.py +++ b/commands/generate.py @@ -69,15 +69,15 @@ class Command(_BaseCommand): options = self.getOptions() # Check that the command has been called with an application - src.check_config_has_application(runner.cfg) + src.check_config_has_application(config) logger.write(_('Generation of SALOME modules for application %s\n') % \ - UTS.label(runner.cfg.VARS.application), 1) + UTS.label(config.VARS.application), 1) status = src.KO_STATUS # verify that YACSGEN is available - yacsgen_dir = check_yacsgen(runner.cfg, options.yacsgen, logger) + yacsgen_dir = check_yacsgen(config, options.yacsgen, logger) if isinstance(yacsgen_dir, tuple): # The check failed @@ -92,35 +92,32 @@ class Command(_BaseCommand): logger.info(" insert directory PATH %s = %s\n" % \ ("YACSGEN", UTS.blue(yacsgen_dir) - products = runner.cfg.APPLICATION.products + products = config.APPLICATION.products if options.products: products = options.products details = [] nbgen = 0 - context = build_context(runner.cfg, logger) + context = build_context(config, logger) for product in products: header = _("Generating %s") % UTS.label(product) header += " %s " % ("." * (20 - len(product))) logger.write(header, 3) logger.flush() - if product not in runner.cfg.PRODUCTS: + if product not in config.PRODUCTS: logger.write(_("Unknown product\n"), 3, False) continue - pi = src.product.get_product_config(runner.cfg, product) + pi = src.product.get_product_config(config, product) if not src.product.product_is_generated(pi): logger.write(_("not a generated product\n"), 3, False) continue nbgen += 1 try: - result = generate_component_list(runner.cfg, - pi, - context, - logger) + result = generate_component_list(config, pi, context, logger) except Exception as exc: result = str(exc) diff --git a/commands/init.py b/commands/init.py index 53e7af6..ddd713a 100644 --- a/commands/init.py +++ b/commands/init.py @@ -20,6 +20,7 @@ import src.debug as DBG import src.returnCode as RCO +import src.utilsSat as UTS from src.salomeTools import _BaseCommand import src.pyconf as PYCONF @@ -76,7 +77,7 @@ class Command(_BaseCommand): # Print some informations logger.write(_('Local Settings of SAT %s\n\n') % \ - UTS.label(runner.cfg.VARS.salometoolsway), 1) + UTS.label(config.VARS.salometoolsway), 1) res = 0 @@ -90,16 +91,16 @@ class Command(_BaseCommand): res_check = check_path(value, logger) res += res_check if res_check == 0: - res_set = set_local_value(runner.cfg, key, value, logger) + res_set = set_local_value(config, key, value, logger) res += res_set # Set the options corresponding to an informative value for opt in [("VCS", options.VCS), ("tag", options.tag)]: key, value = opt - res_set = set_local_value(runner.cfg, key, value, logger) + res_set = set_local_value(config, key, value, logger) res += res_set - display_local_values(runner.cfg, logger) + display_local_values(config, logger) return res @@ -171,7 +172,7 @@ Please provide a path to a directory\n""") % UTS.blue(path_to_check) # Try to create the given path try: - src.ensure_path_exists(str(path)) + UTS.ensure_path_exists(str(path)) except Exception as e: msg = _("""\ Unable to create the directory %s: diff --git a/commands/job.py b/commands/job.py index ec09689..ac03f09 100644 --- a/commands/job.py +++ b/commands/job.py @@ -68,7 +68,7 @@ class Command(_BaseCommand): logger = self.getLogger() options = self.getOptions() - l_cfg_dir = runner.cfg.PATHS.JOBPATH + l_cfg_dir = config.PATHS.JOBPATH # Make sure the jobs_config option has been called if not options.jobs_cfg: @@ -101,7 +101,7 @@ Use the --list option to get the possible files.""") % UTS.blue(fPyconf) logger.error(msg) return 1 - info = [ (_("Platform"), runner.cfg.VARS.dist), + info = [ (_("Platform"), config.VARS.dist), (_("File containing the jobs configuration"), file_jobs_cfg) ] UTS.logger_info_tuples(logger, info) diff --git a/commands/jobs.py b/commands/jobs.py index df736ee..d9554f3 100644 --- a/commands/jobs.py +++ b/commands/jobs.py @@ -33,6 +33,7 @@ import re import src.ElementTree as etree import src.debug as DBG import src.returnCode as RCO +import src.utilsSat as UTS from src.salomeTools import _BaseCommand import src.pyconf as PYCONF @@ -123,7 +124,7 @@ class Command(_BaseCommand): logger = self.getLogger() options = self.getOptions() - l_cfg_dir = runner.cfg.PATHS.JOBPATH + l_cfg_dir = config.PATHS.JOBPATH # list option : display all the available config files if options.list: @@ -163,7 +164,7 @@ Use the --list option to get the possible files.\n""") % config_file one_config_jobs = src.read_config_from_a_file(file_jobs_cfg) merger.merge(config_jobs, one_config_jobs) - info = [(_("Platform"), runner.cfg.VARS.dist), + info = [(_("Platform"), config.VARS.dist), (_("Files containing the jobs configuration"), l_conf_files_path)] UTS.logger_info_tuples(logger, info) @@ -182,15 +183,15 @@ Use the --list option to get the possible files.\n""") % config_file # on every machine name_pyconf = "_".join([os.path.basename(path)[:-len('.pyconf')] for path in l_conf_files_path]) + ".pyconf" - path_pyconf = src.get_tmp_filename(runner.cfg, name_pyconf) + path_pyconf = src.get_tmp_filename(config, name_pyconf) #Save config f = file( path_pyconf , 'w') config_jobs.__save__(f) # log the paramiko problems - log_dir = src.get_log_path(runner.cfg) + log_dir = UTS.get_log_path(config) paramiko_log_dir_path = os.path.join(log_dir, "JOBS") - src.ensure_path_exists(paramiko_log_dir_path) + UTS.ensure_path_exists(paramiko_log_dir_path) paramiko = getParamiko(logger) paramiko.util.log_to_file(os.path.join(paramiko_log_dir_path, logger.txtFileName)) @@ -214,7 +215,7 @@ Use the --list option to get the possible files.\n""") % config_file # Copy the stylesheets in the log directory log_dir = log_dir - xsl_dir = os.path.join(runner.cfg.VARS.srcDir, 'xsl') + xsl_dir = os.path.join(config.VARS.srcDir, 'xsl') files_to_copy = [] files_to_copy.append(os.path.join(xsl_dir, STYLESHEET_GLOBAL)) files_to_copy.append(os.path.join(xsl_dir, STYLESHEET_BOARD)) @@ -230,7 +231,7 @@ Use the --list option to get the possible files.\n""") % config_file gui = Gui(log_dir, today_jobs.ljobs, today_jobs.ljobs_not_today, - runner.cfg.VARS.datehour, + config.VARS.datehour, logger, file_boards = options.input_boards) @@ -758,7 +759,8 @@ class Job(object): self.err += _("Unable to get remote log files!\n%s\n" % str(e)) def total_duration(self): - """Give the total duration of the job + """\ + Give the total duration of the job :return: the total duration of the job in seconds :rtype: int @@ -766,7 +768,8 @@ class Job(object): return self._Tf - self._T0 def run(self): - """Launch the job by executing the remote command. + """\ + Launch the job by executing the remote command. """ # Prevent multiple run @@ -806,7 +809,8 @@ class Job(object): self._has_begun = True def write_results(self): - """Display on the terminal all the job's information + """\ + Display on the terminal all the job's information """ self.logger.write("name : " + self.name + "\n") if self.after: @@ -837,7 +841,8 @@ class Job(object): self.logger.write(self.err + "\n") def get_status(self): - """Get the status of the job (used by the Gui for xml display) + """\ + Get the status of the job (used by the Gui for xml display) :return: The current status of the job :rtype: String @@ -859,8 +864,9 @@ class Job(object): time.localtime(self._Tf)) class Jobs(object): - '''Class to manage the jobs to be run - ''' + """\ + Class to manage the jobs to be run + """ def __init__(self, runner, logger, @@ -894,14 +900,15 @@ class Jobs(object): self.determine_jobs_and_machines() def define_job(self, job_def, machine): - '''Takes a pyconf job definition and a machine (from class machine) - and returns the job instance corresponding to the definition. + """\ + Takes a pyconf job definition and a machine (from class machine) + and returns the job instance corresponding to the definition. :param job_def src.config.Mapping: a job definition :param machine machine: the machine on which the job will run :return: The corresponding job in a job class instance :rtype: job - ''' + """ name = job_def.name cmmnds = job_def.commands if not "timeout" in job_def: @@ -934,12 +941,12 @@ class Jobs(object): prefix = prefix) def determine_jobs_and_machines(self): - '''Function that reads the pyconf jobs definition and instantiates all - the machines and jobs to be done today. + """\ + Reads the pyconf jobs definition and instantiates all + the machines and jobs to be done today. - :return: Nothing - :rtype: N\A - ''' + :return: None + """ today = datetime.date.weekday(datetime.date.today()) host_list = [] diff --git a/commands/launcher.py b/commands/launcher.py index 6c77568..032af1e 100644 --- a/commands/launcher.py +++ b/commands/launcher.py @@ -67,31 +67,29 @@ class Command(_BaseCommand): options = self.getOptions() # Verify that the command was called with an application - src.check_config_has_application( runner.cfg ) + src.check_config_has_application( config ) # Determine the launcher name (from option, profile section or by default "salome") if options.name: launcher_name = options.name else: - launcher_name = src.get_launcher_name(runner.cfg) + launcher_name = src.get_launcher_name(config) # set the launcher path - launcher_path = runner.cfg.APPLICATION.workdir + launcher_path = config.APPLICATION.workdir # Copy a catalog if the option is called additional_environ = {} if options.catalog: - additional_environ = copy_catalog(runner.cfg, options.catalog) + additional_environ = copy_catalog(config, options.catalog) # Generate a catalog of resources if the corresponding option was called if options.gencat: - catalog_path = generate_catalog(options.gencat.split(","), - runner.cfg, - logger) - additional_environ = copy_catalog(runner.cfg, catalog_path) + catalog_path = generate_catalog(options.gencat.split(","), config, logger) + additional_environ = copy_catalog(config, catalog_path) # Generate the launcher - launcherPath = generate_launch_file( runner.cfg, + launcherPath = generate_launch_file( config, logger, launcher_name, launcher_path, diff --git a/commands/log.py b/commands/log.py index 8ea7dbf..2ba5ea0 100644 --- a/commands/log.py +++ b/commands/log.py @@ -27,7 +27,9 @@ import stat import src.debug as DBG import src.returnCode as RCO +import src.utilsSat as UTS from src.salomeTools import _BaseCommand +import src.system as SYSS # Compatibility python 2/3 for input function # input stays input for python 3 and input = raw_input for python 2 @@ -95,7 +97,7 @@ class Command(_BaseCommand): # get the log directory. - logDir = src.get_log_path(runner.cfg) + logDir = UTS.get_log_path(config) # Print a header nb_files_log_dir = len(glob.glob(os.path.join(logDir, "*"))) @@ -108,8 +110,7 @@ class Command(_BaseCommand): if options.clean: nbClean = options.clean # get the list of files to remove - lLogs = src.logger.list_log_file(logDir, - src.logger.log_all_command_file_expression) + lLogs = UTS.list_log_file(logDir, UTS.log_all_command_file_expression) nbLogFiles = len(lLogs) # Delete all if the invoked number is bigger than the number of log files if nbClean > nbLogFiles: @@ -131,17 +132,17 @@ class Command(_BaseCommand): os.path.basename(filePath)[:-len('.xml')] + '.pyconf') remove_log_file(pyconfFilePath, logger) - - logger.write("\n%i logs deleted.\n" % nbClean) - return 0 + msg = "%i logs deleted" % nbClean + logger.info("\n%s\n" % msg) + return RCO.ReturnCode("OK", msg) # determine the commands to show in the hat log - notShownCommands = list(runner.cfg.INTERNAL.log.not_shown_commands) + notShownCommands = list(config.INTERNAL.log.not_shown_commands) if options.full: notShownCommands = [] # Find the stylesheets Directory and files - xslDir = os.path.join(runner.cfg.VARS.srcDir, 'xsl') + xslDir = os.path.join(config.VARS.srcDir, 'xsl') xslCommand = os.path.join(xslDir, "command.xsl") xslHat = os.path.join(xslDir, "hat.xsl") xsltest = os.path.join(xslDir, "test.xsl") @@ -152,21 +153,21 @@ class Command(_BaseCommand): # So we can clean the LOGS directories easily shutil.copy(xslCommand, logDir) shutil.copy(xslHat, logDir) - src.ensure_path_exists(os.path.join(logDir, "TEST")) + UTS.ensure_path_exists(os.path.join(logDir, "TEST")) shutil.copy(xsltest, os.path.join(logDir, "TEST")) shutil.copy(imgLogo, logDir) # If the last option is invoked, just, show the last log file if options.last_terminal: - src.check_config_has_application(runner.cfg) - rootLogDir = os.path.join(runner.cfg.APPLICATION.workdir, 'LOGS') - src.ensure_path_exists(rootLogDir) + src.check_config_has_application(config) + rootLogDir = os.path.join(config.APPLICATION.workdir, 'LOGS') + UTS.ensure_path_exists(rootLogDir) log_dirs = os.listdir(rootLogDir) if log_dirs == []: raise Exception("log directory empty") log_dirs= sorted(log_dirs) - show_last_logs(logger, runner.cfg, log_dirs) - return 0 + res = show_last_logs(logger, config, log_dirs) + return res # If the last option is invoked, just, show the last log file if options.last: @@ -176,24 +177,25 @@ class Command(_BaseCommand): raise Exception("last log file not found in '%s'" % logDir) if options.terminal: # Show the log corresponding to the selected command call - print_log_command_in_terminal(lastLogFilePath, logger) + res = print_log_command_in_terminal(lastLogFilePath, logger) else: # open the log xml file in the user editor - src.system.show_in_editor(runner.cfg.USER.browser, + res = SYSS.show_in_editor(config.USER.browser, lastLogFilePath, logger) - return 0 + return res # If the user asks for a terminal display if options.terminal: # Parse the log directory in order to find # all the files corresponding to the commands - lLogs = src.logger.list_log_file(logDir, - src.logger.log_macro_command_file_expression) + lLogs = UTS.list_log_file(logDir, UTS._log_macro_command_file_expression) lLogsFiltered = [] for filePath, __, date, __, hour, cmd, __ in lLogs: - showLog, cmdAppli, __ = src.logger.show_command_log(filePath, cmd, - runner.cfg.VARS.application, notShownCommands) - if showLog: + showLog = UTS.show_command_log(filePath, cmd, config.VARS.application, notShownCommands) + # showLog, cmdAppli, __ = UTS.show_command_log(filePath, cmd, + # config.VARS.application, notShownCommands) + cmdAppli = showLog.getValue()[0] + if showLog.isOk(): lLogsFiltered.append((filePath, date, hour, cmd, cmdAppli)) lLogsFiltered = sorted(lLogsFiltered) @@ -216,35 +218,38 @@ class Command(_BaseCommand): print_log_command_in_terminal(lLogsFiltered[index][0], logger) x = 0 - return 0 + return RCO.ReturnCode("OK", "end from user") # Create or update the hat xml that gives access to all the commands log files - logger.write(_("Generating the hat log file (can be long) ... "), 3) + logger.info(_("Generating the hat log file (can be long) ... ")) xmlHatFilePath = os.path.join(logDir, 'hat.xml') src.logger.update_hat_xml(logDir, - application = runner.cfg.VARS.application, + application = config.VARS.application, notShownCommands = notShownCommands) - logger.info("\n")) + logger.info("\n") # open the hat xml in the user editor if not options.no_browser: - logger.write(_("\nOpening the log file\n"), 3) - src.system.show_in_editor(runner.cfg.USER.browser, xmlHatFilePath, logger) - return 0 - + logger.info(_("\nOpening the log file\n")) + res = SYSS.show_in_editor(config.USER.browser, xmlHatFilePath, logger) + return res + + return RCO.ReturnCode("OK", "option no browser") def get_last_log_file(logDir, notShownCommands): - '''Used in case of last option. Get the last log command file path. + """\ + Used in case of last option. + Get the last log command file path. :param logDir str: The directory where to search the log files :param notShownCommands list: the list of commands to ignore :return: the path to the last log file :rtype: str - ''' + """ last = (_, 0) for fileName in os.listdir(logDir): # YYYYMMDD_HHMMSS_namecmd.xml - sExpr = src.logger.log_macro_command_file_expression + sExpr = UTS._log_macro_command_file_expression oExpr = re.compile(sExpr) if oExpr.search(fileName): # get date and hour and format it @@ -362,7 +367,7 @@ def show_product_last_logs(logger, config, product_log_dir): if x > 0: (__, file_name) = sorted(l_time_file)[x-1] log_file_path = os.path.join(product_log_dir, file_name) - src.system.show_in_editor(config.USER.editor, log_file_path, logger) + SYSS.show_in_editor(config.USER.editor, log_file_path, logger) def ask_value(nb): '''Ask for an int n. 0 0): + if ('test' in config.LOCAL and + 'display' in config.LOCAL.test and + len(config.LOCAL.test.display) > 0): # use default value for test tool - os.environ['DISPLAY'] = runner.cfg.LOCAL.test.display + os.environ['DISPLAY'] = config.LOCAL.test.display else: os.environ['DISPLAY'] = "localhost:0.0" # initialization ################# if with_application: - tmp_dir = os.path.join(runner.cfg.VARS.tmp_root, - runner.cfg.APPLICATION.name, + tmp_dir = os.path.join(config.VARS.tmp_root, + config.APPLICATION.name, "test") else: - tmp_dir = os.path.join(runner.cfg.VARS.tmp_root, + tmp_dir = os.path.join(config.VARS.tmp_root, "test") # remove previous tmp dir @@ -178,19 +178,19 @@ Please specify an application or a launcher\n""") _("error removing TT_TMP_RESULT %s\n") % tmp_dir) lines = [] - lines.append("date = '%s'" % runner.cfg.VARS.date) - lines.append("hour = '%s'" % runner.cfg.VARS.hour) - lines.append("node = '%s'" % runner.cfg.VARS.node) - lines.append("arch = '%s'" % runner.cfg.VARS.dist) + lines.append("date = '%s'" % config.VARS.date) + lines.append("hour = '%s'" % config.VARS.hour) + lines.append("node = '%s'" % config.VARS.node) + lines.append("arch = '%s'" % config.VARS.dist) - if 'APPLICATION' in runner.cfg: + if 'APPLICATION' in config: lines.append("application_info = {}") lines.append("application_info['name'] = '%s'" % - runner.cfg.APPLICATION.name) + config.APPLICATION.name) lines.append("application_info['tag'] = '%s'" % - runner.cfg.APPLICATION.tag) + config.APPLICATION.tag) lines.append("application_info['products'] = %s" % - str(runner.cfg.APPLICATION.products)) + str(config.APPLICATION.products)) content = "\n".join(lines) @@ -223,8 +223,8 @@ Please specify an application or a launcher\n""") test_base = "" if options.base: test_base = options.base - elif with_application and "test_base" in runner.cfg.APPLICATION: - test_base = runner.cfg.APPLICATION.test_base.name + elif with_application and "test_base" in config.APPLICATION: + test_base = config.APPLICATION.test_base.name fmt = " %s = %s\n" msg = fmt % (_('Display'), os.environ['DISPLAY']) @@ -233,7 +233,7 @@ Please specify an application or a launcher\n""") logger.info(msg) # create the test object - test_runner = src.test_module.Test(runner.cfg, + test_runner = src.test_module.Test(config, logger, base_dir, testbase=test_base, @@ -255,13 +255,13 @@ Please specify an application or a launcher\n""") logger.write("\n", 2, False) logger.write(_("\nGenerate the specific test log\n"), 5) - log_dir = src.get_log_path(runner.cfg) + log_dir = UTS.get_log_path(config) out_dir = os.path.join(log_dir, "TEST") - src.ensure_path_exists(out_dir) + UTS.ensure_path_exists(out_dir) name_xml_board = logger.logFileName.split(".")[0] + "board" + ".xml" - historic_xml_path = generate_history_xml_path(runner.cfg, test_base) + historic_xml_path = generate_history_xml_path(config, test_base) - create_test_report(runner.cfg, + create_test_report(config, historic_xml_path, out_dir, retcode, @@ -746,5 +746,5 @@ def generate_history_xml_path(config, test_base): test_base_name = os.path.basename(test_base) history_xml_name += test_base_name history_xml_name += ".xml" - log_dir = src.get_log_path(config) + log_dir = UTS.get_log_path(config) return os.path.join(log_dir, "TEST", history_xml_name) diff --git a/doc/src/write_command.rst b/doc/src/write_command.rst index 9a68de8..3d4ff35 100644 --- a/doc/src/write_command.rst +++ b/doc/src/write_command.rst @@ -19,6 +19,8 @@ Here are the basic requirements that must be followed in this file in order to a Basic requirements ================== +.. warning :: THIS IS OBSOLETE FOR SAT 5.1 + By adding a file *mycommand.py* in the ``commands`` directory, salomeTools will define a new command named ``mycommand``. In *mycommand.py*, there must be the following method: :: @@ -74,7 +76,7 @@ HowTo access salomeTools config and other commands ======================================================== The *runner* variable is an python instance of *Sat* class. -It gives access to *runner.cfg* which is the data model defined from all +It gives access to *runner.getConfig()* which is the data model defined from all *configuration pyconf files* of salomeTools For example, *runner.cfg.APPLICATION.workdir* contains the root directory of the current application. diff --git a/sat b/sat index 6769e8a..96f2736 100755 --- a/sat +++ b/sat @@ -55,7 +55,10 @@ if __name__ == "__main__": try: returnCode = sat.execute_cli(args) - logger.debug("sat exit code: %s" % returnCode) + if returnCode.isOk(): + logger.debug("sat exit code: %s" % returnCode) # OK no trace + else: + logger.error("sat exit code: %s" % returnCode) # KO say why sys.exit(returnCode.toSys()) except Exception as e: diff --git a/src/catchAll.py b/src/catchAll.py new file mode 100644 index 0000000..c347857 --- /dev/null +++ b/src/catchAll.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +# Copyright (C) 2010-20xx CEA/DEN +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""\ +define class as a simple dictionary with keys +with pretty print __str__ and __repr__ (indented as recursive) +and jsonDumps() + +usage: + >> import catchAll as CAA + >> a = CAA.CatchAll() + >> a.tintin = "reporter" + >> a.milou = "dog" + >> print("a=%s" % a) + >> print("tintin: %s" % a.tintin) +""" + +import pprint as PP +import json + +######################################################################################## +# json utils +######################################################################################## +def dumper(obj): + """to json explore subclass object as dict""" + return obj.__dict__ + +def dumperType(obj): + """\ + to get a "_type" to trace json subclass object, + but ignore all attributes begining with '_' + """ + typeatt = "_type" + aDict = dict((k,v) for k, v in obj.__dict__.iteritems() if k[0] != "_" or k == typeatt) + if not aDict.has_key(typeatt): aDict[typeatt] = obj.__class__.__name__ + return aDict + +def jsonDumps(obj): + """to get direct default jsonDumps method""" + return json.dumps(obj, default=dumperType, sort_keys=True, indent=2) + + +######################################################################################## +class CatchAll(object): + """\ + class as simple dynamic dictionary + with predefined keys as properties in + inherited classes through __init__ method. Or NOT. + with pretty print __str__ and __repr__ (indented as recursive) + with jsonDumps() + + usage: + + >> import catchAll as CAA + >> a = CAA.CatchAll() + >> a.tintin = "reporter" + >> a.milou = "dog" + >> print("a=%s" % a) + >> print("tintin: %s" % a.tintin) + + as + + >> a = {} + >> a["tintin"] = "reporter" + >> a["milou"] = "dog" + >> print("tintin: %s" % a["tintin"] + """ + + def __repr__asList(self): + """\ + goal is to be unambiguous + an ordered list representation is better for test (and visualize) (in)equality + """ + aList = [] + for k in sorted(self.__dict__.keys()): + if k[0] != '_': + aList.append( [k, self.__dict__[k]] ) + return self.__class__.__name__ + " = " + aList.__repr__() + + def __repr__(self): + """goal is to be unambiguous, easy human readeable""" + return self._reprIndent() + + def _reprIndent(self, indent=0): + res = "" + newIndent = indent + 2 + for k in sorted(self.__dict__.keys()): + if k[0] != '_': + kk = self.__dict__[k] + if issubclass(CatchAll, kk.__class__): + res += "\n" + " "*newIndent + "%s: %s" % (k, kk._reprIndent(newIndent)) + else: + skk = self._indent(PP.pformat(kk), newIndent) + res += "\n" + " "*newIndent + "%s: %s" % (k, skk) + return self.__class__.__name__ + "(" + res + ")" + + def _indent(self, txt, indent): + txts = txt.split("\n") + if len(txt) > 1: + return ("\n" + " "*indent).join(txts) + else: + return txt + + + def jsonDumps(self): + return jsonDumps(self) + diff --git a/src/compilation.py b/src/compilation.py index 2b307eb..1ad0703 100644 --- a/src/compilation.py +++ b/src/compilation.py @@ -22,6 +22,7 @@ import sys import shutil from src.options import OptResult +import src.utilsSat as UTS C_COMPILE_ENV_LIST = ["CC", @@ -484,7 +485,7 @@ CC=\\"hack_libtool\\"%g" libtool''' "LOGS", self.product_info.name) file_path = os.path.join(dir_where_to_put, file_name) - src.ensure_path_exists(dir_where_to_put) + UTS.ensure_path_exists(dir_where_to_put) # write the logTxtFile copy it to the destination, and then recreate # it as it was self.logger.logTxtFile.close() diff --git a/src/configManager.py b/src/configManager.py index 9f87b4f..3920927 100644 --- a/src/configManager.py +++ b/src/configManager.py @@ -508,8 +508,8 @@ class ConfigManager: # " file of salomTools).\n") # - src.ensure_path_exists(config.VARS.personalDir) - src.ensure_path_exists(os.path.join(config.VARS.personalDir, + UTS.ensure_path_exists(config.VARS.personalDir) + UTS.ensure_path_exists(os.path.join(config.VARS.personalDir, 'Applications')) f = open(cfg_name, 'w') diff --git a/src/returnCode.py b/src/returnCode.py index 9b910d3..ec5c5a5 100644 --- a/src/returnCode.py +++ b/src/returnCode.py @@ -90,12 +90,12 @@ class ReturnCode(object): def __repr__(self): """complete with value, 'ok, why, value' message""" - res = "%s: '%s' for value: %s" % (self._status, self._why, PP.pformat(self._value)) + res = '%s: "%s" for value: %s' % (self._status, self._why, PP.pformat(self._value)) return res def __str__(self): """without value, only simple 'ok, why' message""" - res = "%s: '%s'" % (self._status, self._why) + res = '%s: "%s"' % (self._status, self._why) return res def indent(self, text, amount=5, ch=' '): diff --git a/src/system.py b/src/system.py index 7d169b1..fd59c04 100644 --- a/src/system.py +++ b/src/system.py @@ -17,22 +17,25 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ''' -In this file : all functions that do a system call, +All utilities method doing a system call, like open a browser or an editor, or call a git command + +usage: + >> import src.system as SYSS ''' import subprocess import os import tarfile - -from . import printcolors +import src.returnCode as RCO def show_in_editor(editor, filePath, logger): - '''open filePath using editor. + """\ + open filePath using editor. :param editor str: The editor to use. :param filePath str: The path to the file to open. - ''' + """ # default editor is vi if editor is None or len(editor) == 0: editor = 'vi' @@ -43,16 +46,20 @@ def show_in_editor(editor, filePath, logger): try: # launch cmd using subprocess.Popen cmd = editor % filePath - logger.write('Launched command:\n' + cmd + '\n', 5) + msg = "show_in_editor command: '%s'" % cmd + logger.debug(msg) p = subprocess.Popen(cmd, shell=True) p.communicate() + return RCO.ReturnCode("OK", msg) except: - logger.write(printcolors.printcError( - _("Unable to edit file %s\n") % filePath), 1) + msg = _("Unable to edit file '%s'") % filePath + logger.error(msg) + return RCO.ReturnCode("KO", msg) def git_extract(from_what, tag, where, logger, environment=None): - '''Extracts sources from a git repository. + """\ + Extracts sources from a git repository. :param from_what str: The remote git repository. :param tag str: The tag. @@ -62,7 +69,7 @@ def git_extract(from_what, tag, where, logger, environment=None): extracting. :return: True if the extraction is successful :rtype: boolean - ''' + """ if not where.exists(): where.make() if tag == "master" or tag == "HEAD": @@ -79,7 +86,7 @@ def git_extract(from_what, tag, where, logger, environment=None): 'where': str(where), 'where_git': where_git } - logger.write(command + "\n", 5) + logger.debug("git_extract \n" + command) logger.logTxtFile.write("\n" + command + "\n") logger.logTxtFile.flush() @@ -92,26 +99,28 @@ def git_extract(from_what, tag, where, logger, environment=None): return (res == 0) def archive_extract(from_what, where, logger): - '''Extracts sources from an archive. + """\ + Extracts sources from an archive. :param from_what str: The path to the archive. :param where str: The path where to extract. :param logger Logger: The logger instance to use. :return: True if the extraction is successful :rtype: boolean - ''' + """ try: archive = tarfile.open(from_what) for i in archive.getmembers(): archive.extract(i, path=str(where)) return True, os.path.commonprefix(archive.getnames()) except Exception as exc: - logger.write("archive_extract: %s\n" % exc) + logger.error("archive_extract: %s\n" % exc) return False, None def cvs_extract(protocol, user, server, base, tag, product, where, logger, checkout=False, environment=None): - '''Extracts sources from a cvs repository. + """\ + Extracts sources from a cvs repository. :param protocol str: The cvs protocol. :param user str: The user to be used. @@ -126,7 +135,7 @@ def cvs_extract(protocol, user, server, base, tag, product, where, extracting. :return: True if the extraction is successful :rtype: boolean - ''' + """ opttag = '' if tag is not None and len(tag) > 0: @@ -170,7 +179,8 @@ def svn_extract(user, logger, checkout=False, environment=None): - '''Extracts sources from a svn repository. + """\ + Extracts sources from a svn repository. :param user str: The user to be used. :param from_what str: The remote git repository. @@ -182,7 +192,7 @@ def svn_extract(user, extracting. :return: True if the extraction is successful :rtype: boolean - ''' + """ if not where.exists(): where.make() diff --git a/src/utilsSat.py b/src/utilsSat.py index e81d11a..5305ea4 100644 --- a/src/utilsSat.py +++ b/src/utilsSat.py @@ -17,14 +17,14 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -""" +"""\ utilities for sat general useful simple methods all-in-one import srs.utilsSat as UTS usage: - >> import srs.utilsSat as UTS - >> UTS.ensure_path_exists(path) +>> import srsc.utilsSat as UTS +>> UTS.ensure_path_exists(path) """ import os @@ -32,7 +32,11 @@ import shutil import errno import stat -from src.coloringSat import cleanColors # as shortcut +import datetime +import re +import tempfile + +import src.returnCode as RCO ############################################################################## # file system utilities @@ -349,14 +353,14 @@ def formatTuples(tuples): :param tuples list: The list of tuples to format :return: The tabulated text. (mutiples lines) """ - # find the maximum length of the first value of the tuples in info + # find the maximum length of the first value of the tuples smax = max(map(lambda l: len(l[0]), tuples)) # Print each item of tuples with good indentation msg = "" - for i in info: + for i in tuples: sp = " " * (smax - len(i[0])) - msg += sp + "%s = %s\n" % i[0:1] # tuples, may be longer - if len(info) > 1: msg += "\n" # for long list + msg += sp + "%s = %s\n" % (i[0], i[1]) # tuples, may be longer + if len(tuples) > 1: msg += "\n" # for long list return msg def formatValue(label, value, suffix=""): @@ -488,4 +492,157 @@ def parse_date(date): return res +############################################################################## +# log utilities (TODO: set in loggingSat class ? ...) +############################################################################## +_log_macro_command_file_expression = "^[0-9]{8}_+[0-9]{6}_+.*\.xml$" + +def date_to_datetime(date): + """\ + From a string date in format YYYYMMDD_HHMMSS + returns list year, mon, day, hour, minutes, seconds + + :param date str: The date in format YYYYMMDD_HHMMSS + :return: the same date and time in separate variables. + :rtype: (str,str,str,str,str,str) + """ + Y = date[:4] + m = date[4:6] + dd = date[6:8] + H = date[9:11] + M = date[11:13] + S = date[13:15] + return Y, m, dd, H, M, S + +def timedelta_total_seconds(timedelta): + """\ + Replace total_seconds from datetime module + in order to be compatible with old python versions + + :param timedelta datetime.timedelta: The delta between two dates + :return: The number of seconds corresponding to timedelta. + :rtype: float + """ + return ( + timedelta.microseconds + 0.0 + + (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6 + +def show_command_log(logFilePath, cmd, application, notShownCommands): + """\ + Used in updateHatXml. + Determine if the log xml file logFilePath + has to be shown or not in the hat log. + + :param logFilePath str: the path to the command xml log file + :param cmd str: the command of the log file + :param application str: the application passed as parameter + to the salomeTools command + :param notShownCommands list: the list of commands + that are not shown by default + + :return: RCO.ReturnCode("OK") if cmd is not in notShownCommands and the application + in the log file corresponds to application + ReturnCode value is tuple (appliLog, launched_cmd) + """ + # When the command is not in notShownCommands, no need to go further : + # Do not show + if cmd in notShownCommands: + return RCO.ReturnCode("KO", "in notShownCommands", None) + + # Get the application of the log file + try: + logFileXml = src.xmlManager.ReadXmlFile(logFilePath) + except Exception as e: + msg = _("The log file '%s' cannot be read:" % logFilePath) + return RCO.ReturnCode("KO", msg, None) + + if 'application' in logFileXml.xmlroot.keys(): + appliLog = logFileXml.xmlroot.get('application') + launched_cmd = logFileXml.xmlroot.find('Site').attrib['launchedCommand'] + # if it corresponds, then the log has to be shown + if appliLog == application: + return RCO.ReturnCode("OK", "appliLog == application", (appliLog, launched_cmd)) + elif application != 'None': + return RCO.ReturnCode("KO", "application != 'None'", (appliLog, launched_cmd)) + + return RCO.ReturnCode("OK", "", (appliLog, launched_cmd)) + + if application == 'None': + return RCO.ReturnCode("OK", "application == 'None'", (None, None)) + + return RCO.ReturnCode("KO", "", (None, None)) + +def list_log_file(dirPath, expression): + """Find all files corresponding to expression in dirPath + + :param dirPath str: the directory where to search the files + :param expression str: the regular expression of files to find + :return: the list of files path and informations about it + :rtype: list + """ + lRes = [] + for fileName in os.listdir(dirPath): + # YYYYMMDD_HHMMSS_namecmd.xml + sExpr = expression + oExpr = re.compile(sExpr) + if oExpr.search(fileName): + file_name = fileName + if fileName.startswith("micro_"): + file_name = fileName[len("micro_"):] + # get date and hour and format it + date_hour_cmd_host = file_name.split('_') + date_not_formated = date_hour_cmd_host[0] + date = "%s/%s/%s" % (date_not_formated[6:8], + date_not_formated[4:6], + date_not_formated[0:4]) + hour_not_formated = date_hour_cmd_host[1] + hour = "%s:%s:%s" % (hour_not_formated[0:2], + hour_not_formated[2:4], + hour_not_formated[4:6]) + if len(date_hour_cmd_host) < 4: + cmd = date_hour_cmd_host[2][:-len('.xml')] + host = "" + else: + cmd = date_hour_cmd_host[2] + host = date_hour_cmd_host[3][:-len('.xml')] + lRes.append((os.path.join(dirPath, fileName), + date_not_formated, + date, + hour_not_formated, + hour, + cmd, + host)) + return lRes + +def update_hat_xml(logDir, application=None, notShownCommands = []): + """\ + Create the xml file in logDir that contain all the xml file + and have a name like YYYYMMDD_HHMMSS_namecmd.xml + + :param logDir str: the directory to parse + :param application str: the name of the application if there is any + """ + # Create an instance of XmlLogFile class to create hat.xml file + xmlHatFilePath = os.path.join(logDir, 'hat.xml') + xmlHat = src.xmlManager.XmlLogFile(xmlHatFilePath, + "LOGlist", {"application" : application}) + # parse the log directory to find all the command logs, + # then add it to the xml file + lLogFile = list_log_file(logDir, _log_macro_command_file_expression) + for filePath, __, date, __, hour, cmd, __ in lLogFile: + showLog, cmdAppli, full_cmd = show_command_log(filePath, cmd, + application, notShownCommands) + #if cmd not in notShownCommands: + if showLog: + # add a node to the hat.xml file + xmlHat.add_simple_node("LogCommand", + text=os.path.basename(filePath), + attrib = {"date" : date, + "hour" : hour, + "cmd" : cmd, + "application" : cmdAppli, + "full_command" : full_cmd}) + + # Write the file on the hard drive + xmlHat.write_tree('hat.xsl') diff --git a/src/xmlManager.py b/src/xmlManager.py index ca8ec61..ef11b41 100644 --- a/src/xmlManager.py +++ b/src/xmlManager.py @@ -24,8 +24,8 @@ try: # For python2 except: pass -import src -from . import ElementTree as etree +import src.utilsSat as UTS +import src.ElementTree as etree class XmlLogFile(object): '''Class to manage writing in salomeTools xml log file @@ -41,7 +41,7 @@ class XmlLogFile(object): # Initialize the filePath and ensure that the directory # that contain the file exists (make it if necessary) self.logFile = filePath - src.ensure_path_exists(os.path.dirname(filePath)) + UTS.ensure_path_exists(os.path.dirname(filePath)) # Initialize the field that contain the xml in memory self.xmlroot = etree.Element(rootname, attrib = attrib) diff --git a/src/xsl/LOGO-SAT.png b/src/xsl/LOGO-SAT.png index 44f2ee668317b36748554fc8681e6603ece9b45e..eb27403e88143acc65d0c8c055bbd04937d83503 100644 GIT binary patch literal 87756 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�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