Salome HOME
commentaire
[tools/eficas.git] / Ihm / I_FORM_ETAPE.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 from __future__ import absolute_import
23 import string,traceback,re
24 identifier = re.compile(r"^[^\d\W]\w*\Z", re.UNICODE)
25
26
27 from Extensions.i18n import tr
28 from .I_MACRO_ETAPE import MACRO_ETAPE
29 from Extensions import interpreteur_formule
30 from Editeur import analyse_catalogue
31
32 analyse_catalogue.l_noms_commandes.append('FORM') # declare le nom FORM a l'analyseur de catalogue
33
34
35 class FORM_ETAPE(MACRO_ETAPE):
36
37     interpreteur = interpreteur_formule.Interpreteur_Formule
38
39     def McBuild(self):
40         self.mc_liste=self.build_mc()
41         # on cree la liste des types autorises (liste des noms de mots-cles
42         # simples dans le catalogue de FORMULE)
43         self.l_types_autorises = list(self.definition.entites.keys())
44         # en plus de la construction traditionnelle des fils de self
45         # il faut pour les FORMULE decortiquer l'expression ...
46         self.type_retourne,self.arguments,self.corps = self.analyse_formule()
47
48
49     def analyse_formule(self):
50         """
51         Cette methode decortique l'expression de la FORMULE.
52         Elle retourne 3 valeurs:
53             - le type retourne par la FORMULE
54             - les arguments de la FORMULE
55             - le corps de la FORMULE, cad son expression
56         """
57         if len(self.mc_liste) == 0:
58             # pas de fils pour self --> la FORMULE est incomplete
59             return None,None,None
60         type_retourne="REEL"
61         if len(self.mc_liste) > 0:
62            child = self.mc_liste[0] # child est un MCSIMP 
63            corps = child.getval()
64         else:
65            corps = None
66         if len(self.mc_liste) > 1:
67            child = self.mc_liste[1]
68            l_args= child.getval()
69         else :
70            l_args=None
71         return type_retourne,l_args,corps
72
73     def get_nom(self):
74         """
75         Retourne le nom de la FORMULE, cad le nom de la SD si elle existe,
76         la string vide sinon
77         """
78         if self.sd :
79             return self.sd.get_name()
80         else:
81             return ''
82
83     def get_formule(self):
84         """
85         Retourne un tuple decrivant la formule :
86         (nom,type_retourne,arguments,corps)
87         """
88         t,a,c = self.analyse_formule()
89         n = self.get_nom()
90         return (n,t,a,c)
91
92     def verif_arguments(self,arguments = None):
93         """
94         Verifie si les arguments passes en argument (si aucun prend les arguments courants)
95         sont des arguments valide pour une FORMULE.
96         Retourne :
97             - un booleen, qui vaut 1 si arguments licites, 0 sinon
98             - un message d'erreurs ('' si illicites)
99         """
100         if not arguments :
101             arguments = self.arguments
102         if not arguments :
103             return 0,"Une formule doit avoir au minimum un argument"
104         # il faut au prealable enlever les parentheses ouvrantes et fermantes
105         # encadrant les arguments
106         arguments = string.strip(arguments)
107         if arguments[0] != '(':
108             return 0,tr("La liste des arguments d'une formule doit etre entre parentheses : parenthese ouvrante manquante")
109         if arguments[-1] != ')':
110             return 0,tr("La liste des arguments d'une formule doit etre entre parentheses : parenthese fermante manquante")
111         # on peut tester la syntaxe de chaque argument maintenant
112         erreur=''
113         test = 1
114         arguments = arguments[1:-1] # on enleve les parentheses ouvrante et fermante
115         l_arguments = string.split(arguments,',')
116         for a in l_arguments :
117             if not re.match(identifier,str(a)) : return 0, str(a)+" n est pas un identifiant"
118         return test,erreur
119
120     def verif_corps(self,corps=None,arguments=None):
121         """
122         Cette methode a pour but de verifier si le corps de la FORMULE
123         est syntaxiquement correct.
124         Retourne :
125             - un booleen, qui vaut 1 si corps de FORMULE licite, 0 sinon
126             - un message d'erreurs ('' si illicite)
127         """
128         if not corps :
129             corps = self.corps
130         if not arguments :
131             arguments = self.arguments
132         formule=(self.get_nom(),self.type_retourne,arguments,corps)
133         # on recupere la liste des constantes et des autres fonctions predefinies
134         # et qui peuvent etre utilisees dans le corps de la formule courante
135         l_ctes,l_form = self.jdc.get_parametres_fonctions_avant_etape(self)
136         # on cree un objet verificateur
137         try:
138             verificateur = self.interpreteur(formule=formule,
139                                              constantes = l_ctes,
140                                              fonctions = l_form)
141         except :
142             traceback.print_exc()
143             return 0,tr("Impossible de realiser la verification de la formule")
144         return verificateur.isvalid(),verificateur.report()
145
146     def verif_nom(self,nom=None):
147         """
148         Verifie si le nom passe en argument (si aucun prend le nom courant)
149         est un nom valide pour une FORMULE.
150         Retourne :
151             - un booleen, qui vaut 1 si nom licite, 0 sinon
152             - un message d'erreurs ('' si illicite)
153         """
154         if not nom :
155             nom = self.get_nom()
156         if nom == "" :
157             return 0,tr("Pas de nom donne a la FORMULE")
158         if len(nom) > 8 :
159             return 0,tr("Un nom de FORMULE ne peut depasser 8 caracteres")
160         if nom[0] > "0" and nom[0] < "9" :
161             return 0,tr("Un nom de FORMULE ne peut pas commencer par un chiffre")
162         sd = self.parent.get_sd_autour_etape(nom,self)
163         if sd :
164             return 0,tr("Un concept de nom %s existe deja !" %nom)
165         return 1,''
166
167     def verif_type(self,type=None):
168         """
169         Verifie si le type passe en argument (si aucun prend le type courant)
170         est un type valide pour une FORMULE.
171         Retourne :
172             - un booleen, qui vaut 1 si type licite, 0 sinon
173             - un message d'erreurs ('' si illicite)
174         """
175         if not type:
176             type = self.type_retourne
177         if not type :
178             return 0,tr("Le type de la valeur retournee n'est pas specifie")
179         if type not in self.l_types_autorises:
180             return 0,tr("Une formule ne peut retourner une valeur de type : %s" %type)
181         return 1,''
182
183     def verif_formule(self,formule=None):
184         """
185         Verifie la validite de la formule passee en argument.
186         Cette nouvelle formule est passee sous la forme d'un tuple : (nom,type_retourne,arguments,corps)
187         Si aucune formule passee, prend les valeurs courantes de la formule
188         Retourne :
189             - un booleen, qui vaut 1 si formule licite, 0 sinon
190             - un message d'erreurs ('' si illicite)
191         """
192         if not formule :
193             formule = (None,None,None,None)
194         test_nom,erreur_nom = self.verif_nom(formule[0])
195         test_type,erreur_type = self.verif_type(formule[1])
196         if formule[2]:
197             args = '('+formule[2]+')'
198         else:
199             args = None
200         test_arguments,erreur_arguments = self.verif_arguments(args)
201         test_corps,erreur_corps = self.verif_corps(corps = formule[3], arguments = args)
202         # test global = produit des tests partiels
203         test = test_nom*test_type*test_arguments*test_corps
204         # message d'erreurs global = concatenation des messages partiels
205         erreur = ''
206         if not test :
207             for mess in (erreur_nom,erreur_type,erreur_arguments,erreur_corps):
208                 erreur = erreur+(len(mess) > 0)*'\n'+mess
209         return test,erreur
210
211     def verif_formule_python(self,formule=None):
212         """
213         Pour l instant ne fait qu un compile python
214         il serait possible d ajouter des tests sur les arguments
215         ou le type retourne mais ...
216         """
217         if not formule :
218             formule = (None,None,None,None)
219         test_nom,erreur_nom = self.verif_nom(formule[0])
220         if formule[2]:
221             args = '('+formule[2]+')'
222         else:
223             args = None
224         test_arguments,erreur_arguments = self.verif_arguments(args)
225         corps=formule[3]
226         erreur_formule= ''
227         test_formule=1
228         try :
229             compile(corps,'<string>','eval')
230         except :
231             erreur_formule= "le corps de la formule n'est pas une formule python valide"
232             test_formule=0
233         erreur = ''
234         test = test_nom*test_arguments*test_formule
235         if not test :
236             for mess in (erreur_nom,erreur_arguments,erreur_formule):
237                 erreur = erreur+(len(mess) > 0)*'\n'+mess
238         return test,erreur
239
240
241     def update(self,formule):
242         """
243         Methode externe.
244         Met a jour les champs nom, type_retourne,arguments et corps de la FORMULE
245         par les nouvelles valeurs passees dans le tuple formule.
246         On stocke les valeurs SANS verifications.
247         """
248         self.type_retourne = formule[1]
249         self.arguments = '('+formule[2]+')'
250         self.corps = formule[3]
251         # il faut ajouter le mot-cle simple correspondant dans mc_liste
252         # pour cela on utilise la methode generale build_mc
253         # du coup on est oblige de modifier le dictionnaire valeur de self ...
254         self.valeur = {}
255         self.valeur[self.type_retourne] = self.arguments+' = ' + self.corps
256         self.McBuild()
257         sd = self.get_sd_prod()
258         if sd:
259             sd.nom = formule[0]
260
261     # bidouille PN 
262     # Il faut que formule soit constituee de 
263     # nom de la formule
264     # type retourne
265     # parametres
266     # corps de la fonction
267     # il faut aussi que les arguments soient sous forme de tuple
268     def update_formule_python(self,formule):
269         self.build_mc()
270         self.mc_liste=[]
271         if len(formule) < 4 :
272            return 0
273         arguments=formule[3]
274         if arguments[0] == '(' :
275            arguments=arguments[1:]
276         if arguments[-1] == ')' :
277            arguments=arguments[:-1]
278         self.arguments=tuple(arguments.split(','))
279
280         mocles={"NOM_PARA":self.arguments}
281         if formule[1] == "REEL":
282           mocles["VALE"]=formule[2]
283         if formule[1] == "COMPLEXE":
284           mocles["VALE_C"]=formule[2]
285
286         for k,v in self.definition.entites.items():
287             if not k in  mocles : continue
288             child=self.definition.entites[k](None,nom=k,parent=self)
289             child.valeur=mocles[k]
290             child.state = 'modified'
291             self.mc_liste.append(child)
292            
293         self.corps = formule[2]
294         self.type_retourne = formule[1]
295         sd = self.get_sd_prod()
296         if sd:
297             sd.nom = formule[0]
298         self.init_modif()
299         return 1
300
301     def active(self):
302         """
303         Rend l'etape courante active.
304         Il faut ajouter la formule au contexte global du JDC
305         """
306         self.actif = 1
307         self.init_modif()
308         nom = self.get_nom()
309         if nom == '' : return
310         try:
311             self.jdc.append_fonction(self.sd)
312         except:
313             pass
314
315     def inactive(self):
316         """
317         Rend l'etape courante inactive
318         Il faut supprimer la formule du contexte global du JDC
319         """
320         self.actif = 0
321         self.init_modif()
322         if not self.sd : return
323         self.jdc.del_fonction(self.sd)
324
325     def update_concept(self,sd):
326         return
327
328     def delete_concept(self,sd):
329         """ 
330          Inputs :
331            - sd=concept detruit
332          Fonction :
333          Mettre a jour les mots cles de l etape et eventuellement le concept produit si reuse
334          suite a la disparition du concept sd
335          Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils,
336          sauf les objets FORM_ETAPE qui doivent verifier que le concept detruit n'est pas 
337          utilise dans le corps de la fonction
338         """
339         self.init_modif()
340          
341     def replace_concept(self,old_sd,sd):
342         """
343          Inputs :
344            - old_sd=concept remplace
345            - sd = nouveau concept
346          Fonction :
347          Les objets FORM_ETAPE devraient verifier que le concept remplace n'est pas
348          utilise dans le corps de la fonction
349         """
350         self.init_modif()
351