Override a read-only property with a read-only column that gets the same value

The game engine provides me with the Player class, which has a uniqueid read-only property to identify players. I would like to β€œconvert” this to an SQLAlchemy Column so that I can query the players this way:

 query = session.query(Player).filter(Player.uniqueid=='STEAM_0:0:1234567') player = query.one_or_none() if player is None: player = Player(uniqueid='STEAM_0:0:1234567') 

Here my class is as follows:

 class Player(game.Player, db.Model): _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False) def __init__(self, index, **kwargs): game.Player.__init__(index) # initializes uniqueid db.Model.__init__(_uniqueid=self.uniqueid, **kwargs) 

Further, I would like to create a read-only interface for _uniqueid , so API users will no longer be able to write a variable (well, they can through _uniqueid , but this depends on their responsibility, since access to it must occur through non-private uniqueid ).

I am thinking of overriding the original uniqueid new one:

 @property def uniqueid(self): return self._uniqueid 

It is read-only and β€œhides” the original _uniqueid , not allowing anyone to write on it unless they intentionally turn to the closed one (I will not even list it in the documentation, private).

The only problem is that it completely overrides the old one, which means that my __init__ _uniqueid=self.uniqueid will not work due to self.uniqueid using the new getter, not the old one.

So, I want to convert a read-only property to a read-only message that can be used to query using SQLAlchemy. Is this possible, and if, how?

+8
python sqlalchemy
source share
1 answer

You can use super to access the game.Player property. We can test using a simple C extension type created using Cython:

 # game.pyx cdef class Player: cdef int index; def __init__(self, index): self.index = index @property def uniqueid(self): return "foo" # test.py class Player(game.Player, Base): __tablename__ = "player" id = Column(Integer, primary_key=True) _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False) def __init__(self, index, **kwargs): game.Player.__init__(self, index) # initializes uniqueid Base.__init__(self, _uniqueid=super().uniqueid, **kwargs) @property def uniqueid(self): return self._uniqueid print(Player(1).uniqueid) # "foo" 

Due to the instability of inheritance from C extension types, this may or may not work depending on what type of C is used for the game.Player type.

In addition, since ORM bypasses __init__ when it loads instances from the database, you need to connect to load to initialize the game.Player type.

+1
source share

All Articles