Salome HOME
Minor source update for OM compatibility
[modules/adao.git] / src / daComposant / daCore / PlatformInfo.py
index 6e50e12d711a12301269a5bd8df82dae7a1c9180..84d961ebe6aea1988048e8904ae423be73828e06 100644 (file)
-#-*-coding:iso-8859-1-*-
+# -*- coding: utf-8 -*-
 #
-#  Copyright (C) 2008-2009  EDF R&D
+# Copyright (C) 2008-2024 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
 #
-__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
+# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
+
+"""
+    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 même 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 - Mars 2008"
+__author__ = "Jean-Philippe ARGAUD"
+__all__ = []
 
 import os
+import sys
+import platform
+import socket
+import locale
+import logging
+import re
+import numpy
 
 # ==============================================================================
-class PlatformInfo:
+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)]
+
+class PathManagement(object):
+    """
+    Mise à jour du path système pour les répertoires d'outils
+    """
+    __slots__ = ("__paths")
+
+    def __init__(self):
+        "Déclaration des répertoires statiques"
+        parent = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
+        self.__paths = {}
+        self.__paths["daNumerics"] = os.path.join(parent, "daNumerics")
+        self.__paths["pst4mod"] = os.path.join(parent, "daNumerics", "pst4mod")
+        #
+        for v in self.__paths.values():
+            if os.path.isdir(v):
+                sys.path.insert(0, v )
+        #
+        # Conserve en unique exemplaire chaque chemin
+        sys.path = uniq( sys.path )
+        del parent
+
+    def getpaths(self):
+        """
+        Renvoie le dictionnaire des chemins ajoutés
+        """
+        return self.__paths
+
+# ==============================================================================
+class PlatformInfo(object):
     """
     Rassemblement des informations sur le code et la plateforme
     """
+    __slots__ = ("has_salome", "has_yacs", "has_adao", "has_eficas")
+
+    def __init__(self):
+        "Sans effet"
+        self.has_salome = bool( "SALOME_ROOT_DIR" in os.environ )
+        self.has_yacs   = bool(   "YACS_ROOT_DIR" in os.environ )
+        self.has_adao   = bool(   "ADAO_ROOT_DIR" in os.environ )
+        self.has_eficas = bool( "EFICAS_ROOT_DIR" in os.environ )
+        PathManagement()
+
     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()))  # noqa: E128
+            elif hasattr(platform, 'dist'):
+                __msg += "\n%s%30s : %s"%(__prefix,
+                    "platform.dist", str(platform.dist()))  # noqa: E128
+        elif sys.platform.startswith('darwin'):
+            if hasattr(platform, 'mac_ver'):
+                # https://fr.wikipedia.org/wiki/MacOS
+                __macosxv10 = {
+                    '0' : 'Cheetah',      '1' : 'Puma',        '2' : 'Jaguar',         # noqa: E241,E203
+                    '3' : 'Panther',      '4' : 'Tiger',       '5' : 'Leopard',        # noqa: E241,E203
+                    '6' : 'Snow Leopard', '7' : 'Lion',        '8' : 'Mountain Lion',  # noqa: E241,E203
+                    '9' : 'Mavericks',    '10': 'Yosemite',    '11': 'El Capitan',     # noqa: E241,E203
+                    '12': 'Sierra',       '13': 'High Sierra', '14': 'Mojave',         # noqa: E241,E203
+                    '15': 'Catalina',
+                }
+                for key in __macosxv10:
+                    __details = platform.mac_ver()[0].split('.')
+                    if (len(__details) > 0) and (__details[1] == key):
+                        __msg += "\n%s%30s : %s"%(__prefix,
+                            "platform.mac_ver", str(platform.mac_ver()[0] + "(" + __macosxv10[key] + ")"))  # noqa: E128
+                __macosxv11 = {
+                    '11': 'Big Sur',      '12': 'Monterey',    '13': 'Ventura',  # noqa: E241
+                    '14': 'Sonoma',       '15': 'Sequoia',                       # noqa: E241
+                }
+                for key in __macosxv11:
+                    __details = platform.mac_ver()[0].split('.')
+                    if (__details[0] == key):
+                        __msg += "\n%s%30s : %s"%(__prefix,
+                            "platform.mac_ver", str(platform.mac_ver()[0] + "(" + __macosxv11[key] + ")"))  # noqa: E128
+            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()))
+        if sys.version_info.major == 3 and sys.version_info.minor < 11:  # Python 3.10
+            __msg += "\n%s%30s : %s"%(__prefix, "locale.getdefaultlocale", str(locale.getdefaultlocale()))
+        else:
+            __msg += "\n%s%30s : %s"%(__prefix, "locale.getlocale", str(locale.getlocale()))
+        __msg += "\n"
+        __msg += "\n%s%30s : %s"%(__prefix, "os.cpu_count", os.cpu_count())
+        if hasattr(os, 'sched_getaffinity'):
+            __msg += "\n%s%30s : %s"%(__prefix, "len(os.sched_getaffinity(0))", len(os.sched_getaffinity(0)))
+        else:
+            __msg += "\n%s%30s : %s"%(__prefix, "len(os.sched_getaffinity(0))", "Unsupported on this platform")
+        __msg += "\n"
+        __msg += "\n%s%30s : %s"%(__prefix, "platform.node", platform.node())
+        __msg += "\n%s%30s : %s"%(__prefix, "socket.getfqdn", socket.getfqdn())
+        __msg += "\n%s%30s : %s"%(__prefix, "os.path.expanduser", os.path.expanduser('~'))
+        return __msg
+
+    def getApplicationInformation(self, __prefix=""):
+        __msg  = ""
+        __msg += "\n%s%30s : %s"%(__prefix, "ADAO version", self.getVersion())
+        __msg += "\n"
+        __msg += "\n%s%30s : %s"%(__prefix, "Python version", self.getPythonVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "Numpy version", self.getNumpyVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "Scipy version", self.getScipyVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "NLopt version", self.getNloptVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "MatplotLib version", self.getMatplotlibVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "GnuplotPy version", self.getGnuplotVersion())
+        __msg += "\n"
+        __msg += "\n%s%30s : %s"%(__prefix, "Pandas version", self.getPandasVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "Fmpy version", self.getFmpyVersion())
+        __msg += "\n%s%30s : %s"%(__prefix, "Sphinx version", self.getSphinxVersion())
+        return __msg
+
+    def getAllInformation(self, __prefix="", __title="Whole system information"):
+        __msg  = ""
+        if len(__title) > 0:
+            __msg += "\n" + "=" * 80 + "\n" + __title + "\n" + "=" * 80 + "\n"
+        __msg += self.getSystemInformation(__prefix)
+        __msg += "\n"
+        __msg += self.getApplicationInformation(__prefix)
+        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]))
+
+    # Tests des modules système
+
+    def _has_numpy(self):
+        try:
+            import numpy  # noqa: F401
+            has_numpy = True
+        except ImportError:
+            raise ImportError("Numpy is not available, despites the fact it is mandatory.")
+        return has_numpy
+    has_numpy = property(fget = _has_numpy)
+
+    def _has_scipy(self):
+        try:
+            import scipy
+            import scipy.version
+            import scipy.optimize  # noqa: F401
+            has_scipy = True
+        except ImportError:
+            has_scipy = False
+        return has_scipy
+    has_scipy = property(fget = _has_scipy)
+
+    def _has_matplotlib(self):
+        try:
+            import matplotlib  # noqa: F401
+            has_matplotlib = True
+        except ImportError:
+            has_matplotlib = False
+        return has_matplotlib
+    has_matplotlib = property(fget = _has_matplotlib)
+
+    def _has_sphinx(self):
+        try:
+            import sphinx  # noqa: F401
+            has_sphinx = True
+        except ImportError:
+            has_sphinx = False
+        return has_sphinx
+    has_sphinx = property(fget = _has_sphinx)
+
+    def _has_nlopt(self):
+        try:
+            import nlopt  # noqa: F401
+            has_nlopt = True
+        except ImportError:
+            has_nlopt = False
+        return has_nlopt
+    has_nlopt = property(fget = _has_nlopt)
+
+    def _has_pandas(self):
+        try:
+            import pandas  # noqa: F401
+            has_pandas = True
+        except ImportError:
+            has_pandas = False
+        return has_pandas
+    has_pandas = property(fget = _has_pandas)
+
+    def _has_sdf(self):
+        try:
+            import sdf  # noqa: F401
+            has_sdf = True
+        except ImportError:
+            has_sdf = False
+        return has_sdf
+    has_sdf = property(fget = _has_sdf)
+
+    def _has_fmpy(self):
+        try:
+            import fmpy  # noqa: F401
+            has_fmpy = True
+        except ImportError:
+            has_fmpy = False
+        return has_fmpy
+    has_fmpy = property(fget = _has_fmpy)
+
+    def _has_buildingspy(self):
+        try:
+            import buildingspy  # noqa: F401
+            has_buildingspy = True
+        except ImportError:
+            has_buildingspy = False
+        return has_buildingspy
+    has_buildingspy = property(fget = _has_buildingspy)
+
+    def _has_control(self):
+        try:
+            import control  # noqa: F401
+            has_control = True
+        except ImportError:
+            has_control = False
+        return has_control
+    has_control = property(fget = _has_control)
+
+    def _has_modelicares(self):
+        try:
+            import modelicares  # noqa: F401
+            has_modelicares = True
+        except ImportError:
+            has_modelicares = False
+        return has_modelicares
+    has_modelicares = property(fget = _has_modelicares)
+
+    # Tests des modules locaux
+
+    def _has_gnuplot(self):
+        try:
+            import Gnuplot  # noqa: F401
+            has_gnuplot = True
+        except ImportError:
+            has_gnuplot = False
+        return has_gnuplot
+    has_gnuplot = property(fget = _has_gnuplot)
+
+    def _has_models(self):
+        try:
+            import Models  # noqa: F401
+            has_models = True
+        except ImportError:
+            has_models = False
+        return has_models
+    has_models = property(fget = _has_models)
+
+    def _has_pst4mod(self):
+        try:
+            import pst4mod  # noqa: F401
+            has_pst4mod = True
+        except ImportError:
+            has_pst4mod = False
+        return has_pst4mod
+    has_pst4mod = property(fget = _has_pst4mod)
+
+    # Versions
 
     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 self.has_scipy:
+            import scipy
+            __version = scipy.version.version
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getNloptVersion(self):
+        "Retourne la version de nlopt disponible"
+        if self.has_nlopt:
+            import nlopt
+            __version = "%s.%s.%s"%(
+                nlopt.version_major(),
+                nlopt.version_minor(),
+                nlopt.version_bugfix(),
+            )
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getMatplotlibVersion(self):
+        "Retourne la version de matplotlib disponible"
+        if self.has_matplotlib:
+            import matplotlib
+            __version = matplotlib.__version__
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getPandasVersion(self):
+        "Retourne la version de pandas disponible"
+        if self.has_pandas:
+            import pandas
+            __version = pandas.__version__
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getGnuplotVersion(self):
+        "Retourne la version de gnuplotpy disponible"
+        if self.has_gnuplot:
+            import Gnuplot
+            __version = Gnuplot.__version__
+        else:
+            __version = "0.0"
+        return __version
+
+    def getFmpyVersion(self):
+        "Retourne la version de fmpy disponible"
+        if self.has_fmpy:
+            import fmpy
+            __version = fmpy.__version__
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getSdfVersion(self):
+        "Retourne la version de sdf disponible"
+        if self.has_sdf:
+            import sdf
+            __version = sdf.__version__
+        else:
+            __version = "0.0.0"
+        return __version
+
+    def getSphinxVersion(self):
+        "Retourne la version de sphinx disponible"
+        if self.has_sphinx:
+            import sphinx
+            __version = sphinx.__version__
+        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 précision 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:
+def vt( __version ):
+    "Version transformée pour comparaison robuste, obtenue comme un tuple"
+    serie = []
+    for sv in re.split("[_.+-]", __version):
+        serie.append(sv.zfill(6))
+    return tuple(serie)
+
+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 interne.
+    Remarque : pour permettre le test correct en MultiFonctions,
+    - Ne pas accepter comme itérable un "numpy.ndarray"
+    - Ne pas accepter comme itérable avec hasattr(__sequence, "__iter__")
     """
