X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FdaComposant%2FdaCore%2FPlatformInfo.py;h=f08b80a57659ec7b0cbb9007425ef8563e96b5ef;hb=d15b67bed58051bd93e3ae300bbbf355720cd428;hp=8b905c7b4b6c8baa41e46688a1540ac84d46aabb;hpb=4a65d3472c5b087fb5eb400026e94f736254bd0d;p=modules%2Fadao.git diff --git a/src/daComposant/daCore/PlatformInfo.py b/src/daComposant/daCore/PlatformInfo.py index 8b905c7..f08b80a 100644 --- a/src/daComposant/daCore/PlatformInfo.py +++ b/src/daComposant/daCore/PlatformInfo.py @@ -1,144 +1,382 @@ -#-*-coding:iso-8859-1-*- +# -*- coding: utf-8 -*- # -# Copyright (C) 2008-2011 EDF R&D +# Copyright (C) 2008-2020 EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. # -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. # -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D +# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D -__doc__ = """ - Informations sur le code et la plateforme, et mise à jour des chemins - - La classe "PlatformInfo" permet de récupérer les informations générales sur +""" + Informations sur le code et la plateforme, et mise à jour des chemins + + La classe "PlatformInfo" permet de récupérer les informations générales sur le code et la plateforme sous forme de strings, ou d'afficher directement - les informations disponibles par les méthodes. L'impression directe d'un + les informations disponibles par les méthodes. L'impression directe d'un objet de cette classe affiche les informations minimales. Par exemple : - print PlatformInfo() - print PlatformInfo().getVersion() + print(PlatformInfo()) + print(PlatformInfo().getVersion()) created = PlatformInfo().getDate() - La classe "PathManagement" permet de mettre à jour les chemins système pour - ajouter les outils numériques, matrices... On l'utilise en instanciant - simplement cette classe, sans meme récupérer d'objet : + La classe "PathManagement" permet de mettre à jour les chemins système pour + ajouter les outils numériques, matrices... On l'utilise en instanciant + simplement cette classe, sans meme récupérer d'objet : PathManagement() + + La classe "SystemUsage" permet de sous Unix les différentes tailles + mémoires du process courant. Ces tailles peuvent être assez variables et + dépendent de la fiabilité des informations du système dans le suivi des + process. """ __author__ = "Jean-Philippe ARGAUD" +__all__ = [] import os +import sys +import platform +import locale +import logging # ============================================================================== -class PlatformInfo: +class PlatformInfo(object): """ Rassemblement des informations sur le code et la plateforme """ + def __init__(self): + "Sans effet" + pass + def getName(self): "Retourne le nom de l'application" - import version - return version.name + import daCore.version as dav + return dav.name def getVersion(self): - "Retourne le numéro de la version" - import version - return version.version + "Retourne le numéro de la version" + import daCore.version as dav + return dav.version def getDate(self): - "Retourne la date de création de la version" - import version - return version.date - + "Retourne la date de création de la version" + import daCore.version as dav + return dav.date + + def getYear(self): + "Retourne l'année de création de la version" + import daCore.version as dav + return dav.year + + def getSystemInformation(self, __prefix=""): + __msg = "" + __msg += "\n%s%30s : %s" %(__prefix,"platform.system",platform.system()) + __msg += "\n%s%30s : %s" %(__prefix,"sys.platform",sys.platform) + __msg += "\n%s%30s : %s" %(__prefix,"platform.version",platform.version()) + __msg += "\n%s%30s : %s" %(__prefix,"platform.platform",platform.platform()) + __msg += "\n%s%30s : %s" %(__prefix,"platform.machine",platform.machine()) + if len(platform.processor())>0: + __msg += "\n%s%30s : %s" %(__prefix,"platform.processor",platform.processor()) + # + if sys.platform.startswith('linux'): + if hasattr(platform, 'linux_distribution'): + __msg += "\n%s%30s : %s" %(__prefix, + "platform.linux_distribution",str(platform.linux_distribution())) + elif hasattr(platform, 'dist'): + __msg += "\n%s%30s : %s" %(__prefix,"platform.dist",str(platform.dist())) + elif sys.platform.startswith('darwin'): + if hasattr(platform, 'mac_ver'): + __macosxv = {'5': 'Leopard', '6': 'Snow Leopard', '7': 'Lion', + '8': 'Mountain Lion', '9': 'Mavericks', '10': 'Yosemite', + '11': 'El Capitan', '12': 'Sierra'} + for key in __macosxv: + if (platform.mac_ver()[0].split('.')[1] == key): + __msg += "\n%s%30s : %s" %(__prefix, + "platform.mac_ver",str(platform.mac_ver()[0]+"(" + macosx_dict[key]+")")) + elif hasattr(platform, 'dist'): + __msg += "\n%s%30s : %s" %(__prefix,"platform.dist",str(platform.dist())) + elif os.name == 'nt': + __msg += "\n%s%30s : %s" %(__prefix,"platform.win32_ver",platform.win32_ver()[1]) + # + __msg += "\n" + __msg += "\n%s%30s : %s" %(__prefix,"platform.python_implementation",platform.python_implementation()) + __msg += "\n%s%30s : %s" %(__prefix,"sys.executable",sys.executable) + __msg += "\n%s%30s : %s" %(__prefix,"sys.version",sys.version.replace('\n','')) + __msg += "\n%s%30s : %s" %(__prefix,"sys.getfilesystemencoding",str(sys.getfilesystemencoding())) + __msg += "\n%s%30s : %s" %(__prefix,"locale.getdefaultlocale",str(locale.getdefaultlocale())) + __msg += "\n" + __msg += "\n%s%30s : %s" %(__prefix,"platform.node",platform.node()) + __msg += "\n%s%30s : %s" %(__prefix,"os.path.expanduser",os.path.expanduser('~')) + return __msg + def getPythonVersion(self): - "Retourne la version de python utilisée" - import sys - return ".".join(map(str,sys.version_info[0:3])) + "Retourne la version de python disponible" + return ".".join([str(x) for x in sys.version_info[0:3]]) # map(str,sys.version_info[0:3])) def getNumpyVersion(self): - "Retourne la version de numpy utilisée" + "Retourne la version de numpy disponible" import numpy.version return numpy.version.version def getScipyVersion(self): - "Retourne la version de scipy utilisée" - import scipy.version - return scipy.version.version + "Retourne la version de scipy disponible" + if has_scipy: + __version = scipy.version.version + else: + __version = "0.0.0" + return __version + + def getMatplotlibVersion(self): + "Retourne la version de matplotlib disponible" + if has_matplotlib: + __version = matplotlib.__version__ + else: + __version = "0.0.0" + return __version + + def getGnuplotVersion(self): + "Retourne la version de gnuplotpy disponible" + if has_gnuplot: + __version = Gnuplot.__version__ + else: + __version = "0.0" + return __version + + def getSphinxVersion(self): + "Retourne la version de sphinx disponible" + if has_sphinx: + __version = sphinx.__version__ + else: + __version = "0.0.0" + return __version + + def getNloptVersion(self): + "Retourne la version de nlopt disponible" + if has_nlopt: + __version = "%s.%s.%s"%( + nlopt.version_major(), + nlopt.version_minor(), + nlopt.version_bugfix(), + ) + else: + __version = "0.0.0" + return __version def getCurrentMemorySize(self): - "Retourne la taille mémoire courante utilisée" + "Retourne la taille mémoire courante utilisée" return 1 + def MaximumPrecision(self): + "Retourne la precision maximale flottante pour Numpy" + import numpy + try: + numpy.array([1.,], dtype='float128') + mfp = 'float128' + except Exception: + mfp = 'float64' + return mfp + + def MachinePrecision(self): + # Alternative sans module : + # eps = 2.38 + # while eps > 0: + # old_eps = eps + # eps = (1.0 + eps/2) - 1.0 + return sys.float_info.epsilon + def __str__(self): - import version - return "%s %s (%s)"%(version.name,version.version,version.date) + import daCore.version as dav + return "%s %s (%s)"%(dav.name,dav.version,dav.date) # ============================================================================== -class PathManagement: +try: + import scipy + import scipy.version + import scipy.optimize + has_scipy = True +except ImportError: + has_scipy = False + +try: + import matplotlib + has_matplotlib = True +except ImportError: + has_matplotlib = False + +try: + import Gnuplot + has_gnuplot = True +except ImportError: + has_gnuplot = False + +try: + import sphinx + has_sphinx = True +except ImportError: + has_sphinx = False + +try: + import nlopt + has_nlopt = True +except ImportError: + has_nlopt = False + +try: + import sdf + has_sdf = True +except ImportError: + has_sdf = False + +has_salome = bool( "ROOT_SALOME" in os.environ ) +has_yacs = bool( "YACS_ROOT_DIR" in os.environ ) +has_adao = bool( "ADAO_ROOT_DIR" in os.environ ) +has_eficas = bool( "EFICAS_ROOT_DIR" in os.environ ) + +# ============================================================================== +def uniq( __sequence ): + """ + Fonction pour rendre unique chaque élément d'une liste, en préservant l'ordre + """ + __seen = set() + return [x for x in __sequence if x not in __seen and not __seen.add(x)] + +def isIterable( __sequence, __check = False, __header = "" ): """ - Mise à jour du path système pour les répertoires d'outils + Vérification que l'argument est un itérable + """ + if isinstance( __sequence, (list, tuple, map) ): + __isOk = True + elif type(__sequence).__name__ in ('generator','range'): + __isOk = True + elif "_iterator" in type(__sequence).__name__: + __isOk = True + else: + __isOk = False + if __check and not __isOk: + raise TypeError("Not iterable or unkown input type%s: %s"%(__header, type(__sequence),)) + return __isOk + +def date2int( __date, __lang="FR" ): + """ + Fonction de secours, conversion pure : dd/mm/yy hh:mm ---> int(yyyymmddhhmm) + """ + __date = __date.strip() + if __date.count('/') == 2 and __date.count(':') == 0 and __date.count(' ') == 0: + d,m,y = __date.split("/") + __number = (10**4)*int(y)+(10**2)*int(m)+int(d) + elif __date.count('/') == 2 and __date.count(':') == 1 and __date.count(' ') > 0: + part1, part2 = __date.split() + d,m,y = part1.strip().split("/") + h,n = part2.strip().split(":") + __number = (10**8)*int(y)+(10**6)*int(m)+(10**4)*int(d)+(10**2)*int(h)+int(n) + else: + raise ValueError("Cannot convert \"%s\" as a D/M/Y H:M date"%d) + return __number + +def checkFileNameConformity( __filename, __warnInsteadOfPrint=True ): + if sys.platform.startswith("win") and len(__filename) > 256: + __conform = False + __msg = (" For some shared or older file systems on Windows, a file "+\ + "name longer than 256 characters can lead to access problems."+\ + "\n The name of the file in question is the following:"+\ + "\n %s")%(__filename,) + if __warnInsteadOfPrint: logging.warning(__msg) + else: print(__msg) + else: + __conform = True + # + return __conform + +def checkFileNameImportability( __filename, __warnInsteadOfPrint=True ): + if str(__filename).count(".") > 1: + __conform = False + __msg = (" The file name contains %i point(s) before the extension "+\ + "separator, which can potentially lead to problems when "+\ + "importing this file into Python, as it can then be recognized "+\ + "as a sub-module (generating a \"ModuleNotFoundError\"). If it "+\ + "is intentional, make sure that there is no module with the "+\ + "same name as the part before the first point, and that there is "+\ + "no \"__init__.py\" file in the same directory."+\ + "\n The name of the file in question is the following:"+\ + "\n %s")%(int(str(__filename).count(".")-1), __filename) + if __warnInsteadOfPrint: logging.warning(__msg) + else: print(__msg) + else: + __conform = True + # + return __conform + +# ============================================================================== +class PathManagement(object): + """ + Mise à jour du path système pour les répertoires d'outils """ def __init__(self): - import os, sys + "Déclaration des répertoires statiques" parent = os.path.abspath(os.path.join(os.path.dirname(__file__),"..")) self.__paths = {} - self.__paths["daExternals"] = os.path.join(parent,"daExternals") - self.__paths["daMatrices"] = os.path.join(parent,"daMatrices") self.__paths["daNumerics"] = os.path.join(parent,"daNumerics") # for v in self.__paths.values(): sys.path.insert(0, v ) # # Conserve en unique exemplaire chaque chemin - sys.path = list(set(sys.path)) + sys.path = uniq( sys.path ) del parent - + def getpaths(self): """ - Renvoie le dictionnaire des chemins ajoutés + Renvoie le dictionnaire des chemins ajoutés """ return self.__paths # ============================================================================== -class SystemUsage: +class SystemUsage(object): """ - Permet de récupérer les différentes tailles mémoires du process courant + Permet de récupérer les différentes tailles mémoires du process courant """ # - # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc - # plutôt : http://code.activestate.com/recipes/286222/ et les infos de - # http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/en-US/Reference_Guide/s2-proc-meminfo.html + # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc + # plutôt : http://code.activestate.com/recipes/286222/ et Wikipedia # _proc_status = '/proc/%d/status' % os.getpid() _memo_status = '/proc/meminfo' _scale = { - 'o': 1.0, - 'ko': 1024.0, 'mo': 1024.0*1024.0, - 'Ko': 1024.0, 'Mo': 1024.0*1024.0, - 'B': 1.0, - 'kB': 1024.0, 'mB': 1024.0*1024.0, - 'KB': 1024.0, 'MB': 1024.0*1024.0, - } - _max_mem = 0 - _max_rss = 0 - _max_sta = 0 + 'o' : 1.0, # Multiples SI de l'octet + 'ko' : 1.e3, + 'Mo' : 1.e6, + 'Go' : 1.e9, + 'kio': 1024.0, # Multiples binaires de l'octet + 'Mio': 1024.0*1024.0, + 'Gio': 1024.0*1024.0*1024.0, + 'B': 1.0, # Multiples binaires du byte=octet + 'kB' : 1024.0, + 'MB' : 1024.0*1024.0, + 'GB' : 1024.0*1024.0*1024.0, + } + # + def __init__(self): + "Sans effet" + pass # def _VmA(self, VmKey, unit): + "Lecture des paramètres mémoire de la machine" try: t = open(self._memo_status) v = t.read() t.close() - except: + except IOError: return 0.0 # non-Linux? i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' v = v[i:].split(None, 3) # whitespace @@ -149,30 +387,31 @@ class SystemUsage: return mem / self._scale[unit] # def getAvailablePhysicalMemory(self, unit="o"): - "Renvoie la mémoire physique utilisable en octets" + "Renvoie la mémoire physique utilisable en octets" return self._VmA('MemTotal:', unit) # def getAvailableSwapMemory(self, unit="o"): - "Renvoie la mémoire swap utilisable en octets" + "Renvoie la mémoire swap utilisable en octets" return self._VmA('SwapTotal:', unit) # def getAvailableMemory(self, unit="o"): - "Renvoie la mémoire totale (physique+swap) utilisable en octets" + "Renvoie la mémoire totale (physique+swap) utilisable en octets" return self._VmA('MemTotal:', unit) + self._VmA('SwapTotal:', unit) # def getUsableMemory(self, unit="o"): - """Renvoie la mémoire utilisable en octets - Rq : il n'est pas sûr que ce décompte soit juste... + """Renvoie la mémoire utilisable en octets + Rq : il n'est pas sûr que ce décompte soit juste... """ return self._VmA('MemFree:', unit) + self._VmA('SwapFree:', unit) + \ self._VmA('Cached:', unit) + self._VmA('SwapCached:', unit) # def _VmB(self, VmKey, unit): + "Lecture des paramètres mémoire du processus" try: t = open(self._proc_status) v = t.read() t.close() - except: + except IOError: return 0.0 # non-Linux? i = v.index(VmKey) # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' v = v[i:].split(None, 3) # whitespace @@ -183,75 +422,25 @@ class SystemUsage: return mem / self._scale[unit] # def getUsedMemory(self, unit="o"): - "Renvoie la mémoire totale utilisée en octets" - mem = self._VmB('VmSize:', unit) - self._max_mem = max(self._max_mem, mem) - return mem + "Renvoie la mémoire résidente utilisée en octets" + return self._VmB('VmRSS:', unit) # - def getUsedResident(self, unit="o"): - "Renvoie la mémoire résidente utilisée en octets" - mem = self._VmB('VmRSS:', unit) - self._max_rss = max(self._max_rss, mem) - return mem + def getVirtualMemory(self, unit="o"): + "Renvoie la mémoire totale utilisée en octets" + return self._VmB('VmSize:', unit) # def getUsedStacksize(self, unit="o"): - "Renvoie la taille du stack utilisé en octets" - mem = self._VmB('VmStk:', unit) - self._max_sta = max(self._max_sta, mem) - return mem - # - def getMaxUsedMemory(self): - "Renvoie la mémoire totale maximale mesurée" - return self._max_mem + "Renvoie la taille du stack utilisé en octets" + return self._VmB('VmStk:', unit) # - def getMaxUsedResident(self): - "Renvoie la mémoire résidente maximale mesurée" - return self._max_rss + def getMaxUsedMemory(self, unit="o"): + "Renvoie la mémoire résidente maximale mesurée" + return self._VmB('VmHWM:', unit) # - def getMaxUsedStacksize(self): - "Renvoie la mémoire du stack maximale mesurée" - return self._max_sta + def getMaxVirtualMemory(self, unit="o"): + "Renvoie la mémoire totale maximale mesurée" + return self._VmB('VmPeak:', unit) # ============================================================================== if __name__ == "__main__": - print '\n AUTODIAGNOSTIC \n' - - print PlatformInfo() - print - p = PlatformInfo() - print "Les caractéristiques détaillées des applications et outils sont :" - print " - Application.......:",p.getName() - print " - Version...........:",p.getVersion() - print " - Date Application..:",p.getDate() - print " - Python............:",p.getPythonVersion() - print " - Numpy.............:",p.getNumpyVersion() - print " - Scipy.............:",p.getScipyVersion() - print - - p = PathManagement() - print "Les chemins ajoutés au système pour des outils :" - for k,v in p.getpaths().items(): - print " %12s : %s"%(k,os.path.basename(v)) - print - - m = SystemUsage() - print "La mémoire disponible est la suivante :" - print " - mémoire totale....: %4.1f Mo"%m.getAvailableMemory("Mo") - print " - mémoire physique..: %4.1f Mo"%m.getAvailablePhysicalMemory("Mo") - print " - mémoire swap......: %4.1f Mo"%m.getAvailableSwapMemory("Mo") - print " - utilisable........: %4.1f Mo"%m.getUsableMemory("Mo") - print "L'usage mémoire de cette exécution est le suivant :" - print " - mémoire totale....: %4.1f Mo"%m.getUsedMemory("Mo") - print " - mémoire résidente.: %4.1f Mo"%m.getUsedResident("Mo") - print " - taille de stack...: %4.1f Mo"%m.getUsedStacksize("Mo") - print "Création d'un objet range(1000000) et mesure mémoire" - x = range(1000000) - print " - mémoire totale....: %4.1f Mo"%m.getUsedMemory("Mo") - print "Destruction de l'objet et mesure mémoire" - del x - print " - mémoire totale....: %4.1f Mo"%m.getUsedMemory("Mo") - print "L'usage mémoire maximal de cette exécution est le suivant :" - print " - mémoire totale....: %4.1f Mo"%m.getMaxUsedMemory() - print " - mémoire résidente.: %4.1f Mo"%m.getMaxUsedResident() - print " - taille de stack...: %4.1f Mo"%m.getMaxUsedStacksize() - print + print('\n AUTODIAGNOSTIC\n')