X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fenvironment.py;h=88a59590118c89c000f74b482292502a3c68ed5a;hb=8cf39613ef6621accc0f7c60c3cfbe574d845548;hp=4adeb116b8b1741422990dcb3596d3a7428d8df8;hpb=fc5d1238d59d8ca3b07275512cecf58bd3d8224a;p=tools%2Fsat.git diff --git a/src/environment.py b/src/environment.py index 4adeb11..88a5959 100644 --- a/src/environment.py +++ b/src/environment.py @@ -22,35 +22,37 @@ import string import sys import src +import src.debug as DBG +import pprint as PP + class Environ: - '''Class to manage the environment context - ''' + """\ + Class to manage the environment context + """ def __init__(self, environ=None): - '''Initialization. If the environ argument is passed, the environment + """Initialization. If the environ argument is passed, the environment will be add to it, else it is the external environment. :param environ dict: - ''' + """ if environ is not None: self.environ = environ else: self.environ = os.environ def __repr__(self): - """easy non exhaustive quick resume for debug print - """ - res={} - res["environ"]=self.environ - return self.__class__.__name__ + str(res)[0:-1] + " ...etc...}" + """easy non exhaustive quick resume for debug print""" + return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(self.environ)) def _expandvars(self, value): - '''replace some $VARIABLE into its actual value in the environment + """\ + replace some $VARIABLE into its actual value in the environment :param value str: the string to be replaced :return: the replaced variable :rtype: str - ''' + """ if "$" in value: # The string.Template class is a string class # for supporting $-substitutions @@ -63,12 +65,17 @@ class Environ: return value def append_value(self, key, value, sep=os.pathsep): - '''append value to key using sep - + """\ + append value to key using sep, + if value contains ":" or ";" then raise error + :param key str: the environment variable to append :param value str: the value to append to key :param sep str: the separator string - ''' + """ + for c in [";", ":"]: # windows or linux path separators + if c in value: + raise Exception("Environ append key '%s' value '%s' contains forbidden character '%s'" % (key, value, c)) # check if the key is already in the environment if key in self.environ: value_list = self.environ[key].split(sep) @@ -82,12 +89,13 @@ class Environ: self.set(key, value) def append(self, key, value, sep=os.pathsep): - '''Same as append_value but the value argument can be a list + """\ + Same as append_value but the value argument can be a list :param key str: the environment variable to append :param value str or list: the value(s) to append to key :param sep str: the separator string - ''' + """ if isinstance(value, list): for v in value: self.append_value(key, v, sep) @@ -95,12 +103,18 @@ class Environ: self.append_value(key, value, sep) def prepend_value(self, key, value, sep=os.pathsep): - '''prepend value to key using sep + """\ + prepend value to key using sep, + if value contains ":" or ";" then raise error :param key str: the environment variable to prepend :param value str: the value to prepend to key :param sep str: the separator string - ''' + """ + for c in [";", ":"]: # windows or linux path separators + if c in value: + raise Exception("Environ prepend key '%s' value '%s' contains forbidden character '%s'" % (key, value, c)) + # check if the key is already in the environment if key in self.environ: value_list = self.environ[key].split(sep) if not value in value_list: @@ -112,50 +126,55 @@ class Environ: self.set(key, value) def prepend(self, key, value, sep=os.pathsep): - '''Same as prepend_value but the value argument can be a list + """\ + Same as prepend_value but the value argument can be a list :param key str: the environment variable to prepend :param value str or list: the value(s) to prepend to key :param sep str: the separator string - ''' + """ if isinstance(value, list): - for v in value: + for v in reversed(value): # prepend list, first item at last to stay first self.prepend_value(key, v, sep) else: self.prepend_value(key, value, sep) def is_defined(self, key): - '''Check if the key exists in the environment + """\ + Check if the key exists in the environment :param key str: the environment variable to check - ''' + """ return key in self.environ.keys() def set(self, key, value): - '''Set the environment variable "key" to value "value" + """\ + Set the environment variable "key" to value "value" :param key str: the environment variable to set :param value str: the value - ''' + """ self.environ[key] = self._expandvars(value) def get(self, key): - '''Get the value of the environment variable "key" + """\ + Get the value of the environment variable "key" :param key str: the environment variable - ''' + """ if key in self.environ: return self.environ[key] else: return "" def command_value(self, key, command): - '''Get the value given by the system command "command" - and put it in the environment variable key + """\ + Get the value given by the system command "command" + and put it in the environment variable key :param key str: the environment variable :param command str: the command to execute - ''' + """ value = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, @@ -164,16 +183,17 @@ class Environ: class SalomeEnviron: - """Class to manage the environment of SALOME. + """\ + Class to manage the environment of SALOME. """ - def __init__(self, cfg, environ, forBuild=False, for_package=None, enable_simple_env_script = True): - '''Initialization. + """\ + Initialization. :param cfg Config: the global config :param environ Environ: the Environ instance where @@ -182,7 +202,7 @@ class SalomeEnviron: else a build one :param for_package str: If not None, produce a relative environment designed for a package. - ''' + """ self.environ = environ self.cfg = cfg self.forBuild = forBuild @@ -191,50 +211,57 @@ class SalomeEnviron: self.silent = False def __repr__(self): - """easy non exhaustive quick resume for debug print""" - res={} - res["environ"]=str(self.environ) - res["forBuild"]=self.forBuild - return self.__class__.__name__ + str(res)[0:-1] + " ...etc...}" + """easy almost exhaustive quick resume for debug print""" + res = { + "environ" : self.environ, + "forBuild" : self.forBuild, + "for_package" : self.for_package, + } + return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(res)) def append(self, key, value, sep=os.pathsep): - '''append value to key using sep + """\ + append value to key using sep :param key str: the environment variable to append :param value str: the value to append to key :param sep str: the separator string - ''' + """ return self.environ.append(key, value, sep) def prepend(self, key, value, sep=os.pathsep): - '''prepend value to key using sep + """\ + prepend value to key using sep :param key str: the environment variable to prepend :param value str: the value to prepend to key :param sep str: the separator string - ''' + """ return self.environ.prepend(key, value, sep) def is_defined(self, key): - '''Check if the key exists in the environment + """\ + Check if the key exists in the environment :param key str: the environment variable to check - ''' + """ return self.environ.is_defined(key) def get(self, key): - '''Get the value of the environment variable "key" + """\ + Get the value of the environment variable "key" :param key str: the environment variable - ''' + """ return self.environ.get(key) def set(self, key, value): - '''Set the environment variable "key" to value "value" + """\ + Set the environment variable "key" to value "value" :param key str: the environment variable to set :param value str: the value - ''' + """ # check if value needs to be evaluated if value is not None and value.startswith("`") and value.endswith("`"): res = subprocess.Popen("echo %s" % value, @@ -245,7 +272,8 @@ class SalomeEnviron: return self.environ.set(key, value) def dump(self, out): - """Write the environment to out + """\ + Write the environment to out :param out file: the stream where to write the environment """ @@ -257,7 +285,8 @@ class SalomeEnviron: out.write("%s=%s\n" % (k, value)) def add_line(self, nb_line): - """Add empty lines to the out stream (in case of file generation) + """\ + Add empty lines to the out stream (in case of file generation) :param nb_line int: the number of empty lines to add """ @@ -265,7 +294,8 @@ class SalomeEnviron: self.environ.add_line(nb_line) def add_comment(self, comment): - """Add a commentary to the out stream (in case of file generation) + """\ + Add a commentary to the out stream (in case of file generation) :param comment str: the commentary to add """ @@ -273,7 +303,8 @@ class SalomeEnviron: self.environ.add_comment(comment) def add_warning(self, warning): - """Add a warning to the out stream (in case of file generation) + """\ + Add a warning to the out stream (in case of file generation) :param warning str: the warning to add """ @@ -281,18 +312,19 @@ class SalomeEnviron: self.environ.add_warning(warning) def finish(self, required): - """Add a final instruction in the out file (in case of file generation) + """\ + Add a final instruction in the out file (in case of file generation) :param required bool: Do nothing if required is False """ if 'finish' in dir(self.environ): self.environ.add_line(1) - self.environ.add_comment("clean all the path") + # what for ? + # self.environ.add_comment("clean all the path") self.environ.finish(required) def set_python_libdirs(self): - """Set some generic variables for python library paths - """ + """Set some generic variables for python library paths""" ver = self.get('PYTHON_VERSION') self.set('PYTHON_LIBDIR0', os.path.join('lib', 'python' + ver, @@ -305,10 +337,11 @@ class SalomeEnviron: self.python_lib1 = self.get('PYTHON_LIBDIR1') def get_names(self, lProducts): - """Get the products name to add in SALOME_MODULES environment variable - It is the name of the product, except in the case where the is a - component name. And it has to be in SALOME_MODULES variable only - if the product has the property has_salome_hui = "yes" + """\ + Get the products name to add in SALOME_MODULES environment variable + It is the name of the product, except in the case where the is a + component name. And it has to be in SALOME_MODULES variable only + if the product has the property has_salome_hui = "yes" :param lProducts list: List of products to potentially add """ @@ -327,15 +360,28 @@ class SalomeEnviron: lProdName.append(ProdName) return lProdName - def set_application_env(self, logger): - """Sets the environment defined in the APPLICATION file. + def set_application_env(self, logger, no_PRODUCT_ROOT_DIR=False): + """\ + Sets the environment defined in the APPLICATION file. :param logger Logger: The logger instance to display messages """ + # add variable PRODUCT_ROOT_DIR as $workdir in APPLICATION.environ section if not present + # but if sat launcher or sat package do not duplicate line context.setVariable(r"PRODUCT_ROOT_DIR", ... + # no_PRODUCT_ROOT_DIR used only for write_cfgForPy_file + if not no_PRODUCT_ROOT_DIR: # do not duplicate context.setVariable(r"PRODUCT_ROOT_DIR" + try: + tmp = self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR + except: + self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR = src.pyconf.Reference(self.cfg, src.pyconf.DOLLAR, "workdir") + DBG.write("set_application_env: add APPLICATION.environ.PRODUCT_ROOT_DIR", self.cfg.APPLICATION.environ) + # Set the variables defined in the "environ" section if 'environ' in self.cfg.APPLICATION: - self.add_comment("APPLICATION environment") + # we write PRODUCT environment it in order to conform to + # parseConfigFile.py + self.add_comment("PRODUCT environment") self.load_cfg_environment(self.cfg.APPLICATION.environ) if self.forBuild and "build" in self.cfg.APPLICATION.environ: self.load_cfg_environment(self.cfg.APPLICATION.environ.build) @@ -343,24 +389,17 @@ class SalomeEnviron: self.load_cfg_environment(self.cfg.APPLICATION.environ.launch) self.add_line(1) - # If there is an "environ_script" section, load the scripts - if 'environ_script' in self.cfg.APPLICATION: - for pscript in self.cfg.APPLICATION.environ_script: - self.add_comment("script %s" % pscript) - sname = pscript.replace(" ", "_") - self.run_env_script("APPLICATION_%s" % sname, - self.cfg.APPLICATION.environ_script[pscript], - logger) - self.add_line(1) def set_salome_minimal_product_env(self, product_info, logger): - """Sets the minimal environment for a SALOME product. - xxx_ROOT_DIR and xxx_SRC_DIR + """\ + Sets the minimal environment for a SALOME product. + xxx_ROOT_DIR and xxx_SRC_DIR :param product_info Config: The product description :param logger Logger: The logger instance to display messages """ # set root dir + DBG.write("set_salome_minimal_product_env", product_info) root_dir = product_info.name + "_ROOT_DIR" if not self.is_defined(root_dir): if 'install_dir' in product_info and product_info.install_dir: @@ -384,7 +423,8 @@ class SalomeEnviron: product_info.name)) def set_salome_generic_product_env(self, pi): - """Sets the generic environment for a SALOME product. + """\ + Sets the generic environment for a SALOME product. :param pi Config: The product description """ @@ -393,26 +433,27 @@ class SalomeEnviron: l_binpath_libpath = [] # create additional ROOT_DIR for CPP components - if src.product.product_is_cpp(pi): - assert 'component_name' in pi, 'Error : CPP component should have a component_name field' + if 'component_name' in pi: compo_name = pi.component_name - compo_root_dir = compo_name + "_ROOT_DIR" - envcompo_root_dir = os.path.join( - self.cfg.TOOLS.common.install_root, compo_name ) - self.set(compo_root_dir , envcompo_root_dir) - bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome') - lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome') - l_binpath_libpath.append( (bin_path, lib_path) ) - - bin_path = os.path.join(env_root_dir, 'bin', 'salome') + if compo_name + "CPP" == pi.name: + compo_root_dir = compo_name + "_ROOT_DIR" + envcompo_root_dir = os.path.join( + self.cfg.TOOLS.common.install_root, compo_name ) + self.set(compo_root_dir , envcompo_root_dir) + bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome') + lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome') + l_binpath_libpath.append( (bin_path, lib_path) ) + if src.get_property_in_product_cfg(pi, "fhs"): lib_path = os.path.join(env_root_dir, 'lib') pylib1_path = os.path.join(env_root_dir, self.python_lib0) pylib2_path = os.path.join(env_root_dir, self.python_lib1) + bin_path = os.path.join(env_root_dir, 'bin') else: lib_path = os.path.join(env_root_dir, 'lib', 'salome') pylib1_path = os.path.join(env_root_dir, self.python_lib0, 'salome') pylib2_path = os.path.join(env_root_dir, self.python_lib1, 'salome') + bin_path = os.path.join(env_root_dir, 'bin', 'salome') # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and # PYTHONPATH @@ -430,7 +471,8 @@ class SalomeEnviron: self.prepend('PYTHONPATH', l) def set_cpp_env(self, product_info): - """Sets the generic environment for a SALOME cpp product. + """\ + Sets the generic environment for a SALOME cpp product. :param product_info Config: The product description """ @@ -459,7 +501,8 @@ class SalomeEnviron: self.prepend('PYTHONPATH', l) def load_cfg_environment(self, cfg_env): - """Loads environment defined in cfg_env + """\ + Loads environment defined in cfg_env :param cfg_env Config: A config containing an environment """ @@ -500,7 +543,8 @@ class SalomeEnviron: self.set(env_def, val) def set_a_product(self, product, logger): - """Sets the environment of a product. + """\ + Sets the environment of a product. :param product str: The product name :param logger Logger: The logger instance to display messages @@ -508,6 +552,20 @@ class SalomeEnviron: # Get the informations corresponding to the product pi = src.product.get_product_config(self.cfg, product) + + # skip mesa products (if any) at run time, + # unless use_mesa property was activated + if not self.forBuild: + if not ("APPLICATION" in self.cfg and + "properties" in self.cfg.APPLICATION and + "use_mesa" in self.cfg.APPLICATION.properties and + self.cfg.APPLICATION.properties.use_mesa == "yes") : + if ("properties" in pi and + "is_mesa" in pi.properties and + pi.properties.is_mesa == "yes") : + logger.write(_("Skip mesa product %s\n") % pi.name, 4) + return + if self.for_package: pi.install_dir = os.path.join("out_dir_Path", @@ -578,7 +636,8 @@ class SalomeEnviron: def run_env_script(self, product_info, logger=None, native=False): - """Runs an environment script. + """\ + Runs an environment script. :param product_info Config: The product description :param logger Logger: The logger instance to display messages @@ -599,10 +658,22 @@ class SalomeEnviron: pyproduct = imp.load_source(product_info.name + "_env_script", env_script) if not native: - pyproduct.set_env(self, - product_info.install_dir, - product_info.version) + if self.forBuild and "set_env_build" in dir(pyproduct): + pyproduct.set_env_build(self, + product_info.install_dir, + product_info.version) + elif (not self.forBuild) and "set_env_launch" in dir(pyproduct): + pyproduct.set_env_launch(self, + product_info.install_dir, + product_info.version) + else: + # at least this one is mandatoryi, + # if set_env_build and set_env_build are not defined + pyproduct.set_env(self, + product_info.install_dir, + product_info.version) else: + # not mandatory, if set_nativ_env not defined, we do nothing if "set_nativ_env" in dir(pyproduct): pyproduct.set_nativ_env(self) except: @@ -613,8 +684,9 @@ class SalomeEnviron: traceback.print_exc() def run_simple_env_script(self, script_path, logger=None): - """Runs an environment script. Same as run_env_script, but with a - script path as parameter. + """\ + Runs an environment script. Same as run_env_script, but with a + script path as parameter. :param script_path str: a path to an environment script :param logger Logger: The logger instance to display messages @@ -647,7 +719,8 @@ class SalomeEnviron: traceback.print_exc() def set_products(self, logger, src_root=None): - """Sets the environment for all the products. + """\ + Sets the environment for all the products. :param logger Logger: The logger instance to display messages :param src_root src: the application working directory @@ -668,12 +741,16 @@ class SalomeEnviron: self.finish(False) def set_full_environ(self, logger, env_info): - """Sets the full environment for products - specified in env_info dictionary. + """\ + Sets the full environment for products + specified in env_info dictionary. :param logger Logger: The logger instance to display messages :param env_info list: the list of products """ + DBG.write("set_full_environ for", env_info) + # DBG.write("set_full_environ config", self.cfg.APPLICATION.environ, True) + # set product environ self.set_application_env(logger) @@ -684,17 +761,19 @@ class SalomeEnviron: self.set_a_product(product, logger) class FileEnvWriter: - """Class to dump the environment to a file. + """\ + Class to dump the environment to a file. """ def __init__(self, config, logger, out_dir, src_root, env_info=None): - '''Initialization. + """\ + Initialization. :param cfg Config: the global config :param logger Logger: The logger instance to display messages :param out_dir str: The directory path where t put the output files :param src_root str: The application working directory :param env_info str: The list of products to add in the files. - ''' + """ self.config = config self.logger = logger self.out_dir = out_dir @@ -703,7 +782,8 @@ class FileEnvWriter: self.env_info = env_info def write_env_file(self, filename, forBuild, shell, for_package = None): - """Create an environment file. + """\ + Create an environment file. :param filename str: the file path :param forBuild bool: if true, the build environment @@ -749,8 +829,9 @@ class FileEnvWriter: additional_env = {}, for_package = None, with_commercial = True): - """Append to current opened aFile a cfgForPy - environment (SALOME python launcher). + """\ + Append to current opened aFile a cfgForPy + environment (SALOME python launcher). :param filename str: the file path :param additional_env dict: a dictionary of additional variables @@ -763,9 +844,9 @@ class FileEnvWriter: src.printcolors.printcLabel(filename.name), 3) # create then env object - tmp = src.fileEnviron.get_file_environ(filename, - "cfgForPy", - {}) + tmp = src.fileEnviron.get_file_environ(filename, "cfgForPy", {}) + # DBG.write("fileEnviron.get_file_environ %s" % filename, tmp, True) + # environment for launch env = SalomeEnviron(self.config, tmp, @@ -774,19 +855,23 @@ class FileEnvWriter: enable_simple_env_script = with_commercial) env.silent = self.silent + DBG.write("write_cfgForPy_file", self.config.APPLICATION.environ) + if self.env_info is not None: env.set_full_environ(self.logger, self.env_info) + DBG.write("set_full_environ", self.env_info) + else: # set env from PRODUCT - env.set_application_env(self.logger) + env.set_application_env(self.logger, no_PRODUCT_ROOT_DIR=True) # The list of products to launch lProductsName = env.get_names(self.config.APPLICATION.products.keys()) - env.set( "SALOME_MODULES", ','.join(lProductsName)) + env.set("SALOME_MODULES", ','.join(lProductsName)) # set the products - env.set_products(self.logger, - src_root=self.src_root) + env.set_products(self.logger, src_root=self.src_root) + DBG.write("set_application_env without PRODUCT_ROOT_DIR", self.config.APPLICATION.environ) # Add the additional environment if it is not empty if len(additional_env) != 0: @@ -797,19 +882,22 @@ class FileEnvWriter: env.finish(True) class Shell: - """Definition of a Shell. + """\ + Definition of a Shell. """ def __init__(self, name, extension): - '''Initialization. + """\ + Initialization. :param name str: the shell name :param extension str: the shell extension - ''' + """ self.name = name self.extension = extension def load_environment(config, build, logger): - """Loads the environment (used to run the tests, for example). + """\ + Loads the environment (used to run the tests, for example). :param config Config: the global config :param build bool: build environement if True