How to "Inspect" Custom Types in Sqlalchemy
I Have a Very Simple Choicestring Custom Column/Data Type: Class Choicestring(Types. Typedecorator): Impl = Types. String Def __Init__(Self, Choices, **Kw)...
I have a very simple ChoiceString custom column/data type:
class ChoiceString(types.TypeDecorator):
impl = types.String
def __init__(self, choices, **kw):
self.choices = dict(choices)
super(ChoiceString, self).__init__(**kw)
def process_bind_param(self, value, dialect):
return [k for k, v in self.choices.iteritems() if v == value][0]
def process_result_value(self, value, dialect):
return self.choices[value]
And I am iterating over the table columns using a mapper:
from sqlalchemy.inspection import inspect
mapper = inspect(SomeTableClass)
for col in mapper.columns:
print col
# how to check the choice values?
print dir(mapper.columns[col]) # does not show the 'choices' attribute
print dir(inspect(mapper.columns[col])) # does not show the 'choices' attribute
print mapper.columns[col].choices # error
But I am can't seem to access the choices custom attribute of the custom type. I also tried "inspecting" the column directly instead of the class, but that doesn't work either.
So how do we access custom attributes of custom types in sqlalchemy, while inspecting?
2 Answers
You're inspecting the Column objects, not their types. Access the type through the type attribute of a Column object:
In [9]: class SomeTableClass(Base):
...: __tablename__ = 'sometableclass'
...: id = Column(Integer, primary_key=True)
...: choices = Column(ChoiceString({ 'asdf': 'qwer'}))
...:
In [10]: mapper = inspect(SomeTableClass)
In [12]: mapper.columns['choices']
Out[12]: Column('choices', ChoiceString(), table=<sometableclass>)
In [13]: mapper.columns['choices'].type.choices
Out[13]: {'asdf': 'qwer'}
The columns can be accessed through the __table__.columns collection. The type and the underlying python type can be accessed through col.type and cole.type.python_type, e.g:
import enum
from sqlalchemy import Column, Enum, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Gender(enum.Enum):
MALE = "male"
FEMALE = "female"
class Person(Base):
__tablename__ = "table_person"
id = Column(Integer, primary_key=True)
name = Column(String(20))
gender = Column(Enum(Gender))
address = Column(Text)
def test_inspect_columns():
col_id = Person.__table__.columns["id"]
assert isinstance(col_id.type, Integer)
assert col_id.type.python_type is int
col_name = Person.__table__.columns["name"]
assert isinstance(col_name.type, String)
assert col_name.type.python_type is str
col_gender = Person.__table__.columns["gender"]
assert isinstance(col_gender.type, Enum)
assert col_gender.type.python_type is Gender
col_address = Person.__table__.columns["address"]
assert isinstance(col_address.type, Text)
assert col_address.type.python_type is str