Hello,

I am actually working on an existing project (an online-game) which is 
already advanced and pretty consequent.

My goal is to replace the save system actually based on Pickle by 
SQLAlchemy. Not so easy because I have to deal with the existing classes 
and there is a lot of work to do (about 400 classes to persist).

I'm not sure to know what is the best way to proceed and I think that I 
require some help.

*Let's look at the classes organization of the project :*

<https://lh3.googleusercontent.com/-rfFB3ExzCXg/WeoZakWziFI/AAAAAAAAAVM/RACvOxxZmSgySRTIswpSNtYO9fd_ht-PgCLcBGAs/s1600/schema2.png>


Every class which should be persistent has to be inherited from Stockable. 
It is already designed this way and I think that it would be too 
complicated to change that. Below Stockable, there is hundred of classes 
with their own hierarchy. For example, Character is inherited from 
Stockable and Player and NPC (Non-player Character) are inherited from 
Character.

My problem today is that I don't know how to proceed regarding the 
metaclass "MetaBase". I am not able to use declarative_base() and MetaBase 
at the same time. There is a metabase conflict. I found some other topics 
about this problem on the internet and I tried several solutions, but 
still, it never works for me. 

*To resume, here is how it basically works without SQLAlchemy :*

class MetaBase(type):

    def __init__(cls, nom, bases, contenu):
        type.__init__(cls, nom, bases, contenu)
        pass

class Stockable(metaclass = MetaBase):

    def __init__(self):
        pass


class Character(Stockable):
 
    def __init__(self):
        pass


*Here is what I would like to do with SQLAlchemy:*

from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy import Column, Integer

Base = declarative_base()

class MetaBase(DeclarativeMeta):

    def __init__(cls, nom, bases, contenu):
        super(MetaBase, cls).__init__(nom, bases, contenu)
        print("Init MetaBase")


class Stockable(metaclass = MetaBase):

    def __init__(self):
        print("Init Stockable")

class Character(Stockable, Base):

    __tablename__ = 'characters'
    id = Column(Integer, primary_key=True)
 
    def __init__(self, name):
        self.name = name
        print("Init character")


jean = Character("Jean")
print(jean.name)


Here is what I get :

>>> 
Traceback (most recent call last):
  File "C:\Users\Sven\Desktop\SQL Alchemy Tests\test2.py", line 10, in 
<module>
    class Stockable(metaclass = MetaBase):
  File "C:\Users\Sven\Desktop\SQL Alchemy Tests\test2.py", line 7, in 
__init__
    super(MetaBase, cls).__init__(nom, bases, contenu)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\api.py", 
line 64, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 88, in _as_declarative
    _MapperConfig.setup_mapping(cls, classname, dict_)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 103, in setup_mapping
    cfg_cls(cls_, classname, dict_)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 125, in __init__
    clsregistry.add_class(self.classname, self.cls)
  File 
"C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\clsregistry.py", 
line 34, in add_class
    if classname in cls._decl_class_registry:
AttributeError: type object 'Stockable' has no attribute 
'_decl_class_registry'
>>>

Does someone knows what it means and how it can be resolved ?

*I tried other things and I found the following solution :*

from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy import Column, Integer

class MetaBase(DeclarativeMeta):

    def __init__(cls, nom, bases, contenu):
        super(MetaBase, cls).__init__(nom, bases, contenu)
        print("Init MetaBase")

Base = declarative_base(metaclass = MetaBase)

class Stockable(Base):

    __abstract__ = True

    def __init__(self):
        print("Init Stockable")

class Character(Stockable):

    __tablename__ = 'characters'
    id = Column(Integer, primary_key=True)
 
    def __init__(self, name):
        self.name = name
        print("Init character")


jean = Character("Jean")
print(jean.name)


It seems to work. I get the following result :

>>> 
Init MetaBase
Init MetaBase
Init MetaBase
Init compte
Jean
>>>

However, the problem with this method is that I have to add *"__abstract__ 
= True" *to every class which is inherited by Stockable... so, about 400 
classes. It is not very clean. Is it possible to avoid that by using 
something similar to my first code ? It would be great !

Thank you very much.

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