Salome HOME
PN vielles macros
[tools/eficas.git] / Ihm / I_FORM_ETAPE.py
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.
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 import string,traceback
24
25 from I_MACRO_ETAPE import MACRO_ETAPE
26 from Extensions import interpreteur_formule
27 from Editeur import analyse_catalogue
28
29 analyse_catalogue.l_noms_commandes.append('FORM') # déclare le nom FORM à l'analyseur de catalogue
30
31
32 class FORM_ETAPE(MACRO_ETAPE):
33
34     interpreteur = interpreteur_formule.Interpreteur_Formule
35
36     def McBuild(self):
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()
44
45
46     def analyse_formule(self):
47         """
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
53         """
54         if len(self.mc_liste) == 0:
55             # pas de fils pour self --> la FORMULE est incomplète
56             return None,None,None
57         type_retourne="REEL"
58         if len(self.mc_liste) > 0:
59            child = self.mc_liste[0] # child est un MCSIMP 
60            corps = child.getval()
61         else:
62            corps = None
63         if len(self.mc_liste) > 1:
64            child = self.mc_liste[1]
65            l_args= child.getval()
66         else :
67            l_args=None
68         return type_retourne,l_args,corps
69
70     def get_nom(self):
71         """
72         Retourne le nom de la FORMULE, cad le nom de la SD si elle existe,
73         la string vide sinon
74         """
75         if self.sd :
76             return self.sd.get_name()
77         else:
78             return ''
79
80     def get_formule(self):
81         """
82         Retourne un tuple décrivant la formule :
83         (nom,type_retourne,arguments,corps)
84         """
85         t,a,c = self.analyse_formule()
86         n = self.get_nom()
87         return (n,t,a,c)
88
89     def verif_arguments(self,arguments = None):
90         """
91         Vérifie si les arguments passés en argument (si aucun prend les arguments courants)
92         sont des arguments valide pour une FORMULE.
93         Retourne :
94             - un booléen, qui vaut 1 si arguments licites, 0 sinon
95             - un message d'erreurs ('' si illicites)
96         """
97         if not arguments :
98             arguments = self.arguments
99         if not 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
109         erreur=''
110         test = 1
111         arguments = arguments[1:-1] # on enlève les parenthèses ouvrante et fermante
112         l_arguments = string.split(arguments,',')
113         #for argument in l_arguments:
114         #    argument = string.strip(argument)
115         #    try:
116         #       nom=argument
117         #        typ,nom = string.split(argument,':')
118         #        #pas de vérification sur le nom de l'argument
119         #        #vérification du type de l'argument
120         #        typ = string.strip(typ)
121         #        if typ not in self.l_types_autorises :
122         #            test = 0
123         #            erreur = erreur + "Le type "+typ+" n'est pas un type permis pour "+nom+'\n'
124         #    except:
125         #        # l'argument ne respecte pas la syntaxe : typ_arg : nom_arg
126         #        test = 0
127         #        erreur = erreur+"Syntaxe argument non valide : "+argument+'\n'
128         return test,erreur
129
130     def verif_corps(self,corps=None,arguments=None):
131         """
132         Cette méthode a pour but de vérifier si le corps de la FORMULE
133         est syntaxiquement correct.
134         Retourne :
135             - un booléen, qui vaut 1 si corps de FORMULE licite, 0 sinon
136             - un message d'erreurs ('' si illicite)
137         """
138         if not corps :
139             corps = self.corps
140         if not arguments :
141             arguments = self.arguments
142         formule=(self.get_nom(),self.type_retourne,arguments,corps)
143         # on récupère la liste des constantes et des autres fonctions prédéfinies
144         # et qui peuvent être utilisées dans le corps de la formule courante
145         l_ctes,l_form = self.jdc.get_parametres_fonctions_avant_etape(self)
146         # on crée un objet vérificateur
147         try:
148             verificateur = self.interpreteur(formule=formule,
149                                              constantes = l_ctes,
150                                              fonctions = l_form)
151         except :
152             traceback.print_exc()
153             return 0,"Impossible de réaliser la vérification de la formule"
154         return verificateur.isvalid(),verificateur.report()
155
156     def verif_nom(self,nom=None):
157         """
158         Vérifie si le nom passé en argument (si aucun prend le nom courant)
159         est un nom valide pour une FORMULE.
160         Retourne :
161             - un booléen, qui vaut 1 si nom licite, 0 sinon
162             - un message d'erreurs ('' si illicite)
163         """
164         if not nom :
165             nom = self.get_nom()
166         if nom == "" :
167             return 0,"Pas de nom donné à la FORMULE"
168         if len(nom) > 8 :
169             return 0,"Un nom de FORMULE ne peut dépasser 8 caractères"
170         if nom[0] > "0" and nom[0] < "9" :
171             return 0,"Un nom de FORMULE ne peut pas commencer par un chiffre"
172         sd = self.parent.get_sd_autour_etape(nom,self)
173         if sd :
174             return 0,"Un concept de nom %s existe déjà !" %nom
175         return 1,''
176
177     def verif_type(self,type=None):
178         """
179         Vérifie si le type passé en argument (si aucun prend le type courant)
180         est un type valide pour une FORMULE.
181         Retourne :
182             - un booléen, qui vaut 1 si type licite, 0 sinon
183             - un message d'erreurs ('' si illicite)
184         """
185         if not type:
186             type = self.type_retourne
187         if not type :
188             return 0,"Le type de la valeur retournée n'est pas spécifié"
189         if type not in self.l_types_autorises:
190             return 0,"Une formule ne peut retourner une valeur de type : %s" %type
191         return 1,''
192
193     def verif_formule(self,formule=None):
194         """
195         Vérifie la validité de la formule passée en argument.
196         Cette nouvelle formule est passée sous la forme d'un tuple : (nom,type_retourne,arguments,corps)
197         Si aucune formule passée, prend les valeurs courantes de la formule
198         Retourne :
199             - un booléen, qui vaut 1 si formule licite, 0 sinon
200             - un message d'erreurs ('' si illicite)
201         """
202         if not formule :
203             formule = (None,None,None,None)
204         test_nom,erreur_nom = self.verif_nom(formule[0])
205         test_type,erreur_type = self.verif_type(formule[1])
206         if formule[2]:
207             args = '('+formule[2]+')'
208         else:
209             args = None
210         test_arguments,erreur_arguments = self.verif_arguments(args)
211         test_corps,erreur_corps = self.verif_corps(corps = formule[3], arguments = args)
212         # test global = produit des tests partiels
213         test = test_nom*test_type*test_arguments*test_corps
214         # message d'erreurs global = concaténation des messages partiels
215         erreur = ''
216         if not test :
217             for mess in (erreur_nom,erreur_type,erreur_arguments,erreur_corps):
218                 erreur = erreur+(len(mess) > 0)*'\n'+mess
219         return test,erreur
220
221     def verif_formule_python(self,formule=None):
222         """
223         Pour l instant ne fait qu un compile python
224         il serait possible d ajouter des tests sur les arguments
225         ou le type retourne mais ...
226         """
227         if not formule :
228             formule = (None,None,None,None)
229         test_nom,erreur_nom = self.verif_nom(formule[0])
230         if formule[2]:
231             args = '('+formule[2]+')'
232         else:
233             args = None
234         test_arguments,erreur_arguments = self.verif_arguments(args)
235         corps=formule[3]
236         erreur_formule= ''
237         test_formule=1
238         try :
239             compile(corps,'<string>','eval')
240         except :
241             erreur_formule= "le corps de la formule n'est pas une formule python valide"
242             test_formule=0
243         erreur = ''
244         test = test_nom*test_arguments*test_formule
245         if not test :
246             for mess in (erreur_nom,erreur_arguments,erreur_formule):
247                 erreur = erreur+(len(mess) > 0)*'\n'+mess
248         return test,erreur
249
250
251     def update(self,formule):
252         """
253         Méthode externe.
254         Met à jour les champs nom, type_retourne,arguments et corps de la FORMULE
255         par les nouvelles valeurs passées dans le tuple formule.
256         On stocke les valeurs SANS vérifications.
257         """
258         self.type_retourne = formule[1]
259         self.arguments = '('+formule[2]+')'
260         self.corps = formule[3]
261         # il faut ajouter le mot-clé simple correspondant dans mc_liste
262         # pour cela on utilise la méthode générale build_mc
263         # du coup on est obligé de modifier le dictionnaire valeur de self ...
264         self.valeur = {}
265         self.valeur[self.type_retourne] = self.arguments+' = ' + self.corps
266         self.McBuild()
267         sd = self.get_sd_prod()
268         if sd:
269             sd.nom = formule[0]
270
271     # bidouille PN 
272     # Il faut que formule soit constituee de 
273     # nom de la formule
274     # type retourne
275     # parametres
276     # corps de la fonction
277     # il faut aussi que les arguments soient sous forme de tuple
278     def update_formule_python(self,formule):
279         self.build_mc()
280         self.mc_liste=[]
281         if len(formule) < 4 :
282            return O
283         arguments=formule[3]
284         if arguments[0] == '(' :
285            arguments=[1,-1 ]
286         if arguments[-1] == '(' :
287            arguments=[0,-2 ]
288         self.arguments=tuple(arguments.split(','))
289
290         i=1
291         for k,v in self.definition.entites.items():
292             child=self.definition.entites[k](None,nom=k,parent=self)
293             new_valeur=formule[i+1]
294             if i+1 == 3 :
295                child.valeur = self.arguments
296             else :
297                child.valeur = new_valeur
298             child.state = 'modified'
299             self.mc_liste.append(child)
300             i=i+1
301            
302         self.corps = formule[2]
303         self.type_retourne = formule[1]
304         sd = self.get_sd_prod()
305         if sd:
306             sd.nom = formule[0]
307         self.init_modif()
308         return 1
309
310     def active(self):
311         """
312         Rend l'etape courante active.
313         Il faut ajouter la formule au contexte global du JDC
314         """
315         self.actif = 1
316         nom = self.get_nom()
317         if nom == '' : return
318         try:
319             self.jdc.append_fonction(self.sd)
320         except:
321             pass
322
323     def inactive(self):
324         """
325         Rend l'etape courante inactive
326         Il faut supprimer la formule du contexte global du JDC
327         """
328         self.actif = 0
329         if not self.sd : return
330         self.jdc.del_fonction(self.sd)
331
332     def delete_concept(self,sd):
333         """ 
334          Inputs :
335            - sd=concept detruit
336          Fonction :
337          Mettre a jour les mots cles de l etape et eventuellement le concept produit si reuse
338          suite à la disparition du concept sd
339          Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils,
340          sauf les objets FORM_ETAPE qui doivent vérifier que le concept détruit n'est pas 
341          utilisé dans le corps de la fonction
342         """
343         self.init_modif()
344          
345     def replace_concept(self,old_sd,sd):
346         """
347          Inputs :
348            - old_sd=concept remplace
349            - sd = nouveau concept
350          Fonction :
351          Les objets FORM_ETAPE devraient vérifier que le concept remplacé n'est pas
352          utilisé dans le corps de la fonction
353         """
354         self.init_modif()
355