Salome HOME
debug intempestif
[tools/eficas.git] / Validation / V_ETAPE.py
1 # coding=utf-8
2 # ======================================================================
3 # COPYRIGHT (C) 2007-2021  EDF R&D                  
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 #
18 #
19 # ======================================================================
20
21
22 """
23    Ce module contient la classe mixin ETAPE qui porte les methodes
24    necessaires pour realiser la validation d'un objet de type ETAPE
25    derive de OBJECT.
26
27    Une classe mixin porte principalement des traitements et est
28    utilisee par heritage multiple pour composer les traitements.
29 """
30 from __future__ import print_function
31 from __future__ import absolute_import
32
33 # Modules Python
34 import types
35 import sys
36 import traceback
37 import re
38
39 # Modules EFICAS
40 from . import V_MCCOMPO
41 from Noyau import MAXSIZE, MAXSIZE_MSGCHK
42 from Noyau.N_Exception import AsException
43 from Noyau.N_utils import AsType
44 from Extensions.i18n import tr
45
46
47
48 class ETAPE(V_MCCOMPO.MCCOMPO):
49
50     """
51     """
52
53     def validChild(self):
54         """ Cette methode teste la validite des mots cles de l'etape """
55         for child in self.mcListe:
56             if not child.isValid():
57                 return 0
58         return 1
59
60     def validRegles(self, cr):
61         """ Cette methode teste la validite des regles de l'etape """
62         text_erreurs, test_regles = self.verifRegles()
63         if not test_regles:
64             if cr == 'oui':
65                 self.cr.fatal( "Regle(s) non respectee(s) : %s" % text_erreurs)
66             return 0
67         return 1
68
69     def validSdnom(self, cr):
70         """ Cette methode teste la validite du nom du concept produit par l'etape """
71         valid = 1
72         if self.sd.nom != None:
73             if self.sd.nom.find('sansnom') != -1:
74                 # la SD est 'sansnom' : --> erreur
75                 if cr == 'oui':
76                     self.cr.fatal(("object must have a name"))
77                 valid = 0
78             elif re.search('^SD_[0-9]*$', self.sd.nom):
79                 # la SD est 'SD_' cad son nom = son id donc pas de nom donne
80                 # par utilisateur : --> erreur
81                 if cr == 'oui':
82                     self.cr.fatal( ("invalid name ('SD_' is a reserved keyword)"))
83                 valid = 0
84         return valid
85
86     def getValid(self):
87         if hasattr(self, 'valid'):
88             return self.valid
89         else:
90             self.valid = None
91             return None
92
93     def setValid(self, valid):
94         old_valid = self.getValid()
95         self.valid = valid
96         self.state = 'unchanged'
97         if not old_valid or old_valid != self.valid:
98             self.initModifUp()
99
100     def isValid(self, sd='oui', cr='non'):
101         """
102            Methode pour verifier la validite de l'objet ETAPE. Cette methode
103            peut etre appelee selon plusieurs modes en fonction de la valeur
104            de sd et de cr.
105
106            Si cr vaut oui elle cree en plus un compte-rendu.
107
108            Cette methode a plusieurs fonctions :
109
110             - mettre a jour l'etat de self (update)
111
112             - retourner un indicateur de validite 0=non, 1=oui
113
114             - produire un compte-rendu : self.cr
115
116         """
117         #if CONTEXT.debug:
118         #if 1 :
119         #   print(("ETAPE.isValid ", self.nom, self.state))
120         #   import traceback
121         #   traceback.print_stack()
122         if self.state == 'unchanged':
123             return self.valid
124         else:
125             valid = self.validChild()
126             valid = valid * self.validRegles(cr)
127             if cr == 'oui' :
128                 if not hasattr(self,'cr') :
129                     from Noyau.N_CR import CR
130                     self.cr=CR()
131                 else :
132                     self.cr.purge()
133             if self.reste_val != {}:
134                 if cr == 'oui':
135                     self.cr.fatal(
136                         "unknown keywords : %s" % ','.join(list(self.reste_val.keys())))
137                 valid = 0
138
139             if sd == "non":
140                 # Dans ce cas, on ne teste qu'une validite partielle (sans tests sur le concept produit)
141                 # Consequence : on ne change pas l'etat ni l'attribut valid, on retourne simplement
142                 # l'indicateur de validite valid
143                 return valid
144
145             if self.definition.reentrant == 'n' and self.reuse:
146                 # Il ne peut y avoir de concept reutilise avec un OPER non
147                 # reentrant
148                 if cr == 'oui':
149                     self.cr.fatal(
150                         'Operateur non reentrant : ne pas utiliser reuse')
151                 valid = 0
152
153             if self.sd == None:
154                 # Le concept produit n'existe pas => erreur
155                 if cr == 'oui':
156                     self.cr.fatal(("Concept is not defined"))
157                 valid = 0
158             else:
159                 valid = valid * self.validSdnom(cr)
160
161             if valid:
162                 valid = self.updateSdprod(cr)
163
164             self.setValid(valid)
165
166             return self.valid
167
168     def updateSdprod(self, cr='non'):
169         """
170              Cette methode met a jour le concept produit en fonction des conditions initiales :
171
172               1. Il n'y a pas de concept retourne (self.definition.sd_prod == None)
173
174               2. Le concept retourne n existait pas (self.sd == None)
175
176               3. Le concept retourne existait. On change alors son type ou on le supprime
177
178              En cas d'erreur (exception) on retourne un indicateur de validite de 0 sinon de 1
179         """
180         sd_prod = self.definition.sd_prod
181         if type(sd_prod) == types.FunctionType:  # Type de concept retourne calcule
182             d = self.creeDictValeurs(self.mcListe)
183             try:
184                 sd_prod = sd_prod(*(), **d)
185             except:
186                 # Erreur pendant le calcul du type retourne
187                 if CONTEXT.debug:
188                     traceback.print_exc()
189                 self.sd = None
190                 if cr == 'oui':
191                     l = traceback.format_exception(sys.exc_info()[0],
192                                                    sys.exc_info()[1],
193                                                    sys.exc_info()[2])
194                     self.cr.fatal(
195                         'unable to affect type to concept\n %s' % ' '.join(l[2:]))
196                 return 0
197         # on teste maintenant si la SD est reutilisee ou s'il faut la
198         # creer
199         valid = 1
200         if self.reuse:
201             if AsType(self.reuse) != sd_prod:
202                 if cr == 'oui':
203                     self.cr.fatal(
204                         ('Type de concept reutilise incompatible avec type produit'))
205                 valid = 0
206             if self.sdnom != '':
207                 if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
208                     # Le nom de la variable de retour (self.sdnom) doit etre le
209                     # meme que celui du concept reutilise (self.reuse.nom)
210                     if cr == 'oui':
211                         self.cr.fatal('Concept reutilise : le nom de la variable de retour devrait etre %s et non %s' % ( self.reuse.nom, self.sdnom))
212                     valid = 0
213             if valid:
214                 self.sd = self.reuse
215         else:
216             if sd_prod == None:  # Pas de concept retourne
217                 # Que faut il faire de l eventuel ancien sd ?
218                 self.sd = None
219             else:
220                 if self.sd:
221                     # Un sd existe deja, on change son type
222                     if CONTEXT.debug:
223                         print(("changement de type:", self.sd, sd_prod))
224                     if self.sd.__class__ != sd_prod:
225                         self.sd.changeType(sd_prod)
226                 else:
227                     # Le sd n existait pas , on ne le cree pas
228                     if cr == 'oui':
229                         self.cr.fatal("Concept retourne non defini")
230                     valid = 0
231             if self.definition.reentrant == 'o':
232                 if cr == 'oui':
233                     self.cr.fatal(
234                         ('Commande obligatoirement reentrante : specifier reuse=concept'))
235                 valid = 0
236         return valid
237
238     def report(self):
239         """
240             Methode pour generation d un rapport de validite
241         """
242         self.cr = self.CR(debut='Command : ' + tr(self.nom)
243                           + '    line : ' + repr(self.appel[0])
244                           + '    file : ' + repr(self.appel[1]),
245                           fin='End Command : ' + tr(self.nom))
246         self.state = 'modified'
247         try:
248             self.isValid(cr='oui')
249         except AsException as e:
250             if CONTEXT.debug:
251                 traceback.print_exc()
252             self.cr.fatal('Command : %s line : %r file : %r %s' % (tr(self.nom), self.appel[0], self.appel[1], e))
253         i = 0
254         for child in self.mcListe:
255             i += 1
256             if i > MAXSIZE:
257                 print (MAXSIZE_MSGCHK.format(MAXSIZE, len(self.mcListe)))
258                 break
259             self.cr.add(child.report())
260         return self.cr