Thank you Mike, it works !

Le samedi 24 février 2018 16:35:57 UTC+1, Mike Bayer a écrit :
>
> On Sat, Feb 24, 2018 at 5:33 AM, Sven <sven....@gmail.com <javascript:>> 
> wrote: 
> > Hello, 
> > 
> > I have now a small example which illustrates the problem. 
> > 
> > Program logic : each NPC inherites from Character and each NPC is based 
> on a 
> > prototype. It means, for example, that you can define the prototype 
> > "red_guard" and then create 100 red guards all based on this prototype. 
> Most 
> > part of the NPC attributes are stored in the class Prototype. For 
> example, I 
> > can define in the prototype that a red guard has 1000 health point and 
> it 
> > will be reflected automatically in every NPC based on the prototype. 
> This is 
> > why, the __getattr_ function of NPC is looking in the prototype 
> attributes. 
>
>
> your NPC class is making it impossible to test if the class has an 
> attribute present or not and additionally `__getattr__()` assumes that 
> the "self.prototype" attribute is present, when it's not, causing an 
> endless loop: 
>
> class Character(object): 
>     def __init__(self): 
>         if hasattr(self, '_foo'): 
>             print("yup") 
>
>
> class Prototype(object): 
>     pass 
>
>
> class NPC(Character): 
>     def __init__(self): 
>         Character.__init__(self) 
>         self.prototype = Prototype() 
>
>     def __getattr__(self, nom_attr): 
>         return getattr(self.prototype, nom_attr) 
>
> NPC() 
>
>
> using pdb  inside of __getattr__ would reveal that the attributes 
> being asked for here start with underscores, so one way to work around 
> this is: 
>
>     def __getattr__(self, nom_attr): 
>         if nom_attr.startswith("_"): 
>             return object.__getattribute__(self, nom_attr) 
>         else: 
>             return getattr(self.prototype, nom_attr) 
>
>
>
>
>
>
>
>
> > 
> > Code: 
> > 
> > from sqlalchemy import create_engine 
> > from sqlalchemy.orm import sessionmaker 
> > from sqlalchemy.ext.declarative import declarative_base 
> > from sqlalchemy import Column, Integer, String, ForeignKey 
> > from sqlalchemy import orm 
> > from sqlalchemy.orm import relationship 
> > 
> > BaseBDD = declarative_base() 
> > engine = create_engine('sqlite:///getattr_loop.db', echo=True) 
> > Session = sessionmaker(bind=engine) 
> > session = Session() 
> > 
> > class Prototype(BaseBDD): 
> >     __tablename__ = "prototypes" 
> >     id = Column(Integer, primary_key=True) 
> > 
> >     npc = relationship("NPC", back_populates="prototype") 
> > 
> > class Character(BaseBDD): 
> >     __tablename__ = "personnages" 
> >     id = Column(Integer, primary_key=True) 
> > 
> >     type = Column(String) 
> > 
> >     __mapper_args__ = { 
> >         'polymorphic_on':type, 
> >         'polymorphic_identity':'personnage' 
> >     } 
> > 
> > class NPC(Character): 
> > 
> >     prototype_id = Column(ForeignKey('prototypes.id')) 
> >     prototype = relationship("Prototype", back_populates="npc") 
> > 
> >     __mapper_args__ = { 
> >         'polymorphic_identity':'npc' 
> >     } 
> > 
> >     def __init__(self, prototype): 
> >         Character.__init__(self) 
> >         self.prototype = prototype 
> >         prototype.npc.append(self) 
> > 
> >     def __getattr__(self, nom_attr): 
> >         return getattr(self.prototype, nom_attr) 
> > 
> > BaseBDD.metadata.create_all(engine) 
> > 
> > proto_jean = Prototype() 
> > jean = NPC(proto_jean) 
> > 
> > Trace: 
> > 
> > Traceback (most recent call last): 
> >   File "C:\Users\Sven\Downloads\loop_test_trace.py", line 52, in 
> <module> 
> >     jean = NPC(proto_jean) 
> >   File "<string>", line 2, in __init__ 
> >   File 
> "C:\Python34\lib\site-packages\sqlalchemy\orm\instrumentation.py", 
> > line 379, in _new_state_if_none 
> >     if hasattr(instance, self.STATE_ATTR): 
> >   File "C:\Users\Sven\Downloads\loop_test_trace.py", line 47, in 
> __getattr__ 
> >     return getattr(self.prototype, nom_attr) 
> >   File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", 
> line 
> > 242, in __get__ 
> >     return self.impl.get(instance_state(instance), dict_) 
> >   File "C:\Users\Sven\Downloads\loop_test_trace.py", line 47, in 
> __getattr__ 
> >     return getattr(self.prototype, nom_attr) 
> >   File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", 
> line 
> > 242, in __get__ 
> >     return self.impl.get(instance_state(instance), dict_) 
> >   File "C:\Users\Sven\Downloads\loop_test_trace.py", line 47, in 
> __getattr__ 
> >     return getattr(self.prototype, nom_attr) 
> >   File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", 
> line 
> > 242, in __get__ 
> >     return self.impl.get(instance_state(instance), dict_) 
> >   File "C:\Users\Sven\Downloads\loop_test_trace.py", line 47, in 
> __getattr__ 
> >     return getattr(self.prototype, nom_attr) 
> > 
> > Unfortunately, the line "return getattr(self.prototype, nom_attr)" is 
> > causing an endless loop. 
> > 
> > Has someone a solution ? How can I avoid this loop ? 
> > 
> > Thank you ! 
> > 
> > Sven 
> > 
> > 
> > -- 
> > SQLAlchemy - 
> > The Python SQL Toolkit and Object Relational Mapper 
> > 
> > http://www.sqlalchemy.org/ 
> > 
> > To post example code, please provide an MCVE: Minimal, Complete, and 
> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> > description. 
> > --- 
> > You received this message because you are subscribed to the Google 
> Groups 
> > "sqlalchemy" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an 
> > email to sqlalchemy+...@googlegroups.com <javascript:>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:>. 
> > Visit this group at https://groups.google.com/group/sqlalchemy. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to