Salome HOME
sauvegarde doc
[tools/eficas.git] / Noyau / N_utils.py
1 # coding=utf-8
2 # Copyright (C) 2007-2013   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 import sys
27
28 # Modules EFICAS
29 from N_Exception import AsException
30 from N_types import is_int, is_float, is_complex, is_str, is_sequence, is_assd
31 from strfunc import get_encoding
32
33 SEP = '_'
34
35 try:
36     # Si la version de Python possède la fonction _getframe
37     # on l'utilise.
38     cur_frame = sys._getframe
39 except:
40     # Sinon on l'émule
41     def cur_frame(offset=0):
42         """ Retourne la frame d execution effective eventuellement en remontant
43             de offset niveaux dans la pile d execution
44             Si il y a moins de offset niveaux retourne None
45         """
46         try:
47             1 / 0
48         except:
49             frame = sys.exc_info()[2].tb_frame.f_back
50         while offset > 0:
51             if frame == None:
52                 return None
53             frame = frame.f_back
54             offset = offset - 1
55         return frame
56
57
58 def callee_where(niveau=4):
59     """
60        recupere la position de l appel
61     """
62     frame = cur_frame(niveau)
63     if frame == None:
64         return 0, "inconnu", 0, {}
65     try:
66         # Python 2.7 compile function does not accept unicode filename, so we encode it
67         # with the current locale encoding in order to have a correct traceback.
68         # Here, we convert it back to unicode.
69         filename = unicode(frame.f_code.co_filename, get_encoding())
70         return frame.f_lineno, filename, frame.f_code.co_firstlineno, frame.f_locals
71     except:
72         return 0, "inconnu", 0, {}
73
74
75 def AsType(a):
76     """
77        Retourne le type d'un concept (a) à partir
78        des caractéristiques de l'objet Python
79     """
80     if is_sequence(a):
81         return AsType(a[0])
82     if is_assd(a):
83         return type(a)
84     if is_float(a):
85         return "R"
86     if is_int(a):
87         return "I"
88     if is_str(a):
89         return "TXM"
90     if a == None:
91         return None
92     raise AsException("type inconnu: %r %s" % (a, type(a)))
93
94
95 def prbanner(s):
96     print "*" * (len(s) + 10)
97     print "*" * 5 + s + "*" * 5
98     print "*" * (len(s) + 10)
99
100
101 def repr_float(valeur):
102     """
103         Cette fonction représente le réel valeur comme une chaine de caractères
104         sous forme mantisse exposant si nécessaire cad si le nombre contient plus de
105         5 caractères
106         NB : valeur est un réel au format Python ou une chaine de caractères représentant un réel
107     """
108     if type(valeur) == str:
109         valeur = eval(valeur)
110     if valeur == 0.:
111         return '0.0'
112     if abs(valeur) > 1.:
113         if abs(valeur) < 10000.:
114             return repr(valeur)
115     else:
116         if abs(valeur) > 0.01:
117             return repr(valeur)
118     t = repr(valeur)
119     if t.find('e') != -1 or t.find('E') != -1:
120         # le réel est déjà sous forme mantisse exposant !
121         # --> on remplace e par E
122         t = t.replace('e', 'E')
123         # --> on doit encore vérifier que la mantisse contient bien un '.'
124         if t.find('.') != -1:
125             return t
126         else:
127             # -->il faut rajouter le point avant le E
128             t = t.replace('E', '.E')
129             return t
130     s = ''
131     neg = 0
132     if t[0] == '-':
133         s = s + t[0]
134         t = t[1:]
135     cpt = 0
136     if t[0].atof() == 0.:
137         # réel plus petit que 1
138         neg = 1
139         t = t[2:]
140         cpt = 1
141         while t[0].atof() == 0.:
142             cpt = cpt + 1
143             t = t[1:]
144         s = s + t[0] + '.'
145         for c in t[1:]:
146             s = s + c
147     else:
148         # réel plus grand que 1
149         s = s + t[0] + '.'
150         if t[1:].atof() == 0.:
151             l = t[1:].split('.')
152             cpt = len(l[0])
153         else:
154             r = 0
155             pt = 0
156             for c in t[1:]:
157                 r = r + 1
158                 if c != '.':
159                     if pt != 1:
160                         cpt = cpt + 1
161                     s = s + c
162                 else:
163                     pt = 1
164                     if r + 1 == len(t) or t[r + 1:].atof() == 0.:
165                         break
166     s = s + 'E' + neg * '-' + repr(cpt)
167     return s
168
169
170 def import_object(uri):
171     """Load and return a python object (class, function...).
172     Its `uri` looks like "mainpkg.subpkg.module.object", this means
173     that "mainpkg.subpkg.module" is imported and "object" is
174     the object to return.
175     """
176     path = uri.split('.')
177     modname = '.'.join(path[:-1])
178     if len(modname) == 0:
179         raise ImportError(u"invalid uri: %s" % uri)
180     mod = object = '?'
181     objname = path[-1]
182     try:
183         __import__(modname)
184         mod = sys.modules[modname]
185     except ImportError, err:
186         raise ImportError(
187             u"can not import module : %s (%s)" % (modname, str(err)))
188     try:
189         object = getattr(mod, objname)
190     except AttributeError, err:
191         raise AttributeError(u"object (%s) not found in module '%s'. "
192                              "Module content is: %s" % (objname, modname, tuple(dir(mod))))
193     return object
194
195
196 class Singleton(object):
197
198     """Singleton implementation in python."""
199     # add _singleton_id attribute to the class to be independant of import
200     # path used
201     __inst = {}
202
203     def __new__(cls, *args, **kargs):
204         cls_id = getattr(cls, '_singleton_id', cls)
205         if Singleton.__inst.get(cls_id) is None:
206             Singleton.__inst[cls_id] = object.__new__(cls)
207         return Singleton.__inst[cls_id]
208
209
210 class Enum(object):
211
212     """
213     This class emulates a C-like enum for python. It is initialized with a list
214     of strings to be used as the enum symbolic keys. The enum values are automatically
215     generated as sequencing integer starting at 0.
216     """
217
218     def __init__(self, *keys):
219         """Constructor"""
220         self._dict_keys = {}
221         for inum, key in enumerate(keys):
222             setattr(self, key, 2 ** inum)
223             self._dict_keys[2 ** inum] = key
224
225     def exists(self, value):
226         """Tell if value is in the enumeration"""
227         return self.get_id(value) is not None
228
229     def get_id(self, value):
230         """Return the key associated to the given value"""
231         return self._dict_keys.get(value, None)