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