From 7798954d7ce7ac727dd4bc91ddce50bbb1d426cd Mon Sep 17 00:00:00 2001 From: Christian Van Wambeke Date: Tue, 23 Jan 2018 10:23:25 +0100 Subject: [PATCH] first src/test/satHelpTest.py ok --- .spyderproject | Bin 0 -> 92 bytes commands/run.py | 8 +- src/debug.py | 14 +- src/i18n/{test_i18n.py => i18nTest.py} | 0 src/logger.py | 6 +- src/options.py | 31 ++-- src/salomeTools.py | 165 +++++++++++++----- src/test/satHelpTest.py | 82 +++++++++ src/test_module.py | 6 +- .../script_test_module.pyTemplate} | 15 +- .../utils_test_module.py} | 6 +- 11 files changed, 258 insertions(+), 75 deletions(-) create mode 100644 .spyderproject rename src/i18n/{test_i18n.py => i18nTest.py} (100%) create mode 100755 src/test/satHelpTest.py rename src/{test/scriptTemplate.py => test_module/script_test_module.pyTemplate} (88%) rename src/{test/TOOLS.py => test_module/utils_test_module.py} (98%) diff --git a/.spyderproject b/.spyderproject new file mode 100644 index 0000000000000000000000000000000000000000..cfa47ec2125ef3d2de96629121e4e877c8c211c0 GIT binary patch literal 92 zcmZo*sx4&H2o)$w%}FdtO^Gik%FjwoE-5Z#iY;Ug6$T4umZioQRF-7q=M^NDWE8T* shO*=(=B5_1MsPDQFcc@2n8p_uRHmdB6|#l0> sat run SALOME-master""") def run(args, runner, logger): '''method that is called when salomeTools is called with run parameter. diff --git a/src/debug.py b/src/debug.py index 8ea680c..33dda56 100644 --- a/src/debug.py +++ b/src/debug.py @@ -26,10 +26,18 @@ import pprint as PP _debug = [False] #support push/pop for temporary active outputs +def indent(text, amount=2, ch=' '): + padding = amount * ch + return ''.join(padding + line for line in text.splitlines(True)) + def write(title, var="", force=None): """write sys.stderr a message if _debug[-1]==True or optionaly force=True""" - if _debug[-1] or force: - sys.stderr.write("\n#### DEBUG: %s:\n%s\n" % (title, PP.pformat(var))) + fmt = "\n#### DEBUG: %s:\n%s\n" + if _debug[-1] or force: + if type(var) is not str: + sys.stderr.write(fmt % (title, indent(PP.pformat(var)))) + else: + sys.stderr.write(fmt % (title, indent(var))) return def push_debug(aBool): @@ -41,5 +49,5 @@ def pop_debug(): if len(_debug) > 1: return _debug.pop() else: - sys.stderr.write("\n#### DEBUG: ERROR: too much pop_debug()") + sys.stderr.write("\nERROR: pop_debug: too much pop.") return None diff --git a/src/i18n/test_i18n.py b/src/i18n/i18nTest.py similarity index 100% rename from src/i18n/test_i18n.py rename to src/i18n/i18nTest.py diff --git a/src/logger.py b/src/logger.py index cebe0e1..db300ee 100644 --- a/src/logger.py +++ b/src/logger.py @@ -25,12 +25,14 @@ import re import tempfile import src -from . import printcolors -from . import xmlManager + +from src import printcolors +from src import xmlManager log_macro_command_file_expression = "^[0-9]{8}_+[0-9]{6}_+.*\.xml$" log_all_command_file_expression = "^.*[0-9]{8}_+[0-9]{6}_+.*\.xml$" + class Logger(object): '''Class to handle log mechanism. ''' diff --git a/src/options.py b/src/options.py index 22c51f9..cce23d3 100644 --- a/src/options.py +++ b/src/options.py @@ -113,26 +113,33 @@ class Options(object): option['result'] = default self.options.append(option) - def print_help(self): - '''Method that display all options stored in self.options and there help + def get_help(self): + '''Method that returns all options stored in self.options + as help message colored string - :return: Nothing. + :return: colored string :rtype: N\A ''' + msg = "" # Do nothing if there are no options if len(self.options) == 0: - return + return _("No available options.") - # for all options, print its values. + # for all options, gets its values. # "shortname" is an optional field of the options - print(src.printcolors.printcHeader(_("Available options are:"))) + msg += src.printcolors.printcHeader(_("Available options are:")) + "\n" for option in self.options: if 'shortName' in option and len(option['shortName']) > 0: - print(" -%(shortName)1s, --%(longName)s" - " (%(optionType)s)\n\t%(helpString)s\n" % option) + msg += "\n -%(shortName)1s, --%(longName)s" \ + " (%(optionType)s)\n\t%(helpString)s\n" % option else: - print(" --%(longName)s (%(optionType)s)\n\t%(helpString)s\n" - % option) + msg += "\n --%(longName)s (%(optionType)s)\n\t%(helpString)s\n" \ + % option + return msg + + def print_help(self): + print(self.get_help()) + def parse_args(self, argList=None): '''Method that instantiates the class OptResult @@ -148,7 +155,7 @@ class Options(object): argList = sys.argv[1:] DBG.write("parse_args", argList) - DBG.write("options", self.options) + # DBG.write("options", self.options) # format shortNameOption and longNameOption # to make right arguments to getopt.getopt function shortNameOption = "" @@ -208,7 +215,7 @@ class Options(object): option['result'] = None self.results = {"optlist": optlist, "optResult": optResult, "args": args, "argList": argList} - DBG.write("options and results", self) + DBG.write("results", self.results) return optResult, args def __repr__(self): diff --git a/src/salomeTools.py b/src/salomeTools.py index f5ca674..4036061 100755 --- a/src/salomeTools.py +++ b/src/salomeTools.py @@ -28,7 +28,7 @@ import imp import types import gettext import traceback - +import subprocess as SP ################################# # NOT MAIN allowed @@ -48,7 +48,6 @@ srcdir = os.path.join(rootdir, "src") cmdsdir = os.path.join(rootdir, "commands") # load resources for internationalization -# DBG.write("TODO", "fix xxsalomeTools to avoid french", True) gettext.install('salomeTools', os.path.join(srcdir, 'i18n')) # salomeTools imports @@ -61,6 +60,7 @@ import commands.config C_PRE_HOOK = "pre" C_POST_HOOK = "post" +_LANG = os.environ["LANG"] # original locale def find_command_list(dirPath): '''Parse files in dirPath that end with .py : it gives commands list @@ -86,6 +86,33 @@ def getCommandsList(): """ return lCommand +def launchSat(command): + """launch sat as subprocess popen + command as string ('sat --help' for example) + used for unittest, or else... + returns tuple (stdout, stderr) + """ + if "sat" not in command.split()[0]: + raise Exception(_("Not a valid command for launchSat: '%s'") % command) + env = dict(os.environ) + env["PATH"] = rootdir + ":" + env["PATH"] + res =SP.Popen(command, shell=True, env=env, stdout=SP.PIPE, stderr=SP.PIPE).communicate() + return res + +def setNotLocale(): + """force english at any moment""" + os.environ["LANG"] = '' + gettext.install('salomeTools', os.path.join(srcdir, 'i18n')) + DBG.write("setNotLocale", os.environ["LANG"]) + +def setLocale(): + """reset initial locale at any moment + 'fr' or else 'TODO' from initial environment var '$LANG' + """ + os.environ["LANG"] = _LANG + gettext.install('salomeTools', os.path.join(srcdir, 'i18n')) + DBG.write("setLocale", os.environ["LANG"]) + # Define all possible option for salomeTools command : sat parser = src.options.Options() parser.add_option('h', 'help', 'boolean', 'help', @@ -102,24 +129,28 @@ parser.add_option('t', 'all_in_terminal', 'boolean', "all_in_terminal", _("all traces in the terminal (for example compilation logs).")) parser.add_option('l', 'logs_paths_in_file', 'string', "logs_paths_in_file", _("put the command result and paths to log files.")) - + class Sat(object): '''The main class that stores all the commands of salomeTools ''' def __init__(self, opt='', datadir=None): '''Initialization - :param opt str: The sat options + :param opt str or list: The sat options :param: datadir str : the directory that contain all the external data (like software pyconf and software scripts) ''' # Read the salomeTools prefixes options before the 'commands' tag # sat - # (the list of possible options is at the beginning of this file) + # (the list of possible options is at the beginning of this file) try: - options, args = parser.parse_args(opt) - DBG.write("Sat args", args) - DBG.write("Sat options", options) + if type(opt) is not list: # as string 'sat --help' for example' + opts = opt.split() + else: + opts = opt + options, args = parser.parse_args(opts) + # DBG.write("Sat args", args) + # DBG.write("Sat options", options) except Exception as exc: write_exception(exc) sys.exit(src.KOSYS) @@ -133,6 +164,8 @@ class Sat(object): # set the commands by calling the dedicated function self._setCommands(cmdsdir) + ''' + # done with execute_command, to avoid sys.exit # if the help option has been called, print help and exit if options.help: try: @@ -142,6 +175,7 @@ class Sat(object): write_exception(exc) DBG.write("args", args, True) sys.exit(src.KOSYS) + ''' def __getattr__(self, name): '''overwrite of __getattr__ function in order to display @@ -152,7 +186,7 @@ class Sat(object): if name in self.__dict__: return self.__dict__[name] else: - raise AttributeError(name + _(" is not a valid command")) + raise AttributeError("'%s'" % name + _(" is not a valid command")) def execute_command(self, opt=None): """select first argument as a command in directory 'commands', and launch on arguments @@ -164,9 +198,15 @@ class Sat(object): else: args = self.arguments + # print general help and returns if len(args) == 0: print_help() return src.OKSYS + + # if the help option has been called, print command help and returns + if self.options.help: + self.print_help(self.arguments) + return src.OKSYS # the command called command = args[0] @@ -375,7 +415,7 @@ class Sat(object): res = 1 # print the log file path if - # the maximum verbose mode is invoked + # the maximum verbose mode is invoked if not micro_command: logger_command.write("\nPath to the xml log file:\n", 5) logger_command.write("%s\n\n" % \ @@ -466,6 +506,7 @@ class Sat(object): if len(opt)==0: print_help() return + # get command name command = opt[0] # read the configuration from all the pyconf files @@ -476,20 +517,35 @@ class Sat(object): if not hasattr(self, command): raise src.SatException(_("Command '%s' does not exist") % command) - # Print salomeTools version - print_version() - # load the module module = self.get_module(command) - + + msg = self.get_module_help(module) + + if isStdoutPipe(): + # clean color if the terminal is redirected by user + # ex: sat compile appli > log.txt + msg = src.printcolors.cleancolor(msg) + print(msg) + return + + def get_module_help(self, module): + """get help for a command + as 'sat --help config' for example + """ + # get salomeTools version + msg = get_version() + "\n\n" + # print the description of the command that is done in the command file - if hasattr( module, "description" ) : - print(src.printcolors.printcHeader( _("Description:") )) - print(module.description() + '\n') + if hasattr( module, "description" ): + msg += src.printcolors.printcHeader( _("Description:") ) + "\n" + msg += module.description() + "\n\n" # print the description of the command options if hasattr( module, "parser" ) : - module.parser.print_help() + msg += module.parser.get_help() + "\n" + return msg + def get_module(self, module): '''Loads a command. Function called only by print_help @@ -504,6 +560,7 @@ class Sat(object): (file_, pathname, description) = imp.find_module(module, [cmdsdir]) module = imp.load_module(module, file_, pathname, description) return module + def get_text_from_options(options): text_options = "" @@ -518,42 +575,56 @@ def get_text_from_options(options): option_contain = "" text_options+= "--%s %s " % (attr, option_contain) return text_options - - -def print_version(): - '''prints salomeTools version (in src/internal_config/salomeTools.pyconf) - ''' - # read the config + + +def isStdoutPipe(): + """check if the terminal is redirected by user (elsewhere a tty) + example: + >> sat compile appli > log.txt + """ + return not ('isatty' in dir(sys.stdout) and sys.stdout.isatty()) + +def get_version(): + """get version colored string + """ cfgManager = commands.config.ConfigManager() cfg = cfgManager.get_config() # print the key corresponding to salomeTools version - print(src.printcolors.printcHeader( _("Version: ") ) + - cfg.INTERNAL.sat_version + '\n') - - -def print_help(): - '''prints salomeTools general help - - :param options str: the options - ''' - print_version() - - print(src.printcolors.printcHeader( _("Usage: ") ) + - "sat [sat_options] [product] [command_options]\n") - - parser.print_help() - - # display all the available commands. - print(src.printcolors.printcHeader(_("Available commands are:\n"))) + msg = src.printcolors.printcHeader( _("Version: ") ) + \ + cfg.INTERNAL.sat_version + return msg + +def get_help(): + """get general help colored string + """ + # read the config + msg = get_version() + "\n\n" + msg += src.printcolors.printcHeader(_("Usage: ")) + \ + "sat [sat_options] [product] [command_options]\n\n" + msg += parser.get_help() + "\n" + msg += src.printcolors.printcHeader(_("Available commands are:")) + "\n\n" for command in lCommand: - print(" - %s" % (command)) - + msg += " - %s\n" % (command) + msg += "\n" # Explain how to get the help for a specific command - print(src.printcolors.printcHeader(_("\nGetting the help for a specific" - " command: ")) + "sat --help \n") + msg += src.printcolors.printcHeader( + _("Getting the help for a specific command: ")) + \ + "sat --help \n" + return msg + +def print_help(): + """prints salomeTools general help + """ + msg = get_help() + if isStdoutPipe(): + # clean color if the terminal is redirected by user + # ex: sat compile appli > log.txt + msg = src.printcolors.cleancolor(msg) + print(msg) + return def write_exception(exc): - '''write exception in case of error in a command + '''write in stderr exception in case of error in a command :param exc exception: the exception to print ''' diff --git a/src/test/satHelpTest.py b/src/test/satHelpTest.py new file mode 100755 index 0000000..6eea8bd --- /dev/null +++ b/src/test/satHelpTest.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +# Copyright (C) 2010-2018 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 + +import os +import sys +import unittest + +import src.salomeTools as SAT +import src +import src.debug as DBG # Easy print stderr (for DEBUG only) + +class TestCase(unittest.TestCase): + "Test the sat --help commands""" + + def test_000(self): + # one shot setUp() for this TestCase + # DBG.push_debug(True) + SAT.setNotLocale() # test english + + def test_010(self): + cmd = "sat --help" + stdout, stderr = SAT.launchSat(cmd) + self.assertEqual(stderr, "") + self.assertTrue(" - config" in stdout) + + def test_011(self): + cmd = "--help" + s = SAT.Sat(cmd) + exitCode = s.execute_command() + self.assertEqual(src.okToStr(exitCode), "OK") + + def test_030(self): + cmd = "sat --help config" + stdout, stderr = SAT.launchSat(cmd) + self.assertEqual(stderr, "") + self.assertTrue("--value" in stdout) + + def test_031(self): + cmd = "--help config" + s = SAT.Sat(cmd) + exitCode = s.execute_command() + self.assertEqual(src.okToStr(exitCode), "OK") + + def test_012(self): + cmd = "config -l" + s = SAT.Sat(cmd) + exitCode = s.execute_command() + self.assertEqual(src.okToStr(exitCode), "OK") + + def test_040(self): + cmds = SAT.getCommandsList() + for c in cmds: + cmd = "sat --help %s" % c + stdout, stderr = SAT.launchSat(cmd) + self.assertEqual(stderr, "") + # DBG.write("stdout '%s'" % cmd, stdout) + self.assertTrue("vailable options" in stdout) + + def test_999(self): + # one shot tearDown() for this TestCase + SAT.setLocale() # end test english + # DBG.pop_debug() + +if __name__ == '__main__': + unittest.main(exit=False) + pass diff --git a/src/test_module.py b/src/test_module.py index ca90232..57a15fd 100755 --- a/src/test_module.py +++ b/src/test_module.py @@ -377,15 +377,15 @@ class Test: def generate_script(self, listTest, script_path, ignoreList): # open template file template_file = open(os.path.join(self.config.VARS.srcDir, - "test", - "scriptTemplate.py"), 'r') + "test_module", + "script_test_module.pyTemplate"), 'r') template = string.Template(template_file.read()) # create substitution dictionary d = dict() d['resourcesWay'] = os.path.join(self.currentDir, 'RESSOURCES') d['tmpDir'] = os.path.join(self.tmp_working_dir, 'WORK') - d['toolsWay'] = os.path.join(self.config.VARS.srcDir, "test") + d['toolsWay'] = os.path.join(self.config.VARS.srcDir, "test_module") d['sessionDir'] = os.path.join(self.currentDir, self.currentgrid, self.currentsession) diff --git a/src/test/scriptTemplate.py b/src/test_module/script_test_module.pyTemplate similarity index 88% rename from src/test/scriptTemplate.py rename to src/test_module/script_test_module.pyTemplate index f3f7de4..b653544 100644 --- a/src/test/scriptTemplate.py +++ b/src/test_module/script_test_module.pyTemplate @@ -1,6 +1,15 @@ #!/usr/bin/env python #-*- coding:utf-8 -*- +# +# WARNING: this script is automaticaly generated from +# salomeTools-5/src/test_module/script_test_module.pyTemplate +# by salomeTools-5/src/test_module.py +# it could be overriden at any time +# +# TODO: change this fucking code +# + import os, sys, traceback import os.path import time as THEBIGTIME @@ -15,10 +24,10 @@ listTest = ${listTest} ignore = ${ignore} sys.path.append(toolsWay) -from TOOLS import TOOLS_class -my_tools = TOOLS_class(resourcesWay, tmpDir, toolsWay) +from utils_test_module import UtilsTest +my_tools = UtilsTest(resourcesWay, tmpDir, toolsWay) -from TOOLS import SatNotApplicableError +from utils_test_module import SatNotApplicableError # on set les variables d'environement os.environ['TT_BASE_RESSOURCES'] = resourcesWay diff --git a/src/test/TOOLS.py b/src/test_module/utils_test_module.py similarity index 98% rename from src/test/TOOLS.py rename to src/test_module/utils_test_module.py index 77e0a4e..2bf5fbb 100644 --- a/src/test/TOOLS.py +++ b/src/test_module/utils_test_module.py @@ -1,15 +1,15 @@ #!/usr/bin/env python #-*- coding:utf-8 -*- -# ToolBox for test framework - import os import string import subprocess """ +ToolBox for test framework salome Exception class for test errors. """ + class SatTestError(Exception): def __init__(self, value): self.value = value @@ -116,7 +116,7 @@ def compMED(file1, file2, tol=0, diff_flags=""): return status -class TOOLS_class: +class UtilsTest: def __init__(self, base_ressources_dir, tmp_dir, test_ressources_dir): self.base_ressources_dir = base_ressources_dir self.tmp_dir = tmp_dir -- 2.39.2