From: pascale.noyret Date: Wed, 28 Jan 2015 09:41:32 +0000 (+0100) Subject: chgt noyau pour aster X-Git-Tag: AdaoV0~9 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=479b2809fce994d6fc2fa7046bac6405daa0d706;p=modules%2Feficas.git chgt noyau pour aster --- diff --git a/Noyau/N_ASSD.py b/Noyau/N_ASSD.py index 8c734c14..0e9a566a 100644 --- a/Noyau/N_ASSD.py +++ b/Noyau/N_ASSD.py @@ -1,5 +1,4 @@ -# -*- coding: iso-8859-1 -*- -""" +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -17,212 +16,217 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + +""" """ from N_utils import import_object from N_info import message, SUPERV + class ASSD(object): - """ - Classe de base pour definir des types de structures de donnees ASTER - equivalent d un concept ASTER - """ - idracine="SD" - - def __init__(self, etape=None, sd=None, reg='oui'): - """ - reg est un paramètre qui vaut oui ou non : - - si oui (défaut) : on enregistre la SD auprès du JDC - - si non : on ne l'enregistre pas - """ - self.etape = etape - self.sd = sd - self.nom = None - if etape: - self.parent = etape.parent - else: - self.parent = CONTEXT.get_current_step() - if self.parent : - self.jdc = self.parent.get_jdc_root() - else: - self.jdc = None - - if not self.parent: - self.id = None - elif reg == 'oui' : - self.id = self.parent.reg_sd(self) - else : - self.id = self.parent.o_register(self) - # permet de savoir si le concept a été calculé (1) ou non (0) - self.executed = 0 - # permet de savoir si le catalogue de SD a déjà été supprimé (1) ou non (0) - self.sd_deleted = 0 - if self.parent: - self.order = self.parent.icmd - else: - self.order = 0 - - # attributs pour le Catalogue de Structure de Données Jeveux - # "self.cata_sdj" est un attribut de classe - self.ptr_class_sdj = None - self.ptr_sdj = None - # construit en tant que CO('...') - # 0 : assd normal, 1 : type CO, 2 : type CO typé - self._as_co = 0 - - def _get_sdj(self): - """Retourne le catalogue de SD associé au concept.""" - if self.ptr_sdj is None: - cata_sdj = getattr(self, 'cata_sdj', None) - assert cata_sdj, "The attribute 'cata_sdj' must be defined in the class %s" \ + + """ + Classe de base pour definir des types de structures de donnees ASTER + equivalent d un concept ASTER + """ + idracine = "SD" + + def __init__(self, etape=None, sd=None, reg='oui'): + """ + reg est un paramètre qui vaut oui ou non : + - si oui (défaut) : on enregistre la SD auprès du JDC + - si non : on ne l'enregistre pas + """ + self.etape = etape + self.sd = sd + self.nom = None + if etape: + self.parent = etape.parent + else: + self.parent = CONTEXT.get_current_step() + if self.parent: + self.jdc = self.parent.get_jdc_root() + else: + self.jdc = None + + if not self.parent: + self.id = None + elif reg == 'oui': + self.id = self.parent.reg_sd(self) + else: + self.id = self.parent.o_register(self) + # permet de savoir si le concept a été calculé (1) ou non (0) + self.executed = 0 + if self.parent: + self.order = self.parent.icmd + else: + self.order = 0 + # attributs pour le Catalogue de Structure de Données Jeveux + # "self.cata_sdj" est un attribut de classe + self.ptr_class_sdj = None + self.ptr_sdj = None + # construit en tant que CO('...') + # 0 : assd normal, 1 : type CO, 2 : type CO typé + self._as_co = 0 + + def _get_sdj(self): + """Retourne le catalogue de SD associé au concept.""" + if self.ptr_sdj is None: + cata_sdj = getattr(self, 'cata_sdj', None) + assert cata_sdj, "The attribute 'cata_sdj' must be defined in the class %s" \ % self.__class__.__name__ - assert self.nom, "The attribute 'nom' has not been filled!" - if self.ptr_class_sdj is None: - self.ptr_class_sdj = import_object(cata_sdj) - self.ptr_sdj = self.ptr_class_sdj(nomj=self.nom) - return self.ptr_sdj - - def _del_sdj(self): - """Suppression du catalogue de SD.""" - if self.ptr_sdj is not None: - self.ptr_sdj.supprime(True) - self.ptr_sdj = None - self.ptr_class_sdj = None - - sdj = property(_get_sdj, None, _del_sdj) - - - def __getitem__(self,key): - from strfunc import convert - text_error = convert(_(u"ASSD.__getitem__ est déprécié car la référence à " - u"l'objet ETAPE parent sera supprimée.")) - #raise NotImplementedError(text_error) - from warnings import warn - warn(text_error, DeprecationWarning, stacklevel=2) - return self.etape[key] - - def set_name(self, nom): - """Positionne le nom de self (et appelle sd_init) - """ - self.nom = nom - - def is_typco(self): - """Permet de savoir si l'ASSD est issu d'un type CO. - Retourne: - 0 : ce n'est pas un type CO - 1 : c'est un type CO, non encore typé - 2 : c'est un type CO retypé - """ - return self._as_co - - def change_type(self, new_type): - """Type connu a posteriori (type CO).""" - self.__class__ = new_type - assert self._as_co != 0, 'it should only be called on CO object.' - self._as_co = 2 - - def get_name(self): - """ - Retourne le nom de self, éventuellement en le demandant au JDC - """ - if not self.nom : - try: - self.nom = self.parent.get_name(self) or self.id - except: - self.nom = "" - if self.nom.find('sansnom') != -1 or self.nom == '': - self.nom = self.id - return self.nom - - def supprime(self, force=False): - """ - Cassage des boucles de références pour destruction du JDC. - 'force' est utilisée pour faire des suppressions complémentaires - (voir les formules dans N_FONCTION). - """ - self.supprime_sd() - self.etape = None - self.sd = None - self.jdc = None - self.parent = None - - def supprime_sd(self): - """Supprime la partie du catalogue de SD.""" - # 'del self.sdj' appellerait la méthode '_get_sdj()'... - self._del_sdj() - - def __del__(self): - #message.debug(SUPERV, "__del__ ASSD %s <%s>", getattr(self, 'nom', 'unknown'), self) - pass - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitASSD(self) - - def __getstate__(self): - """ - Cette methode permet de pickler les objets ASSD - Ceci est possible car on coupe les liens avec les objets - parent, etape et jdc qui conduiraient à pickler de nombreux - objets inutiles ou non picklables. - En sortie, l'objet n'est plus tout à fait le même ! - """ - d = self.__dict__.copy() - for key in ('parent', 'etape', 'jdc'): - if d.has_key(key): - del d[key] - for key in d.keys(): - if key[0] == '_': - del d[key] - return d - - def accessible(self): - """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD. - """ - if CONTEXT.debug: print '| accessible ?', self.nom - is_accessible = CONTEXT.get_current_step().sd_accessible() - if CONTEXT.debug: print ' `- is_accessible =', repr(is_accessible) - return is_accessible - - def filter_context(self, context): - """Filtre le contexte fourni pour retirer (en gros) ce qui vient du catalogue.""" - from N_ENTITE import ENTITE - import types - ctxt = {} - for key, value in context.items(): - if type(value) is types.ClassType: - continue - if type(value) is types.ModuleType and value.__name__.startswith('Accas'): - continue - if issubclass(type(value), types.TypeType): - continue - if isinstance(value, ENTITE): - continue - ctxt[key] = value - return ctxt - - def par_lot(self): - """Conserver uniquement pour la compatibilite avec le catalogue v9 dans eficas.""" - #XXX eficas - if not hasattr(self, 'jdc') or self.jdc == None: - val = None - else: - val = self.jdc.par_lot - return val == 'OUI' - - def rebuild_sd(self): - """Conserver uniquement pour la compatibilite avec le catalogue v10 dans eficas.""" + assert self.nom, "The attribute 'nom' has not been filled!" + if self.ptr_class_sdj is None: + self.ptr_class_sdj = import_object(cata_sdj) + self.ptr_sdj = self.ptr_class_sdj(nomj=self.nom) + return self.ptr_sdj + + def _del_sdj(self): + """Suppression du catalogue de SD.""" + if self.ptr_sdj is not None: + self.ptr_sdj.supprime(True) + self.ptr_sdj = None + self.ptr_class_sdj = None + + sdj = property(_get_sdj, None, _del_sdj) + + def __getitem__(self, key): + from strfunc import convert + text_error = convert(_(u"ASSD.__getitem__ est déprécié car la référence à " + u"l'objet ETAPE parent sera supprimée.")) + # raise NotImplementedError(text_error) + from warnings import warn + warn(text_error, DeprecationWarning, stacklevel=2) + return self.etape[key] + + def set_name(self, nom): + """Positionne le nom de self (et appelle sd_init) + """ + self.nom = nom + + def is_typco(self): + """Permet de savoir si l'ASSD est issu d'un type CO. + Retourne: + 0 : ce n'est pas un type CO + 1 : c'est un type CO, non encore typé + 2 : c'est un type CO retypé + """ + return self._as_co + + def change_type(self, new_type): + """Type connu a posteriori (type CO).""" + self.__class__ = new_type + assert self._as_co != 0, 'it should only be called on CO object.' + self._as_co = 2 + + def get_name(self): + """ + Retourne le nom de self, éventuellement en le demandant au JDC + """ + if not self.nom: + try: + self.nom = self.parent.get_name(self) or self.id + except: + self.nom = "" + if self.nom.find('sansnom') != -1 or self.nom == '': + self.nom = self.id + return self.nom + + def supprime(self, force=False): + """ + Cassage des boucles de références pour destruction du JDC. + 'force' est utilisée pour faire des suppressions complémentaires + (voir les formules dans N_FONCTION). + """ + self.supprime_sd() + self.etape = None + self.sd = None + self.jdc = None + self.parent = None + + def supprime_sd(self): + """Supprime la partie du catalogue de SD.""" + # 'del self.sdj' appellerait la méthode '_get_sdj()'... + self._del_sdj() + + def __del__(self): + # message.debug(SUPERV, "__del__ ASSD %s <%s>", getattr(self, 'nom', + # 'unknown'), self) + pass + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitASSD(self) + + def __getstate__(self): + """ + Cette methode permet de pickler les objets ASSD + Ceci est possible car on coupe les liens avec les objets + parent, etape et jdc qui conduiraient à pickler de nombreux + objets inutiles ou non picklables. + En sortie, l'objet n'est plus tout à fait le même ! + """ + d = self.__dict__.copy() + for key in ('parent', 'etape', 'jdc'): + if d.has_key(key): + del d[key] + for key in d.keys(): + if key in ('_as_co', ): + continue + if key[0] == '_': + del d[key] + return d + + def accessible(self): + """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD. + """ + if CONTEXT.debug: + print '| accessible ?', self.nom + is_accessible = CONTEXT.get_current_step().sd_accessible() + if CONTEXT.debug: + print ' `- is_accessible =', repr(is_accessible) + return is_accessible + + def filter_context(self, context): + """Filtre le contexte fourni pour retirer (en gros) ce qui vient du catalogue.""" + from N_ENTITE import ENTITE + import types + ctxt = {} + for key, value in context.items(): + if type(value) is types.ClassType: + continue + if type(value) is types.ModuleType and value.__name__.startswith('Accas'): + continue + if issubclass(type(value), types.TypeType): + continue + if isinstance(value, ENTITE): + continue + ctxt[key] = value + return ctxt + + def par_lot(self): + """Conserver uniquement pour la compatibilite avec le catalogue v9 dans eficas.""" + # XXX eficas + if not hasattr(self, 'jdc') or self.jdc == None: + val = None + else: + val = self.jdc.par_lot + return val == 'OUI' + + def rebuild_sd(self): + """Conserver uniquement pour la compatibilite avec le catalogue v10 dans eficas.""" class assd(ASSD): + def __convert__(cls, valeur): - # On accepte les vraies ASSD et les objets 'entier' et 'reel' - # qui font tout pour se faire passer pour de vrais entiers/réels. + # On accepte les vraies ASSD et les objets 'entier' et 'reel' + # qui font tout pour se faire passer pour de vrais entiers/réels. if isinstance(valeur, ASSD) or type(valeur) in (int, float): return valeur raise ValueError(_(u"On attend un objet concept.")) @@ -230,7 +234,7 @@ class assd(ASSD): class not_checked(ASSD): + def __convert__(cls, valeur): return valeur __convert__ = classmethod(__convert__) - diff --git a/Noyau/N_ASSD_NonAster.py b/Noyau/N_ASSD_NonAster.py index 92aabeb0..8991c724 100644 --- a/Noyau/N_ASSD_NonAster.py +++ b/Noyau/N_ASSD_NonAster.py @@ -16,7 +16,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ diff --git a/Noyau/N_BLOC.py b/Noyau/N_BLOC.py index 97ecbdf6..e9959fc5 100644 --- a/Noyau/N_BLOC.py +++ b/Noyau/N_BLOC.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,14 +16,16 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient la classe de definition BLOC - qui permet de spécifier les caractéristiques des blocs de mots clés + qui permet de spécifier les caractéristiques des blocs de mots clés """ -import types,string,sys +import types +import string +import sys import traceback import N_ENTITE @@ -32,115 +34,122 @@ from N_Exception import AsException from N_types import force_list from strfunc import ufmt + class BLOC(N_ENTITE.ENTITE): - """ - Classe pour definir un bloc de mots-cles - - Cette classe a deux attributs de classe : - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - bloc de mots-clés avec sa définition - - label qui indique la nature de l'objet de définition (ici, BLOC) - - """ - class_instance = N_MCBLOC.MCBLOC - label = 'BLOC' - - def __init__(self,fr="",ang="",docu="",regles=(),statut='f',condition=None, - **args): - - """ - Un bloc est caractérisé par les attributs suivants : - - - fr : chaine de caractere commentaire pour aide en ligne (en francais) - - ang : chaine de caractere commentaire pour aide en ligne (en anglais) - - regles : liste d'objets de type REGLE pour vérifier la cohérence des sous-objets - - statut : obligatoire ('o') ou facultatif ('f') - - condition : chaine de caractère evaluable par l'interpreteur Python - - entites : dictionnaire contenant les sous-objets de self (mots-clés). - La clé du dictionnaire est le nom du mot-clé et la valeur l'objet de - définition correspondant. Cet attribut est initialisé avec l'argument - args de la méthode __init__ - - """ - # Initialisation des attributs - self.fr=fr - self.ang=ang - self.docu=docu - if type(regles)== types.TupleType: - self.regles=regles - else: - self.regles=(regles,) - self.statut=statut - self.condition=condition - self.entites=args - self.affecter_parente() - - def __call__(self,val,nom,parent=None): - """ - Construit un objet MCBLOC a partir de sa definition (self) - de sa valeur (val), de son nom (nom) et de son parent dans l arboresence (parent) - """ - return self.class_instance(nom=nom,definition=self,val=val,parent=parent) - - def verif_cata(self): - """ - Cette méthode vérifie si les attributs de définition sont valides. - Les éventuels messages d'erreur sont écrits dans l'objet compte-rendu (self.cr). - """ - self.check_fr() - self.check_docu() - self.check_regles() - self.check_statut(into=('f', 'o')) - self.check_condition() - self.verif_cata_regles() - - def verif_presence(self,dict,globs): - """ - Cette méthode vérifie si le dictionnaire passé en argument (dict) - est susceptible de contenir un bloc de mots-clés conforme à la - définition qu'il porte. - - Si la réponse est oui, la méthode retourne 1 - - Si la réponse est non, la méthode retourne 0 - - Le dictionnaire dict a pour clés les noms des mots-clés et pour valeurs - les valeurs des mots-clés - """ - # On recopie le dictionnaire pour protéger l'original - dico = bloc_utils() - dico.update(dict) - if self.condition != None : - try: - test = eval(self.condition,globs,dico) - return test - except NameError: - # erreur 'normale' : un mot-clé n'est pas présent et on veut l'évaluer dans la condition - if CONTEXT.debug: - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - print "WARNING : Erreur a l'evaluation de la condition "+string.join(l) - return 0 - except SyntaxError: - # le texte de la condition n'est pas du Python correct --> faute de catalogue - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("Catalogue entite : ", self.nom,", de pere : ", self.pere.nom, - '\n',"Erreur dans la condition : ", self.condition,string.join(l)) - except: - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("Catalogue entite : ", self.nom,", de pere : ", self.pere.nom, - '\n',"Erreur dans la condition : ", self.condition,string.join(l)) - else : - return 0 + + """ + Classe pour definir un bloc de mots-cles + + Cette classe a deux attributs de classe : + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + bloc de mots-clés avec sa définition + - label qui indique la nature de l'objet de définition (ici, BLOC) + + """ + class_instance = N_MCBLOC.MCBLOC + label = 'BLOC' + + def __init__(self, fr="", docu="", regles=(), statut='f', condition=None,ang="", + **args): + """ + Un bloc est caractérisé par les attributs suivants : + + - fr : chaine de caractere commentaire pour aide en ligne (en francais) + - regles : liste d'objets de type REGLE pour vérifier la cohérence des sous-objets + - statut : obligatoire ('o') ou facultatif ('f') + - condition : chaine de caractère evaluable par l'interpreteur Python + - entites : dictionnaire contenant les sous-objets de self (mots-clés). + La clé du dictionnaire est le nom du mot-clé et la valeur l'objet de + définition correspondant. Cet attribut est initialisé avec l'argument + args de la méthode __init__ + + """ + # Initialisation des attributs + self.fr = fr + self.ang = ang + self.docu = docu + if type(regles) == types.TupleType: + self.regles = regles + else: + self.regles = (regles,) + self.statut = statut + self.condition = condition + self.entites = args + self.affecter_parente() + + def __call__(self, val, nom, parent=None): + """ + Construit un objet MCBLOC a partir de sa definition (self) + de sa valeur (val), de son nom (nom) et de son parent dans l arboresence (parent) + """ + return self.class_instance(nom=nom, definition=self, val=val, parent=parent) + + def verif_cata(self): + """ + Cette méthode vérifie si les attributs de définition sont valides. + Les éventuels messages d'erreur sont écrits dans l'objet compte-rendu (self.cr). + """ + self.check_fr() + self.check_docu() + self.check_regles() + self.check_statut(into=('f', 'o')) + self.check_condition() + self.verif_cata_regles() + + def verif_presence(self, dict, globs): + """ + Cette méthode vérifie si le dictionnaire passé en argument (dict) + est susceptible de contenir un bloc de mots-clés conforme à la + définition qu'il porte. + + Si la réponse est oui, la méthode retourne 1 + + Si la réponse est non, la méthode retourne 0 + + Le dictionnaire dict a pour clés les noms des mots-clés et pour valeurs + les valeurs des mots-clés + """ + # On recopie le dictionnaire pour protéger l'original + dico = bloc_utils() + dico.update(dict) + if self.condition != None: + try: + test = eval(self.condition, globs, dico) + return test + except NameError: + # erreur 'normale' : un mot-clé n'est pas présent et on veut + # l'évaluer dans la condition + if CONTEXT.debug: + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) + print "WARNING : Erreur a l'evaluation de la condition " + string.join(l) + return 0 + except SyntaxError: + # le texte de la condition n'est pas du Python correct --> + # faute de catalogue + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) + raise AsException( + "Catalogue entite : ", self.nom, ", de pere : ", self.pere.nom, + '\n', "Erreur dans la condition : ", self.condition, string.join(l)) + except: + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) + raise AsException( + "Catalogue entite : ", self.nom, ", de pere : ", self.pere.nom, + '\n', "Erreur dans la condition : ", self.condition, string.join(l)) + else: + return 0 def bloc_utils(): - """Définit un ensemble de fonctions utilisables pour écrire les + """Définit un ensemble de fonctions utilisables pour écrire les conditions de BLOC.""" def au_moins_un(mcsimp, valeurs): """Valide si la (ou une) valeur de 'mcsimp' est au moins une fois dans - la ou les 'valeurs'. Similaire à la règle AU_MOINS_UN, 'mcsimp' peut + la ou les 'valeurs'. Similaire à la règle AU_MOINS_UN, 'mcsimp' peut contenir plusieurs valeurs.""" test = set(force_list(mcsimp)) valeurs = set(force_list(valeurs)) @@ -151,4 +160,3 @@ def bloc_utils(): return not au_moins_un(mcsimp, valeurs) return locals() - diff --git a/Noyau/N_CO.py b/Noyau/N_CO.py index b868a341..5faab5f3 100644 --- a/Noyau/N_CO.py +++ b/Noyau/N_CO.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + from N_ASSD import ASSD from N_Exception import AsException @@ -25,24 +25,27 @@ import N_utils from asojb import AsBase + class CO(ASSD, AsBase): - def __init__(self,nom): - ASSD.__init__(self, etape=None, sd=None, reg='oui') - self._as_co = 1 - # - # On demande le nommage du concept - # - if self.parent : - try: - self.parent.NommerSdprod(self,nom) - except AsException,e: - appel=N_utils.callee_where(niveau=2) - raise AsException("Concept CO, fichier: ",appel[1]," ligne : ",appel[0],'\n',e) - else: - self.nom=nom - def __convert__(cls,valeur): - if valeur.is_typco(): - return valeur - raise ValError("Pas un concept CO") - __convert__=classmethod(__convert__) + def __init__(self, nom): + ASSD.__init__(self, etape=None, sd=None, reg='oui') + self._as_co = 1 + # + # On demande le nommage du concept + # + if self.parent: + try: + self.parent.NommerSdprod(self, nom) + except AsException, e: + appel = N_utils.callee_where(niveau=2) + raise AsException( + "Concept CO, fichier: ", appel[1], " ligne : ", appel[0], '\n', e) + else: + self.nom = nom + + def __convert__(cls, valeur): + if valeur.is_typco(): + return valeur + raise ValError("Pas un concept CO") + __convert__ = classmethod(__convert__) diff --git a/Noyau/N_CONVERT.py b/Noyau/N_CONVERT.py index dbae6342..f2bbc99c 100644 --- a/Noyau/N_CONVERT.py +++ b/Noyau/N_CONVERT.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,88 +16,96 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ - Module de conversion des valeurs saisies par l'utilisateur après vérification. + Module de conversion des valeurs saisies par l'utilisateur après vérification. """ -from N_types import is_int, is_float, is_enum, is_sequence +from N_types import is_int, is_float, is_sequence def has_int_value(real): - """Est-ce que 'real' a une valeur entière ? - """ - return abs(int(real) - real) < 1.e-12 + """Est-ce que 'real' a une valeur entière ? + """ + return abs(int(real) - real) < 1.e-12 class Conversion: - """Conversion de type. - """ - def __init__(self, name, typ): - self.name = name - self.typ = typ - - def convert(self, obj): - """Filtre liste - """ - in_as_seq = is_sequence(obj) - if not in_as_seq: - obj = (obj,) - - result = [] - for o in obj: - result.append(self.function(o)) - - if not in_as_seq: - return result[0] - else: - # ne marche pas avec MACR_RECAL qui attend une liste et non un tuple - return tuple(result) - - def function(self, o): - raise NotImplementedError, 'cette classe doit être dérivée' + + """Conversion de type. + """ + + def __init__(self, name, typ): + self.name = name + self.typ = typ + + def convert(self, obj): + """Filtre liste + """ + in_as_seq = is_sequence(obj) + if not in_as_seq: + obj = (obj,) + + result = [] + for o in obj: + result.append(self.function(o)) + + if not in_as_seq: + return result[0] + else: + # ne marche pas avec MACR_RECAL qui attend une liste et non un + # tuple + return tuple(result) + + def function(self, o): + raise NotImplementedError, 'cette classe doit être dérivée' class TypeConversion(Conversion): - """Conversion de type - """ - def __init__(self, typ): - Conversion.__init__(self, 'type', typ) + + """Conversion de type + """ + + def __init__(self, typ): + Conversion.__init__(self, 'type', typ) class IntConversion(TypeConversion): - """Conversion en entier - """ - def __init__(self): - TypeConversion.__init__(self, 'I') - def function(self, o): - if is_float(o) and has_int_value(o): - o = int(o) - return o + """Conversion en entier + """ + + def __init__(self): + TypeConversion.__init__(self, 'I') + + def function(self, o): + if is_float(o) and has_int_value(o): + o = int(o) + return o class FloatConversion(TypeConversion): - """Conversion de type - """ - def __init__(self): - TypeConversion.__init__(self, 'R') - def function(self, o): - if is_float(o): - o = float(o) - return o + """Conversion de type + """ + + def __init__(self): + TypeConversion.__init__(self, 'R') + + def function(self, o): + if is_float(o): + o = float(o) + return o _convertI = IntConversion() _convertR = FloatConversion() -def ConversionFactory(name, typ): - if name == 'type': - if 'I' in typ: - return _convertI - elif 'R' in typ: - return _convertR - return None - +def ConversionFactory(name, typ): + if name == 'type': + if 'I' in typ: + return _convertI + elif 'R' in typ: + return _convertR + return None diff --git a/Noyau/N_CR.py b/Noyau/N_CR.py index 1b6d0466..02200dfe 100644 --- a/Noyau/N_CR.py +++ b/Noyau/N_CR.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,227 +16,236 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + + """ Ce module contient la classe compte-rendu de validation """ import string from strfunc import convert, ufmt -class CR : - """ - Classe servant à la construction et à l'affichage des objets Comptes-rendus - """ - def __init__(self,verbeux = 'non',debut='',fin='',dec=' '): - """ - Attributs - - verbeux - - debut - - fin - - dec - """ - self.verbeux = verbeux - self.debut=debut - self.fin=fin - self.dec=dec - self.crok=[] - self.crwarn=[] - self.crfatal=[] - self.crexception=[] - self.subcr=[] - - def ok(self,comment): - """ Ajoute un commentaire OK à la liste crok""" - self.crok.append(comment) - - def warn(self,comment): - """ Ajoute un commentaire Warning à la liste crwarn""" - self.crwarn.append(comment) - - def fatal(self, comment, *args): - """Ajoute un commentaire Erreur Fatale à la liste crfatal à formater""" - self.crfatal.append(ufmt(comment, *args)) - - def exception(self,comment): - """ Ajoute un commentaire Exception à la liste crexception""" - self.crexception.append(comment) - - def add(self,cr): - """ Ajoute un objet CR à la liste subcr :il s'agit de l'objet CR d'un fils de self """ - self.subcr.append(cr) - - def estvide(self): - """ - Retourne 1 si self ne contient aucun message grave (fatal ou exception) - et aucun CR qui en contienne, 0 sinon - """ - if self.crexception : return 0 - if self.crfatal : return 0 - for s in self.subcr : - if not s.estvide(): return 0 - return 1 - - def purge(self): - """ - Purge complètement le CR sauf les exceptions - """ - self.debut='' - self.fin='' - self.dec=' ' - self.crok=[] - self.crwarn=[] - self.crfatal=[] - self.subcr=[] - - def beautifie_messages(self): - """ - Beautifie les messages stockés dans crok,crfatal,crexception et crwarn - """ - l=[] - for mess in self.crok: - l.append(mess+'\n') - self.crok_belle=l - l=[] - for mess in self.crwarn: - l.append(encadre_message(mess,'*')) - self.crwarn_belle = l - l=[] - for mess in self.crfatal: - l.append(encadre_message(mess,'!')) - self.crfatal_belle = l - l=[] - for mess in self.crexception: - l.append(encadre_message(mess,'!')) - self.crexception_belle = l - - def indent(self,s): - """ - Insère en tete de chaque ligne du texte s la chaine self.dec - """ - l = string.split(s,'\n') - return self.dec+string.join(l,'\n'+self.dec)[:-3] - - def __unicode__(self): - """ - Retourne une chaine de caractères décorée et représentative de self - """ - s='' - self.beautifie_messages() - s=s+string.join(self.crok_belle,'') - s=s+string.join(self.crwarn_belle,'') - s=s+string.join(self.crfatal_belle,'') - s=s+string.join(self.crexception_belle,'') - for subcr in self.subcr: - if self.verbeux == 'oui': - s=s+unicode(subcr)+'\n' - else: + +class CR: + + """ + Classe servant à la construction et à l'affichage des objets Comptes-rendus + """ + + def __init__(self, verbeux='non', debut='', fin='', dec=' '): + """ + Attributs + - verbeux + - debut + - fin + - dec + """ + self.verbeux = verbeux + self.debut = debut + self.fin = fin + self.dec = dec + self.crok = [] + self.crwarn = [] + self.crfatal = [] + self.crexception = [] + self.subcr = [] + + def ok(self, comment): + """ Ajoute un commentaire OK à la liste crok""" + self.crok.append(comment) + + def warn(self, comment): + """ Ajoute un commentaire Warning à la liste crwarn""" + self.crwarn.append(comment) + + def fatal(self, comment, *args): + """Ajoute un commentaire Erreur Fatale à la liste crfatal à formater""" + self.crfatal.append(ufmt(comment, *args)) + + def exception(self, comment): + """ Ajoute un commentaire Exception à la liste crexception""" + self.crexception.append(comment) + + def add(self, cr): + """ Ajoute un objet CR à la liste subcr :il s'agit de l'objet CR d'un fils de self """ + self.subcr.append(cr) + + def estvide(self): + """ + Retourne 1 si self ne contient aucun message grave (fatal ou exception) + et aucun CR qui en contienne, 0 sinon + """ + if self.crexception: + return 0 + if self.crfatal: + return 0 + for s in self.subcr: + if not s.estvide(): + return 0 + return 1 + + def purge(self): + """ + Purge complètement le CR sauf les exceptions + """ + self.debut = '' + self.fin = '' + self.dec = ' ' + self.crok = [] + self.crwarn = [] + self.crfatal = [] + self.subcr = [] + + def beautifie_messages(self): + """ + Beautifie les messages stockés dans crok,crfatal,crexception et crwarn + """ + l = [] + for mess in self.crok: + l.append(mess + '\n') + self.crok_belle = l + l = [] + for mess in self.crwarn: + l.append(encadre_message(mess, '*')) + self.crwarn_belle = l + l = [] + for mess in self.crfatal: + l.append(encadre_message(mess, '!')) + self.crfatal_belle = l + l = [] + for mess in self.crexception: + l.append(encadre_message(mess, '!')) + self.crexception_belle = l + + def indent(self, s): + """ + Insère en tete de chaque ligne du texte s la chaine self.dec + """ + l = string.split(s, '\n') + return self.dec + string.join(l, '\n' + self.dec)[:-3] + + def __unicode__(self): + """ + Retourne une chaine de caractères décorée et représentative de self + """ + s = '' + self.beautifie_messages() + s = s + string.join(self.crok_belle, '') + s = s + string.join(self.crwarn_belle, '') + s = s + string.join(self.crfatal_belle, '') + s = s + string.join(self.crexception_belle, '') + for subcr in self.subcr: + if self.verbeux == 'oui': + s = s + unicode(subcr) + '\n' + else: + if not subcr.estvide(): + s = s + unicode(subcr) + if s != '': + s = self.debut + '\n' + self.indent(s) + self.fin + '\n' + else: + s = self.debut + '\n' + self.fin + '\n' + return s + + def __str__(self): + """Return the report representation""" + # convert into the output encoding + txt = convert(self.__unicode__()) + return txt + + def report(self, decalage=2): + """ + Retourne une chaine de caractères non encadrée mais représentative de self + """ + s = '' + # on stocke dans s les messages de premier niveau + for mess in self.crok: + s = s + decalage * self.dec + mess + self.dec + '\n' + for mess in self.crwarn: + s = s + decalage * self.dec + mess + self.dec + '\n' + for mess in self.crfatal: + s = s + decalage * self.dec + mess + self.dec + '\n' + for mess in self.crexception: + s = s + decalage * self.dec + mess + self.dec + '\n' + # on récupère les messages des sous comptes-rendus ... + for subcr in self.subcr: if not subcr.estvide(): - s=s+unicode(subcr) - if s != '': - s=self.debut+'\n'+self.indent(s)+self.fin+'\n' - else : - s=self.debut+'\n'+self.fin+'\n' - return s - - def __str__(self): - """Return the report representation""" - # convert into the output encoding - txt = convert(self.__unicode__()) - return txt - - def report(self,decalage = 2): - """ - Retourne une chaine de caractères non encadrée mais représentative de self - """ - s='' - # on stocke dans s les messages de premier niveau - for mess in self.crok : - s=s + decalage*self.dec + mess + self.dec + '\n' - for mess in self.crwarn: - s=s + decalage*self.dec + mess + self.dec + '\n' - for mess in self.crfatal: - s=s + decalage*self.dec + mess + self.dec + '\n' - for mess in self.crexception: - s=s + decalage*self.dec + mess + self.dec + '\n' - # on récupère les messages des sous comptes-rendus ... - for subcr in self.subcr: - if not subcr.estvide(): - s=s+subcr.report(decalage = decalage + 1) - # on rajoute les flags de début et de fin ... (si self n'est pas vide) - if not self.estvide() : - s = (decalage-1)*self.dec+self.debut+'\n'+s+ \ - (decalage-1)*self.dec+self.fin+'\n' - return s - - def get_mess_fatal(self): - """ - Retourne une chaine de caractères contenant les messages de - la liste crfatal (du dernier au premier) - """ - self.crfatal.reverse() - s='' - for elem in self.crfatal : - s=s+elem - self.crfatal.reverse() - return s - - def get_mess_exception(self): - """ - Retourne une chaine de caractères contenant les messages - de la liste crexception (du dernier au premier) - """ - self.crexception.reverse() - s='' - for elem in self.crexception : - s=s+elem - self.crexception.reverse() - return s - - -separateurs=(' ',',','/') -def split(ligne,cesure): - ligne= string.rstrip(ligne) - if len(ligne) <= cesure : - return ligne - else: - coupure=cesure - while ligne[coupure] not in separateurs and coupure > 0: - coupure = coupure - 1 - if coupure == 0: - # Il faut augmenter la cesure - coupure =cesure - while ligne[coupure] not in separateurs and coupure < len(ligne)-1 : + s = s + subcr.report(decalage=decalage + 1) + # on rajoute les flags de début et de fin ... (si self n'est pas vide) + if not self.estvide(): + s = (decalage - 1) * self.dec + self.debut + '\n' + s + \ + (decalage - 1) * self.dec + self.fin + '\n' + return s + + def get_mess_fatal(self): + """ + Retourne une chaine de caractères contenant les messages de + la liste crfatal (du dernier au premier) + """ + self.crfatal.reverse() + s = '' + for elem in self.crfatal: + s = s + elem + self.crfatal.reverse() + return s + + def get_mess_exception(self): + """ + Retourne une chaine de caractères contenant les messages + de la liste crexception (du dernier au premier) + """ + self.crexception.reverse() + s = '' + for elem in self.crexception: + s = s + elem + self.crexception.reverse() + return s + + +separateurs = (' ', ',', '/') + + +def split(ligne, cesure): + ligne = string.rstrip(ligne) + if len(ligne) <= cesure: + return ligne + else: + coupure = cesure + while ligne[coupure] not in separateurs and coupure > 0: + coupure = coupure - 1 + if coupure == 0: + # Il faut augmenter la cesure + coupure = cesure + while ligne[coupure] not in separateurs and coupure < len(ligne) - 1: coupure = coupure + 1 - if coupure == len(ligne)-1: - return ligne - else: - return ligne[:coupure+1]+ '\n' + split(ligne[coupure+1:],cesure) - -def justify_text(texte='',cesure=50): - texte = string.strip(texte) - liste_lignes = string.split(texte,'\n') - l=[split(l,cesure) for l in liste_lignes] - texte_justifie=string.join(l,'\n') - return texte_justifie - -def encadre_message(texte,motif): - """ - Retourne la chaine de caractères texte entourée d'un cadre formés - d'éléments 'motif' - """ - texte = justify_text(texte,cesure=80) - lignes = string.split(texte,'\n') - longueur = 0 - for ligne in lignes : - ligne=string.rstrip(ligne) - if len(ligne)> longueur : longueur = len(ligne) - longueur = longueur + 4 - txt = motif*longueur+'\n' - for ligne in lignes : - txt = txt + motif + ' '+ligne+' '*(longueur-len(motif+ligne)-2)+motif+'\n' - txt = txt + motif*longueur+'\n' - return txt - - - - + if coupure == len(ligne) - 1: + return ligne + else: + return ligne[:coupure + 1] + '\n' + split(ligne[coupure + 1:], cesure) + + +def justify_text(texte='', cesure=50): + texte = string.strip(texte) + liste_lignes = string.split(texte, '\n') + l = [split(l, cesure) for l in liste_lignes] + texte_justifie = string.join(l, '\n') + return texte_justifie + + +def encadre_message(texte, motif): + """ + Retourne la chaine de caractères texte entourée d'un cadre formés + d'éléments 'motif' + """ + texte = justify_text(texte, cesure=80) + lignes = string.split(texte, '\n') + longueur = 0 + for ligne in lignes: + ligne = string.rstrip(ligne) + if len(ligne) > longueur: + longueur = len(ligne) + longueur = longueur + 4 + txt = motif * longueur + '\n' + for ligne in lignes: + txt = txt + motif + ' ' + ligne + ' ' * \ + (longueur - len(motif + ligne) - 2) + motif + '\n' + txt = txt + motif * longueur + '\n' + return txt diff --git a/Noyau/N_ENTITE.py b/Noyau/N_ENTITE.py index 6451850d..4ae2a01a 100644 --- a/Noyau/N_ENTITE.py +++ b/Noyau/N_ENTITE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + + """ Ce module contient la classe ENTITE qui est la classe de base de toutes les classes de definition d'EFICAS. @@ -29,209 +30,225 @@ import N_OPS import N_VALIDATOR from strfunc import ufmt + class ENTITE: - """ - Classe de base pour tous les objets de definition : mots cles et commandes - Cette classe ne contient que des methodes utilitaires - Elle ne peut être instanciee et doit d abord être specialisee - """ - CR=N_CR.CR - factories={'validator':N_VALIDATOR.validatorFactory} - - def __init__(self,validators=None): - """ - Initialise les deux attributs regles et entites d'une classe dérivée - à : pas de règles et pas de sous-entités. - - L'attribut regles doit contenir la liste des regles qui s'appliquent - sur ses sous-entités - - L'attribut entités doit contenir le dictionnaires des sous-entités - (clé = nom, valeur=objet) - """ - self.regles=() - self.entites={} - if validators: - self.validators=self.factories['validator'](validators) - else: - self.validators=validators - - def affecter_parente(self): - """ - Cette methode a pour fonction de donner un nom et un pere aux - sous entités qui n'ont aucun moyen pour atteindre leur parent - directement - Il s'agit principalement des mots cles - """ - for k,v in self.entites.items(): - v.pere = self - v.nom = k - - def verif_cata(self): - """ - Cette methode sert à valider les attributs de l'objet de définition - """ - raise NotImplementedError("La méthode verif_cata de la classe %s doit être implémentée" - % self.__class__.__name__) - - def __call__(self): - """ - Cette methode doit retourner un objet dérivé de la classe OBJECT - """ - raise NotImplementedError("La méthode __call__ de la classe %s doit être implémentée" - % self.__class__.__name__) - - def report(self): - """ - Cette méthode construit pour tous les objets dérivés de ENTITE un - rapport de validation de la définition portée par cet objet - """ - self.cr = self.CR() - self.verif_cata() - for k,v in self.entites.items() : - try : - cr = v.report() - cr.debut = u"Début "+v.__class__.__name__+ ' : ' + k - cr.fin = u"Fin "+v.__class__.__name__+ ' : ' + k - self.cr.add(cr) - except: - self.cr.fatal(_(u"Impossible d'obtenir le rapport de %s %s"), k,`v`) - print "Impossible d'obtenir le rapport de %s %s" %(k,`v`) - print "père =",self - return self.cr - - def verif_cata_regles(self): - """ - Cette méthode vérifie pour tous les objets dérivés de ENTITE que - les objets REGLES associés ne portent que sur des sous-entités - existantes - """ - for regle in self.regles : - l=[] - for mc in regle.mcs : - if not self.entites.has_key(mc) : - l.append(mc) - if l != [] : - txt = str(regle) - self.cr.fatal(_(u"Argument(s) non permis : %r pour la règle : %s"), l, txt) - - def check_definition(self, parent): - """Verifie la definition d'un objet composite (commande, fact, bloc).""" - args = self.entites.copy() - mcs = set() - for nom, val in args.items(): - if val.label == 'SIMP': - mcs.add(nom) - #XXX - #if val.max != 1 and val.type == 'TXM': - #print "#CMD", parent, nom - elif val.label == 'FACT': - val.check_definition(parent) - # CALC_SPEC ! - #assert self.label != 'FACT', \ - #'Commande %s : Mot-clef facteur present sous un mot-clef facteur : interdit !' \ - #% parent - else: - continue - del args[nom] - # seuls les blocs peuvent entrer en conflit avec les mcs du plus haut niveau - for nom, val in args.items(): - if val.label == 'BLOC': - mcbloc = val.check_definition(parent) - #XXX - #print "#BLOC", parent, re.sub('\s+', ' ', val.condition) - #assert mcs.isdisjoint(mcbloc), "Commande %s : Mot(s)-clef(s) vu(s) plusieurs fois : %s" \ - # % (parent, tuple(mcs.intersection(mcbloc))) - return mcs - - def check_op(self, valmin=-9999, valmax=9999): - """Vérifie l'attribut op.""" - if self.op is not None and \ - (type(self.op) is not int or self.op < valmin or self.op > valmax): - self.cr.fatal(_(u"L'attribut 'op' doit être un entier " - u"compris entre %d et %d : %r"), valmin, valmax, self.op) - - def check_proc(self): - """Vérifie l'attribut proc.""" - if self.proc is not None and not isinstance(self.proc, N_OPS.OPS): - self.cr.fatal(_(u"L'attribut op doit être une instance d'OPS : %r"), self.proc) - - def check_regles(self): - """Vérifie l'attribut regles.""" - if type(self.regles) is not tuple: - self.cr.fatal(_(u"L'attribut 'regles' doit être un tuple : %r"), - self.regles) - - def check_fr(self): - """Vérifie l'attribut fr.""" - if type(self.fr) not in (str, unicode): - self.cr.fatal(_(u"L'attribut 'fr' doit être une chaine de caractères : %r"), - self.fr) - - def check_docu(self): - """Vérifie l'attribut docu.""" - if type(self.docu) not in (str, unicode): - self.cr.fatal(_(u"L'attribut 'docu' doit être une chaine de caractères : %r"), - self.docu) - - def check_nom(self): - """Vérifie l'attribut proc.""" - if type(self.nom) != types.StringType : - self.cr.fatal(_(u"L'attribut 'nom' doit être une chaine de caractères : %r"), - self.nom) - - def check_reentrant(self): - """Vérifie l'attribut reentrant.""" - if self.reentrant not in ('o', 'n', 'f'): - self.cr.fatal(_(u"L'attribut 'reentrant' doit valoir 'o','n' ou 'f' : %r"), - self.reentrant) - - def check_statut(self, into=('o', 'f', 'c', 'd')): - """Vérifie l'attribut statut.""" - if self.statut not in into: - self.cr.fatal(_(u"L'attribut 'statut' doit être parmi %s : %r"), - into, self.statut) - - def check_condition(self): - """Vérifie l'attribut condition.""" - if self.condition != None : - if type(self.condition) != types.StringType : - self.cr.fatal(_(u"L'attribut 'condition' doit être une chaine de caractères : %r"), - self.condition) - else: - self.cr.fatal(_(u"La condition ne doit pas valoir None !")) - - def check_min_max(self): - """Vérifie les attributs min/max.""" - if type(self.min) != types.IntType : - if self.min != '**': - self.cr.fatal(_(u"L'attribut 'min' doit être un entier : %r"), self.min) - if type(self.max) != types.IntType : - if self.max != '**': - self.cr.fatal(_(u"L'attribut 'max' doit être un entier : %r"), self.max) - if self.min > self.max : - self.cr.fatal(_(u"Nombres d'occurrence min et max invalides : %r %r"), - self.min, self.max) - - def check_validators(self): - """Vérifie les validateurs supplémentaires""" - if self.validators and not self.validators.verif_cata(): - self.cr.fatal(_(u"Un des validateurs est incorrect. Raison : %s"), - self.validators.cata_info) - - def check_homo(self): - """Vérifie l'attribut homo.""" - if self.homo != 0 and self.homo != 1 : - self.cr.fatal(_(u"L'attribut 'homo' doit valoir 0 ou 1 : %r"), self.homo) - - def check_into(self): - """Vérifie l'attribut into.""" - if self.into != None : - if type(self.into) != types.TupleType : - self.cr.fatal(_(u"L'attribut 'into' doit être un tuple : %r"), self.into) - - def check_position(self): - """Vérifie l'attribut position.""" - if self.position not in ('local', 'global', 'global_jdc'): - self.cr.fatal(_(u"L'attribut 'position' doit valoir 'local', 'global' " - u"ou 'global_jdc' : %r"), self.position) + + """ + Classe de base pour tous les objets de definition : mots cles et commandes + Cette classe ne contient que des methodes utilitaires + Elle ne peut être instanciee et doit d abord être specialisee + """ + CR = N_CR.CR + factories = {'validator': N_VALIDATOR.validatorFactory} + + def __init__(self, validators=None): + """ + Initialise les deux attributs regles et entites d'une classe dérivée + à : pas de règles et pas de sous-entités. + + L'attribut regles doit contenir la liste des regles qui s'appliquent + sur ses sous-entités + + L'attribut entités doit contenir le dictionnaires des sous-entités + (clé = nom, valeur=objet) + """ + self.regles = () + self.entites = {} + if validators: + self.validators = self.factories['validator'](validators) + else: + self.validators = validators + + def affecter_parente(self): + """ + Cette methode a pour fonction de donner un nom et un pere aux + sous entités qui n'ont aucun moyen pour atteindre leur parent + directement + Il s'agit principalement des mots cles + """ + for k, v in self.entites.items(): + v.pere = self + v.nom = k + + def verif_cata(self): + """ + Cette methode sert à valider les attributs de l'objet de définition + """ + raise NotImplementedError("La méthode verif_cata de la classe %s doit être implémentée" + % self.__class__.__name__) + + def __call__(self): + """ + Cette methode doit retourner un objet dérivé de la classe OBJECT + """ + raise NotImplementedError("La méthode __call__ de la classe %s doit être implémentée" + % self.__class__.__name__) + + def report(self): + """ + Cette méthode construit pour tous les objets dérivés de ENTITE un + rapport de validation de la définition portée par cet objet + """ + self.cr = self.CR() + self.verif_cata() + for k, v in self.entites.items(): + try: + cr = v.report() + cr.debut = u"Début " + v.__class__.__name__ + ' : ' + k + cr.fin = u"Fin " + v.__class__.__name__ + ' : ' + k + self.cr.add(cr) + except: + self.cr.fatal( + _(u"Impossible d'obtenir le rapport de %s %s"), k, `v`) + print "Impossible d'obtenir le rapport de %s %s" % (k, `v`) + print "père =", self + return self.cr + + def verif_cata_regles(self): + """ + Cette méthode vérifie pour tous les objets dérivés de ENTITE que + les objets REGLES associés ne portent que sur des sous-entités + existantes + """ + for regle in self.regles: + l = [] + for mc in regle.mcs: + if not self.entites.has_key(mc): + l.append(mc) + if l != []: + txt = str(regle) + self.cr.fatal( + _(u"Argument(s) non permis : %r pour la règle : %s"), l, txt) + + def check_definition(self, parent): + """Verifie la definition d'un objet composite (commande, fact, bloc).""" + args = self.entites.copy() + mcs = set() + for nom, val in args.items(): + if val.label == 'SIMP': + mcs.add(nom) + # XXX + # if val.max != 1 and val.type == 'TXM': + # print "#CMD", parent, nom + elif val.label == 'FACT': + val.check_definition(parent) + # CALC_SPEC ! + # assert self.label != 'FACT', \ + #'Commande %s : Mot-clef facteur present sous un mot-clef facteur : interdit !' \ + #% parent + else: + continue + del args[nom] + # seuls les blocs peuvent entrer en conflit avec les mcs du plus haut + # niveau + for nom, val in args.items(): + if val.label == 'BLOC': + mcbloc = val.check_definition(parent) + # XXX + # print "#BLOC", parent, re.sub('\s+', ' ', val.condition) + assert mcs.isdisjoint(mcbloc), "Commande %s : Mot(s)-clef(s) vu(s) plusieurs fois : %s" \ + % (parent, tuple(mcs.intersection(mcbloc))) + return mcs + + def check_op(self, valmin=-9999, valmax=9999): + """Vérifie l'attribut op.""" + if self.op is not None and \ + (type(self.op) is not int or self.op < valmin or self.op > valmax): + self.cr.fatal(_(u"L'attribut 'op' doit être un entier " + u"compris entre %d et %d : %r"), valmin, valmax, self.op) + + def check_proc(self): + """Vérifie l'attribut proc.""" + if self.proc is not None and not isinstance(self.proc, N_OPS.OPS): + self.cr.fatal( + _(u"L'attribut op doit être une instance d'OPS : %r"), self.proc) + + def check_regles(self): + """Vérifie l'attribut regles.""" + if type(self.regles) is not tuple: + self.cr.fatal(_(u"L'attribut 'regles' doit être un tuple : %r"), + self.regles) + + def check_fr(self): + """Vérifie l'attribut fr.""" + if type(self.fr) not in (str, unicode): + self.cr.fatal( + _(u"L'attribut 'fr' doit être une chaine de caractères : %r"), + self.fr) + + def check_docu(self): + """Vérifie l'attribut docu.""" + if type(self.docu) not in (str, unicode): + self.cr.fatal( + _(u"L'attribut 'docu' doit être une chaine de caractères : %r"), + self.docu) + + def check_nom(self): + """Vérifie l'attribut proc.""" + if type(self.nom) != types.StringType: + self.cr.fatal( + _(u"L'attribut 'nom' doit être une chaine de caractères : %r"), + self.nom) + + def check_reentrant(self): + """Vérifie l'attribut reentrant.""" + if self.reentrant not in ('o', 'n', 'f'): + self.cr.fatal( + _(u"L'attribut 'reentrant' doit valoir 'o','n' ou 'f' : %r"), + self.reentrant) + + def check_statut(self, into=('o', 'f', 'c', 'd')): + """Vérifie l'attribut statut.""" + if self.statut not in into: + self.cr.fatal(_(u"L'attribut 'statut' doit être parmi %s : %r"), + into, self.statut) + + def check_condition(self): + """Vérifie l'attribut condition.""" + if self.condition != None: + if type(self.condition) != types.StringType: + self.cr.fatal( + _(u"L'attribut 'condition' doit être une chaine de caractères : %r"), + self.condition) + else: + self.cr.fatal(_(u"La condition ne doit pas valoir None !")) + + def check_min_max(self): + """Vérifie les attributs min/max.""" + if type(self.min) != types.IntType: + if self.min != '**': + self.cr.fatal( + _(u"L'attribut 'min' doit être un entier : %r"), self.min) + if type(self.max) != types.IntType: + if self.max != '**': + self.cr.fatal( + _(u"L'attribut 'max' doit être un entier : %r"), self.max) + if self.min > self.max: + self.cr.fatal( + _(u"Nombres d'occurrence min et max invalides : %r %r"), + self.min, self.max) + + def check_validators(self): + """Vérifie les validateurs supplémentaires""" + if self.validators and not self.validators.verif_cata(): + self.cr.fatal(_(u"Un des validateurs est incorrect. Raison : %s"), + self.validators.cata_info) + + def check_homo(self): + """Vérifie l'attribut homo.""" + if self.homo != 0 and self.homo != 1: + self.cr.fatal( + _(u"L'attribut 'homo' doit valoir 0 ou 1 : %r"), self.homo) + + def check_into(self): + """Vérifie l'attribut into.""" + if self.into != None: + if type(self.into) != types.TupleType: + self.cr.fatal( + _(u"L'attribut 'into' doit être un tuple : %r"), self.into) + + def check_position(self): + """Vérifie l'attribut position.""" + if self.position not in ('local', 'global', 'global_jdc'): + self.cr.fatal(_(u"L'attribut 'position' doit valoir 'local', 'global' " + u"ou 'global_jdc' : %r"), self.position) diff --git a/Noyau/N_ETAPE.py b/Noyau/N_ETAPE.py index fd1cdaaa..f2b345ca 100644 --- a/Noyau/N_ETAPE.py +++ b/Noyau/N_ETAPE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,14 +16,18 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + + """ - Ce module contient la classe ETAPE qui sert à vérifier et à exécuter + Ce module contient la classe ETAPE qui sert à vérifier et à exécuter une commande """ # Modules Python -import types,sys,string,os +import types +import sys +import string +import os import linecache import traceback from copy import copy @@ -36,410 +40,420 @@ from N_utils import AsType from N_ASSD import ASSD from N_info import message, SUPERV + class ETAPE(N_MCCOMPO.MCCOMPO): - """ - Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite - - """ - nature = "OPERATEUR" - - # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build) - # On le met à None pour indiquer qu'il n'y a pas de module de calcul rattaché - codex=None - - def __init__(self, oper=None, reuse=None, args={}, niveau=4): - """ - Attributs : - - definition : objet portant les attributs de définition d'une étape de type opérateur. Il - est initialisé par l'argument oper. - - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie - si les conditions d'exécution de l'opérateur l'autorise - - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args. - """ - self.definition = oper - self.reuse = reuse - self.valeur = args - self.nettoiargs() - self.parent = CONTEXT.get_current_step() - self.etape = self - self.nom = oper.nom - self.idracine = oper.label - self.appel = N_utils.callee_where(niveau) - self.mc_globaux = {} - self.sd = None - self.actif = 1 - self.make_register() - self.icmd = None - - def make_register(self): - """ - Initialise les attributs jdc, id, niveau et réalise les - enregistrements nécessaires - """ - if self.parent : - self.jdc = self.parent.get_jdc_root() - self.id = self.parent.register(self) - self.niveau = None - else: - self.jdc = self.parent = None - self.id = None - self.niveau = None - - def nettoiargs(self): - """ - Cette methode a pour fonction de retirer tous les arguments egaux à None - de la liste des arguments. Ils sont supposés non présents et donc retirés. - """ - for k in self.valeur.keys(): - if self.valeur[k] == None:del self.valeur[k] - - def McBuild(self): - """ - Demande la construction des sous-objets et les stocke dans l'attribut - mc_liste. - """ - self.mc_liste=self.build_mc() - - 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. - - """ - #message.debug(SUPERV, "Build_sd %s", self.nom) - self.sdnom=nom - 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.set_name(nom) - except AsException,e: - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1],e) - except EOFError: - 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)) - - self.Execute() - return sd - - def Execute(self): - """ - Cette methode est un point d'entree prevu pour realiser une execution immediatement - apres avoir construit les mots cles et le concept produit. - Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme. - """ - return - - def get_sd_prod(self): - """ - Retourne le concept résultat de l'étape - Deux cas : - - cas 1 : sd_prod de oper n'est pas une fonction - il s'agit d'une sous classe de ASSD - on construit le sd à partir de cette classe - et on le retourne - - cas 2 : il s'agit d'une fonction - on l'évalue avec les mots-clés de l'étape (mc_liste) - on construit le sd à partir de la classe obtenue - et on le retourne - """ - if type(self.definition.sd_prod) == types.FunctionType: - d=self.cree_dict_valeurs(self.mc_liste) + + """ + Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite + + """ + nature = "OPERATEUR" + + # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build) + # On le met à None pour indiquer qu'il n'y a pas de module de calcul + # rattaché + codex = None + + def __init__(self, oper=None, reuse=None, args={}, niveau=4): + """ + Attributs : + - definition : objet portant les attributs de définition d'une étape de type opérateur. Il + est initialisé par l'argument oper. + - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie + si les conditions d'exécution de l'opérateur l'autorise + - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args. + """ + self.definition = oper + self.reuse = reuse + self.valeur = args + self.nettoiargs() + self.parent = CONTEXT.get_current_step() + self.etape = self + self.nom = oper.nom + self.idracine = oper.label + self.appel = N_utils.callee_where(niveau) + self.mc_globaux = {} + self.sd = None + self.actif = 1 + self.make_register() + self.icmd = None + + def make_register(self): + """ + Initialise les attributs jdc, id, niveau et réalise les + enregistrements nécessaires + """ + if self.parent: + self.jdc = self.parent.get_jdc_root() + self.id = self.parent.register(self) + self.niveau = None + else: + self.jdc = self.parent = None + self.id = None + self.niveau = None + + def nettoiargs(self): + """ + Cette methode a pour fonction de retirer tous les arguments egaux à None + de la liste des arguments. Ils sont supposés non présents et donc retirés. + """ + for k in self.valeur.keys(): + if self.valeur[k] == None: + del self.valeur[k] + + def McBuild(self): + """ + Demande la construction des sous-objets et les stocke dans l'attribut + mc_liste. + """ + self.mc_liste = self.build_mc() + + 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. + + """ + # message.debug(SUPERV, "Build_sd %s", self.nom) + self.sdnom = nom try: - sd_prod= apply(self.definition.sd_prod,(),d) + 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.set_name(nom) + except AsException, e: + raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0], + 'fichier : ', self.appel[1], e) except EOFError: - raise + raise except: - if CONTEXT.debug: traceback.print_exc() - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1], - sys.exc_info()[2]) - raise AsException("impossible d affecter un type au resultat", - string.join(l[2:])) - # sys.exc_info()[0],sys.exc_info()[1],) - else: - sd_prod=self.definition.sd_prod - # on teste maintenant si la SD est réutilisée ou s'il faut la créer - if self.definition.reentrant != 'n' and self.reuse: - # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale. - # Elle sera traitee ulterieurement. - self.sd=self.reuse - else: - self.sd= sd_prod(etape=self) - # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur. - # On ne fait rien ici. L'erreur sera traiter par la suite. - # précaution - if self.sd is not None and not isinstance(self.sd, ASSD): - raise AsException(""" -Impossible de typer le résultat ! + 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)) + + self.Execute() + return sd + + def Execute(self): + """ + Cette methode est un point d'entree prevu pour realiser une execution immediatement + apres avoir construit les mots cles et le concept produit. + Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme. + """ + return + + def get_sd_prod(self): + """ + Retourne le concept résultat de l'étape + Deux cas : + - cas 1 : sd_prod de oper n'est pas une fonction + il s'agit d'une sous classe de ASSD + on construit le sd à partir de cette classe + et on le retourne + - cas 2 : il s'agit d'une fonction + on l'évalue avec les mots-clés de l'étape (mc_liste) + on construit le sd à partir de la classe obtenue + et on le retourne + """ + if type(self.definition.sd_prod) == types.FunctionType: + d = self.cree_dict_valeurs(self.mc_liste) + try: + sd_prod = apply(self.definition.sd_prod, (), d) + except EOFError: + raise + except: + if CONTEXT.debug: + traceback.print_exc() + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], + sys.exc_info()[2]) + raise AsException("impossible d affecter un type au resultat", + string.join(l[2:])) + # sys.exc_info()[0],sys.exc_info()[1],) + else: + sd_prod = self.definition.sd_prod + # on teste maintenant si la SD est réutilisée ou s'il faut la créer + if self.definition.reentrant != 'n' and self.reuse: + # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale. + # Elle sera traitee ulterieurement. + self.sd = self.reuse + else: + self.sd = sd_prod(etape=self) + # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur. + # On ne fait rien ici. L'erreur sera traiter par la suite. + # précaution + if self.sd is not None and not isinstance(self.sd, ASSD): + raise AsException(""" +Impossible de typer le résultat ! Causes possibles : - Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte, - soit il y a une "," à la fin d'une commande précédente. - Développeur : La fonction "sd_prod" retourne un type invalide.""") - return self.sd - - def get_type_produit(self): - try: - return self.get_type_produit_brut() - except: - return None - - def get_type_produit_brut(self): - """ - Retourne le type du concept résultat de l'étape - Deux cas : - - cas 1 : sd_prod de oper n'est pas une fonction - il s'agit d'une sous classe de ASSD - on retourne le nom de la classe - - cas 2 : il s'agit d'une fonction - on l'évalue avec les mots-clés de l'étape (mc_liste) - et on retourne son résultat - """ - if type(self.definition.sd_prod) == types.FunctionType: - d=self.cree_dict_valeurs(self.mc_liste) - sd_prod= apply(self.definition.sd_prod,(),d) - else: - sd_prod=self.definition.sd_prod - return sd_prod - - 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 - """ - return self - - def supprime(self): - """ - Méthode qui supprime toutes les références arrières afin que l'objet puisse - etre correctement détruit par le garbage collector - """ - N_MCCOMPO.MCCOMPO.supprime(self) - self.jdc = None - self.appel = None - for name in dir(self): - if name.startswith( '_cache_' ): - setattr(self, name, None) - if self.sd: - self.sd.supprime() - - def __del__(self): - #message.debug(SUPERV, "__del__ ETAPE %s <%s>", getattr(self, 'nom', 'unknown'), self) - #if self.sd: - #message.debug(SUPERV, " sd : %s", self.sd.nom) - pass - - def get_created_sd(self): - """Retourne la liste des sd réellement produites par l'étape. - Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans - cette liste.""" - if not self.reuse and self.sd: - return [self.sd, ] - return [] - - def isactif(self): - """ - Indique si l'étape est active (1) ou inactive (0) - """ - return self.actif - - def set_current_step(self): - """ - Methode utilisee pour que l etape self se declare etape - courante. Utilise par les macros - """ - #message.debug(SUPERV, "call etape.set_current_step", stack_id=-1) - cs= CONTEXT.get_current_step() - if self.parent != cs : - raise AsException("L'étape courante", cs.nom, cs, - "devrait etre le parent de", self.nom, self) - else : - CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) - - def reset_current_step(self): - """ - Methode utilisee par l'etape self qui remet son etape parent comme - etape courante - """ - cs= CONTEXT.get_current_step() - if self != cs : - raise AsException("L'étape courante", cs.nom, cs, - "devrait etre", self.nom, self) - else : - CONTEXT.unset_current_step() - CONTEXT.set_current_step(self.parent) - - def issubstep(self,etape): - """ - Cette methode retourne un entier indiquant si etape est une - sous etape de self ou non - 1 = oui - 0 = non - Une étape simple n'a pas de sous etape - """ - return 0 - - def get_file(self, unite=None, fic_origine='', fname=None): - """ - Retourne le nom du fichier correspondant à un numero d'unité - logique (entier) ainsi que le source contenu dans le fichier - """ - if self.jdc: - return self.jdc.get_file(unite=unite, fic_origine=fic_origine, fname=fname) - else: - if unite != None: - if os.path.exists("fort."+str(unite)): - fname= "fort."+str(unite) - if fname == None : - raise AsException("Impossible de trouver le fichier correspondant" - " a l unite %s" % unite) - if not os.path.exists(fname): - raise AsException("%s n'est pas un fichier existant" % unite) - fproc = open(fname, 'r') - text = fproc.read() - fproc.close() - text = text.replace('\r\n', '\n') - linecache.cache[fname] = 0, 0, text.split('\n'), fname - return fname, text - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitETAPE(self) - - def update_context(self,d): - """ - Cette methode doit updater le contexte fournit par - l'appelant en argument (d) en fonction de sa definition - """ - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,d)) - if self.sd: - d[self.sd.nom]=self.sd - - def copy(self): - """ Méthode qui retourne une copie de self non enregistrée auprès du JDC - et sans sd - """ - etape = copy(self) - etape.sd = None - 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 - - def copy_reuse(self,old_etape): - """ Méthode qui copie le reuse d'une autre étape. - """ - if hasattr(old_etape,"reuse") : - self.reuse = old_etape.reuse - - def copy_sdnom(self,old_etape): - """ Méthode qui copie le sdnom d'une autre étape. - """ - if hasattr(old_etape,"sdnom") : - self.sdnom = old_etape.sdnom - - 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) - if self.sd and self.reuse == None : - self.sd.jdc=self.jdc - - def get_cmd(self,nomcmd): - """ - Méthode pour recuperer la definition d'une commande - donnee par son nom dans les catalogues declares - au niveau du jdc - Appele par un ops d'une macro en Python - """ - return self.jdc.get_cmd(nomcmd) - - def copy_intern(self,etape): - """ - Méthode permettant lors du processus de recopie de copier - les elements internes d'une etape dans une autre - """ - return - - def full_copy(self,parent=None): - """ - Méthode permettant d'effectuer une copie complète - d'une étape (y compris concept produit, éléments internes) - Si l'argument parent est fourni, la nouvelle étape - aura cet objet comme parent. - """ - new_etape = self.copy() - new_etape.copy_reuse(self) - new_etape.copy_sdnom(self) - if parent: new_etape.reparent(parent) - if self.sd : - new_sd = self.sd.__class__(etape=new_etape) - new_etape.sd = new_sd - if self.reuse == None : - new_etape.parent.NommerSdprod(new_sd,self.sd.nom) - else : - new_sd.set_name(self.sd.nom) - new_etape.copy_intern(self) - return new_etape - - def reset_jdc(self,new_jdc): - """ - Reinitialise le nommage du concept de l'etape lors d'un changement de jdc - """ - if self.sd and self.reuse == None : - self.parent.NommerSdprod(self.sd,self.sd.nom) - - def is_include(self): - """Permet savoir si on a affaire à la commande INCLUDE - car le comportement de ces macros est particulier. - """ - return self.nom.startswith('INCLUDE') - - def sd_accessible(self): - """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape. - """ - if CONTEXT.debug: print '`- ETAPE sd_accessible :', self.nom - return self.parent.sd_accessible() - - def get_concept(self, nomsd): - """ - Méthode pour recuperer un concept à partir de son nom - """ - # pourrait être appelée par une commande fortran faisant appel à des fonctions python - # on passe la main au parent - return self.parent.get_concept(nomsd) + Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte, + soit il y a une "," à la fin d'une commande précédente. + Développeur : La fonction "sd_prod" retourne un type invalide.""") + return self.sd + + def get_type_produit(self): + try: + return self.get_type_produit_brut() + except: + return None + + def get_type_produit_brut(self): + """ + Retourne le type du concept résultat de l'étape + Deux cas : + - cas 1 : sd_prod de oper n'est pas une fonction + il s'agit d'une sous classe de ASSD + on retourne le nom de la classe + - cas 2 : il s'agit d'une fonction + on l'évalue avec les mots-clés de l'étape (mc_liste) + et on retourne son résultat + """ + if type(self.definition.sd_prod) == types.FunctionType: + d = self.cree_dict_valeurs(self.mc_liste) + sd_prod = apply(self.definition.sd_prod, (), d) + else: + sd_prod = self.definition.sd_prod + return sd_prod + + 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 + """ + return self + + def supprime(self): + """ + Méthode qui supprime toutes les références arrières afin que l'objet puisse + etre correctement détruit par le garbage collector + """ + N_MCCOMPO.MCCOMPO.supprime(self) + self.jdc = None + self.appel = None + for name in dir(self): + if name.startswith('_cache_'): + setattr(self, name, None) + if self.sd: + self.sd.supprime() + + def __del__(self): + # message.debug(SUPERV, "__del__ ETAPE %s <%s>", getattr(self, 'nom', 'unknown'), self) + # if self.sd: + # message.debug(SUPERV, " sd : %s", self.sd.nom) + pass + + def get_created_sd(self): + """Retourne la liste des sd réellement produites par l'étape. + Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans + cette liste.""" + if not self.reuse and self.sd: + return [self.sd, ] + return [] + + def isactif(self): + """ + Indique si l'étape est active (1) ou inactive (0) + """ + return self.actif + + def set_current_step(self): + """ + Methode utilisee pour que l etape self se declare etape + courante. Utilise par les macros + """ + # message.debug(SUPERV, "call etape.set_current_step", stack_id=-1) + cs = CONTEXT.get_current_step() + if self.parent != cs: + raise AsException("L'étape courante", cs.nom, cs, + "devrait etre le parent de", self.nom, self) + else: + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) + + def reset_current_step(self): + """ + Methode utilisee par l'etape self qui remet son etape parent comme + etape courante + """ + cs = CONTEXT.get_current_step() + if self != cs: + raise AsException("L'étape courante", cs.nom, cs, + "devrait etre", self.nom, self) + else: + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self.parent) + + def issubstep(self, etape): + """ + Cette methode retourne un entier indiquant si etape est une + sous etape de self ou non + 1 = oui + 0 = non + Une étape simple n'a pas de sous etape + """ + return 0 + + def get_file(self, unite=None, fic_origine='', fname=None): + """ + Retourne le nom du fichier correspondant à un numero d'unité + logique (entier) ainsi que le source contenu dans le fichier + """ + if self.jdc: + return self.jdc.get_file(unite=unite, fic_origine=fic_origine, fname=fname) + else: + if unite != None: + if os.path.exists("fort." + str(unite)): + fname = "fort." + str(unite) + if fname == None: + raise AsException("Impossible de trouver le fichier correspondant" + " a l unite %s" % unite) + if not os.path.exists(fname): + raise AsException("%s n'est pas un fichier existant" % unite) + fproc = open(fname, 'r') + text = fproc.read() + fproc.close() + text = text.replace('\r\n', '\n') + linecache.cache[fname] = 0, 0, text.split('\n'), fname + return fname, text + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitETAPE(self) + + def update_context(self, d): + """ + Cette methode doit updater le contexte fournit par + l'appelant en argument (d) en fonction de sa definition + """ + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init, (self, d)) + if self.sd: + d[self.sd.nom] = self.sd + + def copy(self): + """ Méthode qui retourne une copie de self non enregistrée auprès du JDC + et sans sd + """ + etape = copy(self) + etape.sd = None + 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 + + def copy_reuse(self, old_etape): + """ Méthode qui copie le reuse d'une autre étape. + """ + if hasattr(old_etape, "reuse"): + self.reuse = old_etape.reuse + + def copy_sdnom(self, old_etape): + """ Méthode qui copie le sdnom d'une autre étape. + """ + if hasattr(old_etape, "sdnom"): + self.sdnom = old_etape.sdnom + + 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) + if self.sd and self.reuse == None: + self.sd.jdc = self.jdc + + def get_cmd(self, nomcmd): + """ + Méthode pour recuperer la definition d'une commande + donnee par son nom dans les catalogues declares + au niveau du jdc + Appele par un ops d'une macro en Python + """ + return self.jdc.get_cmd(nomcmd) + + def copy_intern(self, etape): + """ + Méthode permettant lors du processus de recopie de copier + les elements internes d'une etape dans une autre + """ + return + + def full_copy(self, parent=None): + """ + Méthode permettant d'effectuer une copie complète + d'une étape (y compris concept produit, éléments internes) + Si l'argument parent est fourni, la nouvelle étape + aura cet objet comme parent. + """ + new_etape = self.copy() + new_etape.copy_reuse(self) + new_etape.copy_sdnom(self) + if parent: + new_etape.reparent(parent) + if self.sd: + new_sd = self.sd.__class__(etape=new_etape) + new_etape.sd = new_sd + if self.reuse == None: + new_etape.parent.NommerSdprod(new_sd, self.sd.nom) + else: + new_sd.set_name(self.sd.nom) + new_etape.copy_intern(self) + return new_etape + + def reset_jdc(self, new_jdc): + """ + Reinitialise le nommage du concept de l'etape lors d'un changement de jdc + """ + if self.sd and self.reuse == None: + self.parent.NommerSdprod(self.sd, self.sd.nom) + + def is_include(self): + """Permet savoir si on a affaire à la commande INCLUDE + car le comportement de ces macros est particulier. + """ + return self.nom.startswith('INCLUDE') + + def sd_accessible(self): + """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape. + """ + if CONTEXT.debug: + print '`- ETAPE sd_accessible :', self.nom + return self.parent.sd_accessible() + + def get_concept(self, nomsd): + """ + Méthode pour recuperer un concept à partir de son nom + """ + # pourrait être appelée par une commande fortran faisant appel à des fonctions python + # on passe la main au parent + return self.parent.get_concept(nomsd) diff --git a/Noyau/N_Exception.py b/Noyau/N_Exception.py index 00eecd91..a35ffafc 100644 --- a/Noyau/N_Exception.py +++ b/Noyau/N_Exception.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,25 +16,25 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" +""" Ce module contient la classe AsException """ -# Modules Python -import types +# Modules EFICAS +from strfunc import get_encoding + class AsException(Exception): - def __str__(self): - if not self.args: - return '' - elif len(self.args) == 1: - return str(self.args[0]) - else: - s='' - for e in self.args: - if type(e) == types.StringType: s=s+ ' ' + e - else:s=s+ ' ' + str(e) - return s + def __unicode__(self): + return " ".join([unicode(x) for x in self.args]) + + def __str__(self): + return unicode(self).encode(get_encoding()) + + +class InterruptParsingError(Exception): + + """Exception used to interrupt the parsing of the command file + without raising an error (see N_JDC.exec_compile for usage)""" diff --git a/Noyau/N_FACT.py b/Noyau/N_FACT.py index c8797c0c..a94b90b4 100644 --- a/Noyau/N_FACT.py +++ b/Noyau/N_FACT.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,11 +16,10 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ Ce module contient la classe de definition FACT - qui permet de spécifier les caractéristiques des mots clés facteurs + qui permet de spécifier les caractéristiques des mots clés facteurs """ import types @@ -34,121 +33,123 @@ from strfunc import ufmt import N_OBJECT + class FACT(N_ENTITE.ENTITE): - """ - Classe pour definir un mot cle facteur - - Cette classe a trois attributs de classe - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - mot-clé facteur avec sa définition - - - list_instance - - - label qui indique la nature de l'objet de définition (ici, FACT) - """ - class_instance = N_MCFACT.MCFACT - list_instance = N_MCLIST.MCList - label = 'FACT' - - def __init__(self,fr="",ang="",docu="",regles=(),statut='f',defaut=None, - min=0,max=1,validators=None,**args): - - """ - Un mot-clé facteur est caractérisé par les attributs suivants : - - - fr : - - ang : - - statut : - - defaut : - - regles - - min - - max - - position - - docu - """ - N_ENTITE.ENTITE.__init__(self,validators) - # Initialisation des attributs - self.fr=fr - self.ang=ang - self.docu = docu - if type(regles)== types.TupleType: - self.regles=regles - else: - self.regles=(regles,) - self.statut=statut - self.defaut=defaut - self.min=min - self.max=max - self.entites=args - self.position=None - self.affecter_parente() - - def __call__(self,val,nom,parent): - """ - Construit la structure de donnee pour un mot cle facteur a partir - de sa definition (self) de sa valeur (val), de son nom (nom) et de - son parent dans l arboresence (parent) - - Suivant le type de la valeur on retournera soit un objet de type - MCFACT soit une liste de type MCLIST. - - La creation d un mot cle facteur depend de son statut - - Si statut ='o' il est obligatoire - - Si statut == 'd' il est facultatif mais ses sous mots cles avec - defaut sont visibles - - Si statut == 'f' il est facultatif et ses sous mots avec defaut ne - sont pas visibles - - Si statut == 'c' il est cache ??? - - Si defaut != None, on utilise cette valeur pour calculer la valeur - par defaut du mot cle facteur - """ - if val is None: - if self.defaut == None: - val={} - elif type(self.defaut) == types.TupleType: - val=self.defaut - # Est ce utile ? Le défaut pourrait etre uniquement un dict - elif type(self.defaut) == types.DictType or isinstance(self.defaut,_F): - val=self.defaut + + """ + Classe pour definir un mot cle facteur + + Cette classe a trois attributs de classe + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + mot-clé facteur avec sa définition + + - list_instance + + - label qui indique la nature de l'objet de définition (ici, FACT) + """ + class_instance = N_MCFACT.MCFACT + list_instance = N_MCLIST.MCList + label = 'FACT' + + def __init__(self, fr="", docu="", regles=(), statut='f', defaut=None,ang="", + min=0, max=1, validators=None, **args): + """ + Un mot-clé facteur est caractérisé par les attributs suivants : + + - fr : + - statut : + - defaut : + - regles + - min + - max + - position + - docu + """ + N_ENTITE.ENTITE.__init__(self, validators) + # Initialisation des attributs + self.fr = fr + self.ang=ang + self.docu = docu + if type(regles) == types.TupleType: + self.regles = regles else: - # On ne devrait jamais passer par la - print "On ne devrait jamais passer par la" - return None - elif is_sequence(val) and len(val) == 0 and self.statut == 'o': - # On est dans le cas où le mcfact est présent mais est une liste/tuple - # vide. Il est obligatoire donc on l'initialise. Les règles, mots-clés - # obligatoires diront si un mcfact vide est accepté. - val = {} - - # On cree toujours une liste de mcfact - l=self.list_instance() - l.init(nom = nom,parent=parent) - if type(val) in (types.TupleType, types.ListType, self.list_instance) : - for v in val: - if type(v) == types.DictType or isinstance(v, _F): - objet=self.class_instance(nom=nom,definition=self,val=v,parent=parent) - l.append(objet) - elif isinstance(v, self.class_instance): - l.append(v) + self.regles = (regles,) + self.statut = statut + self.defaut = defaut + self.min = min + self.max = max + self.entites = args + self.position = None + self.affecter_parente() + + def __call__(self, val, nom, parent): + """ + Construit la structure de donnee pour un mot cle facteur a partir + de sa definition (self) de sa valeur (val), de son nom (nom) et de + son parent dans l arboresence (parent) + + Suivant le type de la valeur on retournera soit un objet de type + MCFACT soit une liste de type MCLIST. + + La creation d un mot cle facteur depend de son statut + - Si statut ='o' il est obligatoire + - Si statut == 'd' il est facultatif mais ses sous mots cles avec + defaut sont visibles + - Si statut == 'f' il est facultatif et ses sous mots avec defaut ne + sont pas visibles + - Si statut == 'c' il est cache ??? + - Si defaut != None, on utilise cette valeur pour calculer la valeur + par defaut du mot cle facteur + """ + if val is None: + if self.defaut == None: + val = {} + elif type(self.defaut) == types.TupleType: + val = self.defaut + # Est ce utile ? Le défaut pourrait etre uniquement un dict + elif type(self.defaut) == types.DictType or isinstance(self.defaut, _F): + val = self.defaut else: - l.append(N_OBJECT.ErrorObj(self,v,parent,nom)) - elif type(val) == types.DictType or isinstance(val, _F): - objet=self.class_instance(nom=nom,definition=self,val=val,parent=parent) - l.append(objet) - elif isinstance(val, self.class_instance): - l.append(val) - else: - l.append(N_OBJECT.ErrorObj(self,val,parent,nom)) - - return l - - def verif_cata(self): - self.check_min_max() - self.check_fr() - self.check_regles() - self.check_statut() - self.check_docu() - self.check_validators() - self.verif_cata_regles() + # On ne devrait jamais passer par la + print "On ne devrait jamais passer par la" + return None + elif is_sequence(val) and len(val) == 0 and self.statut == 'o': + # On est dans le cas où le mcfact est présent mais est une liste/tuple + # vide. Il est obligatoire donc on l'initialise. Les règles, mots-clés + # obligatoires diront si un mcfact vide est accepté. + val = {} + + # On cree toujours une liste de mcfact + l = self.list_instance() + l.init(nom=nom, parent=parent) + if type(val) in (types.TupleType, types.ListType, self.list_instance): + for v in val: + if type(v) == types.DictType or isinstance(v, _F): + objet = self.class_instance( + nom=nom, definition=self, val=v, parent=parent) + l.append(objet) + elif isinstance(v, self.class_instance): + l.append(v) + else: + l.append(N_OBJECT.ErrorObj(self, v, parent, nom)) + elif type(val) == types.DictType or isinstance(val, _F): + objet = self.class_instance( + nom=nom, definition=self, val=val, parent=parent) + l.append(objet) + elif isinstance(val, self.class_instance): + l.append(val) + else: + l.append(N_OBJECT.ErrorObj(self, val, parent, nom)) + + return l + + def verif_cata(self): + self.check_min_max() + self.check_fr() + self.check_regles() + self.check_statut() + self.check_docu() + self.check_validators() + self.verif_cata_regles() diff --git a/Noyau/N_FONCTION.py b/Noyau/N_FONCTION.py index 2fb52b66..131e6902 100644 --- a/Noyau/N_FONCTION.py +++ b/Noyau/N_FONCTION.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,11 +16,10 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# # Attention : cet import permet d'avoir, en Python, le comportement -# de la division réelle pour les entiers, et non la division entière -# 1/2=0.5 (et non 0). Comportement par défaut dans Python 3.0. +# de la division réelle pour les entiers, et non la division entière +# 1/2=0.5 (et non 0). Comportement par défaut dans Python 3.0. from __future__ import division from math import sin, cos, tan, asin, acos, atan2, atan, sinh, cosh, tanh from math import pi, exp, log, log10, sqrt @@ -28,10 +27,13 @@ from math import pi, exp, log, log10, sqrt from N_ASSD import ASSD from N_info import message, SUPERV + class FONCTION(ASSD): pass + class formule(ASSD): + def __init__(self, *args, **kwargs): ASSD.__init__(self, *args, **kwargs) self.nompar = None @@ -40,40 +42,43 @@ class formule(ASSD): ctxt.update(getattr(self.parent, 'const_context', {})) ctxt.update(getattr(self.parent, 'macro_const_context', {})) self.parent_context = self.filter_context(ctxt) - #message.debug(SUPERV, "add parent_context %s %s", self.nom, self.parent_context) + # message.debug(SUPERV, "add parent_context %s %s", self.nom, + # self.parent_context) def __call__(self, *val): """Evaluation de la formule""" - # en POURSUITE, self.parent_context is None, on essaie de reprendre const_context - context = getattr(self, 'parent_context') or getattr(self.parent, 'const_context', {}) + # en POURSUITE, self.parent_context is None, on essaie de reprendre + # const_context + context = getattr(self, 'parent_context') or getattr( + self.parent, 'const_context', {}) for param, value in zip(self.nompar, val): context[param] = value try: # globals() pour math.* res = eval(self.code, context, globals()) except Exception, exc: - message.error(SUPERV, "ERREUR LORS DE L'ÉVALUATION DE LA FORMULE '%s' " \ - ":\n>> %s",self.nom, str(exc)) + message.error(SUPERV, "ERREUR LORS DE L'ÉVALUATION DE LA FORMULE '%s' " + ":\n>> %s", self.nom, str(exc)) raise return res def setFormule(self, nom_para, texte): """Cette methode sert a initialiser les attributs - nompar, expression et code qui sont utilisés - dans l'évaluation de la formule.""" + nompar, expression et code qui sont utilisés + dans l'évaluation de la formule.""" self.nompar = nom_para self.expression = texte - try : + try: self.code = compile(texte, texte, 'eval') except SyntaxError, exc: - message.error(SUPERV, "ERREUR LORS DE LA CREATION DE LA FORMULE '%s' " \ + message.error(SUPERV, "ERREUR LORS DE LA CREATION DE LA FORMULE '%s' " ":\n>> %s", self.nom, str(exc)) raise - def __setstate__(self,state): + def __setstate__(self, state): """Cette methode sert a restaurer l'attribut code lors d'un unpickle.""" self.__dict__.update(state) # update attributes - self.setFormule(self.nompar, self.expression) # restore code attribute + self.setFormule(self.nompar, self.expression) # restore code attribute def __getstate__(self): """Pour les formules, il faut enlever l'attribut code qui n'est @@ -84,18 +89,18 @@ class formule(ASSD): def supprime(self, force=False): """ - Cassage des boucles de références pour destruction du JDC. - 'force' est utilisée pour faire des suppressions complémentaires. - - Pour être évaluées, les formules ont besoin du contexte des "constantes" + Cassage des boucles de références pour destruction du JDC. + 'force' est utilisée pour faire des suppressions complémentaires. + + Pour être évaluées, les formules ont besoin du contexte des "constantes" (objets autres que les concepts) qui sont soit dans (jdc).const_context, soit dans (macro).macro_const_context. On le stocke dans 'parent_context'. - Deux précautions valent mieux qu'une : on retire tous les concepts. - - Lors de la suppression du concept, 'supprime' est appelée par + Deux précautions valent mieux qu'une : on retire tous les concepts. + + Lors de la suppression du concept, 'supprime' est appelée par 'build_detruire' avec force=True afin de supprimer le "const_context" - conservé. + conservé. """ if force: for ctxt in ('parent_context', 'g_context'): @@ -105,30 +110,30 @@ class formule(ASSD): def Parametres(self): """Equivalent de fonction.Parametres pour pouvoir utiliser des formules - à la place de fonctions dans certaines macro-commandes. + à la place de fonctions dans certaines macro-commandes. """ from SD.sd_fonction import sd_formule from Utilitai.Utmess import UTMESS if self.accessible(): - TypeProl={ 'E':'EXCLU', 'L':'LINEAIRE', 'C':'CONSTANT', 'I':'INTERPRE' } + TypeProl = { + 'E': 'EXCLU', 'L': 'LINEAIRE', 'C': 'CONSTANT', 'I': 'INTERPRE'} sd = sd_formule(self.get_name()) prol = sd.PROL.get() nova = sd.NOVA.get() if prol is None or nova is None: UTMESS('F', 'SDVERI_2', valk=[objev]) - dico={ - 'INTERPOL' : ['LIN','LIN'], - 'NOM_PARA' : [s.strip() for s in nova], - 'NOM_RESU' : prol[3][0:16].strip(), - 'PROL_DROITE' : TypeProl['E'], - 'PROL_GAUCHE' : TypeProl['E'], + dico = { + 'INTERPOL': ['LIN', 'LIN'], + 'NOM_PARA': [s.strip() for s in nova], + 'NOM_RESU': prol[3][0:16].strip(), + 'PROL_DROITE': TypeProl['E'], + 'PROL_GAUCHE': TypeProl['E'], } else: - raise Accas.AsException("Erreur dans fonction.Parametres en PAR_LOT='OUI'") + raise Accas.AsException( + "Erreur dans fonction.Parametres en PAR_LOT='OUI'") return dico class formule_c(formule): pass - - diff --git a/Noyau/N_FORM.py b/Noyau/N_FORM.py index ce2b60d8..89ca09ce 100644 --- a/Noyau/N_FORM.py +++ b/Noyau/N_FORM.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,17 +16,17 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# import N_MACRO import N_FORM_ETAPE + class FORM(N_MACRO.MACRO): + """ - Cette classe sert à définir dans le catalogue des objets de type + Cette classe sert à définir dans le catalogue des objets de type FORMULE pour ASTER. Elle surcharge la classe MACRO """ - class_instance=N_FORM_ETAPE.FORM_ETAPE - + class_instance = N_FORM_ETAPE.FORM_ETAPE diff --git a/Noyau/N_FORM_ETAPE.py b/Noyau/N_FORM_ETAPE.py index aefad317..ad399678 100644 --- a/Noyau/N_FORM_ETAPE.py +++ b/Noyau/N_FORM_ETAPE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,13 +16,15 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + + import N_MACRO_ETAPE + class FORM_ETAPE(N_MACRO_ETAPE.MACRO_ETAPE): + """ - Cette classe sert à construire l'objet ACCAS correspondant à une + Cette classe sert à construire l'objet ACCAS correspondant à une FORMULE Aster. - Il s'agit d'un objet MACRO_ETAPE légèrement modifié + Il s'agit d'un objet MACRO_ETAPE légèrement modifié """ - diff --git a/Noyau/N_GEOM.py b/Noyau/N_GEOM.py index 3309dbb8..471919cd 100644 --- a/Noyau/N_GEOM.py +++ b/Noyau/N_GEOM.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ @@ -24,40 +23,45 @@ """ from N_ASSD import ASSD + class GEOM(ASSD): - """ - Cette classe sert à définir les types de concepts - géométriques comme GROUP_NO, GROUP_MA,NOEUD et MAILLE - - """ - def __init__(self,nom,etape=None,sd=None,reg='oui'): - """ - """ - self.etape=etape - self.sd=sd - if etape: - self.parent=etape.parent - else: - self.parent=CONTEXT.get_current_step() - if self.parent : - self.jdc = self.parent.get_jdc_root() - else: - self.jdc = None - - if not self.parent: - self.id=None - elif reg == 'oui' : - self.id = self.parent.reg_sd(self) - self.nom=nom - - def get_name(self): - return self.nom - - def __convert__(cls,valeur): - if isinstance(valeur, (str,unicode)) and len(valeur.strip()) <= 8: - return valeur.strip() - raise ValueError(_(u'On attend une chaine de caractères (de longueur < 8).')) - __convert__=classmethod(__convert__) - -class geom(GEOM):pass + """ + Cette classe sert à définir les types de concepts + géométriques comme GROUP_NO, GROUP_MA,NOEUD et MAILLE + + """ + + def __init__(self, nom, etape=None, sd=None, reg='oui'): + """ + """ + self.etape = etape + self.sd = sd + if etape: + self.parent = etape.parent + else: + self.parent = CONTEXT.get_current_step() + if self.parent: + self.jdc = self.parent.get_jdc_root() + else: + self.jdc = None + + if not self.parent: + self.id = None + elif reg == 'oui': + self.id = self.parent.reg_sd(self) + self.nom = nom + + def get_name(self): + return self.nom + + def __convert__(cls, valeur): + if isinstance(valeur, (str, unicode)) and len(valeur.strip()) <= 8: + return valeur.strip() + raise ValueError( + _(u'On attend une chaine de caractères (de longueur <= 8).')) + __convert__ = classmethod(__convert__) + + +class geom(GEOM): + pass diff --git a/Noyau/N_JDC.py b/Noyau/N_JDC.py index 02139075..5088de7d 100644 --- a/Noyau/N_JDC.py +++ b/Noyau/N_JDC.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,610 +16,642 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ - Ce module contient la classe JDC qui sert à interpréter un jeu de commandes + Ce module contient la classe JDC qui sert à interpréter un jeu de commandes """ # Modules Python -import os,string,traceback -import types,sys,linecache +import os +import string +import traceback +import types +import sys +import linecache # Modules EFICAS import N_OBJECT import N_CR -from N_Exception import AsException +from N_Exception import AsException, InterruptParsingError from N_ASSD import ASSD from N_info import message, SUPERV +from strfunc import get_encoding MemoryErrorMsg = """MemoryError : -En général, cette erreur se produit car la mémoire utilisée hors du fortran +En général, cette erreur se produit car la mémoire utilisée hors du fortran (jeveux) est importante. Causes possibles : - le calcul produit de gros objets Python dans une macro-commande ou - dans le jeu de commande lui-même, + dans le jeu de commande lui-même, - le calcul appelle un solveur (MUMPS par exemple) ou un outil externe - qui a besoin de mémoire hors jeveux, + qui a besoin de mémoire hors jeveux, - utilisation de jeveux dynamique, - ... Solution : - - distinguer la mémoire limite du calcul (case "Mémoire totale" de astk) - de la mémoire réservée à jeveux (case "dont Aster"), le reste étant + - distinguer la mémoire limite du calcul (case "Mémoire totale" de astk) + de la mémoire réservée à jeveux (case "dont Aster"), le reste étant disponible pour les allocations dynamiques. """ - class JDC(N_OBJECT.OBJECT): - """ - Cette classe interprete un jeu de commandes fourni sous - la forme d'une chaine de caractères - Attributs de classe : + """ + Cette classe interprete un jeu de commandes fourni sous + la forme d'une chaine de caractères - Attributs d'instance : + Attributs de classe : - """ - nature = "JDC" - CR=N_CR.CR - exec_init=""" + Attributs d'instance : + + """ + nature = "JDC" + CR = N_CR.CR + exec_init = """ import Accas from Accas import _F from Accas import * NONE = None """ - from N_utils import SEP - - def __init__(self,definition=None,procedure=None,cata=None, - cata_ord_dico=None,parent=None, - nom='SansNom',appli=None,context_ini=None,**args): - self.procedure=procedure - self.definition = definition - self.cata=cata - if type(self.cata) != types.TupleType and cata != None: - self.cata=(self.cata,) - self._build_reserved_kw_list() - self.cata_ordonne_dico=cata_ord_dico - self.nom = nom - self.appli=appli - self.parent=parent - self.context_ini=context_ini - # On conserve les arguments supplémentaires. Il est possible de passer - # des informations globales au JDC par ce moyen. Il pourrait etre plus - # sur de mettre en place le mecanisme des mots-cles pour verifier la - # validité des valeurs passées. - # Ceci reste à faire - # On initialise avec les parametres de la definition puis on - # update avec ceux du JDC - self.args=self.definition.args - self.args.update(args) - self.nstep=0 - self.nsd=0 - self.par_lot='OUI' - self.par_lot_user = None - if definition: - self.regles=definition.regles - self.code = definition.code - else: - self.regles=() - self.code = "CODE" - # - # Creation de l objet compte rendu pour collecte des erreurs - # - self.cr = self.CR(debut = "CR phase d'initialisation", - fin = "fin CR phase d'initialisation") - # on met le jdc lui-meme dans le context global pour l'avoir sous - # l'etiquette "jdc" dans le fichier de commandes - self.g_context={ 'jdc' : self } - #message.debug(SUPERV, "g_context : %s - %s", self.g_context, id(self.g_context)) - # Dictionnaire pour stocker tous les concepts du JDC (acces rapide par le nom) - self.sds_dict={} - self.etapes=[] - self.index_etapes = {} - self.mc_globaux={} - self.current_context={} - self.condition_context={} - self.index_etape_courante=0 - self.UserError="UserError" - self.alea = None - # permet transitoirement de conserver la liste des étapes - self.hist_etape = False - - def compile(self): - """ - Cette methode compile la chaine procedure - Si des erreurs se produisent, elles sont consignées dans le - compte-rendu self.cr - """ - try: - if self.appli != None : - self.appli.affiche_infos('Compilation du fichier de commandes en cours ...') - self.proc_compile=compile(self.procedure,self.nom,'exec') - except SyntaxError, e: - if CONTEXT.debug : traceback.print_exc() - l=traceback.format_exception_only(SyntaxError,e) - self.cr.exception("Compilation impossible : "+string.join(l)) - except MemoryError, e: - self.cr.exception(MemoryErrorMsg) - except SystemError, e: - erreurs_connues = """ + from N_utils import SEP + + def __init__(self, definition=None, procedure=None, cata=None, + cata_ord_dico=None, parent=None, + nom='SansNom', appli=None, context_ini=None, **args): + self.procedure = procedure + self.definition = definition + self.cata = cata + if type(self.cata) != types.TupleType and cata != None: + self.cata = (self.cata,) + self._build_reserved_kw_list() + self.cata_ordonne_dico = cata_ord_dico + self.nom = nom + self.appli = appli + self.parent = parent + self.context_ini = context_ini + # On conserve les arguments supplémentaires. Il est possible de passer + # des informations globales au JDC par ce moyen. Il pourrait etre plus + # sur de mettre en place le mecanisme des mots-cles pour verifier la + # validité des valeurs passées. + # Ceci reste à faire + # On initialise avec les parametres de la definition puis on + # update avec ceux du JDC + self.args = self.definition.args + self.args.update(args) + self.nstep = 0 + self.nsd = 0 + self.par_lot = 'OUI' + self.par_lot_user = None + if definition: + self.regles = definition.regles + self.code = definition.code + else: + self.regles = () + self.code = "CODE" + # + # Creation de l objet compte rendu pour collecte des erreurs + # + self.cr = self.CR(debut="CR phase d'initialisation", + fin="fin CR phase d'initialisation") + # on met le jdc lui-meme dans le context global pour l'avoir sous + # l'etiquette "jdc" dans le fichier de commandes + self.g_context = {'jdc': self} + # message.debug(SUPERV, "g_context : %s - %s", self.g_context, id(self.g_context)) + # Dictionnaire pour stocker tous les concepts du JDC (acces rapide par + # le nom) + self.sds_dict = {} + self.etapes = [] + self.index_etapes = {} + self.mc_globaux = {} + self.current_context = {} + self.condition_context = {} + self.index_etape_courante = 0 + self.UserError = "UserError" + self.alea = None + # permet transitoirement de conserver la liste des étapes + self.hist_etape = False + + def compile(self): + """ + Cette methode compile la chaine procedure + Si des erreurs se produisent, elles sont consignées dans le + compte-rendu self.cr + """ + try: + if self.appli != None: + self.appli.affiche_infos( + 'Compilation du fichier de commandes en cours ...') + # Python 2.7 compile function does not accept unicode filename, so we encode it + # with the current locale encoding in order to have a correct + # traceback + encoded_filename = self.nom.encode(get_encoding()) + self.proc_compile = compile( + self.procedure, encoded_filename, 'exec') + except SyntaxError, e: + if CONTEXT.debug: + traceback.print_exc() + l = traceback.format_exception_only(SyntaxError, e) + self.cr.exception("Compilation impossible : " + string.join(l)) + except MemoryError, e: + self.cr.exception(MemoryErrorMsg) + except SystemError, e: + erreurs_connues = """ Causes possibles : - - offset too large : liste trop longue derrière un mot-clé. + - offset too large : liste trop longue derrière un mot-clé. Solution : liste = (valeurs, ..., ) MOT_CLE = *liste, """ - l=traceback.format_exception_only(SystemError,e) - l.append(erreurs_connues) - self.cr.exception("Compilation impossible : " + ''.join(l)) - return - - def exec_compile(self): - """ - Cette méthode execute le jeu de commandes compilé dans le contexte - self.g_context de l'objet JDC - """ - CONTEXT.set_current_step(self) - # Le module nommage utilise le module linecache pour accéder - # au source des commandes du jeu de commandes. - # Dans le cas d'un fichier, on accède au contenu de ce fichier - # Dans le cas d'une chaine de caractères il faut accéder - # aux commandes qui sont dans la chaine - import linecache - linecache.cache[self.nom]=0,0,string.split(self.procedure,'\n'),self.nom - try: - exec self.exec_init in self.g_context - #message.debug(SUPERV, "JDC.exec_compile_1 - len(g_context) = %d", len(self.g_context.keys())) - for obj_cata in self.cata: - if type(obj_cata) == types.ModuleType : - init2 = "from "+obj_cata.__name__+" import *" - exec init2 in self.g_context - #message.debug(SUPERV, "JDC.exec_compile_2 - len(g_context) = %d", len(self.g_context.keys())) - - # Initialisation du contexte global pour l'évaluation des conditions de BLOC - # On utilise une copie de l'initialisation du contexte du jdc - self.condition_context=self.g_context.copy() - - # Si l'attribut context_ini n'est pas vide, on ajoute au contexte global - # le contexte initial (--> permet d'évaluer un JDC en récupérant un contexte - # d'un autre par exemple) - if self.context_ini : - self.g_context.update(self.context_ini) - # Update du dictionnaire des concepts - for sdnom,sd in self.context_ini.items(): - if isinstance(sd,ASSD):self.sds_dict[sdnom]=sd - - if self.appli != None : - self.appli.affiche_infos('Interprétation du fichier de commandes en cours ...') - # On sauve le contexte pour garder la memoire des constantes - # En mode edition (EFICAS) ou lors des verifications le contexte - # est recalculé - # mais les constantes sont perdues - self.const_context=self.g_context - #message.debug(SUPERV, "pass") - exec self.proc_compile in self.g_context - #message.debug(SUPERV, "JDC.exec_compile_3 - len(g_context) = %d", len(self.g_context.keys())) - - CONTEXT.unset_current_step() - if self.appli != None : self.appli.affiche_infos('') - - except EOFError: - # Exception utilise pour interrompre un jeu - # de commandes avant la fin - # Fonctionnement normal, ne doit pas etre considere comme une erreur - CONTEXT.unset_current_step() - self.affiche_fin_exec() - self.traiter_fin_exec('commande') - - except AsException,e: - # une erreur a ete identifiee - if CONTEXT.debug : - traceback.print_exc() - # l'exception a été récupérée avant (où, comment ?), - # donc on cherche dans le texte - txt = str(e) - if txt.find('MemoryError') >= 0: - txt = MemoryErrorMsg - self.cr.exception(txt) - CONTEXT.unset_current_step() - - except NameError,e: - etype, value, tb = sys.exc_info() - l= traceback.extract_tb(tb) - s= traceback.format_exception_only("Erreur de nom",e)[0][:-1] - msg = "erreur de syntaxe, %s ligne %d" % (s,l[-1][1]) - if CONTEXT.debug : - traceback.print_exc() - self.cr.exception(msg) - CONTEXT.unset_current_step() - - except self.UserError,exc_val: - self.traiter_user_exception(exc_val) - CONTEXT.unset_current_step() - self.affiche_fin_exec() - self.traiter_fin_exec('commande') - - except : - # erreur inattendue - # sys_exc_typ,sys_exc_value,sys_exc_frame = sys_exc.info() - # (tuple de 3 éléments) - if CONTEXT.debug : traceback.print_exc() - - traceback.print_exc() - - exc_typ,exc_val,exc_fr=sys.exc_info() - l=traceback.format_exception(exc_typ,exc_val,exc_fr) - self.cr.exception("erreur non prevue et non traitee prevenir la maintenance "+'\n'+ string.join(l)) - del exc_typ,exc_val,exc_fr - CONTEXT.unset_current_step() - - def affiche_fin_exec(self): - """ - Cette methode realise l'affichage final des statistiques de temps - apres l'execution de toutes - les commandes en mode commande par commande ou par lot - Elle doit etre surchargee pour en introduire un - """ - return - - def traiter_fin_exec(self,mode,etape=None): - """ - Cette methode realise un traitement final apres l'execution de toutes - les commandes en mode commande par commande ou par lot - Par defaut il n'y a pas de traitement. Elle doit etre surchargee - pour en introduire un - """ - message.info(SUPERV, "FIN D'EXECUTION %s %s", mode, etape) - - def traiter_user_exception(self,exc_val): - """Cette methode realise un traitement sur les exceptions utilisateur - Par defaut il n'y a pas de traitement. La méthode doit etre - surchargée pour en introduire un. - """ - return - - def register(self,etape): - """ - Cette méthode ajoute etape dans la liste des etapes : self.etapes - et retourne un numéro d'enregistrement - """ - self.etapes.append(etape) - self.index_etapes[etape] = len(self.etapes) - 1 - #message.debug(SUPERV, "#%d %s", self.index_etapes[etape], etape.nom) - return self.g_register(etape) - - def o_register(self,sd): - """ - Retourne un identificateur pour concept - """ - self.nsd=self.nsd+1 - nom=sd.idracine + self.SEP + `self.nsd` - return nom - - def g_register(self,etape): - """ - Retourne un identificateur pour etape - """ - self.nstep=self.nstep+1 - idetape=etape.idracine + self.SEP + `self.nstep` - return idetape - - def create_sdprod(self,etape,nomsd): - """ - Cette methode doit fabriquer le concept produit retourne - par l'etape etape et le nommer. - - Elle est appelée à l'initiative de l'etape - pendant le processus de construction de cette etape : - methode __call__ de la classe CMD (OPER ou MACRO) - - Ce travail est réalisé par le contexte supérieur - (etape.parent) car dans certains cas, le concept ne doit - pas etre fabriqué mais l'etape doit simplement utiliser - un concept préexistant. - - Deux cas possibles : - - Cas 1 : etape.reuse != None : le concept est réutilisé - - Cas 2 : l'étape appartient à une macro qui a déclaré un - concept de sortie qui doit etre produit par cette - etape. - Dans le cas du JDC, le deuxième cas ne peut pas se produire. - """ - #print "entree dans create_sd_prod" - sd= etape.get_sd_prod() - if sd != None and (etape.definition.reentrant == 'n' or etape.reuse is None) : - # ATTENTION : On ne nomme la SD que dans le cas de non reutilisation - # d un concept. Commande non reentrante ou reuse absent. - self.NommerSdprod(sd,nomsd) - return sd - - def NommerSdprod(self,sd,sdnom,restrict='non'): - """ - 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 - """ - #print "debut NommerSdprod pour ", sdnom - o=self.sds_dict.get(sdnom,None) - if isinstance(o,ASSD): - raise AsException("Nom de concept deja defini : %s" % sdnom) - if sdnom in self._reserved_kw: - raise AsException("Nom de concept invalide. '%s' est un mot-clé réservé." % sdnom) - - # Ajoute a la creation (appel de reg_sd). - self.sds_dict[sdnom]=sd - sd.set_name(sdnom) - - # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC - if restrict == 'non': - self.g_context[sdnom]=sd - #message.debug(SUPERV, "g_context[%r] = %s", sdnom, sd) - - def reg_sd(self,sd): - """ - Methode appelee dans l __init__ d un ASSD lors de sa creation - pour s enregistrer - """ - return self.o_register(sd) - - def delete_concept_after_etape(self,etape,sd): - """ - Met à jour les étapes du JDC qui sont après etape suite à - la disparition du concept sd - """ - # Cette methode est définie dans le noyau mais ne sert que pendant - # la phase de creation des etapes et des concepts. Il n'y a aucun - # traitement particulier à réaliser. - # Dans d'autres conditions, il faut surcharger cette méthode - return - - def supprime(self): - N_OBJECT.OBJECT.supprime(self) - for etape in self.etapes: - etape.supprime() - - def clean(self, netapes): - """Nettoie les `netapes` dernières étapes de la liste des étapes.""" - if self.hist_etape: - return - for i in xrange(netapes): - e=self.etapes.pop() - jdc=e.jdc - parent=e.parent - e.supprime() - e.parent=parent - e.jdc=jdc - #message.debug(SUPERV, "JDC.clean - etape = %r - refcount(e) = %d", - #e.nom, sys.getrefcount(e)) - del self.index_etapes[e] - - - def get_file(self, unite=None, fic_origine='', fname=None): - """ - Retourne le nom du fichier correspondant à un numero d'unité - logique (entier) ainsi que le source contenu dans le fichier - """ - if self.appli : - # Si le JDC est relié à une application maitre, on délègue la recherche - return self.appli.get_file(unite, fic_origine) - else: - if unite != None: - if os.path.exists("fort."+str(unite)): - fname= "fort."+str(unite) - if fname == None : - raise AsException("Impossible de trouver le fichier correspondant" - " a l unite %s" % unite) - if not os.path.exists(fname): - raise AsException("%s n'est pas un fichier existant" % fname) - fproc = open(fname, 'r') - text=fproc.read() - fproc.close() - text = text.replace('\r\n', '\n') - linecache.cache[fname] = 0, 0, text.split('\n'), fname - return fname, text - - def set_par_lot(self, par_lot, user_value=False): - """ - Met le mode de traitement a PAR LOT - ou a COMMANDE par COMMANDE - en fonction de la valeur du mot cle PAR_LOT et - du contexte : application maitre ou pas - - En PAR_LOT='NON', il n'y a pas d'ambiguité. - En PAR_LOT='OUI', E_SUPERV positionne l'attribut à 'NON' après la phase - d'analyse et juste avant la phase d'exécution. - `user_value` : permet de stocker la valeur choisie par l'utilisateur - pour l'interroger plus tard (par exemple dans `get_contexte_avant`). - """ - #message.debug(SUPERV, "set par_lot = %r", par_lot) - if user_value: - self.par_lot_user = par_lot - if self.appli == None: - # Pas d application maitre - self.par_lot=par_lot - else: - # Avec application maitre - self.par_lot='OUI' - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitJDC(self) - - def interact(self): - """ - Cette methode a pour fonction d'ouvrir un interpreteur - pour que l'utilisateur entre des commandes interactivement - """ - CONTEXT.set_current_step(self) - try: - # Le module nommage utilise le module linecache pour accéder - # au source des commandes du jeu de commandes. - # Dans le cas d'un fichier, on accède au contenu de ce fichier - # Dans le cas de la console interactive, il faut pouvoir accéder - # aux commandes qui sont dans le buffer de la console - import linecache,code - console= code.InteractiveConsole(self.g_context,filename="") - linecache.cache[""]=0,0,console.buffer,"" - banner="""*********************************************** + l = traceback.format_exception_only(SystemError, e) + l.append(erreurs_connues) + self.cr.exception("Compilation impossible : " + ''.join(l)) + return + + def exec_compile(self): + """ + Cette méthode execute le jeu de commandes compilé dans le contexte + self.g_context de l'objet JDC + """ + CONTEXT.set_current_step(self) + # Le module nommage utilise le module linecache pour accéder + # au source des commandes du jeu de commandes. + # Dans le cas d'un fichier, on accède au contenu de ce fichier + # Dans le cas d'une chaine de caractères il faut accéder + # aux commandes qui sont dans la chaine + import linecache + linecache.cache[self.nom] = 0, 0, string.split( + self.procedure, '\n'), self.nom + try: + exec self.exec_init in self.g_context + # message.debug(SUPERV, "JDC.exec_compile_1 - len(g_context) = %d", + # len(self.g_context.keys())) + for obj_cata in self.cata: + if type(obj_cata) == types.ModuleType: + init2 = "from " + obj_cata.__name__ + " import *" + exec init2 in self.g_context + # message.debug(SUPERV, "JDC.exec_compile_2 - len(g_context) = %d", + # len(self.g_context.keys())) + + # Initialisation du contexte global pour l'évaluation des conditions de BLOC + # On utilise une copie de l'initialisation du contexte du jdc + self.condition_context = self.g_context.copy() + + # Si l'attribut context_ini n'est pas vide, on ajoute au contexte global + # le contexte initial (--> permet d'évaluer un JDC en récupérant un contexte + # d'un autre par exemple) + if self.context_ini: + self.g_context.update(self.context_ini) + # Update du dictionnaire des concepts + for sdnom, sd in self.context_ini.items(): + if isinstance(sd, ASSD): + self.sds_dict[sdnom] = sd + + if self.appli != None: + self.appli.affiche_infos( + 'Interprétation du fichier de commandes en cours ...') + # On sauve le contexte pour garder la memoire des constantes + # En mode edition (EFICAS) ou lors des verifications le contexte + # est recalculé + # mais les constantes sont perdues + self.const_context = self.g_context + # message.debug(SUPERV, "pass") + exec self.proc_compile in self.g_context + # message.debug(SUPERV, "JDC.exec_compile_3 - len(g_context) = %d", + # len(self.g_context.keys())) + + CONTEXT.unset_current_step() + if self.appli != None: + self.appli.affiche_infos('') + + except InterruptParsingError: + # interrupt the command file parsing used by FIN to ignore the end + # of the file + pass + + except EOFError: + # Exception utilise pour interrompre un jeu + # de commandes avant la fin + # Fonctionnement normal, ne doit pas etre considere comme une + # erreur + CONTEXT.unset_current_step() + self.affiche_fin_exec() + self.traiter_fin_exec('commande') + + except AsException, e: + # une erreur a ete identifiee + if CONTEXT.debug: + traceback.print_exc() + # l'exception a été récupérée avant (où, comment ?), + # donc on cherche dans le texte + txt = str(e) + if txt.find('MemoryError') >= 0: + txt = MemoryErrorMsg + self.cr.exception(txt) + CONTEXT.unset_current_step() + + except NameError, e: + etype, value, tb = sys.exc_info() + l = traceback.extract_tb(tb) + s = traceback.format_exception_only("Erreur de nom", e)[0][:-1] + msg = "erreur de syntaxe, %s ligne %d" % (s, l[-1][1]) + if CONTEXT.debug: + traceback.print_exc() + self.cr.exception(msg) + CONTEXT.unset_current_step() + + except self.UserError, exc_val: + self.traiter_user_exception(exc_val) + CONTEXT.unset_current_step() + self.affiche_fin_exec() + self.traiter_fin_exec('commande') + + except: + # erreur inattendue + # sys_exc_typ,sys_exc_value,sys_exc_frame = sys_exc.info() + # (tuple de 3 éléments) + if CONTEXT.debug: + traceback.print_exc() + + traceback.print_exc() + + exc_typ, exc_val, exc_fr = sys.exc_info() + l = traceback.format_exception(exc_typ, exc_val, exc_fr) + self.cr.exception( + "erreur non prevue et non traitee prevenir la maintenance " + '\n' + string.join(l)) + del exc_typ, exc_val, exc_fr + CONTEXT.unset_current_step() + + def affiche_fin_exec(self): + """ + Cette methode realise l'affichage final des statistiques de temps + apres l'execution de toutes + les commandes en mode commande par commande ou par lot + Elle doit etre surchargee pour en introduire un + """ + return + + def traiter_fin_exec(self, mode, etape=None): + """ + Cette methode realise un traitement final apres l'execution de toutes + les commandes en mode commande par commande ou par lot + Par defaut il n'y a pas de traitement. Elle doit etre surchargee + pour en introduire un + """ + message.info(SUPERV, "FIN D'EXECUTION %s %s", mode, etape) + + def traiter_user_exception(self, exc_val): + """Cette methode realise un traitement sur les exceptions utilisateur + Par defaut il n'y a pas de traitement. La méthode doit etre + surchargée pour en introduire un. + """ + return + + def register(self, etape): + """ + Cette méthode ajoute etape dans la liste des etapes : self.etapes + et retourne un numéro d'enregistrement + """ + self.etapes.append(etape) + self.index_etapes[etape] = len(self.etapes) - 1 + # message.debug(SUPERV, "#%d %s", self.index_etapes[etape], etape.nom) + return self.g_register(etape) + + def o_register(self, sd): + """ + Retourne un identificateur pour concept + """ + self.nsd = self.nsd + 1 + nom = sd.idracine + self.SEP + `self.nsd` + return nom + + def g_register(self, etape): + """ + Retourne un identificateur pour etape + """ + self.nstep = self.nstep + 1 + idetape = etape.idracine + self.SEP + `self.nstep` + return idetape + + def create_sdprod(self, etape, nomsd): + """ + Cette methode doit fabriquer le concept produit retourne + par l'etape etape et le nommer. + + Elle est appelée à l'initiative de l'etape + pendant le processus de construction de cette etape : + methode __call__ de la classe CMD (OPER ou MACRO) + + Ce travail est réalisé par le contexte supérieur + (etape.parent) car dans certains cas, le concept ne doit + pas etre fabriqué mais l'etape doit simplement utiliser + un concept préexistant. + + Deux cas possibles : + - Cas 1 : etape.reuse != None : le concept est réutilisé + - Cas 2 : l'étape appartient à une macro qui a déclaré un + concept de sortie qui doit etre produit par cette + etape. + Dans le cas du JDC, le deuxième cas ne peut pas se produire. + """ + sd = etape.get_sd_prod() + if sd != None and (etape.definition.reentrant == 'n' or etape.reuse is None): + # ATTENTION : On ne nomme la SD que dans le cas de non reutilisation + # d un concept. Commande non reentrante ou reuse absent. + self.NommerSdprod(sd, nomsd) + return sd + + def NommerSdprod(self, sd, sdnom, restrict='non'): + """ + 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 + """ + o = self.sds_dict.get(sdnom, None) + if isinstance(o, ASSD): + raise AsException("Nom de concept deja defini : %s" % sdnom) + if sdnom in self._reserved_kw: + raise AsException( + "Nom de concept invalide. '%s' est un mot-clé réservé." % sdnom) + + # Ajoute a la creation (appel de reg_sd). + self.sds_dict[sdnom] = sd + sd.set_name(sdnom) + + # En plus si restrict vaut 'non', on insere le concept dans le contexte + # du JDC + if restrict == 'non': + self.g_context[sdnom] = sd + # message.debug(SUPERV, "g_context[%r] = %s", sdnom, sd) + + def reg_sd(self, sd): + """ + Methode appelee dans l __init__ d un ASSD lors de sa creation + pour s enregistrer + """ + return self.o_register(sd) + + def delete_concept_after_etape(self, etape, sd): + """ + Met à jour les étapes du JDC qui sont après etape suite à + la disparition du concept sd + """ + # Cette methode est définie dans le noyau mais ne sert que pendant + # la phase de creation des etapes et des concepts. Il n'y a aucun + # traitement particulier à réaliser. + # Dans d'autres conditions, il faut surcharger cette méthode + return + + def supprime(self): + N_OBJECT.OBJECT.supprime(self) + for etape in self.etapes: + etape.supprime() + + def clean(self, netapes): + """Nettoie les `netapes` dernières étapes de la liste des étapes.""" + if self.hist_etape: + return + for i in xrange(netapes): + e = self.etapes.pop() + jdc = e.jdc + parent = e.parent + e.supprime() + e.parent = parent + e.jdc = jdc + # message.debug(SUPERV, "JDC.clean - etape = %r - refcount(e) = %d", + # e.nom, sys.getrefcount(e)) + del self.index_etapes[e] + + def get_file(self, unite=None, fic_origine='', fname=None): + """ + Retourne le nom du fichier correspondant à un numero d'unité + logique (entier) ainsi que le source contenu dans le fichier + """ + if self.appli: + # Si le JDC est relié à une application maitre, on délègue la + # recherche + return self.appli.get_file(unite, fic_origine) + else: + if unite != None: + if os.path.exists("fort." + str(unite)): + fname = "fort." + str(unite) + if fname == None: + raise AsException("Impossible de trouver le fichier correspondant" + " a l unite %s" % unite) + if not os.path.exists(fname): + raise AsException("%s n'est pas un fichier existant" % fname) + fproc = open(fname, 'r') + text = fproc.read() + fproc.close() + text = text.replace('\r\n', '\n') + linecache.cache[fname] = 0, 0, text.split('\n'), fname + return fname, text + + def set_par_lot(self, par_lot, user_value=False): + """ + Met le mode de traitement a PAR LOT + ou a COMMANDE par COMMANDE + en fonction de la valeur du mot cle PAR_LOT et + du contexte : application maitre ou pas + + En PAR_LOT='NON', il n'y a pas d'ambiguité. + En PAR_LOT='OUI', E_SUPERV positionne l'attribut à 'NON' après la phase + d'analyse et juste avant la phase d'exécution. + `user_value` : permet de stocker la valeur choisie par l'utilisateur + pour l'interroger plus tard (par exemple dans `get_contexte_avant`). + """ + # message.debug(SUPERV, "set par_lot = %r", par_lot) + if user_value: + self.par_lot_user = par_lot + if self.appli == None: + # Pas d application maitre + self.par_lot = par_lot + else: + # Avec application maitre + self.par_lot = 'OUI' + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitJDC(self) + + def interact(self): + """ + Cette methode a pour fonction d'ouvrir un interpreteur + pour que l'utilisateur entre des commandes interactivement + """ + CONTEXT.set_current_step(self) + try: + # Le module nommage utilise le module linecache pour accéder + # au source des commandes du jeu de commandes. + # Dans le cas d'un fichier, on accède au contenu de ce fichier + # Dans le cas de la console interactive, il faut pouvoir accéder + # aux commandes qui sont dans le buffer de la console + import linecache + import code + console = code.InteractiveConsole( + self.g_context, filename="") + linecache.cache[""] = 0, 0, console.buffer, "" + banner = """*********************************************** * Interpreteur interactif %s ***********************************************""" % self.code - console.interact(banner) - finally: - console=None - CONTEXT.unset_current_step() - - def get_contexte_avant(self,etape): - """ - Retourne le dictionnaire des concepts connus avant etape - On tient compte des commandes qui modifient le contexte - comme DETRUIRE ou les macros - Si etape == None, on retourne le contexte en fin de JDC - """ - # L'étape courante pour laquelle le contexte a été calculé est - # mémorisée dans self.index_etape_courante - # XXX on pourrait faire mieux dans le cas PAR_LOT="NON" : en - # mémorisant l'étape - # courante pendant le processus de construction des étapes. - # Si on insère des commandes (par ex, dans EFICAS), il faut préalablement - # remettre ce pointeur à 0 - #message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)]) - #message.debug(SUPERV, "current_context : %s", [k for k, v in self.current_context.items() if isinstance(v, ASSD)]) - if self.par_lot_user == 'NON': - d = self.current_context = self.g_context.copy() - if etape is None: - return d - # retirer les sd produites par 'etape' - sd_names = [sd.nom for sd in etape.get_created_sd()] - #message.debug(SUPERV, "reuse : %s, sdprods : %s", etape.reuse, sd_names) - for nom in sd_names: - try: - del d[nom] - except KeyError: - from warnings import warn - warn("concept '%s' absent du contexte de %s" % (nom, self.nom), - RuntimeWarning, stacklevel=2) - return d - if etape: - index_etape = self.index_etapes[etape] - else: - index_etape=len(self.etapes) - if index_etape >= self.index_etape_courante: - # On calcule le contexte en partant du contexte existant - d=self.current_context - if self.index_etape_courante==0 and self.context_ini: - d.update(self.context_ini) - liste_etapes=self.etapes[self.index_etape_courante:index_etape] - else: - d=self.current_context={} - if self.context_ini: - d.update(self.context_ini) - liste_etapes=self.etapes - - for e in liste_etapes: - if e is etape: - break - if e.isactif(): - e.update_context(d) - self.index_etape_courante=index_etape - #message.debug(SUPERV, "returns : %s", [k for k, v in d.items() if isinstance(v, ASSD)]) - return d - - def get_global_contexte(self): - """Retourne "un" contexte global ;-)""" - # N'est utilisé que par INCLUDE (sauf erreur). - # g_context est remis à {} en PAR_LOT='OUI'. const_context permet - # de retrouver ce qui y a été mis par exec_compile. - # Les concepts n'y sont pas en PAR_LOT='OUI'. Ils sont ajoutés - # par get_global_contexte de la MACRO. - d = self.const_context.copy() - d.update(self.g_context) - return d - - - def get_contexte_courant(self, etape_courante=None): - """ - Retourne le contexte tel qu'il est (ou 'sera' si on est en phase - de construction) au moment de l'exécution de l'étape courante. - """ - if etape_courante is None: - etape_courante = CONTEXT.get_current_step() - return self.get_contexte_avant(etape_courante) - - - def get_concept(self, nomsd): - """ - Méthode pour récuperer un concept à partir de son nom - """ - co = self.get_contexte_courant().get(nomsd.strip(), None) - if not isinstance(co, ASSD): - co = None - return co - - def get_concept_by_type(self, nomsd, typesd, etape): - """ - Méthode pour récuperer un concept à partir de son nom et de son type. - Il aura comme père 'etape'. - """ - assert issubclass(typesd, ASSD), typesd - co = typesd(etape=etape) - co.set_name(nomsd) - co.executed = 1 - return co - - def del_concept(self, nomsd): - """ - Méthode pour supprimer la référence d'un concept dans le sds_dict. - Ne détruire pas le concept (différent de supprime). - """ - try: - del self.sds_dict[nomsd.strip()] - except: - pass - - - def get_cmd(self,nomcmd): - """ - Méthode pour recuperer la definition d'une commande - donnee par son nom dans les catalogues declares - au niveau du jdc - """ - for cata in self.cata: - if hasattr(cata,nomcmd): - return getattr(cata,nomcmd) - - def append_reset(self,etape): - """ - Ajoute une etape provenant d'un autre jdc a la liste des etapes - et remet à jour la parenté de l'étape et des concepts - """ - self.etapes.append(etape) - self.index_etapes[etape] = len(self.etapes) - 1 - etape.reparent(self) - etape.reset_jdc(self) - - def sd_accessible(self): - """On peut acceder aux "valeurs" (jeveux) des ASSD si le JDC est en PAR_LOT="NON". - """ - if CONTEXT.debug: print ' `- JDC sd_accessible : PAR_LOT =', self.par_lot - return self.par_lot == 'NON' - - - def _build_reserved_kw_list(self): - """Construit la liste des mots-clés réservés (interdits pour le - nommage des concepts).""" - self._reserved_kw = set() - for cat in self.cata: - self._reserved_kw.update([kw for kw in dir(cat) if len(kw) <= 8 and kw == kw.upper()]) - self._reserved_kw.difference_update(['OPER', 'MACRO', 'BLOC', 'SIMP', 'FACT', 'FORM', - 'GEOM', 'MCSIMP', 'MCFACT']) - + console.interact(banner) + finally: + console = None + CONTEXT.unset_current_step() + + def get_contexte_avant(self, etape): + """ + Retourne le dictionnaire des concepts connus avant etape + On tient compte des commandes qui modifient le contexte + comme DETRUIRE ou les macros + Si etape == None, on retourne le contexte en fin de JDC + """ + # L'étape courante pour laquelle le contexte a été calculé est + # mémorisée dans self.index_etape_courante + # XXX on pourrait faire mieux dans le cas PAR_LOT="NON" : en + # mémorisant l'étape + # courante pendant le processus de construction des étapes. + # Si on insère des commandes (par ex, dans EFICAS), il faut préalablement + # remettre ce pointeur à 0 + # message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)]) + # message.debug(SUPERV, "current_context : %s", [k for k, v in + # self.current_context.items() if isinstance(v, ASSD)]) + if self.par_lot_user == 'NON': + d = self.current_context = self.g_context.copy() + if etape is None: + return d + # retirer les sd produites par 'etape' + sd_names = [sd.nom for sd in etape.get_created_sd()] + # message.debug(SUPERV, "reuse : %s, sdprods : %s", etape.reuse, + # sd_names) + for nom in sd_names: + try: + del d[nom] + except KeyError: + from warnings import warn + warn( + "concept '%s' absent du contexte de %s" % ( + nom, self.nom), + RuntimeWarning, stacklevel=2) + return d + if etape: + index_etape = self.index_etapes[etape] + else: + index_etape = len(self.etapes) + if index_etape >= self.index_etape_courante: + # On calcule le contexte en partant du contexte existant + d = self.current_context + if self.index_etape_courante == 0 and self.context_ini: + d.update(self.context_ini) + liste_etapes = self.etapes[self.index_etape_courante:index_etape] + else: + d = self.current_context = {} + if self.context_ini: + d.update(self.context_ini) + liste_etapes = self.etapes + + for e in liste_etapes: + if e is etape: + break + if e.isactif(): + e.update_context(d) + self.index_etape_courante = index_etape + # message.debug(SUPERV, "returns : %s", [k for k, v in d.items() if + # isinstance(v, ASSD)]) + return d + + def get_global_contexte(self): + """Retourne "un" contexte global ;-)""" + # N'est utilisé que par INCLUDE (sauf erreur). + # g_context est remis à {} en PAR_LOT='OUI'. const_context permet + # de retrouver ce qui y a été mis par exec_compile. + # Les concepts n'y sont pas en PAR_LOT='OUI'. Ils sont ajoutés + # par get_global_contexte de la MACRO. + d = self.const_context.copy() + d.update(self.g_context) + return d + + def get_contexte_courant(self, etape_courante=None): + """ + Retourne le contexte tel qu'il est (ou 'sera' si on est en phase + de construction) au moment de l'exécution de l'étape courante. + """ + if etape_courante is None: + etape_courante = CONTEXT.get_current_step() + return self.get_contexte_avant(etape_courante) + + def get_concept(self, nomsd): + """ + Méthode pour récuperer un concept à partir de son nom + """ + co = self.get_contexte_courant().get(nomsd.strip(), None) + if not isinstance(co, ASSD): + co = None + return co + + def get_concept_by_type(self, nomsd, typesd, etape): + """ + Méthode pour récuperer un concept à partir de son nom et de son type. + Il aura comme père 'etape'. + """ + assert issubclass(typesd, ASSD), typesd + co = typesd(etape=etape) + co.set_name(nomsd) + co.executed = 1 + return co + + def del_concept(self, nomsd): + """ + Méthode pour supprimer la référence d'un concept dans le sds_dict. + Ne détruire pas le concept (différent de supprime). + """ + try: + del self.sds_dict[nomsd.strip()] + except: + pass + + def get_cmd(self, nomcmd): + """ + Méthode pour recuperer la definition d'une commande + donnee par son nom dans les catalogues declares + au niveau du jdc + """ + for cata in self.cata: + if hasattr(cata, nomcmd): + return getattr(cata, nomcmd) + + def append_reset(self, etape): + """ + Ajoute une etape provenant d'un autre jdc a la liste des etapes + et remet à jour la parenté de l'étape et des concepts + """ + self.etapes.append(etape) + self.index_etapes[etape] = len(self.etapes) - 1 + etape.reparent(self) + etape.reset_jdc(self) + + def sd_accessible(self): + """On peut acceder aux "valeurs" (jeveux) des ASSD si le JDC est en PAR_LOT="NON". + """ + if CONTEXT.debug: + print ' `- JDC sd_accessible : PAR_LOT =', self.par_lot + return self.par_lot == 'NON' + + def _build_reserved_kw_list(self): + """Construit la liste des mots-clés réservés (interdits pour le + nommage des concepts).""" + self._reserved_kw = set() + for cat in self.cata: + self._reserved_kw.update( + [kw for kw in dir(cat) if len(kw) <= 8 and kw == kw.upper()]) + self._reserved_kw.difference_update( + ['OPER', 'MACRO', 'BLOC', 'SIMP', 'FACT', 'FORM', + 'GEOM', 'MCSIMP', 'MCFACT']) diff --git a/Noyau/N_JDC_CATA.py b/Noyau/N_JDC_CATA.py index 16c91665..bfd8832a 100644 --- a/Noyau/N_JDC_CATA.py +++ b/Noyau/N_JDC_CATA.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,121 +16,120 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -# -# ====================================================================== """ Ce module contient la classe de definition JDC_CATA - qui permet de spécifier les caractéristiques d'un JDC + qui permet de spécifier les caractéristiques d'un JDC """ -import types,string,traceback +import types +import string +import traceback import N_ENTITE import N_JDC from strfunc import ufmt -class JDC_CATA(N_ENTITE.ENTITE): - """ - Classe pour definir un jeu de commandes - - Attributs de classe : - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité - du jeu de commandes avec sa définition - - - label qui indique la nature de l'objet de définition (ici, JDC) - - """ - class_instance = N_JDC.JDC - label = 'JDC' - - def __init__(self,code='',execmodul=None,regles=(),niveaux=(),**args): - """ - """ - self.code = code - self.execmodul=execmodul - if type(regles)== types.TupleType: - self.regles = regles - else: - self.regles=(regles,) - # Tous les arguments supplémentaires sont stockés dans l'attribut args - # et seront passés au JDC pour initialiser ses paramètres propres - self.args=args - self.d_niveaux={} - self.l_niveaux=niveaux - self.commandes=[] - for niveau in niveaux: - self.d_niveaux[niveau.nom]=niveau - # On change d'objet catalogue. Il faut d'abord mettre le catalogue - # courant à None - CONTEXT.unset_current_cata() - CONTEXT.set_current_cata(self) - - def __call__(self,procedure=None,cata=None,cata_ord_dico=None, - nom='SansNom',parent=None,**args): - """ - Construit l'objet JDC a partir de sa definition (self), - """ - return self.class_instance(definition=self,procedure=procedure, - cata=cata,cata_ord_dico=cata_ord_dico, - nom=nom, - parent=parent, - **args - ) - - def enregistre(self,commande): - """ - Methode qui permet aux definitions de commandes de s'enregistrer aupres - d'un JDC_CATA - """ - self.commandes.append(commande) - - def verif_cata(self): - """ - Méthode de vérification des attributs de définition - """ - self.check_regles() - self.verif_cata_regles() - - def verif_cata_regles(self): - """ - Cette méthode vérifie pour tous les objets stockés dans la liste entités - respectent les REGLES associés à self - """ - # A FAIRE - - def report(self): - """ - Methode pour produire un compte-rendu de validation d'un catalogue de commandes - """ - self.cr = self.CR(debut = u"Compte-rendu de validation du catalogue "+self.code, - fin = u"Fin Compte-rendu de validation du catalogue "+self.code) - self.verif_cata() - for commande in self.commandes: - cr = commande.report() - cr.debut = u"Début Commande :"+commande.nom - cr.fin = u"Fin commande :"+commande.nom - self.cr.add(cr) - return self.cr - - def supprime(self): - """ - Méthode pour supprimer les références arrières susceptibles de provoquer - des cycles de références - """ - for commande in self.commandes: - commande.supprime() - - def get_niveau(self,nom_niveau): - """ - Retourne l'objet de type NIVEAU de nom nom_niveau - ou None s'il n'existe pas - """ - return self.d_niveaux.get(nom_niveau,None) - +class JDC_CATA(N_ENTITE.ENTITE): + """ + Classe pour definir un jeu de commandes + + Attributs de classe : + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité + du jeu de commandes avec sa définition + + - label qui indique la nature de l'objet de définition (ici, JDC) + + """ + class_instance = N_JDC.JDC + label = 'JDC' + + def __init__(self, code='', execmodul=None, regles=(), niveaux=(), **args): + """ + """ + self.code = code + self.execmodul = execmodul + if type(regles) == types.TupleType: + self.regles = regles + else: + self.regles = (regles,) + # Tous les arguments supplémentaires sont stockés dans l'attribut args + # et seront passés au JDC pour initialiser ses paramètres propres + self.args = args + self.d_niveaux = {} + self.l_niveaux = niveaux + self.commandes = [] + for niveau in niveaux: + self.d_niveaux[niveau.nom] = niveau + # On change d'objet catalogue. Il faut d'abord mettre le catalogue + # courant à None + CONTEXT.unset_current_cata() + CONTEXT.set_current_cata(self) + + def __call__(self, procedure=None, cata=None, cata_ord_dico=None, + nom='SansNom', parent=None, **args): + """ + Construit l'objet JDC a partir de sa definition (self), + """ + return self.class_instance(definition=self, procedure=procedure, + cata=cata, cata_ord_dico=cata_ord_dico, + nom=nom, + parent=parent, + **args + ) + + def enregistre(self, commande): + """ + Methode qui permet aux definitions de commandes de s'enregistrer aupres + d'un JDC_CATA + """ + self.commandes.append(commande) + + def verif_cata(self): + """ + Méthode de vérification des attributs de définition + """ + self.check_regles() + self.verif_cata_regles() + + def verif_cata_regles(self): + """ + Cette méthode vérifie pour tous les objets stockés dans la liste entités + respectent les REGLES associés à self + """ + # A FAIRE + + def report(self): + """ + Methode pour produire un compte-rendu de validation d'un catalogue de commandes + """ + self.cr = self.CR( + debut=u"Compte-rendu de validation du catalogue " + self.code, + fin=u"Fin Compte-rendu de validation du catalogue " + self.code) + self.verif_cata() + for commande in self.commandes: + cr = commande.report() + cr.debut = u"Début Commande :" + commande.nom + cr.fin = u"Fin commande :" + commande.nom + self.cr.add(cr) + return self.cr + + def supprime(self): + """ + Méthode pour supprimer les références arrières susceptibles de provoquer + des cycles de références + """ + for commande in self.commandes: + commande.supprime() + + def get_niveau(self, nom_niveau): + """ + Retourne l'objet de type NIVEAU de nom nom_niveau + ou None s'il n'existe pas + """ + return self.d_niveaux.get(nom_niveau, None) diff --git a/Noyau/N_LASSD.py b/Noyau/N_LASSD.py index 371cfb18..b3886430 100644 --- a/Noyau/N_LASSD.py +++ b/Noyau/N_LASSD.py @@ -16,6 +16,5 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# from N_ASSD import ASSD class LASSD(ASSD,list):pass diff --git a/Noyau/N_MACRO.py b/Noyau/N_MACRO.py index e4fdbb27..58d743e0 100644 --- a/Noyau/N_MACRO.py +++ b/Noyau/N_MACRO.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,160 +16,163 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ Ce module contient la classe de definition MACRO - qui permet de spécifier les caractéristiques d'une macro-commande + qui permet de spécifier les caractéristiques d'une macro-commande """ -import types,string,traceback +import types +import string +import traceback import N_ENTITE import N_MACRO_ETAPE import nommage from strfunc import ufmt + class MACRO(N_ENTITE.ENTITE): - """ - Classe pour definir une macro-commande - - Cette classe a trois attributs de classe - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - macro-commande avec sa définition - - - label qui indique la nature de l'objet de définition (ici, MACRO) - - - nommage qui est un module Python qui fournit la fonctionnalité de nommage - - et les attributs d'instance suivants : - - - nom : son nom - - - op : le numéro d'opérateur - - - sd_prod : le type de concept produit. C'est une classe ou une fonction qui retourne - une classe - - - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur - réentrant peut modifier un concept d'entrée et le produire comme concept de sortie - - - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur - non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort - de l'objet gérant le contexte d'exécution de vérifier cette contrainte. - - - fr : commentaire associé en francais - - - ang : commentaire associé en anglais - - - docu : clé de documentation associée - - - regles : liste des règles associées - - - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette - fonction est exécutée lors des phases d'initialisation de l'étape associée. - - - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre - rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. - Si niveau vaut None, l'opérateur est rangé au niveau global. - - - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit - des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut - est initialisé avec args, c'est à dire les arguments d'appel restants. - - - """ - class_instance = N_MACRO_ETAPE.MACRO_ETAPE - label = 'MACRO' - nommage = nommage - - def __init__(self,nom,op,sd_prod=None,reentrant='n',repetable='o',fr="",ang="", - docu="",regles=(),op_init=None,niveau = None,fichier_ini=0,UIinfo=None,**args): - """ - Méthode d'initialisation de l'objet MACRO. Les arguments sont utilisés pour initialiser - les attributs de meme nom - """ - # XXX fichier_ini n'est pas utilisé pour l'instant - self.nom=nom - # op est obligatoire et permet de spécifier la procédure de construction de la macro - # - Si op est un entier la construction de la macro est réalisée par une subroutine fortran opsxxx ou - # xxx est donné par la valeur absolue de op. L'execution est egalement effectuée via cette subroutine. - # - Si op est une fonction Python, la construction de la macro est effectuée par l'appel à cette fonction - # Suivant le cas on garde l info dans self.op ou dans self.proc - if type(op) == types.IntType: - self.proc=None - self.op=op - else: - self.op=None - self.proc=op - - self.sd_prod=sd_prod - self.reentrant=reentrant - self.fr=fr - self.ang=ang - self.repetable = repetable - self.docu=docu - if type(regles)== types.TupleType: - self.regles=regles - else: - self.regles=(regles,) - self.fichier_ini = fichier_ini - # Attribut op_init : Fonction a appeler a la construction de l operateur sauf si == None - self.op_init=op_init - self.entites = args - current_cata=CONTEXT.get_current_cata() - if niveau == None: - self.niveau=None - current_cata.enregistre(self) - else: - self.niveau=current_cata.get_niveau(niveau) - self.niveau.enregistre(self) - self.UIinfo=UIinfo - self.affecter_parente() - self.check_definition(self.nom) - - def __call__(self,reuse=None,**args): - """ - Construit l'objet MACRO_ETAPE a partir de sa definition (self), - puis demande la construction de ses sous-objets et du concept produit. - """ - nomsd = self.nommage.GetNomConceptResultat(self.nom) - etape = self.class_instance(oper=self,reuse=reuse,args=args) - etape.McBuild() - return etape.Build_sd(nomsd) - - def make_objet(self,mc_list='oui'): - """ - Cette méthode crée l'objet MACRO_ETAPE dont la définition est self sans - créer sa sdprod. - Normalement l'étape est enregistrée auprès de son parent. - Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction - des objets MCxxx. - """ - etape= self.class_instance(oper=self,reuse=None,args={}) - if mc_list == 'oui':etape.McBuild() - return etape - - def verif_cata(self): - """ - Méthode de vérification des attributs de définition - """ - self.check_op(valmax=0) - self.check_proc() - self.check_regles() - self.check_fr() - self.check_docu() - self.check_nom() - self.check_reentrant() - self.verif_cata_regles() - - def supprime(self): - """ - Méthode pour supprimer les références arrières susceptibles de provoquer - des cycles de références - """ - self.niveau=None + """ + Classe pour definir une macro-commande + + Cette classe a trois attributs de classe + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + macro-commande avec sa définition + + - label qui indique la nature de l'objet de définition (ici, MACRO) + + - nommage qui est un module Python qui fournit la fonctionnalité de nommage + + et les attributs d'instance suivants : + + - nom : son nom + + - op : le numéro d'opérateur + + - sd_prod : le type de concept produit. C'est une classe ou une fonction qui retourne + une classe + + - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur + réentrant peut modifier un concept d'entrée et le produire comme concept de sortie + + - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur + non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort + de l'objet gérant le contexte d'exécution de vérifier cette contrainte. + + - fr : commentaire associé en francais + + - docu : clé de documentation associée + + - regles : liste des règles associées + + - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette + fonction est exécutée lors des phases d'initialisation de l'étape associée. + + - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre + rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. + Si niveau vaut None, l'opérateur est rangé au niveau global. + + - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit + des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut + est initialisé avec args, c'est à dire les arguments d'appel restants. + + + """ + class_instance = N_MACRO_ETAPE.MACRO_ETAPE + label = 'MACRO' + nommage = nommage + + def __init__( + self, nom, op, sd_prod=None, reentrant='n', repetable='o', fr="",ang="", + docu="", regles=(), op_init=None, niveau = None, fichier_ini=0, UIinfo=None, **args): + """ + Méthode d'initialisation de l'objet MACRO. Les arguments sont utilisés pour initialiser + les attributs de meme nom + """ + # XXX fichier_ini n'est pas utilisé pour l'instant + self.nom = nom + # op est obligatoire et permet de spécifier la procédure de construction de la macro + # - Si op est un entier la construction de la macro est réalisée par une subroutine fortran opsxxx ou + # xxx est donné par la valeur absolue de op. L'execution est egalement effectuée via cette subroutine. + # - Si op est une fonction Python, la construction de la macro est effectuée par l'appel à cette fonction + # Suivant le cas on garde l info dans self.op ou dans self.proc + if type(op) == types.IntType: + self.proc = None + self.op = op + else: + self.op = None + self.proc = op + + self.sd_prod = sd_prod + self.reentrant = reentrant + self.fr = fr + self.ang=ang + self.repetable = repetable + self.docu = docu + if type(regles) == types.TupleType: + self.regles = regles + else: + self.regles = (regles,) + self.fichier_ini = fichier_ini + # Attribut op_init : Fonction a appeler a la construction de l + # operateur sauf si == None + self.op_init = op_init + self.entites = args + current_cata = CONTEXT.get_current_cata() + if niveau == None: + self.niveau = None + current_cata.enregistre(self) + else: + self.niveau = current_cata.get_niveau(niveau) + self.niveau.enregistre(self) + self.UIinfo = UIinfo + self.affecter_parente() + self.check_definition(self.nom) + + def __call__(self, reuse=None, **args): + """ + Construit l'objet MACRO_ETAPE a partir de sa definition (self), + puis demande la construction de ses sous-objets et du concept produit. + """ + nomsd = self.nommage.GetNomConceptResultat(self.nom) + etape = self.class_instance(oper=self, reuse=reuse, args=args) + etape.McBuild() + return etape.Build_sd(nomsd) + + def make_objet(self, mc_list='oui'): + """ + Cette méthode crée l'objet MACRO_ETAPE dont la définition est self sans + créer sa sdprod. + Normalement l'étape est enregistrée auprès de son parent. + Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction + des objets MCxxx. + """ + etape = self.class_instance(oper=self, reuse=None, args={}) + if mc_list == 'oui': + etape.McBuild() + return etape + + def verif_cata(self): + """ + Méthode de vérification des attributs de définition + """ + self.check_op(valmax=0) + self.check_proc() + self.check_regles() + self.check_fr() + self.check_docu() + self.check_nom() + self.check_reentrant() + self.verif_cata_regles() + + def supprime(self): + """ + Méthode pour supprimer les références arrières susceptibles de provoquer + des cycles de références + """ + self.niveau = None diff --git a/Noyau/N_MACRO_ETAPE.py b/Noyau/N_MACRO_ETAPE.py index ee2e2043..99f6146d 100644 --- a/Noyau/N_MACRO_ETAPE.py +++ b/Noyau/N_MACRO_ETAPE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,15 +16,17 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ - Ce module contient la classe MACRO_ETAPE qui sert à vérifier et à exécuter + Ce module contient la classe MACRO_ETAPE qui sert à vérifier et à exécuter une commande """ # Modules Python -import types,sys,string +import types +import sys +import string import traceback from warnings import warn @@ -38,480 +40,506 @@ from N_CO import CO from N_ASSD import ASSD from N_info import message, SUPERV + class MACRO_ETAPE(N_ETAPE.ETAPE): - """ - - """ - nature = "COMMANDE" - typeCO=CO - def __init__(self,oper=None,reuse=None,args={}): - """ - Attributs : - - definition : objet portant les attributs de définition d'une étape - de type macro-commande. Il est initialisé par - l'argument oper. - - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc - en sortie si les conditions d'exécution de l'opérateur - l'autorise - - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé - avec l'argument args. - """ - N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5) - self.g_context = {} - # Contexte courant - self.current_context = {} - self.macro_const_context = {} - self.index_etape_courante = 0 - self.etapes = [] - self.index_etapes = {} - # Dans le cas d'une macro écrite en Python, l'attribut Outputs est un - # dictionnaire qui contient les concepts produits de sortie - # (nom : ASSD) déclarés dans la fonction sd_prod - self.Outputs = {} - self.sdprods = [] - self.UserError = "UserError" - # permet de stocker le nom du dernier concept nommé dans la macro - self.last = None - - def make_register(self): - """ - Initialise les attributs jdc, id, niveau et réalise les enregistrements - nécessaires - """ - N_ETAPE.ETAPE.make_register(self) - if self.parent : - self.UserError=self.jdc.UserError - else: - self.UserError="UserError" - - 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. - - """ - #message.debug(SUPERV, "%s", self.nom) - self.sdnom=nom - 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.set_name(nom) - self.reset_current_step() - except AsException,e: - self.reset_current_step() - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1],e) - except (EOFError, self.UserError): - # Le retablissement du step courant n'est pas strictement necessaire. On le fait pour des raisons de coherence - 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)) - - self.Execute() - return sd - - def get_sd_prod(self): - """ - Retourne le concept résultat d'une macro étape - La difference avec une etape ou une proc-etape tient a ce que - le concept produit peut exister ou pas - - Si sd_prod == None le concept produit n existe pas on retourne None - - Deux cas : - - cas 1 : sd_prod n'est pas une fonction - il s'agit d'une sous classe de ASSD - on construit le sd à partir de cette classe - et on le retourne - - cas 2 : sd_prod est une fonction - on l'évalue avec les mots-clés de l'étape (mc_liste) - on construit le sd à partir de la classe obtenue - et on le retourne - """ - sd_prod=self.definition.sd_prod - self.typret=None - - if type(self.definition.sd_prod) == types.FunctionType: - d=self.cree_dict_valeurs(self.mc_liste) + + """ + + """ + nature = "COMMANDE" + typeCO = CO + + def __init__(self, oper=None, reuse=None, args={}): + """ + Attributs : + - definition : objet portant les attributs de définition d'une étape + de type macro-commande. Il est initialisé par + l'argument oper. + - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc + en sortie si les conditions d'exécution de l'opérateur + l'autorise + - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé + avec l'argument args. + """ + N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5) + self.g_context = {} + # Contexte courant + self.current_context = {} + self.macro_const_context = {} + self.index_etape_courante = 0 + self.etapes = [] + self.index_etapes = {} + # Dans le cas d'une macro écrite en Python, l'attribut Outputs est un + # dictionnaire qui contient les concepts produits de sortie + # (nom : ASSD) déclarés dans la fonction sd_prod + self.Outputs = {} + self.sdprods = [] + self.UserError = "UserError" + # permet de stocker le nom du dernier concept nommé dans la macro + self.last = None + + def make_register(self): + """ + Initialise les attributs jdc, id, niveau et réalise les enregistrements + nécessaires + """ + N_ETAPE.ETAPE.make_register(self) + if self.parent: + self.UserError = self.jdc.UserError + else: + self.UserError = "UserError" + + 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. + + """ + # message.debug(SUPERV, "%s", self.nom) + self.sdnom = nom try: - # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument - # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute - # les concepts produits dans self.sdprods, il faut le mettre à zéro avant de l'appeler - self.sdprods=[] - sd_prod= apply(sd_prod,(self,),d) - except (EOFError,self.UserError): - raise + # 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.set_name(nom) + self.reset_current_step() + except AsException, e: + self.reset_current_step() + raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0], + 'fichier : ', self.appel[1], e) + except (EOFError, self.UserError): + # Le retablissement du step courant n'est pas strictement + # necessaire. On le fait pour des raisons de coherence + self.reset_current_step() + raise except: - if CONTEXT.debug: traceback.print_exc() - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("impossible d affecter un type au resultat\n",string.join(l[2:])) - - # on teste maintenant si la SD est réutilisée ou s'il faut la créer - if self.definition.reentrant != 'n' and self.reuse: - # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale. - # Elle sera traitee ulterieurement. - self.sd=self.reuse - else: - if sd_prod == None: - self.sd=None + 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)) + + self.Execute() + return sd + + def get_sd_prod(self): + """ + Retourne le concept résultat d'une macro étape + La difference avec une etape ou une proc-etape tient a ce que + le concept produit peut exister ou pas + + Si sd_prod == None le concept produit n existe pas on retourne None + + Deux cas : + - cas 1 : sd_prod n'est pas une fonction + il s'agit d'une sous classe de ASSD + on construit le sd à partir de cette classe + et on le retourne + - cas 2 : sd_prod est une fonction + on l'évalue avec les mots-clés de l'étape (mc_liste) + on construit le sd à partir de la classe obtenue + et on le retourne + """ + sd_prod = self.definition.sd_prod + self.typret = None + + if type(self.definition.sd_prod) == types.FunctionType: + d = self.cree_dict_valeurs(self.mc_liste) + try: + # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument + # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute + # les concepts produits dans self.sdprods, il faut le mettre à + # zéro avant de l'appeler + self.sdprods = [] + sd_prod = apply(sd_prod, (self,), d) + except (EOFError, self.UserError): + raise + except: + if CONTEXT.debug: + traceback.print_exc() + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) + raise AsException( + "impossible d affecter un type au resultat\n", string.join(l[2:])) + + # on teste maintenant si la SD est réutilisée ou s'il faut la créer + if self.definition.reentrant != 'n' and self.reuse: + # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale. + # Elle sera traitee ulterieurement. + self.sd = self.reuse else: - self.sd= sd_prod(etape=self) - self.typret=sd_prod - # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur. - # On ne fait rien ici. L'erreur sera traitee par la suite. - # précaution - if self.sd is not None and not isinstance(self.sd, ASSD): - raise AsException(""" -Impossible de typer le résultat ! + if sd_prod == None: + self.sd = None + else: + self.sd = sd_prod(etape=self) + self.typret = sd_prod + # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur. + # On ne fait rien ici. L'erreur sera traitee par la suite. + # précaution + if self.sd is not None and not isinstance(self.sd, ASSD): + raise AsException(""" +Impossible de typer le résultat ! Causes possibles : - Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte, - soit il y a une "," à la fin d'une commande précédente. - Développeur : La fonction "sd_prod" retourne un type invalide.""") - return self.sd - - def get_type_produit(self,force=0): - try: - return self.get_type_produit_brut(force) - except: - #traceback.print_exc() - return None - - def get_type_produit_brut(self,force=0): - """ - Retourne le type du concept résultat de l'étape et eventuellement type - les concepts produits "à droite" du signe égal (en entrée) - - Deux cas : - - cas 1 : sd_prod de oper n'est pas une fonction - il s'agit d'une sous classe de ASSD - on retourne le nom de la classe - - cas 2 : il s'agit d'une fonction - on l'évalue avec les mots-clés de l'étape (mc_liste) - et on retourne son résultat - """ - if not force and hasattr(self,'typret'): - return self.typret - - if type(self.definition.sd_prod) == types.FunctionType: - d=self.cree_dict_valeurs(self.mc_liste) - # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute - # les concepts produits dans self.sdprods, il faut le mettre à zéro - self.sdprods=[] - sd_prod= apply(self.definition.sd_prod,(self,),d) - else: - sd_prod=self.definition.sd_prod - return sd_prod - - def get_contexte_avant(self,etape): - """ - Retourne le dictionnaire des concepts connus avant etape - pour les commandes internes a la macro - On tient compte des commandes qui modifient le contexte - comme DETRUIRE ou les macros - """ - # L'étape courante pour laquelle le contexte a été calculé est - # mémorisée dans self.index_etape_courante - #message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)]) - #message.debug(SUPERV, "current_context : %s", [k for k, v in self.current_context.items() if isinstance(v, ASSD)]) - d = self.current_context = self.g_context.copy() - if etape is None: - return d - # retirer les sd produites par 'etape' - sd_names = [sd.nom for sd in etape.get_created_sd()] - #message.debug(SUPERV, "etape: %s, reuse : %s, sdprods de %s : %s", - #self.nom, etape.reuse, etape.nom, sd_names) - for nom in sd_names: - try: - del d[nom] - except KeyError: - pass - # Exemple avec INCLUDE_MATERIAU appelé dans une macro. - # Les fonctions restent uniquement dans le contexte de INCLUDE_MATERIAU, - # elles ne sont donc pas dans le contexte de la macro appelante. - #from warnings import warn - #warn("concept '%s' absent du contexte de %s" % (nom, self.nom), - #RuntimeWarning, stacklevel=2) - return d - - def supprime(self): - """ - Méthode qui supprime toutes les références arrières afin que - l'objet puisse etre correctement détruit par le garbage collector - """ - N_MCCOMPO.MCCOMPO.supprime(self) - self.jdc=None - self.appel=None - if self.sd : self.sd.supprime() - for concept in self.sdprods: - concept.supprime() - for etape in self.etapes: - etape.supprime() - - def clean(self, netapes): - """Nettoie les `netapes` dernières étapes de la liste des étapes.""" - if self.jdc.hist_etape: - return - for i in xrange(netapes): - e=self.etapes.pop() - jdc=e.jdc - parent=e.parent - e.supprime() - e.parent=parent - e.jdc=jdc - #message.debug(SUPERV, "MACRO.clean - etape = %s - refcount(e) = %d", - #e.nom, sys.getrefcount(e)) - del self.index_etapes[e] - - def type_sdprod(self,co,t): - """ - Cette methode a pour fonction de typer le concept co avec le type t - dans les conditions suivantes : - 1. co est un concept produit de self - 2. co est un concept libre : on le type et on l attribue à self - - Elle enregistre egalement les concepts produits (on fait l hypothese - que la liste sdprods a été correctement initialisee, vide probablement) - """ - if not hasattr(co,'etape'): - # Le concept vaut None probablement. On ignore l'appel - return - # - # On cherche a discriminer les differents cas de typage d'un concept - # produit par une macro qui est specifie dans un mot cle simple. - # On peut passer plusieurs fois par type_sdprod ce qui explique - # le nombre important de cas. - # - # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom) - # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod. - # Cas semblable a Cas 1. - # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere - # la propriete du concept de la macro parent a la macro courante (self) - # en verifiant que le type est valide - # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est - # deja passe par type_sdprod et que la propriete a ete transfere a une - # etape fille. Cas semblable a Cas 3. - # Cas 5 : Le concept est produit par une etape externe a la macro. - # - if co.etape == None: - # Cas 1 : le concept est libre - # On l'attache a la macro et on change son type dans le type demande - # Recherche du mot cle simple associe au concept - mcs=self.get_mcs_with_co(co) - if len(mcs) != 1: - raise AsException("""Erreur interne. + Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte, + soit il y a une "," à la fin d'une commande précédente. + Développeur : La fonction "sd_prod" retourne un type invalide.""") + return self.sd + + def get_type_produit(self, force=0): + try: + return self.get_type_produit_brut(force) + except: + # traceback.print_exc() + return None + + def get_type_produit_brut(self, force=0): + """ + Retourne le type du concept résultat de l'étape et eventuellement type + les concepts produits "à droite" du signe égal (en entrée) + + Deux cas : + - cas 1 : sd_prod de oper n'est pas une fonction + il s'agit d'une sous classe de ASSD + on retourne le nom de la classe + - cas 2 : il s'agit d'une fonction + on l'évalue avec les mots-clés de l'étape (mc_liste) + et on retourne son résultat + """ + if not force and hasattr(self, 'typret'): + return self.typret + + if type(self.definition.sd_prod) == types.FunctionType: + d = self.cree_dict_valeurs(self.mc_liste) + # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute + # les concepts produits dans self.sdprods, il faut le mettre à zéro + self.sdprods = [] + sd_prod = apply(self.definition.sd_prod, (self,), d) + else: + sd_prod = self.definition.sd_prod + return sd_prod + + def get_contexte_avant(self, etape): + """ + Retourne le dictionnaire des concepts connus avant etape + pour les commandes internes a la macro + On tient compte des commandes qui modifient le contexte + comme DETRUIRE ou les macros + """ + # L'étape courante pour laquelle le contexte a été calculé est + # mémorisée dans self.index_etape_courante + # message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)]) + # message.debug(SUPERV, "current_context : %s", [k for k, v in + # self.current_context.items() if isinstance(v, ASSD)]) + d = self.current_context = self.g_context.copy() + if etape is None: + return d + # retirer les sd produites par 'etape' + sd_names = [sd.nom for sd in etape.get_created_sd()] + # message.debug(SUPERV, "etape: %s, reuse : %s, sdprods de %s : %s", + # self.nom, etape.reuse, etape.nom, sd_names) + for nom in sd_names: + try: + del d[nom] + except KeyError: + pass + # Exemple avec INCLUDE_MATERIAU appelé dans une macro. + # Les fonctions restent uniquement dans le contexte de INCLUDE_MATERIAU, + # elles ne sont donc pas dans le contexte de la macro appelante. + # from warnings import warn + # warn("concept '%s' absent du contexte de %s" % (nom, self.nom), + # RuntimeWarning, stacklevel=2) + return d + + def supprime(self): + """ + Méthode qui supprime toutes les références arrières afin que + l'objet puisse etre correctement détruit par le garbage collector + """ + N_MCCOMPO.MCCOMPO.supprime(self) + self.jdc = None + self.appel = None + if self.sd: + self.sd.supprime() + for concept in self.sdprods: + concept.supprime() + for etape in self.etapes: + etape.supprime() + + def clean(self, netapes): + """Nettoie les `netapes` dernières étapes de la liste des étapes.""" + if self.jdc.hist_etape: + return + for i in xrange(netapes): + e = self.etapes.pop() + jdc = e.jdc + parent = e.parent + e.supprime() + e.parent = parent + e.jdc = jdc + # message.debug(SUPERV, "MACRO.clean - etape = %s - refcount(e) = %d", + # e.nom, sys.getrefcount(e)) + del self.index_etapes[e] + + def type_sdprod(self, co, t): + """ + Cette methode a pour fonction de typer le concept co avec le type t + dans les conditions suivantes : + 1. co est un concept produit de self + 2. co est un concept libre : on le type et on l attribue à self + + Elle enregistre egalement les concepts produits (on fait l hypothese + que la liste sdprods a été correctement initialisee, vide probablement) + """ + if not hasattr(co, 'etape'): + # Le concept vaut None probablement. On ignore l'appel + return + # + # On cherche a discriminer les differents cas de typage d'un concept + # produit par une macro qui est specifie dans un mot cle simple. + # On peut passer plusieurs fois par type_sdprod ce qui explique + # le nombre important de cas. + # + # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom) + # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod. + # Cas semblable a Cas 1. + # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere + # la propriete du concept de la macro parent a la macro courante (self) + # en verifiant que le type est valide + # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est + # deja passe par type_sdprod et que la propriete a ete transfere a une + # etape fille. Cas semblable a Cas 3. + # Cas 5 : Le concept est produit par une etape externe a la macro. + # + if co.etape == None: + # Cas 1 : le concept est libre + # On l'attache a la macro et on change son type dans le type demande + # Recherche du mot cle simple associe au concept + mcs = self.get_mcs_with_co(co) + if len(mcs) != 1: + raise AsException("""Erreur interne. Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co) - mcs=mcs[0] - if not self.typeCO in mcs.definition.type: - raise AsException("""Erreur interne. -Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type)) - co.etape = self - # affectation du bon type du concept - #message.debug(SUPERV, "MACRO.type_sdprod : changement de type de %s --> %s", co, t) - co.change_type(t) - self.sdprods.append(co) - - elif co.etape == self: - # Cas 2 : le concept est produit par la macro (self) - # On est deja passe par type_sdprod (Cas 1 ou 3). - #XXX Peut-il être créer par une autre macro ? - # On vérifie juste que c'est un vrai CO non déjà typé - #if co.etape == co._etape: - if co.is_typco() == 1: - #Le concept a été créé par la macro (self) - #On peut changer son type - co.change_type(t) - else: - #Le concept a été créé par une macro parente - # Le type du concept doit etre coherent avec le type demande (seulement derive) - if not isinstance(co,t): - raise AsException("""Erreur interne. -Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__)) - - self.sdprods.append(co) - - elif co.etape== self.parent: - # Cas 3 : le concept est produit par la macro parente (self.parent) - # on transfere la propriete du concept a la macro fille - # et on change le type du concept comme demande - # Au prealable, on verifie que le concept existant (co) est une instance - # possible du type demande (t) - # Cette règle est normalement cohérente avec les règles de vérification des mots-clés - if not isinstance(co,t): - raise AsException(""" + mcs = mcs[0] + if not self.typeCO in mcs.definition.type: + raise AsException("""Erreur interne. +Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type)) + co.etape = self + # affectation du bon type du concept + # message.debug(SUPERV, "MACRO.type_sdprod : changement de type de + # %s --> %s", co, t) + co.change_type(t) + self.sdprods.append(co) + + elif co.etape == self: + # Cas 2 : le concept est produit par la macro (self) + # On est deja passe par type_sdprod (Cas 1 ou 3). + # XXX Peut-il être créer par une autre macro ? + # On vérifie juste que c'est un vrai CO non déjà typé + # if co.etape == co._etape: + if co.is_typco() == 1: + # Le concept a été créé par la macro (self) + # On peut changer son type + co.change_type(t) + else: + # Le concept a été créé par une macro parente + # Le type du concept doit etre coherent avec le type demande + # (seulement derive) + if not isinstance(co, t): + raise AsException("""Erreur interne. +Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__)) + + self.sdprods.append(co) + + elif co.etape == self.parent: + # Cas 3 : le concept est produit par la macro parente (self.parent) + # on transfere la propriete du concept a la macro fille + # et on change le type du concept comme demande + # Au prealable, on verifie que le concept existant (co) est une instance + # possible du type demande (t) + # Cette règle est normalement cohérente avec les règles de + # vérification des mots-clés + if not isinstance(co, t): + raise AsException(""" Impossible de changer le type du concept produit (%s) en (%s). -Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t)) - mcs=self.get_mcs_with_co(co) - if len(mcs) != 1: - raise AsException("""Erreur interne. +Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co, t, co.__class__, t)) + mcs = self.get_mcs_with_co(co) + if len(mcs) != 1: + raise AsException("""Erreur interne. Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co) - mcs=mcs[0] - if not self.typeCO in mcs.definition.type: - raise AsException("""Erreur interne. -Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type)) - co.etape=self - # On ne change pas le type car il respecte la condition isinstance(co,t) - #co.__class__ = t - self.sdprods.append(co) - - elif self.issubstep(co.etape): - # Cas 4 : Le concept est propriété d'une sous etape de la macro (self). - # On est deja passe par type_sdprod (Cas 3 ou 1). - # Il suffit de le mettre dans la liste des concepts produits (self.sdprods) - # Le type du concept et t doivent etre derives. - # Il n'y a aucune raison pour que la condition ne soit pas verifiee. - if not isinstance(co,t): - raise AsException("""Erreur interne. -Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__)) - self.sdprods.append(co) - - else: - # Cas 5 : le concept est produit par une autre étape - # On ne fait rien - return - - def issubstep(self,etape): - """ - Cette methode retourne un entier indiquant si etape est une - sous etape de la macro self ou non - 1 = oui - 0 = non - """ - if etape in self.etapes:return 1 - for etap in self.etapes: - if etap.issubstep(etape):return 1 - return 0 - - def register(self,etape): - """ - Enregistrement de etape dans le contexte de la macro : liste etapes - et demande d enregistrement global aupres du JDC - """ - self.etapes.append(etape) - self.index_etapes[etape] = len(self.etapes) - 1 - idetape=self.jdc.g_register(etape) - return idetape - - def reg_sd(self,sd): - """ - Methode appelee dans l __init__ d un ASSD a sa creation pour - s enregistrer (reserve aux ASSD créés au sein d'une MACRO) - """ - return self.jdc.o_register(sd) - - def create_sdprod(self,etape,nomsd): - """ - Cette methode doit fabriquer le concept produit retourne - par l'etape etape et le nommer. - - Elle est appelée à l'initiative de l'etape - pendant le processus de construction de cette etape : methode __call__ - de la classe CMD (OPER ou MACRO) - Ce travail est réalisé par le contexte supérieur (etape.parent) - car dans certains cas, le concept ne doit pas etre fabriqué mais - l'etape doit simplement utiliser un concept préexistant. - - Cas 1 : etape.reuse != None : le concept est réutilisé - - Cas 2 : l'étape appartient à une macro qui a déclaré un concept - de sortie qui doit etre produit par cette etape. - """ - if self.Outputs.has_key(nomsd): - # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le créer - # Il faut quand meme appeler la fonction sd_prod si elle existe. - # get_type_produit le fait et donne le type attendu par la commande pour verification ultérieure. - sdprod=etape.get_type_produit_brut() - sd=self.Outputs[nomsd] - # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu - # Cette règle est normalement cohérente avec les règles de vérification des mots-clés - if not issubclass(sdprod,sd.__class__): - raise AsException("Le type du concept produit %s devrait etre une sur classe de %s" %(sd.__class__,sdprod)) - # La propriete du concept est transferee a l'etape avec le type attendu par l'étape - etape.sd=sd - sd.etape=etape - if self.reuse == sd and etape.reuse != sd \ - and getattr(sd, "executed", 0) == 1: # n'a pas été pas détruit - raise AsException("Le concept '%s' est réentrant dans la macro-commande %s. " \ - "Il devrait donc l'être dans %s (produit sous le nom '%s')." \ - % (sd.nom, self.nom, etape.nom, nomsd)) - # On donne au concept le type produit par la sous commande. - # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande - # est bien coherent avec celui initialement affecte par la macro (voir ci dessus) - # on affecte au concept ce type car il peut etre plus precis (derive, en general) - sd.__class__=sdprod - # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom - # du concept associé à nomsd - etape.sdnom=sd.nom - # pour l'ajouter au contexte de la macro - self.g_context[sd.nom] = sd - elif etape.definition.reentrant != 'n' and etape.reuse != None: - # On est dans le cas d'une commande avec reutilisation d'un concept existant - # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree - # pas un nouveau concept. Il retourne le concept reutilise - sd= etape.get_sd_prod() - # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx, - # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom - # du concept reutilise (sd ou etape.reuse c'est pareil) - # Ceci est indispensable pour eviter des erreurs lors des verifications des macros - # En effet une commande avec reutilisation d'un concept verifie que le nom de - # la variable a gauche du signe = est le meme que celui du concept reutilise. - # Lorsqu'une telle commande apparait dans une macro, on supprime cette verification. - if (etape.sdnom == '' or etape.sdnom[0] == '_'): - etape.sdnom=sd.nom - else: - # On est dans le cas de la creation d'un nouveau concept - sd= etape.get_sd_prod() - if sd != None : - self.NommerSdprod(sd,nomsd) - return sd - - def NommerSdprod(self,sd,sdnom,restrict='non'): - """ - Cette méthode est appelée par les etapes internes de la macro. + mcs = mcs[0] + if not self.typeCO in mcs.definition.type: + raise AsException("""Erreur interne. +Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type)) + co.etape = self + # On ne change pas le type car il respecte la condition isinstance(co,t) + # co.__class__ = t + self.sdprods.append(co) + + elif self.issubstep(co.etape): + # Cas 4 : Le concept est propriété d'une sous etape de la macro (self). + # On est deja passe par type_sdprod (Cas 3 ou 1). + # Il suffit de le mettre dans la liste des concepts produits (self.sdprods) + # Le type du concept et t doivent etre derives. + # Il n'y a aucune raison pour que la condition ne soit pas + # verifiee. + if not isinstance(co, t): + raise AsException("""Erreur interne. +Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__)) + self.sdprods.append(co) + + else: + # Cas 5 : le concept est produit par une autre étape + # On ne fait rien + return + + def issubstep(self, etape): + """ + Cette methode retourne un entier indiquant si etape est une + sous etape de la macro self ou non + 1 = oui + 0 = non + """ + if etape in self.etapes: + return 1 + for etap in self.etapes: + if etap.issubstep(etape): + return 1 + return 0 + + def register(self, etape): + """ + Enregistrement de etape dans le contexte de la macro : liste etapes + et demande d enregistrement global aupres du JDC + """ + self.etapes.append(etape) + self.index_etapes[etape] = len(self.etapes) - 1 + idetape = self.jdc.g_register(etape) + return idetape + + def reg_sd(self, sd): + """ + Methode appelee dans l __init__ d un ASSD a sa creation pour + s enregistrer (reserve aux ASSD créés au sein d'une MACRO) + """ + return self.jdc.o_register(sd) + + def create_sdprod(self, etape, nomsd): + """ + Cette methode doit fabriquer le concept produit retourne + par l'etape etape et le nommer. + + Elle est appelée à l'initiative de l'etape + pendant le processus de construction de cette etape : methode __call__ + de la classe CMD (OPER ou MACRO) + Ce travail est réalisé par le contexte supérieur (etape.parent) + car dans certains cas, le concept ne doit pas etre fabriqué mais + l'etape doit simplement utiliser un concept préexistant. + - Cas 1 : etape.reuse != None : le concept est réutilisé + - Cas 2 : l'étape appartient à une macro qui a déclaré un concept + de sortie qui doit etre produit par cette etape. + """ + if self.Outputs.has_key(nomsd): + # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le créer + # Il faut quand meme appeler la fonction sd_prod si elle existe. + # get_type_produit le fait et donne le type attendu par la commande + # pour verification ultérieure. + sdprod = etape.get_type_produit_brut() + sd = self.Outputs[nomsd] + # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu + # Cette règle est normalement cohérente avec les règles de + # vérification des mots-clés + if not issubclass(sdprod, sd.__class__): + raise AsException( + "Le type du concept produit %s devrait etre une sur classe de %s" % (sd.__class__, sdprod)) + # La propriete du concept est transferee a l'etape avec le type + # attendu par l'étape + etape.sd = sd + sd.etape = etape + if self.reuse == sd and etape.reuse != sd \ + and getattr(sd, "executed", 0) == 1: # n'a pas été pas détruit + raise AsException("Le concept '%s' est réentrant dans la macro-commande %s. " + "Il devrait donc l'être dans %s (produit sous le nom '%s')." + % (sd.nom, self.nom, etape.nom, nomsd)) + # On donne au concept le type produit par la sous commande. + # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande + # est bien coherent avec celui initialement affecte par la macro (voir ci dessus) + # on affecte au concept ce type car il peut etre plus precis + # (derive, en general) + sd.__class__ = sdprod + # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom + # du concept associé à nomsd + etape.sdnom = sd.nom + # pour l'ajouter au contexte de la macro + self.g_context[sd.nom] = sd + elif etape.definition.reentrant != 'n' and etape.reuse != None: + # On est dans le cas d'une commande avec reutilisation d'un concept existant + # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree + # pas un nouveau concept. Il retourne le concept reutilise + sd = etape.get_sd_prod() + # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx, + # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom + # du concept reutilise (sd ou etape.reuse c'est pareil) + # Ceci est indispensable pour eviter des erreurs lors des verifications des macros + # En effet une commande avec reutilisation d'un concept verifie que le nom de + # la variable a gauche du signe = est le meme que celui du concept reutilise. + # Lorsqu'une telle commande apparait dans une macro, on supprime + # cette verification. + if (etape.sdnom == '' or etape.sdnom[0] == '_'): + etape.sdnom = sd.nom + else: + # On est dans le cas de la creation d'un nouveau concept + sd = etape.get_sd_prod() + if sd != None: + self.NommerSdprod(sd, nomsd) + return sd + + def NommerSdprod(self, sd, sdnom, restrict='non'): + """ + Cette méthode est appelée par les etapes internes de la macro. La macro appelle le JDC pour valider le nommage. - On considère que l'espace de nom est unique et géré par le JDC. - Si le nom est déjà utilisé, l'appel lève une exception. - Si restrict=='non', on insère le concept dans le contexte du parent de la macro. - Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro. + On considère que l'espace de nom est unique et géré par le JDC. + Si le nom est déjà utilisé, l'appel lève une exception. + Si restrict=='non', on insère le concept dans le contexte du parent de la macro. + Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro. """ # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees. # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode # create_sdprod. La seule chose a verifier apres conversion eventuelle du nom # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant # au JDC par l'intermediaire du parent. - #message.debug(SUPERV, "macro results = %s, (sdnom: %r, restrict: %r)", - #self.Outputs.keys(), sdnom, restrict) + # message.debug(SUPERV, "macro results = %s, (sdnom: %r, restrict: %r)", + # self.Outputs.keys(), sdnom, restrict) if self.Outputs.has_key(sdnom): - # Il s'agit d'un concept de sortie de la macro produit par une sous commande + # Il s'agit d'un concept de sortie de la macro produit par une + # sous commande sdnom = self.Outputs[sdnom].nom elif len(sdnom) > 0: if sdnom[0] in ('_', '.') and sdnom[1:].isdigit(): - # il est déjà de la forme _9000012 ou .9000017 + # il est déjà de la forme _9000012 ou .9000017 pass elif sdnom[0] == '_': - # Si le nom du concept commence par le caractère '_', on lui attribue + # Si le nom du concept commence par le caractère '_', on lui attribue # un identificateur JEVEUX construit par gcncon. - # nom commençant par __ : il s'agit de concepts qui seront détruits - # nom commençant par _ : il s'agit de concepts intermediaires qui seront gardés + # nom commençant par __ : il s'agit de concepts qui seront détruits + # nom commençant par _ : il s'agit de concepts intermediaires + # qui seront gardés if len(sdnom) > 1 and sdnom[1] == '_': sdnom = self.gcncon('.') else: @@ -522,223 +550,225 @@ Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co pass else: # On est dans le cas d'un nom de concept global - #XXX à voir, création de CO() dans CALC_ESSAI (sdls139a) + # XXX à voir, création de CO() dans CALC_ESSAI (sdls139a) if not sd.is_typco(): - raise AsException("Résultat non déclaré par la macro %s : %s" % (self.nom, sdnom)) + raise AsException( + "Résultat non déclaré par la macro %s : %s" % (self.nom, sdnom)) self.last = sdnom if restrict == 'non': # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent # car on va l'ajouter dans le contexte de la macro - self.parent.NommerSdprod(sd,sdnom,restrict='oui') + self.parent.NommerSdprod(sd, sdnom, restrict='oui') # On ajoute dans le contexte de la macro les concepts nommes # Ceci est indispensable pour les CO (macro) dans un INCLUDE - self.g_context[sdnom]=sd - #message.debug(SUPERV, "g_context[%s] = %s", sdnom, sd) + self.g_context[sdnom] = sd + # message.debug(SUPERV, "g_context[%s] = %s", sdnom, sd) else: # La demande de nommage vient probablement d'une macro qui a mis # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui") - #message.debug(SUPERV, "restrict=oui co[%s] = %s", sdnom, sd) - self.parent.NommerSdprod(sd,sdnom,restrict='oui') - - def delete_concept_after_etape(self,etape,sd): - """ - Met à jour les étapes de la MACRO qui sont après etape suite à - la disparition du concept sd - """ - # Cette methode est définie dans le noyau mais ne sert que pendant la phase de creation - # des etapes et des concepts. Il n'y a aucun traitement particulier à réaliser - # Dans d'autres conditions, il faudrait surcharger cette méthode. - return - - def get_created_sd(self): - """Retourne la liste des sd réellement produites par l'étape. - Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans - cette liste.""" - sdprods = self.sdprods[:] - if not self.reuse and self.sd: - sdprods.append(self.sd) - return sdprods - - def get_last_concept(self): - """Retourne le dernier concept produit dans la macro. - Peut-être utile pour accéder au contenu 'fortran' dans une - clause 'except'.""" - return self.g_context.get(self.last, None) - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitMACRO_ETAPE(self) - - def update_context(self,d): - """ - Met à jour le contexte contenu dans le dictionnaire d - Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte - Une fonction enregistree dans op_init peut egalement modifier le contexte - """ - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,d)) - if self.sd != None:d[self.sd.nom]=self.sd - for co in self.sdprods: - d[co.nom]=co - - def make_include(self, unite=None, fname=None): - """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`""" - if unite is not None: - warn("'unite' is deprecated, please use 'fname' instead", - DeprecationWarning, stacklevel=2) - fname = 'fort.%s' % unite - if not fname: - return - f, text = self.get_file(fic_origine=self.parent.nom, fname=fname) - self.fichier_init = f - if f == None: - return - self.make_contexte(f, text) - - def make_poursuite(self): - """Inclut un fichier poursuite""" - raise NotImplementedError('this method must be derivated (in Eficas)') - - def make_contexte(self,f,text): - """ - Interprete le texte fourni (text) issu du fichier f - dans le contexte du parent. - Cette methode est utile pour le fonctionnement des - INCLUDE - """ - # on execute le texte fourni dans le contexte forme par - # le contexte de l etape pere (global au sens Python) - # et le contexte de l etape (local au sens Python) - code = compile(text,f,'exec') - d = self.g_context = self.macro_const_context - globs = self.get_global_contexte() - d.update(globs) - exec code in globs, d - # pour ne pas conserver des références sur tout - self.macro_const_context = {} - - def get_global_contexte(self): - """ - Cette methode retourne le contexte global fourni - par le parent(self) a une etape fille (l'appelant) pour - realiser des evaluations de texte Python (INCLUDE,...) - """ - # Le contexte global est forme par concatenation du contexte - # du parent de self et de celui de l'etape elle meme (self) - # Pour les concepts, cela ne doit rien changer. Mais pour les constantes, - # les valeurs de get_contexte_avant sont moins récentes que dans - # get_global_contexte. On prend donc la précaution de ne pas écraser - # ce qui y est déjà. - d = self.parent.get_global_contexte() - d.update( self.g_context ) - d.update( [(k, v) for k, v in self.parent.get_contexte_avant(self).items() - if d.get(k) is None] ) - return d - - def get_contexte_courant(self, etape_fille_du_jdc=None): - """ - Retourne le contexte tel qu'il est au moment de l'exécution de - l'étape courante. - """ - ctx = {} - # update car par ricochet on modifierait jdc.current_context - ctx.update( self.parent.get_contexte_courant(self) ) - # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière - ctx.update( self.get_contexte_avant(None) ) - return ctx - - def get_concept(self, nomsd): - """ - Méthode pour recuperer un concept à partir de son nom - dans le contexte du jdc connu avant l'exécution de la macro courante. - """ - # chercher dans self.get_contexte_avant, puis si non trouve - # self.parent.get_concept est peut-etre plus performant - co = self.get_contexte_courant().get(nomsd.strip(), None) - if not isinstance(co, ASSD): - co = None - return co - - def get_concept_by_type(self, nomsd, typesd, etape=None): - """ - Méthode pour récuperer un concept à partir de son nom et de son type. - Il aura comme père 'etape' (ou la macro courante si etape est absente). - """ - return self.parent.get_concept_by_type(nomsd, typesd, etape=etape or self) - - def copy(self): - """ Méthode qui retourne une copie de self non enregistrée auprès du JDC - et sans sd - On surcharge la methode de ETAPE pour exprimer que les concepts crees - par la MACRO d'origine ne sont pas crees par la copie mais eventuellement - seulement utilises - """ - etape=N_ETAPE.ETAPE.copy(self) - etape.sdprods=[] - return etape - - def copy_intern(self,etape): - """ Cette méthode effectue la recopie des etapes internes d'une macro - passée en argument (etape) - """ - self.etapes=[] - self.index_etapes={} - for etp in etape.etapes: - new_etp=etp.copy() - new_etp.copy_reuse(etp) - new_etp.copy_sdnom(etp) - new_etp.reparent(self) - if etp.sd: - new_sd = etp.sd.__class__(etape=new_etp) - new_etp.sd = new_sd - if etp.reuse: - new_sd.set_name(etp.sd.nom) - else: - self.NommerSdprod(new_sd,etp.sd.nom) - new_etp.copy_intern(etp) - self.etapes.append(new_etp) - self.index_etapes[new_etp] = len(self.etapes) - 1 - - - def reset_jdc(self,new_jdc): - """ - Reinitialise l'etape avec un nouveau jdc parent new_jdc - """ - if self.sd and self.reuse == None : - self.parent.NommerSdprod(self.sd,self.sd.nom) - for concept in self.sdprods: - self.parent.NommerSdprod(concept,concept.nom) - - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - N_ETAPE.ETAPE.reparent(self,parent) - #on ne change pas la parenté des concepts. On s'assure uniquement que le jdc en référence est le bon - for concept in self.sdprods: - concept.jdc=self.jdc - for e in self.etapes: - e.reparent(self) - - def update_const_context(self, d): - """ - Met à jour le contexte des constantes pour l'évaluation de - formules dans la macro. - """ - # Dans le jdc, const_context est mis à jour par exec_compile - # Dans la macro, on n'a pas le code à compiler pour récupèrer les - # constantes locales à la macro. On demande donc explicitement de - # définir les constantes "locales". - self.macro_const_context.update(d) - - def sd_accessible(self): - """On peut acceder aux "valeurs" (jeveux) des ASSD dans - les macro-commandes qui sont localement en PAR_LOT="NON" - sauf pour INCLUDE. - """ - if CONTEXT.debug: print ' `- MACRO sd_accessible :', self.nom - return self.parent.sd_accessible() or not self.is_include() + # message.debug(SUPERV, "restrict=oui co[%s] = %s", sdnom, sd) + self.parent.NommerSdprod(sd, sdnom, restrict='oui') + + def delete_concept_after_etape(self, etape, sd): + """ + Met à jour les étapes de la MACRO qui sont après etape suite à + la disparition du concept sd + """ + # Cette methode est définie dans le noyau mais ne sert que pendant la phase de creation + # des etapes et des concepts. Il n'y a aucun traitement particulier à réaliser + # Dans d'autres conditions, il faudrait surcharger cette méthode. + return + + def get_created_sd(self): + """Retourne la liste des sd réellement produites par l'étape. + Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans + cette liste.""" + sdprods = self.sdprods[:] + if not self.reuse and self.sd: + sdprods.append(self.sd) + return sdprods + + def get_last_concept(self): + """Retourne le dernier concept produit dans la macro. + Peut-être utile pour accéder au contenu 'fortran' dans une + clause 'except'.""" + return self.g_context.get(self.last, None) + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitMACRO_ETAPE(self) + + def update_context(self, d): + """ + Met à jour le contexte contenu dans le dictionnaire d + Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte + Une fonction enregistree dans op_init peut egalement modifier le contexte + """ + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init, (self, d)) + if self.sd != None: + d[self.sd.nom] = self.sd + for co in self.sdprods: + d[co.nom] = co + + def make_include(self, unite=None, fname=None): + """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`""" + if unite is not None: + warn("'unite' is deprecated, please use 'fname' instead", + DeprecationWarning, stacklevel=2) + fname = 'fort.%s' % unite + if not fname: + return + f, text = self.get_file(fic_origine=self.parent.nom, fname=fname) + self.fichier_init = f + if f == None: + return + self.make_contexte(f, text) + + def make_poursuite(self): + """Inclut un fichier poursuite""" + raise NotImplementedError('this method must be derivated (in Eficas)') + + def make_contexte(self, f, text): + """ + Interprete le texte fourni (text) issu du fichier f + dans le contexte du parent. + Cette methode est utile pour le fonctionnement des + INCLUDE + """ + # on execute le texte fourni dans le contexte forme par + # le contexte de l etape pere (global au sens Python) + # et le contexte de l etape (local au sens Python) + code = compile(text, f, 'exec') + d = self.g_context = self.macro_const_context + globs = self.get_global_contexte() + d.update(globs) + exec code in globs, d + # pour ne pas conserver des références sur tout + self.macro_const_context = {} + + def get_global_contexte(self): + """ + Cette methode retourne le contexte global fourni + par le parent(self) a une etape fille (l'appelant) pour + realiser des evaluations de texte Python (INCLUDE,...) + """ + # Le contexte global est forme par concatenation du contexte + # du parent de self et de celui de l'etape elle meme (self) + # Pour les concepts, cela ne doit rien changer. Mais pour les constantes, + # les valeurs de get_contexte_avant sont moins récentes que dans + # get_global_contexte. On prend donc la précaution de ne pas écraser + # ce qui y est déjà. + d = self.parent.get_global_contexte() + d.update(self.g_context) + d.update([(k, v) for k, v in self.parent.get_contexte_avant(self).items() + if d.get(k) is None]) + return d + + def get_contexte_courant(self, etape_fille_du_jdc=None): + """ + Retourne le contexte tel qu'il est au moment de l'exécution de + l'étape courante. + """ + ctx = {} + # update car par ricochet on modifierait jdc.current_context + ctx.update(self.parent.get_contexte_courant(self)) + # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière + ctx.update(self.get_contexte_avant(None)) + return ctx + + def get_concept(self, nomsd): + """ + Méthode pour recuperer un concept à partir de son nom + dans le contexte du jdc connu avant l'exécution de la macro courante. + """ + # chercher dans self.get_contexte_avant, puis si non trouve + # self.parent.get_concept est peut-etre plus performant + co = self.get_contexte_courant().get(nomsd.strip(), None) + if not isinstance(co, ASSD): + co = None + return co + + def get_concept_by_type(self, nomsd, typesd, etape=None): + """ + Méthode pour récuperer un concept à partir de son nom et de son type. + Il aura comme père 'etape' (ou la macro courante si etape est absente). + """ + return self.parent.get_concept_by_type(nomsd, typesd, etape=etape or self) + + def copy(self): + """ Méthode qui retourne une copie de self non enregistrée auprès du JDC + et sans sd + On surcharge la methode de ETAPE pour exprimer que les concepts crees + par la MACRO d'origine ne sont pas crees par la copie mais eventuellement + seulement utilises + """ + etape = N_ETAPE.ETAPE.copy(self) + etape.sdprods = [] + return etape + def copy_intern(self, etape): + """ Cette méthode effectue la recopie des etapes internes d'une macro + passée en argument (etape) + """ + self.etapes = [] + self.index_etapes = {} + for etp in etape.etapes: + new_etp = etp.copy() + new_etp.copy_reuse(etp) + new_etp.copy_sdnom(etp) + new_etp.reparent(self) + if etp.sd: + new_sd = etp.sd.__class__(etape=new_etp) + new_etp.sd = new_sd + if etp.reuse: + new_sd.set_name(etp.sd.nom) + else: + self.NommerSdprod(new_sd, etp.sd.nom) + new_etp.copy_intern(etp) + self.etapes.append(new_etp) + self.index_etapes[new_etp] = len(self.etapes) - 1 + + def reset_jdc(self, new_jdc): + """ + Reinitialise l'etape avec un nouveau jdc parent new_jdc + """ + if self.sd and self.reuse == None: + self.parent.NommerSdprod(self.sd, self.sd.nom) + for concept in self.sdprods: + self.parent.NommerSdprod(concept, concept.nom) + + def reparent(self, parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + N_ETAPE.ETAPE.reparent(self, parent) + # on ne change pas la parenté des concepts. On s'assure uniquement que + # le jdc en référence est le bon + for concept in self.sdprods: + concept.jdc = self.jdc + for e in self.etapes: + e.reparent(self) + + def update_const_context(self, d): + """ + Met à jour le contexte des constantes pour l'évaluation de + formules dans la macro. + """ + # Dans le jdc, const_context est mis à jour par exec_compile + # Dans la macro, on n'a pas le code à compiler pour récupèrer les + # constantes locales à la macro. On demande donc explicitement de + # définir les constantes "locales". + self.macro_const_context.update(d) + + def sd_accessible(self): + """On peut acceder aux "valeurs" (jeveux) des ASSD dans + les macro-commandes qui sont localement en PAR_LOT="NON" + sauf pour INCLUDE. + """ + if CONTEXT.debug: + print ' `- MACRO sd_accessible :', self.nom + return self.parent.sd_accessible() or not self.is_include() diff --git a/Noyau/N_MCBLOC.py b/Noyau/N_MCBLOC.py index a0f5a9f7..020b1593 100644 --- a/Noyau/N_MCBLOC.py +++ b/Noyau/N_MCBLOC.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,11 +16,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" - Ce module contient la classe MCBLOC qui sert à controler la valeur - d'un bloc de mots-clés par rapport à sa définition portée par un objet + +""" + Ce module contient la classe MCBLOC qui sert à controler la valeur + d'un bloc de mots-clés par rapport à sa définition portée par un objet de type ENTITE """ @@ -28,103 +28,106 @@ import types import N_MCCOMPO + class MCBLOC(N_MCCOMPO.MCCOMPO): - """ - Classe support d'un bloc de mots-clés. - - """ - - nature = "MCBLOC" - def __init__(self,val,definition,nom,parent): - """ - Attributs : - - - val : valeur du bloc (dictionnaire dont les clés sont des noms de mots-clés et les valeurs - les valeurs des mots-clés) - - - definition : objet de définition de type BLOC associé au bloc (porte les attributs de définition) - - - nom : nom du bloc. Ce nom lui est donné par celui qui crée le bloc de mot-clé - - - parent : le créateur du bloc. Ce peut etre un mot-clé facteur ou un autre objet composite de type - OBJECT. Si parent vaut None, le bloc ne possède pas de contexte englobant. - - - mc_liste : liste des sous-objets du bloc construite par appel à la méthode build_mc - - """ - self.definition=definition - self.nom=nom - self.val = val - self.parent = parent - self.valeur = val - if parent : - self.jdc = self.parent.jdc - self.niveau = self.parent.niveau - self.etape = self.parent.etape - else: - # Le mot cle a été créé sans parent - self.jdc = None - self.niveau = None - self.etape = None - self.mc_liste=self.build_mc() - - def get_valeur(self): - """ - Retourne la "valeur" de l'objet bloc. Il s'agit d'un dictionnaire dont - les clés seront les noms des objets de self.mc_liste et les valeurs - les valeurs des objets de self.mc_liste obtenues par application de - la méthode get_valeur. - - Dans le cas particulier d'un objet bloc les éléments du dictionnaire - obtenu par appel de la méthode get_valeur sont intégrés au niveau - supérieur. - - """ - dico={} - for mocle in self.mc_liste: - if mocle.isBLOC(): - # Si mocle est un BLOC, on inclut ses items dans le dictionnaire - # représentatif de la valeur de self. Les mots-clés fils de blocs sont - # donc remontés au niveau supérieur. - dico.update(mocle.get_valeur()) + + """ + Classe support d'un bloc de mots-clés. + + """ + + nature = "MCBLOC" + + def __init__(self, val, definition, nom, parent): + """ + Attributs : + + - val : valeur du bloc (dictionnaire dont les clés sont des noms de mots-clés et les valeurs + les valeurs des mots-clés) + + - definition : objet de définition de type BLOC associé au bloc (porte les attributs de définition) + + - nom : nom du bloc. Ce nom lui est donné par celui qui crée le bloc de mot-clé + + - parent : le créateur du bloc. Ce peut etre un mot-clé facteur ou un autre objet composite de type + OBJECT. Si parent vaut None, le bloc ne possède pas de contexte englobant. + + - mc_liste : liste des sous-objets du bloc construite par appel à la méthode build_mc + + """ + self.definition = definition + self.nom = nom + self.val = val + self.parent = parent + self.valeur = val + if parent: + self.jdc = self.parent.jdc + self.niveau = self.parent.niveau + self.etape = self.parent.etape else: - dico[mocle.nom]=mocle.get_valeur() - - # On rajoute tous les autres mots-clés locaux possibles avec la valeur - # par défaut ou None - # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d') - # et caché ('c') - # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement - # une condition. - for k,v in self.definition.entites.items(): - if not dico.has_key(k): - if v.label == 'SIMP': - # Mot clé simple - dico[k]=v.defaut - elif v.label == 'FACT': - if v.statut in ('c','d') : - # Mot clé facteur avec défaut ou caché provisoire - dico[k]=v(val=None,nom=k,parent=self) - # On demande la suppression des pointeurs arrieres - # pour briser les eventuels cycles - dico[k].supprime() - else: - dico[k]=None - - return dico - - def isBLOC(self): - """ - Indique si l'objet est un BLOC - """ - return 1 - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitMCBLOC(self) - - def makeobjet(self): - return self.definition(val = None, nom = self.nom,parent = self.parent) + # Le mot cle a été créé sans parent + self.jdc = None + self.niveau = None + self.etape = None + self.mc_liste = self.build_mc() + + def get_valeur(self): + """ + Retourne la "valeur" de l'objet bloc. Il s'agit d'un dictionnaire dont + les clés seront les noms des objets de self.mc_liste et les valeurs + les valeurs des objets de self.mc_liste obtenues par application de + la méthode get_valeur. + + Dans le cas particulier d'un objet bloc les éléments du dictionnaire + obtenu par appel de la méthode get_valeur sont intégrés au niveau + supérieur. + + """ + dico = {} + for mocle in self.mc_liste: + if mocle.isBLOC(): + # Si mocle est un BLOC, on inclut ses items dans le dictionnaire + # représentatif de la valeur de self. Les mots-clés fils de blocs sont + # donc remontés au niveau supérieur. + dico.update(mocle.get_valeur()) + else: + dico[mocle.nom] = mocle.get_valeur() + + # On rajoute tous les autres mots-clés locaux possibles avec la valeur + # par défaut ou None + # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d') + # et caché ('c') + # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement + # une condition. + for k, v in self.definition.entites.items(): + if not dico.has_key(k): + if v.label == 'SIMP': + # Mot clé simple + dico[k] = v.defaut + elif v.label == 'FACT': + if v.statut in ('c', 'd'): + # Mot clé facteur avec défaut ou caché provisoire + dico[k] = v(val=None, nom=k, parent=self) + # On demande la suppression des pointeurs arrieres + # pour briser les eventuels cycles + dico[k].supprime() + else: + dico[k] = None + + return dico + + def isBLOC(self): + """ + Indique si l'objet est un BLOC + """ + return 1 + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitMCBLOC(self) + + def makeobjet(self): + return self.definition(val=None, nom=self.nom, parent=self.parent) diff --git a/Noyau/N_MCCOMPO.py b/Noyau/N_MCCOMPO.py index 4580f6ff..dbc7f727 100644 --- a/Noyau/N_MCCOMPO.py +++ b/Noyau/N_MCCOMPO.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,423 +16,444 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ - Ce module contient la classe MCCOMPO qui sert à factoriser les comportements + Ce module contient la classe MCCOMPO qui sert à factoriser les comportements des OBJECT composites """ from copy import copy import N_OBJECT + class MCCOMPO(N_OBJECT.OBJECT): - """ - Classe support d'un OBJECT composite - - """ - - def build_mc(self): - """ - Construit la liste des sous-entites du MCCOMPO - à partir du dictionnaire des arguments (valeur) - """ - if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom - # Dans la phase de reconstruction args peut contenir des mots-clés - # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites) - # de l'objet courant (self) - # mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...) - args = self.valeur - if args == None : args ={} - mc_liste=[] - - # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k]) - args = args.copy() - - # Phase 1: - # On construit les sous entites presentes ou obligatoires - # 1- les entites présentes dans les arguments et dans la définition - # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut - # Phase 1.1 : on traite d'abord les SIMP pour enregistrer les mots cles globaux - for k,v in self.definition.entites.items(): - if v.label != 'SIMP':continue - if args.has_key(k) or v.statut=='o' : - # - # Creation par appel de la methode __call__ de la definition de la sous entite k de self - # si une valeur existe dans args ou est obligatoire (generique si toutes les - # entites ont l attribut statut ) - # - objet=v(val=args.get(k,None),nom=k,parent=self) - mc_liste.append(objet) - # Si l'objet a une position globale on l'ajoute aux listes correspondantes - if hasattr(objet.definition,'position'): - if objet.definition.position == 'global' : - self.append_mc_global(objet) - elif objet.definition.position == 'global_jdc' : - self.append_mc_global_jdc(objet) - if args.has_key(k): - del args[k] - - # Phase 1.2 : on traite les autres entites que SIMP - # (FACT en fait car un BLOC ne peut avoir le meme nom qu'un mot-clef) - for k,v in self.definition.entites.items(): - if v.label == 'SIMP':continue - if args.has_key(k) or v.statut=='o' : - # - # Creation par appel de la methode __call__ de la definition de la sous entite k de self - # si une valeur existe dans args ou est obligatoire (generique si toutes les - # entites ont l attribut statut ) - # - objet=v(val=args.get(k,None),nom=k,parent=self) - mc_liste.append(objet) - if args.has_key(k): - del args[k] - - # Phase 2: - # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés. - # A ce stade, mc_liste ne contient que les fils de l'objet courant - # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont - # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés - dico_valeurs = self.cree_dict_condition(mc_liste,condition=1) - for k,v in self.definition.entites.items(): - if v.label != 'BLOC':continue - # condition and a or b : Equivalent de l'expression : condition ? a : b du langage C - globs= self.jdc and self.jdc.condition_context or {} - if v.verif_presence(dico_valeurs,globs): - # Si le bloc existe : - # 1- on le construit - # 2- on l'ajoute à mc_liste - # 3- on récupère les arguments restant - # 4- on reconstruit le dictionnaire équivalent à mc_liste - bloc = v(nom=k,val=args,parent=self) - mc_liste.append(bloc) - args=bloc.reste_val - # On ne recalcule pas le contexte car on ne tient pas compte des blocs - # pour évaluer les conditions de présence des blocs - #dico_valeurs = self.cree_dict_valeurs(mc_liste) - - # On conserve les arguments superflus dans l'attribut reste_val - self.reste_val=args - # On ordonne la liste ainsi créée suivant l'ordre du catalogue - # (utile seulement pour IHM graphique) - mc_liste = self.ordonne_liste(mc_liste) - # on retourne la liste ainsi construite - return mc_liste - - def ordonne_liste(self,mc_liste): - """ - Ordonne la liste suivant l'ordre du catalogue. - Seulement pour IHM graphique - """ - if self.jdc and self.jdc.cata_ordonne_dico != None : - liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute( - self.get_genealogie(),self.jdc.cata_ordonne_dico) - return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee) - else: - return mc_liste - - def cree_dict_valeurs(self,liste=[],condition=0): - """ - Cette méthode crée un contexte (sous la forme d'un dictionnaire) - à partir des valeurs des mots clés contenus dans l'argument liste. - L'opération consiste à parcourir la liste (d'OBJECT) et à la - transformer en un dictionnaire dont les clés sont les noms des - mots clés et les valeurs dépendent du type d'OBJECT. - Ce dictionnaire servira de liste d'arguments d'appel pour les - fonctions sd_prod de commandes et ops de macros ou de contexte - d'évaluation des conditions de présence de BLOC. - - Si l'argument condition de la méthode vaut 1, on ne - remonte pas les valeurs des mots clés contenus dans des blocs - pour eviter les bouclages. - - Cette méthode réalise les opérations suivantes en plus de transformer - la liste en dictionnaire : - - - ajouter tous les mots-clés non présents avec la valeur None - - ajouter tous les mots-clés globaux (attribut position = 'global' - et 'global_jdc') - - L'argument liste est, en général, une mc_liste en cours de - construction, contenant les mots-clés locaux et les blocs déjà créés. - - """ - dico={} - for v in liste: - if v.isBLOC(): - # Si v est un BLOC, on inclut ses items dans le dictionnaire - # représentatif du contexte. Les blocs sont retournés par get_valeur - # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont - # donc remontés au niveau du contexte. - if not condition: - dadd = v.get_valeur() - assert intersection_vide(dico, dadd) - dico.update(dadd) + + """ + Classe support d'un OBJECT composite + + """ + + def build_mc(self): + """ + Construit la liste des sous-entites du MCCOMPO + à partir du dictionnaire des arguments (valeur) + """ + if CONTEXT.debug: + print "MCCOMPO.build_mc ", self.nom + # Dans la phase de reconstruction args peut contenir des mots-clés + # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites) + # de l'objet courant (self) + # mais qui sont malgré tout des descendants de l'objet courant + # (petits-fils, ...) + args = self.valeur + if args == None: + args = {} + mc_liste = [] + + # On recopie le dictionnaire des arguments pour protéger l'original des + # delete (del args[k]) + args = args.copy() + + # Phase 1: + # On construit les sous entites presentes ou obligatoires + # 1- les entites présentes dans les arguments et dans la définition + # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut + # Phase 1.1 : on traite d'abord les SIMP pour enregistrer les mots cles + # globaux + for k, v in self.definition.entites.items(): + if v.label != 'SIMP': + continue + if args.has_key(k) or v.statut == 'o': + # + # Creation par appel de la methode __call__ de la definition de la sous entite k de self + # si une valeur existe dans args ou est obligatoire (generique si toutes les + # entites ont l attribut statut ) + # + objet = v(val=args.get(k, None), nom=k, parent=self) + mc_liste.append(objet) + # Si l'objet a une position globale on l'ajoute aux listes + # correspondantes + if hasattr(objet.definition, 'position'): + if objet.definition.position == 'global': + self.append_mc_global(objet) + elif objet.definition.position == 'global_jdc': + self.append_mc_global_jdc(objet) + if args.has_key(k): + del args[k] + + # Phase 1.2 : on traite les autres entites que SIMP + # (FACT en fait car un BLOC ne peut avoir le meme nom qu'un mot-clef) + for k, v in self.definition.entites.items(): + if v.label == 'SIMP': + continue + if args.has_key(k) or v.statut == 'o': + # + # Creation par appel de la methode __call__ de la definition de la sous entite k de self + # si une valeur existe dans args ou est obligatoire (generique si toutes les + # entites ont l attribut statut ) + # + objet = v(val=args.get(k, None), nom=k, parent=self) + mc_liste.append(objet) + if args.has_key(k): + del args[k] + + # Phase 2: + # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés. + # A ce stade, mc_liste ne contient que les fils de l'objet courant + # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont + # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés + dico_valeurs = self.cree_dict_condition(mc_liste, condition=1) + for k, v in self.definition.entites.items(): + if v.label != 'BLOC': + continue + # condition and a or b : Equivalent de l'expression : condition ? + # a : b du langage C + globs = self.jdc and self.jdc.condition_context or {} + if v.verif_presence(dico_valeurs, globs): + # Si le bloc existe : + # 1- on le construit + # 2- on l'ajoute à mc_liste + # 3- on récupère les arguments restant + # 4- on reconstruit le dictionnaire équivalent à mc_liste + bloc = v(nom=k, val=args, parent=self) + mc_liste.append(bloc) + args = bloc.reste_val + # On ne recalcule pas le contexte car on ne tient pas compte des blocs + # pour évaluer les conditions de présence des blocs + # dico_valeurs = self.cree_dict_valeurs(mc_liste) + + # On conserve les arguments superflus dans l'attribut reste_val + self.reste_val = args + # On ordonne la liste ainsi créée suivant l'ordre du catalogue + # (utile seulement pour IHM graphique) + mc_liste = self.ordonne_liste(mc_liste) + # on retourne la liste ainsi construite + return mc_liste + + def ordonne_liste(self, mc_liste): + """ + Ordonne la liste suivant l'ordre du catalogue. + Seulement pour IHM graphique + """ + if self.jdc and self.jdc.cata_ordonne_dico != None: + liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute( + self.get_genealogie(), self.jdc.cata_ordonne_dico) + return self.ordonne_liste_mc(mc_liste, liste_noms_mc_ordonnee) else: - assert not dico.has_key(v.nom), "deja vu : %s" % v.nom - dico[v.nom]=v.get_valeur() - - # On rajoute tous les autres mots-clés locaux possibles avec la valeur - # par défaut ou None - # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d') - # et caché ('c') - # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement - # une condition. - #XXX remplacer le not has_key par un dico différent et faire dico2.update(dico) - # ce n'est qu'un pb de perf - for k,v in self.definition.entites.items(): - if not dico.has_key(k): - if v.label == 'SIMP': - # Mot clé simple - dico[k]=v.defaut - elif v.label == 'FACT' : - if v.statut in ('c','d') : - # Mot clé facteur avec défaut ou caché provisoire - dico[k]=v(val=None,nom=k,parent=self) - # On demande la suppression des pointeurs arrieres - # pour briser les eventuels cycles - dico[k].supprime() - else: - dico[k]=None - # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur - # valeur par défaut ou la valeur None - - # On rajoute les mots-clés globaux sans écraser les clés existantes - dico_mc = self.recherche_mc_globaux() - dico_mc.update(dico) - dico=dico_mc - - return dico - - def cree_dict_toutes_valeurs(self): - """Semblable à `cree_dict_valeurs(liste=self.mc_liste)` en supprimant les - valeurs None.""" - dico = self.cree_dict_valeurs(self.mc_liste, condition=0) - dico = dict([(k, v) for k, v in dico.items() if v is not None]) - return dico - - def cree_dict_condition(self,liste=[],condition=0): - """ - Methode pour construire un contexte qui servira dans l'évaluation - des conditions de présence de blocs. Si une commande a un concept - produit réutilisé, on ajoute la clé 'reuse' - """ - dico=self.cree_dict_valeurs(liste,condition=1) - # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination - # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée - if not dico.has_key('reuse') and hasattr(self,'reuse'): - dico['reuse']=self.reuse - return dico - - def recherche_mc_globaux(self): - """ - Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self - et des mots-clés globaux du jdc - """ - etape = self.get_etape() - if etape : - dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs() - for k,v in etape.mc_globaux.items(): - dict_mc_globaux_fac[k]=v.get_valeur() - if self.jdc : - for k,v in self.jdc.mc_globaux.items(): - dict_mc_globaux_fac[k]=v.get_valeur() - return dict_mc_globaux_fac - else : - return {} - - def recherche_mc_globaux_facultatifs(self): - """ - Cette méthode interroge la définition de self et retourne la liste des mots-clés fils - directs de self de type 'global'. - position='global' n'est donc possible (et n'a de sens) qu'au plus haut niveau. - """ - dico={} - etape = self.get_etape() - if not etape : return {} - for k,v in etape.definition.entites.items(): - if v.label != 'SIMP' : continue - if v.position != 'global' : continue - if v.statut == 'o':continue - obj = v(val=None,nom=k,parent=etape) - dico[k]=obj.get_valeur() - return dico - - def supprime(self): - """ - Méthode qui supprime toutes les références arrières afin que l'objet puisse - etre correctement détruit par le garbage collector - """ - N_OBJECT.OBJECT.supprime(self) - for child in self.mc_liste : - child.supprime() - - def __getitem__(self,key): - """ - Cette méthode retourne la valeur d'un sous mot-clé (key) - """ - return self.get_mocle(key) - - def get_mocle(self,key): - """ - Retourne la valeur du sous mot-clé key - Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre - dans un BLOC fils de self - """ - # on cherche dans les mots cles presents, le mot cle de nom key - # s'il est là on retourne sa valeur (méthode get_val) - for child in self.mc_liste: - if child.nom == key : return child.get_valeur() - # Si on n a pas trouve de mot cle present on retourne le defaut - # eventuel pour les mots cles accessibles dans la definition - # a ce niveau - try: - d=self.definition.entites[key] - if d.label == 'SIMP': - return d.defaut - elif d.label == 'FACT': - # il faut construire les objets necessaires pour - # evaluer les conditions des blocs eventuels (a faire) - if d.statut == 'o' :return None - if d.statut != 'c' and d.statut != 'd' : - return None - else : - return d(val=None,nom=key,parent=self) - except KeyError: - # le mot cle n est pas defini a ce niveau - pass - # Si on a toujours rien trouve, on cherche dans les blocs presents - # On suppose que tous les blocs possibles ont ete crees meme ceux - # induits par un mot cle simple absent avec defaut (???) - for mc in self.mc_liste : - if not mc.isBLOC() : continue - try: - return mc.get_mocle(key) - except: - # On n a rien trouve dans ce bloc, on passe au suivant - pass - # On a rien trouve, le mot cle est absent. - # On leve une exception - raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self) - - def get_child(self,name,restreint = 'non'): - """ - Retourne le fils de self de nom name ou None s'il n'existe pas - Si restreint vaut oui : ne regarde que dans la mc_liste - Si restreint vaut non : regarde aussi dans les entites possibles - avec defaut (Ce dernier cas n'est utilisé que dans le catalogue) - """ - for v in self.mc_liste: - if v.nom == name : return v - if restreint == 'non' : + return mc_liste + + def cree_dict_valeurs(self, liste=[], condition=0): + """ + Cette méthode crée un contexte (sous la forme d'un dictionnaire) + à partir des valeurs des mots clés contenus dans l'argument liste. + L'opération consiste à parcourir la liste (d'OBJECT) et à la + transformer en un dictionnaire dont les clés sont les noms des + mots clés et les valeurs dépendent du type d'OBJECT. + Ce dictionnaire servira de liste d'arguments d'appel pour les + fonctions sd_prod de commandes et ops de macros ou de contexte + d'évaluation des conditions de présence de BLOC. + + Si l'argument condition de la méthode vaut 1, on ne + remonte pas les valeurs des mots clés contenus dans des blocs + pour eviter les bouclages. + + Cette méthode réalise les opérations suivantes en plus de transformer + la liste en dictionnaire : + + - ajouter tous les mots-clés non présents avec la valeur None + - ajouter tous les mots-clés globaux (attribut position = 'global' + et 'global_jdc') + + L'argument liste est, en général, une mc_liste en cours de + construction, contenant les mots-clés locaux et les blocs déjà créés. + + """ + dico = {} + for v in liste: + if v.isBLOC(): + # Si v est un BLOC, on inclut ses items dans le dictionnaire + # représentatif du contexte. Les blocs sont retournés par get_valeur + # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont + # donc remontés au niveau du contexte. + if not condition: + dadd = v.get_valeur() + assert intersection_vide(dico, dadd) + dico.update(dadd) + else: + assert not dico.has_key(v.nom), "deja vu : %s" % v.nom + dico[v.nom] = v.get_valeur() + + # On rajoute tous les autres mots-clés locaux possibles avec la valeur + # par défaut ou None + # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d') + # et caché ('c') + # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement + # une condition. + # XXX remplacer le not has_key par un dico différent et faire dico2.update(dico) + # ce n'est qu'un pb de perf + for k, v in self.definition.entites.items(): + if not dico.has_key(k): + if v.label == 'SIMP': + # Mot clé simple + dico[k] = v.defaut + elif v.label == 'FACT': + if v.statut in ('c', 'd'): + # Mot clé facteur avec défaut ou caché provisoire + dico[k] = v(val=None, nom=k, parent=self) + # On demande la suppression des pointeurs arrieres + # pour briser les eventuels cycles + dico[k].supprime() + else: + dico[k] = None + # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur + # valeur par défaut ou la valeur None + + # On rajoute les mots-clés globaux sans écraser les clés existantes + dico_mc = self.recherche_mc_globaux() + dico_mc.update(dico) + dico = dico_mc + + return dico + + def cree_dict_toutes_valeurs(self): + """Semblable à `cree_dict_valeurs(liste=self.mc_liste)` en supprimant les + valeurs None.""" + dico = self.cree_dict_valeurs(self.mc_liste, condition=0) + dico = dict([(k, v) for k, v in dico.items() if v is not None]) + return dico + + def cree_dict_condition(self, liste=[], condition=0): + """ + Methode pour construire un contexte qui servira dans l'évaluation + des conditions de présence de blocs. Si une commande a un concept + produit réutilisé, on ajoute la clé 'reuse' + """ + dico = self.cree_dict_valeurs(liste, condition=1) + # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination + # uniquement des commandes. Ne devrait pas etre dans cette classe mais + # dans une classe dérivée + if not dico.has_key('reuse') and hasattr(self, 'reuse'): + dico['reuse'] = self.reuse + return dico + + def recherche_mc_globaux(self): + """ + Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self + et des mots-clés globaux du jdc + """ + etape = self.get_etape() + if etape: + dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs() + for k, v in etape.mc_globaux.items(): + dict_mc_globaux_fac[k] = v.get_valeur() + if self.jdc: + for k, v in self.jdc.mc_globaux.items(): + dict_mc_globaux_fac[k] = v.get_valeur() + return dict_mc_globaux_fac + else: + return {} + + def recherche_mc_globaux_facultatifs(self): + """ + Cette méthode interroge la définition de self et retourne la liste des mots-clés fils + directs de self de type 'global'. + position='global' n'est donc possible (et n'a de sens) qu'au plus haut niveau. + """ + dico = {} + etape = self.get_etape() + if not etape: + return {} + for k, v in etape.definition.entites.items(): + if v.label != 'SIMP': + continue + if v.position != 'global': + continue + if v.statut == 'o': + continue + obj = v(val=None, nom=k, parent=etape) + dico[k] = obj.get_valeur() + return dico + + def supprime(self): + """ + Méthode qui supprime toutes les références arrières afin que l'objet puisse + etre correctement détruit par le garbage collector + """ + N_OBJECT.OBJECT.supprime(self) + for child in self.mc_liste: + child.supprime() + + def __getitem__(self, key): + """ + Cette méthode retourne la valeur d'un sous mot-clé (key) + """ + return self.get_mocle(key) + + def get_mocle(self, key): + """ + Retourne la valeur du sous mot-clé key + Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre + dans un BLOC fils de self + """ + # on cherche dans les mots cles presents, le mot cle de nom key + # s'il est là on retourne sa valeur (méthode get_val) + for child in self.mc_liste: + if child.nom == key: + return child.get_valeur() + # Si on n a pas trouve de mot cle present on retourne le defaut + # eventuel pour les mots cles accessibles dans la definition + # a ce niveau try: - entite=self.definition.entites[name] - if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')): - return entite(None,name,None) - except: - pass - - return None - - def append_mc_global(self,mc): - """ - Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape - """ - etape = self.get_etape() - if etape : + d = self.definition.entites[key] + if d.label == 'SIMP': + return d.defaut + elif d.label == 'FACT': + # il faut construire les objets necessaires pour + # evaluer les conditions des blocs eventuels (a faire) + if d.statut == 'o': + return None + if d.statut != 'c' and d.statut != 'd': + return None + else: + return d(val=None, nom=key, parent=self) + except KeyError: + # le mot cle n est pas defini a ce niveau + pass + # Si on a toujours rien trouve, on cherche dans les blocs presents + # On suppose que tous les blocs possibles ont ete crees meme ceux + # induits par un mot cle simple absent avec defaut (???) + for mc in self.mc_liste: + if not mc.isBLOC(): + continue + try: + return mc.get_mocle(key) + except: + # On n a rien trouve dans ce bloc, on passe au suivant + pass + # On a rien trouve, le mot cle est absent. + # On leve une exception + raise IndexError, "Le mot cle %s n existe pas dans %s" % (key, self) + + def get_child(self, name, restreint='non'): + """ + Retourne le fils de self de nom name ou None s'il n'existe pas + Si restreint vaut oui : ne regarde que dans la mc_liste + Si restreint vaut non : regarde aussi dans les entites possibles + avec defaut (Ce dernier cas n'est utilisé que dans le catalogue) + """ + for v in self.mc_liste: + if v.nom == name: + return v + if restreint == 'non': + try: + entite = self.definition.entites[name] + if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ('c', 'd')): + return entite(None, name, None) + except: + pass + + return None + + def append_mc_global(self, mc): + """ + Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape + """ + etape = self.get_etape() + if etape: + nom = mc.nom + etape.mc_globaux[nom] = mc + + def append_mc_global_jdc(self, mc): + """ + Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc + """ nom = mc.nom - etape.mc_globaux[nom]=mc - - def append_mc_global_jdc(self,mc): - """ - Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc - """ - nom = mc.nom - self.jdc.mc_globaux[nom]=mc - - def copy(self): - """ Retourne une copie de self """ - objet = self.makeobjet() - # FR : attention !!! avec makeobjet, objet a le meme 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 - - 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 get_sd_utilisees(self): - """ - Retourne la liste des concepts qui sont utilisés à l'intérieur de self - ( comme valorisation d'un MCS) - """ - l=[] - for child in self.mc_liste: - l.extend(child.get_sd_utilisees()) - return l - - def get_sd_mcs_utilisees(self): - """ - Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : - - Si aucune sd n'est utilisée, le dictionnaire est vide. - - Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on - trouve des sd ; la valeur est la liste des sd attenante. - Exemple :: - - { 'VALE_F': [ , - ], - 'MODELE': [] } - """ - dico = {} - for child in self.mc_liste: - daux = child.get_sd_mcs_utilisees() - for cle in daux.keys(): - dico[cle] = dico.get(cle, []) - dico[cle].extend(daux[cle]) - return dico - - def get_mcs_with_co(self,co): - """ - Cette methode retourne l'objet MCSIMP fils de self - qui a le concept co comme valeur. - En principe, elle ne doit etre utilisee que pour les concepts - instances de la classe CO - """ - l=[] - for child in self.mc_liste: - l.extend(child.get_mcs_with_co(co)) - return l - - def get_all_co(self): - """ - Cette methode retourne tous les concepts instances de CO - """ - l=[] - for child in self.mc_liste: - l.extend(child.get_all_co()) - return l + self.jdc.mc_globaux[nom] = mc + + def copy(self): + """ Retourne une copie de self """ + objet = self.makeobjet() + # FR : attention !!! avec makeobjet, objet a le meme 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 + + 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 get_sd_utilisees(self): + """ + Retourne la liste des concepts qui sont utilisés à l'intérieur de self + ( comme valorisation d'un MCS) + """ + l = [] + for child in self.mc_liste: + l.extend(child.get_sd_utilisees()) + return l + + def get_sd_mcs_utilisees(self): + """ + Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : + - Si aucune sd n'est utilisée, le dictionnaire est vide. + - Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on + trouve des sd ; la valeur est la liste des sd attenante. + Exemple :: + + { 'VALE_F': [ , + ], + 'MODELE': [] } + """ + dico = {} + for child in self.mc_liste: + daux = child.get_sd_mcs_utilisees() + for cle in daux.keys(): + dico[cle] = dico.get(cle, []) + dico[cle].extend(daux[cle]) + return dico + + def get_mcs_with_co(self, co): + """ + Cette methode retourne l'objet MCSIMP fils de self + qui a le concept co comme valeur. + En principe, elle ne doit etre utilisee que pour les concepts + instances de la classe CO + """ + l = [] + for child in self.mc_liste: + l.extend(child.get_mcs_with_co(co)) + return l + + def get_all_co(self): + """ + Cette methode retourne tous les concepts instances de CO + """ + l = [] + for child in self.mc_liste: + l.extend(child.get_all_co()) + return l def intersection_vide(dict1, dict2): - """Verification qu'il n'y a pas de clé commune entre 'dict1' et 'dict2'.""" + """Verification qu'il n'y a pas de clé commune entre 'dict1' et 'dict2'.""" sk1 = set(dict1.keys()) sk2 = set(dict2.keys()) inter = sk1.intersection(sk2) diff --git a/Noyau/N_MCFACT.py b/Noyau/N_MCFACT.py index 33297a82..361373cc 100644 --- a/Noyau/N_MCFACT.py +++ b/Noyau/N_MCFACT.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,84 +16,88 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" - Ce module contient la classe MCFACT qui sert à controler la valeur - d'un mot-clé facteur par rapport à sa définition portée par un objet + +""" + Ce module contient la classe MCFACT qui sert à controler la valeur + d'un mot-clé facteur par rapport à sa définition portée par un objet de type ENTITE """ import N_MCCOMPO + class MCFACT(N_MCCOMPO.MCCOMPO): - """ - """ - nature = "MCFACT" - def __init__(self,val,definition,nom,parent): - """ - Attributs : - - val : valeur du mot clé simple - - definition - - nom - - parent - """ - self.definition=definition - self.nom=nom - self.val = val - self.parent = parent - self.valeur = self.GETVAL(self.val) - if parent : - self.jdc = self.parent.jdc - self.niveau = self.parent.niveau - self.etape = self.parent.etape - else: - # Le mot cle a été créé sans parent - self.jdc = None - self.niveau = None - self.etape = None - self.mc_liste=self.build_mc() - - def GETVAL(self,val): - """ - Retourne la valeur effective du mot-clé en fonction - de la valeur donnée. Defaut si val == None - """ - if (val is None and hasattr(self.definition,'defaut')) : - return self.definition.defaut - else: - return val - def get_valeur(self): - """ - Retourne la "valeur" d'un mot-clé facteur qui est l'objet lui-meme. - Cette valeur est utilisée lors de la création d'un contexte - d'évaluation d'expressions à l'aide d'un interpréteur Python - """ - return self + """ + """ + nature = "MCFACT" + + def __init__(self, val, definition, nom, parent): + """ + Attributs : + - val : valeur du mot clé simple + - definition + - nom + - parent + """ + self.definition = definition + self.nom = nom + self.val = val + self.parent = parent + self.valeur = self.GETVAL(self.val) + if parent: + self.jdc = self.parent.jdc + self.niveau = self.parent.niveau + self.etape = self.parent.etape + else: + # Le mot cle a été créé sans parent + self.jdc = None + self.niveau = None + self.etape = None + self.mc_liste = self.build_mc() + + def GETVAL(self, val): + """ + Retourne la valeur effective du mot-clé en fonction + de la valeur donnée. Defaut si val == None + """ + if (val is None and hasattr(self.definition, 'defaut')): + return self.definition.defaut + else: + return val + + def get_valeur(self): + """ + Retourne la "valeur" d'un mot-clé facteur qui est l'objet lui-meme. + Cette valeur est utilisée lors de la création d'un contexte + d'évaluation d'expressions à l'aide d'un interpréteur Python + """ + return self - def get_val(self): - """ - Une autre méthode qui retourne une "autre" valeur du mot clé facteur. - Elle est utilisée par la méthode get_mocle - """ - return [self] + def get_val(self): + """ + Une autre méthode qui retourne une "autre" valeur du mot clé facteur. + Elle est utilisée par la méthode get_mocle + """ + return [self] - def __getitem__(self,key): - """ - Dans le cas d un mot cle facteur unique on simule une liste de - longueur 1 - """ - if key == 0:return self - return self.get_mocle(key) + def __getitem__(self, key): + """ + Dans le cas d un mot cle facteur unique on simule une liste de + longueur 1 + """ + if key == 0: + return self + return self.get_mocle(key) - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitMCFACT(self) + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitMCFACT(self) - def makeobjet(self): - return self.definition.class_instance(val=None,nom=self.nom, - definition=self.definition,parent=self.parent) + def makeobjet(self): + return self.definition.class_instance(val=None, nom=self.nom, + definition=self.definition, parent=self.parent) diff --git a/Noyau/N_MCLIST.py b/Noyau/N_MCLIST.py index 1198e912..90a1d76e 100644 --- a/Noyau/N_MCLIST.py +++ b/Noyau/N_MCLIST.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,12 +16,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" - Ce module contient la classe MCList qui sert à controler la valeur - d'une liste de mots-clés facteur par rapport à sa définition portée par un objet +""" + Ce module contient la classe MCList qui sert à controler la valeur + d'une liste de mots-clés facteur par rapport à sa définition portée par un objet de type ENTITE """ @@ -29,195 +28,204 @@ from copy import copy import UserList import types + class MCList(UserList.UserList): - """ Liste semblable a la liste Python - mais avec quelques methodes en plus - = liste de MCFACT - """ - nature = 'MCList' - def init(self,nom,parent): - self.definition = None - self.nom = nom - self.parent=parent - if parent : - self.jdc = self.parent.jdc - self.niveau = self.parent.niveau - self.etape = self.parent.etape - else: - # Le mot cle a été créé sans parent - self.jdc = None - self.niveau = None - self.etape = None - - def get_valeur(self): - """ - Retourne la "valeur" d'un objet MCList. Sert à construire - un contexte d'évaluation pour une expression Python. - On retourne l'objet lui-meme. - """ - return self - - def get_val(self): - """ - Une autre méthode qui retourne une "autre" valeur d'une MCList - Elle est utilisée par la méthode get_mocle - """ - return self - - def supprime(self): - """ - Méthode qui supprime toutes les références arrières afin que l'objet puisse - etre correctement détruit par le garbage collector - """ - self.parent = None - self.etape = None - self.jdc = None - self.niveau = None - for child in self.data : - child.supprime() - - def get_child(self,name): - """ - Retourne le fils de nom name s'il est contenu dans self - Par défaut retourne le fils du premier de la liste - """ - obj = self.data[0] - # Phase 1 : on cherche dans les fils directs de obj - for child in obj.mc_liste : - if child.nom == name: return child - # Phase 2 : on cherche dans les blocs de self - for child in obj.mc_liste: - if child.isBLOC() : - resu = child.get_child(name) - if resu != None : return resu - # Phase 3 : on cherche dans les entites possibles pour les défauts - for k,v in obj.definition.entites.items(): - #if k == name: return v.defaut - if k == name: - if v.defaut != None : return v(None,k,None) - # si on passe ici, c'est que l'on demande un fils qui n'est pas possible --> erreur - #print "Erreur : %s ne peut etre un descendant de %s" %(name,self.nom) - return None - - def isBLOC(self): - """ - Indique si l'objet est de type BLOC - """ - return 0 - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitMCList(self) - - def get_sd_utilisees(self): - """ - Retourne la liste des concepts qui sont utilisés à l'intérieur de self - ( comme valorisation d'un MCS) - """ - l=[] - for child in self.data: - l.extend(child.get_sd_utilisees()) - return l - - def get_sd_mcs_utilisees(self): - """ - Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : - - Si aucune sd n'est utilisée, le dictionnaire est vide. - - Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on - trouve des sd ; la valeur est la liste des sd attenante. - - Exemple :: - - { 'VALE_F': [ , - ], - 'MODELE': [] } - """ - dico = {} - for child in self.data: - daux = child.get_sd_mcs_utilisees() - for cle in daux.keys(): - dico[cle] = dico.get(cle, []) - dico[cle].extend(daux[cle]) - return dico - - def get_mcs_with_co(self,co): - """ - Cette methode retourne l'objet MCSIMP fils de self - qui a le concept co comme valeur. - En principe, elle ne doit etre utilisee que pour les concepts - instances de la classe CO - """ - l=[] - for child in self.data: - l.extend(child.get_mcs_with_co(co)) - return l - - def get_all_co(self): - """ - Cette methode retourne tous les concepts instances de CO - """ - l=[] - for child in self.data: - l.extend(child.get_all_co()) - return l - - def copy(self): - """ - Réalise la copie d'une MCList - """ - liste = self.data[0].definition.list_instance() - # 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 - - 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 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 __getitem__(self,key): - """ - Dans le cas d un mot cle facteur de longueur 1 on simule un scalaire - """ - if type(key) != types.IntType and len(self) ==1: - return self.data[0].get_mocle(key) - else: - return self.data[key] - - def List_F(self): - """ - Retourne une liste de dictionnaires (eventuellement singleton) qui peut etre - passe directement derriere un mot-cle facteur (pour les macros). - """ - dresu = [] - for mcf in self: - dico = mcf.cree_dict_valeurs(mcf.mc_liste) - for i in dico.keys(): - if dico[i] == None: - del dico[i] - dresu.append(dico) - return dresu + + """ Liste semblable a la liste Python + mais avec quelques methodes en plus + = liste de MCFACT + """ + nature = 'MCList' + + def init(self, nom, parent): + self.definition = None + self.nom = nom + self.parent = parent + if parent: + self.jdc = self.parent.jdc + self.niveau = self.parent.niveau + self.etape = self.parent.etape + else: + # Le mot cle a été créé sans parent + self.jdc = None + self.niveau = None + self.etape = None + + def get_valeur(self): + """ + Retourne la "valeur" d'un objet MCList. Sert à construire + un contexte d'évaluation pour une expression Python. + On retourne l'objet lui-meme. + """ + return self + + def get_val(self): + """ + Une autre méthode qui retourne une "autre" valeur d'une MCList + Elle est utilisée par la méthode get_mocle + """ + return self + + def supprime(self): + """ + Méthode qui supprime toutes les références arrières afin que l'objet puisse + etre correctement détruit par le garbage collector + """ + self.parent = None + self.etape = None + self.jdc = None + self.niveau = None + for child in self.data: + child.supprime() + + def get_child(self, name): + """ + Retourne le fils de nom name s'il est contenu dans self + Par défaut retourne le fils du premier de la liste + """ + obj = self.data[0] + # Phase 1 : on cherche dans les fils directs de obj + for child in obj.mc_liste: + if child.nom == name: + return child + # Phase 2 : on cherche dans les blocs de self + for child in obj.mc_liste: + if child.isBLOC(): + resu = child.get_child(name) + if resu != None: + return resu + # Phase 3 : on cherche dans les entites possibles pour les défauts + for k, v in obj.definition.entites.items(): + # if k == name: return v.defaut + if k == name: + if v.defaut != None: + return v(None, k, None) + # si on passe ici, c'est que l'on demande un fils qui n'est pas possible --> erreur + # print "Erreur : %s ne peut etre un descendant de %s" %(name,self.nom) + return None + + def isBLOC(self): + """ + Indique si l'objet est de type BLOC + """ + return 0 + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitMCList(self) + + def get_sd_utilisees(self): + """ + Retourne la liste des concepts qui sont utilisés à l'intérieur de self + ( comme valorisation d'un MCS) + """ + l = [] + for child in self.data: + l.extend(child.get_sd_utilisees()) + return l + + def get_sd_mcs_utilisees(self): + """ + Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : + - Si aucune sd n'est utilisée, le dictionnaire est vide. + - Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on + trouve des sd ; la valeur est la liste des sd attenante. + + Exemple :: + + { 'VALE_F': [ , + ], + 'MODELE': [] } + """ + dico = {} + for child in self.data: + daux = child.get_sd_mcs_utilisees() + for cle in daux.keys(): + dico[cle] = dico.get(cle, []) + dico[cle].extend(daux[cle]) + return dico + + def get_mcs_with_co(self, co): + """ + Cette methode retourne l'objet MCSIMP fils de self + qui a le concept co comme valeur. + En principe, elle ne doit etre utilisee que pour les concepts + instances de la classe CO + """ + l = [] + for child in self.data: + l.extend(child.get_mcs_with_co(co)) + return l + + def get_all_co(self): + """ + Cette methode retourne tous les concepts instances de CO + """ + l = [] + for child in self.data: + l.extend(child.get_all_co()) + return l + + def copy(self): + """ + Réalise la copie d'une MCList + """ + liste = self.data[0].definition.list_instance() + # 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 + + 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 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 __getitem__(self, key): + """ + Dans le cas d un mot cle facteur de longueur 1 on simule un scalaire + """ + if type(key) != types.IntType and len(self) == 1: + return self.data[0].get_mocle(key) + else: + return self.data[key] + + def List_F(self): + """ + Retourne une liste de dictionnaires (eventuellement singleton) qui peut etre + passe directement derriere un mot-cle facteur (pour les macros). + """ + dresu = [] + for mcf in self: + dico = mcf.cree_dict_valeurs(mcf.mc_liste) + for i in dico.keys(): + if dico[i] == None: + del dico[i] + dresu.append(dico) + return dresu diff --git a/Noyau/N_MCSIMP.py b/Noyau/N_MCSIMP.py index 438b8ee0..7840ee73 100644 --- a/Noyau/N_MCSIMP.py +++ b/Noyau/N_MCSIMP.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,12 +16,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ - Ce module contient la classe MCSIMP qui sert à controler la valeur - d'un mot-clé simple par rapport à sa définition portée par un objet + Ce module contient la classe MCSIMP qui sert à controler la valeur + d'un mot-clé simple par rapport à sa définition portée par un objet de type ENTITE """ @@ -33,159 +32,162 @@ import N_OBJECT from N_CONVERT import ConversionFactory from N_types import force_list, is_sequence + class MCSIMP(N_OBJECT.OBJECT): - """ - """ - nature = 'MCSIMP' - def __init__(self,val,definition,nom,parent): - """ - Attributs : - - - val : valeur du mot clé simple - - - definition - - - nom - - - parent - - Autres attributs : - - - valeur : valeur du mot-clé simple en tenant compte de la valeur par défaut - - """ - self.definition=definition - self.nom=nom - self.val = val - self.parent = parent - self.convProto = ConversionFactory('type', typ=self.definition.type) - self.valeur = self.GETVAL(self.val) - if parent : - self.jdc = self.parent.jdc - self.niveau = self.parent.niveau - self.etape = self.parent.etape - else: - # Le mot cle simple a été créé sans parent - self.jdc = None - self.niveau = None - self.etape = None - - def GETVAL(self,val): - """ - Retourne la valeur effective du mot-clé en fonction - de la valeur donnée. Defaut si val == None - """ - if (val is None and hasattr(self.definition,'defaut')) : - val = self.definition.defaut - if self.convProto: - val = self.convProto.convert(val) - return val - - def get_valeur(self): - """ - Retourne la "valeur" d'un mot-clé simple. - Cette valeur est utilisée lors de la création d'un contexte - d'évaluation d'expressions à l'aide d'un interpréteur Python - """ - v = self.valeur - # Si singleton et max=1, on retourne la valeur. - # Si une valeur simple et max='**', on retourne un singleton. - # (si liste de longueur > 1 et max=1, on sera arrêté plus tard) - # Pour accepter les numpy.array, on remplace : "type(v) not in (list, tuple)" - # par "not has_attr(v, '__iter__')". - if v is None: - pass - elif is_sequence(v) and len(v) == 1 and self.definition.max == 1: - v = v[0] - elif not is_sequence(v) and self.definition.max != 1: - v = (v, ) - # traitement particulier pour les complexes ('RI', r, i) - if 'C' in self.definition.type and self.definition.max != 1 \ - and v[0] in ('RI', 'MP'): - v = (v, ) - return v - - def get_val(self): - """ - Une autre méthode qui retourne une "autre" valeur du mot clé simple. - Elle est utilisée par la méthode get_mocle - """ - return self.valeur - - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitMCSIMP(self) - - def copy(self): - """ Retourne une copie de self """ - objet = self.makeobjet() - # il faut copier les listes et les tuples mais pas les autres valeurs - # possibles (réel,SD,...) - if type(self.valeur) in (list, tuple): - objet.valeur = copy(self.valeur) - else: - objet.valeur = self.valeur - objet.val = objet.valeur - return objet - - def makeobjet(self): - return self.definition(val = None, nom = self.nom,parent = self.parent) - - 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 get_sd_utilisees(self): - """ - Retourne une liste qui contient la ou les SD utilisée par self si c'est le cas - ou alors une liste vide - """ - l=[] - if isinstance(self.valeur, ASSD): - l.append(self.valeur) - elif type(self.valeur) in (list, tuple): - for val in self.valeur : - if isinstance(val, ASSD): - l.append(val) - return l - - def get_sd_mcs_utilisees(self): - """ - Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : - - Si aucune sd n'est utilisée, le dictionnaire est vide. - - Sinon, la clé du dictionnaire est le mot-clé simple ; la valeur est - la liste des sd attenante. - - Exemple :: - { 'VALE_F': [ , - ] } - """ - l=self.get_sd_utilisees() - dico = {} - if len(l) > 0 : - dico[self.nom] = l - return dico - - def get_mcs_with_co(self,co): - """ - Cette methode retourne l'objet MCSIMP self s'il a le concept co - comme valeur. - """ - if co in force_list(self.valeur): - return [self,] - return [] - - def get_all_co(self): - """ - Cette methode retourne la liste de tous les concepts co - associés au mot cle simple - """ - return [co for co in force_list(self.valeur) \ - if isinstance(co, CO) and co.is_typco()] + + """ + """ + nature = 'MCSIMP' + + def __init__(self, val, definition, nom, parent): + """ + Attributs : + + - val : valeur du mot clé simple + + - definition + + - nom + + - parent + + Autres attributs : + + - valeur : valeur du mot-clé simple en tenant compte de la valeur par défaut + + """ + self.definition = definition + self.nom = nom + self.val = val + self.parent = parent + self.convProto = ConversionFactory('type', typ=self.definition.type) + self.valeur = self.GETVAL(self.val) + if parent: + self.jdc = self.parent.jdc + self.niveau = self.parent.niveau + self.etape = self.parent.etape + else: + # Le mot cle simple a été créé sans parent + self.jdc = None + self.niveau = None + self.etape = None + + def GETVAL(self, val): + """ + Retourne la valeur effective du mot-clé en fonction + de la valeur donnée. Defaut si val == None + """ + if (val is None and hasattr(self.definition, 'defaut')): + val = self.definition.defaut + if self.convProto: + val = self.convProto.convert(val) + return val + + def get_valeur(self): + """ + Retourne la "valeur" d'un mot-clé simple. + Cette valeur est utilisée lors de la création d'un contexte + d'évaluation d'expressions à l'aide d'un interpréteur Python + """ + v = self.valeur + # Si singleton et max=1, on retourne la valeur. + # Si une valeur simple et max='**', on retourne un singleton. + # (si liste de longueur > 1 et max=1, on sera arrêté plus tard) + # Pour accepter les numpy.array, on remplace : "type(v) not in (list, tuple)" + # par "not has_attr(v, '__iter__')". + if v is None: + pass + elif is_sequence(v) and len(v) == 1 and self.definition.max == 1: + v = v[0] + elif not is_sequence(v) and self.definition.max != 1: + v = (v, ) + # traitement particulier pour les complexes ('RI', r, i) + if 'C' in self.definition.type and self.definition.max != 1 \ + and v[0] in ('RI', 'MP'): + v = (v, ) + return v + + def get_val(self): + """ + Une autre méthode qui retourne une "autre" valeur du mot clé simple. + Elle est utilisée par la méthode get_mocle + """ + return self.valeur + + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitMCSIMP(self) + + def copy(self): + """ Retourne une copie de self """ + objet = self.makeobjet() + # il faut copier les listes et les tuples mais pas les autres valeurs + # possibles (réel,SD,...) + if type(self.valeur) in (list, tuple): + objet.valeur = copy(self.valeur) + else: + objet.valeur = self.valeur + objet.val = objet.valeur + return objet + + def makeobjet(self): + return self.definition(val=None, nom=self.nom, parent=self.parent) + + 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 get_sd_utilisees(self): + """ + Retourne une liste qui contient la ou les SD utilisée par self si c'est le cas + ou alors une liste vide + """ + l = [] + if isinstance(self.valeur, ASSD): + l.append(self.valeur) + elif type(self.valeur) in (list, tuple): + for val in self.valeur: + if isinstance(val, ASSD): + l.append(val) + return l + + def get_sd_mcs_utilisees(self): + """ + Retourne la ou les SD utilisée par self sous forme d'un dictionnaire : + - Si aucune sd n'est utilisée, le dictionnaire est vide. + - Sinon, la clé du dictionnaire est le mot-clé simple ; la valeur est + la liste des sd attenante. + + Exemple :: + { 'VALE_F': [ , + ] } + """ + l = self.get_sd_utilisees() + dico = {} + if len(l) > 0: + dico[self.nom] = l + return dico + + def get_mcs_with_co(self, co): + """ + Cette methode retourne l'objet MCSIMP self s'il a le concept co + comme valeur. + """ + if co in force_list(self.valeur): + return [self, ] + return [] + + def get_all_co(self): + """ + Cette methode retourne la liste de tous les concepts co + associés au mot cle simple + """ + return [co for co in force_list(self.valeur) + if isinstance(co, CO) and co.is_typco()] diff --git a/Noyau/N_OBJECT.py b/Noyau/N_OBJECT.py index c8fc3c1a..a9c3e421 100644 --- a/Noyau/N_OBJECT.py +++ b/Noyau/N_OBJECT.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,116 +16,121 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ - Ce module contient la classe OBJECT classe mère de tous les objets - servant à controler les valeurs par rapport aux définitions + Ce module contient la classe OBJECT classe mère de tous les objets + servant à controler les valeurs par rapport aux définitions """ from N_CR import CR from strfunc import ufmt + class OBJECT: - """ - Classe OBJECT : cette classe est virtuelle et sert de classe mère - aux classes de type ETAPE et MOCLES. - Elle ne peut etre instanciée. - Une sous classe doit obligatoirement implémenter les méthodes : - - - __init__ - - """ - - 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 supprime(self): - """ - Méthode qui supprime les références arrières suffisantes pour - que l'objet puisse etre correctement détruit par le - garbage collector - """ - self.parent = None - self.etape = None - self.jdc = None - self.niveau = None - - def get_val(self): - """ - Retourne la valeur de l'objet. Cette méthode fournit - une valeur par defaut. Elle doit etre dérivée pour chaque - type d'objet - """ - return self - - def isBLOC(self): - """ - Indique si l'objet est un BLOC - """ - return 0 - - def get_jdc_root(self): - """ - Cette méthode doit retourner l'objet racine c'est à dire celui qui - n'a pas de parent - """ - if self.parent: - return self.parent.get_jdc_root() - else: - return self - - def GETVAL(self,val): - """ - Retourne la valeur effective du mot-clé en fonction - de la valeur donnée. Defaut si val == None - """ - if (val is None and hasattr(self.definition,'defaut')) : - return self.definition.defaut - else: - return val - - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.jdc + + """ + Classe OBJECT : cette classe est virtuelle et sert de classe mère + aux classes de type ETAPE et MOCLES. + Elle ne peut etre instanciée. + Une sous classe doit obligatoirement implémenter les méthodes : + + - __init__ + + """ + + 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 supprime(self): + """ + Méthode qui supprime les références arrières suffisantes pour + que l'objet puisse etre correctement détruit par le + garbage collector + """ + self.parent = None + self.etape = None + self.jdc = None + self.niveau = None + + def get_val(self): + """ + Retourne la valeur de l'objet. Cette méthode fournit + une valeur par defaut. Elle doit etre dérivée pour chaque + type d'objet + """ + return self + + def isBLOC(self): + """ + Indique si l'objet est un BLOC + """ + return 0 + + def get_jdc_root(self): + """ + Cette méthode doit retourner l'objet racine c'est à dire celui qui + n'a pas de parent + """ + if self.parent: + return self.parent.get_jdc_root() + else: + return self + + def GETVAL(self, val): + """ + Retourne la valeur effective du mot-clé en fonction + de la valeur donnée. Defaut si val == None + """ + if (val is None and hasattr(self.definition, 'defaut')): + return self.definition.defaut + else: + return val + + def reparent(self, parent): + """ + Cette methode sert a reinitialiser la parente de l'objet + """ + self.parent = parent + self.jdc = parent.jdc + class ErrorObj(OBJECT): + """Classe pour objets errones : emule le comportement d'un objet tel mcsimp ou mcfact """ - def __init__(self,definition,valeur,parent,nom="err"): - self.nom=nom - self.definition=definition - self.valeur=valeur - self.parent=parent - self.mc_liste=[] - if parent : + + def __init__(self, definition, valeur, parent, nom="err"): + self.nom = nom + self.definition = definition + self.valeur = valeur + self.parent = parent + self.mc_liste = [] + if parent: self.jdc = self.parent.jdc - #self.niveau = self.parent.niveau - #self.etape = self.parent.etape + # self.niveau = self.parent.niveau + # self.etape = self.parent.etape else: # Pas de parent self.jdc = None - #self.niveau = None - #self.etape = None - def isvalid(self,cr='non'): + # self.niveau = None + # self.etape = None + + def isvalid(self, cr='non'): return 0 def report(self): - """ génère le rapport de validation de self """ - self.cr=CR() - self.cr.debut = u"Mot-clé invalide : "+self.nom - self.cr.fin = u"Fin Mot-clé invalide : "+self.nom - self.cr.fatal(_(u"Type non autorisé pour le mot-clé %s : '%s'"), - self.nom, self.valeur) - return self.cr - + """ génère le rapport de validation de self """ + self.cr = CR() + self.cr.debut = u"Mot-clé invalide : " + self.nom + self.cr.fin = u"Fin Mot-clé invalide : " + self.nom + self.cr.fatal(_(u"Type non autorisé pour le mot-clé %s : '%s'"), + self.nom, self.valeur) + return self.cr diff --git a/Noyau/N_OPER.py b/Noyau/N_OPER.py index e5e8a037..3c14e09a 100644 --- a/Noyau/N_OPER.py +++ b/Noyau/N_OPER.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,145 +16,147 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient la classe de definition OPER - qui permet de spécifier les caractéristiques d'un opérateur + qui permet de spécifier les caractéristiques d'un opérateur """ -import types,string,traceback +import types +import string +import traceback import N_ENTITE import N_ETAPE import nommage from strfunc import ufmt -class OPER(N_ENTITE.ENTITE): - """ - Classe pour definir un opérateur - - Cette classe a trois attributs de classe - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - opérateur avec sa définition - - - label qui indique la nature de l'objet de définition (ici, OPER) - - - nommage qui est un module Python qui fournit la fonctionnalité de nommage - - et les attributs d'instance suivants : - - - nom : son nom - - - op : le numéro d'opérateur - - - sd_prod : le type de concept produit. C'est une classe ou une fonction qui retourne - une classe - - - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur - réentrant peut modifier un concept d'entrée et le produire comme concept de sortie - - - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur - non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort - de l'objet gérant le contexte d'exécution de vérifier cette contrainte. - - - fr : commentaire associé en francais - - - ang : commentaire associé en anglais - - - docu : clé de documentation associée - - - regles : liste des règles associées - - - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette - fonction est exécutée lors des phases d'initialisation de l'étape associée. - - - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre - rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. - Si niveau vaut None, l'opérateur est rangé au niveau global. - - - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit - des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut - est initialisé avec args, c'est à dire les arguments d'appel restants. - - - """ - class_instance = N_ETAPE.ETAPE - label = 'OPER' - nommage = nommage - - def __init__(self,nom,op,sd_prod,reentrant='n',repetable='o',fr="",ang="", - docu="",regles=(),op_init=None,niveau = None,UIinfo=None,**args): - """ - Méthode d'initialisation de l'objet OPER. Les arguments sont utilisés pour initialiser - les attributs de meme nom - """ - self.nom=nom - self.op=op - self.sd_prod=sd_prod - self.reentrant=reentrant - self.fr=fr - self.ang=ang - self.repetable = repetable - self.docu=docu - if type(regles)== types.TupleType: - self.regles=regles - else: - self.regles=(regles,) - # Attribut op_init : Fonction a appeler a la construction de l operateur sauf si == None - self.op_init=op_init - self.entites=args - current_cata=CONTEXT.get_current_cata() - if niveau == None: - self.niveau=None - current_cata.enregistre(self) - else: - self.niveau=current_cata.get_niveau(niveau) - self.niveau.enregistre(self) - self.UIinfo=UIinfo - self.affecter_parente() - self.check_definition(self.nom) - - def __call__(self,reuse=None,**args): - """ - Construit l'objet ETAPE a partir de sa definition (self), - puis demande la construction de ses sous-objets et du concept produit. - """ - nomsd=self.nommage.GetNomConceptResultat(self.nom) - etape= self.class_instance(oper=self,reuse=reuse,args=args) - etape.McBuild() - return etape.Build_sd(nomsd) - - def make_objet(self,mc_list='oui'): - """ - Cette méthode crée l'objet ETAPE dont la définition est self sans - l'enregistrer ni créer sa sdprod. - Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction - des objets MCxxx. - """ - etape= self.class_instance(oper=self,reuse=None,args={}) - if mc_list == 'oui':etape.McBuild() - return etape - - def verif_cata(self): - """ - Méthode de vérification des attributs de définition - """ - self.check_regles() - self.check_fr() - self.check_reentrant() - self.check_docu() - self.check_nom() - self.check_op(valmin=0) - self.verif_cata_regles() - - def supprime(self): - """ - Méthode pour supprimer les références arrières susceptibles de provoquer - des cycles de références - """ - self.niveau=None +class OPER(N_ENTITE.ENTITE): + """ + Classe pour definir un opérateur + + Cette classe a trois attributs de classe + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + opérateur avec sa définition + + - label qui indique la nature de l'objet de définition (ici, OPER) + + - nommage qui est un module Python qui fournit la fonctionnalité de nommage + + et les attributs d'instance suivants : + + - nom : son nom + + - op : le numéro d'opérateur + + - sd_prod : le type de concept produit. C'est une classe ou une fonction qui retourne + une classe + + - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur + réentrant peut modifier un concept d'entrée et le produire comme concept de sortie + + - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur + non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort + de l'objet gérant le contexte d'exécution de vérifier cette contrainte. + + - fr : commentaire associé en francais + + - docu : clé de documentation associée + + - regles : liste des règles associées + + - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette + fonction est exécutée lors des phases d'initialisation de l'étape associée. + + - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre + rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. + Si niveau vaut None, l'opérateur est rangé au niveau global. + + - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit + des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut + est initialisé avec args, c'est à dire les arguments d'appel restants. + + + """ + class_instance = N_ETAPE.ETAPE + label = 'OPER' + nommage = nommage + + def __init__(self, nom, op, sd_prod, reentrant='n', repetable='o', fr="",ang="", + docu="", regles=(), op_init=None, niveau = None, UIinfo=None, **args): + """ + Méthode d'initialisation de l'objet OPER. Les arguments sont utilisés pour initialiser + les attributs de meme nom + """ + self.nom = nom + self.op = op + self.sd_prod = sd_prod + self.reentrant = reentrant + self.fr = fr + self.ang = ang + self.repetable = repetable + self.docu = docu + if type(regles) == types.TupleType: + self.regles = regles + else: + self.regles = (regles,) + # Attribut op_init : Fonction a appeler a la construction de l + # operateur sauf si == None + self.op_init = op_init + self.entites = args + current_cata = CONTEXT.get_current_cata() + if niveau == None: + self.niveau = None + current_cata.enregistre(self) + else: + self.niveau = current_cata.get_niveau(niveau) + self.niveau.enregistre(self) + self.UIinfo = UIinfo + self.affecter_parente() + self.check_definition(self.nom) + + def __call__(self, reuse=None, **args): + """ + Construit l'objet ETAPE a partir de sa definition (self), + puis demande la construction de ses sous-objets et du concept produit. + """ + nomsd = self.nommage.GetNomConceptResultat(self.nom) + etape = self.class_instance(oper=self, reuse=reuse, args=args) + etape.McBuild() + return etape.Build_sd(nomsd) + + def make_objet(self, mc_list='oui'): + """ + Cette méthode crée l'objet ETAPE dont la définition est self sans + l'enregistrer ni créer sa sdprod. + Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction + des objets MCxxx. + """ + etape = self.class_instance(oper=self, reuse=None, args={}) + if mc_list == 'oui': + etape.McBuild() + return etape + + def verif_cata(self): + """ + Méthode de vérification des attributs de définition + """ + self.check_regles() + self.check_fr() + self.check_reentrant() + self.check_docu() + self.check_nom() + self.check_op(valmin=0) + self.verif_cata_regles() + + def supprime(self): + """ + Méthode pour supprimer les références arrières susceptibles de provoquer + des cycles de références + """ + self.niveau = None diff --git a/Noyau/N_OPS.py b/Noyau/N_OPS.py index e368d32e..c9e1d6ed 100644 --- a/Noyau/N_OPS.py +++ b/Noyau/N_OPS.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,10 +16,12 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + from N_utils import import_object + class OPS: + """Wrapper to ops functions. This allows to import them only when they are needed.""" @@ -33,8 +35,9 @@ class OPS: return func(*args, **kwargs) -# utilisé par exemple par des macros où tout est fait dans l'init. +# utilisé par exemple par des macros où tout est fait dans l'init. class NOTHING(OPS): + """OPS which does nothing.""" def __call__(self, macro, *args, **kwargs): diff --git a/Noyau/N_PROC.py b/Noyau/N_PROC.py index 15e2823e..ab3f0378 100644 --- a/Noyau/N_PROC.py +++ b/Noyau/N_PROC.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,138 +16,139 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ Ce module contient la classe de definition PROC - qui permet de spécifier les caractéristiques d'une procédure + qui permet de spécifier les caractéristiques d'une procédure """ -import types,string,traceback +import types +import string +import traceback import N_ENTITE import N_PROC_ETAPE from strfunc import ufmt -class PROC(N_ENTITE.ENTITE): - """ - Classe pour definir un opérateur - - Cette classe a deux attributs de classe - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - opérateur avec sa définition - - - label qui indique la nature de l'objet de définition (ici, PROC) - - - et les attributs d'instance suivants : - - - nom : son nom - - - op : le numéro d'opérateur - - - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur - réentrant peut modifier un concept d'entrée et le produire comme concept de sortie - - - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur - non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort - de l'objet gérant le contexte d'exécution de vérifier cette contrainte. - - - fr : commentaire associé en francais - - - ang : commentaire associé en anglais - - - docu : clé de documentation associée - - - regles : liste des règles associées - - - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette - fonction est exécutée lors des phases d'initialisation de l'étape associée. - - - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre - rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. - Si niveau vaut None, l'opérateur est rangé au niveau global. - - - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit - des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut - est initialisé avec args, c'est à dire les arguments d'appel restants. - - - """ - class_instance = N_PROC_ETAPE.PROC_ETAPE - label = 'PROC' - - def __init__(self,nom,op,reentrant='n',repetable='o',fr="",ang="", - docu="",regles=(),op_init=None,niveau = None,UIinfo=None,**args): - """ - Méthode d'initialisation de l'objet PROC. Les arguments sont utilisés pour initialiser - les attributs de meme nom - """ - self.nom=nom - self.op=op - self.reentrant=reentrant - self.repetable = repetable - self.fr=fr - self.ang=ang - self.docu=docu - if type(regles)== types.TupleType: - self.regles=regles - else: - self.regles=(regles,) - # Attribut op_init : Fonction a appeler a la construction de l operateur sauf si == None - self.op_init=op_init - self.entites=args - current_cata=CONTEXT.get_current_cata() - if niveau == None: - self.niveau=None - current_cata.enregistre(self) - else: - self.niveau=current_cata.get_niveau(niveau) - self.niveau.enregistre(self) - self.UIinfo=UIinfo - self.affecter_parente() - self.check_definition(self.nom) - - def __call__(self,**args): - """ - Construit l'objet PROC_ETAPE a partir de sa definition (self), - puis demande la construction de ses sous-objets et du concept produit. - """ - etape= self.class_instance(oper=self,args=args) - etape.McBuild() - return etape.Build_sd() - - def make_objet(self,mc_list='oui'): - """ - Cette méthode crée l'objet PROC_ETAPE dont la définition est self sans - l'enregistrer ni créer sa sdprod. - Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction - des objets MCxxx. - """ - etape= self.class_instance(oper=self,args={}) - if mc_list == 'oui':etape.McBuild() - return etape - - def verif_cata(self): - """ - Méthode de vérification des attributs de définition - """ - self.check_regles() - self.check_fr() - self.check_reentrant() - self.check_docu() - self.check_nom() - self.check_op(valmin=0) - self.verif_cata_regles() - - def supprime(self): - """ - Méthode pour supprimer les références arrières susceptibles de provoquer - des cycles de références - """ - self.niveau=None +class PROC(N_ENTITE.ENTITE): + """ + Classe pour definir un opérateur + + Cette classe a deux attributs de classe + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + opérateur avec sa définition + + - label qui indique la nature de l'objet de définition (ici, PROC) + + + et les attributs d'instance suivants : + + - nom : son nom + + - op : le numéro d'opérateur + + - reentrant : vaut 'n' ou 'o'. Indique si l'opérateur est réentrant ou pas. Un opérateur + réentrant peut modifier un concept d'entrée et le produire comme concept de sortie + + - repetable : vaut 'n' ou 'o'. Indique si l'opérateur est répetable ou pas. Un opérateur + non répétable ne doit apparaitre qu'une fois dans une exécution. C'est du ressort + de l'objet gérant le contexte d'exécution de vérifier cette contrainte. + + - fr : commentaire associé en francais + + - docu : clé de documentation associée + + - regles : liste des règles associées + + - op_init : cet attribut vaut None ou une fonction. Si cet attribut ne vaut pas None, cette + fonction est exécutée lors des phases d'initialisation de l'étape associée. + + - niveau : indique le niveau dans lequel est rangé l'opérateur. Les opérateurs peuvent etre + rangés par niveau. Ils apparaissent alors exclusivement dans leur niveau de rangement. + Si niveau vaut None, l'opérateur est rangé au niveau global. + + - entites : dictionnaire dans lequel sont stockés les sous entités de l'opérateur. Il s'agit + des entités de définition pour les mots-clés : FACT, BLOC, SIMP. Cet attribut + est initialisé avec args, c'est à dire les arguments d'appel restants. + + + """ + class_instance = N_PROC_ETAPE.PROC_ETAPE + label = 'PROC' + + def __init__(self, nom, op, reentrant='n', repetable='o', fr="",ang="", + docu="", regles=(), op_init=None, niveau = None, UIinfo=None, **args): + """ + Méthode d'initialisation de l'objet PROC. Les arguments sont utilisés pour initialiser + les attributs de meme nom + """ + self.nom = nom + self.op = op + self.reentrant = reentrant + self.repetable = repetable + self.fr = fr + self.ang="" + self.docu = docu + if type(regles) == types.TupleType: + self.regles = regles + else: + self.regles = (regles,) + # Attribut op_init : Fonction a appeler a la construction de l + # operateur sauf si == None + self.op_init = op_init + self.entites = args + current_cata = CONTEXT.get_current_cata() + if niveau == None: + self.niveau = None + current_cata.enregistre(self) + else: + self.niveau = current_cata.get_niveau(niveau) + self.niveau.enregistre(self) + self.UIinfo = UIinfo + self.affecter_parente() + self.check_definition(self.nom) + + def __call__(self, **args): + """ + Construit l'objet PROC_ETAPE a partir de sa definition (self), + puis demande la construction de ses sous-objets et du concept produit. + """ + etape = self.class_instance(oper=self, args=args) + etape.McBuild() + return etape.Build_sd() + + def make_objet(self, mc_list='oui'): + """ + Cette méthode crée l'objet PROC_ETAPE dont la définition est self sans + l'enregistrer ni créer sa sdprod. + Si l'argument mc_list vaut 'oui', elle déclenche en plus la construction + des objets MCxxx. + """ + etape = self.class_instance(oper=self, args={}) + if mc_list == 'oui': + etape.McBuild() + return etape + + def verif_cata(self): + """ + Méthode de vérification des attributs de définition + """ + self.check_regles() + self.check_fr() + self.check_reentrant() + self.check_docu() + self.check_nom() + self.check_op(valmin=0) + self.verif_cata_regles() + + def supprime(self): + """ + Méthode pour supprimer les références arrières susceptibles de provoquer + des cycles de références + """ + self.niveau = None diff --git a/Noyau/N_PROC_ETAPE.py b/Noyau/N_PROC_ETAPE.py index 8907f28e..331bcfb2 100644 --- a/Noyau/N_PROC_ETAPE.py +++ b/Noyau/N_PROC_ETAPE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,93 +16,98 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" - Ce module contient la classe PROC_ETAPE qui sert à vérifier et à exécuter - une procédure +""" + Ce module contient la classe PROC_ETAPE qui sert à vérifier et à exécuter + une procédure """ # Modules Python -import types,sys,string +import types +import sys +import string import traceback # Modules EFICAS -import N_MCCOMPO, N_ETAPE +import N_MCCOMPO +import N_ETAPE from N_Exception import AsException import N_utils -class PROC_ETAPE(N_ETAPE.ETAPE): - """ - Cette classe hérite de ETAPE. La seule différence porte sur le fait - qu'une procédure n'a pas de concept produit - """ - nature = "PROCEDURE" - def __init__(self, oper=None, reuse=None, args={}): - """ - Attributs : - - definition : objet portant les attributs de définition d'une étape de type opérateur. Il - est initialisé par l'argument oper. - - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args. - - reuse : forcément None pour une PROC - """ - N_ETAPE.ETAPE.__init__(self, oper, reuse=None, args=args, niveau=5) - self.reuse = None +class PROC_ETAPE(N_ETAPE.ETAPE): - 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 - except AsException,e: - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1],e) - except EOFError: - 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)) + """ + Cette classe hérite de ETAPE. La seule différence porte sur le fait + qu'une procédure n'a pas de concept produit - self.Execute() - return None + """ + nature = "PROCEDURE" - def supprime(self): - """ - Méthode qui supprime toutes les références arrières afin que l'objet puisse - etre correctement détruit par le garbage collector - """ - N_MCCOMPO.MCCOMPO.supprime(self) - self.jdc=None - self.appel=None + def __init__(self, oper=None, reuse=None, args={}): + """ + Attributs : + - definition : objet portant les attributs de définition d'une étape de type opérateur. Il + est initialisé par l'argument oper. + - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args. + - reuse : forcément None pour une PROC + """ + N_ETAPE.ETAPE.__init__(self, oper, reuse=None, args=args, niveau=5) + self.reuse = None - def accept(self,visitor): - """ - Cette methode permet de parcourir l'arborescence des objets - en utilisant le pattern VISITEUR - """ - visitor.visitPROC_ETAPE(self) + 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 + except AsException, e: + raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0], + 'fichier : ', self.appel[1], e) + except EOFError: + 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)) - def update_context(self,d): - """ - Met à jour le contexte de l'appelant passé en argument (d) - Une PROC_ETAPE n ajoute pas directement de concept dans le contexte - Seule une fonction enregistree dans op_init pourrait le faire - """ - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,d)) + self.Execute() + return None + def supprime(self): + """ + Méthode qui supprime toutes les références arrières afin que l'objet puisse + etre correctement détruit par le garbage collector + """ + N_MCCOMPO.MCCOMPO.supprime(self) + self.jdc = None + self.appel = None + def accept(self, visitor): + """ + Cette methode permet de parcourir l'arborescence des objets + en utilisant le pattern VISITEUR + """ + visitor.visitPROC_ETAPE(self) + def update_context(self, d): + """ + Met à jour le contexte de l'appelant passé en argument (d) + Une PROC_ETAPE n ajoute pas directement de concept dans le contexte + Seule une fonction enregistree dans op_init pourrait le faire + """ + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init, (self, d)) diff --git a/Noyau/N_REGLE.py b/Noyau/N_REGLE.py index a38c59d8..5f609e8e 100644 --- a/Noyau/N_REGLE.py +++ b/Noyau/N_REGLE.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,14 +16,14 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient la classe mere pour les classes de definition des regles d exclusion. La classe REGLE est la classe de base : elle est virtuelle, elle ne doit pas etre instanciee. - Les classes regles dérivées qui seront instanciées doivent implementer la methode verif + Les classes regles dérivées qui seront instanciées doivent implementer la methode verif dont l argument est le dictionnaire des mots cles effectivement presents sur lesquels sera operee la verification de la regle @@ -31,52 +31,53 @@ Exemple :: - # Création de l'objet règle UNPARMI + # Création de l'objet règle UNPARMI r=UNPARMI("INFO","AFFE") - # Vérification de la règle r sur le dictionnaire passé en argument + # Vérification de la règle r sur le dictionnaire passé en argument r.verif({"INFO":v1,"AFFE":v2) """ import types + class REGLE: - def __init__(self,*args): - """ - Les classes dérivées peuvent utiliser cet initialiseur par défaut ou - le surcharger - """ - self.mcs=args - - def verif(self,args): - """ - Les classes dérivées doivent implémenter cette méthode - qui doit retourner une paire dont le premier élément est une chaine de caractère - et le deuxième un entier. - - L'entier peut valoir 0 ou 1. -- s'il vaut 1, la règle est vérifiée - s'il vaut 0, la règle n'est pas vérifiée et le texte joint contient - un commentaire de la non validité. - """ - raise NotImplementedError('class REGLE should be derived') - - def liste_to_dico(self,args): - """ - Cette méthode est utilitaire pour les seuls besoins - des classes dérivées. - - Elle transforme une liste de noms de mots clés en un - dictionnaire équivalent dont les clés sont les noms des mts-clés - - Ceci permet d'avoir un traitement identique pour les listes et les dictionnaires - """ - if type(args) == types.DictionaryType: - return args - elif type(args) == types.ListType: - dico={} - for arg in args : - dico[arg]=0 - return dico - else : - raise Exception("Erreur ce n'est ni un dictionnaire ni une liste %s" % args) + def __init__(self, *args): + """ + Les classes dérivées peuvent utiliser cet initialiseur par défaut ou + le surcharger + """ + self.mcs = args + + def verif(self, args): + """ + Les classes dérivées doivent implémenter cette méthode + qui doit retourner une paire dont le premier élément est une chaine de caractère + et le deuxième un entier. + + L'entier peut valoir 0 ou 1. -- s'il vaut 1, la règle est vérifiée + s'il vaut 0, la règle n'est pas vérifiée et le texte joint contient + un commentaire de la non validité. + """ + raise NotImplementedError('class REGLE should be derived') + + def liste_to_dico(self, args): + """ + Cette méthode est utilitaire pour les seuls besoins + des classes dérivées. + + Elle transforme une liste de noms de mots clés en un + dictionnaire équivalent dont les clés sont les noms des mts-clés + Ceci permet d'avoir un traitement identique pour les listes et les dictionnaires + """ + if type(args) == types.DictionaryType: + return args + elif type(args) == types.ListType: + dico = {} + for arg in args: + dico[arg] = 0 + return dico + else: + raise Exception( + "Erreur ce n'est ni un dictionnaire ni une liste %s" % args) diff --git a/Noyau/N_SENSIBILITE.py b/Noyau/N_SENSIBILITE.py index 439f69dd..3bc1ff51 100644 --- a/Noyau/N_SENSIBILITE.py +++ b/Noyau/N_SENSIBILITE.py @@ -16,7 +16,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# """ Ce module contient les règles nécessaires aux commandes sensibles diff --git a/Noyau/N_SIMP.py b/Noyau/N_SIMP.py index ef61e194..21ee6345 100644 --- a/Noyau/N_SIMP.py +++ b/Noyau/N_SIMP.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,10 +16,10 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient la classe de definition SIMP - qui permet de spécifier les caractéristiques des mots clés simples + qui permet de spécifier les caractéristiques des mots clés simples """ import types @@ -28,97 +28,81 @@ import N_ENTITE import N_MCSIMP from strfunc import ufmt -class SIMP(N_ENTITE.ENTITE): - """ - Classe pour definir un mot cle simple - - Cette classe a deux attributs de classe - - - class_instance qui indique la classe qui devra etre utilisée - pour créer l'objet qui servira à controler la conformité d'un - mot-clé simple avec sa définition - - - label qui indique la nature de l'objet de définition (ici, SIMP) - - """ - class_instance = N_MCSIMP.MCSIMP - label = 'SIMP' - - def __init__(self,typ,fr="",ang="",statut='f',into=None,defaut=None, - min=1,max=1,homo=1,position ='local', - val_min = '**',val_max='**',docu="",validators=None,sug=None): - - """ - Un mot-clé simple est caractérisé par les attributs suivants : - - - type : cet attribut est obligatoire et indique le type de valeur attendue - - - fr : - - - ang : - - - statut : - - - into : - - - defaut : - - - min - - - max - - - homo - - - position - - - val_min - - - val_max - - - docu - """ - N_ENTITE.ENTITE.__init__(self,validators) - # Initialisation des attributs - if type(typ) == types.TupleType : - self.type=typ - else : - self.type=(typ,) - self.fr=fr - self.ang=ang - self.statut=statut - self.into=into - self.defaut=defaut - self.min=min - self.max=max - self.homo=homo - self.position = position - self.val_min=val_min - self.val_max=val_max - self.docu = docu - self.sug = sug - - def verif_cata(self): - """ - Cette methode sert à valider les attributs de l'objet de définition - de la classe SIMP - """ - self.check_min_max() - self.check_fr() - self.check_statut() - self.check_homo() - self.check_into() - self.check_position() - self.check_validators() - - def __call__(self,val,nom,parent=None): - """ - Construit un objet mot cle simple (MCSIMP) a partir de sa definition (self) - de sa valeur (val), de son nom (nom) et de son parent dans l arboresence (parent) - """ - return self.class_instance(nom=nom,definition=self,val=val,parent=parent) - - - - +class SIMP(N_ENTITE.ENTITE): + """ + Classe pour definir un mot cle simple + + Cette classe a deux attributs de classe + + - class_instance qui indique la classe qui devra etre utilisée + pour créer l'objet qui servira à controler la conformité d'un + mot-clé simple avec sa définition + + - label qui indique la nature de l'objet de définition (ici, SIMP) + + """ + class_instance = N_MCSIMP.MCSIMP + label = 'SIMP' + + def __init__(self, typ,ang="", fr="", statut='f', into=None, defaut=None, + min=1, max=1, homo=1, position='local', + val_min='**', val_max='**', docu="", validators=None, + sug=None): + """ + Un mot-clé simple est caractérisé par les attributs suivants : + - type : cet attribut est obligatoire et indique le type de valeur attendue + - fr : chaîne documentaire en français + - statut : obligatoire ou facultatif ou caché + - into : valeurs autorisées + - defaut : valeur par défaut + - min : nombre minimal de valeurs + - max : nombre maximal de valeurs + - homo : ? + - ang : doc + - position : si global, le mot-clé peut-être lu n'importe où dans la commande + - val_min : valeur minimale autorisée + - val_max : valeur maximale autorisée + - docu : ? + - sug : ? + """ + N_ENTITE.ENTITE.__init__(self, validators) + # Initialisation des attributs + if type(typ) == types.TupleType: + self.type = typ + else: + self.type = (typ,) + self.fr = fr + self.statut = statut + self.into = into + self.defaut = defaut + self.min = min + self.max = max + self.homo = homo + self.position = position + self.val_min = val_min + self.val_max = val_max + self.docu = docu + self.sug = sug + self.ang=ang + + def verif_cata(self): + """ + Cette methode sert à valider les attributs de l'objet de définition + de la classe SIMP + """ + self.check_min_max() + self.check_fr() + self.check_statut() + self.check_homo() + self.check_into() + self.check_position() + self.check_validators() + + def __call__(self, val, nom, parent=None): + """ + Construit un objet mot cle simple (MCSIMP) a partir de sa definition (self) + de sa valeur (val), de son nom (nom) et de son parent dans l arboresence (parent) + """ + return self.class_instance(nom=nom, definition=self, val=val, parent=parent) diff --git a/Noyau/N_VALIDATOR.py b/Noyau/N_VALIDATOR.py index a39c7ef3..aee9cc88 100644 --- a/Noyau/N_VALIDATOR.py +++ b/Noyau/N_VALIDATOR.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient toutes les classes necessaires pour implanter le concept de validateur dans Accas @@ -25,24 +25,29 @@ import types import traceback import re from N_ASSD import ASSD -from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_enum -from strfunc import convert -from Extensions.i18n import tr +from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence +from strfunc import convert, ufmt + + +class ValError(Exception): + pass -class ValError(Exception):pass def cls_mro(cls): - if hasattr(cls,"__mro__"):return cls.__mro__ - mro=[cls] + if hasattr(cls, "__mro__"): + return cls.__mro__ + mro = [cls] for base in cls.__bases__: mro.extend(cls_mro(base)) return mro + class Protocol: - def __init__(self,name): + + def __init__(self, name): self.registry = {} self.name = name - self.args={} + self.args = {} def register(self, T, A): self.registry[T] = A @@ -51,39 +56,47 @@ class Protocol: # (a) verifier si l'objet peut s'adapter au protocole adapt = getattr(obj, '__adapt__', None) if adapt is not None: - # on demande à l'objet obj de réaliser lui-meme l'adaptation + # on demande à l'objet obj de réaliser lui-meme l'adaptation return adapt(self) - # (b) verifier si un adapteur est enregistré (si oui l'utiliser) + # (b) verifier si un adapteur est enregistré (si oui l'utiliser) if self.registry: for T in cls_mro(obj.__class__): if T in self.registry: - return self.registry[T](obj,self,**self.args) + return self.registry[T](obj, self, **self.args) # (c) utiliser l'adapteur par defaut - return self.default(obj,**self.args) + return self.default(obj, **self.args) - def default(self,obj,**args): + def default(self, obj, **args): raise TypeError("Can't adapt %s to %s" % (obj.__class__.__name__, self.name)) + class PProtocol(Protocol): - """Verificateur de protocole paramétré (classe de base)""" - #Protocole paramétré. Le registre est unique pour toutes les instances. La methode register est une methode de classe - registry={} - def __init__(self,name,**args): + + """Verificateur de protocole paramétré (classe de base)""" + # Protocole paramétré. Le registre est unique pour toutes les instances. + # La methode register est une methode de classe + registry = {} + + def __init__(self, name, **args): self.name = name - self.args=args + self.args = args + def register(cls, T, A): cls.registry[T] = A - register=classmethod(register) + register = classmethod(register) + class ListProtocol(Protocol): - """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure""" - def default(self,obj): + + """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure""" + + def default(self, obj): if type(obj) is tuple: - if len(obj) > 0 and obj[0] in ('RI','MP'): - #il s'agit d'un complexe ancienne mode. La cardinalite vaut 1 + if len(obj) > 0 and obj[0] in ('RI', 'MP'): + # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1 return (obj,) else: return obj @@ -93,84 +106,96 @@ class ListProtocol(Protocol): # pas de valeur affecte. La cardinalite vaut 0 return obj elif is_str(obj): - #il s'agit d'une chaine. La cardinalite vaut 1 + # il s'agit d'une chaine. La cardinalite vaut 1 return (obj,) else: try: # si l'objet supporte len, on a la cardinalite - length=len(obj) + length = len(obj) return obj except: # sinon elle vaut 1 return (obj,) -listProto=ListProtocol("list") +listProto = ListProtocol("list") class TypeProtocol(PProtocol): + """Verificateur de type parmi une liste de types possibles""" - #pas de registre par instance. Registre unique pour toutes les instances de TypeProtocol - registry={} - def __init__(self,name,typ=None): - PProtocol.__init__(self,name,typ=typ) - self.typ=typ + # pas de registre par instance. Registre unique pour toutes les instances + # de TypeProtocol + registry = {} + + def __init__(self, name, typ=None): + PProtocol.__init__(self, name, typ=typ) + self.typ = typ - def default(self,obj,typ): + def default(self, obj, typ): err = "" for type_permis in typ: if type_permis == 'R': - if is_float_or_int(obj): return obj + if is_float_or_int(obj): + return obj elif type_permis == 'I': - if is_int(obj): return obj + if is_int(obj): + return obj elif type_permis == 'C': - if self.is_complexe(obj): return obj + if self.is_complexe(obj): + return obj elif type_permis == 'TXM': - if is_str(obj): return obj + if is_str(obj): + return obj elif type_permis == 'shell': - if is_str(obj): return obj - elif type_permis == 'Fichier' : - import os - if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj): - return obj - #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj))) - else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide")) - elif type_permis == 'FichierNoAbs' : - import os - if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")): - return obj - #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj))) - else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide")) + if is_str(obj): + return obj + elif type_permis == 'Fichier': + import os + if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj): + return obj + else: + raise ValError( + ufmt(_(u"%s n'est pas un fichier valide"), repr(obj))) + elif type_permis == 'FichierNoAbs': + import os + if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")): + return obj + else: + raise ValError( + ufmt(_(u"%s n'est pas un fichier valide"), repr(obj))) elif type_permis == 'Repertoire': import os if os.path.isdir(obj): return obj else: - #raise ValError(ufmt(_(u"%s n'est pas un répertoire valide"), repr(obj))) - raise ValError(repr(obj)+tr(" n'est pas un repertoire valide")) - elif type(type_permis) == types.ClassType or isinstance(type_permis,type): + raise ValError( + ufmt(_(u"%s n'est pas un répertoire valide"), repr(obj))) + elif type(type_permis) == types.ClassType or isinstance(type_permis, type): try: - if self.is_object_from(obj,type_permis): return obj + if self.is_object_from(obj, type_permis): + return obj except Exception, err: pass - elif type(type_permis) == types.InstanceType or isinstance(type_permis,object): + elif type(type_permis) == types.InstanceType or isinstance(type_permis, object): try: - if type_permis.__convert__(obj): return obj + if type_permis.__convert__(obj): + return obj except Exception, err: pass else: - #print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`)) - print tr("Type non encore gere "), `type_permis` - #raise ValError(ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"), - #repr(obj), type(obj), typ, unicode(err))) - raise ValError(repr(obj) +tr("de type ") + repr(type(obj)) + tr (" n'est pas d'un type autorise: ")+ str(typ) + " " + unicode(err)) + print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`)) + raise ValError( + ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"), + repr(obj), type(obj), typ, unicode(err))) - def is_complexe(self,valeur): + def is_complexe(self, valeur): """ Retourne 1 si valeur est un complexe, 0 sinon """ if is_number(valeur): - # Pour permettre l'utilisation de complexes Python (accepte les entiers et réels) + # Pour permettre l'utilisation de complexes Python (accepte les + # entiers et réels) return 1 - elif type(valeur) != tuple : + elif type(valeur) != tuple: # On n'autorise pas les listes pour les complexes return 0 elif len(valeur) != 3: @@ -178,16 +203,16 @@ class TypeProtocol(PProtocol): else: # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere # valeur suivie de 2 reels. - if valeur[0].strip() in ('RI','MP'): + if valeur[0].strip() in ('RI', 'MP'): try: - v1=reelProto.adapt(valeur[1]),reelProto.adapt(valeur[2]) + v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2]) return 1 except: return 0 else: return 0 - def is_object_from(self,objet,classe): + def is_object_from(self, objet, classe): """ Retourne 1 si objet est une instance de la classe classe, 0 sinon """ @@ -195,1005 +220,1063 @@ class TypeProtocol(PProtocol): if convert is not None: # classe verifie les valeurs try: - v= convert(objet) + v = convert(objet) return v is not None except ValueError, err: raise except: return 0 # On accepte les instances de la classe et des classes derivees - return isinstance(objet,classe) + return isinstance(objet, classe) + +reelProto = TypeProtocol("reel", typ=('R',)) -reelProto=TypeProtocol("reel",typ=('R',)) class CardProtocol(PProtocol): - """Verificateur de cardinalité """ - #pas de registre par instance. Registre unique pour toutes les instances - registry={} - def __init__(self,name,min=1,max=1): - PProtocol.__init__(self,name,min=min,max=max) - - def default(self,obj,min,max): - length=len(obj) - if length < min or length >max: - #raise ValError(ufmt(_(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)"), - # repr(obj), min, max)) - raise ValError(tr("Nombre incorrect d'arguments de ")+repr(obj)+"min = "+repr(min)+" max ="+repr(max)) + + """Verificateur de cardinalité """ + # pas de registre par instance. Registre unique pour toutes les instances + registry = {} + + def __init__(self, name, min=1, max=1): + PProtocol.__init__(self, name, min=min, max=max) + + def default(self, obj, min, max): + length = len(obj) + if length < min or length > max: + raise ValError( + ufmt( + _(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)"), + repr(obj), min, max)) return obj + class IntoProtocol(PProtocol): - """Verificateur de choix possibles : liste discrète ou intervalle""" - #pas de registre par instance. Registre unique pour toutes les instances - registry={} - def __init__(self,name,into=None,val_min='**',val_max='**'): - PProtocol.__init__(self,name,into=into,val_min=val_min,val_max=val_max) - self.val_min=val_min - self.val_max=val_max - - def default(self,obj,into,val_min,val_max): + + """Verificateur de choix possibles : liste discrète ou intervalle""" + # pas de registre par instance. Registre unique pour toutes les instances + registry = {} + + def __init__(self, name, into=None, val_min='**', val_max='**'): + PProtocol.__init__( + self, name, into=into, val_min=val_min, val_max=val_max) + self.val_min = val_min + self.val_max = val_max + + def default(self, obj, into, val_min, val_max): if into: if obj not in into: - #raise ValError(ufmt(_(u"La valeur : %s ne fait pas partie des choix possibles %s"), - # repr(obj), into)) - raise ValError(tr("La valeur :") +repr(obj)+ tr(" ne fait pas partie des choix possibles ") + repr(into)) + raise ValError( + ufmt( + _(u"La valeur : %s ne fait pas partie des choix possibles %s"), + repr(obj), into)) else: - #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle) + # on est dans le cas d'un ensemble continu de valeurs possibles + # (intervalle) if is_float_or_int(obj): - if val_min == '**': val_min = obj -1 - if val_max == '**': val_max = obj +1 - if obj < val_min or obj > val_max : - #raise ValError(ufmt(_(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]"), - # repr(obj), self.val_min, self.val_max)) - raise ValError(tr("La valeur :") +repr(obj)+ tr(" est en dehors du domaine de validite [ ") + repr(self.val_min) + "," + repr(self.val_max) + "]") + if val_min == '**': + val_min = obj - 1 + if val_max == '**': + val_max = obj + 1 + if obj < val_min or obj > val_max: + raise ValError( + ufmt( + _(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]"), + repr(obj), self.val_min, self.val_max)) return obj + class MinStr: - #exemple de classe pour verificateur de type - #on utilise des instances de classe comme type (typ=MinStr(3,6), par exemple) - def __init__(self,min,max): - self.min=min - self.max=max - - def __convert__(self,valeur): - if is_str(valeur) and self.min <= len(valeur) <= self.max:return valeur - raise ValError(ufmt(_(u"%s n'est pas une chaine de longueur comprise entre %s et %s"), - valeur, self.min, self.max)) - raise ValError(valeur + tr(" n'est pas une chaine de longueur comprise entre ") + repr(self.min) + " et " + repr(self.max)) + # exemple de classe pour verificateur de type + # on utilise des instances de classe comme type (typ=MinStr(3,6), par + # exemple) + + def __init__(self, min, max): + self.min = min + self.max = max + + def __convert__(self, valeur): + if is_str(valeur) and self.min <= len(valeur) <= self.max: + return valeur + raise ValError( + ufmt( + _(u"%s n'est pas une chaine de longueur comprise entre %s et %s"), + valeur, self.min, self.max)) def __repr__(self): - #return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max) - return tr(" TXM de longueur entre ")+ repr(self.min) + " et " + repr(self.max) + return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max) + class Valid(PProtocol): - """ - Cette classe est la classe mere des validateurs Accas - Elle doit etre derivee - Elle presente la signature des methodes indispensables pour son bon - fonctionnement et dans certains cas leur comportement par défaut. - - @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme - @type cata_info: C{string} - """ - registry={} - def __init__(self,**args): - PProtocol.__init__(self,"valid",**args) - - def info(self): - """ - Cette methode retourne une chaine de caractères informative sur - la validation demandée par le validateur. Elle est utilisée - pour produire le compte-rendu de validité du mot clé associé. - """ - #return _(u"valeur valide") - return tr("valeur valide") - - def aide(self): - """ - Cette methode retourne une chaine de caractère qui permet - de construire un message d'aide en ligne. - En général, le message retourné est le meme que celui retourné par la - méthode info. - """ - return self.info() - - def info_erreur_item(self): - """ - Cette méthode permet d'avoir un message d'erreur pour un item - dans une liste dans le cas ou le validateur fait des vérifications - sur les items d'une liste. Si le validateur fait seulement des - vérifications sur la liste elle meme et non sur ses items, la méthode - doit retourner une chaine vide. - """ - return " " - - def info_erreur_liste(self): - """ - Cette méthode a un comportement complémentaire de celui de - info_erreur_item. Elle retourne un message d'erreur lié uniquement - aux vérifications sur la liste elle meme et pas sur ses items. - Dans le cas où le validateur ne fait pas de vérification sur des - listes, elle retourne une chaine vide - """ - return " " - - def verif(self,valeur): - """ - Cette methode sert a verifier si la valeur passee en argument est consideree - comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1 - (valide) sinon 0 (invalide). - - @type valeur: tout type python - @param valeur: valeur du mot cle a valider - @rtype: C{boolean} - @return: indicateur de validite 1 (valide) ou 0 (invalide) - """ - raise NotImplementedError("Must be implemented") - - def verif_item(self,valeur): - """ - La methode verif du validateur effectue une validation complete de - la valeur. valeur peut etre un scalaire ou une liste. Le validateur - doit traiter les 2 aspects s'il accepte des listes (dans ce cas la - methode is_list doit retourner 1). - La methode valid_item sert pour effectuer des validations partielles - de liste. Elle doit uniquement verifier la validite d'un item de - liste mais pas les caracteristiques de la liste. - """ - return 0 - - def valide_liste_partielle(self,liste_courante): - """ - Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1) - ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on - veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée - comme invalide. - En général un validateur effectue la meme validation pour les listes partielles et les - listes complètes. - """ - return self.verif(liste_courante) - - def verif_cata(self): - """ - Cette methode sert a realiser des verifications du validateur lui meme. - Elle est facultative et retourne 1 (valide) par defaut. - Elle retourne 0 si le validateur est lui meme invalide si par exemple ses - parametres de definition ne sont pas corrects. - La raison de l'invalidite est stockee dans l'attribut cata_info. - - @rtype: C{boolean} - @return: indicateur de validite 1 (valide) ou 0 (invalide) - """ - return 1 - - def is_list(self): - """ - Cette méthode retourne un entier qui indique si le validateur - permet les listes (valeur 1) ou ne les permet pas (valeur 0). - Par défaut, un validateur n'autorise que des scalaires. - """ - return 0 - - def has_into(self): - """ - Cette méthode retourne un entier qui indique si le validateur - propose une liste de choix (valeur 1) ou n'en propose pas. - Par défaut, un validateur n'en propose pas. - """ - return 0 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Cette méthode retourne la liste de choix proposée par le validateur. - Si le validateur ne propose pas de liste de choix, la méthode - retourne None. - L'argument d'entrée liste_courante, s'il est différent de None, donne - la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la - méthode get_into doit calculer la liste des choix en en tenant - compte. Par exemple, si le validateur n'autorise pas les répétitions, - la liste des choix retournée ne doit pas contenir les choix déjà - contenus dans liste_courante. - L'argument d'entrée into_courant, s'il est différent de None, donne - la liste des choix proposés par d'autres validateurs. Dans ce cas, - la méthode get_into doit calculer la liste des choix à retourner - en se limitant à cette liste initiale. Par exemple, si into_courant - vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5), - la méthode ne doit retourner que (3,). - - La méthode get_into peut retourner une liste vide [], ce qui veut - dire qu'il n'y a pas (ou plus) de choix possible. Cette situation - peut etre normale : l''utilisateur a utilisé tous les choix, ou - résulter d'une incohérence des validateurs : - choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de - faire la différence entre ces deux situations. - """ - return into_courant + + """ + Cette classe est la classe mere des validateurs Accas + Elle doit etre derivee + Elle presente la signature des methodes indispensables pour son bon + fonctionnement et dans certains cas leur comportement par défaut. + + @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme + @type cata_info: C{string} + """ + registry = {} + + def __init__(self, **args): + PProtocol.__init__(self, "valid", **args) + + def info(self): + """ + Cette methode retourne une chaine de caractères informative sur + la validation demandée par le validateur. Elle est utilisée + pour produire le compte-rendu de validité du mot clé associé. + """ + return _(u"valeur valide") + + def aide(self): + """ + Cette methode retourne une chaine de caractère qui permet + de construire un message d'aide en ligne. + En général, le message retourné est le meme que celui retourné par la + méthode info. + """ + return self.info() + + def info_erreur_item(self): + """ + Cette méthode permet d'avoir un message d'erreur pour un item + dans une liste dans le cas ou le validateur fait des vérifications + sur les items d'une liste. Si le validateur fait seulement des + vérifications sur la liste elle meme et non sur ses items, la méthode + doit retourner une chaine vide. + """ + return " " + + def info_erreur_liste(self): + """ + Cette méthode a un comportement complémentaire de celui de + info_erreur_item. Elle retourne un message d'erreur lié uniquement + aux vérifications sur la liste elle meme et pas sur ses items. + Dans le cas où le validateur ne fait pas de vérification sur des + listes, elle retourne une chaine vide + """ + return " " + + def verif(self, valeur): + """ + Cette methode sert a verifier si la valeur passee en argument est consideree + comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1 + (valide) sinon 0 (invalide). + + @type valeur: tout type python + @param valeur: valeur du mot cle a valider + @rtype: C{boolean} + @return: indicateur de validite 1 (valide) ou 0 (invalide) + """ + raise NotImplementedError("Must be implemented") + + def verif_item(self, valeur): + """ + La methode verif du validateur effectue une validation complete de + la valeur. valeur peut etre un scalaire ou une liste. Le validateur + doit traiter les 2 aspects s'il accepte des listes (dans ce cas la + methode is_list doit retourner 1). + La methode valid_item sert pour effectuer des validations partielles + de liste. Elle doit uniquement verifier la validite d'un item de + liste mais pas les caracteristiques de la liste. + """ + return 0 + + def valide_liste_partielle(self, liste_courante): + """ + Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1) + ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on + veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée + comme invalide. + En général un validateur effectue la meme validation pour les listes partielles et les + listes complètes. + """ + return self.verif(liste_courante) + + def verif_cata(self): + """ + Cette methode sert a realiser des verifications du validateur lui meme. + Elle est facultative et retourne 1 (valide) par defaut. + Elle retourne 0 si le validateur est lui meme invalide si par exemple ses + parametres de definition ne sont pas corrects. + La raison de l'invalidite est stockee dans l'attribut cata_info. + + @rtype: C{boolean} + @return: indicateur de validite 1 (valide) ou 0 (invalide) + """ + return 1 + + def is_list(self): + """ + Cette méthode retourne un entier qui indique si le validateur + permet les listes (valeur 1) ou ne les permet pas (valeur 0). + Par défaut, un validateur n'autorise que des scalaires. + """ + return 0 + + def has_into(self): + """ + Cette méthode retourne un entier qui indique si le validateur + propose une liste de choix (valeur 1) ou n'en propose pas. + Par défaut, un validateur n'en propose pas. + """ + return 0 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Cette méthode retourne la liste de choix proposée par le validateur. + Si le validateur ne propose pas de liste de choix, la méthode + retourne None. + L'argument d'entrée liste_courante, s'il est différent de None, donne + la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la + méthode get_into doit calculer la liste des choix en en tenant + compte. Par exemple, si le validateur n'autorise pas les répétitions, + la liste des choix retournée ne doit pas contenir les choix déjà + contenus dans liste_courante. + L'argument d'entrée into_courant, s'il est différent de None, donne + la liste des choix proposés par d'autres validateurs. Dans ce cas, + la méthode get_into doit calculer la liste des choix à retourner + en se limitant à cette liste initiale. Par exemple, si into_courant + vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5), + la méthode ne doit retourner que (3,). + + La méthode get_into peut retourner une liste vide [], ce qui veut + dire qu'il n'y a pas (ou plus) de choix possible. Cette situation + peut etre normale : l''utilisateur a utilisé tous les choix, ou + résulter d'une incohérence des validateurs : + choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de + faire la différence entre ces deux situations. + """ + return into_courant + class ListVal(Valid): - """ - Cette classe sert de classe mère pour tous les validateurs qui acceptent - des listes. - """ - def is_list(self): - return 1 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Cette méthode get_into effectue un traitement général qui consiste - a filtrer la liste de choix into_courant, si elle existe, en ne - conservant que les valeurs valides (appel de la méthode valid). - """ - if into_courant is None: - return None - else: - liste_choix=[] - for e in into_courant: - if self.verif(e): - liste_choix.append(e) - return liste_choix - - def convert(self,valeur): - """ - Méthode convert pour les validateurs de listes. Cette méthode - fait appel à la méthode convert_item sur chaque élément de la - liste. - """ - if is_enum(valeur): - for val in valeur: - self.convert_item(val) - return valeur - else: - return self.convert_item(valeur) - - def verif(self,valeur): - """ - Méthode verif pour les validateurs de listes. Cette méthode - fait appel à la méthode verif_item sur chaque élément de la - liste. Si valeur est un paramètre, on utilise sa valeur effective - valeur.valeur. - """ - if is_enum(valeur): - for val in valeur: - if not self.verif_item(val): - return 0 - return 1 - else: - return self.verif_item(valeur) + + """ + Cette classe sert de classe mère pour tous les validateurs qui acceptent + des listes. + """ + + def is_list(self): + return 1 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Cette méthode get_into effectue un traitement général qui consiste + a filtrer la liste de choix into_courant, si elle existe, en ne + conservant que les valeurs valides (appel de la méthode valid). + """ + if into_courant is None: + return None + else: + liste_choix = [] + for e in into_courant: + if self.verif(e): + liste_choix.append(e) + return liste_choix + + def convert(self, valeur): + """ + Méthode convert pour les validateurs de listes. Cette méthode + fait appel à la méthode convert_item sur chaque élément de la + liste. + """ + if is_sequence(valeur): + for val in valeur: + self.convert_item(val) + return valeur + else: + return self.convert_item(valeur) + + def verif(self, valeur): + """ + Méthode verif pour les validateurs de listes. Cette méthode + fait appel à la méthode verif_item sur chaque élément de la + liste. Si valeur est un paramètre, on utilise sa valeur effective + valeur.valeur. + """ + if is_sequence(valeur): + for val in valeur: + if not self.verif_item(val): + return 0 + return 1 + else: + return self.verif_item(valeur) + class Compulsory(ListVal): - """ - Validateur operationnel - Verification de la présence obligatoire d'un élément dans une liste - """ - registry={} - def __init__(self,elem=()): - if not is_enum(elem): elem=(elem,) - Valid.__init__(self,elem=elem) - self.elem=elem - self.cata_info="" - - def info(self): - #return ufmt(_(u"valeur %s obligatoire"), `self.elem`) - return tr("valeur obligatoire") - - def default(self,valeur,elem): - return valeur - - def verif_item(self,valeur): - return 1 - - def convert(self,valeur): - elem=list(self.elem) - for val in valeur: - v=self.adapt(val) - if v in elem:elem.remove(v) - if elem: - #raise ValError(ufmt(_(u"%s ne contient pas les elements obligatoires : %s "), - # valeur, elem)) - raise ValError(valeur + tr(" ne contient pas les elements obligatoires : ")+ elem) - return valeur - - def has_into(self): - return 1 - - def verif(self,valeur): - if not is_enum(valeur): - liste=list(valeur) - else: - liste=valeur - for val in self.elem : - if val not in liste : return 0 - return 1 - - def info_erreur_item(self): - #return _(u"La valeur n'est pas dans la liste des choix possibles") - return tr("La valeur n'est pas dans la liste des choix possibles") + + """ + Validateur operationnel + Verification de la présence obligatoire d'un élément dans une liste + """ + registry = {} + + def __init__(self, elem=()): + if not is_sequence(elem): + elem = (elem,) + Valid.__init__(self, elem=elem) + self.elem = elem + self.cata_info = "" + + def info(self): + return ufmt(_(u"valeur %s obligatoire"), `self.elem`) + + def default(self, valeur, elem): + return valeur + + def verif_item(self, valeur): + return 1 + + def convert(self, valeur): + elem = list(self.elem) + for val in valeur: + v = self.adapt(val) + if v in elem: + elem.remove(v) + if elem: + raise ValError( + ufmt(_(u"%s ne contient pas les elements obligatoires : %s "), + valeur, elem)) + return valeur + + def has_into(self): + return 1 + + def verif(self, valeur): + if not is_sequence(valeur): + liste = list(valeur) + else: + liste = valeur + for val in self.elem: + if val not in liste: + return 0 + return 1 + + def info_erreur_item(self): + return _(u"La valeur n'est pas dans la liste des choix possibles") + class NoRepeat(ListVal): - """ - Validateur operationnel - Verification d'absence de doublons dans la liste. - """ - def __init__(self): - Valid.__init__(self) - self.cata_info="" - - def info(self): - #return _(u": pas de présence de doublon dans la liste") - return tr(": pas de presence de doublon dans la liste") - - def info_erreur_liste(self): - #return _(u"Les doublons ne sont pas permis") - return tr("Les doublons ne sont pas permis") - - def default(self,valeur): - if valeur in self.liste : - #raise ValError(ufmt(_(u"%s est un doublon"), valeur)) - raise ValError(repr(valeur) + tr(" est un doublon")) - return valeur - - def convert(self,valeur): - self.liste=[] - for val in valeur: - v=self.adapt(val) - self.liste.append(v) - return valeur - - def verif_item(self,valeur): - return 1 - - def verif(self,valeur): - if is_enum(valeur): - liste=list(valeur) - for val in liste: - if liste.count(val)!=1 : return 0 - return 1 - else: - return 1 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Methode get_into spécifique pour validateur NoRepeat, on retourne - une liste de choix qui ne contient aucune valeur de into_courant - déjà contenue dans liste_courante - """ - if into_courant is None: - liste_choix=None - else: - liste_choix=[] - for e in into_courant: - if e in liste_choix: continue - if liste_courante is not None and e in liste_courante: continue - liste_choix.append(e) - return liste_choix + + """ + Validateur operationnel + Verification d'absence de doublons dans la liste. + """ + + def __init__(self): + Valid.__init__(self) + self.cata_info = "" + + def info(self): + return _(u": pas de présence de doublon dans la liste") + + def info_erreur_liste(self): + return _(u"Les doublons ne sont pas permis") + + def default(self, valeur): + if valeur in self.liste: + raise ValError(ufmt(_(u"%s est un doublon"), valeur)) + return valeur + + def convert(self, valeur): + self.liste = [] + for val in valeur: + v = self.adapt(val) + self.liste.append(v) + return valeur + + def verif_item(self, valeur): + return 1 + + def verif(self, valeur): + if is_sequence(valeur): + liste = list(valeur) + for val in liste: + if liste.count(val) != 1: + return 0 + return 1 + else: + return 1 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Methode get_into spécifique pour validateur NoRepeat, on retourne + une liste de choix qui ne contient aucune valeur de into_courant + déjà contenue dans liste_courante + """ + if into_courant is None: + liste_choix = None + else: + liste_choix = [] + for e in into_courant: + if e in liste_choix: + continue + if liste_courante is not None and e in liste_courante: + continue + liste_choix.append(e) + return liste_choix + class LongStr(ListVal): - """ - Validateur operationnel - Verification de la longueur d une chaine - """ - def __init__(self,low,high): - ListVal.__init__(self,low=low,high=high) - self.low=low - self.high=high - self.cata_info="" - - def info(self): - #return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high) - return tr("longueur de la chaine entre")+ self.low + tr(" et ")+ self.high - - def info_erreur_item(self): - #return _(u"Longueur de la chaine incorrecte") - return tr("Longueur de la chaine incorrecte") - - def convert(self,valeur): - for val in valeur: - v=self.adapt(val) - return valeur - - def verif_item(self,valeur): - try: - self.adapt(valeur) - return 1 - except: - return 0 - - def default(self,valeur,low,high): - if not is_str(valeur): - #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur))) - raise ValError( repr(valeur) + tr(" n'est pas une chaine")) - if valeur[0]=="'" and valeur[-1]=="'" : - low=low+2 - high=high+2 - if len(valeur) < low or len(valeur) > high : - #raise ValError(ufmt(_(u"%s n'est pas de la bonne longueur"), repr(valeur))) - raise ValError( repr(valeur) + tr(" n'est pas de la bonne longueur")) - return valeur + + """ + Validateur operationnel + Verification de la longueur d une chaine + """ + + def __init__(self, low, high): + ListVal.__init__(self, low=low, high=high) + self.low = low + self.high = high + self.cata_info = "" + + def info(self): + return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high) + + def info_erreur_item(self): + return _(u"Longueur de la chaine incorrecte") + + def convert(self, valeur): + for val in valeur: + v = self.adapt(val) + return valeur + + def verif_item(self, valeur): + try: + self.adapt(valeur) + return 1 + except: + return 0 + + def default(self, valeur, low, high): + if not is_str(valeur): + raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur))) + if valeur[0] == "'" and valeur[-1] == "'": + low = low + 2 + high = high + 2 + if len(valeur) < low or len(valeur) > high: + raise ValError( + ufmt(_(u"%s n'est pas de la bonne longueur"), repr(valeur))) + return valeur + class OnlyStr(ListVal): - """ - Validateur operationnel - Valide que c'est une chaine - """ - def __init__(self): - ListVal.__init__(self) - self.cata_info="" - - def info(self): - #return _(u"regarde si c'est une chaine") - return tr("verifier que c'est une chaine") - - def info_erreur_item(self): - #return _(u"Ce n'est pas une chaine") - return tr("Ce n'est pas une chaine") - - def convert(self,valeur): - for val in valeur: - v=self.adapt(val) - return valeur - - def verif_item(self,valeur): - try: - self.adapt(valeur) - return 1 - except: - return 0 - - def default(self,valeur): - if not is_str(valeur): - #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur))) - raise ValError(repr(valeur) + tr(" n'est pas une chaine")) - return valeur + + """ + Validateur operationnel + Valide que c'est une chaine + """ + + def __init__(self): + ListVal.__init__(self) + self.cata_info = "" + + def info(self): + return _(u"regarde si c'est une chaine") + + def info_erreur_item(self): + return _(u"Ce n'est pas une chaine") + + def convert(self, valeur): + for val in valeur: + v = self.adapt(val) + return valeur + + def verif_item(self, valeur): + try: + self.adapt(valeur) + return 1 + except: + return 0 + + def default(self, valeur): + if not is_str(valeur): + raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur))) + return valeur + class OrdList(ListVal): - """ - Validateur operationnel - Verification qu'une liste est croissante ou decroissante - """ - def __init__(self,ord): - ListVal.__init__(self,ord=ord) - self.ord=ord - self.cata_info="" - - def info(self): - #return ufmt(_(u"liste %s"), self.ord) - return tr("liste ") + self.ord - - def info_erreur_liste(self) : - #return ufmt(_(u"La liste doit etre en ordre %s"), self.ord) - return tr("La liste doit etre en ordre ")+ self.ord - - def convert(self,valeur): - self.val=None - self.liste=valeur - for v in valeur: - self.adapt(v) - return valeur - - def default(self,valeur,ord): - if self.ord=='croissant': - if self.val is not None and valeur self.val: - #raise ValError(ufmt(_(u"%s n'est pas par valeurs decroissantes"), repr(self.liste))) - raise ValError(repr(self.liste) +tr(" n'est pas par valeurs decroissantes")) - self.val=valeur - return valeur - - def verif_item(self,valeur): - return 1 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Methode get_into spécifique pour validateur OrdList, on retourne - une liste de choix qui ne contient aucune valeur de into_courant - dont la valeur est inférieure à la dernière valeur de - liste_courante, si elle est différente de None. - """ - if into_courant is None: - return None - elif not liste_courante : - return into_courant - else: - liste_choix=[] - last_val=liste_choix[-1] - for e in into_courant: - if self.ord=='croissant' and e <= last_val:continue - if self.ord=='decroissant' and e >= last_val:continue - liste_choix.append(e) - return liste_choix + + """ + Validateur operationnel + Verification qu'une liste est croissante ou decroissante + """ + + def __init__(self, ord): + ListVal.__init__(self, ord=ord) + self.ord = ord + self.cata_info = "" + + def info(self): + return ufmt(_(u"liste %s"), self.ord) + + def info_erreur_liste(self): + return ufmt(_(u"La liste doit etre en ordre %s"), self.ord) + + def convert(self, valeur): + self.val = None + self.liste = valeur + for v in valeur: + self.adapt(v) + return valeur + + def default(self, valeur, ord): + if self.ord == 'croissant': + if self.val is not None and valeur < self.val: + raise ValError( + ufmt(_(u"%s n'est pas par valeurs croissantes"), repr(self.liste))) + elif self.ord == 'decroissant': + if self.val is not None and valeur > self.val: + raise ValError( + ufmt(_(u"%s n'est pas par valeurs decroissantes"), repr(self.liste))) + self.val = valeur + return valeur + + def verif_item(self, valeur): + return 1 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Methode get_into spécifique pour validateur OrdList, on retourne + une liste de choix qui ne contient aucune valeur de into_courant + dont la valeur est inférieure à la dernière valeur de + liste_courante, si elle est différente de None. + """ + if into_courant is None: + return None + elif not liste_courante: + return into_courant + else: + liste_choix = [] + last_val = liste_choix[-1] + for e in into_courant: + if self.ord == 'croissant' and e <= last_val: + continue + if self.ord == 'decroissant' and e >= last_val: + continue + liste_choix.append(e) + return liste_choix + class OrVal(Valid): - """ - Validateur operationnel - Cette classe est un validateur qui controle une liste de validateurs - Elle verifie qu'au moins un des validateurs de la liste valide la valeur - """ - def __init__(self,validators=()): - if not is_enum(validators): - validators=(validators,) - self.validators=[] - for validator in validators: - if type(validator) == types.FunctionType: - self.validators.append(FunctionVal(validator)) - else: - self.validators.append(validator) - self.cata_info="" - - def info(self): - return "\n ou ".join([v.info() for v in self.validators]) - - def convert(self,valeur): - for validator in self.validators: - try: - return validator.convert(valeur) - except: - pass - raise ValError(ufmt(_(u"%s n'est pas du bon type"), repr(valeur))) - raise ValError(repr(valeur) + tr(" n'est pas du bon type")) - - def info_erreur_item(self): - l=[] - for v in self.validators: - err=v.info_erreur_item() - if err != " " : l.append(err) - chaine=" \n ou ".join(l) - return chaine - - def info_erreur_liste(self): - l=[] - for v in self.validators: - err=v.info_erreur_liste() - if err != " " : l.append(err) - chaine=" \n ou ".join(l) - return chaine - - def is_list(self): - """ - Si plusieurs validateurs sont reliés par un OU - il suffit qu'un seul des validateurs attende une liste - pour qu'on considère que leur union attend une liste. - """ - for validator in self.validators: - v=validator.is_list() - if v : - return 1 - return 0 - - def verif(self,valeur): - for validator in self.validators: - v=validator.verif(valeur) - if v : - return 1 - return 0 - - def verif_item(self,valeur): - for validator in self.validators: - v=validator.verif_item(valeur) - if v : - return 1 - return 0 - - def verif_cata(self): - infos=[] - for validator in self.validators: - v=validator.verif_cata() - if not v :infos.append(validator.cata_info) - if infos: - self.cata_info="\n".join(infos) - return 0 - self.cata_info="" - return 1 - - def has_into(self): - """ - Dans le cas ou plusieurs validateurs sont reliés par un OU - il faut que tous les validateurs proposent un choix pour - qu'on considère que leur union propose un choix. - Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix - En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6) - """ - for validator in self.validators: - v=validator.has_into() - if not v : - return 0 - return 1 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Dans le cas ou plusieurs validateurs sont reliés par un OU - tous les validateurs doivent proposer un choix pour - qu'on considère que leur union propose un choix. Tous les choix - proposés par les validateurs sont réunis (opérateur d'union). - Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix - En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un - choix (1,2,3,4,5,6) - """ - validator_into=[] - for validator in self.validators: - v_into=validator.get_into(liste_courante,into_courant) - if v_into is None: - return v_into - validator_into.extend(v_into) - return validator_into - - def valide_liste_partielle(self,liste_courante=None): - """ - Méthode de validation de liste partielle pour le validateur Or. - Si un des validateurs gérés par le validateur Or considère la - liste comme valide, le validateur Or la considère comme valide. - """ - for validator in self.validators: - v=validator.valide_liste_partielle(liste_courante) - if v : - return 1 - return 0 + + """ + Validateur operationnel + Cette classe est un validateur qui controle une liste de validateurs + Elle verifie qu'au moins un des validateurs de la liste valide la valeur + """ + + def __init__(self, validators=()): + if not is_sequence(validators): + validators = (validators,) + self.validators = [] + for validator in validators: + if type(validator) == types.FunctionType: + self.validators.append(FunctionVal(validator)) + else: + self.validators.append(validator) + self.cata_info = "" + + def info(self): + return "\n ou ".join([v.info() for v in self.validators]) + + def convert(self, valeur): + for validator in self.validators: + try: + return validator.convert(valeur) + except: + pass + raise ValError(ufmt(_(u"%s n'est pas du bon type"), repr(valeur))) + + def info_erreur_item(self): + l = [] + for v in self.validators: + err = v.info_erreur_item() + if err != " ": + l.append(err) + chaine = " \n ou ".join(l) + return chaine + + def info_erreur_liste(self): + l = [] + for v in self.validators: + err = v.info_erreur_liste() + if err != " ": + l.append(err) + chaine = " \n ou ".join(l) + return chaine + + def is_list(self): + """ + Si plusieurs validateurs sont reliés par un OU + il suffit qu'un seul des validateurs attende une liste + pour qu'on considère que leur union attend une liste. + """ + for validator in self.validators: + v = validator.is_list() + if v: + return 1 + return 0 + + def verif(self, valeur): + for validator in self.validators: + v = validator.verif(valeur) + if v: + return 1 + return 0 + + def verif_item(self, valeur): + for validator in self.validators: + v = validator.verif_item(valeur) + if v: + return 1 + return 0 + + def verif_cata(self): + infos = [] + for validator in self.validators: + v = validator.verif_cata() + if not v: + infos.append(validator.cata_info) + if infos: + self.cata_info = "\n".join(infos) + return 0 + self.cata_info = "" + return 1 + + def has_into(self): + """ + Dans le cas ou plusieurs validateurs sont reliés par un OU + il faut que tous les validateurs proposent un choix pour + qu'on considère que leur union propose un choix. + Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix + En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6) + """ + for validator in self.validators: + v = validator.has_into() + if not v: + return 0 + return 1 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Dans le cas ou plusieurs validateurs sont reliés par un OU + tous les validateurs doivent proposer un choix pour + qu'on considère que leur union propose un choix. Tous les choix + proposés par les validateurs sont réunis (opérateur d'union). + Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix + En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un + choix (1,2,3,4,5,6) + """ + validator_into = [] + for validator in self.validators: + v_into = validator.get_into(liste_courante, into_courant) + if v_into is None: + return v_into + validator_into.extend(v_into) + return validator_into + + def valide_liste_partielle(self, liste_courante=None): + """ + Méthode de validation de liste partielle pour le validateur Or. + Si un des validateurs gérés par le validateur Or considère la + liste comme valide, le validateur Or la considère comme valide. + """ + for validator in self.validators: + v = validator.valide_liste_partielle(liste_courante) + if v: + return 1 + return 0 + class AndVal(Valid): - """ - Validateur operationnel - Cette classe est un validateur qui controle une liste de validateurs - Elle verifie que tous les validateurs de la liste valident la valeur - """ - def __init__(self,validators=()): - if not is_enum(validators): - validators=(validators,) - self.validators=[] - for validator in validators: - if type(validator) == types.FunctionType: - self.validators.append(FunctionVal(validator)) - else: - self.validators.append(validator) - if hasattr(validator,'fonctions'): - for fonction in validator.fonctions : - f=getattr(validator,fonction) - setattr(self,fonction,f) - self.cata_info="" - - def info(self): - return "\n et ".join([v.info() for v in self.validators]) - - def convert(self,valeur): - for validator in self.validators: - valeur=validator.convert(valeur) - return valeur - - def info_erreur_item(self): - chaine="" - a=1 - for v in self.validators: - if v.info_erreur_item() != " " : - if a==1: - chaine=v.info_erreur_item() - a=0 - else: - chaine=chaine+" \n et "+v.info_erreur_item() - return chaine - - def info_erreur_liste(self): - a=1 - for v in self.validators: - if v.info_erreur_liste() != " " : - if a==1: - chaine=v.info_erreur_liste() - a=0 - else: - chaine=chaine+" \n et "+v.info_erreur_liste() - return chaine - - def verif(self,valeur): - for validator in self.validators: - v=validator.verif(valeur) - if not v : - self.local_info=validator.info() - return 0 - return 1 - - def verif_item(self,valeur): - for validator in self.validators: - v=validator.verif_item(valeur) - if not v : - # L'info n'est probablement pas la meme que pour verif ??? - self.local_info=validator.info() - return 0 - return 1 - - def verif_cata(self): - infos=[] - for validator in self.validators: - v=validator.verif_cata() - if not v :infos.append(validator.cata_info) - if infos: - self.cata_info="\n".join(infos) - return 0 - self.cata_info="" - return 1 - - def valide_liste_partielle(self,liste_courante=None): - """ - Méthode de validation de liste partielle pour le validateur And. - Tous les validateurs gérés par le validateur And doivent considérer - la liste comme valide, pour que le validateur And la considère - comme valide. - """ - for validator in self.validators: - v=validator.valide_liste_partielle(liste_courante) - if not v : - return 0 - return 1 - - def is_list(self): - """ - Si plusieurs validateurs sont reliés par un ET - il faut que tous les validateurs attendent une liste - pour qu'on considère que leur intersection attende une liste. - Exemple Range(2,5) ET Card(1) n'attend pas une liste - Range(2,5) ET Pair attend une liste - """ - for validator in self.validators: - v=validator.is_list() - if v == 0 : - return 0 - return 1 - - def has_into(self): - """ - Dans le cas ou plusieurs validateurs sont reliés par un ET - il suffit qu'un seul validateur propose un choix pour - qu'on considère que leur intersection propose un choix. - Exemple : Enum(1,2,3) ET entier pair, propose un choix - En revanche, entier pair ET superieur à 10 ne propose pas de choix - """ - for validator in self.validators: - v=validator.has_into() - if v : - return 1 - return 0 - - def get_into(self,liste_courante=None,into_courant=None): - """ - Dans le cas ou plusieurs validateurs sont reliés par un ET - il suffit qu'un seul validateur propose un choix pour - qu'on considère que leur intersection propose un choix. Tous les - choix proposés par les validateurs sont croisés (opérateur - d'intersection) - Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,) - En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix. - """ - for validator in self.validators: - into_courant=validator.get_into(liste_courante,into_courant) - if into_courant in ([],None):break - return into_courant + + """ + Validateur operationnel + Cette classe est un validateur qui controle une liste de validateurs + Elle verifie que tous les validateurs de la liste valident la valeur + """ + + def __init__(self, validators=()): + if not is_sequence(validators): + validators = (validators,) + self.validators = [] + for validator in validators: + if type(validator) == types.FunctionType: + self.validators.append(FunctionVal(validator)) + else: + self.validators.append(validator) + if hasattr(validator, 'fonctions'): + for fonction in validator.fonctions: + f = getattr(validator, fonction) + setattr(self, fonction, f) + self.cata_info = "" + + def info(self): + return "\n et ".join([v.info() for v in self.validators]) + + def convert(self, valeur): + for validator in self.validators: + valeur = validator.convert(valeur) + return valeur + + def info_erreur_item(self): + chaine = "" + a = 1 + for v in self.validators: + if v.info_erreur_item() != " ": + if a == 1: + chaine = v.info_erreur_item() + a = 0 + else: + chaine = chaine + " \n et " + v.info_erreur_item() + return chaine + + def info_erreur_liste(self): + a = 1 + for v in self.validators: + if v.info_erreur_liste() != " ": + if a == 1: + chaine = v.info_erreur_liste() + a = 0 + else: + chaine = chaine + " \n et " + v.info_erreur_liste() + return chaine + + def verif(self, valeur): + for validator in self.validators: + v = validator.verif(valeur) + if not v: + self.local_info = validator.info() + return 0 + return 1 + + def verif_item(self, valeur): + for validator in self.validators: + v = validator.verif_item(valeur) + if not v: + # L'info n'est probablement pas la meme que pour verif ??? + self.local_info = validator.info() + return 0 + return 1 + + def verif_cata(self): + infos = [] + for validator in self.validators: + v = validator.verif_cata() + if not v: + infos.append(validator.cata_info) + if infos: + self.cata_info = "\n".join(infos) + return 0 + self.cata_info = "" + return 1 + + def valide_liste_partielle(self, liste_courante=None): + """ + Méthode de validation de liste partielle pour le validateur And. + Tous les validateurs gérés par le validateur And doivent considérer + la liste comme valide, pour que le validateur And la considère + comme valide. + """ + for validator in self.validators: + v = validator.valide_liste_partielle(liste_courante) + if not v: + return 0 + return 1 + + def is_list(self): + """ + Si plusieurs validateurs sont reliés par un ET + il faut que tous les validateurs attendent une liste + pour qu'on considère que leur intersection attende une liste. + Exemple Range(2,5) ET Card(1) n'attend pas une liste + Range(2,5) ET Pair attend une liste + """ + for validator in self.validators: + v = validator.is_list() + if v == 0: + return 0 + return 1 + + def has_into(self): + """ + Dans le cas ou plusieurs validateurs sont reliés par un ET + il suffit qu'un seul validateur propose un choix pour + qu'on considère que leur intersection propose un choix. + Exemple : Enum(1,2,3) ET entier pair, propose un choix + En revanche, entier pair ET superieur à 10 ne propose pas de choix + """ + for validator in self.validators: + v = validator.has_into() + if v: + return 1 + return 0 + + def get_into(self, liste_courante=None, into_courant=None): + """ + Dans le cas ou plusieurs validateurs sont reliés par un ET + il suffit qu'un seul validateur propose un choix pour + qu'on considère que leur intersection propose un choix. Tous les + choix proposés par les validateurs sont croisés (opérateur + d'intersection) + Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,) + En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix. + """ + for validator in self.validators: + into_courant = validator.get_into(liste_courante, into_courant) + if into_courant in ([], None): + break + return into_courant + def do_liste(validators): """ Convertit une arborescence de validateurs en OrVal ou AndVal validators est une liste de validateurs ou de listes ou de tuples """ - valids=[] + valids = [] for validator in validators: if type(validator) == types.FunctionType: - valids.append(FunctionVal(validator)) + valids.append(FunctionVal(validator)) elif type(validator) is tuple: - valids.append(OrVal(do_liste(validator))) + valids.append(OrVal(do_liste(validator))) elif type(validator) is list: - valids.append(AndVal(do_liste(validator))) + valids.append(AndVal(do_liste(validator))) else: - valids.append(validator) + valids.append(validator) return valids + def validatorFactory(validator): if type(validator) == types.FunctionType: - return FunctionVal(validator) + return FunctionVal(validator) elif type(validator) is tuple: - return OrVal(do_liste(validator)) + return OrVal(do_liste(validator)) elif type(validator) is list: - return AndVal(do_liste(validator)) + return AndVal(do_liste(validator)) else: - return validator + return validator + +# Ci-dessous : exemples de validateur (peu testés) -# Ci-dessous : exemples de validateur (peu testés) class RangeVal(ListVal): - """ - Exemple de classe validateur : verification qu'une valeur - est dans un intervalle. - Pour une liste on verifie que tous les elements sont - dans l'intervalle - Susceptible de remplacer les attributs "vale_min" "vale_max" - dans les catalogues - """ - def __init__(self,low,high): - self.low=low - self.high=high - #self.cata_info=ufmt(_(u"%s doit être inférieur a %s"), low,high) - self.cata_info=low + tr(" doit être inférieur a ")+ high - - def info(self): - #return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high) - return tr(" valeur dans l 'intervalle ")+self.low+ self.high - - def convert_item(self,valeur): - if valeur > self.low and valeur < self.high:return valeur - #raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"), - # valeur, self.low, self.high)) - raise ValError(valeur + tr(" devrait etre comprise entre ") + self.low + tr(" et ")+ self.high) - - def verif_item(self,valeur): - return valeur > self.low and valeur < self.high - - def info_erreur_item(self) : - #return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high) - return tr("La valeur doit etre comprise entre ") + self.low + tr(" et ") + self.high - - def verif_cata(self): - if self.low > self.high : return 0 - return 1 + + """ + Exemple de classe validateur : verification qu'une valeur + est dans un intervalle. + Pour une liste on verifie que tous les elements sont + dans l'intervalle + Susceptible de remplacer les attributs "vale_min" "vale_max" + dans les catalogues + """ + + def __init__(self, low, high): + self.low = low + self.high = high + self.cata_info = ufmt(_(u"%s doit être inférieur a %s"), low, high) + + def info(self): + return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high) + + def convert_item(self, valeur): + if valeur > self.low and valeur < self.high: + return valeur + raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"), + valeur, self.low, self.high)) + + def verif_item(self, valeur): + return valeur > self.low and valeur < self.high + + def info_erreur_item(self): + return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high) + + def verif_cata(self): + if self.low > self.high: + return 0 + return 1 + class CardVal(Valid): - """ - Exemple de classe validateur : verification qu'une liste est - d'une longueur superieur a un minimum (min) et inferieure - a un maximum (max). - Susceptible de remplacer les attributs "min" "max" dans les - catalogues - """ - def __init__(self,min='**',max='**'): - self.min=min - self.max=max - self.cata_info=min + tr(" doit etre inferieur a ")+ max - #self.cata_info= ufmt(_(u"%s doit etre inferieur a %s"), min,max) - - def info(self): - #return ufmt(_(u"longueur de liste comprise entre %s et %s"), self.min, self.max) - return tr("La longueur doit etre comprise entre ") + self.min + tr(" et ") + self.max - - def info_erreur_liste(self): - #return ufmt(_(u"Le cardinal de la liste doit etre compris entre %s et %s"), - # self.min, self.max) - return tr("Le cardinal de la liste doit etre compris entre ") + self.min + tr(" et ") + self.max - - def is_list(self): - return self.max == '**' or self.max > 1 - - def get_into(self,liste_courante=None,into_courant=None): - if into_courant is None: - return None - elif liste_courante is None: - return into_courant - elif self.max == '**': - return into_courant - elif len(liste_courante) < self.max: - return into_courant - else: - return [] - - def convert(self,valeur): - if is_enum(valeur): - l=len(valeur) - elif valeur is None: - l=0 - else: - l=1 - if self.max != '**' and l > self.max: - #raise ValError(ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max)) - raise ValError(valeur + tr(" devrait etre de longueur inferieure a ")+ self.min) - if self.min != '**' and l < self.min: - #raise ValError(ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min)) - raise ValError(valeur + tr(" devrait etre de longueur superieure a ")+ self.max) - return valeur - - def verif_item(self,valeur): - return 1 - - def verif(self,valeur): - if is_enum(valeur): - if self.max != '**' and len(valeur) > self.max:return 0 - if self.min != '**' and len(valeur) < self.min:return 0 - return 1 - else: - if self.max != '**' and 1 > self.max:return 0 - if self.min != '**' and 1 < self.min:return 0 - return 1 - - def verif_cata(self): - if self.min != '**' and self.max != '**' and self.min > self.max : return 0 - return 1 - - def valide_liste_partielle(self,liste_courante=None): - validite=1 - if liste_courante != None : - if len(liste_courante) > self.max : - validite=0 - return validite + + """ + Exemple de classe validateur : verification qu'une liste est + d'une longueur superieur a un minimum (min) et inferieure + a un maximum (max). + Susceptible de remplacer les attributs "min" "max" dans les + catalogues + """ + + def __init__(self, min='**', max='**'): + self.min = min + self.max = max + self.cata_info = ufmt(_(u"%s doit etre inferieur a %s"), min, max) + + def info(self): + return ufmt(_(u"longueur de liste comprise entre %s et %s"), self.min, self.max) + + def info_erreur_liste(self): + return ufmt( + _(u"Le cardinal de la liste doit etre compris entre %s et %s"), + self.min, self.max) + + def is_list(self): + return self.max == '**' or self.max > 1 + + def get_into(self, liste_courante=None, into_courant=None): + if into_courant is None: + return None + elif liste_courante is None: + return into_courant + elif self.max == '**': + return into_courant + elif len(liste_courante) < self.max: + return into_courant + else: + return [] + + def convert(self, valeur): + if is_sequence(valeur): + l = len(valeur) + elif valeur is None: + l = 0 + else: + l = 1 + if self.max != '**' and l > self.max: + raise ValError( + ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max)) + if self.min != '**' and l < self.min: + raise ValError( + ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min)) + return valeur + + def verif_item(self, valeur): + return 1 + + def verif(self, valeur): + if is_sequence(valeur): + if self.max != '**' and len(valeur) > self.max: + return 0 + if self.min != '**' and len(valeur) < self.min: + return 0 + return 1 + else: + if self.max != '**' and 1 > self.max: + return 0 + if self.min != '**' and 1 < self.min: + return 0 + return 1 + + def verif_cata(self): + if self.min != '**' and self.max != '**' and self.min > self.max: + return 0 + return 1 + + def valide_liste_partielle(self, liste_courante=None): + validite = 1 + if liste_courante != None: + if len(liste_courante) > self.max: + validite = 0 + return validite + class PairVal(ListVal): - """ - Exemple de classe validateur : verification qu'une valeur - est paire. - Pour une liste on verifie que tous les elements sont - pairs - """ - def __init__(self): - ListVal.__init__(self) - self.cata_info="" - - def info(self): - #return _(u"valeur paire") - return tr("valeur paire") - - def info_erreur_item(self): - #return _(u"La valeur saisie doit etre paire") - return tr("La valeur saisie doit etre paire") - - def convert(self,valeur): - for val in valeur: - v=self.adapt(val) - if v % 2 != 0: - #raise ValError(ufmt(_(u"%s contient des valeurs non paires"), repr(valeur))) - raise ValError(repr(valeur)+tr("contient des valeurs non paires")) - return valeur - - def default(self,valeur): - return valeur - - def verif_item(self,valeur): - if type(valeur) not in (int,long): - return 0 - return valeur % 2 == 0 - - def verif(self,valeur): - if is_enum(valeur): - for val in valeur: - if val % 2 != 0:return 0 - return 1 - else: - if valeur % 2 != 0:return 0 - return 1 + + """ + Exemple de classe validateur : verification qu'une valeur + est paire. + Pour une liste on verifie que tous les elements sont + pairs + """ + + def __init__(self): + ListVal.__init__(self) + self.cata_info = "" + + def info(self): + return _(u"valeur paire") + + def info_erreur_item(self): + return _(u"La valeur saisie doit etre paire") + + def convert(self, valeur): + for val in valeur: + v = self.adapt(val) + if v % 2 != 0: + raise ValError( + ufmt(_(u"%s contient des valeurs non paires"), repr(valeur))) + return valeur + + def default(self, valeur): + return valeur + + def verif_item(self, valeur): + if type(valeur) not in (int, long): + return 0 + return valeur % 2 == 0 + + def verif(self, valeur): + if is_sequence(valeur): + for val in valeur: + if val % 2 != 0: + return 0 + return 1 + else: + if valeur % 2 != 0: + return 0 + return 1 + class EnumVal(ListVal): - """ - Exemple de classe validateur : verification qu'une valeur - est prise dans une liste de valeurs. - Susceptible de remplacer l attribut "into" dans les catalogues - """ - def __init__(self,into=()): - if not is_enum(into): - into=(into,) - self.into=into - self.cata_info="" - - def info(self): - #return "valeur dans %s" % `self.into` - return tr("valeur dans") + self.into - - def convert_item(self,valeur): - if valeur in self.into:return valeur - #raise ValError(ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "), - # valeur, self.into)) - raise ValError(valeur + tr(" contient des valeurs hors des choix possibles: ")+ self.into) - - def verif_item(self,valeur): - if valeur not in self.into:return 0 - return 1 - - def has_into(self): - return 1 - - def get_into(self,liste_courante=None,into_courant=None): - if into_courant is None: - liste_choix= list(self.into) - else: - liste_choix=[] - for e in into_courant: - if e in self.into: + + """ + Exemple de classe validateur : verification qu'une valeur + est prise dans une liste de valeurs. + Susceptible de remplacer l attribut "into" dans les catalogues + """ + + def __init__(self, into=()): + if not is_sequence(into): + into = (into,) + self.into = into + self.cata_info = "" + + def info(self): + return "valeur dans %s" % `self.into` + + def convert_item(self, valeur): + if valeur in self.into: + return valeur + raise ValError( + ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "), + valeur, self.into)) + + def verif_item(self, valeur): + if valeur not in self.into: + return 0 + return 1 + + def has_into(self): + return 1 + + def get_into(self, liste_courante=None, into_courant=None): + if into_courant is None: + liste_choix = list(self.into) + else: + liste_choix = [] + for e in into_courant: + if e in self.into: liste_choix.append(e) - return liste_choix + return liste_choix + + def info_erreur_item(self): + return _(u"La valeur n'est pas dans la liste des choix possibles") - def info_erreur_item(self): - #return _(u"La valeur n'est pas dans la liste des choix possibles") - return tr("La valeur n'est pas dans la liste des choix possibles") def ImpairVal(valeur): """ @@ -1201,262 +1284,297 @@ def ImpairVal(valeur): Cette fonction est un validateur. Elle verifie que la valeur passee est bien un nombre impair. """ - if is_enum(valeur): - for val in valeur: - if val % 2 != 1:return 0 - return 1 + if is_sequence(valeur): + for val in valeur: + if val % 2 != 1: + return 0 + return 1 else: - if valeur % 2 != 1:return 0 - return 1 + if valeur % 2 != 1: + return 0 + return 1 + +ImpairVal.info = "valeur impaire" -ImpairVal.info="valeur impaire" class F1Val(Valid): - """ - Exemple de validateur - Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie - que la somme des cles A et B vaut une valeur donnee - en parametre du validateur - """ - def __init__(self,somme=10): - self.somme=somme - self.cata_info="" - - def info(self): - #return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme) - return tr("valeur") + repr(self.somme) + tr(" pour la somme des cles A et B ") - - def verif(self,valeur): - if is_enum(valeur): - for val in valeur: - if not val.has_key("A"):return 0 - if not val.has_key("B"):return 0 - if val["A"]+val["B"] != self.somme:return 0 - return 1 - else: - if not valeur.has_key("A"):return 0 - if not valeur.has_key("B"):return 0 - if valeur["A"]+valeur["B"] != self.somme:return 0 - return 1 + + """ + Exemple de validateur + Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie + que la somme des cles A et B vaut une valeur donnee + en parametre du validateur + """ + + def __init__(self, somme=10): + self.somme = somme + self.cata_info = "" + + def info(self): + return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme) + + def verif(self, valeur): + if is_sequence(valeur): + for val in valeur: + if not val.has_key("A"): + return 0 + if not val.has_key("B"): + return 0 + if val["A"] + val["B"] != self.somme: + return 0 + return 1 + else: + if not valeur.has_key("A"): + return 0 + if not valeur.has_key("B"): + return 0 + if valeur["A"] + valeur["B"] != self.somme: + return 0 + return 1 + class FunctionVal(Valid): - """ - Exemple de validateur - Cette classe est un validateur qui est initialise avec une fonction - """ - def __init__(self,function): - self.function=function - def info(self): - return self.function.info + """ + Exemple de validateur + Cette classe est un validateur qui est initialise avec une fonction + """ - def verif(self,valeur): - return self.function(valeur) + def __init__(self, function): + self.function = function + + def info(self): + return self.function.info + + def verif(self, valeur): + return self.function(valeur) + +# MC ca ne devrait plus servir ! +CoercableFuncs = {types.IntType: int, + types.LongType: long, + types.FloatType: float, + types.ComplexType: complex, + types.UnicodeType: unicode} -#MC ca ne devrait plus servir ! -CoercableFuncs = { types.IntType: int, - types.LongType: long, - types.FloatType: float, - types.ComplexType: complex, - types.UnicodeType: unicode } class TypeVal(ListVal): - """ - Exemple de validateur - Cette classe est un validateur qui controle qu'une valeur - est bien du type Python attendu. - Pour une liste on verifie que tous les elements sont du bon type. - Semblable a InstanceVal mais ici on fait le test par tentative de conversion - alors qu'avec InstanceVal on ne teste que si isinstance est vrai. - """ - def __init__(self, aType): - #Si aType n'est pas un type, on le retrouve a l'aide de la fonction type - #type(1) == int;type(0.2)==float;etc. - if type(aType) != types.TypeType: - aType=type(aType) - self.aType=aType - try: - self.coerce=CoercableFuncs[ aType ] - except: - self.coerce = self.identity - - def info(self): - #return ufmt(_(u"valeur de %s"), self.aType) - return tr("valeur de ")+ self.aType - - def identity ( self, value ): - if type( value ) == self.aType: - return value - raise ValError - - def convert_item(self,valeur): - return self.coerce(valeur) - - def verif_item(self,valeur): - try: - self.coerce(valeur) - except: - return 0 - return 1 + + """ + Exemple de validateur + Cette classe est un validateur qui controle qu'une valeur + est bien du type Python attendu. + Pour une liste on verifie que tous les elements sont du bon type. + Semblable a InstanceVal mais ici on fait le test par tentative de conversion + alors qu'avec InstanceVal on ne teste que si isinstance est vrai. + """ + + def __init__(self, aType): + # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type + # type(1) == int;type(0.2)==float;etc. + if type(aType) != types.TypeType: + aType = type(aType) + self.aType = aType + try: + self.coerce = CoercableFuncs[aType] + except: + self.coerce = self.identity + + def info(self): + return ufmt(_(u"valeur de %s"), self.aType) + + def identity(self, value): + if type(value) == self.aType: + return value + raise ValError + + def convert_item(self, valeur): + return self.coerce(valeur) + + def verif_item(self, valeur): + try: + self.coerce(valeur) + except: + return 0 + return 1 + class InstanceVal(ListVal): - """ - Exemple de validateur - Cette classe est un validateur qui controle qu'une valeur est - bien une instance (au sens Python) d'une classe - Pour une liste on verifie chaque element de la liste - """ - def __init__(self,aClass): - #Si aClass est une classe on la memorise dans self.aClass - #sinon c'est une instance dont on memorise la classe - if type(aClass) == types.InstanceType: - #instance ancienne mode - aClass=aClass.__class__ - elif type(aClass) == types.ClassType: - #classe ancienne mode - aClass=aClass - elif type(aClass) == type: - #classe nouvelle mode - aClass=aClass - elif isinstance(aClass,object): - #instance nouvelle mode - aClass=type(aClass) - else: - raise ValError(_(u"type non supporté")) - - self.aClass=aClass - - def info(self): - #return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__) - return tr("valeur d'instance de ")+ self.aClass.__name__ - - def verif_item(self,valeur): - if not isinstance(valeur,self.aClass): return 0 - return 1 - -class VerifTypeTuple(Valid,ListVal) : - def __init__(self,typeDesTuples): - self.typeDesTuples=typeDesTuples - Valid.__init__(self) - self.cata_info="" - - def info(self): - return _(u": vérifie les types dans un tuple") - - def info_erreur_liste(self): - return _(u"Les types entrés ne sont pas permis") - - def default(self,valeur): - #if valeur in self.liste : raise ValError("%s est un doublon" % valeur) - return valeur - - def is_list(self) : - return 1 - - def convert_item(self,valeur): - if len(valeur) != len(self.typeDesTuples): - #raise ValError(ufmt(_(u"%s devrait etre de type %s "), valeur, repr(self.typeDesTuples))) - raise ValError(repr(valeur)+tr(" devrait etre de type ")+ self.typeDesTuples) - for i in range(len(valeur)) : - ok=self.verifType(valeur[i],self.typeDesTuples[i]) - if ok!=1 : - #raise ValError(ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples)) - raise ValError(repr(valeur)+tr(" devrait etre de type ")+ self.typeDesTuples) - return valeur - - def verif_item(self,valeur): - try : - if len(valeur) != len(self.typeDesTuples): + + """ + Exemple de validateur + Cette classe est un validateur qui controle qu'une valeur est + bien une instance (au sens Python) d'une classe + Pour une liste on verifie chaque element de la liste + """ + + def __init__(self, aClass): + # Si aClass est une classe on la memorise dans self.aClass + # sinon c'est une instance dont on memorise la classe + if type(aClass) == types.InstanceType: + # instance ancienne mode + aClass = aClass.__class__ + elif type(aClass) == types.ClassType: + # classe ancienne mode + aClass = aClass + elif type(aClass) == type: + # classe nouvelle mode + aClass = aClass + elif isinstance(aClass, object): + # instance nouvelle mode + aClass = type(aClass) + else: + raise ValError(_(u"type non supporté")) + + self.aClass = aClass + + def info(self): + return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__) + + def verif_item(self, valeur): + if not isinstance(valeur, self.aClass): + return 0 + return 1 + + +class VerifTypeTuple(Valid, ListVal): + + def __init__(self, typeDesTuples): + self.typeDesTuples = typeDesTuples + Valid.__init__(self) + self.cata_info = "" + + def info(self): + return _(u": vérifie les types dans un tuple") + + def info_erreur_liste(self): + return _(u"Les types entrés ne sont pas permis") + + def default(self, valeur): + # if valeur in self.liste : raise ValError("%s est un doublon" % + # valeur) + return valeur + + def is_list(self): + return 1 + + def convert_item(self, valeur): + if len(valeur) != len(self.typeDesTuples): + raise ValError( + ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples)) + for i in range(len(valeur)): + ok = self.verifType(valeur[i], self.typeDesTuples[i]) + if ok != 1: + raise ValError( + ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples)) + return valeur + + def verif_item(self, valeur): + try: + if len(valeur) != len(self.typeDesTuples): return 0 - for i in range(len(valeur)) : - ok=self.verifType(valeur[i],self.typeDesTuples[i]) - if ok!=1: - return 0 - except : - return 0 - return 1 - - def verifType(self,valeur,type_permis): - if type_permis == 'R': - if type(valeur) in (types.IntType,types.FloatType,types.LongType):return 1 - elif type_permis == 'I': - if type(valeur) in (types.IntType,types.LongType):return 1 - elif type_permis == 'C': - if self.is_complexe(valeur):return 1 - elif type_permis == 'TXM': - if type(valeur)==types.StringType:return 1 - return 0 - - def verif(self,valeur): - if type(valeur) in (types.ListType,types.TupleType): - liste=list(valeur) - for val in liste: - if self.verif_item(val)!=1 : return 0 - return 1 - -class VerifExiste(ListVal) : - """ - fonctionne avec into - Met une liste à jour selon les mot clefs existant - exemple si into = ("A","B","C") - si au niveau N du JDC les objets "A" et "C" existe - alors la liste des into deviendra ( "A","C") - - niveauVerif est le niveau du JDC dans lequel va s effectuer la verification - niveauVerif est defini par rapport au Noeud : - exemple niveauVerif = 1 : on verifie les freres - niveauVerif = 2 : on verifie les oncles.. - """ - def __init__(self,niveauVerif): - ListVal.__init__(self) - self.niveauVerif=niveauVerif - self.MCSimp=None - self.listeDesFreres=() - self.fonctions=('verifie_liste','set_MCSimp') - - def is_list(self): - return 1 - - def verifie_liste(self,liste): - self.set_MCSimp(self.MCSimp) - for item in liste : - if not( item in self.listeDesFreres) : return 0 - return 1 - - def verif_item(self,valeur): - self.set_MCSimp(self.MCSimp) - if valeur in self.listeDesFreres : return 1 - return 0 - - def set_MCSimp(self, MCSimp) : - self.MCSimp=MCSimp - k=self.niveauVerif - mc=MCSimp - while (k != 0) : - parent=mc.parent - mc=parent - k=k-1 - #on met la liste à jour - parent.forceRecalcul=self.niveauVerif - self.listeDesFreres=parent.liste_mc_presents() - - def convert_item(self,valeur): - if valeur in self.listeDesFreres : return valeur - raise ValError(ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres)) + for i in range(len(valeur)): + ok = self.verifType(valeur[i], self.typeDesTuples[i]) + if ok != 1: + return 0 + except: + return 0 + return 1 + + def verifType(self, valeur, type_permis): + if type_permis == 'R': + if type(valeur) in (types.IntType, types.FloatType, types.LongType): + return 1 + elif type_permis == 'I': + if type(valeur) in (types.IntType, types.LongType): + return 1 + elif type_permis == 'C': + if self.is_complexe(valeur): + return 1 + elif type_permis == 'TXM': + if type(valeur) == types.StringType: + return 1 + return 0 + + def verif(self, valeur): + if type(valeur) in (types.ListType, types.TupleType): + liste = list(valeur) + for val in liste: + if self.verif_item(val) != 1: + return 0 + return 1 + + +class VerifExiste(ListVal): + + """ + fonctionne avec into + Met une liste à jour selon les mot clefs existant + exemple si into = ("A","B","C") + si au niveau N du JDC les objets "A" et "C" existe + alors la liste des into deviendra ( "A","C") + + niveauVerif est le niveau du JDC dans lequel va s effectuer la verification + niveauVerif est defini par rapport au Noeud : + exemple niveauVerif = 1 : on verifie les freres + niveauVerif = 2 : on verifie les oncles.. + """ + + def __init__(self, niveauVerif): + ListVal.__init__(self) + self.niveauVerif = niveauVerif + self.MCSimp = None + self.listeDesFreres = () + self.fonctions = ('verifie_liste', 'set_MCSimp') + + def is_list(self): + return 1 + + def verifie_liste(self, liste): + self.set_MCSimp(self.MCSimp) + for item in liste: + if not(item in self.listeDesFreres): + return 0 + return 1 + + def verif_item(self, valeur): + self.set_MCSimp(self.MCSimp) + if valeur in self.listeDesFreres: + return 1 + return 0 + + def set_MCSimp(self, MCSimp): + self.MCSimp = MCSimp + k = self.niveauVerif + mc = MCSimp + while (k != 0): + parent = mc.parent + mc = parent + k = k - 1 + # on met la liste à jour + parent.forceRecalcul = self.niveauVerif + self.listeDesFreres = parent.liste_mc_presents() + + def convert_item(self, valeur): + if valeur in self.listeDesFreres: + return valeur + raise ValError( + ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres)) + class RegExpVal(ListVal): + """ - Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern' + Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern' """ - errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"' + errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"' def __init__(self, pattern): self.pattern = pattern self.compiled_regexp = re.compile(pattern) - + def info(self): - return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern + return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern def verif_item(self, valeur): if self.compiled_regexp.match(valeur): @@ -1468,18 +1586,21 @@ class RegExpVal(ListVal): if self.compiled_regexp.match(valeur): return valeur else: - raise ValError(self.errormsg % {"value": valeur, "pattern": self.pattern}) + raise ValError(self.errormsg % + {"value": valeur, "pattern": self.pattern}) + class FileExtVal(RegExpVal): + """ - Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext' + Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext' """ def __init__(self, ext): self.ext = ext - self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {"ext": ext} + self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % { + "ext": ext} RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext) - + def info(self): - #return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext - return tr('Un nom de fichier se terminant par') + self.ext +tr(" est attendu.") + return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext diff --git a/Noyau/N__F.py b/Noyau/N__F.py index 79421b87..753ba633 100644 --- a/Noyau/N__F.py +++ b/Noyau/N__F.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,40 +16,42 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + import UserDict + class _F(UserDict.UserDict): - """ - Cette classe a un comportement semblable à un - dictionnaire Python et permet de donner - la valeur d'un mot-clé facteur avec pour les sous - mots-clés la syntaxe motcle=valeur - """ - - def __init__(self, *pos, **args): - if len(pos) != 0: - raise SyntaxError("Valeur invalide pour '_F('. "\ - "On attend cette syntaxe : _F(MOTCLE=valeur, ...)") - self.data=args - - def supprime(self): - self.data={} - - def __cmp__(self, dict): - if type(dict) == type(self.data): - return cmp(self.data, dict) - elif hasattr(dict,"data"): - return cmp(self.data, dict.data) - else: - return cmp(self.data, dict) - - def __iter__(self): - return iter(self.data) - - def copy(self): - import copy - c= copy.copy(self) - c.data=self.data.copy() - return c + + """ + Cette classe a un comportement semblable à un + dictionnaire Python et permet de donner + la valeur d'un mot-clé facteur avec pour les sous + mots-clés la syntaxe motcle=valeur + """ + + def __init__(self, *pos, **args): + if len(pos) != 0: + raise SyntaxError("Valeur invalide pour '_F('. " + "On attend cette syntaxe : _F(MOTCLE=valeur, ...)") + self.data = args + + def supprime(self): + self.data = {} + + def __cmp__(self, dict): + if type(dict) == type(self.data): + return cmp(self.data, dict) + elif hasattr(dict, "data"): + return cmp(self.data, dict.data) + else: + return cmp(self.data, dict) + + def __iter__(self): + return iter(self.data) + + def copy(self): + import copy + c = copy.copy(self) + c.data = self.data.copy() + return c diff --git a/Noyau/N_info.py b/Noyau/N_info.py index a75b9400..c97197f7 100644 --- a/Noyau/N_info.py +++ b/Noyau/N_info.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """Module to manage information printing : debug, info, error. Should replace 'print' and 'UTMESS' calls at least in the supervisor @@ -34,6 +34,7 @@ from subprocess import Popen, PIPE from N_utils import Enum, Singleton from strfunc import convert + def default_print(text): """Basic print function.""" print convert(text) @@ -45,17 +46,20 @@ LEVEL = Enum( 'ERROR' ) + class Category(object): + """Define a category of message for different parts of the code. This allows to store different parameters for each category of message.""" + def __init__(self): self._level = LEVEL.INFO self._fmt = "%-8s" self._header = { - LEVEL.DEBUG : "DEBUG", - LEVEL.INFO : None, - LEVEL.WARN : "WARNING", - LEVEL.ERROR : "ERROR", + LEVEL.DEBUG: "DEBUG", + LEVEL.INFO: None, + LEVEL.WARN: "WARNING", + LEVEL.ERROR: "ERROR", } def set_level(self, level): @@ -91,10 +95,13 @@ REGEXP_ORIG = re.compile('File [\'\"]*(.*?)[\'\"]*, *line ([0-9]+), *in (.*)') # slighty different and very simplier than logger objects # from the logging module. + + class InfoLevel(Singleton): + """Store informations level.""" _singleton_id = 'N_info.InfoLevel' - + def __init__(self, level): """Initialization""" self._parts = [] @@ -102,7 +109,7 @@ class InfoLevel(Singleton): part.level = level self.reset_print_function() self._msg_callback = [] - #self.extend_message(ALL, stack_header_callback) + # self.extend_message(ALL, stack_header_callback) self.extend_message(ALL, insert_header) def add(self, category): @@ -165,10 +172,10 @@ class InfoLevel(Singleton): # how to use callbacks ? valk ? from Utilitai.Utmess import MessageLog code = { - LEVEL.DEBUG : 'I', - LEVEL.INFO : 'I', - LEVEL.WARN : 'A', - LEVEL.ERROR : 'F', + LEVEL.DEBUG: 'I', + LEVEL.INFO: 'I', + LEVEL.WARN: 'A', + LEVEL.ERROR: 'F', } valk = kwargs.get('valk', ()) vali = kwargs.get('vali', ()) @@ -215,13 +222,15 @@ def insert_header(category, level, msg, args, kwargs): msg = header + msg return msg, args + def stack_header_callback(category, level, msg, args, kwargs): """To insert the origin.""" if level <= LEVEL.DEBUG: stack_id = -5 + kwargs.get('stack_id', 0) stack = traceback.format_stack(limit=10)[stack_id] mat = REGEXP_ORIG.search(stack) - origin = '[%s:%s in %s] ' % (osp.basename(mat.group(1)), mat.group(2), mat.group(3)) + origin = '[%s:%s in %s] ' % ( + osp.basename(mat.group(1)), mat.group(2), mat.group(3)) msg = origin + msg return msg, args @@ -237,6 +246,7 @@ _pid = os.getpid() RE_VMPEAK = re.compile('VmPeak:\s*([0-9]+)\s*([kMGBo]+)', re.M | re.I) + def memory_used(pid): """Return the current VmPeak value.""" p = Popen(['cat', '/proc/%s/status' % pid], stdout=PIPE) @@ -247,6 +257,7 @@ def memory_used(pid): current_memory_used = partial(memory_used, _pid) + def mem_msg_callback(category, level, msg, args, kwargs): """Callback to add memory infos to message.""" if level <= LEVEL.DEBUG: @@ -258,15 +269,13 @@ def mem_msg_callback(category, level, msg, args, kwargs): if __name__ == "__main__": message.set_level(SUPERV, LEVEL.WARN) message.set_level(MISS, LEVEL.DEBUG) - #message.debug(None, "debug message") + # message.debug(None, "debug message") message.info(ALL, "information message") message.warn(None, "warning message") message.error(ALL, "error message") message.add_memory_info() - #message.debug(MISS, "debug supervisor message") + # message.debug(MISS, "debug supervisor message") message.info(SUPERV, "information supervisor message") message.warn(SUPERV, "warning supervisor message") message.error(SUPERV, "error supervisor message") message.critical(MISS, "test the critical alias") - - diff --git a/Noyau/N_types.py b/Noyau/N_types.py index 377dddff..42626f15 100644 --- a/Noyau/N_types.py +++ b/Noyau/N_types.py @@ -1,23 +1,21 @@ -#@ MODIF N_types Noyau DATE 28/01/2013 AUTEUR COURTOIS M.COURTOIS -# -*- coding: iso-8859-1 -*- -# CONFIGURATION MANAGEMENT OF EDF VERSION -# ====================================================================== -# COPYRIGHT (C) 1991 - 2013 EDF R&D WWW.CODE-ASTER.ORG -# 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, OR -# (AT YOUR OPTION) 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. -# -# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE -# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. -# ====================================================================== -# RESPONSABLE COURTOIS M.COURTOIS +# coding=utf-8 +# Copyright (C) 2007-2013 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com """ Ce module contient des fonctions utilitaires pour tester les types @@ -32,39 +30,52 @@ except ImportError: # use isinstance() instead of type() because objects returned from numpy arrays # inherit from python scalars but are numpy.float64 or numpy.int32... + + def is_int(obj): return isinstance(obj, int) or type(obj) is long + def is_float(obj): return isinstance(obj, float) + def is_complex(obj): return isinstance(obj, complex) from decimal import Decimal + + def is_float_or_int(obj): return is_float(obj) or is_int(obj) or isinstance(obj, Decimal) + def is_number(obj): return is_float_or_int(obj) or is_complex(obj) + def is_str(obj): return isinstance(obj, (str, unicode)) + def is_list(obj): return type(obj) is list + def is_tuple(obj): return type(obj) is tuple + def is_array(obj): """a numpy array ?""" return type(obj) is _np_arr + def is_sequence(obj): """a sequence (allow iteration, not a string) ?""" return is_list(obj) or is_tuple(obj) or is_array(obj) + def is_assd(obj): from N_ASSD import ASSD return isinstance(obj, ASSD) @@ -75,15 +86,18 @@ def force_list(obj): sinon retourne [obj,] (en tant que list). """ if not is_sequence(obj): - obj = [obj,] + obj = [obj, ] return list(obj) + def force_tuple(obj): """Return `obj` as a tuple.""" return tuple(force_list(obj)) # backward compatibility from warnings import warn + + def is_enum(obj): """same as is_sequence""" warn("'is_enum' is deprecated, use 'is_sequence'", diff --git a/Noyau/N_utils.py b/Noyau/N_utils.py index 7b909f18..2b624a47 100644 --- a/Noyau/N_utils.py +++ b/Noyau/N_utils.py @@ -1,4 +1,4 @@ -# -*- coding: iso-8859-1 -*- +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# + """ Ce module contient des fonctions utilitaires @@ -27,130 +27,144 @@ import sys # Modules EFICAS from N_Exception import AsException -from N_types import is_int, is_float, is_complex, is_str, is_sequence, is_assd +from N_types import is_int, is_float, is_complex, is_str, is_sequence, is_assd +from strfunc import get_encoding -SEP='_' +SEP = '_' try: - # Si la version de Python possède la fonction _getframe - # on l'utilise. - cur_frame=sys._getframe + # Si la version de Python possède la fonction _getframe + # on l'utilise. + cur_frame = sys._getframe except: - # Sinon on l'émule - def cur_frame(offset=0): - """ Retourne la frame d execution effective eventuellement en remontant - de offset niveaux dans la pile d execution - Si il y a moins de offset niveaux retourne None - """ - try:1/0 - except: - frame=sys.exc_info()[2].tb_frame.f_back - while offset > 0: - if frame == None:return None - frame=frame.f_back - offset=offset-1 - return frame + # Sinon on l'émule + def cur_frame(offset=0): + """ Retourne la frame d execution effective eventuellement en remontant + de offset niveaux dans la pile d execution + Si il y a moins de offset niveaux retourne None + """ + try: + 1 / 0 + except: + frame = sys.exc_info()[2].tb_frame.f_back + while offset > 0: + if frame == None: + return None + frame = frame.f_back + offset = offset - 1 + return frame def callee_where(niveau=4): - """ - recupere la position de l appel - """ - frame=cur_frame(niveau) - if frame == None: return 0,"inconnu",0,{} - try: - return frame.f_lineno,frame.f_code.co_filename,frame.f_code.co_firstlineno,frame.f_locals - except: - return 0,"inconnu",0,{} + """ + recupere la position de l appel + """ + frame = cur_frame(niveau) + if frame == None: + return 0, "inconnu", 0, {} + try: + # Python 2.7 compile function does not accept unicode filename, so we encode it + # with the current locale encoding in order to have a correct traceback. + # Here, we convert it back to unicode. + filename = unicode(frame.f_code.co_filename, get_encoding()) + return frame.f_lineno, filename, frame.f_code.co_firstlineno, frame.f_locals + except: + return 0, "inconnu", 0, {} def AsType(a): - """ - Retourne le type d'un concept (a) à partir - des caractéristiques de l'objet Python - """ - if is_sequence(a): - return AsType(a[0]) - if is_assd(a): - return type(a) - if is_float(a): - return "R" - if is_int(a): - return "I" - if is_str(a): - return "TXM" - if a == None: - return None - raise AsException("type inconnu: %r %s" % (a, type(a))) + """ + Retourne le type d'un concept (a) à partir + des caractéristiques de l'objet Python + """ + if is_sequence(a): + return AsType(a[0]) + if is_assd(a): + return type(a) + if is_float(a): + return "R" + if is_int(a): + return "I" + if is_str(a): + return "TXM" + if a == None: + return None + raise AsException("type inconnu: %r %s" % (a, type(a))) def prbanner(s): - print "*"*(len(s)+10) - print "*"*5 + s + "*"*5 - print "*"*(len(s)+10) + print "*" * (len(s) + 10) + print "*" * 5 + s + "*" * 5 + print "*" * (len(s) + 10) def repr_float(valeur): - """ - Cette fonction représente le réel valeur comme une chaine de caractères - sous forme mantisse exposant si nécessaire cad si le nombre contient plus de - 5 caractères - NB : valeur est un réel au format Python ou une chaine de caractères représentant un réel - """ - if type(valeur) == str : valeur = eval(valeur) - if valeur == 0. : return '0.0' - if abs(valeur) > 1. : - if abs(valeur) < 10000. : return repr(valeur) - else : - if abs(valeur) > 0.01 : return repr(valeur) - t=repr(valeur) - if t.find('e') != -1 or t.find('E') != -1 : - # le réel est déjà sous forme mantisse exposant ! - # --> on remplace e par E - t=t.replace('e','E') - # --> on doit encore vérifier que la mantisse contient bien un '.' - if t.find('.')!= -1: - return t + """ + Cette fonction représente le réel valeur comme une chaine de caractères + sous forme mantisse exposant si nécessaire cad si le nombre contient plus de + 5 caractères + NB : valeur est un réel au format Python ou une chaine de caractères représentant un réel + """ + if type(valeur) == str: + valeur = eval(valeur) + if valeur == 0.: + return '0.0' + if abs(valeur) > 1.: + if abs(valeur) < 10000.: + return repr(valeur) else: - # -->il faut rajouter le point avant le E - t=t.replace('E','.E') - return t - s='' - neg = 0 - if t[0]=='-': - s=s+t[0] - t=t[1:] - cpt = 0 - if t[0].atof() == 0.: - # réel plus petit que 1 - neg = 1 - t=t[2:] - cpt=1 - while t[0].atof() == 0. : - cpt = cpt+1 - t=t[1:] - s=s+t[0]+'.' - for c in t[1:]: - s=s+c - else: - # réel plus grand que 1 - s=s+t[0]+'.' - if t[1:].atof() == 0.: - l=t[1:].split('.') - cpt = len(l[0]) + if abs(valeur) > 0.01: + return repr(valeur) + t = repr(valeur) + if t.find('e') != -1 or t.find('E') != -1: + # le réel est déjà sous forme mantisse exposant ! + # --> on remplace e par E + t = t.replace('e', 'E') + # --> on doit encore vérifier que la mantisse contient bien un '.' + if t.find('.') != -1: + return t + else: + # -->il faut rajouter le point avant le E + t = t.replace('E', '.E') + return t + s = '' + neg = 0 + if t[0] == '-': + s = s + t[0] + t = t[1:] + cpt = 0 + if t[0].atof() == 0.: + # réel plus petit que 1 + neg = 1 + t = t[2:] + cpt = 1 + while t[0].atof() == 0.: + cpt = cpt + 1 + t = t[1:] + s = s + t[0] + '.' + for c in t[1:]: + s = s + c else: - r=0 - pt=0 - for c in t[1:]: - r=r+1 - if c != '.' : - if pt != 1 : cpt = cpt + 1 - s=s+c + # réel plus grand que 1 + s = s + t[0] + '.' + if t[1:].atof() == 0.: + l = t[1:].split('.') + cpt = len(l[0]) else: - pt = 1 - if r+1 == len(t) or t[r+1:].atof() == 0.:break - s=s+'E'+neg*'-'+repr(cpt) - return s + r = 0 + pt = 0 + for c in t[1:]: + r = r + 1 + if c != '.': + if pt != 1: + cpt = cpt + 1 + s = s + c + else: + pt = 1 + if r + 1 == len(t) or t[r + 1:].atof() == 0.: + break + s = s + 'E' + neg * '-' + repr(cpt) + return s def import_object(uri): @@ -169,19 +183,23 @@ def import_object(uri): __import__(modname) mod = sys.modules[modname] except ImportError, err: - raise ImportError(u"can not import module : %s (%s)" % (modname, str(err))) + raise ImportError( + u"can not import module : %s (%s)" % (modname, str(err))) try: object = getattr(mod, objname) except AttributeError, err: raise AttributeError(u"object (%s) not found in module '%s'. " - "Module content is: %s" % (objname, modname, tuple(dir(mod)))) + "Module content is: %s" % (objname, modname, tuple(dir(mod)))) return object class Singleton(object): + """Singleton implementation in python.""" - # add _singleton_id attribute to the class to be independant of import path used + # add _singleton_id attribute to the class to be independant of import + # path used __inst = {} + def __new__(cls, *args, **kargs): cls_id = getattr(cls, '_singleton_id', cls) if Singleton.__inst.get(cls_id) is None: @@ -190,17 +208,19 @@ class Singleton(object): class Enum(object): + """ This class emulates a C-like enum for python. It is initialized with a list of strings to be used as the enum symbolic keys. The enum values are automatically generated as sequencing integer starting at 0. """ + def __init__(self, *keys): """Constructor""" self._dict_keys = {} for inum, key in enumerate(keys): - setattr(self, key, 2**inum) - self._dict_keys[2**inum] = key + setattr(self, key, 2 ** inum) + self._dict_keys[2 ** inum] = key def exists(self, value): """Tell if value is in the enumeration"""