I've been spending the past few hours trying to
understand/debug a problem I'm having with my single-table inheritance mapping.
I am attaching the code for a test case that results in an attribute error. The
relevant pieces (I think) are shown below. They result in an AttributeError in
the sessionlib.attribute_manager.reset_class_managed on the first inherited
mapper of Node (Algorithm, or Parameter if commenting out
Algorithm)
projects_table = Table('projects', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(40)))
Column('id', Integer, primary_key=True),
Column('name', String(40)))
versions_table = Table('versions', metadata,
Column('project_id', Integer, ForeignKey('projects.id'), primary_key=True),
Column('id', Integer, primary_key=True),
Column('date', DateTime),
Column('comment', String(300)))
Column('project_id', Integer, ForeignKey('projects.id'), primary_key=True),
Column('id', Integer, primary_key=True),
Column('date', DateTime),
Column('comment', String(300)))
node_types = {'Node':0, 'Algorithm':1,'Parameter':2}
nodes_table = Table('nodes', metadata,
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('name', String(30)),
Column('description', String(80)),
Column('comments', String),
Column('start_version_id', Integer),
Column('end_version_id', Integer),
Column('sub_project_id', Integer, ForeignKey('projects.id')),
Column('sub_project_version_id', Integer),
Column('parameter_type', Integer),
Column('value', String),
Column('previous_id', Integer, ForeignKey('nodes.id')),
ForeignKeyConstraint(
['project_id','start_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['project_id','end_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['sub_project_id','sub_project_version_id'],
['versions.project_id','versions.id'])
)
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('name', String(30)),
Column('description', String(80)),
Column('comments', String),
Column('start_version_id', Integer),
Column('end_version_id', Integer),
Column('sub_project_id', Integer, ForeignKey('projects.id')),
Column('sub_project_version_id', Integer),
Column('parameter_type', Integer),
Column('value', String),
Column('previous_id', Integer, ForeignKey('nodes.id')),
ForeignKeyConstraint(
['project_id','start_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['project_id','end_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['sub_project_id','sub_project_version_id'],
['versions.project_id','versions.id'])
)
projects_table.create(checkfirst=True)
versions_table.create(checkfirst=True)
nodes_table.create(checkfirst=True)
versions_table.create(checkfirst=True)
nodes_table.create(checkfirst=True)
class Project(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
class Version(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
self.date = self.date or time.strftime("%Y-%m-%d %H:%M:%S")
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
self.date = self.date or time.strftime("%Y-%m-%d %H:%M:%S")
class Node(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
class Algorithm(Node):
pass
pass
class Parameter(Node):
pass
pass
class VersionKeyMapper(MapperExtension):
def before_insert(self, mapper, connection, instance):
versions_t = mapper.select_table
s = select(
[func.max(versions_t.c.id)+1],
versions_t.c.project_id==instance.project_id
)
r = s.execute()
new_id = r.fetchone()[0]
instance.id = new_id or 1
def before_insert(self, mapper, connection, instance):
versions_t = mapper.select_table
s = select(
[func.max(versions_t.c.id)+1],
versions_t.c.project_id==instance.project_id
)
r = s.execute()
new_id = r.fetchone()[0]
instance.id = new_id or 1
Version.mapper = mapper(Version,versions_table,
extension=VersionKeyMapper())
Project.mapper = mapper(Project,projects_table, properties =
{
'versions' : relation(Version, backref = 'project')
})
'versions' : relation(Version, backref = 'project')
})
Node.mapper = mapper(Node, nodes_table,
polymorphic_on=nodes_table.c.type,
polymorphic_identity=node_types['Node'],
properties = {
'project' : relation(Project,
primaryjoin=nodes_table.c.project_id == Project.c.id,
uselist=False,
foreignkey=Project.c.id),
'start_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.start_version_id == Version.c.id
),backref='start_nodes'),
'end_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.end_version_id == Version.c.id
),backref='end_nodes'),
'previous' : relation(Node,
primaryjoin=nodes_table.c.previous_id == nodes_table.c.id,
backref='next',uselist=False)
})
polymorphic_on=nodes_table.c.type,
polymorphic_identity=node_types['Node'],
properties = {
'project' : relation(Project,
primaryjoin=nodes_table.c.project_id == Project.c.id,
uselist=False,
foreignkey=Project.c.id),
'start_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.start_version_id == Version.c.id
),backref='start_nodes'),
'end_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.end_version_id == Version.c.id
),backref='end_nodes'),
'previous' : relation(Node,
primaryjoin=nodes_table.c.previous_id == nodes_table.c.id,
backref='next',uselist=False)
})
Project.mapper.add_property('nodes', relation(Node,
primaryjoin=Node.c.project_id == Project.c.id,
foreignkey=Node.c.project_id))
primaryjoin=Node.c.project_id == Project.c.id,
foreignkey=Node.c.project_id))
Algorithm.mapper = mapper(Algorithm, inherits=Node.mapper,
polymorphic_identity=node_types['Algorithm'],
properties = {
'sub_project' : relation(Project,
primaryjoin=(nodes_table.c.sub_project_id == Project.c.id),
foreignkey=Project.c.id,
backref = 'alg_nodes_using'),
'sub_project_version' : relation(Version,
primaryjoin=and_(
Node.c.sub_project_id == Version.c.project_id,
Node.c.sub_project_version_id == Version.c.id
), backref = 'alg_nodes_using')
})
polymorphic_identity=node_types['Algorithm'],
properties = {
'sub_project' : relation(Project,
primaryjoin=(nodes_table.c.sub_project_id == Project.c.id),
foreignkey=Project.c.id,
backref = 'alg_nodes_using'),
'sub_project_version' : relation(Version,
primaryjoin=and_(
Node.c.sub_project_id == Version.c.project_id,
Node.c.sub_project_version_id == Version.c.id
), backref = 'alg_nodes_using')
})
Parameter.mapper = mapper(Parameter, inherits=Node.mapper,
polymorphic_identity=node_types['Parameter'])
polymorphic_identity=node_types['Parameter'])
from sqlalchemy import *
import time
import os
try:
os.remove('test.db')
except OSError:
pass
db = create_engine('sqlite:///test.db')
metadata = BoundMetaData(db)
# Define the tables
projects_table = Table('projects', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(40)))
node_types = {'Node':0, 'Algorithm':1,'Parameter':2}
nodes_table = Table('nodes', metadata,
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('name', String(30)),
Column('description', String(80)),
Column('comments', String),
Column('start_version_id', Integer),
Column('end_version_id', Integer),
Column('sub_project_id', Integer, ForeignKey('projects.id')),
Column('sub_project_version_id', Integer),
Column('parameter_type', Integer),
Column('value', String),
Column('previous_id', Integer, ForeignKey('nodes.id')),
ForeignKeyConstraint(
['project_id','start_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['project_id','end_version_id'],
['versions.project_id','versions.id']
),
ForeignKeyConstraint(
['sub_project_id','sub_project_version_id'],
['versions.project_id','versions.id'])
)
edges_table = Table('edges', metadata,
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('name', String(30)),
Column('from_node_id', Integer, ForeignKey('nodes.id')),
Column('to_node_id', Integer, ForeignKey('nodes.id')),
Column('start_version_id', Integer, ForeignKey('versions.id')),
Column('end_version_id', Integer, ForeignKey('versions.id')),
Column('constraint_id', Integer, ForeignKey('contraints.id')),
Column('previous_id', Integer, ForeignKey('edges.id')))
versions_table = Table('versions', metadata,
Column('project_id', Integer, ForeignKey('projects.id'), primary_key=True),
Column('id', Integer, primary_key=True),
Column('date', DateTime),
Column('comment', String(300)))
constraints_table = Table('constraints', metadata,
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('params', String(100)))
# Echo db interactions
metadata.engine.echo = True
# Create the tables if they don't already exist (checkfirst=True)
projects_table.create(checkfirst=True)
versions_table.create(checkfirst=True)
nodes_table.create(checkfirst=True)
class Project(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
class Version(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
self.date = self.date or time.strftime("%Y-%m-%d %H:%M:%S")
class Node(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
class Algorithm(Node):
pass
class Parameter(Node):
pass
class VersionKeyMapper(MapperExtension):
def before_insert(self, mapper, connection, instance):
versions_t = mapper.select_table
s = select(
[func.max(versions_t.c.id)+1],
versions_t.c.project_id==instance.project_id
)
r = s.execute()
new_id = r.fetchone()[0]
instance.id = new_id or 1
Version.mapper = mapper(Version,versions_table, extension=VersionKeyMapper())
Project.mapper = mapper(Project,projects_table, properties = {
'versions' : relation(Version, backref = 'project')
})
Node.mapper = mapper(Node, nodes_table,
polymorphic_on=nodes_table.c.type,
polymorphic_identity=node_types['Node'],
properties = {
'project' : relation(Project,
primaryjoin=nodes_table.c.project_id == Project.c.id,
uselist=False,
foreignkey=Project.c.id),
'start_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.start_version_id == Version.c.id
),backref='start_nodes'),
'end_version' : relation(Version,
primaryjoin=and_(
nodes_table.c.project_id == Version.c.project_id,
nodes_table.c.end_version_id == Version.c.id
),backref='end_nodes'),
'previous' : relation(Node,
primaryjoin=nodes_table.c.previous_id == nodes_table.c.id,
backref='next',uselist=False)
})
Project.mapper.add_property('nodes', relation(Node,
primaryjoin=Node.c.project_id == Project.c.id,
foreignkey=Node.c.project_id))
Algorithm.mapper = mapper(Algorithm, inherits=Node.mapper,
polymorphic_identity=node_types['Algorithm'],
properties = {
'sub_project' : relation(Project,
primaryjoin=(nodes_table.c.sub_project_id == Project.c.id),
foreignkey=Project.c.id,
backref = 'alg_nodes_using'),
'sub_project_version' : relation(Version,
primaryjoin=and_(
Node.c.sub_project_id == Version.c.project_id,
Node.c.sub_project_version_id == Version.c.id
), backref = 'alg_nodes_using')
})
Parameter.mapper = mapper(Parameter, inherits=Node.mapper,
polymorphic_identity=node_types['Parameter'])
session = create_session(bind_to=db)
#Make test data:
p = Project('test')
p.versions.append(Version('first version'))
# Comment out other version adds before flush because of
# sequential dependency error
#p.versions.append(Version('second version'))
#p.versions.append(Version('third version'))
session.save(p)
session.flush()
#n = Node()
#n.name='New node, v1'
#v = session.query(Version).select()[0]
#v.start_nodes.append(n)
------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________ Sqlalchemy-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