-    def __init__(self):
-        import os, sys
-        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))
-        del parent
-    
-    def getpaths(self):
-        """
-        Renvoie le dictionnaire des chemins ajoutés
-        """
-        return self.__paths
+    if isinstance( __sequence, (list, tuple, map, dict) ):
+        __isOk = True
+    elif type(__sequence).__name__ in ('generator', 'range'):
+        __isOk = True
+    elif "_iterator" in type(__sequence).__name__:
+        __isOk = True
+    elif "itertools" in str(type(__sequence)):
+        __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: str, __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"%__date)
+    return __number
+
+def vfloat(__value: numpy.ndarray):
+    """
+    Conversion en flottant d'un vecteur de taille 1 et de dimensions quelconques
+    """
+    if hasattr(__value, "size") and __value.size == 1:
+        return float(__value.flat[0])
+    elif isinstance(__value, (float, int)):
+        return float(__value)
+    else:
+        raise ValueError("Error in converting multiple float values from array when waiting for only one")
+
+def strvect2liststr( __strvect ):
+    """
+    Fonction de secours, conversion d'une chaîne de caractères de
+    représentation de vecteur en une liste de chaînes de caractères de
+    représentation de flottants
+    """
+    for st in ("array", "matrix", "list", "tuple", "[", "]", "(", ")"):
+        __strvect = __strvect.replace(st, "")  # Rien
+    for st in (",", ";"):
+        __strvect = __strvect.replace(st, " ")  # Blanc
+    return __strvect.split()
+
+def strmatrix2liststr( __strvect ):
+    """
+    Fonction de secours, conversion d'une chaîne de caractères de
+    représentation de matrice en une liste de chaînes de caractères de
+    représentation de flottants
+    """
+    for st in ("array", "matrix", "list", "tuple", "[", "(", "'", '"'):
+        __strvect = __strvect.replace(st, "")  # Rien
+    __strvect = __strvect.replace(",", " ")  # Blanc
+    for st in ("]", ")"):
+        __strvect = __strvect.replace(st, ";")  # "]" et ")" par ";"
+    __strvect = re.sub(r';\s*;', r';', __strvect)
+    __strvect = __strvect.rstrip(";")  # Après ^ et avant v
+    __strmat = [__l.split() for __l in __strvect.split(";")]
+    return __strmat
+
+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 is None:
+            pass
+        elif __warnInsteadOfPrint:
+            logging.warning(__msg)
+        else:
+            print(__msg)
+    else:
+        __conform = True
+    #
+    return __conform
 
 # ==============================================================================
