From: Pascale Noyret Date: Tue, 25 Nov 2014 17:09:42 +0000 (+0000) Subject: mise en cohérence version aster X-Git-Tag: V7_5_0rc1~4 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=06c3fd3f323d461bb3994885e904f62bdab15653;p=tools%2Feficas.git mise en cohérence version 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..a491c33a 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,123 @@ 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, + **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 + assert args.get( + 'ang') is None, '"ang" attribute does not exist anymore' + 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 +161,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 bf4722e3..a35ffafc 100644 --- a/Noyau/N_Exception.py +++ b/Noyau/N_Exception.py @@ -1,3 +1,4 @@ +# coding=utf-8 # Copyright (C) 2007-2013 EDF R&D # # This library is free software; you can redistribute it and/or @@ -15,22 +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 EFICAS from strfunc import get_encoding + class AsException(Exception): - def __unicode__(self): - return " ".join([unicode(x) for x in self.args]) - def __str__(self): - return unicode(self).encode(get_encoding()) + 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..df3f0783 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,124 @@ 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, + 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 + assert args.get( + 'ang') is None, '"ang" attribute does not exist anymore' + 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 ba59be46..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,16 +16,19 @@ # 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 @@ -38,596 +41,617 @@ 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 ...') - # 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 = """ + 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 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. - """ - #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..f2350ddc 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,164 @@ # 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="", + 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 + assert args.get( + 'ang') is None, '"ang" attribute does not exist anymore' + 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..a98c9644 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,148 @@ # 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="", + 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 + assert args.get( + 'ang') is None, '"ang" attribute does not exist anymore' + 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..dc735a2b 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,140 @@ # 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="", + 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 + assert args.get( + 'ang') is None, '"ang" attribute does not exist anymore' + 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..6152b513 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,79 @@ 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, 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 : ? + - 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 + + 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 0e5227ff..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,135 +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: - # 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,{} + """ + 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): @@ -174,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: @@ -195,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""" diff --git a/Noyau/__init__.py b/Noyau/__init__.py index 589d390f..beaec67e 100644 --- a/Noyau/__init__.py +++ b/Noyau/__init__.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 package fournit les classes de base d'EFICAS. - Ces classes permettent d'effectuer quelques opérations basiques : + Ces classes permettent d'effectuer quelques opérations basiques : - - la création + - la création - - la vérification des définitions + - la vérification des définitions - - la création d'objets de type OBJECT à partir d'une définition de type ENTITE + - la création d'objets de type OBJECT à partir d'une définition de type ENTITE """ # Avant toutes choses, on met le module context dans le global de l'interpreteur (__builtin__) -# sous le nom CONTEXT afin d'avoir accès aux fonctions -# get_current_step, set_current_step et unset_current_step de n'importe où +# sous le nom CONTEXT afin d'avoir accès aux fonctions +# get_current_step, set_current_step et unset_current_step de n'importe où import context import __builtin__ -__builtin__.CONTEXT=context +__builtin__.CONTEXT = context + def _(msg): """Differs translation.""" @@ -46,6 +46,14 @@ __builtin__._ = _ from N_SIMP import SIMP from N_FACT import FACT -# structures de données +# structures de données import asojb from asojb import AsBase + +# Only the first MAXSIZE objects will be checked +# This is used for the number of MCFACT, the number of MCSIMP and the number of +# values in a MCSIMP. +MAXSIZE = 500 + +MAXSIZE_MSGCHK = ' Only the first {0} occurrences (total: {1}) have been checked.' +MAXSIZE_MSGKEEP = ' Only the first {0} occurrences (total: {1}) have been kept.' diff --git a/Noyau/ascheckers.py b/Noyau/ascheckers.py index 8ed138b3..5bcbf9bd 100644 --- a/Noyau/ascheckers.py +++ b/Noyau/ascheckers.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,83 +16,86 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - class Parmi(object): + """Classe qui exprime une contrainte multiple pour un attribut""" + def __init__(self, *args): self.values = list(args) - def add_value(self, value ): + def add_value(self, value): if value not in self.values: - self.values.append( value ) + self.values.append(value) - def __call__(self, obj, name, value, log ): + def __call__(self, obj, name, value, log): if value not in self.values: - log.err( obj, "l'attribut %s=%r n'est pas dans %r" % (name, value, self.values) ) + log.err(obj, "l'attribut %s=%r n'est pas dans %r" % + (name, value, self.values)) def __repr__(self): - l = [ "Parmi(", ] - g = [ repr(v) for v in self.values ] - l.append( ", ".join(g) ) - l.append( ")" ) - return "".join( l ) + l = ["Parmi(", ] + g = [repr(v) for v in self.values] + l.append(", ".join(g)) + l.append(")") + return "".join(l) + class CheckLog(object): - """Un validateur qui enregistre toutes les erreurs trouvées. - checkedXXX répond True si la "marq" courante est inférieure ou égale - à la celle de la dernière vérification. - Si on incrémentait "marq" à chaque étape, on revérifie à chaque fois. + + """Un validateur qui enregistre toutes les erreurs trouvées. + checkedXXX répond True si la "marq" courante est inférieure ou égale + à la celle de la dernière vérification. + Si on incrémentait "marq" à chaque étape, on revérifie à chaque fois. """ def __init__(self): - self.msg = [] - self.names = {} - self.cksums = {} - self.optional = False - self._marq = 1 + self.msg = [] + self.names = {} + self.cksums = {} + self.optional = False + self._marq = 1 self._lastmarq = self._marq - self._debug = False - self._profond = False # True pour forcer des vérifications plus profondes + self._debug = False + self._profond = False # True pour forcer des vérifications plus profondes - def log(self, level, obj, msg ): - if obj : - self.msg.append( (level, obj.nomj(), msg) ) - else : - self.msg.append( (level, 'None', msg) ) + def log(self, level, obj, msg): + if obj: + self.msg.append((level, obj.nomj(), msg)) + else: + self.msg.append((level, 'None', msg)) - def err(self, obj, msg ): - self.log( 0, obj, msg ) + def err(self, obj, msg): + self.log(0, obj, msg) - def warn(self, obj, msg ): - self.log( 1, obj, msg ) + def warn(self, obj, msg): + self.log(1, obj, msg) def visitOJB(self, obj): key = obj.nomj() self.names[key] = self._marq def checkSumOJB(self, obj, sd, maj='non'): - # vérifie que le checksum de obj n'a pas changé + # vérifie que le checksum de obj n'a pas changé # sd : concept qui contient obj - # maj='maj', l'opérateur a le droit de modifier ojb - if obj.exists : + # maj='maj', l'opérateur a le droit de modifier ojb + if obj.exists: import md5 - m=md5.new() + m = md5.new() m.update(str(obj.get())) - cksum=m.digest() - nom=obj.nomj() - if not self.cksums.has_key(nom) : - self.cksums[nom]=cksum - else : - if self.cksums[nom] != cksum : + cksum = m.digest() + nom = obj.nomj() + if not self.cksums.has_key(nom): + self.cksums[nom] = cksum + else: + if self.cksums[nom] != cksum: self.cksums[nom] = cksum - #if maj.strip()=='maj' and nom[0:8].strip()==sd.nomj.nomj[0:8].strip() : - # Remarque : ne pas tester 'maj' premet de résoudre (un peu) le problème - # posé par la commande DETRUIRE - if nom[0:8].strip()==sd.nomj.nomj[0:8].strip() : + # if maj.strip()=='maj' and nom[0:8].strip()==sd.nomj.nomj[0:8].strip() : + # Remarque : ne pas tester 'maj' premet de résoudre (un peu) le problème + # posé par la commande DETRUIRE + if nom[0:8].strip() == sd.nomj.nomj[0:8].strip(): pass - else : - self.err(obj,'Le checksum a changé') + else: + self.err(obj, 'Le checksum a changé') def visitAsBase(self, obj): key = (obj.nomj(), obj.__class__.__name__) @@ -100,15 +103,15 @@ class CheckLog(object): def force(self, force=False): if not force: - self._marq = 1 + self._marq = 1 else: - self._lastmarq += 1 - self._marq = self._lastmarq + self._lastmarq += 1 + self._marq = self._lastmarq def checkedOJB(self, obj): key = obj.nomj() res = self.names.get(key, 0) >= self._marq - self.help_dbg([key,], res) + self.help_dbg([key, ], res) return res def checkedAsBase(self, obj): @@ -120,18 +123,21 @@ class CheckLog(object): def help_dbg(self, key, res): if self._debug: if res: - s = 'ignore' + s = 'ignore' else: - s = 'check ' + s = 'check ' print '#DBG %6d %s : %s' % (self._marq, s, ', '.join(key)) def __str__(self): - d = { 0: "E", 1:"W" } - return "\n".join( [ "%s:%s: %s" % (d[l],n,m) - for l,n,m in self.msg ]) + d = {0: "E", 1: "W"} + return "\n".join(["%s:%s: %s" % (d[l], n, m) + for l, n, m in self.msg]) + class CheckFail(CheckLog): - """Un validateur qui lève une exception - dès la première erreur""" - def err(self, obj, msg ): - raise AssertionError("%s: %s" % (obj.nomj(), msg) ) + + """Un validateur qui lève une exception + dès la première erreur""" + + def err(self, obj, msg): + raise AssertionError("%s: %s" % (obj.nomj(), msg)) diff --git a/Noyau/asnom.py b/Noyau/asnom.py index 370da214..9ee9fd0e 100644 --- a/Noyau/asnom.py +++ b/Noyau/asnom.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,28 +16,28 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - """ Description des types de base aster -version 2 - réécrite pour essayer de simplifier -le problème des instances/types et instances/instances +version 2 - réécrite pour essayer de simplifier +le problème des instances/types et instances/instances -le type de base ASBase permet de représenter une structure -de donnée. Une instance de ASBase comme attribut d'une classe -dérivée de ASBase représente une sous-structure nommée. +le type de base ASBase permet de représenter une structure +de donnée. Une instance de ASBase comme attribut d'une classe +dérivée de ASBase représente une sous-structure nommée. -une instance de ASBase 'libre' représente une instance de la -structure de donnée complète. +une instance de ASBase 'libre' représente une instance de la +structure de donnée complète. -c'est ce comportement qui est capturé dans la classe StructType +c'est ce comportement qui est capturé dans la classe StructType """ from basetype import Type + class SDNom(Type): - """Objet représentant une sous-partie de nom + + """Objet représentant une sous-partie de nom d'objet jeveux""" nomj = None debut = None @@ -45,28 +45,29 @@ class SDNom(Type): just = None justtype = None - def __init__(self, nomj=None, debut=None, fin=None, just='l', **kwargs ): + def __init__(self, nomj=None, debut=None, fin=None, just='l', **kwargs): """ Configure un objet nom - nomj : la partie du nom fixée (par ex .TITR) ou '' si non précisée - debut, fin : la partie du K24 concernée + nomj : la partie du nom fixée (par ex .TITR) ou '' si non précisée + debut, fin : la partie du K24 concernée just : la justification a droite ou a gauche ('l' ou 'r') - kwargs : inutilisé, juste par simplicité + kwargs : inutilisé, juste par simplicité Note: On utilise cet objet comme attribut d'instance ou de classe. En attribut de classe pour les noms de structure, cela permet - de définir la position du nom d'objet dans le nom jeveux, l'attribut + de définir la position du nom d'objet dans le nom jeveux, l'attribut nom est alors la valeur du suffixe pour une sous-structure ou None pour une structure principale. """ - super( SDNom, self ).__init__( nomj=nomj, debut=debut, fin=fin, just=just, **kwargs ) - self.update( (nomj, debut, fin, just) ) + super(SDNom, self).__init__( + nomj=nomj, debut=debut, fin=fin, just=just, **kwargs) + self.update((nomj, debut, fin, just)) def __call__(self): if self._parent is None or self._parent._parent is None: debut = self.debut or 0 - prefix = ' '*debut + prefix = ' ' * debut else: # normalement # assert self._parent.nomj is self @@ -75,37 +76,36 @@ class SDNom(Type): debut = self.debut or nomparent.fin or len(prefix) fin = self.fin or 24 nomj = self.nomj or '' - nomj = self.just( nomj, fin-debut ) + nomj = self.just(nomj, fin - debut) prefix = prefix.ljust(24) - res = prefix[:debut]+nomj+prefix[fin:] + res = prefix[:debut] + nomj + prefix[fin:] return res[:24] def fcata(self): - return self.just(self.nomj,self.fin-self.debut).replace(' ','?') + return self.just(self.nomj, self.fin - self.debut).replace(' ', '?') def __repr__(self): - return "" % (self.nomj,self.debut,self.fin) + return "" % (self.nomj, self.debut, self.fin) - # On utilise pickle pour les copies, et pickle ne sait pas gérer la - # sauvegarde de str.ljust ou str.rjust (c'est une méthode non liée) + # On utilise pickle pour les copies, et pickle ne sait pas gérer la + # sauvegarde de str.ljust ou str.rjust (c'est une méthode non liée) def __getstate__(self): - return (self.nomj, self.debut, self.fin, self.justtype ) + return (self.nomj, self.debut, self.fin, self.justtype) - def __setstate__( self, (nomj,debut,fin,just) ): + def __setstate__(self, (nomj, debut, fin, just)): self.nomj = nomj self.debut = debut self.fin = fin - if just=='l' or just is None: + if just == 'l' or just is None: self.just = str.ljust - elif just=='r': + elif just == 'r': self.just = str.rjust else: - raise ValueError("Justification '%s' invalide" % just ) + raise ValueError("Justification '%s' invalide" % just) self.justtype = just - - def update( self, (nomj,debut,fin,just) ): + def update(self, (nomj, debut, fin, just)): if nomj is not None: self.nomj = nomj if self.debut is None: @@ -113,21 +113,19 @@ class SDNom(Type): if self.fin is None: self.fin = fin if self.justtype is None and just is not None: - if just=='l': + if just == 'l': self.just = str.ljust - elif just=='r': + elif just == 'r': self.just = str.rjust else: - raise ValueError("Justification '%s' invalide" % just ) + raise ValueError("Justification '%s' invalide" % just) self.justtype = just - def reparent( self, parent, new_name ): + def reparent(self, parent, new_name): self._parent = parent self._name = new_name for nam in self._subtypes: - obj = getattr( self, nam ) - obj.reparent( self, nam ) + obj = getattr(self, nam) + obj.reparent(self, nam) if self.nomj is None and self._parent._name is not None: self.nomj = "." + self._parent._name - - diff --git a/Noyau/asojb.py b/Noyau/asojb.py index 0eb259c5..b1c08bf5 100644 --- a/Noyau/asojb.py +++ b/Noyau/asojb.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 -# """ Description des OJB jeveux @@ -24,68 +23,71 @@ from basetype import Type from asnom import SDNom from ascheckers import CheckLog -import traceback,sys +import traceback +import sys # pour utilisation dans eficas try: - import aster - from Utilitai.Utmess import UTMESS + import aster + from Utilitai.Utmess import UTMESS except: - pass + pass # ----------------------------------------------------------------------------- + + class AsBase(Type): nomj = SDNom() optional = False - def __init__(self, nomj=None, *args, **kwargs ): - super(AsBase,self).__init__( nomj, *args, **kwargs ) + def __init__(self, nomj=None, *args, **kwargs): + super(AsBase, self).__init__(nomj, *args, **kwargs) assert self.nomj is not self.__class__.nomj - if isinstance( nomj, str ): + if isinstance(nomj, str): self.nomj.nomj = nomj - elif isinstance( nomj, SDNom ): - self.nomj.update( nomj.__getstate__() ) + elif isinstance(nomj, SDNom): + self.nomj.update(nomj.__getstate__()) def set_name(self, nomj): """Positionne le nomj de self """ - assert isinstance( self.nomj.nomj, str ), "uniquement pour les concepts" + assert isinstance(self.nomj.nomj, str), "uniquement pour les concepts" self.nomj.nomj = nomj def check(self, checker=None): if checker is None: checker = CheckLog() - # vérif déjà faite ? (en tenant compte du type) + # vérif déjà faite ? (en tenant compte du type) if checker.checkedAsBase(self): return checker - checker.visitAsBase( self ) + checker.visitAsBase(self) - # vérifie les enfants : + # vérifie les enfants : optional = checker.optional checker.optional = checker.optional or self.optional for name in self._subtypes: v = getattr(self, name) - if isinstance( v, (OJB,AsBase) ): + if isinstance(v, (OJB, AsBase)): v.check(checker) for name in dir(self): - if name.startswith( 'check_' ): + if name.startswith('check_'): v = getattr(self, name) if callable(v): - try : - v( checker ) - except : - mess=60*'-'+'\n' - mess=mess+'Erreur SDVERI (Attention : vérification incomplète)'+'\n' - mess=mess.join(traceback.format_tb(sys.exc_traceback)) - checker.err(self,mess) + try: + v(checker) + except: + mess = 60 * '-' + '\n' + mess = mess + \ + 'Erreur SDVERI (Attention : vérification incomplète)' + \ + '\n' + mess = mess.join( + traceback.format_tb(sys.exc_traceback)) + checker.err(self, mess) checker.optional = optional return checker - def members( self ): - pass - def dump(self, indent=""): import pydoc l = [] @@ -95,66 +97,71 @@ class AsBase(Type): f = "(f)" else: f = "(o)" - l.append( f+" "+nomj ) - #l.append( '-'*(len(nomj)+3) ) + l.append(f + " " + nomj) for name in self._subtypes: obj = getattr(self, name) - if isinstance(obj,(AsBase,OJB)): - l.append( obj.dump(indent) ) + if isinstance(obj, (AsBase, OJB)): + l.append(obj.dump(indent)) for name in dir(self): - if name.startswith( 'check_' ): + if name.startswith('check_'): obj = getattr(self, name) if callable(obj) and name.startswith("check_"): - checkers.append( obj ) + checkers.append(obj) - indent = " "*len(nomj) + indent = " " * len(nomj) for checker in checkers: - doc = pydoc.text.document( checker ) + doc = pydoc.text.document(checker) for line in doc.splitlines(): - l.append( indent + line ) - return "\n".join( l ) + l.append(indent + line) + return "\n".join(l) def short_repr(self): - return "<%s(%x,%r)>" % (self.__class__.__name__, id(self), self.nomj() ) + return "<%s(%x,%r)>" % (self.__class__.__name__, id(self), self.nomj()) def long_repr(self): if not hasattr(self, "accessible") or not self.accessible(): - # hors Aster ou en par_lot='oui' - return self.short_repr() + # hors Aster ou en par_lot='oui' + return self.short_repr() else: - from Cata.cata import IMPR_CO, _F - IMPR_CO(CONCEPT=_F(NOM=self.nom), UNITE=6) - return '' + from Cata.cata import IMPR_CO, _F + IMPR_CO(CONCEPT=_F(NOM=self.nom), UNITE=6) + return '' def __repr__(self): - # par défaut, on fait court ! + # par défaut, on fait court ! return self.short_repr() # ----------------------------------------------------------------------------- class JeveuxAttr(object): + """Un attribut jeveux""" + def __init__(self, name): self.name = name def __get__(self, obj, klass): raise NotImplementedError - def check(self, attrname, obj, log ): - checker = getattr(obj, "_"+attrname, None ) + def check(self, attrname, obj, log): + checker = getattr(obj, "_" + attrname, None) if checker is None: return True - val = self.__get__( obj, obj.__class__ ) - if callable( checker ): - return checker( obj, attrname, val, log ) + val = self.__get__(obj, obj.__class__) + if callable(checker): + return checker(obj, attrname, val, log) + elif val == checker: + return True else: - test = val == checker - if not test: - log.err( obj, "Attribut incorrect %s %r!=%r" % (self.name, val, checker ) ) - return test + log.err(obj, "Attribut incorrect %s %r!=%r" % + (self.name, val, checker)) + return False # ----------------------------------------------------------------------------- + + class JeveuxExists(JeveuxAttr): + def __init__(self): pass @@ -162,33 +169,41 @@ class JeveuxExists(JeveuxAttr): if obj is None: return self nomj = obj.nomj() - if len(nomj)!=24: + if len(nomj) != 24: raise AssertionError(repr(nomj)) - return aster.jeveux_exists( nomj.ljust(24) ) + return aster.jeveux_exists(nomj.ljust(24)) # ----------------------------------------------------------------------------- + + class JeveuxIntAttr(JeveuxAttr): + def __get__(self, obj, klass): if obj is None: return self nomj = obj.nomj() - if aster.jeveux_exists( nomj ): - return aster.jeveux_getattr( nomj, self.name )[0] - else : + if aster.jeveux_exists(nomj): + return aster.jeveux_getattr(nomj, self.name)[0] + else: return None # ----------------------------------------------------------------------------- + + class JeveuxStrAttr(JeveuxAttr): + def __get__(self, obj, klass): if obj is None: return self nomj = obj.nomj() - if aster.jeveux_exists( nomj ): - return aster.jeveux_getattr( nomj, self.name )[1].strip() - else : + if aster.jeveux_exists(nomj): + return aster.jeveux_getattr(nomj, self.name)[1].strip() + else: return None # ----------------------------------------------------------------------------- + + class OJB(AsBase): _clas = None _genr = None @@ -205,58 +220,57 @@ class OJB(AsBase): xous = JeveuxStrAttr("XOUS") docu = JeveuxStrAttr("DOCU") exists = JeveuxExists() - #optional = False nomj = SDNom() def __init__(self, nomj=None, **attrs): - super(OJB,self).__init__( nomj, **attrs ) - self.foreachattr( self.setattribute, attrs ) + super(OJB, self).__init__(nomj, **attrs) + self.foreachattr(self.setattribute, attrs) self.optional = attrs.get('optional', False) - def setattribute( self, name, prop, attrs ): - _name = "_"+name + def setattribute(self, name, prop, attrs): + _name = "_" + name if name in attrs: - setattr( self, _name, attrs[name] ) + setattr(self, _name, attrs[name]) def get(self): nomj = self.nomj() - if aster.jeveux_exists( nomj ): - obj_simple = aster.jeveux_getattr( nomj, 'XOUS')[1].strip() == 'S' - if obj_simple : - return aster.getvectjev( nomj ) - else : - return aster.getcolljev( nomj ) + if aster.jeveux_exists(nomj): + obj_simple = aster.jeveux_getattr(nomj, 'XOUS')[1].strip() == 'S' + if obj_simple: + return aster.getvectjev(nomj) + else: + return aster.getcolljev(nomj) else: return None def get_stripped(self): - """Fonction utilitaire, renvoie une liste de chaines 'strippées'""" + """Fonction utilitaire, renvoie une liste de chaines 'strippées'""" data = self.get() if data is not None: - return [ x.strip() for x in data ] + return [x.strip() for x in data] else: return [] def foreachattr(self, callback, *args, **kwargs): klass = self.__class__ for k in dir(klass): - v = getattr( klass, k ) + v = getattr(klass, k) if isinstance(v, JeveuxAttr): - callback( k, v, *args, **kwargs ) + callback(k, v, *args, **kwargs) def check(self, checker=None): if checker is None: checker = CheckLog() - # l'objet a déjà été vérifié, on ne fait rien + # l'objet a déjà été vérifié, on ne fait rien if checker.checkedOJB(self): - return checker - checker.visitOJB( self ) + return checker + checker.visitOJB(self) if self.exists: - self.foreachattr( lambda k,v,obj,c: v.check(k, obj, c), - self, checker ) + self.foreachattr(lambda k, v, obj, c: v.check(k, obj, c), + self, checker) else: - if not self.optional and not checker.optional : - checker.err( self, "n'existe pas (%r)" %self._parent ) + if not self.optional and not checker.optional: + checker.err(self, "n'existe pas (%r)" % self._parent) return checker def dump(self, indent=""): @@ -264,14 +278,18 @@ class OJB(AsBase): f = "(f)" else: f = "(o)" - return f +" "+ self.nomj() +" "+ str(self.exists) + return f + " " + self.nomj() + " " + str(self.exists) # ----------------------------------------------------------------------------- -def Facultatif( ojb ): + + +def Facultatif(ojb): ojb.optional = True return ojb # ----------------------------------------------------------------------------- + + class OJBVect(OJB): lonmax = JeveuxIntAttr("LONMAX") lonuti = JeveuxIntAttr("LONUTI") @@ -279,6 +297,8 @@ class OJBVect(OJB): _genr = "V" # ----------------------------------------------------------------------------- + + class OJBPtnom(OJB): nommax = JeveuxIntAttr("NOMMAX") nomuti = JeveuxIntAttr("NOMUTI") @@ -287,60 +307,82 @@ class OJBPtnom(OJB): _type = "K" # ----------------------------------------------------------------------------- + + class OJBCollec(OJB): stockage = JeveuxStrAttr("STOCKAGE") - nutioc = JeveuxIntAttr( "NUTIOC" ) - acces = JeveuxStrAttr( "ACCES" ) - modelong = JeveuxStrAttr( "MODELONG" ) - nmaxoc = JeveuxIntAttr( "NMAXOC" ) + nutioc = JeveuxIntAttr("NUTIOC") + acces = JeveuxStrAttr("ACCES") + modelong = JeveuxStrAttr("MODELONG") + nmaxoc = JeveuxIntAttr("NMAXOC") # ----------------------------------------------------------------------------- + + class AsVI(OJBVect): _type = "I" # ----------------------------------------------------------------------------- + + class AsVS(OJBVect): _type = "S" # ----------------------------------------------------------------------------- + + class AsVR(OJBVect): _type = "R" # ----------------------------------------------------------------------------- + + class AsVC(OJBVect): _type = "C" # ----------------------------------------------------------------------------- + + class AsVL(OJBVect): _type = "L" # ----------------------------------------------------------------------------- + + class AsVK8(OJBVect): _type = "K" _ltyp = 8 # ----------------------------------------------------------------------------- + + class AsVK16(OJBVect): _type = "K" _ltyp = 16 # ----------------------------------------------------------------------------- + + class AsVK24(OJBVect): _type = "K" _ltyp = 24 # ----------------------------------------------------------------------------- + + class AsVK32(OJBVect): _type = "K" _ltyp = 32 # ----------------------------------------------------------------------------- + + class AsVK80(OJBVect): _type = "K" _ltyp = 80 # Pour compatibilite AsObject = OJB -AsColl = OJBCollec -AsPn = OJBPtnom -AsVect = OJBVect +AsColl = OJBCollec +AsPn = OJBPtnom +AsVect = OJBVect diff --git a/Noyau/basetype.py b/Noyau/basetype.py index b3fc2e69..57ab8251 100644 --- a/Noyau/basetype.py +++ b/Noyau/basetype.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,24 +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 -# + """ + Description des types de base aster ----------------------------------- -version 2 - réécrite pour essayer de simplifier -le problème des instances/types et instances/instances. +version 2 - réécrite pour essayer de simplifier +le problème des instances/types et instances/instances. -Le type de base `Type` permet de représenter une structure -de donnée. Une instance de `Type` comme attribut d'une classe -dérivée de `Type` représente une sous-structure nommée. +Le type de base `Type` permet de représenter une structure +de donnée. Une instance de `Type` comme attribut d'une classe +dérivée de `Type` représente une sous-structure nommée. -Une instance de `Type` 'libre' représente une instance de la -structure de donnée complète. +Une instance de `Type` 'libre' représente une instance de la +structure de donnée complète. -C'est ce comportement qui est capturé dans la classe BaseType +C'est ce comportement qui est capturé dans la classe BaseType -La classe `Type` hérite de BaseType et y associe la métaclasse MetaType. +La classe `Type` hérite de BaseType et y associe la métaclasse MetaType. """ @@ -42,41 +43,40 @@ import cPickle __docformat__ = "restructuredtext" - - class MetaType(type): - """Métaclasse d'un type représentant une structure de données. - Les méthodes spéciales __new__ et __call__ sont réimplémentées + + """Métaclasse d'un type représentant une structure de données. + Les méthodes spéciales __new__ et __call__ sont réimplémentées """ - def __new__( mcs, name, bases, classdict ): - """Création d'une nouvelle 'classe' dérivant de Type. + def __new__(mcs, name, bases, classdict): + """Création d'une nouvelle 'classe' dérivant de Type. - Cette méthode permet de calculer certains attributs automatiquement: + Cette méthode permet de calculer certains attributs automatiquement: - L'attribut _subtypes qui contient la liste des sous-structures - de type 'Type' attributs (directs ou hérités) de cette classe. + de type 'Type' attributs (directs ou hérités) de cette classe. - Pour chaque attribut de classe héritant de Type, on recrée une nouvelle - instance des attributs hérités pour pouvoir maintenir une structure de - parentée entre l'attribut de classe et sa nouvelle classe. + Pour chaque attribut de classe héritant de Type, on recrée une nouvelle + instance des attributs hérités pour pouvoir maintenir une structure de + parentée entre l'attribut de classe et sa nouvelle classe. L'effet obtenu est que tous les attributs de classe ou des classes parentes - de cette classe sont des attributs associés à la classe feuille. Ces attributs + de cette classe sont des attributs associés à la classe feuille. Ces attributs ont eux-meme un attribut parent qui pointe sur la classe qui les contient. """ - new_cls = type.__new__( mcs, name, bases, classdict ) + new_cls = type.__new__(mcs, name, bases, classdict) new_cls._subtypes = [] for b in bases: - if hasattr(b,'_subtypes'): + if hasattr(b, '_subtypes'): new_cls._subtypes += b._subtypes # affecte la classe comme parent des attributs de classe - # et donne l'occasion aux attributs de se renommer à partir - # du nom utilisé. + # et donne l'occasion aux attributs de se renommer à partir + # du nom utilisé. for k, v in classdict.items(): - if not isinstance( v, BaseType ): + if not isinstance(v, BaseType): continue - v.reparent( new_cls, k ) - new_cls._subtypes.append( k ) + v.reparent(new_cls, k) + new_cls._subtypes.append(k) return new_cls def dup_attr(cls, inst): @@ -85,30 +85,30 @@ class MetaType(type): """ # reinstantiate and reparent subtypes for nam in cls._subtypes: - obj = getattr( cls, nam ) - # permet de dupliquer completement l'instance - cpy = cPickle.dumps(obj) - newobj = cPickle.loads( cpy ) - newobj.reparent( inst, None ) - setattr( inst, nam, newobj ) + obj = getattr(cls, nam) + # permet de dupliquer completement l'instance + cpy = cPickle.dumps(obj) + newobj = cPickle.loads(cpy) + newobj.reparent(inst, None) + setattr(inst, nam, newobj) def __call__(cls, *args, **kwargs): - """Instanciation d'un Type structuré. - Lors de l'instanciation on effectue un travail similaire à la - création de classe: Les attributs sont re-parentés à l'instance - et réinstanciés pour obtenir une instanciation de toute la structure + """Instanciation d'un Type structuré. + Lors de l'instanciation on effectue un travail similaire à la + création de classe: Les attributs sont re-parentés à l'instance + et réinstanciés pour obtenir une instanciation de toute la structure et de ses sous-structures. Les attributs de classe deviennent des attributs d'instance. """ inst = cls.__new__(cls, *args, **kwargs) # reinstantiate and reparent subtypes - cls.dup_attr( inst ) + cls.dup_attr(inst) type(inst).__init__(inst, *args, **kwargs) return inst def mymethod(cls): - pass + pass class BaseType(object): @@ -122,38 +122,36 @@ class BaseType(object): self._name = None self._parent = None - def reparent( self, parent, new_name ): + def reparent(self, parent, new_name): self._parent = parent self._name = new_name for nam in self._subtypes: - obj = getattr( self, nam ) - obj.reparent( self, nam ) + obj = getattr(self, nam) + obj.reparent(self, nam) def supprime(self, delete=False): - """Permet de casser les boucles de références pour que les ASSD - puissent être détruites. - Si `delete` vaut True, on supprime l'objet lui-même et pas - seulement les références remontantes.""" + """Permet de casser les boucles de références pour que les ASSD + puissent être détruites. + Si `delete` vaut True, on supprime l'objet lui-même et pas + seulement les références remontantes.""" self._parent = None self._name = None for nam in self._subtypes: obj = getattr(self, nam) obj.supprime(delete) - #XXX MC : avec ce code, j'ai l'impression qu'on supprime aussi - # des attributs de classe, ce qui pose problème pour une + # XXX MC : avec ce code, j'ai l'impression qu'on supprime aussi + # des attributs de classe, ce qui pose problème pour une # instanciation future... - # Dans une version précédente, on utilisait l'attribut - # sd_deleted pour ne faire qu'une fois, à voir. - # Supprimer les références remontantes devrait suffir. - #if delete: - #while len(self._subtypes): - #nam = self._subtypes.pop(0) - #try: - #delattr(self, nam) - #except AttributeError: - #pass - - def base( self ): + # Supprimer les références remontantes devrait suffir. + # if delete: + # while len(self._subtypes): + # nam = self._subtypes.pop(0) + # try: + # delattr(self, nam) + # except AttributeError: + # pass + + def base(self): if self._parent is None: return self return self._parent.base() @@ -161,4 +159,3 @@ class BaseType(object): class Type(BaseType): __metaclass__ = MetaType - diff --git a/Noyau/context.py b/Noyau/context.py index 7ba23342..7fa6bf39 100644 --- a/Noyau/context.py +++ b/Noyau/context.py @@ -1,73 +1,83 @@ -# -*- coding: iso-8859-1 -*- -# Copyright (C) 2007-2013 EDF R&D +# coding=utf-8 +# person_in_charge: mathieu.courtois at edf.fr +# ====================================================================== +# COPYRIGHT (C) 1991 - 2012 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 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 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. # -# 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 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. # -# 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 -# -_root=None -_cata=None -debug=0 +# ====================================================================== + +_root = None +_cata = None +debug = 0 from Noyau.N_info import message, SUPERV -# Le "current step" est l'étape courante. -# Une macro se déclare étape courante dans sa méthode Build avant de construire -# ses étapes filles ou dans BuildExec avant de les exécuter. -# Les étapes simples le font aussi : dans Execute et BuildExec. -# (Build ne fait rien pour une étape) +# Le "current step" est l'étape courante. +# Une macro se déclare étape courante dans sa méthode Build avant de construire +# ses étapes filles ou dans BuildExec avant de les exécuter. +# Les étapes simples le font aussi : dans Execute et BuildExec. +# (Build ne fait rien pour une étape) + def set_current_step(step): - """ - Fonction qui permet de changer la valeur de l'étape courante - """ - global _root - if _root : raise Exception("Impossible d'affecter _root. Il devrait valoir None") - _root=step - #message.debug(SUPERV, "current_step = %s", step and step.nom, stack_id=-1) + """ + Fonction qui permet de changer la valeur de l'étape courante + """ + global _root + if _root: + raise Exception("Impossible d'affecter _root. Il devrait valoir None") + _root = step + # message.debug(SUPERV, "current_step = %s", step and step.nom, + # stack_id=-1) + def get_current_step(): - """ - Fonction qui permet d'obtenir la valeur de l'étape courante - """ - return _root + """ + Fonction qui permet d'obtenir la valeur de l'étape courante + """ + return _root + def unset_current_step(): - """ - Fonction qui permet de remettre à None l'étape courante - """ - global _root - _root=None + """ + Fonction qui permet de remettre à None l'étape courante + """ + global _root + _root = None + def set_current_cata(cata): - """ - Fonction qui permet de changer l'objet catalogue courant - """ - global _cata - if _cata : raise Exception("Impossible d'affecter _cata. Il devrait valoir None") - _cata=cata + """ + Fonction qui permet de changer l'objet catalogue courant + """ + global _cata + if _cata: + raise Exception("Impossible d'affecter _cata. Il devrait valoir None") + _cata = cata + def get_current_cata(): - """ - Fonction qui retourne l'objet catalogue courant - """ - return _cata + """ + Fonction qui retourne l'objet catalogue courant + """ + return _cata -def unset_current_cata(): - """ - Fonction qui permet de remettre à None le catalogue courant - """ - global _cata - _cata=None +def unset_current_cata(): + """ + Fonction qui permet de remettre à None le catalogue courant + """ + global _cata + _cata = None diff --git a/Noyau/nommage.py b/Noyau/nommage.py index eddbc7ae..b65e9fe5 100644 --- a/Noyau/nommage.py +++ b/Noyau/nommage.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,26 +16,26 @@ # 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 sert à nommer les concepts produits par les commandes. + Ce module sert à nommer les concepts produits par les commandes. Le nom du concept est obtenu en appelant la fonction GetNomConceptResultat du module avec le nom de la commande en argument. Cette fonction parcourt le source dans lequel la commande se trouve, parse le - fichier et retrouve le nom du concept qui se trouve à gauche du signe = précédant + fichier et retrouve le nom du concept qui se trouve à gauche du signe = précédant le nom de la commande. Cette fonction utilise la fonction cur_frame du module N_utils qui retourne la frame - d'exécution Python située 2 niveaux au-dessus. C'est à partir de cette frame que - l'on retrouve le fichier source et le numéro de ligne où se trouve l'appel à la commande. + d'exécution Python située 2 niveaux au-dessus. C'est à partir de cette frame que + l'on retrouve le fichier source et le numéro de ligne où se trouve l'appel à la commande. """ # Modules Python -import re,string +import re +import string import linecache from functools import partial @@ -44,116 +43,127 @@ from functools import partial import N_utils from strfunc import get_encoding -regex1='=?\s*%s\s*\(' -#commentaire standard precede d'un nombre quelconque de blancs (pas multiligne) -pattern_comment = re.compile(r"^\s*#.*") +regex1 = '=?\s*%s\s*\(' +# commentaire standard precede d'un nombre quelconque de blancs (pas +# multiligne) +pattern_comment = re.compile(r"^\s*#.*") + def _GetNomConceptResultat(ope, level=2): - """ - Cette fonction recherche dans la pile des appels, l'appel à la commande - qui doit etre situé à 2 niveaux au-dessus (cur_frame(2)). - On retrouve d'abord la frame d'exécution f. Puis le numéro de la ligne - dans le source f.f_lineno et le nom du fichier source (f.f_code.co_filename). - A partir de là, on récupère la ligne de source avec linecache.getline - et on vérifie que cette ligne correspond véritablement à l'appel. - - En effet, lorsque les commandes tiennent sur plusieurs lignes, on retrouve - la dernière ligne. Il faut donc remonter dans le source jusqu'à la première - ligne. - - Enfin la fonction evalnom forme un nom acceptable lorsque le concept est un - élément d'une liste, par exemple. - - """ - f=N_utils.cur_frame(level) - lineno = f.f_lineno # XXX Too bad if -O is used - #lineno = f_lineno(f) # Ne marche pas toujours - co = f.f_code - filename = unicode(co.co_filename, get_encoding()) - name = co.co_name - #pattern pour identifier le debut de la commande - pattern_oper=re.compile(regex1 % ope) - - list=[] - while lineno > 0: - line = linecache.getline(filename, lineno) - lineno=lineno-1 - if pattern_comment.match(line):continue - list.append(line) - if pattern_oper.search(line): - l=pattern_oper.split(line) - list.reverse() - # On suppose que le concept resultat a bien ete - # isole en tete de la ligne de source - m=evalnom(string.strip(l[0]),f.f_locals) - #print "NOMS ",m - if m!=[] : return m[-1] - else : return '' - #print "appel inconnu" - return "" - -def evalnom(text,d): - """ - Retourne un nom pour le concept resultat identifie par text - Pour obtenir ce nom il y a plusieurs possibilites : - 1. text est un identificateur python c'est le nom du concept - 2. text est un element d'une liste on construit le nom en - evaluant la partie indice dans le contexte de l'appelant d - """ - l=re.split('([\[\]]+)',text) - if l[-1] == '' :l=l[:-1] - lll=[] - i=0 - while i 0: + line = linecache.getline(filename, lineno) + lineno = lineno - 1 + if pattern_comment.match(line): + continue + list.append(line) + if pattern_oper.search(line): + l = pattern_oper.split(line) + list.reverse() + # On suppose que le concept resultat a bien ete + # isole en tete de la ligne de source + m = evalnom(string.strip(l[0]), f.f_locals) + # print "NOMS ",m + if m != []: + return m[-1] + else: + return '' + # print "appel inconnu" + return "" + + +def evalnom(text, d): + """ + Retourne un nom pour le concept resultat identifie par text + Pour obtenir ce nom il y a plusieurs possibilites : + 1. text est un identificateur python c'est le nom du concept + 2. text est un element d'une liste on construit le nom en + evaluant la partie indice dans le contexte de l'appelant d + """ + l = re.split('([\[\]]+)', text) + if l[-1] == '': + l = l[:-1] + lll = [] + i = 0 + while i < len(l): + s = l[i] + ll = re.split('[ ,]+', s) + if ll[0] == '': + ll = ll[1:] + if len(ll) == 1: + id0 = ll[0] + else: + lll = lll + ll[0:-1] + id0 = ll[-1] + if i + 1 < len(l) and l[i + 1] == '[': # le nom est suivi d un subscript + sub = l[i + 2] + nom = id0 + '_' + str(eval(sub, d)) + i = i + 4 + else: + nom = id0 + i = i + 1 + lll.append(nom) + return lll + def f_lineno(f): - """ - Calcule le numero de ligne courant - Devrait marcher meme avec -O - Semble ne pas marcher en présence de tuples longs - """ - c=f.f_code - if not hasattr(c, 'co_lnotab'):return f.f_lineno - tab=c.co_lnotab - line = c.co_firstlineno - stopat = f.f_lasti - addr = 0 - for i in range(0, len(tab), 2): - addr = addr + ord(tab[i]) - if addr > stopat: - break - line = line + ord(tab[i+1]) - return line + """ + Calcule le numero de ligne courant + Devrait marcher meme avec -O + Semble ne pas marcher en présence de tuples longs + """ + c = f.f_code + if not hasattr(c, 'co_lnotab'): + return f.f_lineno + tab = c.co_lnotab + line = c.co_firstlineno + stopat = f.f_lasti + addr = 0 + for i in range(0, len(tab), 2): + addr = addr + ord(tab[i]) + if addr > stopat: + break + line = line + ord(tab[i + 1]) + return line class NamingSystem(N_utils.Singleton): - """Cette classe définit un système de nommage dynamique des concepts.""" + + """Cette classe définit un système de nommage dynamique des concepts.""" _singleton_id = 'nommage.NamingSystem' - + def __init__(self): """Initialisation""" self.native = _GetNomConceptResultat self.use_global_naming() def use_naming_function(self, function): - """Utilise une fonction particulière de nommage.""" + """Utilise une fonction particulière de nommage.""" self.naming_func = function def use_global_naming(self): @@ -161,7 +171,7 @@ class NamingSystem(N_utils.Singleton): self.naming_func = partial(self.native, level=3) def __call__(self, *args): - """Appel à la fonction de nommage.""" + """Appel à la fonction de nommage.""" return self.naming_func(*args) GetNomConceptResultat = NamingSystem() diff --git a/Noyau/strfunc.py b/Noyau/strfunc.py index 7bdb345e..edb7b31e 100644 --- a/Noyau/strfunc.py +++ b/Noyau/strfunc.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 -# +"""Module rassemblant des fonctions utilitaires de manipulations +de chaines de caractères """ -Module rassemblant des fonctions utilitaires de manipulations -de chaines de caractères -""" -# module identique à Execution/strfunc.py pour usage dans Eficas +# module identique à Execution/strfunc.py pour usage dans Eficas import locale _encoding = None + + def get_encoding(): """Return local encoding """ @@ -63,6 +63,7 @@ def to_unicode(string): pass return unicode(string, 'utf-8', 'replace') + def from_unicode(ustring, encoding, errors='replace'): """Try to encode a unicode string using encoding.""" try: @@ -71,6 +72,7 @@ def from_unicode(ustring, encoding, errors='replace'): pass return ustring.encode(encoding, errors) + def convert(content, encoding=None, errors='replace'): """Convert content using encoding or default encoding if None.""" if type(content) not in (str, unicode): @@ -79,6 +81,7 @@ def convert(content, encoding=None, errors='replace'): content = to_unicode(content) return from_unicode(content, encoding or get_encoding(), errors) + def ufmt(uformat, *args): """Helper function to format a string by converting all its arguments to unicode""" if type(uformat) is not unicode: