- utterly remarkable: added a single space between 'CREATE TABLE'
and '(<the rest of it>' since *thats how MySQL indicates a non-
reserved word tablename.....* [ticket:206]
+- more fixes to inheritance, related to many-to-many relations
+properly saving
0.2.3
- overhaul to mapper compilation to be deferred. this allows mappers
class OneToManyDP(DependencyProcessor):
def register_dependencies(self, uowcommit):
if self.post_update:
- stub = MapperStub(self.mapper)
+ stub = MapperStub(self.parent, self.mapper, self.key)
uowcommit.register_dependency(self.mapper, stub)
uowcommit.register_dependency(self.parent, stub)
uowcommit.register_processor(stub, self, self.parent)
class ManyToOneDP(DependencyProcessor):
def register_dependencies(self, uowcommit):
if self.post_update:
- stub = MapperStub(self.mapper)
+ stub = MapperStub(self.parent, self.mapper, self.key)
uowcommit.register_dependency(self.mapper, stub)
uowcommit.register_dependency(self.parent, stub)
uowcommit.register_processor(stub, self, self.parent)
# if we are the "backref" half of a two-way backref
# relationship, let the other mapper handle inserting the rows
return
- stub = MapperStub(self.mapper)
+ stub = MapperStub(self.parent, self.mapper, self.key)
uowcommit.register_dependency(self.parent, stub)
uowcommit.register_dependency(self.mapper, stub)
uowcommit.register_processor(stub, self, self.parent)
# association/parent->stub->self, then we process the child
# elments after the 'stub' save, which is before our own
# mapper's save.
- stub = MapperStub(self.association)
+ stub = MapperStub(self.parent, self.association, self.key)
uowcommit.register_dependency(self.parent, stub)
uowcommit.register_dependency(self.association, stub)
uowcommit.register_dependency(stub, self.mapper)
The Task objects in the objectstore module treat it just like
any other Mapper, but in fact it only serves as a "dependency" placeholder
for the many-to-many update task."""
- def __init__(self, mapper):
+ __metaclass__ = util.ArgSingleton
+ def __init__(self, parent, mapper, key):
self.mapper = mapper
self._inheriting_mappers = []
def register_dependencies(self, uowcommit):
def register_dependencies(self, uowcommit):
self._dependency_processor.register_dependencies(uowcommit)
-
+
def _compile_synchronizers(self):
"""assembles a list of 'synchronization rules', which are instructions on how to populate
the objects on each side of a relationship. This is done when a PropertyLoader is
this method returns or creates the single per-transaction instance of
UOWTask that exists for that mapper."""
try:
- if isinstance(mapper, UOWTask):
- raise "wha"
return self.tasks[mapper]
except KeyError:
if dontcreate:
# print "TASK OBJ:", obj
# for elem in task.get_elements(polymorphic=True):
# print "POLYMORPHIC TASK OBJ:", elem.obj
+
+ # insure that we have a UOWTask for every mapper that will be involved
+ # in the topological sort
+ [self.get_task_by_mapper(m) for m in self._get_noninheriting_mappers()]
+
#print "-----------------------------"
# pre-execute dependency processors. this process may
# result in new tasks, objects and/or dependency processors being added,
q = sess.query(Bar)
self.assert_(len(q.selectfirst().lazy) == 1)
self.assert_(len(q.selectfirst().eager) == 1)
-
+
+
+class InheritTest7(testbase.AssertMixin):
+ """test dependency sorting among inheriting mappers"""
+ def setUpAll(self):
+ global users, roles, user_roles, admins, metadata
+ metadata=BoundMetaData(testbase.db)
+ users = Table('user', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('email', String(128)),
+ Column('password', String(16)),
+ )
+
+ roles = Table('role', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('description', String(32))
+ )
+
+ user_roles = Table('user_role', metadata,
+ Column('user_id', Integer, ForeignKey('user.id'), primary_key=True),
+ Column('role_id', Integer, ForeignKey('role.id'), primary_key=True)
+ )
+
+ admins = Table('admin', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('user_id', Integer, ForeignKey('user.id'))
+ )
+ metadata.create_all()
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def testbasic(self):
+ class User(object):pass
+ class Role(object):pass
+ class Admin(User):pass
+ role_mapper = mapper(Role, roles)
+ user_mapper = mapper(User, users, properties = {
+ 'roles' : relation(Role, secondary=user_roles, lazy=False, private=False)
+ }
+ )
+ admin_mapper = mapper(Admin, admins, inherits=user_mapper)
+ sess = create_session()
+ adminrole = Role('admin')
+ sess.save(adminrole)
+ sess.flush()
+
+ # create an Admin, and append a Role. the dependency processors
+ # corresponding to the "roles" attribute for the Admin mapper and the User mapper
+ # have to insure that two dependency processors dont fire off and insert the
+ # many to many row twice.
+ a = Admin()
+ a.roles.append(adminrole)
+ a.password = 'admin'
+ sess.save(a)
+ sess.flush()
+
+ assert user_roles.count().scalar() == 1
+
if __name__ == "__main__":
testbase.main()