Hello,

I'm actually working on an online-game which is already advanced and pretty 
consequent. As I explained in a previous mail, my goal is to replace the 
save system actually based on Pickle by SQLAlchemy. If it is possible, it 
would be better for me to stay with the initial classes organizations and 
try to map it to the Database without changing anything.

It is a MUD, a textual game. Each player is in a room and each room 
contains exits leading to other rooms. For example :

Player Brian is in a room "kitchen". The room "kitchen" contains an exit 
"north" leading to the room "bathroom". If player Brian type "north", he 
leaves the kitchen and goes in the bathroom.

Here is my classes organization :

Each room contains an instance of the class "Exits". Exits is a class 
container which contains an OrderedDict always based on the same template : 

EXIT_NAMES = OrderedDict()
EXIT_NAMES["south"] = None
EXIT_NAMES["southwest"] = None
EXIT_NAMES["west"] = None
EXIT_NAMES["northwest"] = None
EXIT_NAMES["north"] = None
EXIT_NAMES["northeast"] = None
EXIT_NAMES["east"] = None
EXIT_NAMES["southeast"] = None

Initially, everything is setted by None. The room has no exit. When an exit 
is added, for example at the north of the room, EXIT_NAMES["north"] 
contains an instance of the class "Exit".

Only the values different from None have to be inserted in the Database.

I found the following example about the mapping of the OrderedDict in the 
SQLAlchemy documentation :

http://docs.sqlalchemy.org/en/latest/orm/collections.html#custom-dictionary-based-collections

I tried to use it and here is what I have done so far :

from collections import OrderedDict
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy import orm
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, Boolean, String, ForeignKey
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.orm.collections import column_mapped_collection
from sqlalchemy.util import OrderedDict
from sqlalchemy.orm.collections import MappedCollection, collection
 
Base = declarative_base()
 
EXIT_NAMES = OrderedDict()
EXIT_NAMES["south"] = None
EXIT_NAMES["southwest"] = None
EXIT_NAMES["west"] = None
EXIT_NAMES["northwest"] = None
EXIT_NAMES["north"] = None
EXIT_NAMES["northeast"] = None
EXIT_NAMES["east"] = None
EXIT_NAMES["southheast"] = None
 
class OrderedExits(OrderedDict, MappedCollection):
 
      def __init__(self, *args, **kw):
            MappedCollection.__init__(self, keyfunc=lambda node: node.name)
            OrderedDict.__init__(self, *args, **kw)
 
class Exits(Base):
 
            __tablename__ = "exits_container"
            id = Column(Integer, primary_key=True)
            exits = relationship("Exit", collection_class=OrderedExits)
 
            def __init__(self):
                        self.exits = OrderedExits(EXIT_NAMES)
 
            def __repr__(self): 
                        text = ""
                        for s in self.exits.keys():
                                    text = text + s + " : " + str(self.exits
[s]) + "\n"
                        return text
 
class Exit(Base):
 
            __tablename__ = "exit"
            id = Column(Integer, primary_key=True)
            id_sorties = Column(Integer, ForeignKey("exits_container.id"), 
nullable = False)
 
            direction = Column(String)
 
            def __init__(self, direction):
                        self.direction = direction
 
            def __repr__(self):
                        return self.direction
 
if __name__ == '__main__':
 
            engine = create_engine(
'postgresql://USERNAME:PASSWORD@localhost/DATABASE', echo = True)
 
            Base.metadata.create_all(engine)
 
            Session = sessionmaker(bind=engine)
            session = Session()
 
            south = Exit("south")
            west = Exit("west")
           
            e = Exits()
 
            e.exits["south"] = south
            e.exits["west"] = west
 
            session.add(south)
            session.add(west)
            session.add(e)
 
            session.commit()
 
            print(e)


Here is the error that I get :

Traceback (most recent call last):
  File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 72, 
in <module>
    e = Exits()
  File "<string>", line 4, in __init__
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\state.py", line 415, 
in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "C:\Python34\lib\site-packages\sqlalchemy\util\langhelpers.py", line 
66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "C:\Python34\lib\site-packages\sqlalchemy\util\compat.py", line 187, 
in reraise
    raise value
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\state.py", line 412, 
in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 38, 
in __init__
    self.exits = OrderedExits(EXIT_NAMES)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", line 
229, in __set__
    instance_dict(instance), value, None)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\attributes.py", line 
1082, in set
    new_values = list(iterable)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\collections.py", line 
1535, in _convert
    new_key = self.keyfunc(value)
  File "C:\Users\Sven\Desktop\SQL Alchemy Tests\ordereddict.py", line 28, 
in <lambda>
    MappedCollection.__init__(self, keyfunc=lambda node: node.name)
AttributeError: 'NoneType' object has no attribute 'name'

SQLAlchemy doesn't know what to do with the None values, which is logical. 
How can I say to SQLAlchemy to ignore these values and how can I be sure 
that SQLAlchemy will be able to populate my objects and set the exits and 
the None values at the loading of the program ? What is the good way to 
proceed ?

Thank you !

Regards,

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