I'm running into an issue in a hierarchy of single-table inheritance objects with multiple inheritance. The objects represent users/groups/etc. from various directories and applications.
Retrieving the list of synonyms from an object at the bottom of the inheritance tree doesn't return the entire list of synonyms.
When I make some of the "mixin" type objects abstract the synonyms returned are as expected, but I lose the ability to query those objects.
Maybe I'm overlooking a simpler implementation, or simply using SQLAlchemy in a way that wasn't intended?
Here's a simplified subset of the code. In practice any object ending with Entry and the base DirectoryUser and DirectoryGroup wouldn't be created.
import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class DirectoryEntry(Base):
guid = sa.Column(sa.Integer, primary_key=True)
_type = sa.Column(sa.String, nullable=False, index=True)
distinguished_name = sa.Column(sa.String, index=True)
name = sa.Column(sa.String, index=True)
__tablename__ = 'directory_entry'
__mapper_args__ = {
'polymorphic_on': _type,
'polymorphic_identity': 'directory_entry',
}
class DirectoryUser(DirectoryEntry):
first_name = sa.Column(sa.String)
last_name = sa.Column(sa.String)
email = sa.Column(sa.String)
username = sa.Column(sa.String)
__mapper_args__ = {
'polymorphic_identity': 'directory_user',
}
class LdapEntry(DirectoryEntry):
cn = orm.synonym('name')
__mapper_args__ = {
'polymorphic_identity': 'ldap_entry',
}
class LdapUser(DirectoryUser, LdapEntry):
givenName = orm.synonym('first_name')
sn = orm.synonym('last_name')
__mapper_args__ = {
'polymorphic_identity': 'ldap_user',
}
class ActiveDirectoryEntry(LdapEntry):
distinguishedName = orm.synonym('distinguished_name')
__mapper_args__ = {
'polymorphic_identity': 'active_directory_entry',
}
class ActiveDirectoryUser(LdapUser, ActiveDirectoryEntry):
mail = orm.synonym('email')
sAMAccountName = orm.synonym('username')
__mapper_args__ = {
'polymorphic_identity': 'active_directory_user'
}
engine_url = 'postgresql+psycopg2://postgres@localhost/inherit_test'
engine = sa.create_engine(engine_url, echo=True)
Base.metadata.create_all(engine)
session = orm.sessionmaker(bind=engine)()
ad_user = ActiveDirectoryUser(
cn='John Doe',
sAMAccountName='jdoe',
distinguishedName='ou=domain',
givenName='John'
)
session.add(ad_user)
session.commit()
user1 = session.query(DirectoryUser).filter(DirectoryUser.username == 'jdoe').one()
user3 = session.query(LdapUser).filter(LdapUser.username == 'jdoe').one()
user2 = session.query(ActiveDirectoryUser).filter(ActiveDirectoryUser.username == 'jdoe').one()
user4 = session.query(DirectoryEntry).filter(DirectoryEntry.name == 'John Doe').one()
assert(user1 == user2 == user3 == user4)
mapper = sa.inspect(ad_user.__class__)
synonyms = mapper.synonyms.keys()
assert(synonyms == ['mail', 'sAMAccountName', 'givenName', 'sn', 'cn', 'distinguishedName'])
Any help is appreciated!