Salome HOME
gestion des listes et label sur 2
[tools/eficas.git] / Validation / V_MACRO_ETAPE.py
1 # coding=utf-8
2 # person_in_charge: mathieu.courtois at edf.fr
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2015  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21
22
23 """
24    Ce module contient la classe mixin MACRO_ETAPE qui porte les méthodes
25    nécessaires pour réaliser la validation d'un objet de type MACRO_ETAPE
26    dérivé de OBJECT.
27
28    Une classe mixin porte principalement des traitements et est
29    utilisée par héritage multiple pour composer les traitements.
30 """
31 # Modules Python
32 import types
33 import sys
34 import traceback
35
36 # Modules EFICAS
37 import V_MCCOMPO
38 import V_ETAPE
39 from Noyau.N_Exception import AsException
40 from Noyau.N_utils import AsType
41 from Noyau.strfunc import ufmt
42
43
44 class MACRO_ETAPE(V_ETAPE.ETAPE):
45
46     """
47     """
48
49     def isvalid(self, sd='oui', cr='non'):
50         """
51            Methode pour verifier la validité de l'objet ETAPE. Cette méthode
52            peut etre appelée selon plusieurs modes en fonction de la valeur
53            de sd et de cr.
54
55            Si cr vaut oui elle crée en plus un compte-rendu.
56
57            Cette méthode a plusieurs fonctions :
58
59             - mettre à jour l'état de self (update)
60
61             - retourner un indicateur de validité 0=non, 1=oui
62
63             - produire un compte-rendu : self.cr
64
65         """
66         if CONTEXT.debug:
67             print "ETAPE.isvalid ", self.nom
68         if self.state == 'unchanged':
69             return self.valid
70         else:
71             valid = 1
72             # On marque les concepts CO pour verification ulterieure de leur
73             # bonne utilisation
74             l = self.get_all_co()
75             # On verifie que les concepts CO sont bien passes par type_sdprod
76             for c in l:
77                 # if c.etape is self.parent:
78                 if c.is_typco() != 2:
79                     # le concept est propriete de l'etape parent
80                     # Il n'a pas ete transforme par type_sdprod
81                     # Cette situation est interdite
82                     # Pb: La macro-commande a passe le concept a une commande
83                     # (macro ?) mal definie
84                     if cr == 'oui':
85                         self.cr.fatal(_(u"Macro-commande mal définie : le concept n'a pas été typé par "
86                                         u"un appel à type_sdprod pour %s"), c.nom)
87                     valid = 0
88
89             valid = valid * self.valid_child()
90             valid = valid * self.valid_regles(cr)
91
92             if self.reste_val != {}:
93                 if cr == 'oui':
94                     self.cr.fatal(
95                         _(u"Mots clés inconnus : %s"), ','.join(self.reste_val.keys()))
96                 valid = 0
97
98             if sd == "non":
99                 # Dans ce cas, on ne calcule qu'une validite partielle, on ne modifie pas l'état de self
100                 # on retourne simplement l'indicateur valid
101                 return valid
102
103             if self.sd != None:
104                 valid = valid * self.valid_sdnom(cr)
105
106             if self.definition.reentrant == 'n' and self.reuse:
107                 # Il ne peut y avoir de concept reutilise avec une MACRO  non
108                 # reentrante
109                 if cr == 'oui':
110                     self.cr.fatal(
111                         _(u'Macro-commande non réentrante : ne pas utiliser reuse'))
112                 valid = 0
113
114             if valid:
115                 valid = self.update_sdprod(cr)
116
117             # Si la macro comprend des etapes internes, on teste leur validite
118             for e in self.etapes:
119                 if not e.isvalid():
120                     valid = 0
121                     break
122
123             self.set_valid(valid)
124
125             return self.valid
126
127     def update_sdprod(self, cr='non'):
128         """
129              Cette méthode met à jour le concept produit en fonction des conditions initiales :
130
131               1. Il n'y a pas de concept retourné (self.definition.sd_prod == None)
132
133               2. Le concept retourné n existait pas (self.sd == None)
134
135               3. Le concept retourné existait. On change alors son type ou on le supprime
136
137              En cas d'erreur (exception) on retourne un indicateur de validité de 0 sinon de 1
138         """
139         sd_prod = self.definition.sd_prod
140         # On memorise le type retourné dans l attribut typret
141         self.typret = None
142         if type(sd_prod) == types.FunctionType:
143             # Type de concept retourné calculé
144             d = self.cree_dict_valeurs(self.mc_liste)
145             try:
146                 # la sd_prod d'une macro a l'objet lui meme en premier argument
147                 # contrairement à une ETAPE ou PROC_ETAPE
148                 # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
149                 # les concepts produits dans self.sdprods, il faut le mettre à
150                 # zéro
151                 self.sdprods = []
152                 sd_prod = apply(sd_prod, (self,), d)
153             except:
154                 # Erreur pendant le calcul du type retourné
155                 if CONTEXT.debug:
156                     traceback.print_exc()
157                 self.sd = None
158                 if cr == 'oui':
159                     l = traceback.format_exception(sys.exc_info()[0],
160                                                    sys.exc_info()[1],
161                                                    sys.exc_info()[2])
162                     self.cr.fatal(
163                         _(u'Impossible d affecter un type au résultat\n%s'), ' '.join(l[2:]))
164                 return 0
165         # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la
166         # cr\351er
167         valid = 1
168         if self.reuse:
169             # Un concept reutilise a ete specifie
170             if AsType(self.reuse) != sd_prod:
171                 if cr == 'oui':
172                     self.cr.fatal(
173                         _(u'Type de concept réutilisé incompatible avec type produit'))
174                 valid = 0
175             if self.sdnom != '':
176                 if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
177                     # Le nom de la variable de retour (self.sdnom) doit etre le
178                     # meme que celui du concept reutilise (self.reuse.nom)
179                     if cr == 'oui':
180                         self.cr.fatal(_(u'Concept réutilisé : le nom de la variable de '
181                                         u'retour devrait être %s et non %s'),
182                                       self.reuse.nom, self.sdnom)
183                     valid = 0
184             if valid:
185                 self.sd = self.reuse
186         else:
187             # Cas d'un concept non reutilise
188             if sd_prod == None:  # Pas de concept retourné
189                 # Que faut il faire de l eventuel ancien sd ?
190                 self.sd = None
191             else:
192                 if self.sd:
193                     # Un sd existe deja, on change son type
194                     if CONTEXT.debug:
195                         print "changement de type:", self.sd, sd_prod
196                     if self.sd.__class__ != sd_prod:
197                         self.sd.change_type(sd_prod)
198                     self.typret = sd_prod
199                 else:
200                     # Le sd n existait pas , on ne le crée pas
201                     self.typret = sd_prod
202                     if cr == 'oui':
203                         self.cr.fatal(_(u"Concept retourné non défini"))
204                     valid = 0
205             if self.definition.reentrant == 'o':
206                 if cr == 'oui':
207                     self.cr.fatal(
208                         _(u'Commande obligatoirement réentrante : spécifier reuse=concept'))
209                 valid = 0
210         return valid
211
212     def report(self):
213         """
214             Methode pour la generation d un rapport de validation
215         """
216         V_ETAPE.ETAPE.report(self)
217         for e in self.etapes:
218             self.cr.add(e.report())
219         return self.cr