From d124679f978696866a934c155fab666728df35a9 Mon Sep 17 00:00:00 2001 From: cvs2git Date: Thu, 14 Jun 2007 16:19:32 +0000 Subject: [PATCH] This commit was manufactured by cvs2git to create tag 'V_12a1'. Sprout from BR_V1_12a1 2007-06-14 16:19:31 UTC Pascale Noyret 'modif mathieu courtois' Cherrypick from BR_V1_12a1 2007-04-26 07:56:11 UTC Christian Caremoli 'CCAR: Creation de la version Eficas 1.12 avec mise a niveau Aster 9.0.16': Sdbase/__init__.py Sdbase/ascheckers.py Sdbase/asnom.py Sdbase/asojb.py Sdbase/basetype.py --- Sdbase/__init__.py | 3 + Sdbase/ascheckers.py | 70 ++++++++++ Sdbase/asnom.py | 133 +++++++++++++++++++ Sdbase/asojb.py | 304 +++++++++++++++++++++++++++++++++++++++++++ Sdbase/basetype.py | 156 ++++++++++++++++++++++ 5 files changed, 666 insertions(+) create mode 100644 Sdbase/__init__.py create mode 100644 Sdbase/ascheckers.py create mode 100644 Sdbase/asnom.py create mode 100644 Sdbase/asojb.py create mode 100644 Sdbase/basetype.py diff --git a/Sdbase/__init__.py b/Sdbase/__init__.py new file mode 100644 index 00000000..9c2d49df --- /dev/null +++ b/Sdbase/__init__.py @@ -0,0 +1,3 @@ + +import asojb +from asojb import AsBase diff --git a/Sdbase/ascheckers.py b/Sdbase/ascheckers.py new file mode 100644 index 00000000..fc6a9b4d --- /dev/null +++ b/Sdbase/ascheckers.py @@ -0,0 +1,70 @@ +#@ MODIF ascheckers SD DATE 13/02/2007 AUTEUR PELLET J.PELLET +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2007 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. +# ====================================================================== + +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 ): + if value not in self.values: + self.values.append( value ) + + 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) ) + + def __repr__(self): + 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""" + def __init__(self): + self.msg = [] + self.names = {} + self.optional = False + + def log(self, level, obj, msg ): + self.msg.append( (level, obj.nomj(), msg) ) + + def err(self, obj, msg ): + self.log( 0, obj, msg ) + + def warn(self, obj, msg ): + self.log( 1, obj, msg ) + + def visit(self, obj ): + self.names[obj.nomj()] = 1 + + 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 ]) + +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) ) diff --git a/Sdbase/asnom.py b/Sdbase/asnom.py new file mode 100644 index 00000000..89a541b8 --- /dev/null +++ b/Sdbase/asnom.py @@ -0,0 +1,133 @@ +#@ MODIF asnom SD DATE 13/02/2007 AUTEUR PELLET J.PELLET +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2007 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. +# ====================================================================== + +""" +Description des types de base aster + +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. + +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 +""" + +from basetype import Type + +class SDNom(Type): + """Objet représentant une sous-partie de nom + d'objet jeveux""" + nomj = None + debut = None + fin = None + just = None + justtype = None + + 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 + just : la justification a droite ou a gauche ('l' ou 'r') + 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 + 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) ) + + def __call__(self): + if self._parent is None or self._parent._parent is None: + debut = self.debut or 0 + prefix = ' '*debut + else: + # normalement + # assert self._parent.nomj is self + nomparent = self._parent._parent.nomj + prefix = nomparent() + debut = self.debut or nomparent.fin or len(prefix) + fin = self.fin or 24 + nomj = self.nomj or '' + nomj = self.just( nomj, fin-debut ) + prefix = prefix.ljust(24) + res = prefix[:debut]+nomj+prefix[fin:] + return res[:24] + + def fcata(self): + return self.just(self.nomj,self.fin-self.debut).replace(' ','?') + + def __repr__(self): + 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) + + def __getstate__(self): + return (self.nomj, self.debut, self.fin, self.justtype ) + + def __setstate__( self, (nomj,debut,fin,just) ): + self.nomj = nomj + self.debut = debut + self.fin = fin + if just=='l' or just is None: + self.just = str.ljust + elif just=='r': + self.just = str.rjust + else: + raise ValueError("Justification '%s' invalide" % just ) + self.justtype = just + + + def update( self, (nomj,debut,fin,just) ): + if nomj is not None: + self.nomj = nomj + if self.debut is None: + self.debut = debut + if self.fin is None: + self.fin = fin + if self.justtype is None and just is not None: + if just=='l': + self.just = str.ljust + elif just=='r': + self.just = str.rjust + else: + raise ValueError("Justification '%s' invalide" % just ) + self.justtype = just + + 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 ) + if self.nomj is None and self._parent._name is not None: + self.nomj = "." + self._parent._name + + diff --git a/Sdbase/asojb.py b/Sdbase/asojb.py new file mode 100644 index 00000000..9e3c9e70 --- /dev/null +++ b/Sdbase/asojb.py @@ -0,0 +1,304 @@ +#@ MODIF asojb SD DATE 13/02/2007 AUTEUR PELLET J.PELLET +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2007 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. +# ====================================================================== + +""" + Description des OJB jeveux +""" +from basetype import Type, MetaType +from asnom import SDNom +from ascheckers import CheckLog + +# pour utilisation dans eficas +try: + import aster +except: + pass + +# ----------------------------------------------------------------------------- +class AsBase(Type): + nomj = SDNom() + optional = False + + 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 ): + self.nomj.nomj = nomj + 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" + self.nomj.nomj = nomj + + def check(self, checker=None): + if checker is None: + checker = CheckLog() + + # 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) ): + v.check(checker) + for name in dir(self): + if name.startswith( 'check_' ): + v = getattr(self, name) + if callable(v): + v( checker ) + + checker.optional = optional + return checker + + def members( self ): + pass + + def dump(self, indent=""): + import pydoc + l = [] + checkers = [] + nomj = self.nomj() + if self.optional: + f = "(f)" + else: + f = "(o)" + l.append( f+" "+nomj ) + #l.append( '-'*(len(nomj)+3) ) + for name in self._subtypes: + obj = getattr(self, name) + if isinstance(obj,(AsBase,OJB)): + l.append( obj.dump(indent) ) + for name in dir(self): + if name.startswith( 'check_' ): + obj = getattr(self, name) + if callable(obj) and name.startswith("check_"): + checkers.append( obj ) + + indent = " "*len(nomj) + for checker in checkers: + doc = pydoc.text.document( checker ) + for line in doc.splitlines(): + l.append( indent + line ) + return "\n".join( l ) + + def __repr__(self): + return "<%s(%x,%r)>" % (self.__class__.__name__, id(self), self.nomj() ) + + +# ----------------------------------------------------------------------------- +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 ) + if checker is None: + return True + val = self.__get__( obj, obj.__class__ ) + if callable( checker ): + return checker( obj, attrname, val, log ) + else: + test = val == checker + if not test: + log.err( obj, "Attribut incorrect %s %r!=%r" % (self.name, val, checker ) ) + return test + +# ----------------------------------------------------------------------------- +class JeveuxExists(JeveuxAttr): + def __init__(self): + pass + + def __get__(self, obj, klass): + if obj is None: + return self + nomj = obj.nomj() + if len(nomj)!=24: + raise AssertionError(repr(nomj)) + return aster.jeveux_exists( nomj.ljust(24) ) + +# ----------------------------------------------------------------------------- +class JeveuxIntAttr(JeveuxAttr): + def __get__(self, obj, klass): + if obj is None: + return self + return aster.jeveux_getattr( obj.nomj(), self.name )[0] + +# ----------------------------------------------------------------------------- +class JeveuxStrAttr(JeveuxAttr): + def __get__(self, obj, klass): + if obj is None: + return self + return aster.jeveux_getattr( obj.nomj(), self.name )[1].strip() + +# ----------------------------------------------------------------------------- +class OJB(AsBase): + _clas = None + _genr = None + _type = None + _ltyp = None + _xous = None + _docu = None + _exists = True + + clas = JeveuxStrAttr("CLAS") + genr = JeveuxStrAttr("GENR") + type = JeveuxStrAttr("TYPE") + ltyp = JeveuxIntAttr("LTYP") + 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 ) + self.optional = attrs.get('optional', False) + + def setattribute( self, name, prop, attrs ): + _name = "_"+name + if name in attrs: + 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 ) + else: + return None + + def get_stripped(self): + """Fonction utilitaire, renvoie une liste de chaines 'strippées'""" + data = self.get() + if data is not None: + return [ x.strip() for x in self.get() ] + else: + return [] + + def foreachattr(self, callable, *args, **kwargs): + klass = self.__class__ + for k in dir(klass): + v = getattr( klass, k ) + if isinstance(v, JeveuxAttr): + callable( 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 + if self.nomj() in checker.names.keys(): + return checker + checker.visit( self ) + if self.exists: + 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 ) + return checker + + def tous_compris(self, checker, vmin=None, vmax=None): + # Vérifie que toutes les valeurs du vecteur sont comprises entre vmin et vmax + # Les bornes vmin et vmax sont autorisées + assert vmin or vmax, 'Il faut fournir au moins une des valeurs vmin ou vmax' + vect = self.get() + if not vect : return + ier = 0 + for v in vect : + if vmin and v < vmin : ier = 1 + if vmax and v > vmax : ier = 1 + if ier == 1 : checker.err( self, "L'objet doit contenir des valeurs dans l'intervalle : %s %s " % (vmin,vmax)) + + def dump(self, indent=""): + if self.optional: + f = "(f)" + else: + f = "(o)" + return f +" "+ self.nomj() +" "+ str(self.exists) + +# ----------------------------------------------------------------------------- +def Facultatif( ojb ): + ojb.optional = True + return ojb + +# ----------------------------------------------------------------------------- +class OJBVect(OJB): + lonmax = JeveuxIntAttr("LONMAX") + lonuti = JeveuxIntAttr("LONUTI") + +# ----------------------------------------------------------------------------- +class OJBCollec(OJB): + stockage = JeveuxStrAttr("STOCKAGE") + nutioc = JeveuxIntAttr( "NUTIOC" ) + acces = JeveuxStrAttr( "ACCES" ) + modelong = JeveuxStrAttr( "MODELONG" ) + nmaxoc = JeveuxIntAttr( "NMAXOC" ) + +# ----------------------------------------------------------------------------- +class AsVI(OJBVect): + _type = "I" + +# ----------------------------------------------------------------------------- +class AsVR(OJBVect): + _type = "R" + +# ----------------------------------------------------------------------------- +class AsVC(OJBVect): + _type = "C" + +# ----------------------------------------------------------------------------- +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 +AsColl = OJBCollec +AsObject = OJB diff --git a/Sdbase/basetype.py b/Sdbase/basetype.py new file mode 100644 index 00000000..050ec233 --- /dev/null +++ b/Sdbase/basetype.py @@ -0,0 +1,156 @@ +#@ MODIF basetype SD DATE 13/02/2007 AUTEUR PELLET J.PELLET +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2007 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. +# ====================================================================== + +""" +Description des types de base aster +----------------------------------- + +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. + +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 + +La classe `Type` hérite de BaseType et y associe la métaclasse MetaType. + +""" +from copy import copy,deepcopy +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 + """ + 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: + + - L'attribut _subtypes qui contient la liste des sous-structures + 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. + + 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 + ont eux-meme un attribut parent qui pointe sur la classe qui les contient. + """ + new_cls = type.__new__( mcs, name, bases, classdict ) + new_cls._subtypes = [] + for b in bases: + 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é. + for k, v in classdict.items(): + if not isinstance( v, BaseType ): + continue + v.reparent( new_cls, k ) + new_cls._subtypes.append( k ) + return new_cls + + def dup_attr(cls, inst): + """Duplique les attributs de la classe `cls` pour qu'ils deviennent + des attributs de l'instance `inst`. + """ + # 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 ) + + 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 + 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 ) + type(inst).__init__(inst, *args, **kwargs) + return inst + + def mymethod(cls): + pass + + +class BaseType(object): + # Le parent de la structure pour les sous-structures + _parent = None + _name = None + + def __init__(self, *args, **kwargs): + self._initargs = args + self._initkwargs = kwargs + self._name = None + self._parent = None + + 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 ) + + def base( self ): + if self._parent is None: + return self + return self._parent.base() + + def change_type(self, new_type, nomj=None): + """Méthode appelée quand on change a posteriori le type + du concept (pour les 'CO'). + Si `nomj` est None, on prend `self.nom`. + """ + self.__class__ = new_type + nomj = nomj or self.nom + new_type.dup_attr(self) + + # Comment appeler AsBase.__init__ ? + # type(nomj)=str donc plus simple que dans AsBase.__init__... + assert isinstance(nomj, str), 'Valeur inattendue pour nomj : %s' % nomj + assert self.nomj is not self.__class__.nomj + self.nomj.nomj = nomj + + +class Type(BaseType): + __metaclass__ = MetaType + -- 2.39.2