Salome HOME
debug intempestif
[tools/eficas.git] / Ihm / I_FORM_ETAPE.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2021   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.mcListe=self.buildMc()
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.analyseFormule()
47
48
49     def analyseFormule(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.mcListe) == 0:
58             # pas de fils pour self --> la FORMULE est incomplete
59             return None,None,None
60         type_retourne="REEL"
61         if len(self.mcListe) > 0:
62             child = self.mcListe[0] # child est un MCSIMP
63             corps = child.getVal()
64         else:
65             corps = None
66         if len(self.mcListe) > 1:
67             child = self.mcListe[1]
68             l_args= child.getVal()
69         else :
70             l_args=None
71         return type_retourne,l_args,corps
72
73     def getNom(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.getName()
80         else:
81             return ''
82
83     def getFormule(self):
84         """
85         Retourne un tuple decrivant la formule :
86         (nom,type_retourne,arguments,corps)
87         """
88         t,a,c = self.analyseFormule()
89         n = self.getNom()
90         return (n,t,a,c)
91
92     def verifArguments(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 verifCorps(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.getNom(),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.getParametresFonctionsAvantEtape(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 verifNom(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.getNom()
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.getSdAutourEtape(nom,self)
163         if sd :
164             return 0,tr("Un concept de nom %s existe deja !" %nom)
165         return 1,''
166
167     def verifType(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 verifFormule(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.verifNom(formule[0])
195         test_type,erreur_type = self.verifType(formule[1])
196         if formule[2]:
197             args = '('+formule[2]+')'
198         else:
199             args = None
200         test_arguments,erreur_arguments = self.verifArguments(args)
201         test_corps,erreur_corps = self.verifCorps(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 verifFormule_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.verifNom(formule[0])
220         if formule[2]:
221             args = '('+formule[2]+')'
222         else:
223             args = None
224         test_arguments,erreur_arguments = self.verifArguments(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 mcListe
252         # pour cela on utilise la methode generale buildMc
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.getSdProd()
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 updateFormulePython(self,formule):
269         self.buildMc()
270         self.mcListe=[]
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.mcListe.append(child)
292
293         self.corps = formule[2]
294         self.type_retourne = formule[1]
295         sd = self.getSdProd()
296         if sd:
297             sd.nom = formule[0]
298         self.initModif()
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.initModif()
308         nom = self.getNom()
309         if nom == '' : return
310         try:
311             self.jdc.appendFonction(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.initModif()
322         if not self.sd : return
323         self.jdc.delFonction(self.sd)
324
325     def updateConcept(self,sd):
326         return
327
328     def deleteConcept(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.initModif()
340
341     def replaceConcept(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.initModif()