actually, heres both tests passing. however, i am sure this mapping is going to have more problems, its really complicated. one for the test suite for sure if it ever works fully. |
from sqlalchemy import *
import time
import os
metadata = DynamicMetaData()
tables = {}
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
class Edge(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
# Define the tables
tables['projects'] = \
Table('projects', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(40)))
tables['nodes'] = \
Table('nodes', metadata,
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
Column('type', Integer),
Column('name', String(30), nullable=False),
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('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'])
)
tables['edges'] = \
Table('edges', metadata,
Column('project_id', Integer, ForeignKey('projects.id')),
Column('id', Integer, primary_key=True),
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('previous_id', Integer, ForeignKey('edges.id')))
tables['versions'] = \
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)))
Version.mapper = mapper(Version, tables['versions'],
extension=VersionKeyMapper(), batch=False)
Project.mapper = mapper(Project, tables['projects'],
properties = {
'versions' : relation(Version, backref = 'project')#,
})
node_types = {'Node':0, 'Algorithm':1,'Parameter':2}
Node.mapper = mapper(Node, tables['nodes'],
polymorphic_on=tables['nodes'].c.type,
polymorphic_identity=node_types['Node'],
properties = {
'project' : relation(Project,
primaryjoin=
tables['nodes'].c.project_id == Project.c.id,
uselist=False,
foreignkey=Project.c.id,
backref=backref('nodes', primaryjoin=
tables['nodes'].c.project_id
== tables['projects'].c.id,
foreignkey=tables['nodes'].c.project_id)),
'start_version' : relation(Version,
primaryjoin=and_(
tables['nodes'].c.project_id==Version.c.project_id,
tables['nodes'].c.start_version_id==Version.c.id
),backref='start_nodes', viewonly=True),
'end_version' : relation(Version,
primaryjoin=and_(
tables['nodes'].c.project_id==Version.c.project_id,
tables['nodes'].c.end_version_id==Version.c.id
),backref='end_nodes', viewonly=True),
'previous' : relation(Node,
primaryjoin=
tables['nodes'].c.previous_id
== tables['nodes'].c.id,
backref='next',uselist=False)
})
Edge.mapper = mapper(Edge,tables['edges'],
properties = {
'project' : relation(Project,
primaryjoin=
tables['edges'].c.project_id
== Project.c.id,
uselist=False,
foreignkey=Project.c.id),
'start_version' : relation(Version,
primaryjoin=and_(
tables['edges'].c.project_id
== Version.c.project_id,
tables['edges'].c.start_version_id
== Version.c.id
),backref='start_edges', viewonly=True),
'end_version' : relation(Version,
primaryjoin=and_(
tables['edges'].c.project_id
== Version.c.project_id,
tables['edges'].c.end_version_id
== Version.c.id
),backref='end_edges', viewonly=True),
'previous' : relation(Edge,
primaryjoin=tables['edges'].c.previous_id
== tables['edges'].c.id,
backref='next',uselist=False)
})
Node.mapper.add_property('inputs', relation(Edge,
primaryjoin=tables['nodes'].c.id == tables['edges'].c.to_node_id,
backref='to_node'))
Node.mapper.add_property('outputs', relation(Edge,
primaryjoin=tables['nodes'].c.id == tables['edges'].c.from_node_id,
backref='from_node'))
Algorithm.mapper = mapper(Algorithm, inherits=Node.mapper,
polymorphic_identity=node_types['Algorithm'],
properties = {
'sub_project' : relation(Project,
primaryjoin=(tables['nodes'].c.sub_project_id == Project.c.id),
foreignkey=Project.c.id,
uselist=False),
'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', viewonly=True)
})
Project.mapper.add_property('alg_nodes_using', relation(Algorithm,
primaryjoin=(tables['nodes'].c.sub_project_id == Project.c.id),
foreignkey=tables['nodes'].c.sub_project_id))
Parameter.mapper = mapper(Parameter, inherits=Node.mapper,
polymorphic_identity=node_types['Parameter'])
class RelateDB:
def __init__(self, filename='relate.db', meta=metadata):
self.filename = filename
self.engine = create_engine('sqlite:///%s' % self.filename)
self.metadata = meta
self.metadata.connect(self.engine)
self.session = create_session(bind_to = self.engine)
def create_file(self):
self.metadata.create_all()
def delete_file(self):
try:
os.remove(self.filename)
except OSError: # File didn't exist
pass
def recreate_file(self):
self.delete_file()
self.create_file()
import logging
#logging.basicConfig()
#logging.getLogger('sqlalchemy.orm').setLevel(logging.DEBUG)
#logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
from db import *
import unittest
class TestRelateDB(unittest.TestCase):
def setUp(self):
self.db = RelateDB('test.db')
self.db.recreate_file()
def tearDown(self):
self.db.delete_file()
def test_algorithm(self):
a = Algorithm(name='a1')
self.db.session.save(a)
self.db.session.flush()
print "ITS", self.db.session.query(Node).get_by_name('a1')
assert type(self.db.session.query(Node).get_by_name('a1')) is Algorithm
def test_nodes(self):
algs = [Algorithm(name='a'+str(num)) for num in range(0,7)]
params = [Parameter(name='p'+str(num)) for num in range(0,20)]
for p in params:
print p.name
for a in algs:
self.db.session.save(a)
Edge(from_node=params[0],to_node=algs[0])
Edge(from_node=params[1],to_node=algs[0])
Edge(from_node=params[2],to_node=algs[0])
Edge(from_node=params[1],to_node=algs[1])
Edge(from_node=params[2],to_node=algs[1])
Edge(from_node=params[3],to_node=algs[1])
Edge(from_node=params[4],to_node=algs[1])
Edge(from_node=params[4],to_node=algs[2])
Edge(from_node=params[5],to_node=algs[2])
Edge(from_node=params[6],to_node=algs[2])
Edge(from_node=algs[0],to_node=params[7])
Edge(from_node=algs[0],to_node=params[8])
Edge(from_node=algs[1],to_node=params[9])
Edge(from_node=algs[1],to_node=params[10])
Edge(from_node=algs[2],to_node=params[11])
Edge(from_node=algs[2],to_node=params[12])
Edge(from_node=algs[2],to_node=params[13])
Edge(from_node=params[7],to_node=algs[3])
Edge(from_node=params[8],to_node=algs[3])
Edge(from_node=params[9],to_node=algs[3])
Edge(from_node=params[10],to_node=algs[3])
Edge(from_node=params[4],to_node=algs[4])
Edge(from_node=params[10],to_node=algs[4])
Edge(from_node=params[11],to_node=algs[4])
Edge(from_node=params[12],to_node=algs[4])
Edge(from_node=params[13],to_node=algs[4])
Edge(from_node=algs[3],to_node=params[14])
Edge(from_node=algs[3],to_node=params[15])
Edge(from_node=algs[4],to_node=params[16])
Edge(from_node=params[7],to_node=algs[5])
Edge(from_node=params[14],to_node=algs[5])
Edge(from_node=params[15],to_node=algs[5])
Edge(from_node=params[14],to_node=algs[6])
Edge(from_node=params[15],to_node=algs[6])
Edge(from_node=params[16],to_node=algs[6])
Edge(from_node=params[13],to_node=algs[6])
Edge(from_node=algs[5],to_node=params[17])
Edge(from_node=algs[6],to_node=params[18])
Edge(from_node=algs[6],to_node=params[19])
self.db.session.flush()
a = self.db.session.query(Algorithm).get_by_name('a4')
print [p.__class__ for p in a.inputs]
print [p.from_node.name for p in a.inputs]
print [p.id for p in a.inputs]
assert set([p.from_node.name for p in a.inputs]) \
== set(['p10','p4','p11','p12','p13'])
if __name__ == '__main__':
unittest.main()
On Sep 26, 2006, at 4:29 PM, Hogarty, David A. wrote: I'm getting a strange error when flushing the session after the following sequence of creations: def test_nodes(self): algs = [Algorithm(name='a'+str(num)) for num in range(0,7)] 1) params = [Parameter(name='p'+str(num)) for num in range(0,20)] for a in algs: self.db.session.save(a) for p in params: self.db.session.save(p) Edge(from_node=params[0],to_node=algs[0]) Edge(from_node=params[1],to_node=algs[0]) Edge(from_node=params[2],to_node=algs[0]) Edge(from_node=params[1],to_node=algs[1]) Edge(from_node=params[2],to_node=algs[1]) Edge(from_node=params[3],to_node=algs[1]) Edge(from_node=params[4],to_node=algs[1]) Edge(from_node=params[4],to_node=algs[2]) Edge(from_node=params[5],to_node=algs[2]) Edge(from_node=params[6],to_node=algs[2]) Edge(from_node=algs[0],to_node=params[7]) Edge(from_node=algs[0],to_node=params[8]) Edge(from_node=algs[1],to_node=params[9]) Edge(from_node=algs[1],to_node=params[10]) Edge(from_node=algs[2],to_node=params[11]) Edge(from_node=algs[2],to_node=params[12]) Edge(from_node=algs[2],to_node=params[13]) Edge(from_node=params[7],to_node=algs[3]) Edge(from_node=params[8],to_node=algs[3]) Edge(from_node=params[9],to_node=algs[3]) Edge(from_node=params[10],to_node=algs[3]) Edge(from_node=params[4],to_node=algs[4]) Edge(from_node=params[10],to_node=algs[4]) Edge(from_node=params[11],to_node=algs[4]) Edge(from_node=params[12],to_node=algs[4]) Edge(from_node=params[13],to_node=algs[4]) Edge(from_node=algs[3],to_node=params[14]) Edge(from_node=algs[3],to_node=params[15]) Edge(from_node=algs[4],to_node=params[16]) Edge(from_node=params[7],to_node=algs[5]) Edge(from_node=params[14],to_node=algs[5]) Edge(from_node=params[15],to_node=algs[5]) Edge(from_node=params[14],to_node=algs[6]) Edge(from_node=params[15],to_node=algs[6]) Edge(from_node=params[16],to_node=algs[6]) Edge(from_node=params[13],to_node=algs[6]) Edge(from_node=algs[5],to_node=params[17]) Edge(from_node=algs[6],to_node=params[18]) Edge(from_node=algs[6],to_node=params[19]) self.db.session.flush() a = self.db.session.query(Algorithm).get_by_name('a4') assert set([p.name for p in a.inputs]) \ == set(['p10','p4','p11','p12','p13']) At some point, it tries to re-insert one of the Parameter nodes created at 1) above, initially created with 2006-09-26 14:53:59,192 INFO sqlalchemy.engine.base.ComposedSQLEngine.0x190cc66c INSERT INTO nodes (project_id, type, name, description, comments, start_version _id, end_version_id, sub_project_id, sub_project_version_id, value, previous_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 2006-09-26 14:53:59,193 INFO sqlalchemy.engine.base.ComposedSQLEngine.0x190cc66c [None, 2, 'p14', None, None, None, None, None, None, None, None] with the following (now is inserting over the existing primary key, causing an integrity error) SQLError: (IntegrityError) PRIMARY KEY must be unique 'INSERT INTO nodes (projec t_id, id, type, name, description, comments, start_version_id, end_version_id, s ub_project_id, sub_project_version_id, value, previous_id) VALUES (?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?)' [None, 2, 2, 'p14', None, None, None, None, None, None, None, None] Attached are two files that are a test case. You need nose to run the test: put them in the same directory and run 'nosetests' (Or manually run the setUp, test_nodes, and tearDown methods of test_db.py:TestRelateDB). On re-running the test case before sending, I found that it has several different possible results. I included four output files from recent runs to demonstrate. All of these runs are with the attached code. Any help would be much appreciated, -Dave H <test.tar.gz> ------------------------------------------------------------------------- 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 Sqlalchemy-users mailing list |
-------------------------------------------------------------------------
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
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users