-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
     """
+    __slots__ = ()
     #
-    # 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          # noqa: E203
+        'ko' : 1.e3,                                       # noqa: E203
+        'Mo' : 1.e6,                                       # noqa: E203
+        'Go' : 1.e9,                                       # noqa: E203
+        'kio': 1024.0,  # Multiples binaires de l'octet    # noqa: E203
+        'Mio': 1024.0 * 1024.0,                            # noqa: E203
+        'Gio': 1024.0 * 1024.0 * 1024.0,                   # noqa: E203
+        'B'  : 1.0,     # Multiples binaires du byte=octet # noqa: E203
+        'kB' : 1024.0,                                     # noqa: E203
+        'MB' : 1024.0 * 1024.0,                            # noqa: E203
+        'GB' : 1024.0 * 1024.0 * 1024.0,                   # noqa: E203
+    }
+
+    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:
-            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
+        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
         if len(v) < 3:
-            return 0.0           # invalid format?
+            return 0.0            # invalid format?
         # convert Vm value to bytes
         mem = float(v[1]) * self._scale[v[2]]
         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)
-    #
+            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:
-            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
+        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
         if len(v) < 3:
-            return 0.0           # invalid format?
+            return 0.0            # invalid format?
         # convert Vm value to bytes
         mem = float(v[1]) * self._scale[v[2]]
         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
-    #
-    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
-    #
+        "Renvoie la mémoire résidente utilisée en octets"
+        return self._VmB('VmRSS:', unit)
+
+    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
-    #
-    def getMaxUsedResident(self):
-        "Renvoie la mémoire résidente maximale mesurée"
-        return self._max_rss
-    #
-    def getMaxUsedStacksize(self):
-        "Renvoie la mémoire du stack maximale mesurée"
-        return self._max_sta
+        "Renvoie la taille du stack utilisé en octets"
+        return self._VmB('VmStk:', unit)
+
+    def getMaxUsedMemory(self, unit="o"):
+        "Renvoie la mémoire résidente maximale mesurée"
+        return self._VmB('VmHWM:', unit)
+
+    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")