Salome HOME
correction pb condition_context avec newJDC
[tools/eficas.git] / Ihm / I_MACRO_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 # Modules Python
24 import sys
25 import traceback,types,string
26
27 # Modules Eficas
28 import I_ETAPE
29 from Noyau.N_ASSD import ASSD
30
31 # import rajoutés suite à l'ajout de Build_sd --> à résorber
32 import Noyau, Validation.V_MACRO_ETAPE
33 from Noyau import N_Exception
34 from Noyau.N_Exception import AsException
35 # fin import à résorber
36
37 class MACRO_ETAPE(I_ETAPE.ETAPE):
38
39   def __init__(self):
40       self.typret=None
41       self.recorded_units={}
42
43   def get_sdprods(self,nom_sd):
44     """ 
45          Fonction : retourne le concept produit par l etape de nom nom_sd
46          s il existe sinon None
47     """
48     if self.sd and self.sd.nom == nom_sd :return self.sd
49     for co in self.sdprods:
50       if co.nom == nom_sd:return co
51     if type(self.definition.op_init) == types.FunctionType:
52       d={}
53       apply(self.definition.op_init,(self,d))
54       return d.get(nom_sd,None)
55     return None
56
57   def get_contexte_jdc(self,fichier,text):
58     """ 
59          Interprète text comme un texte de jdc et retourne le 
60          contexte final
61          cad le dictionnaire des sd disponibles à la dernière étape
62          Si text n'est pas un texte de jdc valide, retourne None
63          ou leve une exception
64          --> utilisée par ops.POURSUITE et INCLUDE
65     """
66     print "get_contexte_jdc"
67     try:
68        # on essaie de créer un objet JDC auxiliaire avec un contexte initial
69        context_ini = self.parent.get_contexte_avant(self)
70
71        # Indispensable avant de creer un nouveau JDC
72        CONTEXT.unset_current_step()
73        args=self.jdc.args
74        prefix_include=None
75        if hasattr(self,'prefix'):
76           prefix_include=self.prefix
77        # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des 
78        # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
79        # tout le traitement et de ne pas le reinitialiser brutalement (utiliser 
80        # clear plutot) si on ne veut pas perdre la memoire des unites.
81        # En principe si la memorisation est faite au bon moment il n'est pas necessaire
82        # de prendre cette precaution mais ce n'est pas vrai partout.
83        old_recorded_units=self.recorded_units.copy()
84        #print "get_contexte_jdc",id(self.recorded_units)
85        #self.recorded_units.clear()
86
87        j=self.JdC_aux( procedure=text, nom=fichier,
88                                 appli=self.jdc.appli,
89                                 cata=self.jdc.cata,
90                                 cata_ord_dico=self.jdc.cata_ordonne_dico,
91                                 context_ini = context_ini,
92                                 jdc_pere=self.jdc,etape_include=self,
93                                 prefix_include=prefix_include,
94                                 recorded_units=self.recorded_units,
95                                 old_recorded_units=old_recorded_units,**args)
96
97        j.analyse()
98        # On récupère les étapes internes (pour validation)
99        self.etapes=j.etapes
100        self.jdc_aux=j
101        print "get_contexte_jdc",id(self.etapes)
102     except:
103        traceback.print_exc()
104        # On force le contexte (etape courante) à self
105        CONTEXT.unset_current_step()
106        CONTEXT.set_current_step(self)
107        return None
108
109     if not j.cr.estvide():
110        # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
111        # mais on n'insere pas les concepts
112        # On force le contexte (etape courante) à self
113        CONTEXT.unset_current_step()
114        CONTEXT.set_current_step(self)
115        raise Exception("Impossible de relire le fichier\n"+str(j.cr))
116
117     if not j.isvalid():
118        # L'INCLUDE n'est pas valide.
119        # on produit un rapport d'erreurs
120        # On force le contexte (etape courante) à self
121        cr=j.report()
122        CONTEXT.unset_current_step()
123        CONTEXT.set_current_step(self)
124        raise Exception("Le fichier include contient des erreurs\n"+str(cr))
125
126     # Si aucune erreur rencontrée
127     # On recupere le contexte de l'include verifie
128     try:
129        j_context=j.get_verif_contexte()
130     except:
131        CONTEXT.unset_current_step()
132        CONTEXT.set_current_step(self)
133        raise
134
135     # On remplit le dictionnaire des concepts produits inclus
136     # en retirant les concepts présents dans le  contexte initial
137     # On ajoute egalement le concept produit dans le sds_dict du parent
138     # sans verification car on est sur (verification integrée) que 
139     # le nommage est possible
140     self.g_context.clear()
141     for k,v in j_context.items():
142        if not context_ini.has_key(k) or context_ini[k] != v:
143            self.g_context[k]=v
144            self.parent.sds_dict[k]=v
145
146
147     # On recupere le contexte courant
148     self.current_context=j.current_context
149     self.index_etape_courante=j.index_etape_courante
150     self.jdc_aux=j
151
152     # XXX j.supprime() ???
153     # On rétablit le contexte (etape courante) à self
154     CONTEXT.unset_current_step()
155     CONTEXT.set_current_step(self)
156
157     return j_context
158
159   def reevalue_sd_jdc(self):
160      """
161          Avec la liste des SD qui ont été supprimées, propage la 
162          disparition de ces SD dans toutes les étapes et descendants
163      """
164      l_sd_supp,l_sd_repl = self.diff_contextes()
165      for sd in l_sd_supp:
166         self.parent.delete_concept_after_etape(self,sd)
167      for old_sd,sd in l_sd_repl:
168         self.parent.replace_concept_after_etape(self,old_sd,sd)
169
170   def diff_contextes(self):
171      """ 
172          Réalise la différence entre les 2 contextes 
173          old_contexte_fichier_init et contexte_fichier_init
174          cad retourne la liste des sd qui ont disparu ou ne derivent pas 
175          de la meme classe et des sd qui ont ete remplacees
176      """
177      if not hasattr(self,'old_contexte_fichier_init'):return [],[]
178      l_sd_suppressed = []
179      l_sd_replaced = []
180      for old_key in self.old_contexte_fichier_init.keys():
181        if not self.contexte_fichier_init.has_key(old_key):
182          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
183            l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
184        else:
185          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
186             # Un concept de meme nom existe
187             old_class=self.old_contexte_fichier_init[old_key].__class__
188             if not isinstance(self.contexte_fichier_init[old_key],old_class):
189                # S'il n'est pas d'une classe derivee, on le supprime
190                l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
191             else:
192                l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key]))
193      return l_sd_suppressed,l_sd_replaced
194       
195   def control_sdprods(self,d):
196       """
197           Cette methode doit updater le contexte fournit par
198           l'appelant en argument (d) en fonction de sa definition
199           tout en verifiant que ses concepts produits ne sont pas
200           deja definis dans le contexte
201       """
202       if hasattr(self,"fichier_unite"):
203          self.update_fichier_init(self.fichier_unite)
204          self.init_modif()
205
206       if type(self.definition.op_init) == types.FunctionType:
207         apply(self.definition.op_init,(self,d))
208       if self.sd:
209         if d.has_key(self.sd.nom):
210            # Le concept est deja defini
211            if self.reuse and self.reuse is d[self.sd.nom]:
212               # Le concept est reutilise : situation normale
213               pass
214            else:
215               # Redefinition du concept, on l'annule
216               #XXX on pourrait simplement annuler son nom pour conserver les objets
217               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
218               self.sd=self.reuse=self.sdnom=None
219               self.init_modif()
220         else:
221            # Le concept n'est pas defini, on peut updater d
222            d[self.sd.nom]=self.sd
223       # On verifie les concepts a droite du signe =
224       for co in self.sdprods:
225         if d.has_key(co.nom) and co is not d[co.nom] :
226            self.delete_concept(co)
227         else:
228            d[co.nom]=co
229        
230
231   def supprime_sdprods(self):
232       """
233           Fonction:
234           Lors d'une destruction d'etape, detruit tous les concepts produits
235           Un opérateur n a qu un concept produit
236           Une procedure n'en a aucun
237           Une macro en a en général plus d'un
238       """
239       if not self.is_reentrant() :
240          # l'étape n'est pas réentrante
241          # le concept retourné par l'étape est à supprimer car il était
242          # créé par l'étape
243          if self.sd != None :
244             self.parent.del_sdprod(self.sd)
245             self.parent.delete_concept(self.sd)
246       # On détruit les concepts à droite du signe =
247       for co in self.sdprods:
248          self.parent.del_sdprod(co)
249          self.parent.delete_concept(co)
250       # Si la macro a des etapes et des concepts inclus, on les detruit
251       for nom_sd,co in self.g_context.items():
252          if not isinstance(co,ASSD):continue
253          self.parent.del_sdprod(co)
254          self.parent.delete_concept(co)
255       # On met g_context à blanc
256       self.g_context={}
257          
258   def make_contexte_include(self,fichier,text):
259     """
260         Cette méthode sert à créer un contexte en interprétant un texte source
261         Python
262     """
263     print "make_contexte_include"
264     # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
265     contexte = self.get_contexte_jdc(fichier,text)
266     if contexte == None :
267       raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
268     else:
269       # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE
270       # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion
271       # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits
272       # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts
273       # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc)
274       # g_context est utilisé pour avoir les concepts produits par la macro
275       # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro
276       self.contexte_fichier_init = contexte
277
278   def reevalue_fichier_init(self):
279       """Recalcule les concepts produits par le fichier enregistre"""
280       old_context=self.contexte_fichier_init
281       try:
282          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
283       except:
284          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
285          self.fichier_err = string.join(l)
286          #self.etapes=[]
287          self.g_context={}
288
289          self.old_contexte_fichier_init=old_context
290          self.contexte_fichier_init={}
291          self.reevalue_sd_jdc()
292          return
293
294       # L'evaluation s'est bien passee
295       self.fichier_err = None
296       self.old_contexte_fichier_init=old_context
297       self.reevalue_sd_jdc()
298
299   def update_fichier_init(self,unite):
300       """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur 
301          les noms des fichiers
302          Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
303       """
304       print "update_fichier_init",unite
305       self.fichier_err=None
306       self.old_contexte_fichier_init=self.contexte_fichier_init
307       old_fichier_ini=self.fichier_ini
308
309       #print "update_fichier_init",self,self.parent,self.parent.recorded_units
310
311       #if unite != self.fichier_unite or not self.parent.recorded_units.has_key(unite):
312       if not self.parent.recorded_units.has_key(unite):
313          # Nouvelle unite
314          f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
315          units={}
316          if f is not None:
317             self.fichier_ini = f
318             self.fichier_text=text
319          self.recorded_units=units
320          if self.fichier_ini is None and self.jdc.appli:
321             self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
322                      message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
323       else:
324          # Unite existante
325          f,text,units=self.parent.recorded_units[unite]
326          self.fichier_ini = f
327          self.fichier_text=text
328          self.recorded_units=units
329
330       if self.fichier_ini is None:
331          # Le fichier n'est pas défini
332          self.fichier_err="Le fichier associé n'est pas défini"
333          self.parent.change_unit(unite,self,self.fichier_unite)
334          self.g_context={}
335          self.contexte_fichier_init={}
336          self.parent.reset_context()
337          self.reevalue_sd_jdc()
338          return
339
340       if old_fichier_ini == self.fichier_ini:
341          # Le fichier inclus n'a pas changé. On ne recrée pas le contexte
342          return
343
344       try:
345         self.make_contexte_include(self.fichier_ini,self.fichier_text)
346         # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
347         # avant d'appeler change_unit
348         self.parent.change_unit(unite,self,self.fichier_unite)
349       except:
350         # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
351         l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
352         # On conserve la memoire du nouveau fichier
353         # mais on n'utilise pas les concepts crees par ce fichier
354         # on met l'etape en erreur : fichier_err=string.join(l)
355         self.fichier_err=string.join(l)
356         self.parent.change_unit(unite,self,self.fichier_unite)
357         self.g_context={}
358         self.contexte_fichier_init={}
359
360       # Le contexte du parent doit etre reinitialise car les concepts 
361       # produits ont changé
362       self.parent.reset_context()
363       # Si des concepts ont disparu lors du changement de fichier, on 
364       # demande leur suppression
365       self.reevalue_sd_jdc()
366
367   def record_unite(self):
368       if self.nom == "POURSUITE":
369          self.parent.record_unit(None,self)
370       else:
371          if hasattr(self,'fichier_unite') : 
372             self.parent.record_unit(self.fichier_unite,self)
373
374   def get_file_memo(self,unite=None,fic_origine=''):
375       """Retourne le nom du fichier et le source correspondant a l'unite unite
376          Initialise en plus recorded_units
377       """
378       #print "get_file_memo",unite,fic_origine,self,self.parent
379       #print self.parent.old_recorded_units
380       #print self.parent.recorded_units
381       if unite is None:
382          units={}
383       else:
384          units=self.parent.recorded_units
385       if self.parent.old_recorded_units.has_key(unite):
386          f,text,units=self.parent.old_recorded_units[unite]
387          #print id(self.recorded_units)
388          self.recorded_units=units
389          #print id(self.recorded_units)
390          return f,text
391       elif self.jdc :
392          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
393       else:
394          f,text=None,None
395       self.recorded_units=units
396       if f is None and self.jdc.appli:
397          self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
398                           message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
399       return f,text
400
401 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
402   def get_file(self,unite=None,fic_origine=''):
403       """Retourne le nom du fichier et le source correspondant a l'unite unite
404          Initialise en plus recorded_units
405       """
406       #print "get_file",unite
407       units={}
408       if self.jdc :
409          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
410       else:
411          f,text=None,None
412       self.recorded_units=units
413       return f,text
414
415 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
416   def make_include(self,unite=None):
417       """
418           Inclut un fichier dont l'unite logique est unite
419           Cette methode est appelee par la fonction sd_prod de la macro INCLUDE
420           Si l'INCLUDE est invalide, la methode doit produire une exception 
421           Sinon on retourne None. Les concepts produits par l'INCLUDE sont
422           pris en compte par le JDC parent lors du calcul du contexte (appel de ???)
423       """
424       print "make_include",unite
425       # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE
426       # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
427       del self.unite
428       # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None
429       if not unite : return
430
431       if not hasattr(self,'fichier_ini') : 
432          # Si le fichier n'est pas defini on le demande
433          f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
434          # On memorise le fichier retourne
435          self.fichier_ini  = f
436          self.fichier_text = text
437          self.contexte_fichier_init={}
438          self.fichier_unite=unite
439          self.fichier_err=None
440          try:
441            import Extensions.jdc_include
442          except:
443            traceback.print_exc()
444            raise
445          self.JdC_aux=Extensions.jdc_include.JdC_include
446
447          if f is None:
448              self.fichier_err="Le fichier INCLUDE n est pas defini"
449              self.parent.record_unit(unite,self)
450              raise Exception(self.fichier_err)
451
452          try:
453            self.make_contexte_include(self.fichier_ini ,self.fichier_text)
454            self.parent.record_unit(unite,self)
455          except:
456            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
457            if self.jdc.appli:
458               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
459                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
460                                            )
461            self.parent.record_unit(unite,self)
462            self.g_context={}
463            self.fichier_err = string.join(l)
464            self.contexte_fichier_init={}
465            raise
466
467       else:
468          # Si le fichier est deja defini on ne reevalue pas le fichier
469          # et on leve une exception si une erreur a été enregistrée
470          self.update_fichier_init(unite)
471          self.fichier_unite=unite
472          if self.fichier_err is not None: raise Exception(self.fichier_err)
473         
474
475 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
476   def make_contexte(self,fichier,text):
477     """
478         Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU
479         en interprétant un texte source Python
480         Elle est appelee par la fonction sd_prd d'INCLUDE_MATERIAU
481     """
482     # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU
483     # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
484     if hasattr(self,'mat'):del self.mat
485     self.fichier_ini =fichier
486     self.fichier_unite =fichier
487     self.fichier_text=text
488     self.fichier_err=None 
489     self.contexte_fichier_init={}
490     # On specifie la classe a utiliser pour le JDC auxiliaire
491     try:
492       import Extensions.jdc_include
493     except:
494       traceback.print_exc()
495       raise
496     self.JdC_aux=Extensions.jdc_include.JdC_include
497     try:
498        self.make_contexte_include(self.fichier_ini ,self.fichier_text)
499        self.parent.record_unit(self.fichier_unite,self)
500     except:
501        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
502        self.fichier_err = string.join(l)
503        self.parent.record_unit(self.fichier_unite,self)
504        self.g_context={}
505        self.contexte_fichier_init={}
506        raise
507
508 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
509   def update_sdprod(self,cr='non'):
510      # Cette methode peut etre appelee dans EFICAS avec des mots cles de 
511      # la commande modifies. Ceci peut conduire a la construction ou
512      # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU
513      # Il faut donc positionner le current_step avant l'appel
514      CONTEXT.unset_current_step()
515      CONTEXT.set_current_step(self)
516      valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr)
517      CONTEXT.unset_current_step()
518      return valid
519
520 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
521   def Build_sd(self,nom):
522       """
523            Methode de Noyau surchargee pour poursuivre malgre tout
524            si une erreur se produit pendant la creation du concept produit
525       """
526       try:
527          sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom)
528       except AsException,e:
529          # Une erreur s'est produite lors de la construction du concept
530          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
531          # Si on poursuit, on a le choix entre deux possibilités :
532          # 1. on annule la sd associée à self
533          # 2. on la conserve mais il faut la retourner
534          # On choisit de l'annuler
535          # En plus il faut rendre coherents sdnom et sd.nom
536          self.sd=None
537          self.sdnom=None
538          self.state="unchanged"
539          self.valid=0
540
541       return self.sd
542
543 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
544   def make_poursuite(self):
545       """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE
546       """
547       print "make_poursuite"
548       if not hasattr(self,'fichier_ini') :
549          # Si le fichier n'est pas defini on le demande
550          f,text=self.get_file_memo(fic_origine=self.parent.nom)
551          # On memorise le fichier retourne
552          self.fichier_ini = f
553          self.fichier_unite = None
554          self.fichier_text = text
555          self.fichier_err=None
556          try:
557            import Extensions.jdc_include
558          except:
559            traceback.print_exc()
560            raise
561          self.JdC_aux=Extensions.jdc_include.JdC_poursuite
562          self.contexte_fichier_init={}
563
564          if f is None:
565              self.fichier_err="Le fichier POURSUITE n'est pas defini"
566              self.parent.record_unit(None,self)
567              raise Exception(self.fichier_err)
568
569          try:
570            self.make_contexte_include(self.fichier_ini,self.fichier_text)
571            self.parent.record_unit(None,self)
572          except:
573            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
574            if self.jdc.appli:
575               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite",
576                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
577                                            )
578            self.parent.record_unit(None,self)
579            self.g_context={}
580            self.fichier_err = string.join(l)
581            self.contexte_fichier_init={}
582            raise
583
584       else:
585          # Si le fichier est deja defini on ne reevalue pas le fichier
586          # et on leve une exception si une erreur a été enregistrée
587          self.update_fichier_init(None)
588          if self.fichier_err is not None: raise Exception(self.fichier_err)
589