From: cvs2git Date: Thu, 25 Apr 2002 15:06:37 +0000 (+0000) Subject: This commit was manufactured by cvs2git to create tag 'FR_25_04'. X-Git-Tag: FR_25_04^0 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b92c5acee60f5a1f578dc2f47a6e9605cd83ddfe;p=tools%2Feficas.git This commit was manufactured by cvs2git to create tag 'FR_25_04'. Sprout from I26 2002-03-26 09:08:47 UTC eficas 'Version initiale de EFICAS 1.2' Cherrypick from master 2002-04-25 15:06:36 UTC eficas 'F.R: - modifs dans I_MACRO_ETAPE et I_PROC_ETAPE car il faut aussi surcharger': Accas/A_ASSD.py Accas/A_JDC.py Accas/__init__.py Aster/INSTALL Aster/LICENSE.TERMS Aster/README Aster/prefs.py Aster/sdist.py Editeur/Objecttreeitem.py Editeur/appli.py Editeur/bureau.py Editeur/compomacro.py Editeur/compomclist.py Editeur/compooper.py Editeur/compoproc.py Editeur/composimp.py Editeur/eficas.py Editeur/jdcdisplay.py Editeur/menubar.py Editeur/panels.py Editeur/treeitemincanvas.py Editeur/treewidget.py Exemples/ex11/main.py Extensions/commande_comm.py Extensions/commentaire.py Extensions/interpreteur_formule.py Extensions/mcnuplet.py Extensions/parametre.py Extensions/parametre_eval.py Ihm/I_ASSD.py Ihm/I_ETAPE.py Ihm/I_FONCTION.py Ihm/I_FORM_ETAPE.py Ihm/I_JDC.py Ihm/I_MACRO_ETAPE.py Ihm/I_MCCOMPO.py Ihm/I_MCLIST.py Ihm/I_MCSIMP.py Ihm/I_OBJECT.py Ihm/I_PROC_ETAPE.py Minicode/cata_saturne.py Minicode/eficas_mini.py Validation/V_ETAPE.py Validation/V_MACRO_ETAPE.py generator/generator_aplat.py generator/generator_python.py --- diff --git a/Accas/A_ASSD.py b/Accas/A_ASSD.py new file mode 100644 index 00000000..1fd9f3a2 --- /dev/null +++ b/Accas/A_ASSD.py @@ -0,0 +1,30 @@ + +from Ihm import I_ASSD +from Ihm import I_FONCTION +from Noyau import N_ASSD +from Noyau import N_GEOM +from Noyau import N_FONCTION +from Noyau import N_CO + +# On ajoute la classe ASSD dans l'héritage multiple pour recréer +# une hiérarchie d'héritage identique à celle de Noyau +# pour faire en sorte que isinstance(o,ASSD) marche encore après +# dérivation + +class ASSD(N_ASSD.ASSD,I_ASSD.ASSD):pass + +class assd(N_ASSD.assd,I_ASSD.ASSD,ASSD):pass + +class FONCTION(N_FONCTION.FONCTION,I_FONCTION.FONCTION,ASSD): + def __init__(self,etape=None,sd=None,reg='oui'): + N_FONCTION.FONCTION.__init__(self,etape=etape,sd=sd,reg=reg) + I_FONCTION.FONCTION.__init__(self,etape=etape,sd=sd,reg=reg) + +class fonction(N_FONCTION.fonction,I_FONCTION.fonction,ASSD): + def __init__(self,etape=None,sd=None,reg='oui'): + N_FONCTION.fonction.__init__(self,etape=etape,sd=sd,reg=reg) + I_FONCTION.fonction.__init__(self,etape=etape,sd=sd,reg=reg) + +class GEOM(N_GEOM.GEOM,I_ASSD.ASSD,ASSD):pass +class geom(N_GEOM.geom,I_ASSD.ASSD,ASSD):pass +class CO(N_CO.CO,I_ASSD.ASSD,ASSD):pass diff --git a/Accas/A_JDC.py b/Accas/A_JDC.py index b709e01f..34af1460 100644 --- a/Accas/A_JDC.py +++ b/Accas/A_JDC.py @@ -4,6 +4,8 @@ from Extensions import jdc from Ihm import I_JDC class JDC(jdc.JDC,I_JDC.JDC,V_JDC.JDC,N_JDC.JDC): + from A_ASSD import CO,assd + def __init__(self,*pos,**args): N_JDC.JDC.__init__(self,*pos,**args) V_JDC.JDC.__init__(self) diff --git a/Accas/__init__.py b/Accas/__init__.py index b61776b3..c0711f72 100644 --- a/Accas/__init__.py +++ b/Accas/__init__.py @@ -39,11 +39,11 @@ from A_EXCLUS import EXCLUS from A_ENSEMBLE import ENSEMBLE from A_A_CLASSER import A_CLASSER -from Noyau.N_ASSD import ASSD,assd -from Noyau.N_GEOM import GEOM,geom -from Noyau.N_FONCTION import FONCTION -from Noyau.N_FONCTION import fonction -from Noyau.N_CO import CO +from A_ASSD import ASSD,assd +from A_ASSD import GEOM,geom +from A_ASSD import FONCTION, fonction +from A_ASSD import CO + from Noyau.N__F import _F from Noyau.N_Exception import AsException diff --git a/Aster/INSTALL b/Aster/INSTALL new file mode 100644 index 00000000..044599cc --- /dev/null +++ b/Aster/INSTALL @@ -0,0 +1,33 @@ + + +1- Installation standard + +Pour installer EFICAS a partir de la distribution : Eficas.tgz +faire : + tar xzvf Eficas.tgz + +ce qui a pour effet de créer un répertoire Eficas +Tel que Eficas est prêt à etre executé. + +ATTENTION : +Si Eficas est installé dans un répertoire particulier d'administration +dans lequel les utilisateurs n'ont pas le droit d'écriture, il faut que +l'administrateur lance Eficas avec les deux versions 5 et 6 pour générer +les fichiers et catalogues compilés .pyc et _pickled.py + +2- Utilisation d'Eficas + +Pour utiliser Eficas, aller dans le répertoire Aster et faire : + python eficas_aster.py + +3- Installation avec un noyau pré-installé + +Aller dans le répertoire Aster du répertoire Eficas +et modifier le fichier prefs.py comme suit : +Mettre dans la variable CODE_PATH le chemin absolu vers +le répertoire contenant les deux répertoires Noyau et Validation que vous voulez +utiliser à la place de ceux fournis dans la livraison d'Eficas + +Pour changer les catalogues, modifier le fichier editeur.ini dans le répertoire Aster + + diff --git a/Aster/LICENSE.TERMS b/Aster/LICENSE.TERMS new file mode 100644 index 00000000..8c88a1e5 --- /dev/null +++ b/Aster/LICENSE.TERMS @@ -0,0 +1,21 @@ + ====================================================================== + THIS PROGRAM IS FREE SOFTWARE. YOU CAN REDISTRIBUTE IT AND/OR MODIFY + IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY + THE FREE SOFTWARE FOUNDATION, EITHER VERSION 2 OF THE LICENSE, AND + ANY LATER VERSION. + THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT + WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + SEE THE GNU GENERAL PUBLIC LICENSE FOR MORE DETAILS. + ====================================================================== + TRADUCTION EDF ( POUR INFORMATION ) + ====================================================================== + CE PROGRAMME EST UN LOGICIEL LIBRE. VOUS POUVEZ LE DIFFUSER ET/OU LE + MODIFIER SELON LES DISPOSITIONS DE LA LICENCE GRAND PUBLIC GNU (GPL) + TELLE QU'ELLE EST PUBLIEE PAR LA FREE SOFTWARE FOUNDATION, VERSION 2 + DE LA LICENCE ET TOUTE VERSION ULTERIEURE. + CE PROGRAMME EST DIFFUSE AVEC L'ESPOIR QU'IL SERA UTILE, MAIS SANS + GARANTIE, SANS MEME LA GARANTIE IMPLICITE DE QUALIFICATION DE MISE SUR + LE MARCHE OU D'ADAPTATION A UNE UTILISATION PARTICULIERE. + VOIR POUR DE PLUS AMPLES DETAILS LA LICENCE GRAND PUBLIC GNU (GPL) + ====================================================================== diff --git a/Aster/README b/Aster/README new file mode 100644 index 00000000..0597ecbb --- /dev/null +++ b/Aster/README @@ -0,0 +1,2 @@ + +Pour installer EFICAS voir dans le fichier INSTALL diff --git a/Aster/prefs.py b/Aster/prefs.py index f3d82ae8..b80a2f81 100644 --- a/Aster/prefs.py +++ b/Aster/prefs.py @@ -19,3 +19,40 @@ CODE_PATH = None # Par défaut on utilise le répertoire icons dans Editeur ICONDIR=os.path.join(INSTALLDIR,'Editeur','icons') +labels= ('Fichier','Edition','Jeu de commandes', + # 'Catalogue','Browsers','Options' + ) + +extensions=['readercata','bureau', + # 'browser','options' + ] + +menu_defs={ 'bureau': [ + ('Fichier',[ + ('Nouveau','newJDC'), + ('Ouvrir','openJDC'), + ('Enregistrer','saveJDC'), + ('Enregistrer sous','saveasJDC'), + None, + ('Fermer','closeJDC'), + ('Quitter','exitEFICAS'), + ] + ), + ('Edition',[ + ('Copier','copy'), + ('Couper','cut'), + ('Coller','paste'), + ] + ), + ('Jeu de commandes',[ + ('Rapport de validation','visuCRJDC'), + # ('Fichier à plat','visu_a_plat'), + ('Fichier format v6','visuJDC_py'), + ('Fichier source','visu_txt_brut_JDC'), + ('Paramètres Eficas','affichage_fichier_ini'), + ('Mots-clés inconnus','mc_inconnus'), + ] + ), + ] + } + diff --git a/Aster/sdist.py b/Aster/sdist.py new file mode 100644 index 00000000..830ccb73 --- /dev/null +++ b/Aster/sdist.py @@ -0,0 +1,116 @@ +""" + Ce module sert à construire les distributions d'EFICAS en fonction + du tag CVS courant + Les distributions sont : + - un tar.gz pour UNIX ne contenant pas mxTextTools + - un zip pour Windows contenant mx TextTools préinstallé + L'utilisation de ce module est la suivante : + 1- Se mettre dans un répertoire de travail + 2- Configurer son environnement pour utiliser le référentiel CVS EFICAS + 3- Exporter les sources d'EficasV1 par la commande : + cvs export -r TAG -d Eficas_export EficasV1 + ou TAG est le tag CVS de la version que l'on veut distribuer (par exemple V1_1p1) + 4- Copier le répertoire fourni par Aster (ACCAS6.2.0) au meme niveau que Eficas_export + 5- Aller dans le répertoire Eficas_export + 6- Executer le script sdist.py + python sdist.py + Ce qui a pour effet de creer un repertoire dist contenant les 2 distributions + et de les copier dans le répertoire indiqué par dir_download s'il est accessible + +""" +import os,shutil,glob,sys +import types + +version="$Name: $"[7:-2] or 'Test1_2' +# ==========Path du noyau fourni par Aster==================== +path_Noyau="../../../Tutorial/Superv" +# ============================================================ +nom_distrib="Eficas"+version+"AsterSTA6" +path_distrib=os.path.join("dist",nom_distrib) +path_TextTools="/home/eficas/pkg/mxTools/egenix2.0.2pourWindows/mx/TextTools" +dir_download= "/home/eficas/WWW/telechargement/eficas" + +def main(): + if os.path.isdir('dist'):shutil.rmtree('dist') + + copyfiles('.',path_distrib,['README','LICENSE.TERMS','INSTALL']) + + copyfiles('../Editeur',os.path.join(path_distrib,'Editeur'),['*.py','faqs.txt']) + copyfiles('../Ihm',os.path.join(path_distrib,'Ihm'),['*.py']) + copyfiles('../Extensions',os.path.join(path_distrib,'Extensions'),['*.py']) + copyfiles('../Accas',os.path.join(path_distrib,'Accas'),['*.py']) + copyfiles('../Aster',os.path.join(path_distrib,'Aster'),['prefs.py', + 'editeur.ini', + 'eficas_aster.py', + ]) + copyfiles('../convert',os.path.join(path_distrib,'convert'),['*.py']) + copyfiles('../convert/Parserv5',os.path.join(path_distrib,'convert','Parserv5'),['*.py']) + + copyfiles('../generator',os.path.join(path_distrib,'generator'),['*.py']) + + copyfiles('../Editeur/icons',os.path.join(path_distrib,'Editeur','icons'),['*.gif']) + + copyfiles(os.path.join(path_Noyau,'Noyau'),os.path.join(path_distrib,'Noyau'),['*.py']) + copyfiles(os.path.join(path_Noyau,'Validation'),os.path.join(path_distrib,'Validation'),['*.py']) + copyfiles(os.path.join(path_Noyau,'Cata'),os.path.join(path_distrib,'Aster','Cata'),['*.py', + ]) + + copyfiles('../Tools',os.path.join(path_distrib,'Tools'),['*.py']) + copyfiles('../Tools/foztools',os.path.join(path_distrib,'Tools','foztools'),['*.py']) + + tarball= maketarball('dist',nom_distrib,nom_distrib) + try: + shutil.copy(tarball,dir_download) + except: + print "Repertoire de download inconnu : ",dir_download + + try: + shutil.copytree(path_TextTools,os.path.join(path_distrib,'Tools','TextTools')) + except: + print "Impossible de recuperer mxTextTools : ",dir_download + sys.exit(1) + + zipfile= makezipfile('dist',nom_distrib,nom_distrib) + try: + shutil.copy(zipfile,dir_download) + except: + print "Repertoire de download inconnu : ",dir_download + +def make_dir(dir_cible): + if type(dir_cible) is not types.StringType: + raise "make_dir : dir_cible doit etre une string (%s)" % `dir_cible` + head,tail=os.path.split(dir_cible) + tails=[tail] + while head and tail and not os.path.isdir(head): + head,tail=os.path.split(head) + tails.insert(0, tail) + + for d in tails: + head = os.path.join(head, d) + if not os.path.isdir(head):os.mkdir(head) + + +def copyfiles(dir_origin,dir_cible,listfiles): + if not os.path.isdir(dir_cible):make_dir(dir_cible) + for glob_files in listfiles: + for file in glob.glob(os.path.join(dir_origin,glob_files)): + shutil.copy(file,dir_cible) + +def maketarball(dir_trav,dir_cible,nom_tar): + prev=os.getcwd() + print prev + os.chdir(dir_trav) + os.system("tar -cf "+nom_tar+".tar "+dir_cible) + os.system("gzip -f9 "+nom_tar+".tar ") + os.chdir(prev) + return os.path.join(dir_trav,nom_tar+".tar.gz") + +def makezipfile(dir_trav,dir_cible,nom_tar): + prev=os.getcwd() + os.chdir(dir_trav) + os.system("zip -rq "+nom_tar+".zip "+dir_cible) + os.chdir(prev) + return os.path.join(dir_trav,nom_tar+".zip") + +main() + diff --git a/Editeur/Objecttreeitem.py b/Editeur/Objecttreeitem.py index 7e9ff7db..4a912c12 100644 --- a/Editeur/Objecttreeitem.py +++ b/Editeur/Objecttreeitem.py @@ -393,6 +393,12 @@ class SequenceTreeItem(ObjectTreeItem): def GetText(self): return " " + def additem(self,obj,pos): + # XXX Passer par addentite de MCList ??? + self.object.insert(pos,obj) + item = self.make_objecttreeitem(self.appli, obj.nom + ":", obj) + return item + def suppitem(self,item): if not self.object.isMCList():return 1 try : diff --git a/Editeur/appli.py b/Editeur/appli.py index f8b031f7..701d5766 100644 --- a/Editeur/appli.py +++ b/Editeur/appli.py @@ -110,6 +110,7 @@ class APPLI: root.option_add('*background', 'grey') root.option_add('*foreground', 'black') root.option_add('*EntryField.Entry.background', 'white') + root.option_add('*Entry*background', 'white') root.option_add('*Listbox*background', 'white') root.option_add('*Listbox*selectBackground', '#00008b') root.option_add('*Listbox*selectForeground', 'white') diff --git a/Editeur/bureau.py b/Editeur/bureau.py index 41840842..9a90b6f2 100644 --- a/Editeur/bureau.py +++ b/Editeur/bureau.py @@ -10,6 +10,7 @@ from tkMessageBox import showinfo,askyesno,showerror # Modules Eficas import splash +import prefs import convert import generator from jdcdisplay import JDCDISPLAY @@ -58,6 +59,14 @@ class BUREAU: ('Delete24',"delete","Supprime l'objet courant",'jdc'), ('Help24',"view_doc","Documentation de l'objet courant",'jdc') ) + try: + menu_defs=prefs.menu_defs['bureau'] + except: + pass + try: + button_defs=prefs.button_defs['bureau'] + except: + pass def __init__(self,appli,parent): self.parent=parent @@ -108,6 +117,7 @@ class BUREAU: cata_ord_dico=self.cata_ordonne_dico, appli=self.appli) self.JDCName=J.nom + self.fileName=None self.ShowJDC(J,self.JDCName) self.appli.toolbar.active_boutons() @@ -196,7 +206,7 @@ class BUREAU: Demande à l'utilisateur quel JDC existant il veut ouvrir """ if self.code == 'ASTER': - filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),) + filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*')) else: filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),) if not hasattr(self,'initialdir'): @@ -504,12 +514,16 @@ class BUREAU: """ if not hasattr(self,'JDC') : return titre = "fichier de commandes utilisateur" - texte = self.JDC.procedure - if texte == None: + #texte = self.JDC.procedure + #if texte == None: + if self.JDCDisplay_courant.fichier == None: self.appli.affiche_infos("Pas de fichier initial") - showerror("Impossible de visualiser le fichier initial","EFICAS ne peut visualiser le fichier \ - initial.\nIl s'agit d'un nouveau JDC") + showerror("Impossible de visualiser le fichier initial", + "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC") return + f=open(self.JDCDisplay_courant.fichier,'r') + texte=f.read() + f.close() self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte) def affichage_fichier_ini(self): diff --git a/Editeur/compomacro.py b/Editeur/compomacro.py index ce439f5d..e8bcc6a9 100644 --- a/Editeur/compomacro.py +++ b/Editeur/compomacro.py @@ -23,8 +23,8 @@ import convert from widgets import Fenetre # -__version__="$Name: V1_1p1 $" -__Id__="$Id: compomacro.py,v 1.1.1.1 2001/12/04 15:38:22 eficas Exp $" +__version__="$Name: $" +__Id__="$Id: compomacro.py,v 1.2 2002/04/03 11:35:12 eficas Exp $" # class MACROPanel(panels.OngletPanel): @@ -187,6 +187,11 @@ class MACROTreeItem(compooper.EtapeTreeItem): Ce nom dépend de la validité de l'objet """ if self.object.isactif(): + if self.object.state != 'unchanged': + # Si des modifications ont eu lieu on force le calcul des concepts de sortie + # et celui du contexte glissant + self.object.get_type_produit(force=1) + self.object.parent.reset_context() if self.object.isvalid(): return "ast-green-square" else: @@ -230,6 +235,7 @@ class MACROTreeItem(compooper.EtapeTreeItem): # item.object = MCSIMP, MCFACT, MCBLOC ou MCList if item.object.isoblig() : self.appli.affiche_infos('Impossible de supprimer un mot-clé obligatoire ') + print "Impossible de supprimer un mot-clé obligatoire" return 0 else : self.object.suppentite(item.object) @@ -274,10 +280,6 @@ class MACROTreeItem(compooper.EtapeTreeItem): def verif_condition_bloc(self): return self.object.verif_condition_bloc() - def nomme_sd(self,nom): - """ Lance la méthode de nommage de la SD """ - return self.object.nomme_sd(nom) - def get_noms_sd_oper_reentrant(self): return self.object.get_noms_sd_oper_reentrant() diff --git a/Editeur/compomclist.py b/Editeur/compomclist.py index 74f5254e..5fc08afb 100644 --- a/Editeur/compomclist.py +++ b/Editeur/compomclist.py @@ -39,7 +39,35 @@ class MCListTreeItem(Objecttreeitem.SequenceTreeItem): Retourne 1 si l'objet pointé par self est un MCFact, 0 sinon """ return 0 - + + def isMCList(self): + """ + Retourne 1 si l'objet pointé par self est une MCList, 0 sinon + """ + return 1 + + def additem(self,obj,pos): + """ + Ajoute un objet MCFACT à la MCList (self.object) à la position pos + """ + self.object.init_modif() + obj.verif_existence_sd() + obj.reparent(self.object.parent) + self.object.insert(pos,obj) + item = self.make_objecttreeitem(self.appli, obj.nom + ":", obj) + return item + + def suppitem(self,item): + """ + Retire un objet MCFACT de la MCList (self.object) + """ + self.object.init_modif() + self.object.remove(item.object) + # la liste peut être retournée vide ! + message = "Mot-clé " + item.object.nom + " supprimé" + self.appli.affiche_infos(message) + return 1 + import Accas treeitem = MCListTreeItem objet = Accas.MCList diff --git a/Editeur/compooper.py b/Editeur/compooper.py index eceb5cf8..e356edb9 100644 --- a/Editeur/compooper.py +++ b/Editeur/compooper.py @@ -7,6 +7,7 @@ # ====================================================================== from Tkinter import * import Pmw +import traceback import Objecttreeitem import panels import fontes @@ -68,7 +69,8 @@ class OPERPanel(panels.OngletPanel): choix = self.listbox.getcurselection()[0] self.valeur_choisie.set(choix) except: - pass + traceback.print_exc() + def choose_valeur_from_list(self,command): try: @@ -76,7 +78,7 @@ class OPERPanel(panels.OngletPanel): self.valeur_choisie.set(choix) apply(command,(),{}) except: - pass + traceback.print_exc() class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): panel = OPERPanel @@ -189,7 +191,9 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): def nomme_sd(self,nom): """ Lance la méthode de nommage de la SD """ - return self.object.nomme_sd(nom) + test,mess= self.object.nomme_sd(nom) + if test:self.object.parent.reset_context() + return test,mess def is_reentrant(self): return self.object.is_reentrant() @@ -218,6 +222,16 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): commande_comment.jdc = commande_comment.parent = self.object.jdc return commande_comment + def replace_child(self,old_item,new_item): + """ + Remplace old_item.object par new_item.object dans les fils de self.object + """ + index = self.object.mc_liste.index(old_item.object) + self.object.init_modif() + self.object.mc_liste.remove(old_item.object) + self.object.mc_liste.insert(index,new_item.object) + self.object.fin_modif() + import Accas treeitem = EtapeTreeItem objet = Accas.ETAPE diff --git a/Editeur/compoproc.py b/Editeur/compoproc.py index 7cbc5edf..f802546f 100644 --- a/Editeur/compoproc.py +++ b/Editeur/compoproc.py @@ -130,10 +130,6 @@ class ProcEtapeTreeItem(compooper.EtapeTreeItem): def verif_condition_bloc(self): return self.object.verif_condition_bloc() - def nomme_sd(self,nom): - """ Lance la méthode de nommage de la SD """ - return self.object.nomme_sd(nom) - def get_noms_sd_oper_reentrant(self): return self.object.get_noms_sd_oper_reentrant() diff --git a/Editeur/composimp.py b/Editeur/composimp.py index d7ec659b..837fa925 100644 --- a/Editeur/composimp.py +++ b/Editeur/composimp.py @@ -5,13 +5,16 @@ # SEE THE FILE "LICENSE.TERMS" FOR INFORMATION ON USAGE AND # REDISTRIBUTION OF THIS FILE. # ====================================================================== +# Modules Python import string,types,os from Tkinter import * import Pmw from tkFileDialog import * from tkMessageBox import showinfo from copy import copy,deepcopy +import traceback +# Modules Eficas import Objecttreeitem import prefs import panels @@ -51,7 +54,8 @@ class newSIMPPanel(panels.OngletPanel): def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'): """ - Enregistre val comme valeur de self.node.item.object SANS faire de test de validité + Enregistre val comme valeur de self.node.item.object SANS + faire de test de validité """ if self.parent.modified == 'n' : self.parent.init_modif() if name != None: @@ -67,9 +71,9 @@ class newSIMPPanel(panels.OngletPanel): self.node.racine.verif_all() else : self.node.parent.verif() + self.node.update() if self.node.item.isvalid(): self.node.parent.select() - self.node.update() # ---------------------------------------------------------------------------------------- # Méthodes utlisées pour la manipulation des items dans les listes de choix # ---------------------------------------------------------------------------------------- @@ -196,18 +200,18 @@ class PLUSIEURS_Panel(newSIMPPanel): self.record_valeur(valeur) if self.node.item.isvalid(): self.node.parent.select() - # fermeture de la fenêtre de sélection - if self.ajout_valeurs: - self.ajout_valeurs.quit() + # fermeture de la fenêtre de sélection + if self.ajout_valeurs: + self.ajout_valeurs.quit() def annule_modifs_valeur(self): """ RAZ de la liste des valeurs (annule toutes les valeurs saisies par l'utilisateur) """ self.node.select() - # fermeture de la fenêtre de sélection - if self.ajout_valeurs: - self.ajout_valeurs.quit() + # fermeture de la fenêtre de sélection + if self.ajout_valeurs: + self.ajout_valeurs.quit() def traite_reel(self,valeur): """ @@ -305,7 +309,7 @@ class PLUSIEURS_INTO_Panel(PLUSIEURS_Panel): """ Génère la page de saisie de plusieurs valeurs parmi un ensemble discret de possibles - """ + """ self.ajout_valeurs = None # On récupère la bulle d'aide du panneau, l'objet, min et max (cardinalité de la liste), # la liste des choix et la liste des valeurs @@ -424,12 +428,12 @@ class PLUSIEURS_BASE_Panel(PLUSIEURS_Panel): # Création de l'entry ou de la liste des SD self.label = Label(self.frame_choix,text="Valeur :") self.make_entry(frame = self.frame_choix,command = self.add_valeur_sans_into) - self.label.place(relx=0.05,rely=0.5) - # Création d'un bouton "Importer ..." sur le panel. - bouton_valeurs_fichier = Button(self.frame_choix, - text="Importer ...", - command=self.select_in_file) - bouton_valeurs_fichier.place(relx=0.28,rely=0.7,relwidth=0.6) + self.label.place(relx=0.05,rely=0.5) + # Création d'un bouton "Importer ..." sur le panel. + bouton_valeurs_fichier = Button(self.frame_choix, + text="Importer ...", + command=self.select_in_file) + bouton_valeurs_fichier.place(relx=0.28,rely=0.7,relwidth=0.6) self.ajout_valeurs = None # boutons Ajouter et Supprimer bouton_add = Button(self.frame_boutons_fleches, @@ -441,10 +445,12 @@ class PLUSIEURS_BASE_Panel(PLUSIEURS_Panel): bouton_add.place(relx=0.3,rely=0.35) bouton_sup.place(relx=0.3,rely=0.65) # affichage de l'aide + self.frame_aide.update() self.aide = Label(self.frame_aide, text = aide, justify='center', - anchor='center') + anchor='center', + wraplength=int(self.frame_aide.winfo_width()*0.8)) self.aide.place(relx=0.5,rely=0.5,anchor='center',relwidth=1) self.Liste_valeurs.affiche_liste() # boutons Accepter et Annuler @@ -456,21 +462,24 @@ class PLUSIEURS_BASE_Panel(PLUSIEURS_Panel): command = self.annule_modifs_valeur) for but in (bouton_accepter,bouton_annuler): but.pack(side='left',padx=5) - - def select_in_file(self): - """ Permet d'ouvrir un fichier choisi par l'utilisateur. """ - nom_fichier = askopenfilename(title="Choix fichier :") - if nom_fichier == "": - return - try: - f = open(nom_fichier, "rb") - selection_texte = f.read() - f.close() - self.ajout_valeurs = FenetreDeSelection(self, self.node.item, - titre="Sélection de valeurs", - texte=selection_texte) - except: - showinfo("Erreur de fichier","impossible d'ouvir le fichier "+nom_fichier) + + def select_in_file(self): + """ Permet d'ouvrir un fichier choisi par l'utilisateur. """ + nom_fichier = askopenfilename(title="Choix fichier :") + if nom_fichier == "": + return + try: + f = open(nom_fichier, "rb") + selection_texte = f.read() + f.close() + self.ajout_valeurs = FenetreDeSelection(self, + self.node.item, + self.parent.appli, + titre="Sélection de valeurs", + texte=selection_texte) + except: + traceback.print_exc() + showinfo("Erreur de fichier","impossible d'ouvir le fichier "+nom_fichier) def get_bulle_aide(self): """ @@ -700,22 +709,20 @@ class UNIQUE_Panel(newSIMPPanel): if not test : mess = "impossible d'évaluer : %s " %`valeur` self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess) - return elif self.node.item.isvalid() : self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée') + if self.node.item.get_position()=='global': + self.node.etape.verif_all() + elif self.node.item.get_position()=='global_jdc': + self.node.racine.verif_all() + else : + self.node.parent.verif() + self.node.update() self.node.parent.select() else : cr = self.node.item.get_cr() mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() self.record_valeur(anc_val,mess=mess) - return - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() class UNIQUE_INTO_Panel(UNIQUE_Panel): """ @@ -878,7 +885,7 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): self.listbox.place(relx=0.5,rely=0.3,relheight=0.4,anchor='center') # affichage du bouton 'Nouveau concept' self.b_co = Pmw.OptionMenu(self.frame_valeur,labelpos='w',label_text = "Nouveau concept : ", - items = ('OUI','NON'),menubutton_width=10) + items = ('NON','OUI'),menubutton_width=10) self.b_co.configure(command = lambda e,s=self : s.ask_new_concept()) self.b_co.place(relx=0.05,rely=0.6,anchor='w') self.label_co = Label(self.frame_valeur,text='Nom du nouveau concept :') @@ -888,9 +895,12 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): self.l_resu = Label(self.frame_valeur,text='Structure de donnée choisie :') self.valeur_choisie = StringVar() self.label_valeur = Label(self.frame_valeur,textvariable=self.valeur_choisie) - self.aide = Label(self.frame_valeur, text = aide) + self.frame_valeur.update() + self.aide = Label(self.frame_valeur, + text = aide, + wraplength=int(self.frame_valeur.winfo_width()*0.8), + justify='center') self.aide.place(relx=0.5,rely=0.85,anchor='n') - self.b_co.invoke('NON') # affichage de la valeur courante self.display_valeur() @@ -902,13 +912,66 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): pour valoriser le mot-clé simple courant ou cliquez sur NOUVEAU CONCEPT pour entrer le nom d'un concept non encore existant""" + def valid_valeur(self): + """ + Teste si la valeur fournie par l'utilisateur est une valeur permise : + - si oui, l'enregistre + - si non, restaure l'ancienne valeur + """ + if self.parent.modified == 'n' : self.parent.init_modif() + valeur = self.get_valeur() + self.erase_valeur() + anc_val = self.node.item.get_valeur() + test_CO=self.node.item.is_CO(anc_val) + test = self.node.item.set_valeur(valeur) + if not test : + mess = "impossible d'évaluer : %s " %`valeur` + self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess) + return + elif self.node.item.isvalid() : + self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée') + if test_CO: + # il faut egalement propager la destruction de l'ancien concept + self.node.item.delete_valeur_co(valeur=anc_val) + # et on force le recalcul des concepts de sortie de l'etape + self.node.item.object.etape.get_type_produit(force=1) + # et le recalcul du contexte + self.node.item.object.etape.parent.reset_context() + self.node.parent.select() + else : + cr = self.node.item.get_cr() + mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() + self.record_valeur(anc_val,mess=mess) + return + if self.node.item.get_position()=='global': + self.node.etape.verif_all() + elif self.node.item.get_position()=='global_jdc': + self.node.racine.verif_all() + else : + self.node.parent.verif() + self.node.update() + def valid_nom_concept_co(self,event=None): """ Lit le nom donné par l'utilisateur au concept de type CO qui doit être la valeur du MCS courant et stocke cette valeur """ + if self.parent.modified == 'n' : self.parent.init_modif() + anc_val = self.node.item.get_valeur() nom_concept = self.entry_co.get() - self.node.item.set_valeur_co(nom_concept) + test,mess=self.node.item.set_valeur_co(nom_concept) + if not test: + # On n'a pas pu créer le concept + self.parent.appli.affiche_infos(mess) + return + elif self.node.item.isvalid() : + self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée') + self.node.parent.select() + else : + cr = self.node.item.get_cr() + mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() + self.record_valeur(anc_val,mess=mess) + return if self.node.item.get_position()=='global': self.node.etape.verif_all() elif self.node.item.get_position()=='global_jdc': @@ -932,6 +995,9 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): self.label_valeur.place_forget() self.entry_co.focus() elif new_concept == 'NON': + # On est passe de OUI à NON, on supprime la valeur + self.node.item.delete_valeur_co() + self.record_valeur(name=None,mess="Suppression CO enregistrée") self.label_co.place_forget() self.entry_co.place_forget() self.l_resu.place(relx=0.05,rely=0.7) @@ -942,14 +1008,40 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): Affiche la valeur de l'objet pointé par self """ valeur = self.node.item.get_valeur() - if valeur == None : return # pas de valeur à afficher ... + if valeur == None or valeur == '': + self.valeur_choisie.set('') + return # pas de valeur à afficher ... # il faut configurer le bouton si la valeur est un objet CO # sinon afficher le nom du concept dans self.valeur_choisie - if valeur.__class__.__name__ != 'CO': - self.valeur_choisie.set(valeur.nom) - else: + if self.node.item.is_CO(): self.b_co.invoke('OUI') self.entry_co.insert(0,valeur.nom) + else: + self.valeur_choisie.set(valeur.nom) + + def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'): + """ + Enregistre val comme valeur de self.node.item.object SANS faire de test de validité + """ + if self.parent.modified == 'n' : self.parent.init_modif() + if name != None: + valeur =name + else : + self.entry_co.delete(0,END) + valeur= self.entry_co.get() + self.node.item.set_valeur_co(valeur) + self.parent.appli.affiche_infos(mess) + # On met a jour le display dans le panneau + self.display_valeur() + if self.node.item.get_position()=='global': + self.node.etape.verif_all() + elif self.node.item.get_position()=='global_jdc': + self.node.racine.verif_all() + else : + self.node.parent.verif() + if self.node.item.isvalid(): + self.node.parent.select() + self.node.update() class UNIQUE_BASE_Panel(UNIQUE_Panel): @@ -980,7 +1072,11 @@ class UNIQUE_BASE_Panel(UNIQUE_Panel): self.entry.bind("",lambda e,c=self.valid_valeur:c()) self.entry.focus() # aide associée au panneau - self.aide = Label(self.frame_valeur, text = aide) + self.frame_valeur.update() + self.aide = Label(self.frame_valeur, + text = aide, + wraplength=int(self.frame_valeur.winfo_width()*0.8), + justify='center') self.aide.place(relx=0.5,rely=0.7,anchor='n') # affichage de la valeur du MCS self.display_valeur() @@ -1047,7 +1143,11 @@ class UNIQUE_COMP_Panel(UNIQUE_Panel): self.entry1.place(relx=0.27,rely = 0.5,relwidth=0.35) self.entry2.place(relx=0.65,rely = 0.5,relwidth=0.35) self.entry1.focus() - self.aide = Label(self.frame_valeur, text = aide) + self.frame_valeur.update() + self.aide = Label(self.frame_valeur, + text = aide, + wraplength=int(self.frame_valeur.winfo_width()*0.8), + justify='center') self.aide.place(relx=0.5,rely=0.7,anchor='n') def get_bulle_aide(self): @@ -1135,7 +1235,6 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): else: # on attend un entier, un réel ou une string self.panel = UNIQUE_BASE_Panel - def SetText(self, text): try: @@ -1218,42 +1317,47 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): def GetMinMax(self): """ Retourne les valeurs min et max de la définition de object """ return self.object.get_min_max() - - def GetMultiplicite(self): - """ A préciser. - Retourne la multiplicité des valeurs affectées à l'objet - représenté par l'item. Pour le moment retourne invariablement 1. - """ - return 1 - - def GetType(self): - """ Retourne le type de valeur attendu par l'objet représenté par l'item. - """ - return self.object.get_type() - - def GetIntervalle(self): - """ Retourne le domaine de valeur attendu par l'objet représenté par l'item. - """ - return self.object.getintervalle() - - def IsInIntervalle(self,valeur): - """ Retourne 1 si la valeur est dans l'intervalle permis par - l'objet représenté par l'item. - """ - return self.object.isinintervalle(valeur) + + def GetMultiplicite(self): + """ A préciser. + Retourne la multiplicité des valeurs affectées à l'objet + représenté par l'item. Pour le moment retourne invariablement 1. + """ + return 1 + + def GetType(self): + """ + Retourne le type de valeur attendu par l'objet représenté par l'item. + """ + return self.object.get_type() + + def GetIntervalle(self): + """ + Retourne le domaine de valeur attendu par l'objet représenté + par l'item. + """ + return self.object.getintervalle() + + def IsInIntervalle(self,valeur): + """ + Retourne 1 si la valeur est dans l'intervalle permis par + l'objet représenté par l'item. + """ + return self.object.isinintervalle(valeur) def set_valeur_co(self,nom_co): """ Affecte au MCS pointé par self l'objet de type CO et de nom nom_co """ - self.object.set_valeur_co(nom_co) + return self.object.set_valeur_co(nom_co) def get_sd_avant_du_bon_type(self): """ Retourne la liste des noms des SD présentes avant l'étape qui contient le MCS pointé par self et du type requis par ce MCS """ - return self.object.jdc.get_sd_avant_du_bon_type(self.object.etape,self.object.definition.type) + return self.object.etape.parent.get_sd_avant_du_bon_type(self.object.etape, + self.object.definition.type) def GetListeValeurs(self) : """ Retourne la liste des valeurs de object """ @@ -1272,6 +1376,34 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): - retourne 'valeur' (chaîne de caractères) sinon """ return self.object.eval_valeur(valeur) + def is_CO(self,valeur=None): + """ + Indique si valeur est un concept produit de la macro + Cette méthode n'a de sens que pour un MCSIMP d'une MACRO + Si valeur vaut None on teste la valeur du mot cle + """ + # Pour savoir si un concept est un nouveau concept de macro + # on regarde s'il est présent dans l'attribut sdprods de l'étape + # ou si son nom de classe est CO. + # Il faut faire les 2 tests car une macro non valide peut etre + # dans un etat pas tres catholique avec des CO pas encore types + # et donc pas dans sdprods (resultat d'une exception dans type_sdprod) + if not valeur:valeur=self.object.valeur + if valeur in self.object.etape.sdprods:return 1 + if type(valeur) is not types.ClassType:return 0 + if valeur.__class__.__name__ == 'CO':return 1 + return 0 + + def delete_valeur_co(self,valeur=None): + """ + Supprime la valeur du mot cle (de type CO) + il faut propager la destruction aux autres etapes + """ + if not valeur : valeur=self.object.valeur + # XXX faut il vraiment appeler del_sdprod ??? + #self.object.etape.parent.del_sdprod(valeur) + self.object.etape.parent.delete_concept(valeur) + import Accas treeitem = SIMPTreeItem objet = Accas.MCSIMP diff --git a/Editeur/eficas.py b/Editeur/eficas.py index c1d683c1..e8d46db4 100644 --- a/Editeur/eficas.py +++ b/Editeur/eficas.py @@ -17,7 +17,10 @@ from widgets import Fenetre class EFICAS(appli.APPLI): - extensions=['readercata','bureau','browser','options'] + try: + from prefs import extensions + except: + extensions=['readercata','bureau','browser','options'] def get_texte_infos(self): texte=appli.APPLI.get_texte_infos(self) diff --git a/Editeur/jdcdisplay.py b/Editeur/jdcdisplay.py index d85ab06a..b78d2d24 100644 --- a/Editeur/jdcdisplay.py +++ b/Editeur/jdcdisplay.py @@ -25,6 +25,7 @@ class JDCDISPLAY: self.jdc=jdc self.nom_jdc=nom_jdc self.fichier=None + self.panel_courant=None if not appli: class Appli: @@ -78,13 +79,32 @@ class JDCDISPLAY: Lance la génération du panneau contextuel de l'objet sélectionné dans l'arbre """ + if self.panel_courant: + # On detruit le panneau + self.panel_courant.destroy() + o=self.panel_courant + self.panel_courant=None + # Mettre à 1 pour verifier les cycles entre objets + # pour les panneaux + withCyclops=0 + if withCyclops: + from Misc import Cyclops + z = Cyclops.CycleFinder() + z.register(o) + del o + z.find_cycles() + z.show_stats() + z.show_cycles() + + if node.item.isactif(): if hasattr(node.item,"panel"): - return node.item.panel(self,self.pane.pane('selected'),node) + self.panel_courant=node.item.panel(self,self.pane.pane('selected'),node) else: raise Exception("Le noeud sélectionné n'a pas de panel associé") else: - return panels.Panel_Inactif(self,self.pane.pane('selected'),node) + self.panel_courant = panels.Panel_Inactif(self,self.pane.pane('selected'),node) + return self.panel_courant def init_modif(self): """ @@ -148,7 +168,7 @@ class JDCDISPLAY: Ne permet que la copie d'objets de type Commande ou MCF """ objet_a_copier = self.appli.noeud_a_editer.item.get_copie_objet() - if objet_a_copier.__class__.__name__ in ('ETAPE','PROC_ETAPE','MACRO_ETAPE'): + if objet_a_copier.__class__.__name__ in ('ETAPE','PROC_ETAPE','MACRO_ETAPE','FORM_ETAPE'): self.doPaste_Commande(objet_a_copier) elif objet_a_copier.__class__.__name__ == "MCFACT": self.doPaste_MCF(objet_a_copier) @@ -159,14 +179,16 @@ class JDCDISPLAY: def doPaste_Commande(self,objet_a_copier): """ - Réalise la copie de l'objet passé en argument qui est nécessairement une commande + Réalise la copie de l'objet passé en argument qui est nécessairement + une commande """ # il faut vérifier que le noeud sélectionné (noeud courant) est bien # une commande ou un JDC sinon la copie est impossible ... if self.node_selected.item.isCommande() : child = self.node_selected.append_brother(objet_a_copier,retour='oui') elif self.node_selected.item.isJdc() : - child = self.node_selected.append_child(objet_a_copier,retour='oui') + child = self.node_selected.append_child(objet_a_copier,pos='first', + retour='oui') else: showinfo("Copie impossible", "Vous ne pouvez coller la commande copiée à ce niveau de l'arborescence !") @@ -195,10 +217,17 @@ class JDCDISPLAY: child = self.node_selected.append_child(objet_a_copier,retour='oui') elif self.node_selected.item.isMCList() : # le noeud courant est une MCList - child = self.node_selected.parent.append_child(objet_a_copier,retour='oui') + child = self.node_selected.parent.append_child(objet_a_copier,pos='first',retour='oui') elif self.node_selected.item.isMCFact(): # le noeud courant est un MCFACT - child = self.node_selected.parent.append_child(objet_a_copier,retour='oui') + if self.node_selected.parent.item.isMCList(): + # le noeud selectionne est un MCFACT dans une MCList + child = self.node_selected.parent.append_child(objet_a_copier, + pos=self.node_selected.item, + retour='oui') + else: + # le noeud MCFACT selectionne n'est pas dans une MCList + child = self.node_selected.parent.append_child(objet_a_copier,retour='oui') else: showinfo("Copie impossible", "Vous ne pouvez coller le mot-clé facteur copié à ce niveau de l'arborescence !") diff --git a/Editeur/menubar.py b/Editeur/menubar.py index ad2366e8..dd1f8d1d 100644 --- a/Editeur/menubar.py +++ b/Editeur/menubar.py @@ -12,7 +12,10 @@ class MENUBAR: self.parent.configure(menu=self.menubar) self.init() - labels= ('Fichier','Edition','Jeu de commandes','Catalogue','Browsers','Options') + try: + from prefs import labels + except: + labels= ('Fichier','Edition','Jeu de commandes','Catalogue','Browsers','Options') def init(self): self.menudict={} @@ -21,11 +24,3 @@ class MENUBAR: self.menudict[label]=menu self.menubar.add_cascade(label=label,menu=menu) - #self.optionmenu.add_command(label='Catalogue développeur',command=self.choix_cata_developpeur) - - #self.browsermenu.add_command(label='Browser catalogue',command = self.browser_catalogue) - #self.browsermenu.add_command(label='Shell',command = self.shell) - #self.browsermenu.add_command(label='Editeur catalogue',command = self.edite_catalogue) - - - diff --git a/Editeur/panels.py b/Editeur/panels.py index 8338308a..78d292ae 100644 --- a/Editeur/panels.py +++ b/Editeur/panels.py @@ -29,6 +29,32 @@ class Panel(Frame) : self.creer_boutons() self.init() + def destroy(self): + Frame.destroy(self) + self.panneau=None + self.parent=None + # Because on herite de Frame + self.master=None + # On supprime explicitement les references aux objets Tk + self.nb=None + self.fr_but=None + self.bouton_cata=None + self.bouton_doc=None + self.bouton_com=None + self.bouton_sup=None + self.frame_eval=None + self.label=None + self.frame_boutons=None + self.frame_comment=None + self.frame_param=None + # On termine la suppression de facon brutale (objets Tk et non Tk) + for k in self.__dict__.keys(): + # il est plus prudent de ne pas détruire le lien sur le Node + # si on voulait mettre l'attribut node à None, il faudrait + # que tous les appels à node.parent.select() apparaissent après + # toutes les autres actions liées au panel (node.item.isglobal(), ...) + if k != 'node' : setattr(self,k,None) + def creer_boutons(self): """ Méthode créant les boutons se trouvant dans la partie contextuelle d'EFICAS @@ -152,7 +178,6 @@ class Panel(Frame) : if self.parent.modified == 'n' : self.parent.init_modif() pere = self.node.parent self.node.delete() - pere.select() def affiche(self): """ Force l'affichage des fenêtres en cours """ diff --git a/Editeur/treeitemincanvas.py b/Editeur/treeitemincanvas.py index 5ec26438..a9f60e76 100644 --- a/Editeur/treeitemincanvas.py +++ b/Editeur/treeitemincanvas.py @@ -25,7 +25,7 @@ class TREEITEMINCANVAS: self.parent=parent self.item=Objecttreeitem.make_objecttreeitem(self.appli,self.nom,self.object) - self.canvas=Pmw.ScrolledCanvas(self.parent,borderframe=1) + self.canvas=Pmw.ScrolledCanvas(self.parent,borderframe=1,canvas_background='gray95') self.canvas.pack(padx=10,pady=10,fill = 'both', expand = 1) if not sel: def sel(event=None): diff --git a/Editeur/treewidget.py b/Editeur/treewidget.py index a0d6554e..e328c184 100644 --- a/Editeur/treewidget.py +++ b/Editeur/treewidget.py @@ -5,7 +5,7 @@ # SEE THE FILE "LICENSE.TERMS" FOR INFORMATION ON USAGE AND # REDISTRIBUTION OF THIS FILE. # ====================================================================== -import os,sys,string,re,types +import os,sys,string,re,types,traceback from Tkinter import * @@ -13,8 +13,8 @@ import fontes import images # -__version__="$Name: V1_1p1 $" -__Id__="$Id: treewidget.py,v 1.1.1.1 2001/12/04 15:38:23 eficas Exp $" +__version__="$Name: $" +__Id__="$Id: treewidget.py,v 1.3 2002/04/03 11:35:12 eficas Exp $" # Fonte_Standard = fontes.standard @@ -468,6 +468,7 @@ class Node : try: self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3]) except: + print "Erreur dans move :" print self print self.item print self.item.object @@ -493,6 +494,7 @@ class Node : try: child.trace_ligne() except: + print "Erreur dans trace_ligne :" print child print child.item.object @@ -521,21 +523,23 @@ class Node : def full_creation(self,name,pos=None): """ - Interface avec ACCAS : création de l'objet de nom name et - du noeud associé. Retourne le noeud fils ainsi créé + Interface avec ACCAS : création de l'objet de nom name et + du noeud associé. Retourne le noeud fils ainsi créé """ item = self.item.additem(name,pos) if item == None or item == 0: # impossible d'ajouter le noeud de nom : name return 0 nature = item.get_nature() - #if nature =="COMMANDE" or nature == "OPERATEUR" or nature == "PROCEDURE": if nature in ("COMMANDE","OPERATEUR","PROCEDURE","COMMENTAIRE", "PARAMETRE","COMMANDE_COMMENTARISEE","PARAMETRE_EVAL"): # on veut ajouter une commande ou un commentaire ou un paramètre # il ne faut pas rechercher un même objet déjà existant # à modifier : il faut tester l'attribut 'repetable' enfant = None + elif self.item.object.isMCList(): + # Dans ce cas on ne fait pas de remplacement. On ne cherche pas un objet de meme nom + enfant=None else : enfant = self.get_node_fils(item.get_nom()) if enfant : @@ -611,6 +615,9 @@ class Node : # on donne la position depuis l'extérieur # (appel de append_child par append_brother par exemple) index = pos + elif type(pos) == types.InstanceType: + # pos est un item. Il faut inserer name apres pos + index = self.item.get_index(pos) +1 else : if type(name) == types.InstanceType: index = self.item.get_index_child(name.nom) @@ -676,6 +683,7 @@ class Node : print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete' nbnew = pere.get_nb_children() pere.redraw(nbnew-nbold) + pere.select() def copynode(self,node,pos) : """ node est le noeud à copier à la position pos de self ( = parent de node) """ @@ -690,15 +698,16 @@ class Node : try : child.item.object.mc_liste = objet_copie.mc_liste except: - pass + traceback.print_exc() #-------------------------------------------------------------- # Méthodes de vérification du contexte et de validité du noeud #-------------------------------------------------------------- - def traite_mclist(self): + def traite_mclist_OLD(self): """ Dans le cas d'une MCList il faut vérifier qu'elle n'est pas vide ou réduite à un seul élément suite à une destruction """ # self représente une MCList + print "on passe par traite_mclist ",len(self.item) if len(self.item) == 0 : # la liste est vide : il faut la supprimer self.delete() @@ -709,6 +718,8 @@ class Node : noeud = self.children[0] if self.parent.delete_child(self): self.parent.append_node_child(noeud.item,pos=index,verif='non') + else: + print "destruction de self impossible !" #if self.parent.delete_child(self): # self.parent.copynode(self.children[0],index) #else : @@ -716,6 +727,26 @@ class Node : else : return + def traite_mclist(self): + """ Dans le cas d'une MCList il faut vérifier qu'elle n'est pas vide + ou réduite à un seul élément suite à une destruction + """ + # self représente une MCList + if len(self.item) == 0 : + # la liste est vide : il faut la supprimer + self.delete() + elif len(self.item) == 1: + # il ne reste plus qu'un élément dans la liste + # il faut supprimer la liste et créer directement l'objet + index = self.parent.children.index(self) + noeud = self.children[0] + noeud.parent = self.parent + self.parent.delete_node_child(self) + self.parent.item.replace_child(self.item,noeud.item) + self.parent.children.insert(index,noeud) + else : + return + def verif_all(self): self.verif_all_children() diff --git a/Exemples/ex11/main.py b/Exemples/ex11/main.py index 08352a34..942472b5 100644 --- a/Exemples/ex11/main.py +++ b/Exemples/ex11/main.py @@ -28,6 +28,16 @@ class concept: """ Retourne 1 si sd est du bon type par rapport à la classe """ return 0 +class cata: + def __init__(self): + CONTEXT.unset_current_cata() + CONTEXT.set_current_cata(self) + + def enregistre(self,commande): + return + +c=cata() + OP1 = OPER(nom='OP1',op=1,sd_prod=concept,reentrant='f', a=SIMP(typ='I'), c=SIMP(typ='I',position='global'), diff --git a/Extensions/commande_comm.py b/Extensions/commande_comm.py index 68bd102d..7e622720 100644 --- a/Extensions/commande_comm.py +++ b/Extensions/commande_comm.py @@ -30,6 +30,7 @@ class COMMANDE_COMM: self.definition=self self.nom = '' self.niveau = self.parent.niveau + self.actif=1 #self.appel = N_utils.callee_where(niveau=2) if reg=='oui' : self.register() @@ -216,3 +217,19 @@ class COMMANDE_COMM: """ return [] + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.get_jdc_root() + self.etape=self + + def verif_existence_sd(self): + """ + Vérifie que les structures de données utilisées dans self existent bien dans le contexte + avant étape, sinon enlève la référence à ces concepts + --> sans objet pour les commandes commentarisées + """ + pass + diff --git a/Extensions/commentaire.py b/Extensions/commentaire.py index 733a2016..21ec130d 100644 --- a/Extensions/commentaire.py +++ b/Extensions/commentaire.py @@ -145,5 +145,12 @@ class COMMENTAIRE : """ return [] - + def get_sdprods(self,nom_sd): + """ + Retourne les concepts produits par la commande + """ + return None + + def verif_existence_sd(self): + pass diff --git a/Extensions/interpreteur_formule.py b/Extensions/interpreteur_formule.py index 7e2dbdf9..ad4db800 100644 --- a/Extensions/interpreteur_formule.py +++ b/Extensions/interpreteur_formule.py @@ -145,6 +145,8 @@ class Interpreteur_Formule: texte = [texte,] for text_arg in texte: text_arg = string.replace(text_arg,'\n','') + # Enleve les espaces + text_arg = string.replace(text_arg,' ','') try: self.l_operateurs.append(self.split_operateurs(text_arg)) except InterpreteurException,e: diff --git a/Extensions/mcnuplet.py b/Extensions/mcnuplet.py index da997b6d..b3753a84 100644 --- a/Extensions/mcnuplet.py +++ b/Extensions/mcnuplet.py @@ -32,6 +32,7 @@ class MCNUPLET(V_MCCOMPO.MCCOMPO,N_MCCOMPO.MCCOMPO): self.niveau = None self.etape = None self.state = 'undetermined' + self.actif=1 self.mc_liste=self.build_mc() def build_mc(self): diff --git a/Extensions/parametre.py b/Extensions/parametre.py index 94f028f0..250eae1d 100644 --- a/Extensions/parametre.py +++ b/Extensions/parametre.py @@ -33,6 +33,7 @@ class PARAMETRE : self.definition=self self.jdc = self.parent = CONTEXT.get_current_step() self.niveau=self.parent.niveau + self.actif=1 self.register() def interprete_valeur(self,val): @@ -249,7 +250,8 @@ class PARAMETRE : """ return [] - + def verif_existence_sd(self): + pass diff --git a/Extensions/parametre_eval.py b/Extensions/parametre_eval.py index 73bf9bd6..8518aa46 100644 --- a/Extensions/parametre_eval.py +++ b/Extensions/parametre_eval.py @@ -36,6 +36,7 @@ class PARAMETRE_EVAL(parametre.PARAMETRE) : self.jdc = self.parent = CONTEXT.get_current_step() self.definition=self self.niveau = self.parent.niveau + self.actif=1 # Ceci est-il indispensable ??? #self.appel = N_utils.callee_where(niveau=2) self.register() @@ -60,6 +61,8 @@ class PARAMETRE_EVAL(parametre.PARAMETRE) : """ if not val : return None d={} + val = string.strip(val) + if val[-1] == ';' : val = val[0:-1] d['EVAL'] = Accas.EVAL try: valeur = eval(val,{},d) diff --git a/Ihm/I_ASSD.py b/Ihm/I_ASSD.py new file mode 100644 index 00000000..cd08c8c9 --- /dev/null +++ b/Ihm/I_ASSD.py @@ -0,0 +1,4 @@ + +class ASSD: + def __repr__(self): + return "concept %s de type %s" % (self.get_name(),self.__class__.__name__) diff --git a/Ihm/I_ETAPE.py b/Ihm/I_ETAPE.py index 8937c110..7450d2c1 100644 --- a/Ihm/I_ETAPE.py +++ b/Ihm/I_ETAPE.py @@ -4,6 +4,13 @@ import string,types from copy import copy +# import rajoutés suite à l'ajout de Build_sd --> à résorber +import traceback +import Noyau +from Noyau import N_Exception +from Noyau.N_Exception import AsException +# fin import à résorber + # Modules EFICAS import I_MCCOMPO @@ -63,7 +70,8 @@ class ETAPE(I_MCCOMPO.MCCOMPO): """ if self.isvalid() : if type(self.definition.op_init) == types.FunctionType : - apply(self.definition.op_init,(self,self.master.g_context)) + # XXX Normalement en mode editeur g_context ne peut pas etre utilisé + apply(self.definition.op_init,(self,self.parent.g_context)) self.state = 'modified' def nomme_sd(self,nom) : @@ -82,7 +90,9 @@ class ETAPE(I_MCCOMPO.MCCOMPO): # Cas particulier des opérateurs réentrants if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide" if self.definition.reentrant == 'o': - self.sd = self.reuse = self.jdc.get_sdprod(nom) + # FR : appel à get_sdprod incorrect : il faut appeler get_sd_avant_etape + #self.sd = self.reuse = self.jdc.get_sdprod(nom) + self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self) if self.sd != None : return 1,"Concept existant" else: @@ -90,8 +100,12 @@ class ETAPE(I_MCCOMPO.MCCOMPO): if self.definition.reentrant == 'f' : sd = self.jdc.get_sd_avant_etape(nom,self) if sd != None : - self.sd = self.reuse = sd - return 1,"Opérateur facultativement réentrant et concept existant trouvé" + # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!! + if isinstance(sd,self.get_type_produit()) : + self.sd = self.reuse = sd + return 1,"Opérateur facultativement réentrant et concept existant trouvé" + else: + return 0,"Concept déjà existant et de mauvais type" else : # il faut éventuellement enlever le lien vers une SD existante car si on passe ici # cela signifie que l'opérateur n'est pas utilisé en mode réentrant. @@ -234,9 +248,11 @@ class ETAPE(I_MCCOMPO.MCCOMPO): etape.state = 'modified' etape.reuse = None etape.sdnom = None + etape.etape=etape etape.mc_liste=[] for objet in self.mc_liste: new_obj = objet.copy() + new_obj.reparent(etape) etape.mc_liste.append(new_obj) return etape @@ -270,3 +286,99 @@ class ETAPE(I_MCCOMPO.MCCOMPO): l.extend(child.get_sd_utilisees()) return l + def get_genealogie(self): + """ + Retourne la liste des noms des ascendants de l'objet self + en s'arretant à la première ETAPE rencontrée + """ + return [self.nom] + + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.get_jdc_root() + self.etape=self + for mocle in self.mc_liste: + mocle.reparent(self) + + def verif_existence_sd(self): + """ + Vérifie que les structures de données utilisées dans self existent bien dans le contexte + avant étape, sinon enlève la référence à ces concepts + """ + for motcle in self.mc_liste : + motcle.verif_existence_sd() + + def Build_sd(self,nom): + """ + Construit le concept produit de l'opérateur. Deux cas + peuvent se présenter : + + - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création + et le nommage du concept. + + - le parent est défini. Dans ce cas, l'étape demande au parent la création et + le nommage du concept. + + """ + if not self.isactif():return + # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui + # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de + # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait + # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style : + # sansnom = AFFE_CHAR_CINE(MODELE=None) + # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger + # cette méthode ici en rajoutant le test manquant ... + if not self.isvalid(sd='non') : return + try: + if self.parent: + sd= self.parent.create_sdprod(self,nom) + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init,(self,self.parent.g_context)) + else: + sd=self.get_sd_prod() + # On n'utilise pas self.definition.op_init car self.parent + # n'existe pas + if sd != None and self.reuse == None: + # On ne nomme le concept que dans le cas de non reutilisation + # d un concept + sd.nom=nom + if self.jdc and self.jdc.par_lot == "NON" : + self.Execute() + return sd + except AsException,e: + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1],e) + except EOFError: + # XXX Normalement le contexte courant doit etre le parent. + # Il n'y a pas de raison de remettre le contexte au parent + #self.reset_current_step() + raise + except : + l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1]+'\n', + string.join(l)) + + + + + + + + + + + + + + + + + + + + + diff --git a/Ihm/I_FONCTION.py b/Ihm/I_FONCTION.py new file mode 100644 index 00000000..44f6a170 --- /dev/null +++ b/Ihm/I_FONCTION.py @@ -0,0 +1,22 @@ +from I_ASSD import ASSD + +class FONCTION(ASSD): + def __init__(self,etape=None,sd=None,reg='oui'): + #ASSD.__init__(self,etape=etape,sd=sd,reg=reg) + if reg=='oui': + self.jdc.register_fonction(self) + + def get_formule(self): + """ + Retourne une formule décrivant self sous la forme d'un tuple : + (nom,type_retourne,arguments,corps) + """ + if hasattr(self.etape,'get_formule'): + # on est dans le cas d'une formule Aster + return self.etape.get_formule() + else: + # on est dans le cas d'une fonction + return (self.nom,'REEL','(REEL:x)','''bidon''') + +class fonction(FONCTION) : pass + diff --git a/Ihm/I_FORM_ETAPE.py b/Ihm/I_FORM_ETAPE.py index 51100165..c45aa676 100644 --- a/Ihm/I_FORM_ETAPE.py +++ b/Ihm/I_FORM_ETAPE.py @@ -56,6 +56,15 @@ class FORM_ETAPE(MACRO_ETAPE): else: return '' + def get_formule(self): + """ + Retourne un tuple décrivant la formule : + (nom,type_retourne,arguments,corps) + """ + t,a,c = self.analyse_formule() + n = self.get_nom() + return (n,t,a,c) + def verif_arguments(self,arguments = None): """ Vérifie si les arguments passés en argument (si aucun prend les arguments courants) diff --git a/Ihm/I_JDC.py b/Ihm/I_JDC.py index 2c26ab8e..7e3fd61f 100644 --- a/Ihm/I_JDC.py +++ b/Ihm/I_JDC.py @@ -6,9 +6,8 @@ import string,linecache # Modules Eficas import I_OBJECT -from Noyau.N_ASSD import assd +from Noyau.N_ASSD import ASSD from Noyau.N_ETAPE import ETAPE -from Noyau.N_CO import CO from Noyau.N_Exception import AsException from Extensions import commentaire,parametre,parametre_eval @@ -21,6 +20,7 @@ class JDC(I_OBJECT.OBJECT): self.niveau=self self.params=[] self.fonctions=[] + self._etape_context=None def get_cmd(self,nomcmd): """ @@ -38,20 +38,32 @@ class JDC(I_OBJECT.OBJECT): l=[] for k,v in d.items(): if type(v) != types.InstanceType : continue - if assd in types_permis or CO in types_permis : - l.append(k) - continue - for type_ok in types_permis: - if type_ok in ('R','I','C','TXM') and v in self.params : l.append(k) - elif type_ok == 'R' and v.__class__.__name__ == 'reel' : l.append(k) - elif type_ok == 'I' and v.__class__.__name__ == 'entier' : l.append(k) - elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : l.append(k) - elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : l.append(k) - elif type(type_ok) != types.ClassType : continue - elif v.__class__ == type_ok or issubclass(v.__class__,type_ok): l.append(k) + # On considère que seul assd indique un type quelconque pas CO + elif self.assd in types_permis : + l.append(k) + elif self.est_permis(v,types_permis): + l.append(k) l.sort() return l + def est_permis(self,v,types_permis): + for type_ok in types_permis: + if type_ok in ('R','I','C','TXM') and v in self.params : + return 1 + elif type_ok == 'R' and v.__class__.__name__ == 'reel' : + return 1 + elif type_ok == 'I' and v.__class__.__name__ == 'entier' : + return 1 + elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : + return 1 + elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : + return 1 + elif type(type_ok) != types.ClassType : + continue + elif v.__class__ == type_ok or issubclass(v.__class__,type_ok): + return 1 + return 0 + def addentite(self,name,pos): """ Ajoute une entite : @@ -83,6 +95,7 @@ class JDC(I_OBJECT.OBJECT): if pos == None : pos = 0 self.etapes.insert(pos,objet) self.editmode=0 + self.reset_context() self.active_etapes() return objet elif name == "PARAMETRE_EVAL": @@ -93,6 +106,7 @@ class JDC(I_OBJECT.OBJECT): if pos == None : pos = 0 self.etapes.insert(pos,objet) self.editmode=0 + self.reset_context() self.active_etapes() return objet elif type(name)==types.InstanceType: @@ -100,10 +114,8 @@ class JDC(I_OBJECT.OBJECT): # existante (par copie donc) # on est donc nécessairement en mode editeur ... objet = name - objet.jdc = objet.parent = self - #XXX current_step n'existe plus. A priori le parent devrait etre self - # ainsi que le step courant. - #objet.parent = self.current_step + # Il ne faut pas oublier de reaffecter le parent d'obj (si copie) + objet.reparent(self) self.set_current_step() if isinstance(objet,ETAPE): if objet.nom_niveau_definition == 'JDC': @@ -115,8 +127,12 @@ class JDC(I_OBJECT.OBJECT): objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet) objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition] self.etapes.insert(pos,objet) + # il faut vérifier que les concepts utilisés par objet existent bien + # à ce niveau d'arborescence + objet.verif_existence_sd() self.active_etapes() self.editmode=0 + self.reset_context() return objet else : # On veut ajouter une nouvelle commande @@ -125,11 +141,13 @@ class JDC(I_OBJECT.OBJECT): cmd=self.get_cmd(name) # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape # auprès du step courant car editmode vaut 1 + # Par contre elle a le bon parent grace a set_current_step e=cmd.make_objet() if pos == None : pos = 0 self.etapes.insert(pos,e) self.reset_current_step() self.editmode=0 + self.reset_context() self.active_etapes() return e except: @@ -151,13 +169,15 @@ class JDC(I_OBJECT.OBJECT): def get_sd_avant_etape(self,nom_sd,etape): return self.get_contexte_avant(etape).get(nom_sd,None) - def get_sd_apres_etape(self,nom_sd,etape): + def get_sd_apres_etape(self,nom_sd,etape,avec='non'): """ Cette méthode retourne la SD de nom nom_sd qui est éventuellement - définie apres etape + définie apres etape + Si avec vaut 'non' exclut etape de la recherche """ ietap=self.etapes.index(etape) - for e in self.etapes[ietap+1:]: + if avec == 'non':ietap=ietap+1 + for e in self.etapes[ietap:]: sd=e.get_sdprods(nom_sd) if sd: if hasattr(e,'reuse'): @@ -165,16 +185,17 @@ class JDC(I_OBJECT.OBJECT): return sd return None - def get_sd_autour_etape(self,nom_sd,etape): + def get_sd_autour_etape(self,nom_sd,etape,avec='non'): """ Fonction: retourne la SD de nom nom_sd qui est éventuellement définie avant ou apres etape Permet de vérifier si un concept de meme nom existe dans le périmètre d'une étape + Si avec vaut 'non' exclut etape de la recherche """ sd=self.get_sd_avant_etape(nom_sd,etape) if sd:return sd - return self.get_sd_apres_etape(nom_sd,etape) + return self.get_sd_apres_etape(nom_sd,etape,avec) def active_etapes(self): """ @@ -267,6 +288,12 @@ class JDC(I_OBJECT.OBJECT): """ self.params.append(param) + def register_fonction(self,fonction): + """ + Cette méthode sert à ajouter une fonction dans la liste des fonctions + """ + self.fonctions.append(fonction) + def delete_param(self,param): """ Supprime le paramètre param de la liste des paramètres @@ -297,6 +324,14 @@ class JDC(I_OBJECT.OBJECT): nom = form.nom if not nom : continue if d.has_key(nom): l_fonctions.append(form.get_formule()) + + # on ajoute les concepts produits par DEFI_VALEUR + # XXX On pourrait peut etre faire plutot le test sur le type + # de concept : entier, reel, complexe, etc. + for k,v in d.items(): + if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',): + l_constantes.append(k) + # on retourne les deux listes return l_constantes,l_fonctions @@ -373,3 +408,69 @@ class JDC(I_OBJECT.OBJECT): linecache.cache[file]=0,0,string.split(text,'\n'),file return file,text + + def get_genealogie(self): + """ + Retourne la liste des noms des ascendants de l'objet self + jusqu'à la première ETAPE parent. + """ + return [] + + def NommerSdprod(self,sd,sdnom): + """ + Nomme la SD apres avoir verifie que le nommage est possible : nom + non utilise + Si le nom est deja utilise, leve une exception + Met le concept créé dans le concept global g_context + """ + # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment + # Le dictionnaire g_context ne représente pas le contexte + # effectif avant une étape. + # Il faut utiliser get_contexte_avant avec une indication de l'étape + # traitée. Pour le moment, il n'y a pas de moyen de le faire : ajouter + # un attribut dans le JDC ??? + if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom + if self._etape_context: + o=self.get_contexte_avant(self._etape_context).get(sdnom,None) + else: + o=self.g_context.get(sdnom,None) + if isinstance(o,ASSD): + raise AsException("Nom de concept deja defini : %s" % sdnom) + + # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja. + # Ajoute a la creation (appel de reg_sd). + self.g_context[sdnom]=sd + sd.nom=sdnom + + def set_etape_context(self,etape): + """ + Positionne l'etape qui sera utilisee dans NommerSdProd pour + decider si le concept passé pourra etre nommé + """ + self._etape_context=etape + + def reset_context(self): + """ + Cette methode reinitialise le contexte glissant pour pouvoir + tenir compte des modifications de l'utilisateur : création + de commandes, nommage de concepts, etc. + """ + self.current_context={} + self.index_etape_courante=0 + + def del_param(self,param): + """ + Supprime le paramètre param de la liste des paramètres + et du contexte gobal + """ + if param in self.params : self.params.remove(param) + if self.g_context.has_key(param.nom) : del self.g_context[param.nom] + + def del_fonction(self,fonction): + """ + Supprime la fonction fonction de la liste des fonctions + et du contexte gobal + """ + if fonction in self.fonctions : self.fonctions.remove(fonction) + if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom] + diff --git a/Ihm/I_MACRO_ETAPE.py b/Ihm/I_MACRO_ETAPE.py index be318d25..b8a307b8 100644 --- a/Ihm/I_MACRO_ETAPE.py +++ b/Ihm/I_MACRO_ETAPE.py @@ -7,10 +7,19 @@ import traceback,types,string import I_ETAPE from Noyau.N_ASSD import ASSD +# import rajoutés suite à l'ajout de Build_sd --> à résorber +import Noyau +from Noyau import N_Exception +from Noyau.N_Exception import AsException +# fin import à résorber + class MACRO_ETAPE(I_ETAPE.ETAPE): def __init__(self): I_ETAPE.ETAPE.__init__(self) + # XXX CCAR : ne suis pas certain que typret doive etre + # initialise à None (a verifier) + self.typret=None def get_sdprods(self,nom_sd): """ @@ -61,6 +70,10 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): context_ini = context_ini, appli=self.jdc.appli) j.analyse() + # XXX en passant par un jdc auxiliaire, on risque de rendre les etapes inactives + # on les force dans l'etat actif + for etape in j.etapes: + etape.active() except: traceback.print_exc() return None @@ -146,3 +159,48 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # On met g_context à blanc self.g_context={} + def Build_sd(self,nom): + """ + Construit le concept produit de l'opérateur. Deux cas + peuvent se présenter : + + - le parent n'est pas défini. Dans ce cas, l'étape prend en charge + la création et le nommage du concept. + + - le parent est défini. Dans ce cas, l'étape demande au parent la + création et le nommage du concept. + + """ + if not self.isactif():return + try: + # On positionne la macro self en tant que current_step pour que les + # étapes créées lors de l'appel à sd_prod et à op_init aient la macro + # comme parent + self.set_current_step() + if self.parent: + sd= self.parent.create_sdprod(self,nom) + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init,(self,self.parent.g_context)) + else: + sd=self.get_sd_prod() + if sd != None and self.reuse == None: + # On ne nomme le concept que dans le cas de non reutilisation + # d un concept + sd.nom=nom + self.reset_current_step() + if self.jdc and self.jdc.par_lot == "NON" : + self.Execute() + return sd + except AsException,e: + self.reset_current_step() + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1],e) + except EOFError: + #self.reset_current_step() + raise + except : + self.reset_current_step() + l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1]+'\n', + string.join(l)) diff --git a/Ihm/I_MCCOMPO.py b/Ihm/I_MCCOMPO.py index 24f71cca..0fcab2e6 100644 --- a/Ihm/I_MCCOMPO.py +++ b/Ihm/I_MCCOMPO.py @@ -25,24 +25,6 @@ class MCCOMPO(I_OBJECT.OBJECT): else: return self.nom - def get_genealogie(self): - """ - Retourne la liste des noms des ascendants (noms de MCSIMP,MCFACT,MCBLOC - ou ETAPE) de self jusqu'au premier objet etape rencontré - """ - l=[] - objet = self - while objet.definition.label != 'JDC' : - if not objet.isMCList() : - l.append(string.strip(objet.nom)) - else : - pass - # Si objet.etape == etape c'est que objet est l'étape origine de la généalogie - if objet.etape == objet: break - objet = objet.parent - l.reverse() - return l - def get_liste_mc_ordonnee(self,liste,dico): """ Retourne la liste ordonnée (suivant le catalogue) des mots-clés @@ -178,6 +160,7 @@ class MCCOMPO(I_OBJECT.OBJECT): """ self.init_modif() if type(name)==types.StringType : + # on est en mode création d'un motcle if self.ispermis(name) == 0 : return 0 objet=self.definition.entites[name](val=None,nom=name,parent=self) if hasattr(objet.definition,'position'): @@ -186,7 +169,9 @@ class MCCOMPO(I_OBJECT.OBJECT): elif objet.definition.position == 'global_jdc' : self.append_mc_global_jdc(objet) else : + # dans ce cas on est en mode copie d'un motcle objet = name + objet.verif_existence_sd() # si un objet de même nom est déjà présent dans la liste # et si l'objet est répétable # il faut créer une MCList et remplacer l'objet de la liste @@ -219,6 +204,8 @@ class MCCOMPO(I_OBJECT.OBJECT): new_obj.init(objet.nom,self) new_obj.append(old_obj) new_obj.append(objet) + # Il ne faut pas oublier de reaffecter le parent d'obj + objet.reparent(self) self.mc_liste.remove(old_obj) self.mc_liste.insert(index,new_obj) self.fin_modif() @@ -227,12 +214,16 @@ class MCCOMPO(I_OBJECT.OBJECT): # une liste d'objets de même type existe déjà #print "une liste d'objets de même type existe déjà" old_obj.append(objet) + # Il ne faut pas oublier de reaffecter le parent d'obj + objet.reparent(self) self.fin_modif() return old_obj if pos == None : self.mc_liste.append(objet) else : self.mc_liste.insert(pos,objet) + # Il ne faut pas oublier de reaffecter le parent d'obj (si copie) + objet.reparent(self) self.fin_modif() return objet @@ -304,11 +295,18 @@ class MCCOMPO(I_OBJECT.OBJECT): def copy(self): """ Retourne une copie de self """ objet = self.makeobjet() + # FR : attention !!! avec makeobjet, objet a le même parent que self + # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!! + # FR : peut-on passer par là autrement que dans le cas d'une copie ??? + # FR --> je suppose que non + # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet + # Il me semble preferable de changer le parent a la fin quand la copie est acceptee objet.valeur = copy(self.valeur) objet.val = copy(self.val) objet.mc_liste=[] for obj in self.mc_liste: new_obj = obj.copy() + new_obj.reparent(objet) objet.mc_liste.append(new_obj) return objet @@ -365,3 +363,20 @@ class MCCOMPO(I_OBJECT.OBJECT): liste_retraits.append(k) return liste_ajouts,liste_retraits + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.get_jdc_root() + self.etape=parent.etape + for mocle in self.mc_liste: + mocle.reparent(self) + + def verif_existence_sd(self): + """ + Vérifie que les structures de données utilisées dans self existent bien dans le contexte + avant étape, sinon enlève la référence à ces concepts + """ + for motcle in self.mc_liste : + motcle.verif_existence_sd() diff --git a/Ihm/I_MCLIST.py b/Ihm/I_MCLIST.py index c08a3834..fc4afcf6 100644 --- a/Ihm/I_MCLIST.py +++ b/Ihm/I_MCLIST.py @@ -28,9 +28,13 @@ class MCList: return 0 def isoblig(self): - for i in self.data: - if i.isoblig():return 1 - return 0 + """ + Une MCList n'est jamais obligatoire (même si le MCFACT qu'elle représente l'est + """ + return 0 + #for i in self.data: + # if i.isoblig():return 1 + #return 0 def liste_mc_presents(self): return [] @@ -49,11 +53,17 @@ class MCList: child.delete_concept(sd) def copy(self): + """ + Réalise la copie d'une MCList + """ liste = self.data[0].definition.list_instance() - # XXX Pas de parent ?? - liste.init(self.nom) + # FR -->Il faut spécifier un parent pour la méthode init qui attend 2 arguments ... + liste.init(self.nom,self.parent) for objet in self: new_obj = objet.copy() + # Pour etre coherent avec le constructeur de mots cles facteurs N_FACT.__call__ + # dans lequel le parent de l'element d'une MCList est le parent de la MCList + new_obj.reparent(self.parent) liste.append(new_obj) return liste @@ -93,3 +103,61 @@ class MCList: # Sans objet pour une liste de mots clés facteurs return [],[] + def init_modif(self): + """ + Met l'état de l'objet à modified et propage au parent + qui vaut None s'il n'existe pas + """ + self.state = 'modified' + if self.parent: + self.parent.init_modif() + + def get_etape(self): + """ + Retourne l'étape à laquelle appartient self + Un objet de la catégorie etape doit retourner self pour indiquer que + l'étape a été trouvée + XXX double emploi avec self.etape ??? + """ + if self.parent == None: return None + return self.parent.get_etape() + + def get_genealogie(self): + """ + Retourne la liste des noms des ascendants. + Un objet MCList n'est pas enregistré dans la genealogie. + XXX Meme si le MCFACT fils ne l'est pas lui non plus ???? + """ + if self.parent: + return self.parent.get_genealogie() + else: + return [] + + def get_liste_mc_ordonnee_brute(self,liste,dico): + """ + Retourne la liste ordonnée (suivant le catalogue) BRUTE des mots-clés + d'une entité composée dont le chemin complet est donné sous forme + d'une liste du type :ETAPE + MCFACT ou MCBLOC + ... + """ + for arg in liste: + objet_cata = dico[arg] + dico=objet_cata.dico + return objet_cata.liste + + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.jdc + self.etape=parent.etape + for mcfact in self.data: + mcfact.reparent(parent) + + def verif_existence_sd(self): + """ + Vérifie que les structures de données utilisées dans self existent bien dans le contexte + avant étape, sinon enlève la référence à ces concepts + """ + for motcle in self.data : + motcle.verif_existence_sd() diff --git a/Ihm/I_MCSIMP.py b/Ihm/I_MCSIMP.py index 96fe6ccd..b1709703 100644 --- a/Ihm/I_MCSIMP.py +++ b/Ihm/I_MCSIMP.py @@ -7,10 +7,21 @@ myrepr.maxstring = 100 myrepr.maxother = 100 from Noyau.N_utils import repr_float + +# Attention : les classes ASSD,.... peuvent etre surchargées +# dans le package Accas. Il faut donc prendre des précautions si +# on utilise les classes du Noyau pour faire des tests (isxxxx, ...) +# Si on veut créer des objets comme des CO avec les classes du noyau +# ils n'auront pas les conportements des autres packages (pb!!!) +# Il vaut mieux les importer d'Accas mais problème d'import circulaire, +# on ne peut pas les importer au début. +# On fait donc un import local quand c'est nécessaire (peut occasionner +# des pbs de prformance). from Noyau.N_ASSD import ASSD,assd from Noyau.N_GEOM import GEOM,geom from Noyau.N_CO import CO -from Noyau.N_EVAL import EVAL +# fin attention + from Extensions import parametre import I_OBJECT @@ -82,7 +93,8 @@ class MCSIMP(I_OBJECT.OBJECT): """ for typ in self.definition.type: if type(typ) == types.ClassType : - if typ is CO : return 1 + if issubclass(typ,CO) : + return 1 return 0 def wait_assd(self): @@ -104,7 +116,7 @@ class MCSIMP(I_OBJECT.OBJECT): """ for typ in self.definition.type: if type(typ) == types.ClassType : - if typ in (GEOM,ASSD,geom,assd) or issubclass(typ,GEOM) : + if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) : return 1 return 0 @@ -165,6 +177,8 @@ class MCSIMP(I_OBJECT.OBJECT): # type de nom new_valeur if self.wait_co(): try: + # Pour avoir la classe CO avec tous ses comportements + from Accas import CO self.valeur=CO(new_valeur) except: traceback.print_exc() @@ -204,6 +218,8 @@ class MCSIMP(I_OBJECT.OBJECT): return sd,1 else: d={} + # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ?? + from Accas import EVAL d['EVAL']=EVAL try : objet = eval(new_valeur,d) @@ -238,9 +254,13 @@ class MCSIMP(I_OBJECT.OBJECT): def copy(self): """ Retourne une copie de self """ objet = self.makeobjet() - #XXX est ce utile ?? - objet.valeur = copy(self.valeur) - objet.val = copy(self.val) + # il faut copier les listes et les tuples mais pas les autres valeurs + # possibles (réel,SD,...) + if type(self.valeur) in (types.ListType,types.TupleType): + objet.valeur = copy(self.valeur) + else: + objet.valeur = self.valeur + objet.val = objet.valeur return objet def makeobjet(self): @@ -257,3 +277,100 @@ class MCSIMP(I_OBJECT.OBJECT): if issubclass(self.valeur.__class__,ASSD) : l.append(self.valeur) return l + + def set_valeur_co(self,nom_co): + """ + Affecte à self l'objet de type CO et de nom nom_co + """ + step=self.etape.parent + if nom_co == None or nom_co == '': + new_objet=None + else: + # Pour le moment on importe en local le CO de Accas. + # Si problème de perfs, il faudra faire autrement + from Accas import CO + # Avant de créer un concept il faut s'assurer du contexte : step + # courant + sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui') + if sd: + # Si un concept du meme nom existe deja dans la portée de l'étape + # on ne crée pas le concept + return 0,"un concept de meme nom existe deja" + # Il n'existe pas de concept de meme nom. On peut donc le créer + # Il faut néanmoins que la méthode NommerSdProd de step gère les + # contextes en mode editeur + # Normalement la méthode du Noyau doit etre surchargée + # On déclare l'étape du mot clé comme etape courante pour NommerSdprod + cs= CONTEXT.get_current_step() + CONTEXT.unset_current_step() + CONTEXT.set_current_step(step) + step.set_etape_context(self.etape) + new_objet = CO(nom_co) + CONTEXT.unset_current_step() + CONTEXT.set_current_step(cs) + self.valeur = new_objet + self.val = new_objet + self.init_modif() + step.reset_context() + # On force l'enregistrement de new_objet en tant que concept produit + # de la macro en appelant get_type_produit avec force=1 + self.etape.get_type_produit(force=1) + return 1,"Concept créé" + + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.jdc + self.etape=parent.etape + + def verif_existence_sd(self): + """ + Vérifie que les structures de données utilisées dans self existent bien dans le contexte + avant étape, sinon enlève la référence à ces concepts + """ + l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values() + if type(self.valeur) in (types.TupleType,types.ListType) : + l=[] + for sd in self.valeur: + if isinstance(sd,ASSD) : + if sd in l_sd_avant_etape : + l.append(sd) + else: + l.append(sd) + self.valeur=l + self.init_modif() + else: + if isinstance(self.valeur,ASSD) : + if self.valeur not in l_sd_avant_etape : + self.valeur = None + self.init_modif() + + + def get_min_max(self): + """ + Retourne les valeurs min et max admissibles pour la valeur de self + """ + return self.definition.min,self.definition.max + + + def get_type(self): + """ + Retourne le type attendu par le mot-clé simple + """ + return self.definition.type + + + + + + + + + + + + + + diff --git a/Ihm/I_OBJECT.py b/Ihm/I_OBJECT.py index 559ebcd5..dea18249 100644 --- a/Ihm/I_OBJECT.py +++ b/Ihm/I_OBJECT.py @@ -1,7 +1,13 @@ """ """ +import string + +import Noyau class OBJECT: + from Noyau.N_CO import CO + from Noyau.N_ASSD import assd + def isMCList(self): """ Retourne 1 si self est une MCList (liste de mots-clés), @@ -80,4 +86,23 @@ class OBJECT: """ return [],[] + def get_genealogie(self): + """ + Retourne la liste des noms des ascendants (noms de MCSIMP,MCFACT,MCBLOC + ou ETAPE) de self jusqu'au premier objet etape rencontré + """ + if self.parent: + l=self.parent.get_genealogie() + l.append(string.strip(self.nom)) + return l + else: + return [string.strip(self.nom)] + + def reparent(self,parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent=parent + self.jdc=parent.jdc + diff --git a/Ihm/I_PROC_ETAPE.py b/Ihm/I_PROC_ETAPE.py index ddfdabeb..99a7612c 100644 --- a/Ihm/I_PROC_ETAPE.py +++ b/Ihm/I_PROC_ETAPE.py @@ -1,4 +1,13 @@ import I_ETAPE + + +# import rajoutés suite à l'ajout de Build_sd --> à résorber +import traceback,types +import Noyau +from Noyau import N_Exception +from Noyau.N_Exception import AsException +# fin import à résorber + class PROC_ETAPE(I_ETAPE.ETAPE): def get_sdname(self): return "" @@ -24,3 +33,30 @@ class PROC_ETAPE(I_ETAPE.ETAPE): for child in self.mc_liste : child.delete_concept(sd) + def Build_sd(self): + """ + Cette methode applique la fonction op_init au contexte du parent + et lance l'exécution en cas de traitement commande par commande + Elle doit retourner le concept produit qui pour une PROC est toujours None + En cas d'erreur, elle leve une exception : AsException ou EOFError + """ + if not self.isactif():return + try: + if self.parent: + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init,(self,self.parent.g_context)) + else: + pass + if self.jdc.par_lot == "NON" : + self.Execute() + except AsException,e: + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1],e) + except EOFError: + self.reset_current_step() + raise + except : + l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) + raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], + 'fichier : ',self.appel[1]+'\n', + string.join(l)) diff --git a/Minicode/cata_saturne.py b/Minicode/cata_saturne.py index 40975a2d..d45445c8 100755 --- a/Minicode/cata_saturne.py +++ b/Minicode/cata_saturne.py @@ -11,13 +11,21 @@ JdC = JDC_CATA(code='SATURNE', AU_MOINS_UN('FIN'), A_CLASSER(('DEBUT','POURSUITE'),'FIN') ) - ); + ) # P. RASCLE MMN # remarques diverses sur le catalogue Saturne # - dans les blocs, il faut au moins un mot clé de statut obligatoire # probleme de rafraichissement des blocs dépendants quand la valeur d'un mot cle global (ITURB) passe de 1 à 0 +# Type le plus general +class entier (ASSD):pass +class reel (ASSD):pass +class complexe(ASSD):pass +class liste (ASSD):pass +class chaine (ASSD):pass + + class sonde(ASSD):pass class varsca(ASSD):pass class flusca(ASSD):pass @@ -36,7 +44,35 @@ class tsr23(ASSD):pass class resti(ASSD):pass class maillage(ASSD):pass -class listr8 (ASSD):pass +class modele(ASSD):pass +class matr_asse(ASSD):pass +class cham_elem_sief_r(ASSD):pass +class theta_geom(ASSD):pass +class cham_mater(ASSD):pass +class cara_elem(ASSD):pass +class char_ther(ASSD):pass +class char_meca(ASSD):pass +class nume_ddl(ASSD):pass +class char_acou(ASSD):pass +class listr8 (ASSD):pass +class matr_elem(ASSD):pass +class matr_elem_depl_c(matr_elem):pass +class matr_elem_depl_r(matr_elem):pass +class matr_elem_pres_c(matr_elem):pass +class matr_elem_temp_r(matr_elem):pass + +# matr_asse : +#-------------------------------- +class matr_asse(ASSD):pass +class matr_asse_depl_c(matr_asse):pass +class matr_asse_depl_r(matr_asse):pass +class matr_asse_gene_r(matr_asse):pass +class matr_asse_gene_c(matr_asse):pass +class matr_asse_pres_c(matr_asse):pass +class matr_asse_pres_r(matr_asse):pass +class matr_asse_temp_c(matr_asse):pass +class matr_asse_temp_r(matr_asse):pass + # fin entete @@ -101,6 +137,33 @@ FORMULE = FORM( nom='FORMULE',op=-5,sd_prod=fonction, COMPLEXE = SIMP(typ = 'shell',max=1), ) ; +AFFE_MODELE=OPER(nom="AFFE_MODELE",op=18,sd_prod=modele,docu="U4.41.01-f1", + fr="Affectation des éléments finis sur le maillage",reentrant='n', + MAILLAGE =SIMP(statut='o',typ=(maillage) ), + INFO =SIMP(statut='f',typ='I',defaut=1,into=(1,2) ), + VERIF =SIMP(statut='f',typ='TXM',max=2,into=("MAILLE","NOEUD") ), + ); +NUME_DDL=OPER(nom="NUME_DDL",op=11,sd_prod=nume_ddl,docu="U4.61.11-f",reentrant='n', + fr="Etablissement de la numérotation des ddl avec ou sans renumérotation et du stockage de la matrice", + MATR_RIGI =SIMP(statut='f',typ=(matr_elem_depl_r ,matr_elem_depl_c, + matr_elem_temp_r,matr_elem_pres_c),max=100 ), + MODELE =SIMP(statut='f',typ=modele ), + b_modele =BLOC(condition = "MODELE != None", + CHARGE =SIMP(statut='f',max='**',typ=(char_meca,char_ther,char_acou, ),), + ), + METHODE =SIMP(statut='f',typ='TXM',defaut="MULT_FRONT",into=("MULT_FRONT","LDLT","GCPC") ), + b_mult_front =BLOC(condition="METHODE=='MULT_FRONT'",fr="paramètres associés à la méthode multifrontale", + RENUM =SIMP(statut='f',typ='TXM',into=("MD","MDA","METIS"),defaut="METIS" ), + ), + b_ldlt =BLOC(condition="METHODE=='LDLT'",fr="paramètres associés à la méthode LDLT", + RENUM =SIMP(statut='f',typ='TXM',into=("RCMK","SANS"),defaut="RCMK" ), + ), + b_gcpc =BLOC(condition="METHODE=='GCPC'",fr="paramètres associés à la méthode gradient conjugué", + RENUM =SIMP(statut='f',typ='TXM',into=("RCMK","SANS"),defaut="RCMK" ), + ), + INFO =SIMP(statut='f',typ='I',into=(1,2)), +) ; + DEFI_SONDE = OPER(nom="DEFI_SONDE",op= 1,sd_prod=sonde, docu="U2D1", fr="définition d'une sonde historique avec ses coordonnées", @@ -1229,3 +1292,210 @@ FIN=PROC(nom="FIN",op=9999,repetable='n',fr="Fin d'une ) ; +def macro_matr_asse_ops(self,MODELE,CHAM_MATER,CARA_ELEM,MATR_ASSE, + SOLVEUR,NUME_DDL,CHARGE,INST,**args): + """ + Ecriture de la macro MACRO_MATR_ASSE + """ + ier=0 + # On met le mot cle NUME_DDL dans une variable locale pour le proteger + numeddl=NUME_DDL + # On importe les definitions des commandes a utiliser dans la macro + # Le nom de la variable doit etre obligatoirement le nom de la commande + CALC_MATR_ELEM=self.get_cmd('CALC_MATR_ELEM') + NUME_DDL =self.get_cmd('NUME_DDL') + ASSE_MATRICE =self.get_cmd('ASSE_MATRICE') + # La macro compte pour 1 dans la numerotation des commandes + self.icmd=1 + + if SOLVEUR: + methode=SOLVEUR['METHODE'] + if methode=='LDLT': + if SOLVEUR['RENUM']: + renum=SOLVEUR['RENUM'] + else: + renum='RCMK' + if renum not in ('SANS','RCMK'): + ier=ier+1 + self.cr.fatal("Avec methode LDLT, RENUM doit etre SANS ou RCMK.") + return ier + elif methode=='MULT_FRONT': + if SOLVEUR['RENUM']: + renum=SOLVEUR['RENUM'] + else: + renum='MDA' + if renum not in ('MDA','MD','METIS'): + ier=ier+1 + self.cr.fatal("Avec methode MULT_FRONT, RENUM doit etre MDA, MD ou RCMK.") + return ier + elif methode=='GCPC': + if SOLVEUR['RENUM']: + renum=SOLVEUR['RENUM'] + else: + renum='SANS' + if renum not in ('SANS','RCMK'): + ier=ier+1 + self.cr.fatal("Avec methode GCPC, RENUM doit etre SANS ou RCMK.") + return ier + else: + methode='MULT_FRONT' + renum ='MDA' + + if numeddl in self.sdprods: + # Si le concept numeddl est dans self.sdprods + # il doit etre produit par la macro + # il faudra donc appeler la commande NUME_DDL + lnume = 1 + else: + lnume = 0 + lrigel = 0 + lmasel = 0 + + iocc=0 + for m in MATR_ASSE: + iocc=iocc+1 + option=m['OPTION'] + if iocc == 1 and lnume == 1 and option not in ('RIGI_MECA','RIGI_MECA_LAGR', + 'RIGI_THER','RIGI_ACOU') : + ier=ier+1 + self.cr.fatal("LA PREMIERE OPTION DOIT ETRE RIGI_MECA OU RIGI_THER OU RIGI_ACOU OU RIGI_MECA_LAGR") + return ier + + if m['SIEF_ELGA']!=None and option!='RIGI_GEOM': + ier=ier+1 + self.cr.fatal("SIEF_ELGA N EST ADMIS QU AVEC L OPTION RIGI_GEOM") + return ier + + if m['MODE_FOURIER']!=None and option not in ('RIGI_MECA','RIGI_FLUI_STRU','RIGI_THER'): + ier=ier+1 + self.cr.fatal("MODE_FOURIER N EST ADMIS QU AVEC UNE DES OPTIONS RIGI_MECA RIGI_FLUI_STRU RIGI_THER") + return ier + + if (m['THETA']!=None or m['PROPAGATION']!=None) and option!='RIGI_MECA_LAGR': + ier=ier+1 + self.cr.fatal("PROPAGATION ET,OU THETA NE SONT ADMIS QU AVEC L OPTION RIGI_MECA_LAGR") + return ier + motscles={'OPTION':option} + if option == 'AMOR_MECA': + if (not lrigel or not lmasel): + ier=ier+1 + self.cr.fatal("""POUR CALCULER AMOR_MECA, IL FAUT AVOIR CALCULE + RIGI_MECA ET MASS_MECA AUPARAVANT (DANS LE MEME APPEL)""") + return ier + if CHAM_MATER != None: + motscles['RIGI_MECA'] =rigel + motscles['MASS_MECA'] =masel + if CHARGE != None: + if option[0:9] not in ('MASS_THER','RIGI_GEOM','MASS_ID_M'): + motscles['CHARGE'] =CHARGE + if CHAM_MATER != None: motscles['CHAM_MATER'] =CHAM_MATER + if CARA_ELEM != None: motscles['CARA_ELEM'] =CARA_ELEM + if INST != None: motscles['INST'] =INST + if m['SIEF_ELGA'] : motscles['SIEF_ELGA'] =m['SIEF_ELGA'] + if m['MODE_FOURIER']: motscles['MODE_FOURIER']=m['MODE_FOURIER'] + if m['THETA'] : motscles['THETA'] =m['THETA'] + if m['PROPAGATION'] : motscles['PROPAGATION'] =m['PROPAGATION'] + __a=CALC_MATR_ELEM(MODELE=MODELE,**motscles) + + if option == 'RIGI_MECA': + rigel = __a + lrigel = 1 + if option == 'MASS_MECA': + masel = __a + lmasel = 1 + + if lnume and option in ('RIGI_MECA','RIGI_THER','RIGI_ACOU','RIGI_MECA_LAGR'): + self.DeclareOut('num',numeddl) + # On peut passer des mots cles egaux a None. Ils sont ignores + num=NUME_DDL(MATR_RIGI=__a,METHODE=methode,RENUM=renum) + else: + num=numeddl + + self.DeclareOut('mm',m['MATRICE']) + mm=ASSE_MATRICE(MATR_ELEM=__a,NUME_DDL=num) + return ier + +def macro_matr_asse_prod(self,NUME_DDL,MATR_ASSE,**args): + if not MATR_ASSE: raise AsException("Impossible de typer les concepts resultats") + if not NUME_DDL: raise AsException("Impossible de typer les concepts resultats") + self.type_sdprod(NUME_DDL,nume_ddl) + for m in MATR_ASSE: + opti=m['OPTION'] + + if opti in ( "RIGI_MECA","RIGI_FLUI_STRU","RIGI_MECA_LAGR" , + "MASS_MECA" , "MASS_FLUI_STRU" ,"RIGI_GEOM" ,"RIGI_ROTA", + "AMOR_MECA","IMPE_MECA","MASS_ID_MDEP_R","MASS_ID_MDNS_R", + "ONDE_FLUI","MASS_MECA_DIAG" ) : t=matr_asse_depl_r + + if opti in ( "RIGI_ACOU","MASS_ACOU","AMOR_ACOU",) : t=matr_asse_pres_c + + if opti in ( "RIGI_THER","MASS_THER","RIGI_THER_CONV" , + "RIGI_THER_CONV_D","MASS_ID_MTEM_R","MASS_ID_MTNS_R",) : t=matr_asse_temp_r + + if opti == "RIGI_MECA_HYST" : t= matr_asse_depl_c + + self.type_sdprod(m['MATRICE'],t) + return None + +MACRO_MATR_ASSE=MACRO(nom="MACRO_MATR_ASSE",op=macro_matr_asse_ops,docu="U4.61.21-c", + sd_prod=macro_matr_asse_prod, + fr="Calcul des matrices assemblées (matr_asse_gd) par exemple de rigidité, de masse ", + MODELE =SIMP(statut='o',typ=modele), + CHAM_MATER =SIMP(statut='f',typ=cham_mater), + CARA_ELEM =SIMP(statut='f',typ=cara_elem), + CHARGE =SIMP(statut='f',typ=(char_meca,char_ther,char_acou)), + INST =SIMP(statut='f',typ='R'), + NUME_DDL =SIMP(statut='o',typ=(nume_ddl,CO)), + SOLVEUR =FACT(statut='d',min=01,max=01, + METHODE =SIMP(statut='f',typ='TXM',defaut="MULT_FRONT", + into=("LDLT","MULT_FRONT","GCPC")), + RENUM =SIMP(statut='f',typ='TXM',into=("SANS","RCMK","MD","MDA","METIS")), + ), + MATR_ASSE =FACT(statut='o',min=01,max='**', + MATRICE =SIMP(statut='o',typ=(matr_asse,CO)), + OPTION =SIMP(statut='o',typ='TXM', + into=("RIGI_MECA","MASS_MECA","MASS_MECA_DIAG", + "AMOR_MECA","RIGI_MECA_HYST","IMPE_MECA", + "ONDE_FLUI","RIGI_FLUI_STRU","MASS_FLUI_STRU", + "RIGI_ROTA","RIGI_GEOM","RIGI_MECA_LAGR", + "RIGI_THER","MASS_THER", + "RIGI_ACOU","MASS_ACOU","AMOR_ACOU", + "MASS_ID_MTEM_R","MASS_ID_MTNS_R","MASS_ID_MDEP_R","MASS_ID_MDNS_R",) + ), + SIEF_ELGA =SIMP(statut='f',typ=cham_elem_sief_r), + MODE_FOURIER =SIMP(statut='f',typ='I'), + THETA =SIMP(statut='f',typ=theta_geom), + PROPAGATION =SIMP(statut='f',typ='R'), + ), + TITRE =SIMP(statut='f',typ='TXM',max='**'), + INFO =SIMP(statut='f',typ='I',defaut=1,into=(1,2)), +) ; + + +def defi_valeur_prod(self,IS=None,R8=None,TX=None,C8=None,LS=None): + if IS != None : return entier + if R8 != None : return reel + if TX != None : return chaine + if C8 != None : return complexe + if LS != None : return liste + raise AsException("type de concept resultat non prevu") + +DEFI_VALEUR=MACRO(nom="DEFI_VALEUR",op=-4,sd_prod=defi_valeur_prod, + fr="Affectation d une valeur à une variable Superviseur", + docu="U4.31.04-e1",reentrant='f', + regles=(UN_PARMI('IS','R8','TX','C8','LS'),), + IS =SIMP(statut='f',typ='I',max='**'), + R8 =SIMP(statut='f',typ='R',max='**'), + TX =SIMP(statut='f',typ='TXM',max='**'), + C8 =SIMP(statut='f',typ='C',max='**'), + LS =SIMP(statut='f',typ='L',max='**'), +) ; + +def macro2_prod(self,MODELE,**args): + return maillage + +MACRO2 =MACRO(nom="MACRO2",op= -5 ,docu="U4.61.21-c", + sd_prod=macro2_prod, + fr="Calcul des matrices assemblées (matr_asse_gd) par exemple de rigidité, de masse ", + MODELE =SIMP(statut='o',typ=modele), +); diff --git a/Minicode/eficas_mini.py b/Minicode/eficas_mini.py index c8a97ac1..f7990da3 100755 --- a/Minicode/eficas_mini.py +++ b/Minicode/eficas_mini.py @@ -12,10 +12,30 @@ sys.path[:0]=[prefs.INSTALLDIR] import Editeur from Editeur import eficas_go -if len(sys.argv) > 1 : - # on veut ouvrir un fichier directement au lancement d'Eficas - eficas_go.lance_eficas(code='SATURNE',fichier = sys.argv[1]) +def main(): + if len(sys.argv) > 1 : + # on veut ouvrir un fichier directement au lancement d'Eficas + eficas_go.lance_eficas(code='SATURNE',fichier = sys.argv[1]) + else: + # on veut ouvrir Eficas 'vide' + eficas_go.lance_eficas(code='SATURNE') + +def hidez(): + from Misc import Cyclops + z = Cyclops.CycleFinder() + z.run(main) + z.find_cycles() + z.show_stats() + z.show_cycles() + # z.show_cycleobjs() + # z.show_sccs() + z.show_arcs() + +withCyclops=0 + +if withCyclops: + hidez() else: - # on veut ouvrir Eficas 'vide' - eficas_go.lance_eficas(code='SATURNE') + main() + diff --git a/Validation/V_ETAPE.py b/Validation/V_ETAPE.py index 1152f81f..a5105d37 100644 --- a/Validation/V_ETAPE.py +++ b/Validation/V_ETAPE.py @@ -7,7 +7,7 @@ utilisée par héritage multiple pour composer les traitements. """ # Modules Python -import string,types +import string,types,sys import traceback # Modules EFICAS @@ -118,7 +118,11 @@ class ETAPE(V_MCCOMPO.MCCOMPO): # Erreur pendant le calcul du type retourné if CONTEXT.debug:traceback.print_exc() self.sd=None - if cr == 'oui' : self.cr.fatal('Impossible d affecter un type au résultat') + if cr == 'oui' : + l=traceback.format_exception(sys.exc_info()[0], + sys.exc_info()[1], + sys.exc_info()[2]) + self.cr.fatal('Impossible d affecter un type au résultat\n'+ string.join(l[2:])) return 0 # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la cr\351er if self.reuse: diff --git a/Validation/V_MACRO_ETAPE.py b/Validation/V_MACRO_ETAPE.py index b0531a12..f4ce1892 100644 --- a/Validation/V_MACRO_ETAPE.py +++ b/Validation/V_MACRO_ETAPE.py @@ -7,7 +7,7 @@ utilisée par héritage multiple pour composer les traitements. """ # Modules Python -import string,types +import string,types,sys import traceback # Modules EFICAS @@ -120,7 +120,11 @@ class MACRO_ETAPE(V_ETAPE.ETAPE): # Erreur pendant le calcul du type retourné if CONTEXT.debug:traceback.print_exc() self.sd=None - if cr == 'oui' : self.cr.fatal('Impossible d affecter un type au résultat') + if cr == 'oui' : + l=traceback.format_exception(sys.exc_info()[0], + sys.exc_info()[1], + sys.exc_info()[2]) + self.cr.fatal('Impossible d affecter un type au résultat\n'+string.join(l[2:])) return 0 # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la cr\351er if self.reuse: diff --git a/generator/generator_aplat.py b/generator/generator_aplat.py index c12b6dac..11a9953f 100644 --- a/generator/generator_aplat.py +++ b/generator/generator_aplat.py @@ -268,7 +268,7 @@ class AplatGenerator: text = '' init = self.init + self.sep + obj.nom old_init=self.init - for data in self.data : + for data in obj.data : i=i+1 self.init = init + self.sep + "occurrence n°"+`i` text = text + self.generator(data) @@ -283,7 +283,7 @@ class AplatGenerator: if type(obj.valeur) in (types.TupleType,types.ListType) : # On est en présence d'une liste de valeur rep = '(' - for val in self.valeur: + for val in obj.valeur: if type(val) == types.InstanceType : rep = rep + self.generator(val) +',' else: diff --git a/generator/generator_python.py b/generator/generator_python.py index 6220c818..212efca3 100644 --- a/generator/generator_python.py +++ b/generator/generator_python.py @@ -453,6 +453,8 @@ class PythonGenerator: if hasattr(obj.etape,'sdprods'): if val in obj.etape.sdprods : s = s + "CO('"+ self.generator(val) +"')" + elif val.__class__.__name__ == 'CO': + s = s + "CO('"+ self.generator(val) +"')" else: s = s + self.generator(val) elif isinstance(val,PARAMETRE): @@ -472,6 +474,8 @@ class PythonGenerator: if hasattr(obj.etape,'sdprods'): if val in obj.etape.sdprods : s = "CO('"+ self.generator(val) +"')" + elif val.__class__.__name__ == 'CO': + s = "CO('"+ self.generator(val) +"')" else: s = self.generator(val) elif isinstance(val,PARAMETRE):