X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2FsalomeContextUtils.py.in;h=71192305de34aaf0b1ec1d1330cf2097ebcf3791;hb=17f89acccd51b2d2c86d44e70a1c053c10da0b3d;hp=3f517dcf73b3c154d03c8d0dc99170cce3e16ac0;hpb=d9c3812022bf47f170380167372a7b61e7b1daa4;p=modules%2Fkernel.git diff --git a/bin/salomeContextUtils.py.in b/bin/salomeContextUtils.py.in index 3f517dcf7..71192305d 100644 --- a/bin/salomeContextUtils.py.in +++ b/bin/salomeContextUtils.py.in @@ -1,6 +1,4 @@ -#! /usr/bin/env python - -# Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +# 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 @@ -24,6 +22,8 @@ import sys import glob import subprocess import re +import socket +import json """ Define a specific exception class to manage exceptions related to SalomeContext @@ -38,12 +38,6 @@ def __listDirectory(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 # @@ -59,18 +53,14 @@ def __getConfigFileNamesDefault(): 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) ] +def __getEnvironmentFileNames(args, optionPrefix, checkExistence): + # special case: extra configuration/environment files are provided by user + # Search for command-line argument(s) =file1,file2,..., filen + # Search for command-line argument(s) =dir1,dir2,..., dirn + configArgs = [ str(x) for x in args if str(x).startswith(optionPrefix) ] - 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 ] + args = [ x for x in args if not x.startswith(optionPrefix) ] + allLists = [ x.replace(optionPrefix, '') for x in configArgs ] configFileNames = [] unexisting = [] @@ -89,7 +79,23 @@ def getConfigFileNames(args, checkExistence=False): return configFileNames, args, unexisting # +def getConfigFileNames(args, checkExistence=False): + configOptionPrefix = "--config=" + configArgs = [ str(x) for x in args if str(x).startswith(configOptionPrefix) ] + if len(configArgs) == 0: + configFileNames, unexist = __getConfigFileNamesDefault(), [] + else: + # get configuration filenames + configFileNames, args, unexist = __getEnvironmentFileNames(args, configOptionPrefix, checkExistence) + + return configFileNames, args, unexist +# + def __getScriptPath(scriptName, searchPathList): + scriptName = os.path.expanduser(scriptName) + if os.path.isabs(scriptName): + return scriptName + if searchPathList is None or len(searchPathList) == 0: return None @@ -101,8 +107,54 @@ def __getScriptPath(scriptName, searchPathList): return None # -# Return an array of dictionaries {script_name: [list_of_its_args]} -def getScriptsAndArgs(args=[], searchPathList=None): +class ScriptAndArgs: + # script: the command to be run, e.g. python + # args: its input parameters + # out: its output parameters + def __init__(self, script=None, args=None, out=None): + self.script = script + self.args = args + self.out = out + # + def __repr__(self): + msg = "\n# Script: %s\n"%self.script + msg += " * Input: %s\n"%self.args + msg += " * Output: %s\n"%self.out + return msg + # +# +class ScriptAndArgsObjectEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, ScriptAndArgs): + # to be easily parsed in GUI module (SalomeApp_Application) + # Do not export output arguments + return {obj.script:obj.args or []} + else: + return json.JSONEncoder.default(self, obj) +# + +def getShortAndExtraArgs(args=None): + if args is None: + args = [] + try: + pos = args.index("--") # raise a ValueError if not found + short_args = args[:pos] + extra_args = args[pos:] # include "--" + except ValueError: + short_args = args + extra_args = [] + pass + + return short_args, extra_args +# + +# Return an array of ScriptAndArgs objects +def getScriptsAndArgs(args=None, searchPathList=None): + if args is None: + args = [] + short_args, extra_args = getShortAndExtraArgs(args) + args = short_args + if searchPathList is None: searchPathList = sys.path @@ -110,94 +162,162 @@ def getScriptsAndArgs(args=[], searchPathList=None): scriptArgs = [] currentKey = None argsPrefix = "args:" + outPrefix = "out:" callPython = False + afterArgs = False currentScript = None for i in range(len(args)): - elt = args[i] + elt = os.path.expanduser(args[i]) + isDriver = (elt == "driver") # special case for YACS scheme execution 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(",") + # Special process if some items of 'args:' list are themselves lists + # Note that an item can be a list, but not a list of lists... + # So we can have something like this: + # myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok" + # 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' + # We have to split elt to obtain: ['[file1,file2]','val1','done','[1,2,3]','[True,False]','ok'] + contains_list = re.findall('(\[[^\]]*\])', elt) + if contains_list: + extracted_args = [] + x = elt.split(",") + # x is ['[file1', 'file2]', 'val1', 'done', '[1', '2', '3]', '[True', 'False]', 'ok'] + list_begin_indices = [i for i in range(len(x)) if x[i].startswith('[')] # [0, 4, 7] + list_end_indices = [i for i in range(len(x)) if x[i].endswith(']')] # [1, 6, 8] + start = 0 + for lbeg, lend in zip(list_begin_indices,list_end_indices): # [(0, 1), (4, 6), (7, 8)] + if lbeg > start: + extracted_args += x[start:lbeg] + pass + extracted_args += [','.join(x[lbeg:lend+1])] + start = lend+1 + pass + if start < len(x): + extracted_args += x[start:len(x)] + pass + scriptArgs[len(scriptArgs)-1].args = extracted_args + pass + else: # a single split is enough + scriptArgs[len(scriptArgs)-1].args = [os.path.expanduser(x) for x in elt.split(",")] + pass currentKey = None callPython = False + afterArgs = True + elif elt.startswith(outPrefix): + if (not currentKey and not afterArgs) or callPython: + raise SalomeContextException("out list must follow both corresponding script file and its args in command line.") + elt = elt.replace(outPrefix, '') + scriptArgs[len(scriptArgs)-1].out = [os.path.expanduser(x) for x in elt.split(",")] + currentKey = None + callPython = False + afterArgs = False elif elt.startswith("python"): callPython = True + afterArgs = False else: + file_extension = os.path.splitext(elt)[-1] 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": + if file_extension == ".py": raise SalomeContextException("Script not found: %s"%elt) + scriptArgs.append(ScriptAndArgs(script=elt)) continue elt = eltInSearchPath - if elt[-4:] != ".hdf": - if elt[-3:] == ".py": + if file_extension != ".hdf": + if file_extension == ".py" or isDriver: 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:[]}) + scriptArgs.append(ScriptAndArgs(script=currentKey)) callPython = False elif currentScript: - if not os.access(currentScript, os.X_OK): + script_extension = os.path.splitext(currentScript)[-1] + if isDriver: + currentKey = currentScript + scriptArgs.append(ScriptAndArgs(script=currentKey)) + callPython = False + elif not os.access(currentScript, os.X_OK): currentKey = "@PYTHONBIN@ "+currentScript - scriptArgs.append({currentKey:[]}) + scriptArgs.append(ScriptAndArgs(script=currentKey)) else: ispython = False try: fn = open(currentScript) - for i in xrange(10): # read only 10 first lines + for i in range(10): # read only 10 first lines ln = fn.readline() if re.search("#!.*python"): ispython = True break pass - fn.close() - except: + except Exception: pass - if not ispython and currentScript[-3:] == ".py": + finally: + fn.close() + if not ispython and script_extension == ".py": currentKey = "@PYTHONBIN@ "+currentScript else: currentKey = currentScript pass - scriptArgs.append({currentKey:[]}) + scriptArgs.append(ScriptAndArgs(script=currentKey)) + # CLOSE elif currentScript + afterArgs = False # end for loop + + if len(extra_args) > 1: # syntax: -- program [options] [arguments] + command = extra_args[1] + command_args = extra_args[2:] + scriptArgs.append(ScriptAndArgs(script=command, args=command_args)) + pass + return scriptArgs # # Formatting scripts and args as a Bash-like command-line: # script1.py [args] ; script2.py [args] ; ... -def formatScriptsAndArgs(scriptArgs=[]): +# scriptArgs is a list of ScriptAndArgs objects; their output parameters are omitted +def formatScriptsAndArgs(scriptArgs=None, escapeSpaces=False): + if scriptArgs is None: + return "" 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) + for sa_obj in scriptArgs: + cmd = sa_obj.script + if escapeSpaces and cmd: + if sys.platform == "win32": + cmd = cmd.replace(' ', ' "', 1) + cmd = cmd + '"' + else: + cmd = cmd.replace(' ', '\ ').replace('\ ', ' ', 1) + if sa_obj.args: + cmd = " ".join([cmd]+sa_obj.args) + commands.append(cmd) + sep = " ; " if sys.platform == "win32": - sep= " & " + 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 +# Ensure OMNIORB_USER_PATH is defined. This variable refers to a 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 +# - If APPLI environment variable is set, and if ${APPLI}/USERS points at an existing +# folder with write access, then OMNIORB_USER_PATH is set to ${APPLI}/USERS. +# 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(): @@ -207,11 +327,27 @@ def setOmniOrbUserPath(): 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 + # Must be in /tmp (or equivalent) to handle application concurrency + try: + import tempfile + temp = tempfile.NamedTemporaryFile() + temp_dir = os.path.dirname(temp.name) + temp.close() + if not os.access(temp_dir, os.W_OK): + raise Exception("Unable to get write access to directory: %s"%temp_dir) + os.environ["OMNIORB_USER_PATH"] = temp_dir + except Exception: + homePath = os.path.realpath(os.path.expanduser('~')) + #defaultOmniorbUserPath = os.path.join(homePath, ".salomeConfig/USERS") + defaultOmniorbUserPath = homePath + if os.getenv("APPLI"): + appli_users_path=os.path.join(homePath, os.getenv("APPLI"), "USERS") + if os.access(appli_users_path, os.W_OK): + defaultOmniorbUserPath = appli_users_path + pass + os.environ["OMNIORB_USER_PATH"] = defaultOmniorbUserPath +# + +def getHostname(): + return socket.gethostname().split('.')[0] #