# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""\
+initial imports and utilities methods for salomeTools
+"""
+
import os
import shutil
import errno
import stat
+import fnmatch
+import pprint as PP
+from ftplib import FTP
from . import pyconf
from . import architecture
KNOWNFAILURE_STATUS = "KF"
TIMEOUT_STATUS = "TIMEOUT"
-CONFIG_FILENAME = "sat-config.pyconf"
-
class SatException(Exception):
- '''rename Exception Class
- '''
+ """rename Exception Class"""
pass
def ensure_path_exists(p):
- '''Create a path if not existing
+ """Create a path if not existing
:param p str: The path.
- '''
+ """
if not os.path.exists(p):
os.makedirs(p)
def check_config_has_application( config, details = None ):
- '''check that the config has the key APPLICATION. Else raise an exception.
+ """check that the config has the key APPLICATION. Else raise an exception.
:param config class 'common.pyconf.Config': The config.
- '''
+ """
if 'APPLICATION' not in config:
- message = _("An APPLICATION is required. Use 'config --list' to get"
- " the list of available applications.\n")
+ message = _("An APPLICATION is required. Use 'config --list' to get the list of available applications.\n")
if details :
details.append(message)
raise SatException( message )
def check_config_has_profile( config, details = None ):
- '''check that the config has the key APPLICATION.profile.
- Else, raise an exception.
+ """\
+ check that the config has the key APPLICATION.profile.
+ else, raise an exception.
:param config class 'common.pyconf.Config': The config.
- '''
+ """
check_config_has_application(config)
if 'profile' not in config.APPLICATION:
message = _("A profile section is required in your application.\n")
return 'APPLICATION' in config
def get_cfg_param(config, param_name, default):
- '''Search for param_name value in config.
- If param_name is not in config, then return default,
- else, return the found value
+ """\
+ eearch for param_name value in config.
+ if param_name is not in config
+ then return default,
+ else return the found value
:param config class 'common.pyconf.Config': The config.
:param param_name str: the name of the parameter to get the value
:param default str: The value to return if param_name is not in config
:return: see initial description of the function
:rtype: str
- '''
+ """
if param_name in config:
return config[param_name]
return default
+def strSplitN(aList, nb, skip="\n "):
+ """
+ example
+ aStr = 'this-is-a-string'
+ splitN(aStr, 2, '-')
+ split it by every 2nd '-' rather than every '-'
+ """
+ strValue = ""
+ i = 0
+ for v in aList:
+ strValue += "%15s, " % str(v)
+ i += 1
+ if i >= nb:
+ strValue += skip
+ i = 0
+ if len(aList) > nb:
+ strValue = skip + strValue
+ return strValue
+
+def getProductNames(cfg, wildcards, logger):
+ """get products names using * or ? as wildcards like shell Linux"""
+ res = []
+ if type(wildcards) is list:
+ wilds = wildcards
+ else:
+ wilds = [wildcards]
+ notFound = {}
+ products = cfg.APPLICATION.products.keys()
+ for wild in wildcards:
+ ok = False
+ for prod in products:
+ filtered = fnmatch.filter([prod], wild)
+ # print("filtered", prod, wild, filtered)
+ if len(filtered) > 0:
+ res.append(prod)
+ ok = True
+ continue
+ if not ok:
+ notFound[wild] = None
+ if len(res) == 0:
+ logger.warning("Empty list of products, from %s" % wilds)
+ if len(notFound.keys()) > 0:
+ strProd = strSplitN( sorted(products), 5)
+ logger.warning("products not found: %s\n availables products are:\n%s" % \
+ (sorted(notFound.keys()), strProd) )
+ return res
+
+
def print_info(logger, info):
- '''Prints the tuples that are in info variable in a formatted way.
+ """\
+ Prints the tuples that are in info variable in a formatted way.
:param logger Logger: The logging instance to use for the prints.
:param info list: The list of tuples to display
- '''
+ """
# find the maximum length of the first value of the tuples in info
smax = max(map(lambda l: len(l[0]), info))
# Print each item of info with good indentation
logger.write("\n", 2)
def get_base_path(config):
- '''Returns the path of the products base.
+ """\
+ Returns the path of the products base.
:param config Config: The global Config instance.
:return: The path of the products base.
:rtype: str
- '''
+ """
if "base" not in config.LOCAL:
local_file_path = os.path.join(config.VARS.salometoolsway,
"data",
return base_path
def get_launcher_name(config):
- '''Returns the name of salome launcher.
+ """\
+ Returns the name of salome launcher.
:param config Config: The global Config instance.
:return: The name of salome launcher.
:rtype: str
- '''
+ """
check_config_has_application(config)
- if 'profile' in config.APPLICATION and 'launcher_name=' in config.APPLICATION.profile:
+ if 'profile' in config.APPLICATION and 'launcher_name' in config.APPLICATION.profile:
launcher_name = config.APPLICATION.profile.launcher_name
else:
launcher_name = 'salome'
return launcher_name
def get_log_path(config):
- '''Returns the path of the logs.
+ """\
+ Returns the path of the logs.
:param config Config: The global Config instance.
:return: The path of the logs.
:rtype: str
- '''
+ """
if "log_dir" not in config.LOCAL:
local_file_path = os.path.join(config.VARS.salometoolsway,
"data",
return log_dir_path
def get_salome_version(config):
+ import versionMinorMajorPatch as VMMP
+
if hasattr(config.APPLICATION, 'version_salome'):
- Version = config.APPLICATION.version_salome
+ version = VMMP.MinorMajorPatch(config.APPLICATION.version_salome)
else:
- KERNEL_info = product.get_product_config(config, "KERNEL")
- VERSION = os.path.join(
- KERNEL_info.install_dir,
+ kernel_info = product.get_product_config(config, "KERNEL")
+ aFile = os.path.join(
+ kernel_info.install_dir,
"bin",
"salome",
"VERSION")
- if not os.path.isfile(VERSION):
+ if not os.path.isfile(aFile):
return None
-
- fVERSION = open(VERSION)
- Version = fVERSION.readline()
- fVERSION.close()
-
- VersionSalome = int(only_numbers(Version))
- return VersionSalome
+ with open(aFile) as f:
+ line = f.readline() # example: '[SALOME KERNEL] : 8.4.0'
+ version = VMMP.MinorMajorPatch(line.split(":")[1])
-def only_numbers(str_num):
- return ''.join([nb for nb in str_num if nb in '0123456789'] or '0')
+ res = version.strCompact()
+ # print("get_salome_version %s -> %s" % (version, res))
+ return int(res) # TODO may be future avoid test(s) on integer, use MajorMinorPatch
def read_config_from_a_file(filePath):
try:
return False
def find_file_in_lpath(file_name, lpath, additional_dir = ""):
- """Find in all the directories in lpath list the file that has the same name
- as file_name. If it is found, return the full path of the file, else,
- return False.
- The additional_dir (optional) is the name of the directory to add to all
- paths in lpath.
+ """\
+ Find in all the directories in lpath list the file that has the same name
+ as file_name.
+ If it is found
+ then return the full path of the file
+ else return False.
+
+ The additional_dir (optional) is the name of the directory to add to all
+ paths in lpath.
:param file_name str: The file name to search
:param lpath List: The list of directories where to search
return os.path.join(dir_complete, file_name)
return False
+def find_file_in_ftppath(file_name, ftppath, installation_dir, logger):
+ """\
+ Find in all ftp servers in ftppath the file called file_name
+ If it is found then return the destination path of the file
+ (the place where the file was downloaded"
+ else return False.
+
+ :param file_name str: The file name to search
+ :param ftppath, List: The list of ftp servers where to search
+ :param installation_dir str: The name of the installation directory
+ :return: the full path of the file or False if not found
+ :param logger Logger: The logging instance to use for the prints.
+ :rtype: str
+ """
+
+ # make sure installation_dir exists
+ if not os.path.exists(installation_dir):
+ os.makedirs(installation_dir)
+
+ destination=os.path.join(installation_dir, file_name)
+
+ # paths in ftppath may contain several paths separated by ":"
+ # we plit them, and push all paths in bigftppath
+ bigftppath=[]
+ for ipath in ftppath:
+ splpath=ipath.split(":")
+ bigftppath+=splpath
+
+ for ftp_archive in bigftppath:
+ try:
+ # ftp_archive has the form ftp.xxx.yyy/dir1/dir2/...
+ ftp_archive_split=ftp_archive.split("/")
+ ftp_server=ftp_archive_split[0]
+ ftp = FTP(ftp_server)
+ logger.write(" Connect to ftp server %s\n" % ftp_server, 3)
+ ftp.login()
+ for directory in ftp_archive_split[1:]:
+ logger.write(" Change directory to %s\n" % directory, 3)
+ ftp.cwd(directory)
+ except:
+ logger.error("while connecting to ftp server %s\n" % ftp_server)
+
+ try:
+ if ftp.size(file_name) > 0:
+ # if file exists and is non empty
+ with open(destination,'wb') as dest_file:
+ ftp.retrbinary("RETR "+file_name, dest_file.write)
+ logger.write(" Archive %s was retrieved and stored in %s\n" % (file_name, destination), 3)
+ return destination
+ except:
+ logger.error("File not found in ftp_archive %s\n" % ftp_server)
+ pass
+
+ return False
+
def handleRemoveReadonly(func, path, exc):
excvalue = exc[1]
if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
raise
def deepcopy_list(input_list):
- """ Do a deep copy of a list
+ """\
+ Do a deep copy of a list
:param input_list List: The list to copy
:return: The copy of the list
return res
def remove_item_from_list(input_list, item):
- """ Remove all occurences of item from input_list
+ """\
+ Remove all occurences of item from input_list
:param input_list List: The list to modify
:return: The without any item
return res
def parse_date(date):
- """Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss.
+ """\
+ Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss.
:param date str: The date to transform
:return: The date in the new format
return res
def merge_dicts(*dict_args):
- '''
+ """\
Given any number of dicts, shallow copy and merge into a new dict,
precedence goes to key value pairs in latter dicts.
- '''
+ """
result = {}
for dictionary in dict_args:
result.update(dictionary)
return result
def replace_in_file(filein, strin, strout):
- '''Replace <strin> by <strout> in file <filein>
- '''
+ """Replace <strin> by <strout> in file <filein>"""
shutil.move(filein, filein + "_old")
fileout= filein
filein = filein + "_old"
if not pprty in product_cfg.properties:
return None
return product_cfg.properties[pprty]
+
+def activate_mesa_property(config):
+ """Add mesa property into application properties
+
+ :param config Config: The global configuration. It must have an application!
+ """
+ # Verify the existence of the file
+ if not 'properties' in config.APPLICATION:
+ config.APPLICATION.addMapping( 'properties', pyconf.Mapping(), None )
+ config.APPLICATION.properties.use_mesa="yes"
+