Salome HOME
sat prepare and sat install with pip, triggered by pip properties nct/pip
authorcrouzet <nicolas.crouzet@cea.fr>
Mon, 15 Jul 2019 15:09:59 +0000 (17:09 +0200)
committercrouzet <nicolas.crouzet@cea.fr>
Mon, 15 Jul 2019 15:09:59 +0000 (17:09 +0200)
commands/compile.py
commands/source.py
src/__init__.py
src/product.py

index 4c469bcf5b3aee24b909da3a304bd9c00f640e60..fb1fee07b478785404f69eaaae1cbc23967279bf 100644 (file)
@@ -18,6 +18,7 @@
 
 import os
 import re
+import subprocess
 import src
 import src.debug as DBG
 
@@ -328,23 +329,36 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end):
     # build_sources : cmake     -> cmake, make, make install
     # build_sources : script    -> script executions
     res = 0
-    if (src.product.product_is_autotools(p_info) or 
-                                          src.product.product_is_cmake(p_info)):
-        res, len_end_line, error_step = compile_product_cmake_autotools(sat,
-                                                                  p_name_info,
-                                                                  config,
-                                                                  options,
-                                                                  logger,
-                                                                  header,
-                                                                  len_end)
-    if src.product.product_has_script(p_info):
-        res, len_end_line, error_step = compile_product_script(sat,
-                                                                  p_name_info,
-                                                                  config,
-                                                                  options,
-                                                                  logger,
-                                                                  header,
-                                                                  len_end)
+
+    
+    # check if pip should be used : the application and product have pip property
+    if (src.appli_test_property(config,"pip", "yes") and 
+       src.product.product_test_property(p_info,"pip", "yes")):
+            res, len_end_line, error_step = compile_product_pip(sat,
+                                                                p_name_info,
+                                                                config,
+                                                                options,
+                                                                logger,
+                                                                header,
+                                                                len_end)
+    else:
+        if (src.product.product_is_autotools(p_info) or 
+                                              src.product.product_is_cmake(p_info)):
+            res, len_end_line, error_step = compile_product_cmake_autotools(sat,
+                                                                      p_name_info,
+                                                                      config,
+                                                                      options,
+                                                                      logger,
+                                                                      header,
+                                                                      len_end)
+        if src.product.product_has_script(p_info):
+            res, len_end_line, error_step = compile_product_script(sat,
+                                                                   p_name_info,
+                                                                   config,
+                                                                   options,
+                                                                   logger,
+                                                                   header,
+                                                                   len_end)
 
     # Check that the install directory exists
     if res==0 and not(os.path.exists(p_info.install_dir)):
@@ -376,6 +390,88 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end):
     
     return res, len_end_line, error_step
 
