Salome HOME
Merge V9 dans Master
[tools/eficas.git] / Noyau / N_utils.py
1 # coding=utf-8
2 # Copyright (C) 2007-2017   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19
20
21 """
22    Ce module contient des fonctions utilitaires
23 """
24
25 # Modules Python
26 from __future__ import absolute_import
27 from __future__ import print_function
28 from __future__ import division
29 try :
30    from builtins import str
31    from builtins import object
32 except :
33    pass
34 import sys
35
36 # Modules EFICAS
37 from .N_Exception import AsException
38 from .N_types import isInt, isFloat, isComplex, isStr, isSequence, isASSD
39 from .strfunc import getEncoding
40 import six
41
42 SEP = '_'
43
44 try :
45   cur_frame = sys._getframe
46 except :
47   print ('pb avec la version de python pour cur_frame = sys._getframe')
48
49 def calleeWhere(niveau=4):
50     """
51        recupere la position de l appel
52     """
53     frame = sys._getframe(niveau)
54     if frame == None:
55         return 0, "inconnu", 0, {}
56     try:
57         # Python 2.7 compile function does not accept unicode filename, so we encode it
58         # with the current locale encoding in order to have a correct traceback.
59         # Here, we convert it back to unicode.
60         filename = six.text_type(frame.f_code.co_filename, getEncoding())
61         return frame.fLineNo, filename, frame.f_code.co_firstlineno, frame.f_locals
62     except:
63         return 0, "inconnu", 0, {}
64
65
66 def AsType(a):
67     """
68        Retourne le type d'un concept (a) à partir
69        des caractéristiques de l'objet Python
70     """
71     if isSequence(a):
72         return AsType(a[0])
73     if isASSD(a):
74         return type(a)
75     if isFloat(a):
76         return "R"
77     if isInt(a):
78         return "I"
79     if isStr(a):
80         return "TXM"
81     if a == None:
82         return None
83     raise AsException("type inconnu: %r %s" % (a, type(a)))
84
85
86 def prbanner(s):
87     print(("*" * (len(s) + 10)))
88     print(("*" * 5 + s + "*" * 5))
89     print(("*" * (len(s) + 10)))
90
91
92 def repr_float(valeur):
93     """
94         Cette fonction représente le réel valeur comme une chaine de caractères
95         sous forme mantisse exposant si nécessaire cad si le nombre contient plus de
96         5 caractères
97         NB : valeur est un réel au format Python ou une chaine de caractères représentant un réel
98     """
99     if type(valeur) == str:
100         valeur = eval(valeur)
101     if valeur == 0.:
102         return '0.0'
103     if abs(valeur) > 1.:
104         if abs(valeur) < 10000.:
105             return repr(valeur)
106     else:
107         if abs(valeur) > 0.01:
108             return repr(valeur)
109     t = repr(valeur)
110     if t.find('e') != -1 or t.find('E') != -1:
111         # le réel est déjà sous forme mantisse exposant !
112         # --> on remplace e par E
113         t = t.replace('e', 'E')
114         # --> on doit encore vérifier que la mantisse contient bien un '.'
115         if t.find('.') != -1:
116             return t
117         else:
118             # -->il faut rajouter le point avant le E
119             t = t.replace('E', '.E')
120             return t
121     s = ''
122     neg = 0
123     if t[0] == '-':
124         s = s + t[0]
125         t = t[1:]
126     cpt = 0
127     if t[0].atof() == 0.:
128         # réel plus petit que 1
129         neg = 1
130         t = t[2:]
131         cpt = 1
132         while t[0].atof() == 0.:
133             cpt = cpt + 1
134             t = t[1:]
135         s = s + t[0] + '.'
136         for c in t[1:]:
137             s = s + c
138     else:
139         # réel plus grand que 1
140         s = s + t[0] + '.'
141         if t[1:].atof() == 0.:
142             l = t[1:].split('.')
143             cpt = len(l[0])
144         else:
145             r = 0
146             pt = 0
147             for c in t[1:]:
148                 r = r + 1
149                 if c != '.':
150                     if pt != 1:
151                         cpt = cpt + 1
152                     s = s + c
153                 else:
154                     pt = 1
155                     if r + 1 == len(t) or t[r + 1:].atof() == 0.:
156                         break
157     s = s + 'E' + neg * '-' + repr(cpt)
158     return s
159
160
161 def importObject(uri):
162     """Load and return a python object (class, function...).
163     Its `uri` looks like "mainpkg.subpkg.module.object", this means
164     that "mainpkg.subpkg.module" is imported and "object" is
165     the object to return.
166     """
167     path = uri.split('.')
168     modname = '.'.join(path[:-1])
169     if len(modname) == 0:
170         raise ImportError(u"invalid uri: %s" % uri)
171     mod = object = '?'
172     objname = path[-1]
173     try:
174         __import__(modname)
175         mod = sys.modules[modname]
176     except ImportError as err:
177         raise ImportError(
178             "can not import module : %s (%s)" % (modname, str(err)))
179     try:
180         object = getattr(mod, objname)
181     except AttributeError as err:
182         raise AttributeError("object (%s) not found in module '%s'. "
183                              "Module content is: %s" % (objname, modname, tuple(dir(mod))))
184     return object
185
186
187 class Singleton(object):
188
189     """Singleton implementation in python."""
190     # add _singleton_id attribute to the class to be independant of import
191     # path used
192     __inst = {}
193
194     def __new__(cls, *args, **kargs):
195         cls_id = getattr(cls, '_singleton_id', cls)
196         if Singleton.__inst.get(cls_id) is None:
197             Singleton.__inst[cls_id] = object.__new__(cls)
198         return Singleton.__inst[cls_id]
199
200
201 class Enum(object):
202
203     """
204     This class emulates a C-like enum for python. It is initialized with a list
205     of strings to be used as the enum symbolic keys. The enum values are automatically
206     generated as sequencing integer starting at 0.
207     """
208
209     def __init__(self, *keys):
210         """Constructor"""
211         self._dict_keys = {}
212         for inum, key in enumerate(keys):
213             setattr(self, key, 2 ** inum)
214             self._dict_keys[2 ** inum] = key
215
216     def exists(self, value):
217         """Tell if value is in the enumeration"""
218         return self.getId(value) is not None
219
220     def getId(self, value):
221         """Return the key associated to the given value"""
222         return self._dict_keys.get(value, None)