-# Copyright (C) 2013-2017 CEA/DEN, EDF R&D, OPEN CASCADE
+#! /usr/bin/env python3
+# Copyright (C) 2013-2024 CEA, EDF, OPEN CASCADE
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
import tempfile
import pickle
import subprocess
+import sys
import platform
from salomeContextUtils import SalomeContextException
def usage():
msg = '''\
-Usage: salome [command] [options] [--config=<file,folder,...>]
+Usage: salome [command] [options] [--config=<file,folder,...>] [--with-env-modules=<env_module1,env_module2,...>]
Commands:
=========
- start Start a new SALOME instance.
+ start Start a new SALOME instance. Start a single SALOME_Session_Server_No_Server
+ process with environment relevant to the application and hosting all servants in it.
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
application is not started.
- connect Connect a Python console to the active SALOME instance.
- kill <port(s)> Terminate SALOME instances running on given ports for current user.
- Port numbers must be separated by blank characters.
- killall Terminate *all* SALOME running instances for current user.
- Do not start a new one.
test Run SALOME tests.
info Display some information about SALOME.
doc <module(s)> Show online module documentation (if available).
Module names must be separated by blank characters.
help Show this message.
+ remote run command in SALOME environment from remote call, ssh or rsh.
+ withsession Start a new SWS SALOME instance with multiple servers hosting all servants.
+ connect In SWS context, Connect a Python console to the active SALOME instance.
+ kill <port(s)> In SWS context, Terminate SALOME instances running on given ports for current user.
+ Port numbers must be separated by blank characters.
+ killall Terminate *all* SALOME running SWS instances for current user.
+ Do not start a new one.
If no command is given, default is start.
--config=<file,folder,...>
==========================
Initialize SALOME context from a list of context files and/or a list
- of folders containing context files. The list is comma-separated, whithout
+ of folders containing context files. The list is comma-separated, without
any blank characters.
+
+--with-env-modules=<env_module1,env_module2,...>
+================================================
+ Initialize SALOME context with the provided additional environment modules.
+ The list is comma-separated, without any blank characters.
'''
print(msg)
#
def __loadEnvModules(self, env_modules):
- print("Trying to load env modules: %s..." % ' '.join(env_modules))
+ modulecmd = os.getenv('LMOD_CMD')
+ if not modulecmd:
+ raise SalomeContextException("Module environment not present")
+ return
try:
- out, err = subprocess.Popen(["modulecmd", "python", "load"] + env_modules, stdout=subprocess.PIPE).communicate()
- exec(out) # define specific environment variables
- print("OK")
- except:
- print("** Failed **")
+ out, err = subprocess.Popen([modulecmd, "python", "try-load"] + env_modules, stdout=subprocess.PIPE).communicate()
+ exec(out) # define specific environment variables
+ except Exception:
+ raise SalomeContextException("Failed to load env modules: %s ..." % ' '.join(env_modules))
pass
#
env_copy = os.environ.copy()
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)
+ proc = subprocess.Popen(['python3', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), selfBytes.decode('latin1'), argsBytes.decode('latin1')], shell=False, close_fds=True, env=env_copy)
out, err = proc.communicate()
return out, err, proc.returncode
#
"""Append value to LD_LIBRARY_PATH environment variable"""
def addToLdLibraryPath(self, value):
- if platform.system() == 'Windows':
+ if sys.platform == 'win32':
self.addToVariable('PATH', value)
- elif platform.system() == 'Darwin':
+ elif sys.platform == 'darwin':
if "LAPACK" in value:
self.addToVariable('DYLD_FALLBACK_LIBRARY_PATH', value)
else:
os.environ[name] = value
#
+ def setDefaultValue(self, name, value):
+ """ Set environment variable only if it is undefined."""
+ env = os.getenv(name, '')
+ if not env:
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Set environment variable: %s=%s", name, value)
+ os.environ[name] = value
+
"""Unset environment variable"""
def unsetVariable(self, name):
- if os.environ.has_key(name):
+ if name in os.environ:
del os.environ[name]
#
- """Append value to environment variable"""
+ """Prepend value to environment variable"""
def addToVariable(self, name, value, separator=os.pathsep):
if value == '':
return
os.environ[name] = value + separator + env
#
+ """Append a variable"""
+ def appendVariable(self, name, value, separator=os.pathsep):
+ if value == '':
+ return
+
+ value = os.path.expandvars(value) # expand environment variables
+ env = os.getenv(name, None)
+ if env is None:
+ os.environ[name] = value
+ else:
+ os.environ[name] = env + separator + value
+ return
+
+ """Remove value from environment variable"""
+ def removeFromVariable(self, name, value, separator=os.pathsep):
+ if value == '':
+ return
+
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Remove from %s: %s", name, value)
+ env = os.getenv(name, None)
+ if env == value:
+ env = ''
+ else:
+ env = env.removeprefix(value + separator)
+ env = env.removesuffix(separator + value)
+ env = env.replace(separator + value + separator, ':')
+
+ os.environ[name] = env
+ #
+
###################################
# This begins the private section #
###################################
options = args[1:]
availableCommands = {
- 'start' : '_runAppli',
+ 'start' : '_sessionless',
+ 'withsession' : '_runAppli',
'context' : '_setContext',
'shell' : '_runSession',
+ 'remote' : '_runRemote',
'connect' : '_runConsole',
'kill' : '_kill',
'killall' : '_killAll',
path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome", "appliskel"))
add_path(path, "PYTHONPATH")
- except:
+ except Exception:
pass
command, options = self.__parseArguments(args)
usage()
return 0
# try to default to "start" command
- command = "_runAppli"
+ command = "_sessionless"
try:
res = getattr(self, command)(options) # run appropriate method
#
def __setContextFromConfigFile(self, filename, reserved=None):
+ mesa_root_dir = "MESA_ROOT_DIR"
if reserved is None:
reserved = []
try:
- unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+ configInfo = parseConfigFile(filename, reserved)
+ unsetVars = configInfo.unsetVariables
+ configVars = configInfo.outputVariables
+ reservedDict = configInfo.reservedValues
+ defaultValues = configInfo.defaultValues
except SalomeContextException as e:
msg = "%s"%e
self.getLogger().error(msg)
for var in unsetVars:
self.unsetVariable(var)
+ # mesa stuff
+ if "MESA_GL_VERSION_OVERRIDE" in os.environ:
+ configVarsDict = {k:v for (k,v) in configVars}
+ if mesa_root_dir in configVarsDict:
+ path_to_mesa_lib = os.path.join(configVarsDict[mesa_root_dir],"lib")
+ if os.name == "posix":
+ self.addToVariable("LD_LIBRARY_PATH",path_to_mesa_lib)
+ else:
+ self.addToVariable("PATH",path_to_mesa_lib)
+
# set context
for reserved in reservedDict:
a = [_f for _f in reservedDict[reserved] if _f] # remove empty elements
self.addToVariable(reserved, reformattedVals)
pass
+
for key,val in configVars:
self.setVariable(key, val, overwrite=True)
pass
+ for key,val in defaultValues:
+ self.setDefaultValue(key, val)
+ pass
+
pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep)
pythonpath = [ os.path.realpath(x) for x in pythonpath ]
sys.path[:0] = pythonpath
if args is None:
args = []
# Initialize SALOME environment
+ sys.argv = ['runSalomeOld'] + args
+ import setenv
+ setenv.main(True, exeName="salome withsession")
+
+ import runSalomeOld
+ runSalomeOld.runSalome()
+ return 0
+ #
+
+ def _sessionless(self, args=None):
+ if args is None:
+ args = []
sys.argv = ['runSalome'] + args
import setenv
- setenv.main(True, exeName="salome start")
+ setenv.main(True, exeName="salome withsession")
import runSalome
runSalome.runSalome()
print("*** Enter 'exit' (only once!) to leave SALOME context.")
print("***")
- cmd = ["/bin/bash"]
+ if sys.platform == 'win32':
+ cmd = ['cmd.exe']
+ else:
+ cmd = ["/bin/bash"]
proc = subprocess.Popen(cmd, shell=False, close_fds=True)
proc.communicate()
return proc.returncode
return runSession.runSession(params, args)
#
+ def _runRemote(self, args=None):
+ if args is None:
+ args = []
+# complete salome environment
+ sys.argv = ['runRemote']
+ import setenv
+ setenv.main(True)
+
+ import runRemote
+ return runRemote.runRemote(args)
+ #
+
def _runConsole(self, args=None):
if args is None:
args = []
print("Port number(s) not provided to command: salome kill <port(s)>")
return 1
- from multiprocessing import Process
- from killSalomeWithPort import killMyPort
- import tempfile
+ import subprocess
+ sys.argv = ['kill']
+ import setenv
+ setenv.main(True)
+ if os.getenv("NSHOST") == "no_host":
+ os.unsetenv("NSHOST")
for port in ports:
- with tempfile.NamedTemporaryFile():
- p = Process(target = killMyPort, args=(port,))
- p.start()
- p.join()
+ if sys.platform == "win32":
+ proc = subprocess.Popen([os.getenv("PYTHONBIN"), "-m", "killSalomeWithPort", str(port)])
+ else:
+ proc = subprocess.Popen(["killSalomeWithPort.py", str(port)])
+ proc.communicate()
return 0
#
def _killAll(self, unused=None):
+ sys.argv = ['killAll']
+ import setenv
+ setenv.main(True)
+ if os.getenv("NSHOST") == "no_host":
+ os.unsetenv("NSHOST")
try:
import PortManager # mandatory
- from multiprocessing import Process
- from killSalomeWithPort import killMyPort
+ import subprocess
ports = PortManager.getBusyPorts()['this']
if ports:
- import tempfile
for port in ports:
- with tempfile.NamedTemporaryFile():
- p = Process(target = killMyPort, args=(port,))
- p.start()
- p.join()
+ if sys.platform == "win32":
+ proc = subprocess.Popen([os.getenv("PYTHONBIN"), "-m", "killSalomeWithPort", str(port)])
+ else:
+ proc = subprocess.Popen(["killSalomeWithPort.py", str(port)])
+ proc.communicate()
except ImportError:
# :TODO: should be declared obsolete
from killSalome import killAllPorts
killAllPorts()
pass
+ from addToKillList import killList
+ killList()
return 0
#
versions[software.upper()] = version
if len(software) > max_len:
max_len = len(software)
- except:
+ except Exception:
pass
pass
pass
if softwares:
for soft in softwares:
- if versions.has_key(soft.upper()):
+ if soft.upper() in versions:
print(soft.upper().rjust(max_len), versions[soft.upper()])
else:
import collections
od = collections.OrderedDict(sorted(versions.items()))
- for name, version in od.iteritems():
+ for name, version in od.items():
print(name.rjust(max_len), versions[name])
pass
if "-v" in args or "--version" in args:
print("Running with python", platform.python_version())
- return self._runAppli(["--version"])
+ return self._sessionless(["--version"])
return 0
#
if __name__ == "__main__":
if len(sys.argv) == 3:
- context = pickle.loads(sys.argv[1].encode())
- args = pickle.loads(sys.argv[2].encode())
+ context = pickle.loads(sys.argv[1].encode('latin1'))
+ args = pickle.loads(sys.argv[2].encode('latin1'))
status = context._startSalome(args)
sys.exit(status)