X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=bin%2FsalomeContext.py;h=b67209092e82ac095f26d1542f5f7af2d06a5fed;hb=82668fe5e4d077072402d253497f96d4c53391f9;hp=b2fdc14bfcf04fd8fe1130d9e1faccce8294087f;hpb=cda7408fd5043f4e91e70e79edb0a5caf548d519;p=modules%2Fkernel.git diff --git a/bin/salomeContext.py b/bin/salomeContext.py index b2fdc14bf..b67209092 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 @@ -23,7 +23,6 @@ import logging 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= ========================== @@ -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,22 @@ 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 + out, err = proc.communicate() + return out, err, proc.returncode # """Append value to PATH environment variable""" @@ -155,6 +142,11 @@ class SalomeContext: def addToLdLibraryPath(self, 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) # @@ -173,11 +165,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) @@ -224,6 +216,7 @@ class SalomeContext: 'killall' : '_killAll', 'test' : '_runTests', 'info' : '_showInfo', + 'doc' : '_showDoc', 'help' : '_usage', 'coffee' : '_makeCoffee', 'car' : '_getCar', @@ -238,7 +231,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): @@ -261,25 +254,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) + 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 StandardError: self.getLogger().error("Unexpected error:") import traceback traceback.print_exc() - sys.exit(1) + return 1 except SalomeContextException, e: self.getLogger().error(e) - sys.exit(1) + return 1 # def __setContextFromConfigFile(self, filename, reserved=None): @@ -289,28 +282,8 @@ class SalomeContext: unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved) except SalomeContextException, 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: @@ -346,6 +319,7 @@ class SalomeContext: import runSalome runSalome.runSalome() + return 0 # def _setContext(self, args=None): @@ -355,7 +329,7 @@ class SalomeContext: print "*** SALOME context has already been set." print "*** Enter 'exit' (only once!) to leave SALOME context." print "***" - return + return 0 os.environ["SALOME_CONTEXT_SET"] = "yes" print "***" @@ -365,7 +339,8 @@ class SalomeContext: 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): @@ -400,7 +375,7 @@ class SalomeContext: ports = args if not ports: print "Port number(s) not provided to command: salome kill " - return + return 1 from multiprocessing import Process from killSalomeWithPort import killMyPort @@ -410,7 +385,7 @@ class SalomeContext: p = Process(target = killMyPort, args=(port,)) p.start() p.join() - pass + return 0 # def _killAll(self, unused=None): @@ -418,7 +393,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 @@ -432,6 +407,7 @@ class SalomeContext: from killSalome import killAllPorts killAllPorts() pass + return 0 # def _runTests(self, args=None): @@ -445,6 +421,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 = [] @@ -453,29 +457,79 @@ 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 + 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"]) + 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() # @@ -506,7 +560,6 @@ Available options are: print "" print " SALOME is working for you; what else?" print "" - sys.exit(0) # def _getCar(self, unused=None): @@ -540,7 +593,6 @@ Available options are: print "" print " Drive your simulation properly with SALOME!" print "" - sys.exit(0) # # Add the following two methods since logger is not pickable @@ -569,11 +621,8 @@ if __name__ == "__main__": 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) + status = context._startSalome(args) + sys.exit(status) else: usage() #