Salome HOME
Merge branch 'cvw/sprint_180319' of https://codev-tuleap.cea.fr/plugins/git/spns...
[tools/sat.git] / src / __init__.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2013  CEA/DEN
4 #
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.
9 #
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.
14 #
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
18
19
20 """\
21 initial imports and utilities methods for salomeTools
22 """
23
24 import os
25 import shutil
26 import errno
27 import stat
28
29 from . import pyconf
30 from . import architecture
31 from . import printcolors
32 from . import options
33 from . import system
34 from . import ElementTree
35 from . import logger
36 from . import product
37 from . import environment
38 from . import fileEnviron
39 from . import compilation
40 from . import test_module
41 from . import template
42
43 import platform
44 if platform.system() == "Windows" :
45     import colorama
46     colorama.init()
47
48 OK_STATUS = "OK"
49 KO_STATUS = "KO"
50 NA_STATUS = "NA"
51 KNOWNFAILURE_STATUS = "KF"
52 TIMEOUT_STATUS = "TIMEOUT"
53
54 CONFIG_FILENAME = "sat-config.pyconf"
55
56 class SatException(Exception):
57     """rename Exception Class"""
58     pass
59
60 def ensure_path_exists(p):
61     """Create a path if not existing
62     
63     :param p str: The path.
64     """
65     if not os.path.exists(p):
66         os.makedirs(p)
67         
68 def check_config_has_application( config, details = None ):
69     """check that the config has the key APPLICATION. Else raise an exception.
70     
71     :param config class 'common.pyconf.Config': The config.
72     """
73     if 'APPLICATION' not in config:
74         message = _("An APPLICATION is required. Use 'config --list' to get"
75                     " the list of available applications.\n")
76         if details :
77             details.append(message)
78         raise SatException( message )
79
80 def check_config_has_profile( config, details = None ):
81     """\
82     check that the config has the key APPLICATION.profile.
83     else, raise an exception.
84     
85     :param config class 'common.pyconf.Config': The config.
86     """
87     check_config_has_application(config)
88     if 'profile' not in config.APPLICATION:
89         message = _("A profile section is required in your application.\n")
90         if details :
91             details.append(message)
92         raise SatException( message )
93
94 def config_has_application( config ):
95     return 'APPLICATION' in config
96
97 def get_cfg_param(config, param_name, default):
98     """\
99     eearch for param_name value in config.
100     if param_name is not in config 
101     then return default,
102     else return the found value
103        
104     :param config class 'common.pyconf.Config': The config.
105     :param param_name str: the name of the parameter to get the value
106     :param default str: The value to return if param_name is not in config
107     :return: see initial description of the function
108     :rtype: str
109     """
110     if param_name in config:
111         return config[param_name]
112     return default
113
114 def print_info(logger, info):
115     """\
116     Prints the tuples that are in info variable in a formatted way.
117     
118     :param logger Logger: The logging instance to use for the prints.
119     :param info list: The list of tuples to display
120     """
121     # find the maximum length of the first value of the tuples in info
122     smax = max(map(lambda l: len(l[0]), info))
123     # Print each item of info with good indentation
124     for i in info:
125         sp = " " * (smax - len(i[0]))
126         printcolors.print_value(logger, sp + i[0], i[1], 2)
127     logger.write("\n", 2)
128
129 def get_base_path(config):
130     """\
131     Returns the path of the products base.
132     
133     :param config Config: The global Config instance.
134     :return: The path of the products base.
135     :rtype: str
136     """
137     if "base" not in config.LOCAL:
138         local_file_path = os.path.join(config.VARS.salometoolsway,
139                                       "data",
140                                       "local.pyconf")
141         msg = _("Please define a base path in the file %s" % local_file_path)
142         raise SatException(msg)
143         
144     base_path = os.path.abspath(config.LOCAL.base)
145     
146     return base_path
147
148 def get_launcher_name(config):
149     """\
150     Returns the name of salome launcher.
151     
152     :param config Config: The global Config instance.
153     :return: The name of salome launcher.
154     :rtype: str
155     """
156     check_config_has_application(config)
157     if 'profile' in config.APPLICATION and 'launcher_name' in config.APPLICATION.profile:
158         launcher_name = config.APPLICATION.profile.launcher_name
159     else:
160         launcher_name = 'salome'
161
162     return launcher_name
163
164 def get_log_path(config):
165     """\
166     Returns the path of the logs.
167     
168     :param config Config: The global Config instance.
169     :return: The path of the logs.
170     :rtype: str
171     """
172     if "log_dir" not in config.LOCAL:
173         local_file_path = os.path.join(config.VARS.salometoolsway,
174                                       "data",
175                                       "local.pyconf")
176         msg = _("Please define a log_dir in the file %s" % local_file_path)
177         raise SatException(msg)
178       
179     log_dir_path = os.path.abspath(config.LOCAL.log_dir)
180     
181     return log_dir_path
182
183 def get_salome_version(config):
184     if hasattr(config.APPLICATION, 'version_salome'):
185         Version = config.APPLICATION.version_salome
186     else:
187         KERNEL_info = product.get_product_config(config, "KERNEL")
188         VERSION = os.path.join(
189                             KERNEL_info.install_dir,
190                             "bin",
191                             "salome",
192                             "VERSION")
193         if not os.path.isfile(VERSION):
194             return None
195             
196         fVERSION = open(VERSION)
197         Version = fVERSION.readline()
198         fVERSION.close()
199         
200     VersionSalome = int(only_numbers(Version))    
201     return VersionSalome
202
203 def only_numbers(str_num):
204     return ''.join([nb for nb in str_num if nb in '0123456789'] or '0')
205
206 def read_config_from_a_file(filePath):
207         try:
208             cfg_file = pyconf.Config(filePath)
209         except pyconf.ConfigError as e:
210             raise SatException(_("Error in configuration file: %(file)s\n  %(error)s") % \
211                 { 'file': filePath, 'error': str(e) })
212         return cfg_file
213
214 def get_tmp_filename(cfg, name):
215     if not os.path.exists(cfg.VARS.tmp_root):
216         os.makedirs(cfg.VARS.tmp_root)
217
218     return os.path.join(cfg.VARS.tmp_root, name)
219
220 ##
221 # Utils class to simplify path manipulations.
222 class Path:
223     def __init__(self, path):
224         self.path = str(path)
225
226     def __add__(self, other):
227         return Path(os.path.join(self.path, str(other)))
228
229     def __abs__(self):
230         return Path(os.path.abspath(self.path))
231
232     def __str__(self):
233         return self.path
234
235     def __eq__(self, other):
236         return self.path == other.path
237
238     def exists(self):
239         return self.islink() or os.path.exists(self.path)
240
241     def islink(self):
242         return os.path.islink(self.path)
243
244     def isdir(self):
245         return os.path.isdir(self.path)
246
247     def isfile(self):
248         return os.path.isfile(self.path)
249
250     def list(self):
251         return [Path(p) for p in os.listdir(self.path)]
252
253     def dir(self):
254         return Path(os.path.dirname(self.path))
255
256     def base(self):
257         return Path(os.path.basename(self.path))
258
259     def make(self, mode=None):
260         os.makedirs(self.path)        
261         if mode:
262             os.chmod(self.path, mode)
263         
264     def chmod(self, mode):
265         os.chmod(self.path, mode)
266
267     def rm(self):    
268         if self.islink():
269             os.remove(self.path)
270         else:
271             shutil.rmtree( self.path, onerror = handleRemoveReadonly )
272
273     def copy(self, path, smart=False):
274         if not isinstance(path, Path):
275             path = Path(path)
276
277         if os.path.islink(self.path):
278             return self.copylink(path)
279         elif os.path.isdir(self.path):
280             return self.copydir(path, smart)
281         else:
282             return self.copyfile(path)
283
284     def smartcopy(self, path):
285         return self.copy(path, True)
286
287     def readlink(self):
288         if self.islink():
289             return os.readlink(self.path)
290         else:
291             return False
292
293     def symlink(self, path):
294         try:
295             os.symlink(str(path), self.path)
296             return True
297         except:
298             return False
299
300     def copylink(self, path):
301         try:
302             os.symlink(os.readlink(self.path), str(path))
303             return True
304         except:
305             return False
306
307     def copydir(self, dst, smart=False):
308         try:
309             names = self.list()
310
311             if not dst.exists():
312                 dst.make()
313
314             for name in names:
315                 if name == dst:
316                     continue
317                 if smart and (str(name) in [".git", "CVS", ".svn"]):
318                     continue
319                 srcname = self + name
320                 dstname = dst + name
321                 srcname.copy(dstname, smart)
322             return True
323         except:
324             return False
325
326     def copyfile(self, path):
327         try:
328             shutil.copy2(self.path, str(path))
329             return True
330         except:
331             return False
332
333 def find_file_in_lpath(file_name, lpath, additional_dir = ""):
334     """\
335     Find in all the directories in lpath list the file that has the same name
336     as file_name. 
337     If it is found 
338     then return the full path of the file
339     else return False.
340  
341     The additional_dir (optional) is the name of the directory to add to all 
342     paths in lpath.
343     
344     :param file_name str: The file name to search
345     :param lpath List: The list of directories where to search
346     :param additional_dir str: The name of the additional directory
347     :return: the full path of the file or False if not found
348     :rtype: str
349     """
350     for directory in lpath:
351         dir_complete = os.path.join(directory, additional_dir)
352         if not os.path.isdir(directory) or not os.path.isdir(dir_complete):
353             continue
354         l_files = os.listdir(dir_complete)
355         for file_n in l_files:
356             if file_n == file_name:
357                 return os.path.join(dir_complete, file_name)
358     return False
359
360 def handleRemoveReadonly(func, path, exc):
361     excvalue = exc[1]
362     if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
363         os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
364         func(path)
365     else:
366         raise
367
368 def deepcopy_list(input_list):
369     """\
370     Do a deep copy of a list
371     
372     :param input_list List: The list to copy
373     :return: The copy of the list
374     :rtype: List
375     """
376     res = []
377     for elem in input_list:
378         res.append(elem)
379     return res
380
381 def remove_item_from_list(input_list, item):
382     """\
383     Remove all occurences of item from input_list
384     
385     :param input_list List: The list to modify
386     :return: The without any item
387     :rtype: List
388     """
389     res = []
390     for elem in input_list:
391         if elem == item:
392             continue
393         res.append(elem)
394     return res
395
396 def parse_date(date):
397     """\
398     Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss.
399     
400     :param date str: The date to transform
401     :return: The date in the new format
402     :rtype: str
403     """
404     if len(date) != 15:
405         return date
406     res = "%s-%s-%s %s:%s:%s" % (date[0:4],
407                                  date[4:6],
408                                  date[6:8],
409                                  date[9:11],
410                                  date[11:13],
411                                  date[13:])
412     return res
413
414 def merge_dicts(*dict_args):
415     """\
416     Given any number of dicts, shallow copy and merge into a new dict,
417     precedence goes to key value pairs in latter dicts.
418     """
419     result = {}
420     for dictionary in dict_args:
421         result.update(dictionary)
422     return result
423
424 def replace_in_file(filein, strin, strout):
425     """Replace <strin> by <strout> in file <filein>"""
426     shutil.move(filein, filein + "_old")
427     fileout= filein
428     filein = filein + "_old"
429     fin = open(filein, "r")
430     fout = open(fileout, "w")
431     for line in fin:
432         fout.write(line.replace(strin, strout))
433
434 def get_property_in_product_cfg(product_cfg, pprty):
435     if not "properties" in product_cfg:
436         return None
437     if not pprty in product_cfg.properties:
438         return None
439     return product_cfg.properties[pprty]