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.

*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+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