1 # -*- coding: utf-8 -*-
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 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.
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.
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.
20 # ======================================================================
23 import string,traceback
25 from I_MACRO_ETAPE import MACRO_ETAPE
26 from Extensions import interpreteur_formule
27 from Editeur import analyse_catalogue
29 analyse_catalogue.l_noms_commandes.append('FORM') # déclare le nom FORM à l'analyseur de catalogue
32 class FORM_ETAPE(MACRO_ETAPE):
34 interpreteur = interpreteur_formule.Interpreteur_Formule
37 self.mc_liste=self.build_mc()
38 # on crée la liste des types autorisés (liste des noms de mots-clés
39 # simples dans le catalogue de FORMULE)
40 self.l_types_autorises = self.definition.entites.keys()
41 # en plus de la construction traditionnelle des fils de self
42 # il faut pour les FORMULE décortiquer l'expression ...
43 self.type_retourne,self.arguments,self.corps = self.analyse_formule()
46 def analyse_formule(self):
48 Cette méthode décortique l'expression de la FORMULE.
49 Elle retourne 3 valeurs:
50 - le type retourné par la FORMULE
51 - les arguments de la FORMULE
52 - le corps de la FORMULE, cad son expression
54 if len(self.mc_liste) == 0:
55 # pas de fils pour self --> la FORMULE est incomplète
58 if len(self.mc_liste) > 0:
59 child = self.mc_liste[0] # child est un MCSIMP
60 corps = child.getval()
63 if len(self.mc_liste) > 1:
64 child = self.mc_liste[1]
65 l_args= child.getval()
68 return type_retourne,l_args,corps
72 Retourne le nom de la FORMULE, cad le nom de la SD si elle existe,
76 return self.sd.get_name()
80 def get_formule(self):
82 Retourne un tuple décrivant la formule :
83 (nom,type_retourne,arguments,corps)
85 t,a,c = self.analyse_formule()
89 def verif_arguments(self,arguments = None):
91 Vérifie si les arguments passés en argument (si aucun prend les arguments courants)
92 sont des arguments valide pour une FORMULE.
94 - un booléen, qui vaut 1 si arguments licites, 0 sinon
95 - un message d'erreurs ('' si illicites)
98 arguments = self.arguments
100 return 0,"Une formule doit avoir au minimum un argument"
101 # il faut au préalable enlever les parenthèses ouvrantes et fermantes
102 # encadrant les arguments
103 arguments = string.strip(arguments)
104 if arguments[0] != '(':
105 return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse ouvrante manquante"
106 if arguments[-1] != ')':
107 return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse fermante manquante"
108 # on peut tester la syntaxe de chaque argument maintenant
111 arguments = arguments[1:-1] # on enlève les parenthèses ouvrante et fermante
112 l_arguments = string.split(arguments,',')
115 def verif_corps(self,corps=None,arguments=None):
117 Cette méthode a pour but de vérifier si le corps de la FORMULE
118 est syntaxiquement correct.
120 - un booléen, qui vaut 1 si corps de FORMULE licite, 0 sinon
121 - un message d'erreurs ('' si illicite)
126 arguments = self.arguments
127 formule=(self.get_nom(),self.type_retourne,arguments,corps)
128 # on récupère la liste des constantes et des autres fonctions prédéfinies
129 # et qui peuvent être utilisées dans le corps de la formule courante
130 l_ctes,l_form = self.jdc.get_parametres_fonctions_avant_etape(self)
131 # on crée un objet vérificateur
133 verificateur = self.interpreteur(formule=formule,
137 traceback.print_exc()
138 return 0,"Impossible de réaliser la vérification de la formule"
139 return verificateur.isvalid(),verificateur.report()
141 def verif_nom(self,nom=None):
143 Vérifie si le nom passé en argument (si aucun prend le nom courant)
144 est un nom valide pour une FORMULE.
146 - un booléen, qui vaut 1 si nom licite, 0 sinon
147 - un message d'erreurs ('' si illicite)
152 return 0,"Pas de nom donné à la FORMULE"
154 return 0,"Un nom de FORMULE ne peut dépasser 8 caractères"
155 if nom[0] > "0" and nom[0] < "9" :
156 return 0,"Un nom de FORMULE ne peut pas commencer par un chiffre"
157 sd = self.parent.get_sd_autour_etape(nom,self)
159 return 0,"Un concept de nom %s existe déjà !" %nom
162 def verif_type(self,type=None):
164 Vérifie si le type passé en argument (si aucun prend le type courant)
165 est un type valide pour une FORMULE.
167 - un booléen, qui vaut 1 si type licite, 0 sinon
168 - un message d'erreurs ('' si illicite)
171 type = self.type_retourne
173 return 0,"Le type de la valeur retournée n'est pas spécifié"
174 if type not in self.l_types_autorises:
175 return 0,"Une formule ne peut retourner une valeur de type : %s" %type
178 def verif_formule(self,formule=None):
180 Vérifie la validité de la formule passée en argument.
181 Cette nouvelle formule est passée sous la forme d'un tuple : (nom,type_retourne,arguments,corps)
182 Si aucune formule passée, prend les valeurs courantes de la formule
184 - un booléen, qui vaut 1 si formule licite, 0 sinon
185 - un message d'erreurs ('' si illicite)
188 formule = (None,None,None,None)
189 test_nom,erreur_nom = self.verif_nom(formule[0])
190 test_type,erreur_type = self.verif_type(formule[1])
192 args = '('+formule[2]+')'
195 test_arguments,erreur_arguments = self.verif_arguments(args)
196 test_corps,erreur_corps = self.verif_corps(corps = formule[3], arguments = args)
197 # test global = produit des tests partiels
198 test = test_nom*test_type*test_arguments*test_corps
199 # message d'erreurs global = concaténation des messages partiels
202 for mess in (erreur_nom,erreur_type,erreur_arguments,erreur_corps):
203 erreur = erreur+(len(mess) > 0)*'\n'+mess
206 def verif_formule_python(self,formule=None):
208 Pour l instant ne fait qu un compile python
209 il serait possible d ajouter des tests sur les arguments
210 ou le type retourne mais ...
213 formule = (None,None,None,None)
214 test_nom,erreur_nom = self.verif_nom(formule[0])
216 args = '('+formule[2]+')'
219 test_arguments,erreur_arguments = self.verif_arguments(args)
224 compile(corps,'<string>','eval')
226 erreur_formule= "le corps de la formule n'est pas une formule python valide"
229 test = test_nom*test_arguments*test_formule
231 for mess in (erreur_nom,erreur_arguments,erreur_formule):
232 erreur = erreur+(len(mess) > 0)*'\n'+mess
236 def update(self,formule):
239 Met à jour les champs nom, type_retourne,arguments et corps de la FORMULE
240 par les nouvelles valeurs passées dans le tuple formule.
241 On stocke les valeurs SANS vérifications.
243 self.type_retourne = formule[1]
244 self.arguments = '('+formule[2]+')'
245 self.corps = formule[3]
246 # il faut ajouter le mot-clé simple correspondant dans mc_liste
247 # pour cela on utilise la méthode générale build_mc
248 # du coup on est obligé de modifier le dictionnaire valeur de self ...
250 self.valeur[self.type_retourne] = self.arguments+' = ' + self.corps
252 sd = self.get_sd_prod()
257 # Il faut que formule soit constituee de
261 # corps de la fonction
262 # il faut aussi que les arguments soient sous forme de tuple
263 def update_formule_python(self,formule):
266 if len(formule) < 4 :
269 if arguments[0] == '(' :
270 arguments=arguments[1:]
271 if arguments[-1] == ')' :
272 arguments=arguments[:-1]
273 self.arguments=tuple(arguments.split(','))
275 mocles={"NOM_PARA":self.arguments}
276 if formule[1] == "REEL":
277 mocles["VALE"]=formule[2]
278 if formule[1] == "COMPLEXE":
279 mocles["VALE_C"]=formule[2]
281 for k,v in self.definition.entites.items():
282 if not mocles.has_key(k):continue
283 child=self.definition.entites[k](None,nom=k,parent=self)
284 child.valeur=mocles[k]
285 child.state = 'modified'
286 self.mc_liste.append(child)
288 self.corps = formule[2]
289 self.type_retourne = formule[1]
290 sd = self.get_sd_prod()
298 Rend l'etape courante active.
299 Il faut ajouter la formule au contexte global du JDC
304 if nom == '' : return
306 self.jdc.append_fonction(self.sd)
312 Rend l'etape courante inactive
313 Il faut supprimer la formule du contexte global du JDC
317 if not self.sd : return
318 self.jdc.del_fonction(self.sd)
320 def update_concept(self,sd):
323 def delete_concept(self,sd):
328 Mettre a jour les mots cles de l etape et eventuellement le concept produit si reuse
329 suite à la disparition du concept sd
330 Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils,
331 sauf les objets FORM_ETAPE qui doivent vérifier que le concept détruit n'est pas
332 utilisé dans le corps de la fonction
336 def replace_concept(self,old_sd,sd):
339 - old_sd=concept remplace
340 - sd = nouveau concept
342 Les objets FORM_ETAPE devraient vérifier que le concept remplacé n'est pas
343 utilisé dans le corps de la fonction