ADD_SUBDIRECTORY(appliskel)
SALOME_CONFIGURE_FILE(VERSION.in VERSION INSTALL ${SALOME_INSTALL_BINS})
-SALOME_CONFIGURE_FILE(salomeLauncherUtils.py.in salomeLauncherUtils.py)
+SALOME_CONFIGURE_FILE(salomeContextUtils.py.in salomeContextUtils.py)
# ===============================================================
# Files to be installed
runSession.py
runConsole.py
salomeConsole.py
- ${CMAKE_CURRENT_BINARY_DIR}/salomeLauncherUtils.py
- salomeRunner.py
+ ${CMAKE_CURRENT_BINARY_DIR}/salomeContextUtils.py
+ salomeContext.py
salome_session.py
salome_utils.py
searchFreePort.py
#------------------------------------
# A file locker (Linux only)
-import fcntl
-class PortManagerLock:
- def __init__(self, filename, readonly=False, blocking=True):
- # This will create it if it does not exist already
- logger.debug("Create lock on %s"%filename)
- self.__readonly = readonly
- self.__blocking = blocking
- self.__filename = filename
- flag = 'w'
- if self.__readonly:
- flag = 'r'
- self.handle = open(self.__filename, 'a+')
-
- def acquire(self):
- mode = fcntl.LOCK_EX
- if not self.__blocking: # Raise an IOError exception if file has already been locked
- mode = mode | fcntl.LOCK_NB
- fcntl.flock(self.handle, mode)
- logger.debug("lock acquired %s"%self.__blocking)
-
- def release(self):
- fcntl.flock(self.handle, fcntl.LOCK_UN)
- logger.debug("lock released")
-
- def __del__(self):
- logger.debug("Close lock file")
- self.handle.close()
- os.remove(self.__filename)
+def __acquire_lock(lock):
+ if sys.platform == "win32":
+ import msvcrt
+ # lock 1 byte: file is supposed to be zero-byte long
+ msvcrt.locking(lock.fileno(), msvcrt.LK_LOCK, 1)
+ else:
+ import fcntl
+ fcntl.flock(lock, fcntl.LOCK_EX)
+#
+def __release_lock(lock):
+ if sys.platform == "win32":
+ import msvcrt
+ msvcrt.locking(lock.fileno(), msvcrt.LK_UNLCK, 1)
+ else:
+ import fcntl
+ fcntl.flock(lock, fcntl.LOCK_UN)
#
def _getConfigurationFilename():
config_file, lock_file = _getConfigurationFilename()
with open(lock_file, 'w') as lock:
# acquire lock
- fcntl.flock(lock, fcntl.LOCK_EX)
+ __acquire_lock(lock)
# read config
config = {'busy_ports':[]}
pass
# release lock
- fcntl.flock(lock, fcntl.LOCK_UN)
+ __release_lock(lock)
logger.debug("get port: %s"%str(port))
return port
config_file, lock_file = _getConfigurationFilename()
with open(lock_file, 'w') as lock:
# acquire lock
- fcntl.flock(lock, fcntl.LOCK_EX)
+ __acquire_lock(lock)
# read config
config = {'busy_ports':[]}
pass
# release lock
- fcntl.flock(lock, fcntl.LOCK_UN)
+ __release_lock(lock)
logger.debug("released port port: %s"%str(port))
#
config_file, lock_file = _getConfigurationFilename()
with open(lock_file, 'w') as lock:
# acquire lock
- fcntl.flock(lock, fcntl.LOCK_EX)
+ __acquire_lock(lock)
# read config
config = {'busy_ports':[]}
busy_ports = config["busy_ports"]
# release lock
- fcntl.flock(lock, fcntl.LOCK_UN)
+ __release_lock(lock)
return busy_ports
#
import os
import sys
+def __detectAppliPath(fromPath):
+ detection_criterion = "USERS" # the application folder is found if it contains a USERS subfolder
+
+ users_folder = os.path.join(fromPath, detection_criterion)
+ if os.path.isdir(users_folder):
+ return fromPath
+
+ pattern = "/bin/salome/appliskel"
+ if fromPath.endswith(pattern):
+ currentPath = __detectAppliPath(fromPath[:-len(pattern)])
+ if not currentPath is None:
+ return currentPath
+
+ if sys.platform.startswith("linux"):
+ filename = os.path.basename(__file__)
+ link_target = os.readlink(os.path.join(fromPath,filename)) # LINUX ONLY
+ currentPath = os.path.dirname(os.path.abspath(link_target))
+ return __detectAppliPath(currentPath)
+
+ return None
+#
+
# Preliminary work to initialize path to SALOME Python modules
def __initialize():
currentPath = os.path.dirname( os.path.abspath( __file__ ) )
homePath = os.path.realpath(os.path.expanduser('~'))
- appliPath = os.path.relpath(currentPath, homePath)
- pattern = "/bin/salome/appliskel"
- if appliPath.endswith(pattern):
- appliPath = appliPath[:-len(pattern)]
+ appliPath = __detectAppliPath(currentPath)
+
+ if appliPath is None:
+ print "ERROR: Unable to find application folder"
+ sys.exit(0)
+ appliPath = os.path.relpath(appliPath, homePath)
absoluteAppliPath = os.path.join(homePath, appliPath)
os.environ['APPLI'] = appliPath # needed to convert .sh environment files
os.environ['ABSOLUTE_APPLI_PATH'] = absoluteAppliPath
# define folder to store omniorb config (initially in virtual application folder)
try:
- from salomeLauncherUtils import setOmniOrbUserPath
+ from salomeContextUtils import setOmniOrbUserPath
setOmniOrbUserPath()
except Exception, e:
print e
__initialize()
if args == ['--help']:
- from salomeRunner import usage
+ from salomeContext import usage
usage()
sys.exit(0)
- from salomeLauncherUtils import getConfigFileNames
+ from salomeContextUtils import getConfigFileNames
configFileNames, args, unexisting = getConfigFileNames(args, checkExistence=True)
if len(unexisting) > 0:
print "ERROR: unexisting configuration file(s): " + ', '.join(unexisting)
sys.exit(1)
- # Create a SalomeRunner which parses configFileNames to initialize environment
+ # Create a SalomeContext which parses configFileNames to initialize environment
try:
- from salomeRunner import SalomeRunner, SalomeRunnerException
- runner = SalomeRunner(configFileNames)
+ from salomeContext import SalomeContext, SalomeContextException
+ context = SalomeContext(configFileNames)
# Here set specific variables, if needed
- # runner.addToPath('mypath')
- # runner.addToLdLibraryPath('myldlibrarypath')
- # runner.addToPythonPath('mypythonpath')
- # runner.setEnviron('myvarname', 'value')
+ # context.addToPath('mypath')
+ # context.addToLdLibraryPath('myldlibrarypath')
+ # context.addToPythonPath('mypythonpath')
+ # context.setVariable('myvarname', 'value')
# Start SALOME, parsing command line arguments
- runner.go(args)
- print 'Thank you for using SALOME!'
+ context.runSalome(args)
+ #print 'Thank you for using SALOME!'
- except SalomeRunnerException, e:
+ except SalomeContextException, e:
import logging
logging.getLogger("salome").error(e)
sys.exit(1)
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-#ADD_SUBDIRECTORY(concurrentSession)
+ADD_SUBDIRECTORY(concurrentSession)
ADD_SUBDIRECTORY(launcher)
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-include(CTest)
-ENABLE_TESTING()
+FILE(GLOB py_scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.py")
+FILE(GLOB sh_scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.sh")
-# define environment for running tests
-SET(PYTHON_VERSION ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
+LIST(APPEND scripts ${py_scripts} ${sh_scripts})
-SET(THIS_PYTHONPATH ${CMAKE_SOURCE_DIR}/bin:$ENV{PYTHONPATH})
-#SET(THIS_LD_LIBRARY_PATH $ENV{LD_LIBRARY_PATH})
-
-# add tests (use make test to run)
-FILE(GLOB tests "${CMAKE_CURRENT_SOURCE_DIR}/Test*.py")
-FOREACH(file ${tests})
- GET_FILENAME_COMPONENT(testname ${file} NAME_WE)
- ADD_TEST(${testname} ${PYTHON_EXECUTABLE} "${file}")
-# SET_PROPERTY(TEST ${testname} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${THIS_PYTHONPATH} LD_LIBRARY_PATH=${THIS_LD_LIBRARY_PATH})
- SET_PROPERTY(TEST ${testname} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${THIS_PYTHONPATH})
-ENDFOREACH()
-
-# install Python scripts
-FILE(GLOB scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.py")
SALOME_INSTALL_SCRIPTS("${scripts}" ${SALOME_INSTALL_SCRIPT_SCRIPTS}/appliskel/tests/concurrentSession)
--- /dev/null
+# Copyright (C) 2013-2014 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# 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
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import unittest
+import tempfile
+
+import os
+import sys
+import imp
+from cStringIO import StringIO
+import multiprocessing
+
+
+class TestConcurrentLaunch(unittest.TestCase):
+ def setUp(self):
+ # Initialize path to SALOME application
+ path_to_launcher = os.getenv("SALOME_LAUNCHER")
+ appli_dir = os.path.dirname(path_to_launcher)
+
+ # Configure session startup
+ self.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome"))
+ self.SALOME_appli_args = ["start", "-t"]
+ self.SALOME_shell_args = ["shell"]
+ #
+ def tearDown(self):
+ pass
+ #
+ def appli(self, args=[]):
+ self.SALOME.main(self.SALOME_appli_args + args)
+ #
+ def session(self, args=[]):
+ self.SALOME.main(self.SALOME_shell_args + args)
+ #
+ def test01_SingleSession(self):
+ print "** Testing single session **"
+ self.session(["hello.py"])
+ #
+ def test02_MultiSession(self):
+ print "** Testing multi sessions **"
+ jobs = []
+ for i in range(9):
+ p = multiprocessing.Process(target=self.session, args=(["hello.py"],))
+ jobs.append(p)
+ p.start()
+
+ for j in jobs:
+ j.join()
+ #
+ def test03_SingleAppli(self):
+ print "** Testing single appli **"
+ current_directory = os.path.dirname(os.path.abspath(__file__))
+ session_log = tempfile.NamedTemporaryFile(prefix='session_', suffix='.log')
+ self.appli(["--ns-port-log=%s"%session_log.name])
+ port_number = None
+ with open(session_log.name, "r") as f:
+ port_number = f.readline()
+ self.session(["hello.py"])
+ self.session(["-p", port_number, "killSalomeWithPort.py", "args:%s"%port_number])
+ session_log.close()
+ #
+ def test04_MultiAppli(self):
+ print "** Testing multi appli **"
+ jobs = []
+ for i in range(9):
+ p = multiprocessing.Process(target=self.test03_SingleAppli)
+ jobs.append(p)
+ p.start()
+
+ for j in jobs:
+ j.join()
+ #
+#
+
+if __name__ == "__main__":
+ path_to_launcher = os.getenv("SALOME_LAUNCHER")
+ if not path_to_launcher:
+ msg = "Error: please set SALOME_LAUNCHER variable to the salome command in your application folder."
+ raise Exception(msg)
+
+ if not os.path.isfile("hello.py"):
+ with open("hello.py", "w") as f:
+ f.write("print 'Hello!'")
+
+ unittest.main()
+#
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-from PortManager import getPort, releasePort, stopServer
+import os
import sys
import multiprocessing
import unittest
-def port_reservation(prefered=None, test=None, expected=None):
+def port_reservation(obtained_ports, prefered=None, test=None, expected=None):
+ from PortManager import getPort
if prefered:
port = getPort(prefered)
else:
port = getPort()
- print "port = %s"%port
+ print "obtained port = %s"%port
+
+ obtained_ports.put(port)
if expected:
- print "expected = %s"%expected
- test.assertTrue(port == expected)
+ test.assertTrue(port == expected, "used = %s, expected = %s"%(port, expected))
#
class TestMinimalExample(unittest.TestCase):
- @classmethod
- def tearDownClass(cls):
- stopServer()
- stopServer() # no effect
- #
def testSequential(self):
- print "BEGIN testSequential"
+ from PortManager import releasePort, getBusyPorts
+ print "\nBEGIN testSequential"
+ print "Busy ports", getBusyPorts()
+ obtained_ports = multiprocessing.Queue()
+
processes = [
- multiprocessing.Process(target=port_reservation)
+ multiprocessing.Process(target=port_reservation, args=(obtained_ports,))
for i in range(3)
]
for p in processes:
p.join()
+ print "Busy ports", getBusyPorts()
# Try to get specific port number
- expected = 2872
- p = multiprocessing.Process(target=port_reservation, args=(2872, self,expected,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2872, self, 2872,))
p.start()
p.join()
# Try to get specific port number
- p = multiprocessing.Process(target=port_reservation, args=(2812, self,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self,))
+ p.start()
+ p.join()
+
+ # Try to get specific port number
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self,))
p.start()
p.join()
# Release port
+ print "release port 2812"
p = multiprocessing.Process(target=releasePort, args=(2812,))
p.start()
p.join()
# Try to get specific port number
- expected = 2812
- p = multiprocessing.Process(target=port_reservation, args=(2812, self,expected,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self, 2812,))
p.start()
p.join()
+ # Release ports
+ print "Busy ports", getBusyPorts()
+ while not obtained_ports.empty():
+ port = obtained_ports.get()
+ print "release port", port
+ p = multiprocessing.Process(target=releasePort, args=(port,))
+ p.start()
+ p.join()
+
print "END testSequential"
#
+
def testConcurrent(self):
- print "BEGIN testConcurrent"
+ from PortManager import releasePort, getBusyPorts
+ print "\nBEGIN testConcurrent"
+ print "Busy ports", getBusyPorts()
+ obtained_ports = multiprocessing.Queue()
processes = [
- multiprocessing.Process(target=port_reservation)
+ multiprocessing.Process(target=port_reservation, args=(obtained_ports,))
+
for i in range(3)
]
# Try to get specific port number
- p = multiprocessing.Process(target=port_reservation, args=(2852,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2872, self, 2872,))
processes.append(p)
# Try to get specific port number
- p = multiprocessing.Process(target=port_reservation, args=(2812,))
- processes.append(p)
-
- # Release port
- p = multiprocessing.Process(target=releasePort, args=(2812,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812,))
processes.append(p)
# Try to get specific port number
- p = multiprocessing.Process(target=port_reservation, args=(2812,))
+ p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812,))
processes.append(p)
for p in processes:
for p in processes:
p.join()
+ # Release ports
+ print "Busy ports", getBusyPorts()
+ while not obtained_ports.empty():
+ port = obtained_ports.get()
+ print "release port", port
+ p = multiprocessing.Process(target=releasePort, args=(port,))
+ p.start()
+ p.join()
+
print "END testConcurrent"
#
#
-unittest.main()
+if __name__ == "__main__":
+ omniorb_user_path = os.getenv("OMNIORB_USER_PATH")
+ if not omniorb_user_path:
+ msg = "Error: please set OMNIORB_USER_PATH variable."
+ raise Exception(msg)
+
+ try:
+ import PortManager
+ except ImportError:
+ msg = "Error: can't import PortManager; please check PYTHONPATH variable."
+ raise Exception(msg)
+
+ unittest.main()
+#
+++ /dev/null
-#!/usr/bin/env python
-# Copyright (C) 2013-2014 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
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# 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
-#
-# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
-
-import os
-import sys
-import unittest
-import multiprocessing
-import imp
-
-def unwrap_self_session(arg, **kwarg):
- return TestConcurrentLaunch.session(*arg, **kwarg)
-#
-
-class TestConcurrentLaunch(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- # Initialize path to SALOME application
- path_to_launcher = os.getenv("SALOME_LAUNCHER")
- appli_dir = os.path.dirname(path_to_launcher)
- cls.envd_dir = os.path.join(appli_dir, "env.d")
-
- # Configure session startup
- cls.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome"))
- #cls.SALOME_args = ["shell", "--config="+cls.envd_dir]
- cls.SALOME_args = ["--config="+cls.envd_dir]
- #
- @classmethod
- def tearDownClass(cls):
- args = ["killall", "--config="+cls.envd_dir]
- cls.SALOME.main(args)
- pass
- #
- def session(self, args=[]):
- self.SALOME.main(self.SALOME_args + args)
- #
- def test01_SingleSession(self):
- print "** Testing single session **"
- self.session()
- #
- def test02_MultiSession(self):
- print "** Testing multi sessions **"
-
- jobs = []
- for i in range(3):
- p = multiprocessing.Process(target=unwrap_self_session, args=([self],))
- jobs.append(p)
- p.start()
-
- for j in jobs:
- j.join()
- #
-#
-
-
-if __name__ == "__main__":
- path_to_launcher = os.getenv("SALOME_LAUNCHER")
- if not path_to_launcher:
- msg = "Error: please set SALOME_LAUNCHER variable to the salome command of your application folder."
- raise Exception(msg)
-
- unittest.main()
-#
--- /dev/null
+#!/bin/bash
+
+echo "This is a script that can be run concurrently."
+echo "It takes as single argument the number of concurrent executions:"
+echo "Usage: " $0 "<nb_execution>"
+echo
+echo "Here is what executed code contents looks like:"
+echo " - do some stuff"
+echo " - run SALOME in terminal mode, and log port number to a file"
+echo " - run some scripts (Python, binary), each in a dedicated SALOME session on a specific port"
+echo " - do some stuff"
+echo
+
+
+if [ $# != 2 ]; then
+ echo "Usage:" $0 "<nb_execution> <output_folder>"
+ exit 1
+fi
+
+NB_COMP=$1
+OUTPUT_FOLDER=$2
+BASE_DIR=`pwd`
+
+if [ "x${SALOME_APPLI_FOLDER}" == "x" ]; then
+ echo "SALOME_APPLI_FOLDER variable is not set (or empty)."
+ echo "Try to locate SALOME launcher in current directory."
+ SALOME_APPLI_FOLDER=`pwd`
+ if ! [ -f ${SALOME_APPLI_FOLDER}/salome ]; then
+ echo "Unable to locate salome command."
+ exit 1
+ fi
+fi
+
+run_command() {
+ WORK_DIR=`pwd` # a pushd has been done before calling this function
+ echo "Run command in folder:" ${WORK_DIR}
+ ${SALOME_APPLI_FOLDER}/salome start -t --ns-port-log=${WORK_DIR}/session.log
+ ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${SALOME_APPLI_FOLDER}/bin/salome/waitContainers.py
+ ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${BASE_DIR}/hello.py
+ ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${SALOME_APPLI_FOLDER}/bin/salome/killSalomeWithPort.py args:`cat ${WORK_DIR}/session.log`
+ echo "Execution terminated in folder:" ${WORK_DIR}
+}
+
+
+# make hello.py
+echo "
+#!/usr/bin/env python
+print 'Hello\!'
+" > ${BASE_DIR}/hello.py
+
+# Build output folders
+typeset -i i=${NB_COMP}
+while (( $i > 0 ))
+do
+ mkdir -p ${OUTPUT_FOLDER}/execution_$i
+ let "i=i-1"
+done
+
+# Start execution
+typeset -i i=${NB_COMP}
+while (( $i > 0 ))
+do
+ pushd ${OUTPUT_FOLDER}/execution_$i > /dev/null
+ run_command &
+ popd > /dev/null
+ let "i=i-1"
+done
logger.addHandler(logging.StreamHandler())
class TestSessionArgs(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
+ #
+ logFile = "log.txt"
+ # Set some predefined command args and corresponding output messages
+ hello0 = ["hello.py", "args:outfile="+logFile]
+ hello0Msg = "Hello!"
+ hello1 = ["hello.py", "args:you,outfile="+logFile]
+ hello1Msg = "Hello to: you"
+ helloToAdd = ["hello.py", "args:add.py,1,2,3,outfile="+logFile]
+ helloToAddMsg = "Hello to: add.py, 1, 2, 3"
+ add0 = ["add.py", "args:outfile="+logFile]
+ add0Msg = "No args!"
+ add3 = ["add.py", "args:1,2,3,outfile="+logFile]
+ add3Msg = "1+2+3 = 6"
+ lines0 = ["lines.py", "args:outfile="+logFile]
+ lines0Msg = "No files given"
+ lines2 = ["lines.py", "args:hello.py,add.py,outfile="+logFile]
+ lines2Msg = "hello.py is 35 lines longadd.py is 37 lines long"
+ linesUnreadable = ["lines.py", "args:hello.py,add.py,1,2,outfile="+logFile]
+ linesUnreadableMsg = "hello.py is 35 lines longadd.py is 37 lines longFile '1' cannot be readFile '2' cannot be read"
+ #
+ def setUp(self):
# Initialize path to SALOME application
path_to_launcher = os.getenv("SALOME_LAUNCHER")
appli_dir = os.path.dirname(path_to_launcher)
envd_dir = os.path.join(appli_dir, "env.d")
# Configure session startup
- cls.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome"))
- cls.SALOME_args = ["shell", "--config="+envd_dir]
+ self.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome"))
+ self.SALOME_args = ["shell", "--config="+envd_dir]
- cls.logFile = "log.txt"
sys.stdout = StringIO()
-
- # Set some predefined command args and corresponding output messages
- cls.hello0 = ["hello.py", "args:outfile="+cls.logFile]
- cls.hello0Msg = "Hello!"
- cls.hello1 = ["hello.py", "args:you,outfile="+cls.logFile]
- cls.hello1Msg = "Hello to: you"
- cls.helloToAdd = ["hello.py", "args:add.py,1,2,3,outfile="+cls.logFile]
- cls.helloToAddMsg = "Hello to: add.py, 1, 2, 3"
- cls.add0 = ["add.py", "args:outfile="+cls.logFile]
- cls.add0Msg = "No args!"
- cls.add3 = ["add.py", "args:1,2,3,outfile="+cls.logFile]
- cls.add3Msg = "1+2+3 = 6"
- cls.lines0 = ["lines.py", "args:outfile="+cls.logFile]
- cls.lines0Msg = "No files given"
- cls.lines2 = ["lines.py", "args:hello.py,add.py,outfile="+cls.logFile]
- cls.lines2Msg = "hello.py is 16 lines longadd.py is 18 lines long"
- cls.linesUnreadable = ["lines.py", "args:hello.py,add.py,1,2,outfile="+cls.logFile]
- cls.linesUnreadableMsg = "hello.py is 16 lines longadd.py is 18 lines longFile '1' cannot be readFile '2' cannot be read"
- #
- @classmethod
- def tearDownClass(cls):
- pass
- #
- def setUp(self):
self.removeLogFile()
#
def tearDown(self):
with open(self.logFile, "r") as f:
contents = f.read().replace('\n', '')
- #sys.stderr.write("Generated contents :%s\n"%contents)
- #sys.stderr.write("Expected contents :%s\n"%message)
- self.assertTrue(contents==message)
+ self.assertTrue(contents==message, "Contents differ!\n\tGenerated contents: %s\n\tExpected contents: %s"%(contents, message))
#
def testHello0(self):
self.session(self.hello0)
from salome_utils import verbose, setVerbose, getPortNumber, getHomeDir
-from salomeLauncherUtils import getScriptsAndArgs
+from salomeContextUtils import getScriptsAndArgs
# names of tags in XML configuration file
doc_tag = "document"
pass # end for key,val
pass # end for section
- return unsetVariables, outputVariables, reservedValues
+ # remove duplicate values
+ outVars = []
+ for (var, values) in outputVariables:
+ vals = values.split(',')
+ vals = list(set(vals))
+ outVars.append((var, ','.join(vals)))
+
+ return unsetVariables, outVars, reservedValues
#
def _trimColons(var):
if not args['gui'] or not args['session_gui']:
toimport = args['pyscript']
- from salomeLauncherUtils import formatScriptsAndArgs
+ from salomeContextUtils import formatScriptsAndArgs
command = formatScriptsAndArgs(toimport)
if command:
proc = subprocess.Popen(command, shell=True)
searchFreePort(args, 0)
clt = useSalome(args, modules_list, modules_root_dir)
- if args.has_key('shutdown_servers') :
+ if args.has_key('shutdown_servers') :
var = args['shutdown_servers']
- if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
+ if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
var.delete()
return clt
# define folder to store omniorb config (initially in virtual application folder)
try:
- from salomeLauncherUtils import setOmniOrbUserPath
+ from salomeContextUtils import setOmniOrbUserPath
setOmniOrbUserPath()
except Exception, e:
print e
foreGround(clt, args)
pass
# --
- if args.has_key('shutdown_servers') :
+ if args.has_key('shutdown_servers') :
var = args['shutdown_servers']
- if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
+ if hasattr(var, 'delete') and callable(getattr(var, 'delete')) :
var.delete()
pass
#
--- /dev/null
+# Copyright (C) 2013-2014 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# 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
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import os
+import sys
+import logging
+import ConfigParser
+
+from parseConfigFile import parseConfigFile
+from parseConfigFile import convertEnvFileToConfigFile
+
+import tempfile
+import pickle
+import subprocess
+import platform
+
+from salomeContextUtils import SalomeContextException
+from salomeContextUtils import getScriptsAndArgs, formatScriptsAndArgs
+
+def usage():
+ #exeName = os.path.splitext(os.path.basename(__file__))[0]
+
+ msg = '''\
+Usage: salome [command] [options] [--config=file1,...,filen]
+
+Commands:
+ start Launches SALOME virtual application [DEFAULT]
+ shell Executes a script under SALOME application environment
+ connect Connects a Python console to the active SALOME session
+ killall Kill all SALOME running sessions
+ info Display some information about SALOME
+ help Show this message
+ coffee Yes! SALOME can also make coffee!!"
+
+Use salome start --help or salome shell --help
+to show help on start and shell commands.
+'''
+
+ print msg
+#
+
+"""
+The SalomeContext class in an API to configure SALOME environment then
+start SALOME using a single python command.
+
+"""
+class SalomeContext:
+ """
+ Initialize environment 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 environment.
+ """
+ def __init__(self, configFileNames=[]):
+ #it could be None explicitely (if user use multiples setVariable...for standalone)
+ if configFileNames==None:
+ return
+
+ if len(configFileNames) == 0:
+ raise SalomeContextException("No configuration files given")
+
+ reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
+ for filename in configFileNames:
+ basename, extension = os.path.splitext(filename)
+ if extension == ".cfg":
+ self.__setEnvironmentFromConfigFile(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.__setEnvironmentFromConfigFile(temp.name, reserved)
+ except ConfigParser.ParsingError, e:
+ self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
+ print e
+ print '\n'
+ finally:
+ # Automatically cleans up the file
+ temp.close()
+ else:
+ self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
+ #
+
+ def runSalome(self, args):
+ # Run this module as a script, in order to use appropriate Python interpreter
+ # according to current path (initialized from environment files).
+ kill = False
+ for e in args:
+ if "--shutdown-server" in e:
+ kill = True
+ args.remove(e)
+
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
+ msg = proc.communicate()
+ if kill:
+ self._killAll(args)
+ return msg
+ #
+
+ """Append value to PATH environment variable"""
+ def addToPath(self, value):
+ self.addToVariable('PATH', value)
+ #
+
+ """Append value to LD_LIBRARY_PATH environment variable"""
+ def addToLdLibraryPath(self, value):
+ self.addToVariable('LD_LIBRARY_PATH', value)
+ #
+
+ """Append value to PYTHONPATH environment variable"""
+ def addToPythonPath(self, value):
+ self.addToVariable('PYTHONPATH', value)
+ #
+
+ """Set environment variable to value"""
+ 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)
+ return
+
+ if env:
+ self.getLogger().warning("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)
+ os.environ[name] = value
+ #
+
+ """Unset environment variable"""
+ def unsetVariable(self, name):
+ if os.environ.has_key(name):
+ del os.environ[name]
+ #
+
+ """Append value to environment variable"""
+ def addToVariable(self, name, value, separator=os.pathsep):
+ if value == '':
+ return
+
+ value = os.path.expandvars(value) # expand environment variables
+ self.getLogger().debug("Add to %s: %s", name, value)
+ env = os.getenv(name, None)
+ if env is None:
+ os.environ[name] = value
+ else:
+ os.environ[name] = value + separator + env
+ #
+
+ ###################################
+ # This begins the private section #
+ ###################################
+
+ def __parseArguments(self, args):
+ if len(args) == 0 or args[0].startswith("-"):
+ return None, args
+
+ command = args[0]
+ options = args[1:]
+
+ availableCommands = {
+ 'start' : '_runAppli',
+ 'shell' : '_runSession',
+ 'connect' : '_runConsole',
+ 'killall': '_killAll',
+ 'info': '_showInfo',
+ 'help': '_usage',
+ 'coffee' : '_makeCoffee'
+ }
+
+ if not command in availableCommands.keys():
+ command = "start"
+ options = args
+
+ return availableCommands[command], options
+ #
+
+ """
+ Run SALOME!
+ Args consist in a mandatory command followed by optionnal parameters.
+ See usage for details on commands.
+ """
+ def _startSalome(self, args):
+ command, options = self.__parseArguments(args)
+ sys.argv = options
+
+ if command is None:
+ if args and args[0] in ["-h","--help","help"]:
+ usage()
+ sys.exit(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, exc:
+ if exc==0:
+ sys.exit(0) #catch sys.exit(0) happy end no warning
+ if exc==1:
+ self.getLogger().warning("SystemExit 1 in method %s.", command)
+ sys.exit(1)
+ except StandardError:
+ self.getLogger().error("Unexpected error:")
+ import traceback
+ traceback.print_exc()
+ sys.exit(1)
+ except SalomeContextException, e:
+ self.getLogger().error(e)
+ sys.exit(1)
+ #
+
+ def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
+ unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+
+ # unset variables
+ for var in unsetVars:
+ self.unsetVariable(var)
+
+ # set environment
+ for reserved in reservedDict:
+ a = filter(None, reservedDict[reserved]) # remove empty elements
+ reformattedVals = ':'.join(a)
+ self.addToVariable(reserved, reformattedVals)
+ pass
+
+ for key,val in configVars:
+ self.setVariable(key, val, overwrite=True)
+ pass
+
+ sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
+ #
+
+ def _runAppli(self, args=[]):
+ # Initialize SALOME environment
+ sys.argv = ['runSalome'] + args
+ import setenv
+ setenv.main(True)
+
+ import runSalome
+ runSalome.runSalome()
+ #
+
+ def _runSession(self, args=[]):
+ sys.argv = ['runSession'] + args
+ import runSession
+ runSession.configureSession(args)
+
+ import setenv
+ setenv.main(True)
+
+ scriptArgs = getScriptsAndArgs(args)
+ command = formatScriptsAndArgs(scriptArgs)
+ if command:
+ sep = ";"
+ if sys.platform == "win32":
+ sep= "&"
+ command = command.split(sep)
+ outmsg = []
+ errmsg = []
+ for cmd in command:
+ cmd = cmd.strip().split(' ')
+ #proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen(cmd)
+ (stdoutdata, stderrdata) = proc.communicate()
+ if stdoutdata or stderrdata:
+ outmsg.append(stdoutdata)
+ errmsg.append(stderrdata)
+
+ return ("".join(outmsg), "".join(errmsg))
+ else:
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
+ proc = subprocess.Popen(cmd, shell=False, close_fds=True)
+ return proc.communicate()
+ #
+
+ def _runConsole(self, args=[]):
+ # Initialize SALOME environment
+ sys.argv = ['runConsole'] + args
+ import setenv
+ setenv.main(True)
+
+ cmd = ["python", "-c", "import runConsole\nrunConsole.connect()" ]
+ proc = subprocess.Popen(cmd, shell=False, close_fds=True)
+ return proc.communicate()
+ #
+
+ def _killAll(self, args=[]):
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ try:
+ import PortManager # mandatory
+ from multiprocessing import Process
+ from killSalomeWithPort import killMyPort
+ ports = PortManager.getBusyPorts()
+
+ if ports:
+ import tempfile
+ for port in ports:
+ with tempfile.NamedTemporaryFile():
+ p = Process(target = killMyPort, args=(port,))
+ p.start()
+ p.join()
+
+ p = Process(target = killMyPort, args=(2809,))
+ p.start()
+ p.join()
+ except ImportError:
+ from killSalome import killAllPorts
+ killAllPorts()
+ pass
+
+ #
+
+ def _showInfo(self, args=[]):
+ print "Running with python", platform.python_version()
+ self._runAppli(["--version"])
+ #
+
+ def _usage(self, unused=[]):
+ usage()
+ #
+
+ def _makeCoffee(self, args=[]):
+ print " ("
+ print " ) ("
+ print " ___...(-------)-....___"
+ print " .-\"\" ) ( \"\"-."
+ print " .-\'``\'|-._ ) _.-|"
+ print " / .--.| `\"\"---...........---\"\"` |"
+ print " / / | |"
+ print " | | | |"
+ print " \\ \\ | |"
+ print " `\\ `\\ | |"
+ print " `\\ `| |"
+ print " _/ /\\ /"
+ print " (__/ \\ /"
+ print " _..---\"\"` \\ /`\"\"---.._"
+ print " .-\' \\ / \'-."
+ print " : `-.__ __.-\' :"
+ print " : ) \"\"---...---\"\" ( :"
+ print " \'._ `\"--...___...--\"` _.\'"
+ print " \\\"\"--..__ __..--\"\"/"
+ print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
+ print " `\"\"--..,,_____ _____,,..--\"\"`"
+ print " `\"\"\"----\"\"\"`"
+ sys.exit(0)
+ #
+
+ # Add the following two methods since logger is not pickable
+ # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
+ def __getstate__(self):
+ d = dict(self.__dict__)
+ if hasattr(self, '_logger'):
+ del d['_logger']
+ return d
+ #
+ def __setstate__(self, d):
+ self.__dict__.update(d) # I *think* this is a safe way to do it
+ #
+ # Excluding self._logger from pickle operation imply using the following method to access logger
+ def getLogger(self):
+ if not hasattr(self, '_logger'):
+ self._logger = logging.getLogger(__name__)
+ #self._logger.setLevel(logging.DEBUG)
+ self._logger.setLevel(logging.ERROR)
+ return self._logger
+ #
+
+###
+import pickle
+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)
+ else:
+ usage()
+#
--- /dev/null
+#! /usr/bin/env python
+
+# Copyright (C) 2013-2014 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# 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
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import os
+import sys
+import glob
+import subprocess
+import re
+
+"""
+Define a specific exception class to manage exceptions related to SalomeContext
+"""
+class SalomeContextException(Exception):
+ """Report error messages to the user interface of SalomeContext."""
+#
+
+def __listDirectory(path):
+ allFiles = []
+ for root, dirs, files in os.walk(path):
+ cfgFiles = glob.glob(os.path.join(root,'*.cfg'))
+ allFiles += cfgFiles
+
+ shFiles = glob.glob(os.path.join(root,'*.sh'))
+ for f in shFiles:
+ no_ext = os.path.splitext(f)[0]
+ if not os.path.isfile(no_ext+".cfg"):
+ allFiles.append(f)
+
+ return allFiles
+#
+
+def __getConfigFileNamesDefault():
+ absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+ if not absoluteAppliPath:
+ return []
+
+ envdDir = absoluteAppliPath + '/env.d'
+ if not os.path.isdir(envdDir):
+ return []
+
+ return __listDirectory(envdDir)
+#
+
+def getConfigFileNames(args, checkExistence=False):
+ # special case: configuration files are provided by user
+ # Search for command-line argument(s) --config=file1,file2,..., filen
+ # Search for command-line argument(s) --config=dir1,dir2,..., dirn
+ configOptionPrefix = "--config="
+ configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ]
+
+ if len(configArgs) == 0:
+ return __getConfigFileNamesDefault(), args, []
+
+ args = [ x for x in args if not x.startswith(configOptionPrefix) ]
+ allLists = [ x.replace(configOptionPrefix, '') for x in configArgs ]
+
+ configFileNames = []
+ unexisting = []
+ for currentList in allLists:
+ elements = currentList.split(',')
+ for elt in elements:
+ elt = os.path.realpath(os.path.expanduser(elt))
+ if os.path.isdir(elt):
+ configFileNames += __listDirectory(elt)
+ else:
+ if checkExistence and not os.path.isfile(elt):
+ unexisting += [elt]
+ else:
+ configFileNames += [elt]
+
+ return configFileNames, args, unexisting
+#
+
+def __getScriptPath(scriptName, searchPathList):
+ if searchPathList is None or len(searchPathList) == 0:
+ return None
+
+ for path in searchPathList:
+ fullName = os.path.join(path, scriptName)
+ if os.path.isfile(fullName) or os.path.isfile(fullName+".py"):
+ return fullName
+
+ return None
+#
+
+# Return an array of dictionaries {script_name: [list_of_its_args]}
+def getScriptsAndArgs(args=[], searchPathList=None):
+ if searchPathList is None:
+ searchPathList = sys.path
+
+ # Syntax of args: script.py [args:a1,a2=val,an] ... script.py [args:a1,a2=val,an]
+ scriptArgs = []
+ currentKey = None
+ argsPrefix = "args:"
+ callPython = False
+ currentScript = None
+
+ for i in range(len(args)):
+ elt = args[i]
+
+ if elt.startswith(argsPrefix):
+ if not currentKey or callPython:
+ raise SalomeContextException("args list must follow corresponding script file in command line.")
+ elt = elt.replace(argsPrefix, '')
+ scriptArgs[len(scriptArgs)-1][currentKey] = elt.split(",")
+ currentKey = None
+ callPython = False
+ elif elt.startswith("python"):
+ callPython = True
+ else:
+ if not os.path.isfile(elt) and not os.path.isfile(elt+".py"):
+ eltInSearchPath = __getScriptPath(elt, searchPathList)
+ if eltInSearchPath is None or (not os.path.isfile(eltInSearchPath) and not os.path.isfile(eltInSearchPath+".py")):
+ if elt[-3:] == ".py":
+ raise SalomeContextException("Script not found: %s"%elt)
+ continue
+ elt = eltInSearchPath
+
+ if elt[-4:] != ".hdf":
+ if elt[-3:] == ".py":
+ currentScript = os.path.abspath(elt)
+ elif os.path.isfile(elt+".py"):
+ currentScript = os.path.abspath(elt+".py")
+ else:
+ currentScript = os.path.abspath(elt) # python script not necessary has .py extension
+ pass
+ if currentScript and callPython:
+ currentKey = "@PYTHONBIN@ "+currentScript
+ scriptArgs.append({currentKey:[]})
+ callPython = False
+ elif currentScript:
+ if not os.access(currentScript, os.X_OK):
+ currentKey = "@PYTHONBIN@ "+currentScript
+ scriptArgs.append({currentKey:[]})
+ else:
+ ispython = False
+ try:
+ fn = open(currentScript)
+ for i in xrange(10): # read only 10 first lines
+ ln = fn.readline()
+ if re.search("#!.*python"):
+ ispython = True
+ break
+ pass
+ fn.close()
+ except:
+ pass
+ if not ispython and currentScript[-3:] == ".py":
+ currentKey = "@PYTHONBIN@ "+currentScript
+ else:
+ currentKey = currentScript
+ pass
+ scriptArgs.append({currentKey:[]})
+ # end for loop
+ return scriptArgs
+#
+
+# Formatting scripts and args as a Bash-like command-line:
+# script1.py [args] ; script2.py [args] ; ...
+def formatScriptsAndArgs(scriptArgs=[]):
+ commands = []
+ for sc_dict in scriptArgs:
+ for script, sc_args in sc_dict.items(): # single entry
+ cmd = script
+ if sc_args:
+ cmd = cmd + " " + " ".join(sc_args)
+ commands.append(cmd)
+ sep = " ; "
+ if sys.platform == "win32":
+ sep= " & "
+ command = sep.join(["%s"%x for x in commands])
+ return command
+#
+
+# Ensure OMNIORB_USER_PATH is defined. This variable refers to a the folder in which
+# SALOME will write omniOrb configuration files.
+# If OMNIORB_USER_PATH is already set, only checks write access to associated directory ;
+# an exception is raised if check fails. It allows users for choosing a specific folder.
+# Else the function sets OMNIORB_USER_PATH this way:
+# - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS.
+# The function does not check USERS folder existence or write access. This folder
+# must exist ; this is the case if SALOME virtual application has been created using
+# appli_gen.py script.
+# - Else OMNIORB_USER_PATH is set to user home directory.
+def setOmniOrbUserPath():
+ omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
+ if omniorbUserPath:
+ if not os.access(omniorbUserPath, os.W_OK):
+ raise Exception("Unable to get write access to directory: %s"%omniorbUserPath)
+ pass
+ else:
+ homePath = os.path.realpath(os.path.expanduser('~'))
+ #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS")
+ defaultOmniorbUserPath = homePath
+ if os.getenv("APPLI"):
+ defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS")
+ pass
+ os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath
+#
+++ /dev/null
-#! /usr/bin/env python
-
-# Copyright (C) 2013-2014 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
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# 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
-#
-# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
-
-import os
-import sys
-import glob
-import subprocess
-import re
-
-"""
-Define a specific exception class to manage exceptions related to SalomeRunner
-"""
-class SalomeRunnerException(Exception):
- """Report error messages to the user interface of SalomeRunner."""
-#
-
-def __listDirectory(path):
- allFiles = []
- for root, dirs, files in os.walk(path):
- configFileNames = glob.glob(os.path.join(root,'*.cfg')) + glob.glob(os.path.join(root,'*.sh'))
- allFiles += configFileNames
- return allFiles
-#
-
-def __getConfigFileNamesDefault():
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- if not absoluteAppliPath:
- return []
-
- envdDir = absoluteAppliPath + '/env.d'
- if not os.path.isdir(envdDir):
- return []
-
- return __listDirectory(envdDir)
-#
-
-def getConfigFileNames(args, checkExistence=False):
- # special case: configuration files are provided by user
- # Search for command-line argument(s) --config=file1,file2,..., filen
- # Search for command-line argument(s) --config=dir1,dir2,..., dirn
- configOptionPrefix = "--config="
- configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ]
-
- if len(configArgs) == 0:
- return __getConfigFileNamesDefault(), args, []
-
- args = [ x for x in args if not x.startswith(configOptionPrefix) ]
- allLists = [ x.replace(configOptionPrefix, '') for x in configArgs ]
-
- configFileNames = []
- unexisting = []
- for currentList in allLists:
- elements = currentList.split(',')
- for elt in elements:
- elt = os.path.realpath(os.path.expanduser(elt))
- if os.path.isdir(elt):
- configFileNames += __listDirectory(elt)
- else:
- if checkExistence and not os.path.isfile(elt):
- unexisting += [elt]
- else:
- configFileNames += [elt]
-
- return configFileNames, args, unexisting
-#
-
-# Return an array of dictionaries {script_name: [list_of_its_args]}
-def getScriptsAndArgs(args=[]):
- # Syntax of args: script.py [args:a1,a2=val,an] ... script.py [args:a1,a2=val,an]
- scriptArgs = []
- currentKey = None
- argsPrefix = "args:"
- callPython = False
- currentScript = None
-
- for i in range(len(args)):
- elt = args[i]
-
- if elt.startswith(argsPrefix):
- if not currentKey or callPython:
- raise SalomeRunnerException("args list must follow corresponding script file in command line.")
- elt = elt.replace(argsPrefix, '')
- scriptArgs[len(scriptArgs)-1][currentKey] = elt.split(",")
- currentKey = None
- callPython = False
- elif elt.startswith("python"):
- callPython = True
- elif os.path.isfile(elt) or os.path.isfile(elt+".py"):
- if elt[-4:] != ".hdf":
- if elt[-3:] == ".py":
- currentScript = os.path.abspath(elt)
- elif os.path.isfile(elt+".py"):
- currentScript = os.path.abspath(elt+".py")
- else:
- currentScript = os.path.abspath(elt) # python script not necessary has .py extension
- pass
- if currentScript and callPython:
- currentKey = "@PYTHONBIN@ "+currentScript
- scriptArgs.append({currentKey:[]})
- callPython = False
- elif currentScript:
- if not os.access(currentScript, os.X_OK):
- currentKey = "@PYTHONBIN@ "+currentScript
- scriptArgs.append({currentKey:[]})
- else:
- ispython = False
- try:
- fn = open(currentScript)
- for i in xrange(10): # read only 10 first lines
- ln = fn.readline()
- if re.search("#!.*python"):
- ispython = True
- break
- pass
- fn.close()
- except:
- pass
- if not ispython and currentScript[-3:] == ".py":
- currentKey = "@PYTHONBIN@ "+currentScript
- else:
- currentKey = currentScript
- pass
- scriptArgs.append({currentKey:[]})
- # end for loop
- return scriptArgs
-#
-
-# Formatting scripts and args as a Bash-like command-line:
-# script1.py [args] ; script2.py [args] ; ...
-def formatScriptsAndArgs(scriptArgs=[]):
- commands = []
- for sc_dict in scriptArgs:
- for script, sc_args in sc_dict.items(): # single entry
- cmd = script
- if sc_args:
- cmd = cmd + " " + " ".join(sc_args)
- commands.append(cmd)
- sep = " ; "
- if sys.platform == "win32":
- sep= " & "
- command = sep.join(["%s"%x for x in commands])
- return command
-#
-
-# Ensure OMNIORB_USER_PATH is defined. This variable refers to a the folder in which
-# SALOME will write omniOrb configuration files.
-# If OMNIORB_USER_PATH is already set, only checks write access to associated directory ;
-# an exception is raised if check fails. It allows users for choosing a specific folder.
-# Else the function sets OMNIORB_USER_PATH this way:
-# - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS.
-# The function does not check USERS folder existence or wrute access. This folder
-# must exist ; this is the case if SALOME virtual application has been create using
-# appli_gen.py script.
-# - Else OMNIORB_USER_PATH is set to user home directory.
-def setOmniOrbUserPath():
- omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
- if omniorbUserPath:
- if not os.access(omniorbUserPath, os.W_OK):
- raise Exception("Unable to get write access to directory: %s"%omniorbUserPath)
- pass
- else:
- homePath = os.path.realpath(os.path.expanduser('~'))
- #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS")
- defaultOmniorbUserPath = homePath
- if os.getenv("APPLI"):
- defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS")
- pass
- os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath
-#
+++ /dev/null
-# Copyright (C) 2013-2014 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
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# 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
-#
-# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-#
-
-import os
-import sys
-import logging
-import ConfigParser
-
-from parseConfigFile import parseConfigFile
-from parseConfigFile import convertEnvFileToConfigFile
-
-import tempfile
-import pickle
-import subprocess
-import platform
-
-from salomeLauncherUtils import SalomeRunnerException
-from salomeLauncherUtils import getScriptsAndArgs, formatScriptsAndArgs
-
-def usage():
- #exeName = os.path.splitext(os.path.basename(__file__))[0]
-
- msg = '''\
-Usage: salome [command] [options] [--config=file1,...,filen]
-
-Commands:
- start Launches SALOME virtual application [DEFAULT]
- shell Executes a script under SALOME application environment
- connect Connects a Python console to the active SALOME session
- killall Kill all SALOME running sessions
- info Display some information about SALOME
- help Show this message
- coffee Yes! SALOME can also make coffee!!"
-
-Use salome start --help or salome shell --help
-to show help on start and shell commands.
-'''
-
- print msg
-#
-
-"""
-The SalomeRunner class in an API to configure SALOME environment then
-start SALOME using a single python command.
-
-"""
-class SalomeRunner:
- """
- Initialize environment 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 SalomeRunner class will try to automatically convert them
- to .cfg format before setting the environment.
- """
- def __init__(self, configFileNames=[]):
- #it could be None explicitely (if user use multiples setEnviron...for standalone)
- if configFileNames==None:
- return
-
- if len(configFileNames) == 0:
- raise SalomeRunnerException("No configuration files given")
-
- reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
- for filename in configFileNames:
- basename, extension = os.path.splitext(filename)
- if extension == ".cfg":
- self.__setEnvironmentFromConfigFile(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.__setEnvironmentFromConfigFile(temp.name, reserved)
- except ConfigParser.ParsingError, e:
- self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
- print e
- print '\n'
- finally:
- # Automatically cleans up the file
- temp.close()
- else:
- self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
- #
-
- def go(self, args):
- # Run this module as a script, in order to use appropriate Python interpreter
- # according to current path (initialized from environment files).
- kill = False
- for e in args:
- if "--shutdown-server" in e:
- kill = True
- args.remove(e)
-
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeRunner.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True)
- proc.communicate()
- if kill:
- self._killAll(args)
- #
-
- """Append value to PATH environment variable"""
- def addToPath(self, value):
- self.addToEnviron('PATH', value)
- #
-
- """Append value to LD_LIBRARY_PATH environment variable"""
- def addToLdLibraryPath(self, value):
- self.addToEnviron('LD_LIBRARY_PATH', value)
- #
-
- """Append value to PYTHONPATH environment variable"""
- def addToPythonPath(self, value):
- self.addToEnviron('PYTHONPATH', value)
- #
-
- """Set environment variable to value"""
- def setEnviron(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)
- return
-
- if env:
- self.getLogger().warning("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)
- os.environ[name] = value
- #
-
- """Unset environment variable"""
- def unsetEnviron(self, name):
- if os.environ.has_key(name):
- del os.environ[name]
- #
-
- """Append value to environment variable"""
- def addToEnviron(self, name, value, separator=os.pathsep):
- if value == '':
- return
-
- value = os.path.expandvars(value) # expand environment variables
- self.getLogger().debug("Add to %s: %s", name, value)
- env = os.getenv(name, None)
- if env is None:
- os.environ[name] = value
- else:
- os.environ[name] = value + separator + env
- #
-
- ###################################
- # This begins the private section #
- ###################################
-
- def __parseArguments(self, args):
- if len(args) == 0 or args[0].startswith("-"):
- return None, args
-
- command = args[0]
- options = args[1:]
-
- availableCommands = {
- 'start' : '_runAppli',
- 'shell' : '_runSession',
- 'connect' : '_runConsole',
- 'killall': '_killAll',
- 'info': '_showInfo',
- 'help': '_usage',
- 'coffee' : '_makeCoffee'
- }
-
- if not command in availableCommands.keys():
- command = "start"
- options = args
-
- return availableCommands[command], options
- #
-
- """
- Run SALOME!
- Args consist in a mandatory command followed by optionnal parameters.
- See usage for details on commands.
- """
- def _getStarted(self, args):
- command, options = self.__parseArguments(args)
- sys.argv = options
-
- if command is None:
- if args and args[0] in ["-h","--help","help"]:
- usage()
- sys.exit(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, exc:
- if exc==0:
- sys.exit(0) #catch sys.exit(0) happy end no warning
- if exc==1:
- self.getLogger().warning("SystemExit 1 in method %s.", command)
- sys.exit(1)
- except StandardError:
- self.getLogger().error("Unexpected error:")
- import traceback
- traceback.print_exc()
- sys.exit(1)
- except SalomeRunnerException, e:
- self.getLogger().error(e)
- sys.exit(1)
- #
-
- def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
- unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
-
- # unset variables
- for var in unsetVars:
- self.unsetEnviron(var)
-
- # set environment
- for reserved in reservedDict:
- a = filter(None, reservedDict[reserved]) # remove empty elements
- reformattedVals = ':'.join(a)
- self.addToEnviron(reserved, reformattedVals)
- pass
-
- for key,val in configVars:
- self.setEnviron(key, val, overwrite=True)
- pass
-
- sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
- #
-
- def _runAppli(self, args=[]):
- # Initialize SALOME environment
- sys.argv = ['runSalome'] + args
- import setenv
- setenv.main(True)
-
- import runSalome
- runSalome.runSalome()
- #
-
- def _runSession(self, args=[]):
- sys.argv = ['runSession'] + args
- import runSession
- runSession.configureSession(args)
-
- import setenv
- setenv.main(True)
-
- scriptArgs = getScriptsAndArgs(args)
- command = formatScriptsAndArgs(scriptArgs)
- if command:
- sep = ";"
- if sys.platform == "win32":
- sep= "&"
- command = command.split(sep)
- outmsg = []
- errmsg = []
- for cmd in command:
- cmd = cmd.strip().split(' ')
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdoutdata, stderrdata) = proc.communicate()
- if stdoutdata or stderrdata:
- outmsg.append(stdoutdata)
- errmsg.append(stderrdata)
-
- return ("".join(outmsg), "".join(errmsg))
- else:
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- cmd = ["/bin/bash", "--rcfile", absoluteAppliPath + "/.bashrc" ]
- proc = subprocess.Popen(cmd, shell=False, close_fds=True)
- proc.wait()
- #
-
- def _runConsole(self, args=[]):
- # Initialize SALOME environment
- sys.argv = ['runConsole'] + args
- import setenv
- setenv.main(True)
-
- import runConsole
- runConsole.connect()
- #
-
- def _killAll(self, args=[]):
- absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
- try:
- import PortManager # mandatory
- from multiprocessing import Process
- from killSalomeWithPort import killMyPort
- ports = PortManager.getBusyPorts()
-
- if ports:
- import tempfile
- for port in ports:
- with tempfile.NamedTemporaryFile():
- p = Process(target = killMyPort, args=(port,))
- p.start()
- p.join()
-
- p = Process(target = killMyPort, args=(2809,))
- p.start()
- p.join()
- except ImportError:
- from killSalome import killAllPorts
- killAllPorts()
- pass
-
- #
-
- def _showInfo(self, args=[]):
- print "Running with python", platform.python_version()
- self._runAppli(["--version"])
- #
-
- def _usage(self, unused=[]):
- usage()
- #
-
- def _makeCoffee(self, args=[]):
- print " ("
- print " ) ("
- print " ___...(-------)-....___"
- print " .-\"\" ) ( \"\"-."
- print " .-\'``\'|-._ ) _.-|"
- print " / .--.| `\"\"---...........---\"\"` |"
- print " / / | |"
- print " | | | |"
- print " \\ \\ | |"
- print " `\\ `\\ | |"
- print " `\\ `| |"
- print " _/ /\\ /"
- print " (__/ \\ /"
- print " _..---\"\"` \\ /`\"\"---.._"
- print " .-\' \\ / \'-."
- print " : `-.__ __.-\' :"
- print " : ) \"\"---...---\"\" ( :"
- print " \'._ `\"--...___...--\"` _.\'"
- print " \\\"\"--..__ __..--\"\"/"
- print " \'._ \"\"\"----.....______.....----\"\"\" _.\'"
- print " `\"\"--..,,_____ _____,,..--\"\"`"
- print " `\"\"\"----\"\"\"`"
- sys.exit(0)
- #
-
- # Add the following two methods since logger is not pickable
- # Ref: http://stackoverflow.com/questions/2999638/how-to-stop-attributes-from-being-pickled-in-python
- def __getstate__(self):
- d = dict(self.__dict__)
- if hasattr(self, '_logger'):
- del d['_logger']
- return d
- #
- def __setstate__(self, d):
- self.__dict__.update(d) # I *think* this is a safe way to do it
- #
- # Excluding self._logger from pickle operation imply using the following method to access logger
- def getLogger(self):
- if not hasattr(self, '_logger'):
- self._logger = logging.getLogger(__name__)
- #self._logger.setLevel(logging.DEBUG)
- self._logger.setLevel(logging.ERROR)
- return self._logger
- #
-
-###
-import pickle
-if __name__ == "__main__":
- if len(sys.argv) == 3:
- runner = pickle.loads(sys.argv[1])
- args = pickle.loads(sys.argv[2])
- (out, err) = runner._getStarted(args)
- if out:
- sys.stdout.write(out)
- if err:
- sys.stderr.write(err)
- else:
- usage()
-#
if args.has_key('ns_port_log_file'):
omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
file_name = os.path.join(omniorbUserPath, args["ns_port_log_file"])
- print file_name, os.environ['NSPORT']
with open(file_name, "w") as f:
f.write(os.environ['NSPORT'])
#