+
+def compile_product_pip(sat,
+                        p_name_info,
+                        config,
+                        options,
+                        logger,
+                        header,
+                        len_end):
+    '''Execute the proper build procedure for pip products
+    :param p_name_info tuple: (str, Config) => (product_name, product_info)
+    :param config Config: The global configuration
+    :param logger Logger: The logger instance to use for the display 
+                          and logging
+    :param header Str: the header to display when logging
+    :param len_end Int: the lenght of the the end of line (used in display)
+    :return: 1 if it fails, else 0.
+    :rtype: int
+    '''
+    p_name, p_info = p_name_info
+    
+    # Execute "sat configure", "sat make" and "sat install"
+    res = 0
+    error_step = ""
+    pip_install_in_python=False
+    if src.appli_test_property(config,"pip_install_dir", "python"):
+        # pip will install product in python directory"
+        pip_install_cmd="pip3 install --disable-pip-version-check --no-index --find-links=%s --build %s %s==%s" %\
+        (config.LOCAL.archive_dir, p_info.build_dir, p_name, p_info.version)
+        pip_install_in_python=True
+        
+    else: 
+        # pip will install product in product install_dir
+        pip_install_dir=os.path.join(p_info.install_dir, "lib", "python${PYTHON_VERSION:0:3}", "site-packages")
+        pip_install_cmd="pip3 install --disable-pip-version-check --no-index --find-links=%s --build %s --target %s %s==%s" %\
+        (config.LOCAL.archive_dir, p_info.build_dir, pip_install_dir, p_name, p_info.version)
+    log_step(logger, header, "PIP")
+    logger.write("\n"+pip_install_cmd+"\n", 4)
+    len_end_line = len_end + 3
+    error_step = ""
+    build_environ = src.environment.SalomeEnviron(config,
+                             src.environment.Environ(dict(os.environ)),
+                             True)
+    environ_info = src.product.get_product_dependencies(config,
+                                                        p_info)
+    build_environ.silent = (config.USER.output_verbose_level < 5)
+    build_environ.set_full_environ(logger, environ_info)
+    
+    if pip_install_in_python and (options.clean_install or options.clean_all):
+        # for products installed by pip inside python install dir
+        # finish the clean by uninstalling the product from python install dir
+        pip_clean_cmd="pip3 uninstall -y  %s==%s" % (p_name, p_info.version)
+        res_pipclean = (subprocess.call(pip_clean_cmd, 
+                                   shell=True, 
+                                   cwd=config.LOCAL.workdir,
+                                   env=build_environ.environ.environ,
+                                   stdout=logger.logTxtFile, 
+                                   stderr=subprocess.STDOUT) == 0)        
+        if not res_pipclean:
+            logger.write("\n",1)
+            logger.warning("pip3 uninstall failed!")
+
+    res_pip = (subprocess.call(pip_install_cmd, 
+                               shell=True, 
+                               cwd=config.LOCAL.workdir,
+                               env=build_environ.environ.environ,
+                               stdout=logger.logTxtFile, 
+                               stderr=subprocess.STDOUT) == 0)        
+    if res_pip:
+        res=0
+        if pip_install_in_python:
+            # when product is installed in python, create install_dir 
+            # (to put inside product info and mark the installation success)
+            os.mkdir(p_info.install_dir)
+    else:
+        #log_res_step(logger, res)
+        res=1
+        error_step = "PIP"
+
+    return res, len_end_line, error_step 
+
+
+
 def compile_product_cmake_autotools(sat,
                                     p_name_info,
                                     config,
index 823e1da309d2ba50c78382b77b9eaf47f5471f16..54bd9f0f07802309eeb8f7e9026269b4e68ee3d9 100644 (file)
@@ -19,6 +19,7 @@
 import os
 import shutil
 import re
+import subprocess
 
 import src
 import prepare
@@ -153,6 +154,21 @@ def get_source_from_archive(config, product_info, source_dir, logger):
     :return: True if it succeed, else False
     :rtype: boolean
     '''
+
+    # check if pip should be used : pip mode id activated if the application and product have pip property
+    if (src.appli_test_property(config,"pip", "yes") and 
+       src.product.product_test_property(product_info,"pip", "yes")):
+        # download whl in local archive dir
+        pip_download_cmd="pip download --disable-pip-version-check --destination-directory %s --no-deps %s==%s " %\
+                         (config.LOCAL.archive_dir, product_info.name, product_info.version)
+        logger.write(pip_download_cmd, 3, False) 
+        res_pip = (subprocess.call(pip_download_cmd, 
+                                   shell=True, 
+                                   cwd=config.LOCAL.workdir,
+                                   stdout=logger.logTxtFile, 
+                                   stderr=subprocess.STDOUT) == 0)        
+        return res_pip
+
     # check archive exists
     if not os.path.exists(product_info.archive_info.archive_name):
         # The archive is not found on local file system (ARCHIVEPATH)
index 310c669f10e02a94be73fc8f6f1cf49dd04d6c7d..ad0997b4f816e1c0aa5ecc563f02250cc5bd816c 100644 (file)
@@ -91,6 +91,27 @@ def check_config_has_profile( config, details = None ):
             details.append(message)
         raise SatException( message )
 
+def appli_test_property(config,property_name, property_value):
+    """Generic function to test if an application has a property set to a value
+    :param config class 'common.pyconf.Config': The config.
+    :param property_name : The name of the property to check
+    :param property_value : The value of the property to test
+    :return: True if the application has the property set to property_value
+    :rtype: boolean
+    """
+    # first check if application has property_value
+    if not ("APPLICATION"  in config and
+            "properties"   in config.APPLICATION and
+            property_name  in config.APPLICATION.properties):
+        return False
+
+    # then check to the property is set to property_value
+    eval_expression = 'config.APPLICATION.properties.%s == "%s"' %\
+                      (property_name,property_value)
+    result = eval(eval_expression)
+    return result
+    
+
 def config_has_application( config ):
     return 'APPLICATION' in config
 
index 44d20e9faf8bf4b2670f4c1d95d4dfb101ff27dc..ce07ef76247c8bd09dd79215f69b0f33ecabf7a2 100644 (file)
@@ -1069,6 +1069,29 @@ def product_is_compile_time(product_info):
             "compile_time" in product_info.properties and
             product_info.properties.compile_time == "yes")
 
+
+def product_test_property(product_info, property_name, property_value):
+    """Generic function to test if a product has a property set to a value
+    
+    :param product_info Config: The configuration specific to 
+                               the product
+    :param property_name : The name of the property to check
+    :param property_value : The value of the property to test
+    :return: True if the product has the property and the property is set to property_value
+    :rtype: boolean
+    """
+    # first check if product has the property
+    if not ("properties" in product_info and
+            property_name in product_info.properties):
+        return False
+  
+    # then check to the property is set to property_value
+    eval_expression = 'product_info.properties.%s == "%s"' % (property_name,property_value)
+    result = eval(eval_expression)
+    return result
+
+
+
 def get_product_components(product_info):
     """Get the component list to generate with the product