1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2022 EDF R&D
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.
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.
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
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 Informations sur le code et la plateforme, et mise à jour des chemins.
26 La classe "PlatformInfo" permet de récupérer les informations générales sur
27 le code et la plateforme sous forme de strings, ou d'afficher directement
28 les informations disponibles par les méthodes. L'impression directe d'un
29 objet de cette classe affiche les informations minimales. Par exemple :
31 print(PlatformInfo().getVersion())
32 created = PlatformInfo().getDate()
34 La classe "PathManagement" permet de mettre à jour les chemins système pour
35 ajouter les outils numériques, matrices... On l'utilise en instanciant
36 simplement cette classe, sans meme récupérer d'objet :
39 La classe "SystemUsage" permet de sous Unix les différentes tailles
40 mémoires du process courant. Ces tailles peuvent être assez variables et
41 dépendent de la fiabilité des informations du système dans le suivi des
44 __author__ = "Jean-Philippe ARGAUD"
54 # ==============================================================================
55 class PlatformInfo(object):
57 Rassemblement des informations sur le code et la plateforme
64 "Retourne le nom de l'application"
65 import daCore.version as dav
69 "Retourne le numéro de la version"
70 import daCore.version as dav
74 "Retourne la date de création de la version"
75 import daCore.version as dav
79 "Retourne l'année de création de la version"
80 import daCore.version as dav
83 def getSystemInformation(self, __prefix=""):
85 __msg += "\n%s%30s : %s" %(__prefix,"platform.system",platform.system())
86 __msg += "\n%s%30s : %s" %(__prefix,"sys.platform",sys.platform)
87 __msg += "\n%s%30s : %s" %(__prefix,"platform.version",platform.version())
88 __msg += "\n%s%30s : %s" %(__prefix,"platform.platform",platform.platform())
89 __msg += "\n%s%30s : %s" %(__prefix,"platform.machine",platform.machine())
90 if len(platform.processor())>0:
91 __msg += "\n%s%30s : %s" %(__prefix,"platform.processor",platform.processor())
93 if sys.platform.startswith('linux'):
94 if hasattr(platform, 'linux_distribution'):
95 __msg += "\n%s%30s : %s" %(__prefix,
96 "platform.linux_distribution",str(platform.linux_distribution()))
97 elif hasattr(platform, 'dist'):
98 __msg += "\n%s%30s : %s" %(__prefix,"platform.dist",str(platform.dist()))
99 elif sys.platform.startswith('darwin'):
100 if hasattr(platform, 'mac_ver'):
101 __macosxv = {'5': 'Leopard', '6': 'Snow Leopard', '7': 'Lion',
102 '8': 'Mountain Lion', '9': 'Mavericks', '10': 'Yosemite',
103 '11': 'El Capitan', '12': 'Sierra'}
104 for key in __macosxv:
105 if (platform.mac_ver()[0].split('.')[1] == key):
106 __msg += "\n%s%30s : %s" %(__prefix,
107 "platform.mac_ver",str(platform.mac_ver()[0]+"(" + macosx_dict[key]+")"))
108 elif hasattr(platform, 'dist'):
109 __msg += "\n%s%30s : %s" %(__prefix,"platform.dist",str(platform.dist()))
110 elif os.name == 'nt':
111 __msg += "\n%s%30s : %s" %(__prefix,"platform.win32_ver",platform.win32_ver()[1])
114 __msg += "\n%s%30s : %s" %(__prefix,"platform.python_implementation",platform.python_implementation())
115 __msg += "\n%s%30s : %s" %(__prefix,"sys.executable",sys.executable)
116 __msg += "\n%s%30s : %s" %(__prefix,"sys.version",sys.version.replace('\n',''))
117 __msg += "\n%s%30s : %s" %(__prefix,"sys.getfilesystemencoding",str(sys.getfilesystemencoding()))
118 __msg += "\n%s%30s : %s" %(__prefix,"locale.getdefaultlocale",str(locale.getdefaultlocale()))
120 __msg += "\n%s%30s : %s" %(__prefix,"os.cpu_count",os.cpu_count())
121 if hasattr(os, 'sched_getaffinity'):
122 __msg += "\n%s%30s : %s" %(__prefix,"len(os.sched_getaffinity(0))",len(os.sched_getaffinity(0)))
124 __msg += "\n%s%30s : %s" %(__prefix,"len(os.sched_getaffinity(0))","Unsupported on this platform")
126 __msg += "\n%s%30s : %s" %(__prefix,"platform.node",platform.node())
127 __msg += "\n%s%30s : %s" %(__prefix,"os.path.expanduser",os.path.expanduser('~'))
130 def getPythonVersion(self):
131 "Retourne la version de python disponible"
132 return ".".join([str(x) for x in sys.version_info[0:3]]) # map(str,sys.version_info[0:3]))
134 def getNumpyVersion(self):
135 "Retourne la version de numpy disponible"
137 return numpy.version.version
139 def getScipyVersion(self):
140 "Retourne la version de scipy disponible"
142 __version = scipy.version.version
147 def getMatplotlibVersion(self):
148 "Retourne la version de matplotlib disponible"
150 __version = matplotlib.__version__
155 def getGnuplotVersion(self):
156 "Retourne la version de gnuplotpy disponible"
158 __version = Gnuplot.__version__
163 def getSphinxVersion(self):
164 "Retourne la version de sphinx disponible"
166 __version = sphinx.__version__
171 def getNloptVersion(self):
172 "Retourne la version de nlopt disponible"
174 __version = "%s.%s.%s"%(
175 nlopt.version_major(),
176 nlopt.version_minor(),
177 nlopt.version_bugfix(),
183 def getCurrentMemorySize(self):
184 "Retourne la taille mémoire courante utilisée"
187 def MaximumPrecision(self):
188 "Retourne la precision maximale flottante pour Numpy"
191 numpy.array([1.,], dtype='float128')
197 def MachinePrecision(self):
198 # Alternative sans module :
202 # eps = (1.0 + eps/2) - 1.0
203 return sys.float_info.epsilon
206 import daCore.version as dav
207 return "%s %s (%s)"%(dav.name,dav.version,dav.date)
209 # ==============================================================================
213 import scipy.optimize
220 has_matplotlib = True
222 has_matplotlib = False
248 has_salome = bool( "ROOT_SALOME" in os.environ )
249 has_yacs = bool( "YACS_ROOT_DIR" in os.environ )
250 has_adao = bool( "ADAO_ROOT_DIR" in os.environ )
251 has_eficas = bool( "EFICAS_ROOT_DIR" in os.environ )
253 # ==============================================================================
254 def uniq( __sequence ):
256 Fonction pour rendre unique chaque élément d'une liste, en préservant l'ordre
259 return [x for x in __sequence if x not in __seen and not __seen.add(x)]
261 def isIterable( __sequence, __check = False, __header = "" ):
263 Vérification que l'argument est un itérable interne.
264 Remarque : pour permettre le test correct en MultiFonctions,
265 - Ne pas accepter comme itérable un "numpy.ndarray"
266 - Ne pas accepter comme itérable avec hasattr(__sequence, "__iter__")
268 if isinstance( __sequence, (list, tuple, map, dict) ):
270 elif type(__sequence).__name__ in ('generator','range'):
272 elif "_iterator" in type(__sequence).__name__:
276 if __check and not __isOk:
277 raise TypeError("Not iterable or unkown input type%s: %s"%(__header, type(__sequence),))
280 def date2int( __date, __lang="FR" ):
282 Fonction de secours, conversion pure : dd/mm/yy hh:mm ---> int(yyyymmddhhmm)
284 __date = __date.strip()
285 if __date.count('/') == 2 and __date.count(':') == 0 and __date.count(' ') == 0:
286 d,m,y = __date.split("/")
287 __number = (10**4)*int(y)+(10**2)*int(m)+int(d)
288 elif __date.count('/') == 2 and __date.count(':') == 1 and __date.count(' ') > 0:
289 part1, part2 = __date.split()
290 d,m,y = part1.strip().split("/")
291 h,n = part2.strip().split(":")
292 __number = (10**8)*int(y)+(10**6)*int(m)+(10**4)*int(d)+(10**2)*int(h)+int(n)
294 raise ValueError("Cannot convert \"%s\" as a D/M/Y H:M date"%d)
297 def strvect2liststr( __strvect ):
299 Fonction de secours, conversion d'une chaîne de caractères de
300 représentation de vecteur en une liste de chaînes de caractères de
301 représentation de flottants
303 for s in ("array", "matrix", "list", "tuple", "[", "]", "(", ")"):
304 __strvect = __strvect.replace(s,"") # Rien
306 __strvect = __strvect.replace(s," ") # Blanc
307 return __strvect.split()
309 def strmatrix2liststr( __strvect ):
311 Fonction de secours, conversion d'une chaîne de caractères de
312 représentation de matrice en une liste de chaînes de caractères de
313 représentation de flottants
315 for s in ("array", "matrix", "list", "tuple", "[", "(", "'", '"'):
316 __strvect = __strvect.replace(s,"") # Rien
317 __strvect = __strvect.replace(","," ") # Blanc
319 __strvect = __strvect.replace(s,";") # "]" et ")" par ";"
320 __strvect = re.sub(';\s*;',';',__strvect)
321 __strvect = __strvect.rstrip(";") # Après ^ et avant v
322 __strmat = [l.split() for l in __strvect.split(";")]
325 def checkFileNameConformity( __filename, __warnInsteadOfPrint=True ):
326 if sys.platform.startswith("win") and len(__filename) > 256:
328 __msg = (" For some shared or older file systems on Windows, a file "+\
329 "name longer than 256 characters can lead to access problems."+\
330 "\n The name of the file in question is the following:"+\
331 "\n %s")%(__filename,)
332 if __warnInsteadOfPrint: logging.warning(__msg)
339 def checkFileNameImportability( __filename, __warnInsteadOfPrint=True ):
340 if str(__filename).count(".") > 1:
342 __msg = (" The file name contains %i point(s) before the extension "+\
343 "separator, which can potentially lead to problems when "+\
344 "importing this file into Python, as it can then be recognized "+\
345 "as a sub-module (generating a \"ModuleNotFoundError\"). If it "+\
346 "is intentional, make sure that there is no module with the "+\
347 "same name as the part before the first point, and that there is "+\
348 "no \"__init__.py\" file in the same directory."+\
349 "\n The name of the file in question is the following:"+\
350 "\n %s")%(int(str(__filename).count(".")-1), __filename)
351 if __warnInsteadOfPrint is None: pass
352 elif __warnInsteadOfPrint: logging.warning(__msg)
359 # ==============================================================================
360 class PathManagement(object):
362 Mise à jour du path système pour les répertoires d'outils
365 "Déclaration des répertoires statiques"
366 parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
368 self.__paths["daNumerics"] = os.path.join(parent,"daNumerics")
370 for v in self.__paths.values():
371 sys.path.insert(0, v )
373 # Conserve en unique exemplaire chaque chemin
374 sys.path = uniq( sys.path )
379 Renvoie le dictionnaire des chemins ajoutés
383 # ==============================================================================
384 class SystemUsage(object):
386 Permet de récupérer les différentes tailles mémoires du process courant
389 # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc
390 # plutôt : http://code.activestate.com/recipes/286222/ et Wikipedia
392 _proc_status = '/proc/%d/status' % os.getpid()
393 _memo_status = '/proc/meminfo'
395 'o' : 1.0, # Multiples SI de l'octet
399 'kio': 1024.0, # Multiples binaires de l'octet
400 'Mio': 1024.0*1024.0,
401 'Gio': 1024.0*1024.0*1024.0,
402 'B': 1.0, # Multiples binaires du byte=octet
404 'MB' : 1024.0*1024.0,
405 'GB' : 1024.0*1024.0*1024.0,
412 def _VmA(self, VmKey, unit):
413 "Lecture des paramètres mémoire de la machine"
415 t = open(self._memo_status)
419 return 0.0 # non-Linux?
420 i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
421 v = v[i:].split(None, 3) # whitespace
423 return 0.0 # invalid format?
424 # convert Vm value to bytes
425 mem = float(v[1]) * self._scale[v[2]]
426 return mem / self._scale[unit]
428 def getAvailablePhysicalMemory(self, unit="o"):
429 "Renvoie la mémoire physique utilisable en octets"
430 return self._VmA('MemTotal:', unit)
432 def getAvailableSwapMemory(self, unit="o"):
433 "Renvoie la mémoire swap utilisable en octets"
434 return self._VmA('SwapTotal:', unit)
436 def getAvailableMemory(self, unit="o"):
437 "Renvoie la mémoire totale (physique+swap) utilisable en octets"
438 return self._VmA('MemTotal:', unit) + self._VmA('SwapTotal:', unit)
440 def getUsableMemory(self, unit="o"):
441 """Renvoie la mémoire utilisable en octets
442 Rq : il n'est pas sûr que ce décompte soit juste...
444 return self._VmA('MemFree:', unit) + self._VmA('SwapFree:', unit) + \
445 self._VmA('Cached:', unit) + self._VmA('SwapCached:', unit)
447 def _VmB(self, VmKey, unit):
448 "Lecture des paramètres mémoire du processus"
450 t = open(self._proc_status)
454 return 0.0 # non-Linux?
455 i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
456 v = v[i:].split(None, 3) # whitespace
458 return 0.0 # invalid format?
459 # convert Vm value to bytes
460 mem = float(v[1]) * self._scale[v[2]]
461 return mem / self._scale[unit]
463 def getUsedMemory(self, unit="o"):
464 "Renvoie la mémoire résidente utilisée en octets"
465 return self._VmB('VmRSS:', unit)
467 def getVirtualMemory(self, unit="o"):
468 "Renvoie la mémoire totale utilisée en octets"
469 return self._VmB('VmSize:', unit)
471 def getUsedStacksize(self, unit="o"):
472 "Renvoie la taille du stack utilisé en octets"
473 return self._VmB('VmStk:', unit)
475 def getMaxUsedMemory(self, unit="o"):
476 "Renvoie la mémoire résidente maximale mesurée"
477 return self._VmB('VmHWM:', unit)
479 def getMaxVirtualMemory(self, unit="o"):
480 "Renvoie la mémoire totale maximale mesurée"
481 return self._VmB('VmPeak:', unit)
483 # ==============================================================================
484 if __name__ == "__main__":
485 print('\n AUTODIAGNOSTIC\n')