X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2FsalomeContext.py;h=aa8ce10a654fc742b830fca5b18045e52178084f;hb=4b14a3f48efda72f90b88c78c6ae02153631dfd6;hp=2132c0613ac6d29698c46b5ed551b89327f8b022;hpb=463b7bde63a727ea30995123dc820d5a4e421924;p=modules%2Fkernel.git diff --git a/bin/salomeContext.py b/bin/salomeContext.py index 2132c0613..aa8ce10a6 100644 --- a/bin/salomeContext.py +++ b/bin/salomeContext.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2016 CEA/DEN, EDF R&D, OPEN CASCADE +# Copyright (C) 2013-2017 CEA/DEN, EDF R&D, OPEN CASCADE # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,10 +20,9 @@ import os import sys import logging -import ConfigParser +import configparser from parseConfigFile import parseConfigFile -from parseConfigFile import convertEnvFileToConfigFile import tempfile import pickle @@ -42,7 +41,7 @@ Commands: context Initialize SALOME context. Current environment is extended. shell Initialize SALOME context, attached to the last created SALOME instance if any, and executes scripts passed as command arguments. - User works in a Shell terminal; SALOME environment is set but + User works in a Shell terminal. SALOME environment is set but application is not started. connect Connect a Python console to the active SALOME instance. kill Terminate SALOME instances running on given ports for current user. @@ -51,14 +50,16 @@ Commands: Do not start a new one. test Run SALOME tests. info Display some information about SALOME. + doc Show online module documentation (if available). + Module names must be separated by blank characters. help Show this message. -If no command is given, default to start. +If no command is given, default is start. Command options: ================ - Use salome --help to show help on command ; available for commands: - start, shell, connect, test, info. + Use salome --help to show help on command. Available for the + following commands: start, shell, connect, test, info. --config= ========================== @@ -67,7 +68,7 @@ Command options: any blank characters. ''' - print msg + print(msg) # """ @@ -79,48 +80,34 @@ class SalomeContext: """ Initialize context from a list of configuration files identified by their names. - These files should be in appropriate (new .cfg) format. - However you can give old .sh environment files; in this case, - the SalomeContext class will try to automatically convert them - to .cfg format before setting the context. + These files should be in appropriate .cfg format. """ def __init__(self, configFileNames=0): - #it could be None explicitely (if user use multiples setVariable...for standalone) + self.getLogger().setLevel(logging.INFO) + #it could be None explicitly (if user use multiples setVariable...for standalone) if configFileNames is None: return configFileNames = configFileNames or [] if len(configFileNames) == 0: raise SalomeContextException("No configuration files given") - reserved=['PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH'] + reserved=['PATH', 'DYLD_FALLBACK_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH', 'LIBRARY_PATH', 'QT_PLUGIN_PATH'] for filename in configFileNames: basename, extension = os.path.splitext(filename) if extension == ".cfg": self.__setContextFromConfigFile(filename, reserved) - elif extension == ".sh": - #new convert procedures, temporary could be use not to be automatically deleted - #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False) - temp = tempfile.NamedTemporaryFile(suffix='.cfg') - try: - convertEnvFileToConfigFile(filename, temp.name, reserved) - self.__setContextFromConfigFile(temp.name, reserved) - temp.close() - except (ConfigParser.ParsingError, ValueError) as e: - self.getLogger().error("Invalid token found when parsing file: %s\n"%(filename)) - temp.close() - sys.exit(1) else: - self.getLogger().warning("Unrecognized extension for configuration file: %s", filename) + self.getLogger().error("Unrecognized extension for configuration file: %s", filename) # - def __loadMPI(self, module_name): - print "Trying to load MPI module: %s..."%module_name, + def __loadEnvModules(self, env_modules): + print("Trying to load env modules: %s..." % ' '.join(env_modules)) try: - out, err = subprocess.Popen(["modulecmd", "python", "load", module_name], stdout=subprocess.PIPE).communicate() - exec out # define specific environment variables - print " OK" + out, err = subprocess.Popen(["modulecmd", "python", "load"] + env_modules, stdout=subprocess.PIPE).communicate() + exec(out) # define specific environment variables + print("OK") except: - print " ** Failed **" + print("** Failed **") pass # @@ -128,22 +115,24 @@ class SalomeContext: import os # Run this module as a script, in order to use appropriate Python interpreter # according to current path (initialized from context files). - mpi_module_option = "--with-mpi-module=" - mpi_module = [x for x in args if x.startswith(mpi_module_option)] - if mpi_module: - mpi_module = mpi_module[0][len(mpi_module_option):] - self.__loadMPI(mpi_module) - args = [x for x in args if not x.startswith(mpi_module_option)] + env_modules_option = "--with-env-modules=" + env_modules_l = [x for x in args if x.startswith(env_modules_option)] + if env_modules_l: + env_modules = env_modules_l[-1][len(env_modules_option):].split(',') + self.__loadEnvModules(env_modules) + args = [x for x in args if not x.startswith(env_modules_option)] else: - mpi_module = os.getenv("SALOME_MPI_MODULE_NAME", None) - if mpi_module: - self.__loadMPI(mpi_module) + env_modules = os.getenv("SALOME_ENV_MODULES", None) + if env_modules: + self.__loadEnvModules(env_modules.split(',')) absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','') env_copy = os.environ.copy() - proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True, env=env_copy) - msg = proc.communicate() - return msg, proc.returncode + selfBytes= pickle.dumps(self, protocol=0) + argsBytes= pickle.dumps(args, protocol=0) + proc = subprocess.Popen(['python3', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), selfBytes.decode(), argsBytes.decode()], shell=False, close_fds=True, env=env_copy) + out, err = proc.communicate() + return out, err, proc.returncode # """Append value to PATH environment variable""" @@ -153,7 +142,15 @@ class SalomeContext: """Append value to LD_LIBRARY_PATH environment variable""" def addToLdLibraryPath(self, value): - self.addToVariable('LD_LIBRARY_PATH', value) + if platform.system() == 'Windows': + self.addToVariable('PATH', value) + elif platform.system() == 'Darwin': + if "LAPACK" in value: + self.addToVariable('DYLD_FALLBACK_LIBRARY_PATH', value) + else: + self.addToVariable('DYLD_LIBRARY_PATH', value) + else: + self.addToVariable('LD_LIBRARY_PATH', value) # """Append value to DYLD_LIBRARY_PATH environment variable""" @@ -170,11 +167,11 @@ class SalomeContext: def setVariable(self, name, value, overwrite=False): env = os.getenv(name, '') if env and not overwrite: - self.getLogger().warning("Environment variable already existing (and not overwritten): %s=%s", name, value) + self.getLogger().error("Environment variable already existing (and not overwritten): %s=%s", name, value) return if env: - self.getLogger().warning("Overwriting environment variable: %s=%s", name, value) + self.getLogger().debug("Overwriting environment variable: %s=%s", name, value) value = os.path.expandvars(value) # expand environment variables self.getLogger().debug("Set environment variable: %s=%s", name, value) @@ -221,12 +218,13 @@ class SalomeContext: 'killall' : '_killAll', 'test' : '_runTests', 'info' : '_showInfo', + 'doc' : '_showDoc', 'help' : '_usage', 'coffee' : '_makeCoffee', 'car' : '_getCar', } - if not command in availableCommands.keys(): + if command not in availableCommands: command = "start" options = args @@ -235,7 +233,7 @@ class SalomeContext: """ Run SALOME! - Args consist in a mandatory command followed by optionnal parameters. + Args consist in a mandatory command followed by optional parameters. See usage for details on commands. """ def _startSalome(self, args): @@ -258,25 +256,25 @@ class SalomeContext: if command is None: if args and args[0] in ["-h","--help","help"]: usage() - sys.exit(0) + return 0 # try to default to "start" command command = "_runAppli" try: res = getattr(self, command)(options) # run appropriate method - return res or (None, None) - except SystemExit, returncode: - if returncode != 0: - self.getLogger().warning("SystemExit %s in method %s.", returncode, command) - sys.exit(returncode) - except StandardError: + return res or 0 + except SystemExit as ex: + if ex.code != 0: + self.getLogger().error("SystemExit %s in method %s.", ex.code, command) + return ex.code + except SalomeContextException as e: + self.getLogger().error(e) + return 1 + except Exception: self.getLogger().error("Unexpected error:") import traceback traceback.print_exc() - sys.exit(1) - except SalomeContextException, e: - self.getLogger().error(e) - sys.exit(1) + return 1 # def __setContextFromConfigFile(self, filename, reserved=None): @@ -284,30 +282,10 @@ class SalomeContext: reserved = [] try: unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved) - except SalomeContextException, e: + except SalomeContextException as e: msg = "%s"%e - file_dir = os.path.dirname(filename) - file_base = os.path.basename(filename) - base_no_ext, ext = os.path.splitext(file_base) - sh_file = os.path.join(file_dir, base_no_ext+'.sh') - if ext == ".cfg" and os.path.isfile(sh_file): - msg += "Found similar %s file; trying to parse this one instead..."%(base_no_ext+'.sh') - temp = tempfile.NamedTemporaryFile(suffix='.cfg') - try: - convertEnvFileToConfigFile(sh_file, temp.name, reserved) - self.__setContextFromConfigFile(temp.name, reserved) - msg += "OK\n" - self.getLogger().warning(msg) - temp.close() - return - except (ConfigParser.ParsingError, ValueError) as e: - msg += "Invalid token found when parsing file: %s\n"%(sh_file) - self.getLogger().error(msg) - temp.close() - sys.exit(1) - else: - self.getLogger().error(msg) - sys.exit(1) + self.getLogger().error(msg) + return 1 # unset variables for var in unsetVars: @@ -315,7 +293,7 @@ class SalomeContext: # set context for reserved in reservedDict: - a = filter(None, reservedDict[reserved]) # remove empty elements + a = [_f for _f in reservedDict[reserved] if _f] # remove empty elements a = [ os.path.realpath(x) for x in a ] reformattedVals = os.pathsep.join(a) if reserved in ["INCLUDE", "LIBPATH"]: @@ -343,26 +321,28 @@ class SalomeContext: import runSalome runSalome.runSalome() + return 0 # def _setContext(self, args=None): salome_context_set = os.getenv("SALOME_CONTEXT_SET") if salome_context_set: - print "***" - print "*** SALOME context has already been set." - print "*** Enter 'exit' (only once!) to leave SALOME context." - print "***" - return + print("***") + print("*** SALOME context has already been set.") + print("*** Enter 'exit' (only once!) to leave SALOME context.") + print("***") + return 0 os.environ["SALOME_CONTEXT_SET"] = "yes" - print "***" - print "*** SALOME context is now set." - print "*** Enter 'exit' (only once!) to leave SALOME context." - print "***" + print("***") + print("*** SALOME context is now set.") + print("*** Enter 'exit' (only once!) to leave SALOME context.") + print("***") cmd = ["/bin/bash"] proc = subprocess.Popen(cmd, shell=False, close_fds=True) - return proc.communicate() + proc.communicate() + return proc.returncode # def _runSession(self, args=None): @@ -396,8 +376,8 @@ class SalomeContext: args = [] ports = args if not ports: - print "Port number(s) not provided to command: salome kill " - return + print("Port number(s) not provided to command: salome kill ") + return 1 from multiprocessing import Process from killSalomeWithPort import killMyPort @@ -407,7 +387,7 @@ class SalomeContext: p = Process(target = killMyPort, args=(port,)) p.start() p.join() - pass + return 0 # def _killAll(self, unused=None): @@ -415,7 +395,7 @@ class SalomeContext: import PortManager # mandatory from multiprocessing import Process from killSalomeWithPort import killMyPort - ports = PortManager.getBusyPorts() + ports = PortManager.getBusyPorts()['this'] if ports: import tempfile @@ -429,6 +409,7 @@ class SalomeContext: from killSalome import killAllPorts killAllPorts() pass + return 0 # def _runTests(self, args=None): @@ -442,6 +423,34 @@ class SalomeContext: return runTests.runTests(args, exe="salome test") # + def _showSoftwareVersions(self, softwares=None): + config = configparser.SafeConfigParser() + absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH') + filename = os.path.join(absoluteAppliPath, "sha1_collections.txt") + versions = {} + max_len = 0 + with open(filename) as f: + for line in f: + try: + software, version, sha1 = line.split() + versions[software.upper()] = version + if len(software) > max_len: + max_len = len(software) + except: + pass + pass + pass + if softwares: + for soft in softwares: + if versions.has_key(soft.upper()): + print(soft.upper().rjust(max_len), versions[soft.upper()]) + else: + import collections + od = collections.OrderedDict(sorted(versions.items())) + for name, version in od.iteritems(): + print(name.rjust(max_len), versions[name]) + pass + def _showInfo(self, args=None): if args is None: args = [] @@ -450,94 +459,142 @@ class SalomeContext: epilog = """\n Display some information about SALOME.\n Available options are: - -p,--ports Show list of busy ports (running SALOME instances). - -v,--version Show running SALOME version. - -h,--help Show this message. + -p,--ports Show the list of busy ports (running SALOME instances). + -s,--softwares [software(s)] Show the list and versions of SALOME softwares. + Software names must be separated by blank characters. + If no software is given, show version of all softwares. + -v,--version Show running SALOME version. + -h,--help Show this message. """ if not args: args = ["--version"] if "-h" in args or "--help" in args: - print usage + epilog - return + print(usage + epilog) + return 0 if "-p" in args or "--ports" in args: import PortManager ports = PortManager.getBusyPorts() - print "SALOME instances are running on ports:", ports - if ports: - print "Last started instance on port %s"%ports[-1] + this_ports = ports['this'] + other_ports = ports['other'] + if this_ports or other_ports: + print("SALOME instances are running on the following ports:") + if this_ports: + print(" This application:", this_ports) + else: + print(" No SALOME instances of this application") + if other_ports: + print(" Other applications:", other_ports) + else: + print(" No SALOME instances of other applications") + else: + print("No SALOME instances are running") + + if "-s" in args or "--softwares" in args: + if "-s" in args: + index = args.index("-s") + else: + index = args.index("--softwares") + indexEnd=index+1 + while indexEnd < len(args) and args[indexEnd][0] != "-": + indexEnd = indexEnd + 1 + self._showSoftwareVersions(softwares=args[index+1:indexEnd]) if "-v" in args or "--version" in args: - print "Running with python", platform.python_version() - self._runAppli(["--version"]) + print("Running with python", platform.python_version()) + return self._runAppli(["--version"]) + + return 0 # + def _showDoc(self, args=None): + if args is None: + args = [] + + modules = args + if not modules: + print("Module(s) not provided to command: salome doc ") + return 1 + + appliPath = os.getenv("ABSOLUTE_APPLI_PATH") + if not appliPath: + raise SalomeContextException("Unable to find application path. Please check that the variable ABSOLUTE_APPLI_PATH is set.") + baseDir = os.path.join(appliPath, "share", "doc", "salome") + for module in modules: + docfile = os.path.join(baseDir, "gui", module.upper(), "index.html") + if not os.path.isfile(docfile): + docfile = os.path.join(baseDir, "tui", module.upper(), "index.html") + if not os.path.isfile(docfile): + docfile = os.path.join(baseDir, "dev", module.upper(), "index.html") + if os.path.isfile(docfile): + out, err = subprocess.Popen(["xdg-open", docfile]).communicate() + else: + print("Online documentation is not accessible for module:", module) + def _usage(self, unused=None): usage() # def _makeCoffee(self, unused=None): - print " (" - print " ) (" - print " ___...(-------)-....___" - print " .-\"\" ) ( \"\"-." - print " .-\'``\'|-._ ) _.-|" - print " / .--.| `\"\"---...........---\"\"` |" - print " / / | |" - print " | | | |" - print " \\ \\ | |" - print " `\\ `\\ | |" - print " `\\ `| SALOME |" - print " _/ /\\ 4 EVER /" - print " (__/ \\ <3 /" - print " _..---\"\"` \\ /`\"\"---.._" - print " .-\' \\ / \'-." - print " : `-.__ __.-\' :" - print " : ) \"\"---...---\"\" ( :" - print " \'._ `\"--...___...--\"` _.\'" - print " \\\"\"--..__ __..--\"\"/" - print " \'._ \"\"\"----.....______.....----\"\"\" _.\'" - print " `\"\"--..,,_____ _____,,..--\"\"`" - print " `\"\"\"----\"\"\"`" - print "" - print " SALOME is working for you; what else?" - print "" - sys.exit(0) + print(" (") + print(" ) (") + print(" ___...(-------)-....___") + print(" .-\"\" ) ( \"\"-.") + print(" .-\'``\'|-._ ) _.-|") + print(" / .--.| `\"\"---...........---\"\"` |") + print(" / / | |") + print(" | | | |") + print(" \\ \\ | |") + print(" `\\ `\\ | |") + print(" `\\ `| SALOME |") + print(" _/ /\\ 4 EVER /") + print(" (__/ \\ <3 /") + print(" _..---\"\"` \\ /`\"\"---.._") + print(" .-\' \\ / \'-.") + print(" : `-.__ __.-\' :") + print(" : ) \"\"---...---\"\" ( :") + print(" \'._ `\"--...___...--\"` _.\'") + print(" \\\"\"--..__ __..--\"\"/") + print(" \'._ \"\"\"----.....______.....----\"\"\" _.\'") + print(" `\"\"--..,,_____ _____,,..--\"\"`") + print(" `\"\"\"----\"\"\"`") + print("") + print(" SALOME is working for you; what else?") + print("") # def _getCar(self, unused=None): - print " _____________" - print " ..---:::::::-----------. ::::;;." - print " .\'\"\"\"\"\"\" ;; \\ \":." - print " .\'\' ; \\ \"\\__." - print " .\' ;; ; \\\\\";" - print " .\' ; _____; \\\\/" - print " .\' :; ;\" \\ ___:\'." - print " .\'--........................... : = ____:\" \\ \\" - print " ..-\"\" \"\"\"\' o\"\"\" ; ; :" - print " .--\"\" .----- ..----... _.- --. ..-\" ; ; ; ;" - print " .\"\"_- \"--\"\"-----\'\"\" _-\" .-\"\" ; ; .-." - print " .\' .\' SALOME .\" .\" ; ; /. |" - print " /-./\' 4 EVER <3 .\" / _.. ; ; ;;;|" - print " : ;-.______ / _________==. /_ \\ ; ; ;;;;" - print " ; / | \"\"\"\"\"\"\"\"\"\"\".---.\"\"\"\"\"\"\" : /\" \". |; ; _; ;;;" - print " /\"-/ | / / / / ;|; ;-\" | ;\';" - print ":- : \"\"\"----______ / / ____. . .\"\'. ;; .-\"..T\" ." - print "\'. \" ___ \"\": \'\"\"\"\"\"\"\"\"\"\"\"\"\"\" . ; ; ;; ;.\" .\" \'--\"" - print " \", __ \"\"\" \"\"---... :- - - - - - - - - \' \' ; ; ; ;;\" .\"" - print " /. ; \"\"\"---___ ; ; ; ;|.\"\"" - print " : \": \"\"\"----. .-------. ; ; ; ;:" - print " \\ \'--__ \\ \\ \\ / | ; ;;" - print " \'-.. \"\"\"\"---___ : .______..\\ __/..-\"\"| ; ; ;" - print " \"\"--.. \"\"\"--\" m l s . \". . ;" - print " \"\"------... ..--\"\" \" :" - print " \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \\ /" - print " \"------\"" - print "" - print " Drive your simulation properly with SALOME!" - print "" - sys.exit(0) + print(" _____________") + print(" ..---:::::::-----------. ::::;;.") + print(" .\'\"\"\"\"\"\" ;; \\ \":.") + print(" .\'\' ; \\ \"\\__.") + print(" .\' ;; ; \\\\\";") + print(" .\' ; _____; \\\\/") + print(" .\' :; ;\" \\ ___:\'.") + print(" .\'--........................... : = ____:\" \\ \\") + print(" ..-\"\" \"\"\"\' o\"\"\" ; ; :") + print(" .--\"\" .----- ..----... _.- --. ..-\" ; ; ; ;") + print(" .\"\"_- \"--\"\"-----\'\"\" _-\" .-\"\" ; ; .-.") + print(" .\' .\' SALOME .\" .\" ; ; /. |") + print(" /-./\' 4 EVER <3 .\" / _.. ; ; ;;;|") + print(" : ;-.______ / _________==. /_ \\ ; ; ;;;;") + print(" ; / | \"\"\"\"\"\"\"\"\"\"\".---.\"\"\"\"\"\"\" : /\" \". |; ; _; ;;;") + print(" /\"-/ | / / / / ;|; ;-\" | ;\';") + print(":- : \"\"\"----______ / / ____. . .\"\'. ;; .-\"..T\" .") + print("\'. \" ___ \"\": \'\"\"\"\"\"\"\"\"\"\"\"\"\"\" . ; ; ;; ;.\" .\" \'--\"") + print(" \", __ \"\"\" \"\"---... :- - - - - - - - - \' \' ; ; ; ;;\" .\"") + print(" /. ; \"\"\"---___ ; ; ; ;|.\"\"") + print(" : \": \"\"\"----. .-------. ; ; ; ;:") + print(" \\ \'--__ \\ \\ \\ / | ; ;;") + print(" \'-.. \"\"\"\"---___ : .______..\\ __/..-\"\"| ; ; ;") + print(" \"\"--.. \"\"\"--\" m l s . \". . ;") + print(" \"\"------... ..--\"\" \" :") + print(" \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \\ /") + print(" \"------\"") + print("") + print(" Drive your simulation properly with SALOME!") + print("") # # Add the following two methods since logger is not pickable @@ -563,14 +620,11 @@ Available options are: if __name__ == "__main__": if len(sys.argv) == 3: - context = pickle.loads(sys.argv[1]) - args = pickle.loads(sys.argv[2]) - - (out, err) = context._startSalome(args) - if out: - sys.stdout.write(out) - if err: - sys.stderr.write(err) + context = pickle.loads(sys.argv[1].encode()) + args = pickle.loads(sys.argv[2].encode()) + + status = context._startSalome(args) + sys.exit(status) else: usage() #