3 # Copyright (C) 2013-2016 CEA/DEN, EDF R&D, OPEN CASCADE
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
31 Define a specific exception class to manage exceptions related to SalomeContext
33 class SalomeContextException(Exception):
34 """Report error messages to the user interface of SalomeContext."""
37 def __listDirectory(path):
39 for root, dirs, files in os.walk(path):
40 cfgFiles = glob.glob(os.path.join(root,'*.cfg'))
46 def __getConfigFileNamesDefault():
47 absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
48 if not absoluteAppliPath:
51 envdDir = absoluteAppliPath + '/env.d'
52 if not os.path.isdir(envdDir):
55 return __listDirectory(envdDir)
58 def __getEnvironmentFileNames(args, optionPrefix, checkExistence):
59 # special case: extra configuration/environment files are provided by user
60 # Search for command-line argument(s) <optionPrefix>=file1,file2,..., filen
61 # Search for command-line argument(s) <optionPrefix>=dir1,dir2,..., dirn
62 configArgs = [ str(x) for x in args if str(x).startswith(optionPrefix) ]
64 args = [ x for x in args if not x.startswith(optionPrefix) ]
65 allLists = [ x.replace(optionPrefix, '') for x in configArgs ]
69 for currentList in allLists:
70 elements = currentList.split(',')
72 elt = os.path.realpath(os.path.expanduser(elt))
73 if os.path.isdir(elt):
74 configFileNames += __listDirectory(elt)
76 if checkExistence and not os.path.isfile(elt):
79 configFileNames += [elt]
81 return configFileNames, args, unexisting
84 def getConfigFileNames(args, checkExistence=False):
85 configOptionPrefix = "--config="
86 configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ]
87 if len(configArgs) == 0:
88 configFileNames, unexist = __getConfigFileNamesDefault(), []
90 # get configuration filenames
91 configFileNames, args, unexist = __getEnvironmentFileNames(args, configOptionPrefix, checkExistence)
93 return configFileNames, args, unexist
96 def __getScriptPath(scriptName, searchPathList):
97 scriptName = os.path.expanduser(scriptName)
98 if os.path.isabs(scriptName):
101 if searchPathList is None or len(searchPathList) == 0:
104 for path in searchPathList:
105 fullName = os.path.join(path, scriptName)
106 if os.path.isfile(fullName) or os.path.isfile(fullName+".py"):
113 # script: the command to be run, e.g. python <script.py>
114 # args: its input parameters
115 # out: its output parameters
116 def __init__(self, script=None, args=None, out=None):
122 msg = "\n# Script: %s\n"%self.script
123 msg += " * Input: %s\n"%self.args
124 msg += " * Output: %s\n"%self.out
128 class ScriptAndArgsObjectEncoder(json.JSONEncoder):
129 def default(self, obj):
130 if isinstance(obj, ScriptAndArgs):
131 # to be easily parsed in GUI module (SalomeApp_Application)
132 # Do not export output arguments
133 return {obj.script:obj.args or []}
135 return json.JSONEncoder.default(self, obj)
138 def getShortAndExtraArgs(args=None):
142 pos = args.index("--") # raise a ValueError if not found
143 short_args = args[:pos]
144 extra_args = args[pos:] # include "--"
150 return short_args, extra_args
153 # Return an array of ScriptAndArgs objects
154 def getScriptsAndArgs(args=None, searchPathList=None):
157 short_args, extra_args = getShortAndExtraArgs(args)
160 if searchPathList is None:
161 searchPathList = sys.path
163 # Syntax of args: script.py [args:a1,a2=val,an] ... script.py [args:a1,a2=val,an]
172 for i in range(len(args)):
173 elt = os.path.expanduser(args[i])
174 isDriver = (elt == "driver") # special case for YACS scheme execution
176 if elt.startswith(argsPrefix):
177 if not currentKey or callPython:
178 raise SalomeContextException("args list must follow corresponding script file in command line.")
179 elt = elt.replace(argsPrefix, '')
180 # Special process if some items of 'args:' list are themselves lists
181 # Note that an item can be a list, but not a list of lists...
182 # So we can have something like this:
183 # myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
184 # With such a call, an elt variable contains the string representing ['file1','file2'],val1,"done",[1,2,3],[True,False],"ok" that is '[file1,file2],val1,done,[1,2,3],[True,False],ok'
185 # We have to split elt to obtain: ['[file1,file2]','val1','done','[1,2,3]','[True,False]','ok']
186 contains_list = re.findall('(\[[^\]]*\])', elt)
190 # x is ['[file1', 'file2]', 'val1', 'done', '[1', '2', '3]', '[True', 'False]', 'ok']
191 list_begin_indices = [i for i in xrange(len(x)) if x[i].startswith('[')] # [0, 4, 7]
192 list_end_indices = [i for i in xrange(len(x)) if x[i].endswith(']')] # [1, 6, 8]
194 for lbeg, lend in zip(list_begin_indices,list_end_indices): # [(0, 1), (4, 6), (7, 8)]
196 extracted_args += x[start:lbeg]
198 extracted_args += [','.join(x[lbeg:lend+1])]
202 extracted_args += x[start:len(x)]
204 scriptArgs[len(scriptArgs)-1].args = extracted_args
206 else: # a single split is enough
207 scriptArgs[len(scriptArgs)-1].args = [os.path.expanduser(x) for x in elt.split(",")]
212 elif elt.startswith(outPrefix):
213 if (not currentKey and not afterArgs) or callPython:
214 raise SalomeContextException("out list must follow both corresponding script file and its args in command line.")
215 elt = elt.replace(outPrefix, '')
216 scriptArgs[len(scriptArgs)-1].out = [os.path.expanduser(x) for x in elt.split(",")]
220 elif elt.startswith("python"):
224 if not os.path.isfile(elt) and not os.path.isfile(elt+".py"):
225 eltInSearchPath = __getScriptPath(elt, searchPathList)
226 if eltInSearchPath is None or (not os.path.isfile(eltInSearchPath) and not os.path.isfile(eltInSearchPath+".py")):
227 if elt[-3:] == ".py":
228 raise SalomeContextException("Script not found: %s"%elt)
229 scriptArgs.append(ScriptAndArgs(script=elt))
231 elt = eltInSearchPath
233 if elt[-4:] != ".hdf":
234 if elt[-3:] == ".py" or isDriver:
235 currentScript = os.path.abspath(elt)
236 elif os.path.isfile(elt+".py"):
237 currentScript = os.path.abspath(elt+".py")
239 currentScript = os.path.abspath(elt) # python script not necessary has .py extension
242 if currentScript and callPython:
243 currentKey = "@PYTHONBIN@ "+currentScript
244 scriptArgs.append(ScriptAndArgs(script=currentKey))
248 currentKey = currentScript
249 scriptArgs.append(ScriptAndArgs(script=currentKey))
251 elif not os.access(currentScript, os.X_OK):
252 currentKey = "@PYTHONBIN@ "+currentScript
253 scriptArgs.append(ScriptAndArgs(script=currentKey))
257 fn = open(currentScript)
258 for i in xrange(10): # read only 10 first lines
260 if re.search("#!.*python"):
267 if not ispython and currentScript[-3:] == ".py":
268 currentKey = "@PYTHONBIN@ "+currentScript
270 currentKey = currentScript
272 scriptArgs.append(ScriptAndArgs(script=currentKey))
273 # CLOSE elif currentScript
277 if len(extra_args) > 1: # syntax: -- program [options] [arguments]
278 command = extra_args[1]
279 command_args = extra_args[2:]
280 scriptArgs.append(ScriptAndArgs(script=command, args=command_args))
286 # Formatting scripts and args as a Bash-like command-line:
287 # script1.py [args] ; script2.py [args] ; ...
288 # scriptArgs is a list of ScriptAndArgs objects; their output parameters are omitted
289 def formatScriptsAndArgs(scriptArgs=None):
290 if scriptArgs is None:
293 for sa_obj in scriptArgs:
296 cmd = " ".join([cmd]+sa_obj.args)
300 if sys.platform == "win32":
302 command = sep.join(["%s"%x for x in commands])
306 # Ensure OMNIORB_USER_PATH is defined. This variable refers to a folder in which
307 # SALOME will write omniOrb configuration files.
308 # If OMNIORB_USER_PATH is already set, only checks write access to associated directory ;
309 # an exception is raised if check fails. It allows users for choosing a specific folder.
310 # Else the function sets OMNIORB_USER_PATH this way:
311 # - If APPLI environment variable is set, OMNIORB_USER_PATH is set to ${APPLI}/USERS.
312 # The function does not check USERS folder existence or write access. This folder
313 # must exist ; this is the case if SALOME virtual application has been created using
314 # appli_gen.py script.
315 # - Else OMNIORB_USER_PATH is set to user home directory.
316 def setOmniOrbUserPath():
317 omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
319 if not os.access(omniorbUserPath, os.W_OK):
320 raise Exception("Unable to get write access to directory: %s"%omniorbUserPath)
323 homePath = os.path.realpath(os.path.expanduser('~'))
324 #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS")
325 defaultOmniorbUserPath = homePath
326 if os.getenv("APPLI"):
327 defaultOmniorbUserPath = os.path.join(homePath, os.getenv("APPLI"), "USERS")
329 os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath
333 return socket.gethostname().split('.')[0]