modeling-cvs Mailing List for Object-Relational Bridge for python (Page 19)
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(54) |
Apr
(29) |
May
(94) |
Jun
(47) |
Jul
(156) |
Aug
(132) |
Sep
(40) |
Oct
(6) |
Nov
(18) |
Dec
(24) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(18) |
Feb
(59) |
Mar
(7) |
Apr
|
May
(8) |
Jun
(2) |
Jul
(12) |
Aug
(15) |
Sep
(12) |
Oct
(6) |
Nov
(25) |
Dec
(1) |
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
(27) |
Mar
|
Apr
(16) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sbi...@us...> - 2003-07-28 11:00:33
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/doc In directory sc8-pr-cvs1:/tmp/cvs-serv16682/Modeling/doc Modified Files: UserGuide.tex Tutorial.tex Log Message: Release 0.9pre11 Index: UserGuide.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide.tex,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** UserGuide.tex 18 Jul 2003 15:01:13 -0000 1.24 --- UserGuide.tex 28 Jul 2003 11:00:30 -0000 1.25 *************** *** 12,18 **** % the rest is at your discretion. \authoraddress{Email: \email{sbi...@us...}} ! \date{Jun 18, 2003} %\date{\today} ! \release{0.9-pre-10} %\setreleaseinfo{pre-8} \setshortversion{0.9} --- 12,18 ---- % the rest is at your discretion. \authoraddress{Email: \email{sbi...@us...}} ! \date{Jun 28, 2003} %\date{\today} ! \release{0.9-pre-11} %\setreleaseinfo{pre-8} \setshortversion{0.9} Index: Tutorial.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/Tutorial.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Tutorial.tex 18 Jul 2003 15:01:13 -0000 1.6 --- Tutorial.tex 28 Jul 2003 11:00:30 -0000 1.7 *************** *** 14,18 **** \date{February 10, 2003} %\date{\today} ! \release{0.9-pre-10} %\setreleaseinfo{5} \setshortversion{0.9} --- 14,18 ---- \date{February 10, 2003} %\date{\today} ! \release{0.9-pre-11} %\setreleaseinfo{5} \setshortversion{0.9} |
From: <sbi...@us...> - 2003-07-28 11:00:32
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv16682/Modeling Modified Files: CHANGES Log Message: Release 0.9pre11 Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.137 retrieving revision 1.138 diff -C2 -d -r1.137 -r1.138 *** CHANGES 28 Jul 2003 06:15:16 -0000 1.137 --- CHANGES 28 Jul 2003 11:00:30 -0000 1.138 *************** *** 3,11 **** Module Modeling --------------- ! Current release is: 0.9-pre-10 / See also: TODO, INSTALL and doc/ * ** Distributed under the GNU General Public License ** -------------------------------------------------------- * Removed the constraint on to-many relationships for which an inverse to-one relationship had to be defined. --- 3,14 ---- Module Modeling --------------- ! Current release is: 0.9-pre-11 / See also: TODO, INSTALL and doc/ * ** Distributed under the GNU General Public License ** -------------------------------------------------------- + 0.9-pre-11 (2003/07/28) + ----------------------- + * Removed the constraint on to-many relationships for which an inverse to-one relationship had to be defined. *************** *** 28,32 **** * Simple methods for models, entities, attributes, relationships and ! ClassDescriptions can now be automatically cached, This speeds up operations where model introspection is needed (when saving changes, when using RelationshipManipulation interface, etc.). See Appendix A.1, --- 31,35 ---- * Simple methods for models, entities, attributes, relationships and ! ClassDescriptions can now be automatically cached. This speeds up operations where model introspection is needed (when saving changes, when using RelationshipManipulation interface, etc.). See Appendix A.1, |
From: <sbi...@us...> - 2003-07-28 11:00:32
|
Update of /cvsroot/modeling/ProjectModeling In directory sc8-pr-cvs1:/tmp/cvs-serv16682 Modified Files: setup.py Log Message: Release 0.9pre11 Index: setup.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/setup.py,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** setup.py 18 Jul 2003 15:01:12 -0000 1.27 --- setup.py 28 Jul 2003 11:00:29 -0000 1.28 *************** *** 46,50 **** setup(name="ModelingCore", ! version="0.9-pre-10", licence ="GNU General Public License", description=short_description, --- 46,50 ---- setup(name="ModelingCore", ! version="0.9-pre-11", licence ="GNU General Public License", description=short_description, |
From: <sbi...@us...> - 2003-07-28 07:28:54
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide In directory sc8-pr-cvs1:/tmp/cvs-serv12687/doc/UserGuide Modified Files: DefiningaModel.tex Log Message: Removed the constraint on to-many relationships for which an inverse to-one relationship had to be defined. Index: DefiningaModel.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide/DefiningaModel.tex,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** DefiningaModel.tex 17 Jul 2003 13:49:32 -0000 1.12 --- DefiningaModel.tex 28 Jul 2003 07:08:00 -0000 1.13 *************** *** 697,707 **** \subsection{Designing relationships \label{design-rels}} ! \strong{Warning}: For the moment, ! toMany relationships are required to have inverse (toOne) relationships defined in the ! model. This constraint will be removed sometime in the future. ! ! ! A relationship and its inverse relationship define an association. ! Associations can be of the three kinds, with the following constraints: \begin{description} --- 697,704 ---- \subsection{Designing relationships \label{design-rels}} ! A relationship and its inverse relationship (when defined) define an ! association. If a relationship has no inverse, the corresponding association ! is said to be uni-directional, otherwise it is bi-directional. Associations ! can be of the three kinds, with the following constraints: \begin{description} *************** *** 775,786 **** \method{CustomObject.inverseForRelationshipKey()} documentation string. - \begin{notice}[note] - \strong{Inheritance issue}: when an entity inherits from an other one, the - ZModelization tool will not show you any inverse relationships for the - inherited relationships. This is normal and no particular action has to be - done (except verifying that the parent entity defining the relationship - does show some inverse relationship. For further details about inheritance - and how it should be modeled, see \ref{design-inheritance}. - \end{notice} --- 772,775 ---- |
From: <sbi...@us...> - 2003-07-28 07:19:03
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv14238 Modified Files: Relationship.py Log Message: docstring for inverseRelationship() Index: Relationship.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Relationship.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** Relationship.py 25 Jul 2003 15:39:03 -0000 1.14 --- Relationship.py 28 Jul 2003 07:18:59 -0000 1.15 *************** *** 494,497 **** --- 494,503 ---- or None if it does not exist + Note: the inverseRelationship() is not idempotent, + i.e. rel.inverseRelationship().inverseRelationship() does not necessarily + returns self. It returns self if and only if the relationship's entity has + no parent entity, or if the relationship is not an inherited property + (none of the parent entities defines the relationship). + See also: anyInverseRelationship() """ |
From: <sbi...@us...> - 2003-07-28 06:53:36
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv10728/tests Modified Files: test_EditingContext_Global_Inheritance.py Log Message: Fixed tests 10, 11, 12 and 13: tests for the root entity (Employee) and one of its sub-entities (SalesClerks) Index: test_EditingContext_Global_Inheritance.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_Global_Inheritance.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** test_EditingContext_Global_Inheritance.py 28 Jul 2003 06:15:16 -0000 1.17 --- test_EditingContext_Global_Inheritance.py 28 Jul 2003 06:53:33 -0000 1.18 *************** *** 404,409 **** new instances of Employee/Holidays. """ ! emp=Employee.Employee() ! emp.setLastName('Test'); emp.setFirstName('T.') from mx.DateTime import DateFrom holidays=Holidays() --- 404,409 ---- new instances of Employee/Holidays. """ ! emp=self._test_10_class_employee() ! emp.setLastName('Test10'); emp.setFirstName('T.') from mx.DateTime import DateFrom holidays=Holidays() *************** *** 435,442 **** ec2=EditingContext() ! emp2=ec2.fetch('Employee')[0] self.failIf(len(emp2.getHolidays())==0) ! def test_10a_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/a]" # insert (h.+emp) + emp.addToHolidays + saveChanges --- 435,442 ---- ec2=EditingContext() ! emp2=ec2.fetch('Employee','lastName=="Test10"', isDeep=1)[0] self.failIf(len(emp2.getHolidays())==0) ! def _test_10a_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/a]" # insert (h.+emp) + emp.addToHolidays + saveChanges *************** *** 452,456 **** self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10b_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" # insert h. + saveChanges + emp.addToHolidays + saveChanges --- 452,463 ---- self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10a_toMany_with_no_inverse(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/a]" ! self._test_10_class_employee=Employee.Employee ! self._test_10a_toMany_with_no_inverse() ! self._test_10_class_employee=SalesClerk ! self._test_10a_toMany_with_no_inverse() ! ! def _test_10b_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" # insert h. + saveChanges + emp.addToHolidays + saveChanges *************** *** 472,476 **** self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10c_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" # insert h. + emp.addToHolidays + saveChanges --- 479,490 ---- self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10b_toMany_with_no_inverse(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" ! self._test_10_class_employee=Employee.Employee ! self._test_10b_toMany_with_no_inverse() ! self._test_10_class_employee=SalesClerk ! self._test_10b_toMany_with_no_inverse() ! ! def _test_10c_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" # insert h. + emp.addToHolidays + saveChanges *************** *** 488,492 **** self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10d_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/d]" #insert h. + saveChanges + emp.addToHolidays + h.setStartDate + saveChanges --- 502,513 ---- self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10c_toMany_with_no_inverse(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" ! self._test_10_class_employee=Employee.Employee ! self._test_10c_toMany_with_no_inverse() ! self._test_10_class_employee=SalesClerk ! self._test_10c_toMany_with_no_inverse() ! ! def _test_10d_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/d]" #insert h. + saveChanges + emp.addToHolidays + h.setStartDate + saveChanges *************** *** 508,512 **** self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10e_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/e]" # insert h. + save + insert emp. + emp.addToHolidays + saveChanges --- 529,540 ---- self._test_10_check_insert_correctness_part2(emp_gid, db) ! def test_10d_toMany_with_no_inverse(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/d]" ! self._test_10_class_employee=Employee.Employee ! self._test_10d_toMany_with_no_inverse() ! self._test_10_class_employee=SalesClerk ! self._test_10d_toMany_with_no_inverse() ! ! def _test_10e_toMany_with_no_inverse(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/e]" # insert h. + save + insert emp. + emp.addToHolidays + saveChanges *************** *** 524,530 **** self._test_10_check_insert_correctness_part2(emp_gid, db) def _test_11a_init_emp_and_holidays(self, ec): ! emp=Employee.Employee() ! emp.setLastName('Test'); emp.setFirstName('T.') from mx.DateTime import DateFrom holidays=Holidays() --- 552,565 ---- self._test_10_check_insert_correctness_part2(emp_gid, db) + def test_10e_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/e]" + self._test_10_class_employee=Employee.Employee + self._test_10e_toMany_with_no_inverse() + self._test_10_class_employee=SalesClerk + self._test_10e_toMany_with_no_inverse() + def _test_11a_init_emp_and_holidays(self, ec): ! emp=self._test_11_class_employee() ! emp.setLastName('Test11'); emp.setFirstName('T.') from mx.DateTime import DateFrom holidays=Holidays() *************** *** 537,541 **** return emp, holidays ! def test_11a_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [remove/a]" # remove simple --- 572,576 ---- return emp, holidays ! def _test_11a_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [remove/a]" # remove simple *************** *** 555,562 **** self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) ec2=EditingContext() ! emp2=ec2.fetch('Employee')[0] self.failIf(len(emp2.getHolidays())!=0) ! def test_11b_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" # remove + add --- 590,604 ---- self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) ec2=EditingContext() ! emp2=ec2.fetch('Employee', 'lastName=="Test11"', isDeep=1)[0] self.failIf(len(emp2.getHolidays())!=0) ! def test_11a_toMany_with_no_inverse__remove(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [remove/a]" ! self._test_11_class_employee=Employee.Employee ! self._test_11a_toMany_with_no_inverse__remove() ! self._test_11_class_employee=SalesClerk ! self._test_11a_toMany_with_no_inverse__remove() ! ! def _test_11b_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" # remove + add *************** *** 584,588 **** self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) ec2=EditingContext() ! emp2=ec2.fetch('Employee')[0] self.assertEqual(len(emp2.getHolidays()), 1) h2b=emp2.getHolidays()[0] --- 626,630 ---- self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) ec2=EditingContext() ! emp2=ec2.fetch('Employee', 'lastName=="Test11"', isDeep=1)[0] self.assertEqual(len(emp2.getHolidays()), 1) h2b=emp2.getHolidays()[0] *************** *** 591,595 **** #print db.snapshotForGlobalID(h_gid) ! def test_11c_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" # remove + add --- 633,644 ---- #print db.snapshotForGlobalID(h_gid) ! def test_11b_toMany_with_no_inverse__remove(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" ! self._test_11_class_employee=Employee.Employee ! self._test_11b_toMany_with_no_inverse__remove() ! self._test_11_class_employee=SalesClerk ! self._test_11b_toMany_with_no_inverse__remove() ! ! def _test_11c_toMany_with_no_inverse__remove(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" # remove + add *************** *** 610,614 **** self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']!=None) ! def test_12_toMany_with_no_inverse__correct_fetch(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly fetched" ec=EditingContext() --- 659,670 ---- self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']!=None) ! def test_11c_toMany_with_no_inverse__remove(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" ! self._test_11_class_employee=Employee.Employee ! self._test_11c_toMany_with_no_inverse__remove() ! self._test_11_class_employee=SalesClerk ! self._test_11c_toMany_with_no_inverse__remove() ! ! def _test_12_toMany_with_no_inverse__correct_fetch(self): "[EC/Inheritance] toMany w/o inverse: obj. correctly fetched" ec=EditingContext() *************** *** 621,625 **** self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']==None) ! def test_13_toMany_with_no_inverse__snapshot_row(self): "[EC/Inheritance] toMany w/o inverse: obj.snapshot_raw()" ec=EditingContext() --- 677,688 ---- self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']==None) ! def test_12_toMany_with_no_inverse__correct_fetch(self): ! "[EC/Inheritance] toMany w/o inverse: obj. correctly fetched" ! self._test_11_class_employee=Employee.Employee ! self._test_12_toMany_with_no_inverse__correct_fetch() ! self._test_11_class_employee=SalesClerk ! self._test_12_toMany_with_no_inverse__correct_fetch() ! ! def _test_13_toMany_with_no_inverse__snapshot_row(self): "[EC/Inheritance] toMany w/o inverse: obj.snapshot_raw()" ec=EditingContext() *************** *** 635,638 **** --- 698,708 ---- emp.globalID().keyValues()['id']) + def test_13_toMany_with_no_inverse__snapshot_row(self): + "[EC/Inheritance] toMany w/o inverse: obj.snapshot_raw()" + self._test_10_class_employee=Employee.Employee + self._test_13_toMany_with_no_inverse__snapshot_row() + self._test_10_class_employee=SalesClerk + self._test_13_toMany_with_no_inverse__snapshot_row() + def tearDown(self): """ |
From: <sbi...@us...> - 2003-07-28 06:20:27
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv6663 Modified Files: CustomObject.py Log Message: Fixed snapshot_raw(): it was raising when it comes to fill the value for a FK used in a relationship pointing to the object, with no to-one inverse relationship defined in the object's entity Index: CustomObject.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CustomObject.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** CustomObject.py 16 Jul 2003 18:41:37 -0000 1.15 --- CustomObject.py 28 Jul 2003 06:20:19 -0000 1.16 *************** *** 314,319 **** continue ! res[key]=self.storedValueForKey(key) ! # Handle PKs gid=self.globalID() --- 314,334 ---- continue ! try: ! res[key]=self.storedValueForKey(key) ! except AttributeError: ! # This happens when it comes to fill the value for a FK used in a ! # relationship pointing to the object, with no to-one inverse ! # relationship defined in the object's entity (thus, this fk is not ! # in fks=ClassDescription.foreignKeys() ! attr=cd.entity().attributeNamed(key) ! if attr and not attr.isClassProperty(): ! if self.globalID().isTemporary(): ! # cannot compute, insert None ! res[key]=None ! else: ! db=ec.rootObjectStore().objectStoreForObject(self).database() ! snap=db.snapshotForGlobalID(self.globalID()) ! res[key]=snap[key] ! # Handle PKs gid=self.globalID() |
From: <sbi...@us...> - 2003-07-28 06:15:19
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv5634/tests Modified Files: test_EditingContext_Global_Inheritance.py Log Message: Removed the constraint on to-many relationships for which an inverse to-one relationship had to be defined. Details: recordChangesInEditingContext() refactored, recordUpdateForObject() implemented, Index: test_EditingContext_Global_Inheritance.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_Global_Inheritance.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** test_EditingContext_Global_Inheritance.py 24 Jul 2003 11:30:52 -0000 1.16 --- test_EditingContext_Global_Inheritance.py 28 Jul 2003 06:15:16 -0000 1.17 *************** *** 55,58 **** --- 55,59 ---- from StoreEmployees.Executive import Executive from StoreEmployees.Address import Address + from StoreEmployees.Holidays import Holidays *************** *** 61,65 **** def test_01_objectsWithFetchSpecification(self): ! "[EditingContext/Inheritance] objectsWithFetchSpecification" ec=EditingContext() fetchSpec=FetchSpecification(entityName='Employee', deepFlag=0) --- 62,66 ---- def test_01_objectsWithFetchSpecification(self): ! "[EC/Inheritance] objectsWithFetchSpecification" ec=EditingContext() fetchSpec=FetchSpecification(entityName='Employee', deepFlag=0) *************** *** 73,77 **** def test_02_toOneFault(self): ! "[EditingContext/Inheritance] toOneFault" ec=EditingContext() qual=qualifierWithQualifierFormat('street like "2,*"') --- 74,78 ---- def test_02_toOneFault(self): ! "[EC/Inheritance] toOneFault" ec=EditingContext() qual=qualifierWithQualifierFormat('street like "2,*"') *************** *** 92,96 **** def test_03_toOneFault_notifications(self): ! "[EditingContext/Inheritance] toOneFault/GlobalIDChangedNotification" ec1=EditingContext() ec2=EditingContext() --- 93,97 ---- def test_03_toOneFault_notifications(self): ! "[EC/Inheritance] toOneFault/GlobalIDChangedNotification" ec1=EditingContext() ec2=EditingContext() *************** *** 152,156 **** def test_04_validation(self): ! "[EditingContext/Inheritance] test Validation" ec=EditingContext() qual=qualifierWithQualifierFormat('street like "2,*"') --- 153,157 ---- def test_04_validation(self): ! "[EC/Inheritance] test Validation" ec=EditingContext() qual=qualifierWithQualifierFormat('street like "2,*"') *************** *** 166,170 **** def test_05_toOneFault_uniquing(self): ! "[EditingContext/Inheritance] Tests that toFaults are also unique within a ec" ec=EditingContext() # get address for John Cleese --- 167,171 ---- def test_05_toOneFault_uniquing(self): ! "[EC/Inheritance] Tests that toFaults are also unique within a ec" ec=EditingContext() # get address for John Cleese *************** *** 189,193 **** def test_05b_toOneFault_uniquing(self): ! "[EditingContext/Inheritance] Tests unicity for toOne-related objects when they are already fetched" ## In this test we make sure that, after an object has been fetched, ## any other object pointing to it do not get a to-one fault, but the --- 190,194 ---- def test_05b_toOneFault_uniquing(self): ! "[EC/Inheritance] Tests unicity for toOne-related objects when they are already fetched" ## In this test we make sure that, after an object has been fetched, ## any other object pointing to it do not get a to-one fault, but the *************** *** 248,252 **** def test_06_objectsCountWithFetchSpecification(self): ! "[EditingContext/Inheritance] objectsCountWithFetchSpecification" ec=EditingContext() fs=FetchSpecification(entityName='Employee') --- 249,253 ---- def test_06_objectsCountWithFetchSpecification(self): ! "[EC/Inheritance] objectsCountWithFetchSpecification" ec=EditingContext() fs=FetchSpecification(entityName='Employee') *************** *** 260,264 **** def test_07_fetch_shouldnt_change_FetchSpecification(self): ! "[EditingContext/Inheritance] fetching shouldn't change FetchSpecification" # Bug #753147 from StoreEmployees import Address --- 261,265 ---- def test_07_fetch_shouldnt_change_FetchSpecification(self): ! "[EC/Inheritance] fetching shouldn't change FetchSpecification" # Bug #753147 from StoreEmployees import Address *************** *** 277,281 **** def test_08a_fetchesRawRows(self): ! "[EditingContext/Inheritance] fetchesRawRows / basics" ec=EditingContext() --- 278,282 ---- def test_08a_fetchesRawRows(self): ! "[EC/Inheritance] fetchesRawRows / basics" ec=EditingContext() *************** *** 302,306 **** def test_08b_fetchesRawRows(self): ! "[EditingContext/Inheritance] fetchesRawRows / inserted & deleted objects" ec=EditingContext() --- 303,307 ---- def test_08b_fetchesRawRows(self): ! "[EC/Inheritance] fetchesRawRows / inserted & deleted objects" ec=EditingContext() *************** *** 335,339 **** def test_09_faultForRawRow(self): ! "[EditingContext/Inheritance] faultForRawRow" ec=EditingContext() employees=ec.fetch('Employee', isDeep=1, rawRows=1) --- 336,340 ---- def test_09_faultForRawRow(self): ! "[EC/Inheritance] faultForRawRow" ec=EditingContext() employees=ec.fetch('Employee', isDeep=1, rawRows=1) *************** *** 368,371 **** --- 369,637 ---- ## TBD: CHECK FOR TEMPORARY/INSERTED + + def test_10_toMany_no_inverse__db_snapshot_is_correct(self): + "[EC/Inheritance] toMany w/o inverse: check db snapshot" + # We check here that a database snapshot for an object being pointed to + # by a toMany relationship with no inverse correctly contains its FK + ec=EditingContext() + holidays=Holidays() + from mx.DateTime import DateFrom + holidays.setStartDate(DateFrom('2003-07-01 08:00')) + holidays.setEndDate(DateFrom('2003-08-01 08:00')) + ec.insert(holidays) + ec.saveChanges() + + database=ec.rootObjectStore().objectStoreForObject(holidays).database() + snap=database.snapshotForGlobalID(holidays.globalID()) + self.failIf(not snap.has_key('fkEmployeeId')) + + ## ToMany with no inverse: + # test10 / insertion: + # [a] insert (h.+emp.) + emp.addToHolidays + saveChges + # [b] insert h. + saveChges + emp.addToHolidays + saveChges + # [c] insert h.+ emp.addToHolidays + saveChges + # [d] insert h.+ saveChges + emp.addToHolidays + h.setStartDate + saveChges + # [e] insert h. + saveChges + insert emp. + emp.addToHolidays + saveChanges + # + # test11 / remove: + # [a] remove simple + # [b] add h1 + remove h2 + # [c] remove (+ implicit delete w/ cascade rule) emp. + + def _test_10_create_emp_n_holidays(self): + """ + helper function for tests test_10...: return (employee, holidays), brand + new instances of Employee/Holidays. + """ + emp=Employee.Employee() + emp.setLastName('Test'); emp.setFirstName('T.') + from mx.DateTime import DateFrom + holidays=Holidays() + holidays.setStartDate(DateFrom('2003-07-01 08:00')) + holidays.setEndDate(DateFrom('2003-08-01 08:00')) + return emp, holidays + + def _test_10_check_insert_correctness_part1(self, ec, emp, holidays): + emp_gid=emp.globalID() + holidays_gid=holidays.globalID() + db=ec.rootObjectStore().objectStoreForObject(emp).database() + + self.failUnless(holidays_gid) + self.failIf(not db.snapshotForGlobalID(holidays_gid)) + self.failIf(not db.snapshotForGlobalID(holidays_gid).has_key('fkEmployeeId')) + self.assertEqual(db.snapshotForGlobalID(holidays_gid)['fkEmployeeId'], + emp_gid.keyValues()['id']) + self.failUnless(db.snapshotForSourceGlobalID(emp.globalID(), 'holidays')) + return emp_gid, db + + def _test_10_check_insert_correctness_part2(self, emp_gid, database): + "" + # Now check that it was correctly saved. If 'holidays' was not correctly + # saved, it hasn't get the right value for its FK and we won't retrieve + # any holidays for the test employee + + # make sure we won't get informations from the db cache + self.failIf(database.snapshotForSourceGlobalID(emp_gid, 'holidays')) + + ec2=EditingContext() + emp2=ec2.fetch('Employee')[0] + self.failIf(len(emp2.getHolidays())==0) + + def test_10a_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/a]" + # insert (h.+emp) + emp.addToHolidays + saveChanges + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + ec.insert(emp) + ec.insert(holidays) + emp.addToHolidays(holidays) + ec.saveChanges() + + emp_gid, db=self._test_10_check_insert_correctness_part1(ec, emp, holidays) + del ec # deleting the ec invalidates the database's cache + self._test_10_check_insert_correctness_part2(emp_gid, db) + + def test_10b_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" + # insert h. + saveChanges + emp.addToHolidays + saveChanges + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + emp_gid=emp.globalID() + ec.insert(emp) + ec.saveChanges() + + ec.insert(holidays) + ec.saveChanges() + + emp.addToHolidays(holidays) + #emp.setLastName('fdsk') + ec.saveChanges() + + emp_gid, db=self._test_10_check_insert_correctness_part1(ec, emp, holidays) + del ec # deleting the ec invalidates the database's cache + self._test_10_check_insert_correctness_part2(emp_gid, db) + + def test_10c_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" + # insert h. + emp.addToHolidays + saveChanges + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + ec.insert(emp) + ec.saveChanges() + + ec.insert(holidays) + emp.addToHolidays(holidays) + ec.saveChanges() + + emp_gid, db=self._test_10_check_insert_correctness_part1(ec, emp, holidays) + del ec # deleting the ec invalidates the database's cache + self._test_10_check_insert_correctness_part2(emp_gid, db) + + def test_10d_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/d]" + #insert h. + saveChanges + emp.addToHolidays + h.setStartDate + saveChanges + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + ec.insert(emp) + ec.saveChanges() + + ec.insert(holidays) + ec.saveChanges() + + emp.addToHolidays(holidays) + from mx.DateTime import DateFrom + holidays.setStartDate(DateFrom('2003-07-02 08:00')) + ec.saveChanges() + + emp_gid, db=self._test_10_check_insert_correctness_part1(ec, emp, holidays) + del ec # deleting the ec invalidates the database's cache + self._test_10_check_insert_correctness_part2(emp_gid, db) + + def test_10e_toMany_with_no_inverse(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/e]" + # insert h. + save + insert emp. + emp.addToHolidays + saveChanges + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + ec.insert(holidays) + ec.saveChanges() + + ec.insert(emp) + emp.addToHolidays(holidays) + ec.saveChanges() + + emp_gid, db=self._test_10_check_insert_correctness_part1(ec, emp, holidays) + del ec # deleting the ec invalidates the database's cache + self._test_10_check_insert_correctness_part2(emp_gid, db) + + def _test_11a_init_emp_and_holidays(self, ec): + emp=Employee.Employee() + emp.setLastName('Test'); emp.setFirstName('T.') + from mx.DateTime import DateFrom + holidays=Holidays() + holidays.setStartDate(DateFrom('2003-07-01 08:00')) + holidays.setEndDate(DateFrom('2003-08-01 08:00')) + ec.insert(emp) + ec.insert(holidays) + emp.addToHolidays(holidays) + ec.saveChanges() + return emp, holidays + + def test_11a_toMany_with_no_inverse__remove(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [remove/a]" + # remove simple + ec=EditingContext() + emp, holidays=self._test_11a_init_emp_and_holidays(ec) + + emp.removeFromHolidays(holidays) + ec.saveChanges() + + emp_gid=emp.globalID() + h_gid=holidays.globalID() + db=ec.rootObjectStore().objectStoreForObject(emp).database() + self.failUnless(db.snapshotForGlobalID(h_gid)['fkEmployeeId'] is None) + del ec + + # make sure we won't get informations from the db cache + self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) + ec2=EditingContext() + emp2=ec2.fetch('Employee')[0] + self.failIf(len(emp2.getHolidays())!=0) + + def test_11b_toMany_with_no_inverse__remove(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/b]" + # remove + add + ec=EditingContext() + emp, holidays=self._test_11a_init_emp_and_holidays(ec) + + emp.removeFromHolidays(holidays) + h2=Holidays() + from mx.DateTime import DateFrom + sd2=DateFrom('2003-01-01 01:00') + ed2=DateFrom('2003-02-02 02:00') + h2.setStartDate(sd2) + h2.setEndDate(ed2) + ec.insert(h2) + emp.addToHolidays(h2) + ec.saveChanges() + + emp_gid=emp.globalID() + h_gid=holidays.globalID() + db=ec.rootObjectStore().objectStoreForObject(emp).database() + self.failUnless(db.snapshotForGlobalID(h_gid)['fkEmployeeId'] is None) + del ec + + # make sure we won't get informations from the db cache + self.failIf(db.snapshotForSourceGlobalID(emp_gid, 'holidays')) + ec2=EditingContext() + emp2=ec2.fetch('Employee')[0] + self.assertEqual(len(emp2.getHolidays()), 1) + h2b=emp2.getHolidays()[0] + self.assertEqual(sd2, h2b.getStartDate()) + self.assertEqual(ed2, h2b.getEndDate()) + #print db.snapshotForGlobalID(h_gid) + + def test_11c_toMany_with_no_inverse__remove(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly updated [insert/c]" + # remove + add + ec=EditingContext() + emp, holidays=self._test_11a_init_emp_and_holidays(ec) + + emp.removeFromHolidays(holidays) + ec.delete(emp) + ec.saveChanges() + + db=ec.rootObjectStore().objectStoreForObject(holidays).database() + h_gid=holidays.globalID() + del ec + + ec2=EditingContext() + h2=ec2.fetch('Holidays')[0] + #print db.snapshotForGlobalID(h_gid) + self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']!=None) + + def test_12_toMany_with_no_inverse__correct_fetch(self): + "[EC/Inheritance] toMany w/o inverse: obj. correctly fetched" + ec=EditingContext() + emp, holidays=self._test_11a_init_emp_and_holidays(ec) + db=ec.rootObjectStore().objectStoreForObject(holidays).database() + h_gid=holidays.globalID() + del ec + ec2=EditingContext() + h2=ec2.fetch('Holidays')[0] + self.failIf(db.snapshotForGlobalID(h_gid)['fkEmployeeId']==None) + + def test_13_toMany_with_no_inverse__snapshot_row(self): + "[EC/Inheritance] toMany w/o inverse: obj.snapshot_raw()" + ec=EditingContext() + emp, holidays=self._test_10_create_emp_n_holidays() + ec.insert(emp) + ec.insert(holidays) + emp.addToHolidays(holidays) + + # Not computed before saveChanges() + self.assertEqual(holidays.snapshot_raw()['fkEmployeeId'], None) + ec.saveChanges() + self.assertEqual(holidays.snapshot_raw()['fkEmployeeId'], + emp.globalID().keyValues()['id']) def tearDown(self): *************** *** 387,390 **** --- 653,660 ---- sqlExpr.setStatement("delete from ADDRESS where id>3") channel.evaluateExpression(sqlExpr) + sqlExpr.setStatement("delete from EMPLOYEE") + channel.evaluateExpression(sqlExpr) + sqlExpr.setStatement("delete from HOLIDAYS") + channel.evaluateExpression(sqlExpr) *************** *** 536,539 **** --- 806,814 ---- model=ModelSet.defaultModelSet().modelNamed('StoreEmployees') Model.updateModelWithCFG(model, database_cfg) + + # MySQL specifics: change TIMESTAMP to DATETIME + if database_cfg=='MySQL.cfg': + model.entityNamed('Holidays').attributeNamed('startDate').setExternalType('DATETIME') + model.entityNamed('Holidays').attributeNamed('endDate').setExternalType('DATETIME') utils.enable_model_cache_and_compute() |
From: <sbi...@us...> - 2003-07-28 06:15:19
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv5634 Modified Files: DatabaseContext.py CHANGES Log Message: Removed the constraint on to-many relationships for which an inverse to-one relationship had to be defined. Details: recordChangesInEditingContext() refactored, recordUpdateForObject() implemented, Index: DatabaseContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseContext.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** DatabaseContext.py 16 Jul 2003 19:16:00 -0000 1.17 --- DatabaseContext.py 28 Jul 2003 06:15:15 -0000 1.18 *************** *** 21,25 **** # #----------------------------------------------------------------------------- ! """ --- 21,25 ---- # #----------------------------------------------------------------------------- ! from __future__ import nested_scopes """ *************** *** 81,84 **** --- 81,87 ---- from mx.DateTime import DateFrom + import sys + #trace=lambda msg: sys.stderr.write(str(msg)+'\n') + # Framework from Database import DistantPastTimeInterval, GeneralDatabaseException *************** *** 304,307 **** --- 307,311 ---- # Set of DatabaseOperation self._dbOperations=[] + self._pending_dbOperations={} # gid -> DatabaseOperation # local cache for snapshots, initialized in prepareForSaveWithCoordinator *************** *** 486,489 **** --- 490,494 ---- """ + See SnapshotsHandling/recordSnapshotForGlobalID() """ return self.__snapshots.recordSnapshotForGlobalID(snapshot, aGlobalID) *************** *** 492,495 **** --- 497,501 ---- """ + See SnapshotsHandling.recordSnapshotForSourceGlobalID() """ return self.__snapshots.recordSnapshotForSourceGlobalID(aGlobalID) *************** *** 498,501 **** --- 504,508 ---- """ + See SnapshotsHandling.recordSnapshots() """ return self.__snapshots.recordSnapshots(snapshots) *************** *** 505,508 **** --- 512,516 ---- """ + See SnapshotsHandling.recordToManySnapshots() """ return self.__snapshots.recordToManySnapshots(snapshots) *************** *** 510,517 **** def recordUpdateForObject(self, aDatabaseObject, changes): """ ! Unimplemented yet """ ! self.__unimplemented__() def registerChannel(self, aDBchannel): """ --- 518,619 ---- def recordUpdateForObject(self, aDatabaseObject, changes): """ ! Called by the ObjectStoreCoordinator when an other DatabaseContext ! (including self) needs to forward changes on a given object --this can ! happen, for example, when a toMany relationship that has no inverse to-one ! relationship is modified in a given object 'obj1', because in this case ! the modification implies the modification of a foreign key stored in one ! or more objects 'obj<i>!=obj1'. ! ! This method is for internal use, you should not need to call it by ! hand. The following explanations are implementation details. ! ! DatabaseContexts are designed in such a way that it can receive such ! messages before or after recordChangesInEditingContext() has processed its ! own changes. More precisely, when calling this method on self, ! recordChangesInEditingContext() takes care to process all its changes ! (inserted, updated or deleted objects) before it may call this method. ! ! As a consequence: ! ! - if recordChangesInEditingContext() has not been called yet, it just ! stores the pending changes to be applied, by simply storing 'changes' ! in a pending database operation's newRow(). These changes will be then ! processed when recordChangesInEditingContext() is called. ! ! - otherwise, the behaviour depends on whether the method ! recordChangesInEditingContext() already created a database operation ! for the object. If it did, then this database operation is updated ! according to the supplied changes; otherwise a brand new database ! oeration is created and local snapshots are registered for the object. ! ! Parameters: ! ! aDatabaseObject -- the database object for which changes are notified ! ! changes -- a dictionary of {attributeName: value} ! ! See also: ObjectStoreCoordinator.forwardUpdateForObject() ! recordChangesInEditingContext() """ ! #self.__unimplemented_() ! # search for DB OP TBD ! original_gid=object_gid=aDatabaseObject.globalID() ! if object_gid.isTemporary(): ! object_gid=self.__temporaryGID_to_KeyGlobalID[object_gid] ! trace('recordUpdateForObject() aDatabaseObject: %s gid: %s changes: %s'%(aDatabaseObject, object_gid, changes)) ! dbOp=None ! ! if not self._dbOperations: ! # recordChangesInEditingContext() not called yet: just store changes ! # for later use ! trace('recordUpdateForObject() CALLED BEFORE recordChangesInEditingContext()') ! entity=self._database.entityNamed(object_gid.entityName()) ! dbOp=DatabaseOperation(object_gid, aDatabaseObject, entity) ! dbOp.setDatabaseOperator(DATABASE_UPDATE_OPERATOR) ! dbOp.setNewRow(changes) ! pendingDBops=self._pending_dbOperations.setdefault(object_gid, []) ! pendingDBops.append(dbOp) ! return ! ! # from this point on, we know recordChangesInEditingContext() was called: ! # we then either find the relevant dbOperation, or create our own ! # ! for op in self._dbOperations: # TBD optimize / filter et/ou acces par dict. ! if op.globalID() == object_gid: ! trace('recordUpdate() Found dbOp %s'%op) ! dbOp=op ! break ! ! if dbOp is None: ! trace('recordUpdate() Creating dbOp') ! entity=self._database.entityNamed(object_gid.entityName()) ! dbOp=DatabaseOperation(object_gid, aDatabaseObject, entity) ! dbOp.setDatabaseOperator(DATABASE_UPDATE_OPERATOR) ! self._dbOperations.append(dbOp) ! toManyKeys=aDatabaseObject.toManyRelationshipKeys() ! snapshot=aDatabaseObject.snapshot() ! snapshot.update(changes) ! snapshot, toManySnapshots=\ ! self._objectSnapshotToDBOperatorSnapshots(snapshot, object_gid, ! toManyKeys, entity) ! self.recordSnapshotForGlobalID(snapshot, object_gid) ! self.recordToManySnapshots({object_gid: toManySnapshots}) ! dbOp.setNewRow(snapshot) ! trace('recordUpdate snapshot:%s dbOp.newRow():%s'%(snapshot, dbOp.newRow())) ! dbOp.recordToManySnapshots(toManySnapshots) ! if aDatabaseObject.globalID().isTemporary(): ! dbOp.setDBSnapshot({}) ! else: ! dbOp.setDBSnapshot(self.database().snapshotForGlobalID(object_gid)) + + else: + dbOp.newRow().update(changes) + trace('YYYYYYYYYYYYYYYY %s %s'%(object_gid,self.snapshotForGlobalID(object_gid))) + #self.recordSnapshotForGlobalID(dbOp.newRow(), object_gid) + new_row=dbOp.newRow() + trace('recordUpdateForObject(): new_row: %s'%new_row) + + def registerChannel(self, aDBchannel): """ *************** *** 546,549 **** --- 648,652 ---- def registerLockedObjectWithGlobalID(self, aGlobalID): """ + Unimplemented """ *************** *** 645,649 **** finalizeCommitChanges() """ ! if not self.__isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" --- 748,752 ---- finalizeCommitChanges() """ ! if not self.isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" *************** *** 683,687 **** """ ! if not self.__isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" --- 786,790 ---- """ ! if not self.isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" *************** *** 706,712 **** def handlesFetchSpecification(self, aFetchSpecification): """ ! Searches the Database object for an entity named ! aFetchSpecification.entityName, returns 1/true if such an entity was ! found, 0/false otherwise. """ if self._database.entityNamed(aFetchSpecification.entityName()): --- 809,816 ---- def handlesFetchSpecification(self, aFetchSpecification): """ ! Tells whether the DatabaseContext is responsible for the fetch ! specification. A DatabaseContext is responsible for a fetch specification ! if the fetchSpec's entity is registered in the entities set managed by the ! dbContext.database() """ if self._database.entityNamed(aFetchSpecification.entityName()): *************** *** 716,719 **** --- 820,826 ---- def ownsGlobalID(self, aGlobalID): """ + Tells whether the DatabaseContext is responsible for the object. A + DatabaseContext is responsible for an object if the global id's entity is + registered in the entities set managed by the dbContext.database() """ try: *************** *** 727,730 **** --- 834,840 ---- def ownsObject(self, anObject): """ + Tells whether the DatabaseContext is responsible for the object. A + DatabaseContext is responsible for an object if the object's entity is + registered in the entities set managed by the dbContext.database() """ cd=ClassDescription.classDescriptionForObject(anObject) *************** *** 753,757 **** Raises 'RuntimeError' if the DatabaseContext is not saving changes. """ ! if not self.__isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" --- 863,867 ---- Raises 'RuntimeError' if the DatabaseContext is not saving changes. """ ! if not self.isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" *************** *** 762,765 **** --- 872,879 ---- _adaptorOperations=[] + trace('performChanges: dbOps: %s'%self._dbOperations) + #import pprint + #pprint.pprint(self._dbOperations) + for dbOp in self._dbOperations: # Simple: No locking, just operations *************** *** 804,807 **** --- 918,922 ---- ADAPTOR_INSERT_OPERATOR) adOp.setChangedValues(databaseOperation.newRow()) + trace('dbOptoAdOp: new row: %s'%databaseOperation.newRow()) return [adOp] *************** *** 818,821 **** --- 933,937 ---- rowDiffs=databaseOperation.rowDiffs() if not rowDiffs: + trace('NO ROW DIFF %s'%databaseOperation) return [] adOp=AdaptorOperation(databaseOperation.entity(), *************** *** 893,900 **** self.__temporaryGID_to_KeyGlobalID[gID]=newGid def recordChangesInEditingContext(self): """ Second step being triggered by the ObjectStoreCoordinator when the latter ! was instructed to do save the changes made in an EditingContext. The 'EditingContext' instance this method works with is the one supplied when 'prepareForSaveWithCoordinator()' was called. --- 1009,1093 ---- self.__temporaryGID_to_KeyGlobalID[gID]=newGid + def _recordChangesInEditingContext(self, gID, obj, dbOperator): + """ + Called by recordChangesInEditingContext() for each inserted, updated and + deleted object it examines. This method is for internal use only, you + should not need to call it by hand. + + This method creates the corresponding DatabaseOperation for the object, + adds it to the DatabaseContext's database operations. It also registers + the local snapshots for that objects (whose local snapshots will be passed + to the database() obect when changes are saved). It also examines any + pending DatabaseOperations that have been received by + recordUpdateForObject() before recordChangesInEditingContext() was called + (these changes were submitted by other DatabaseContexts). Last, it also + examines the resulting DatabaseOperation and set its operator to + DATABASE_NOTHING_OPERATOR if appropriate. + + Parameters: + + gID -- the globalID of the object, either temporary or not. If it is + temporary, it will be translated into the non-temporary GlobalID + the object will receive after it's been changed. + + obj -- the object to register + + dbOperator -- the database operator to be used for the created + DatabaseOperation + + See also: _examineToManySnapshots() + """ + entity=self.database().entityForObject(obj) + + if dbOperator==DATABASE_INSERT_OPERATOR or gID.isTemporary(): + # Build and use a regular (Key)GlobalID + gID=KeyGlobalID(entity.name(), self._pks_for_inserted_gIDs[gID]) + else: + pass + + #self.__temporaryGID_to_KeyGlobalID[tempGID]=gID + dbOp=DatabaseOperation(gID, obj, entity) + dbOp.setDatabaseOperator(dbOperator) + self._dbOperations.append(dbOp) + + # Now for the snapshotting part + objSnapshot=obj.snapshot() + toManyKeys=obj.toManyRelationshipKeys() + snapshot, toManySnapshots=\ + self._objectSnapshotToDBOperatorSnapshots(objSnapshot, gID, + toManyKeys, entity) + + # get pending operations received by recordUpdateForObject() + pending_ops=self._pending_dbOperations.get(gID, []) + for pending_op in pending_ops: + snapshot.update(pending_op.newRow()) + if pending_ops: + del self._pending_dbOperations[gID] + + self.recordSnapshotForGlobalID(snapshot, gID) + self.recordToManySnapshots({gID: toManySnapshots}) + dbOp.setNewRow(snapshot) + dbOp.recordToManySnapshots(toManySnapshots) + + if dbOperator==DATABASE_INSERT_OPERATOR: + dbOp.setDBSnapshot({}) + else: + dbOp.setDBSnapshot(self.database().snapshotForGlobalID(gID)) + + if dbOperator==DATABASE_UPDATE_OPERATOR: + # requires: + # dbOp.__dbSnapshot/setDBSnapshot + .__newRow/setNewRow + rowDiffs=dbOp.rowDiffs() + if not rowDiffs: + trace('recordChangesInEditingContext() ->NOTHING obj:%s gID:%s'%(obj, gID)) + dbOp.setDatabaseOperator(DATABASE_NOTHING_OPERATOR) + + trace('_recordChangesInEditingContext returning: %s, %s'%(gID, toManySnapshots)) + return gID, toManySnapshots + def recordChangesInEditingContext(self): """ Second step being triggered by the ObjectStoreCoordinator when the latter ! was instructed to save the changes made in an EditingContext. The 'EditingContext' instance this method works with is the one supplied when 'prepareForSaveWithCoordinator()' was called. *************** *** 905,909 **** persistent, ! - it also registered every changed objects into the local snapshotting table. **IMPORTANT**: the local snapshotting mechanism does not have any references to TemporaryGlobalID objects: new objects are detected --- 1098,1102 ---- persistent, ! - it also registers every changed objects into the local snapshotting table. **IMPORTANT**: the local snapshotting mechanism does not have any references to TemporaryGlobalID objects: new objects are detected *************** *** 919,922 **** --- 1112,1116 ---- commitChanges(), rollbackChanges(), EditingContext.saveChanges() + recordUpdateForObject() Raises 'RuntimeError' if the DatabaseContext is not saving changes. *************** *** 932,1008 **** complete discussion on this topic. ! See also: DatabaseOperation """ ! if not self.__isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" for tempGID in self._inserted_gIDs: ! object=self._editingContext.objectForGlobalID(tempGID) ! entity=self.database().entityForObject(object) ! # Build and use a regular (Key)GlobalID ! gID=KeyGlobalID(entity.name(), self._pks_for_inserted_gIDs[tempGID]) ! #self.__temporaryGID_to_KeyGlobalID[tempGID]=gID ! dbOp=DatabaseOperation(gID, object, entity) ! dbOp.setDatabaseOperator(DATABASE_INSERT_OPERATOR) ! self._dbOperations.append(dbOp) ! # Now for the snapshotting part ! objSnapshot=object.snapshot() ! toManyKeys=object.toManyRelationshipKeys() ! snapshot, toManySnapshots=\ ! self._objectSnapshotToDBOperatorSnapshots(objSnapshot, gID, ! toManyKeys, entity) ! self.recordSnapshotForGlobalID(snapshot, gID) ! self.recordToManySnapshots({gID: toManySnapshots}) ! dbOp.setNewRow(snapshot) ! dbOp.recordToManySnapshots(toManySnapshots) ! dbOp.setDBSnapshot({}) ! for gID in self._updated_gIDs: ! object=self._editingContext.objectForGlobalID(gID) ! entity=self.database().entityForObject(object) ! dbOp=DatabaseOperation(gID, object, entity) ! dbOp.setDatabaseOperator(DATABASE_UPDATE_OPERATOR) ! self._dbOperations.append(dbOp) ! toManyKeys=object.toManyRelationshipKeys() ! objSnapshot=object.snapshot() ! snapshot, toManySnapshots=\ ! self._objectSnapshotToDBOperatorSnapshots(objSnapshot, gID, ! toManyKeys, entity) ! self.recordSnapshotForGlobalID(snapshot, gID) ! self.recordToManySnapshots({gID: toManySnapshots}) ! dbOp.setNewRow(snapshot) ! dbOp.recordToManySnapshots(toManySnapshots) ! dbOp.setDBSnapshot(self.database().snapshotForGlobalID(gID)) for gID in self._deleted_gIDs: ! object=self._editingContext.objectForGlobalID(gID) ! entity=self.database().entityForObject(object) ! dbOp=DatabaseOperation(gID, object, entity) ! dbOp.setDatabaseOperator(DATABASE_DELETE_OPERATOR) ! self._dbOperations.append(dbOp) ! # __TBD is this needed?? ! toManyKeys=object.toManyRelationshipKeys() ! snapshot=object.snapshot() ! snapshot, toManySnapshots=\ ! self._objectSnapshotToDBOperatorSnapshots(snapshot, gID, ! toManyKeys, entity) ! self.recordSnapshotForGlobalID(snapshot, gID) ! self.recordToManySnapshots({gID: toManySnapshots}) ! dbOp.setNewRow(snapshot) ! dbOp.recordToManySnapshots(toManySnapshots) ! dbOp.setDBSnapshot(self.database().snapshotForGlobalID(gID)) def _objectSnapshotToDBOperatorSnapshots(self, objectSnapshot, globalID, toManyKeys, entity): """ Internally used to convert a CustomObject.snapshot() to a snapshot a ! DatabaseOperator can fed fed with. Returns a tuple of two elements: --- 1126,1273 ---- complete discussion on this topic. ! This method also always add a fake DatabaseOperation to its own set, whose ! operator is DATABASE_NOTHING_OPERATOR and whose globalID, object and ! entity all equals to the string 'fake' --this is used by ! recordUpdateForObject(), see this method for a complete discussion on ! this. ! ! See also: DatabaseOperation, ! _recordChangesInEditingContext(), _examineToManySnapshots() """ ! if not self.isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" + # recordUpdateForObject() uses self._dbOperations to check whether + # we've been already called, so we add a fake dbOperation making NOTHING + # See recordUpdateForObject() docstring for details + fake_dbOp=DatabaseOperation('fake', 'fake', 'fake') + fake_dbOp.setDatabaseOperator(DATABASE_NOTHING_OPERATOR) + self._dbOperations.append(fake_dbOp) + + # this holds tomany snapshots, returned by _recordChangesInEditingContext() + # for use by the last phase, when invoking _examineToManySnapshots() + toManySnaps={} + for tempGID in self._inserted_gIDs: ! obj=self._editingContext.objectForGlobalID(tempGID) ! toManySnaps[tempGID]=self._recordChangesInEditingContext(tempGID, obj, DATABASE_INSERT_OPERATOR) ! for gID in self._updated_gIDs: ! obj=self._editingContext.objectForGlobalID(gID) ! toManySnaps[gID]=self._recordChangesInEditingContext(gID, obj, DATABASE_UPDATE_OPERATOR) ! ! for gID in self._deleted_gIDs: ! obj=self._editingContext.objectForGlobalID(gID) ! toManySnaps[gID]=self._recordChangesInEditingContext(gID, obj, DATABASE_DELETE_OPERATOR) ! ! # process the remaining pending databaseOperation ! for pending_gid, pending_dbOps in self._pending_dbOperations.items(): ! trace('recordUpdate(): processing pending gid: %s'%pending_gid) ! assert(not pending_gid.isTemporary()) ## ! obj=self._editingContext.objectForGlobalID(gid) ! toManySnaps[gID]=self._recordChangesInEditingContext(pending_gid, obj, DATABASE_UPDATE_OPERATOR) ! self._updated_gIDs.append(pending_gid) ! ! assert(self._pending_dbOperations == {}) # reset ! # Forwards possible changes (to recordUpdateForObject()) at the end ! for tempGID in self._inserted_gIDs: ! obj=self._editingContext.objectForGlobalID(tempGID) ! self._examineToManySnapshots(obj, ! toManySnaps[tempGID][0], ! toManySnaps[tempGID][1]) ! for gID in self._updated_gIDs: ! obj=self._editingContext.objectForGlobalID(gID) ! self._examineToManySnapshots(obj, gID, toManySnaps[gID][1]) for gID in self._deleted_gIDs: ! obj=self._editingContext.objectForGlobalID(gID) ! self._examineToManySnapshots(obj, gID, toManySnaps[gID][1]) ! ! def _examineToManySnapshots(self, object, aGlobalID, toManySnapshots): ! """ ! Examine the toMany snapshot computed by recordChangesInEditingContext() ! for an object, and takes the responsability to invoke ! ObjectStoreCoordinator.forwardUpdateForObject() for any object that should ! be notified of changes they couldn't be aware of yet. This is the case ! when an object modifies a to-many relationship which has no inverse: in ! this case we have to notify the added or removed objects that the foreign ! key storing the information for the to-many rel. should be changed. ! ! This method is for internal use, you should not need to call it by hand. ! ! Note: this method does NOT react to any modifications of to-many ! relationships which have an inverse to-one relationship defined in the ! model. It is the developer's responsability to maintain the consistency of ! the graph of objects hold by an EditingContext; when this is done, as ! expected, the added or removed objects have already been notified that ! something has changed and shouldn't be notified twice. ! ! Parameters: ! ! object -- the object to which the toManySnapshots belongs ! ! aGlobalID -- the object's non-temporary global id ! ! toManySnapshots -- the to-many snapshots to be examined ! ! """ ! changes={} ! ec=self._editingContext + for key in toManySnapshots.keys(): + rel=object.classDescription().entity().relationshipNamed(key) + assert(rel.isToMany()) + + # to-many rel + if rel.inverseRelationship(): + continue + db_snap=self.database().snapshotForSourceGlobalID(aGlobalID, key) + if list(db_snap) == toManySnapshots[key]: + continue + trace('############### %s != %s'%(list(db_snap), toManySnapshots[key])) + inv_rel=rel.anyInverseRelationship() + added_gids=[gid for gid in toManySnapshots[key] if gid not in db_snap] + removed_gids=[gid for gid in db_snap if gid not in toManySnapshots[key]] + trace('ADDED: %s'% added_gids) + trace('REMOVED: %s'% removed_gids) + modified_gids=added_gids+removed_gids + ### + def forwardChangesToObjects(self, inv_rel, removed): + for join in inv_rel.joins(): + src_attr=join.sourceAttributeName() + dst_attr=join.destinationAttributeName() + if removed: + changes[src_attr]=None + else: + changes[src_attr]=aGlobalID.keyValues()[dst_attr] + real_gid=gid + for g in self.__temporaryGID_to_KeyGlobalID.keys(): + if self.__temporaryGID_to_KeyGlobalID[g]==gid: + real_gid=g + break + + related_object=ec.faultForGlobalID(real_gid, ec) + trace('_examineToManySnapshots() related object: %s real_gid: %s'%(related_object, real_gid)) + self._coordinator.forwardUpdateForObject(related_object, changes) + ### + + for gid in added_gids: + forwardChangesToObjects(self, inv_rel, removed=0) + + for gid in removed_gids: + forwardChangesToObjects(self, inv_rel, removed=1) + def _objectSnapshotToDBOperatorSnapshots(self, objectSnapshot, globalID, toManyKeys, entity): """ Internally used to convert a CustomObject.snapshot() to a snapshot a ! DatabaseOperator can fed with. Returns a tuple of two elements: *************** *** 1048,1052 **** #snap.update(self._pks_for_inserted_gIDs[globalID]) ! # last, remove keys corresponding to a to-one relationship and # replace them with the appropriate (source-)attributes' keys and values for key in snap.keys(): --- 1313,1317 ---- #snap.update(self._pks_for_inserted_gIDs[globalID]) ! # Remove keys corresponding to a to-one relationship and # replace them with the appropriate (source-)attributes' keys and values for key in snap.keys(): *************** *** 1072,1075 **** --- 1337,1348 ---- for idx in range(len(srcAttrs)): snap[srcAttrNames[idx]]=pkValues[rel.destinationAttributeForSourceAttribute(srcAttrs[idx]).name()] + + # Last, check that all FKs are included, as expected + # It can happen that it is not the case when a toMany rel. has no inverse + # --> see test_EditingContext_Global_Inheritance, + # test: test_10_toMany_with_no_inverse__db_snapshot_is_correct() + for attr in entity.attributesNames(): + snap.setdefault(attr, None) + return (snap, toManySnap) *************** *** 1087,1091 **** See also: commitChanges() """ ! if not self.__isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" --- 1360,1364 ---- See also: commitChanges() """ ! if not self.isSavingChanges(): raise RuntimeError, "Invalid state: DatabaseContext isn't saving changes" *************** *** 1093,1112 **** self._endTransaction() - def recordUpdateForObject(self, anObject, aDictionaryOfChanges): - """ - Unimplemented: for the moment being we assume that every relationship has - an inverseRelationship defined in the model, and that the corresponding - delete rules are *NOT* DELETE_NOACTION ; as a consequence, - EditingContext.processRecentChanges() does the necessary to keep the graph - of objects in sync with all the modifications that are made, hence there - is no need to forward changes that couldnt have been noticed earlier - (there cannot be one of these!) - """ - #?defined in upper abstract class?# - #?defined in upper abstract class?# - #?defined in upper abstract class?# - self.__unimplemented__() - # update local snapshot - def valuesForKeys(self, keys, aDatabaseObject): """ --- 1366,1369 ---- *************** *** 1128,1132 **** after commit or rollback). ! See also: __isSavingChanges() """ self._coordinator=None --- 1385,1389 ---- after commit or rollback). ! See also: isSavingChanges() """ self._coordinator=None *************** *** 1137,1140 **** --- 1394,1398 ---- self._pks_for_inserted_gIDs={} self._dbOperations=[] + self._pending_dbOperations={} self.__snapshots=None self.__channel.closeChannel() *************** *** 1142,1149 **** self.__temporaryGID_to_KeyGlobalID=None ! def __isSavingChanges(self): """ Tells whether the DatabaseContext is currently saving changes. - (internal use) See also: prepareForSaveWithCoordinator(), saveChangesInEditingContext(), --- 1400,1406 ---- self.__temporaryGID_to_KeyGlobalID=None ! def isSavingChanges(self): """ Tells whether the DatabaseContext is currently saving changes. See also: prepareForSaveWithCoordinator(), saveChangesInEditingContext(), Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.136 retrieving revision 1.137 diff -C2 -d -r1.136 -r1.137 *** CHANGES 25 Jul 2003 15:39:03 -0000 1.136 --- CHANGES 28 Jul 2003 06:15:16 -0000 1.137 *************** *** 8,11 **** --- 8,17 ---- -------------------------------------------------------- + * Removed the constraint on to-many relationships for which an inverse + to-one relationship had to be defined. + Details: recordChangesInEditingContext() refactored, + recordUpdateForObject() implemented, + model StoreEmployees changed. + * Added Relationship.anyInverseRelationship() --plus entity Holidays in test model StoreEmployees, with a toMany rel. Employee-->Holidays having |
From: <sbi...@us...> - 2003-07-28 06:10:27
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv4622 Modified Files: test_EditingContext_ParentChild.py Log Message: Added entity StoreEmployees.Holidays uses TIMESTAMP that should be reverted to DATETIME for MySQL Index: test_EditingContext_ParentChild.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_ParentChild.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** test_EditingContext_ParentChild.py 24 Jul 2003 11:30:52 -0000 1.12 --- test_EditingContext_ParentChild.py 28 Jul 2003 06:04:47 -0000 1.13 *************** *** 655,658 **** --- 655,660 ---- if database_cfg=='MySQL.cfg': author_books_model.entityNamed('Writer').attributeNamed('birthday').setExternalType('DATETIME') + store_employee_model.entityNamed('Holidays').attributeNamed('startDate').setExternalType('DATETIME') + store_employee_model.entityNamed('Holidays').attributeNamed('endDate').setExternalType('DATETIME') utils.enable_model_cache_and_compute() |
From: <sbi...@us...> - 2003-07-28 06:03:39
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv4491 Modified Files: test_EditingContext_Global.py Log Message: misc. doc. Index: test_EditingContext_Global.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_Global.py,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** test_EditingContext_Global.py 24 Jul 2003 12:07:25 -0000 1.33 --- test_EditingContext_Global.py 28 Jul 2003 06:03:36 -0000 1.34 *************** *** 876,880 **** # Now delete one of these, on a new EditingContext, WITHOUT deleting the ! # former one so that snapshots are not forgotten ec2=EditingContext() qualifier=qualifierWithQualifierFormat('lastName=="Hugo"') --- 876,880 ---- # Now delete one of these, on a new EditingContext, WITHOUT deleting the ! # former EC so that snapshots are not forgotten ec2=EditingContext() qualifier=qualifierWithQualifierFormat('lastName=="Hugo"') |
From: <sbi...@us...> - 2003-07-27 17:02:03
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv30275 Modified Files: DatabaseOperation.py Log Message: Modified __str__ so that it is now more explicit on its internals + added __repr__ Index: DatabaseOperation.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseOperation.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** DatabaseOperation.py 14 Mar 2003 11:40:08 -0000 1.3 --- DatabaseOperation.py 27 Jul 2003 17:02:01 -0000 1.4 *************** *** 371,374 **** """ """ ! return repr(self) --- 371,376 ---- """ """ ! return "<DBOperation op: %s gid: %s newRow: %s dbSnapshot: %s at %s>"%(self.__databaseOperator, self.__gID, self.__newRow, self.__dbSnapshot, hex(id(self))) + def __repr__(self): + return self.__str__() |
From: <sbi...@us...> - 2003-07-27 17:00:37
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv30002 Modified Files: Entity.py Log Message: Fixed attributesToFetch(): was omitting any FK involved in a to-many-relationship (with no inverse) declared in an other entity Index: Entity.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Entity.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** Entity.py 24 Jul 2003 17:02:34 -0000 1.16 --- Entity.py 27 Jul 2003 17:00:34 -0000 1.17 *************** *** 257,262 **** def attributes(self): """ ! Returns the full set of attributes ; it is returned as a dictionary ! where keys are 'attributeName's and values, 'Attribute' instances. """ return self._attributes.values() --- 257,261 ---- def attributes(self): """ ! Returns the full set of attributes """ return self._attributes.values() *************** *** 272,281 **** into at least one of these categories: ! - they are primary keys, ! ! - they are ``used for locking'' ! ! - they are class' properties ! - they are source attributes of a relationship --- 271,276 ---- into at least one of these categories: ! - they are not derived, ! - they are source attributes of a relationship *************** *** 295,301 **** for attribute in self.attributesUsedForLocking(): append(attribute, attributesToFetch); continue ! # ClassProperties for attribute in self.attributes(): ! if attribute.isClassProperty(): append(attribute, attributesToFetch); continue --- 290,296 ---- for attribute in self.attributesUsedForLocking(): append(attribute, attributesToFetch); continue ! # non derived for attribute in self.attributes(): ! if not attribute.isDerived(): append(attribute, attributesToFetch); continue |
From: <sbi...@us...> - 2003-07-26 18:32:42
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv5376/tests Modified Files: test_Model.py test_Relationship.py Log Message: Added Relationship.anyInverseRelationship() --plus entity Holidays in test model StoreEmployees, with a toMany rel. Employee-->Holidays having no inverse. This is the first step towards the removal of the constraint on to-many relationships that should have an inverse toOne rel. for the moment being. Index: test_Model.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_Model.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** test_Model.py 24 Jul 2003 16:46:36 -0000 1.5 --- test_Model.py 25 Jul 2003 15:39:04 -0000 1.6 *************** *** 35,39 **** def checkStoreEmployee(self, model): "Minimum checking of model StoreEmployees" ! entities=('Store','Employee','Executive','SalesClerk','Mark','Address') self.assertEqual(len(model.entities()), len(entities)) for e in entities: --- 35,39 ---- def checkStoreEmployee(self, model): "Minimum checking of model StoreEmployees" ! entities=('Store','Employee','Executive','SalesClerk','Mark','Address','Holidays') self.assertEqual(len(model.entities()), len(entities)) for e in entities: Index: test_Relationship.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_Relationship.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** test_Relationship.py 24 Jul 2003 17:02:34 -0000 1.4 --- test_Relationship.py 25 Jul 2003 15:39:04 -0000 1.5 *************** *** 25,28 **** --- 25,30 ---- """Tests for module Relationship""" + from __future__ import nested_scopes + import unittest if __name__ == "__main__": *************** *** 128,131 **** --- 130,134 ---- salesclerk=model.entityNamed('SalesClerk') address=model.entityNamed('Address') + holidays=model.entityNamed('Holidays') def test_01_inverseRelationship(self): *************** *** 158,161 **** --- 161,203 ---- self.assertEqual(paddr_toEmp_inverse, emp_toAddr) + def test_02_anyInverseRelationship(self): + "[Relationship/Inheritance] anyInverseRelationship" + emp_toAddr=self.employee.relationshipNamed('toAddresses') + ex_toAddr=self.executive.relationshipNamed('toAddresses') + sc_toAddr=self.salesclerk.relationshipNamed('toAddresses') + + emp_holidays=self.employee.relationshipNamed('holidays') + ex_holidays=self.executive.relationshipNamed('holidays') + sc_holidays=self.salesclerk.relationshipNamed('holidays') + + # relationship 'toAddresses' has inverse defined in the model + self.assertEqual(emp_toAddr.anyInverseRelationship(), + emp_toAddr.inverseRelationship()) + self.assertEqual(ex_toAddr.anyInverseRelationship(), + ex_toAddr.inverseRelationship()) + self.assertEqual(sc_toAddr.anyInverseRelationship(), + sc_toAddr.inverseRelationship()) + # relationships 'toHolidays' has no inverse defined in the model + self.assertEqual(emp_holidays.inverseRelationship(), None) + + def check_inverse(inverse): + self.failIf(inverse is None) + self.failIf(inverse in self.holidays.relationships()) + self.assertEqual(inverse.entity(), self.holidays) + self.failUnless(inverse.isToOne()) + self.assertEqual(inverse.entity(), self.holidays) + self.assertEqual(inverse.destinationEntity(), self.employee) + self.assertEqual(inverse.inverseRelationship(), emp_holidays) + + any_inv_emp_holidays=emp_holidays.anyInverseRelationship() + check_inverse(any_inv_emp_holidays) + + any_inv_ex_holidays=ex_holidays.anyInverseRelationship() + check_inverse(any_inv_ex_holidays) + + any_inv_sc_holidays=sc_holidays.anyInverseRelationship() + check_inverse(any_inv_sc_holidays) + + def test_suite(): suite = unittest.TestSuite() |
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/StoreEmployees In directory sc8-pr-cvs1:/tmp/cvs-serv5376/tests/testPackages/StoreEmployees Modified Files: Employee.py model_StoreEmployees.py model_StoreEmployees.xml pymodel_StoreEmployees.py Added Files: Holidays.py Log Message: Added Relationship.anyInverseRelationship() --plus entity Holidays in test model StoreEmployees, with a toMany rel. Employee-->Holidays having no inverse. This is the first step towards the removal of the constraint on to-many relationships that should have an inverse toOne rel. for the moment being. --- NEW FILE: Holidays.py --- # Modeling from Modeling.CustomObject import CustomObject from Modeling.Validation import ValidationException class Holidays(CustomObject): """ Holidays are objects ... """ __implements__ = CustomObject.__implements__ def __init__(self): "Initializer" self._startDate = None self._endDate = None def entityName(self): "Used by the framework to link this object to its entity" return "Holidays" # do not change # Attribute: month def getStartDate(self): "Return the Holidays / startDate attribute value" self.willRead() return self._startDate def setStartDate(self,startDate): "Change the Holidays / startDate attribute value" self.willChange() self._startDate = startDate def validateStartDate(self, value): "Edit this to enforce custom business logic" if 0: # your custom bizlogic raise ValidationException return # Attribute: endDate def getEndDate(self): "Return the Holidays / endDate attribute value" self.willRead() return self._endDate def setEndDate(self,endDate): "Change the Holidays / endDate attribute value" self.willChange() self._endDate = endDate def validateEndDate(self, value): "Edit this to enforce custom business logic" if 0: # your custom bizlogic raise ValidationException return Index: Employee.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/StoreEmployees/Employee.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Employee.py 2 Oct 2002 08:39:59 -0000 1.3 --- Employee.py 25 Jul 2003 15:39:04 -0000 1.4 *************** *** 17,20 **** --- 17,21 ---- self._firstName = None self._toAddresses=[] + self._holidays=[] self._toStore=None *************** *** 83,86 **** --- 84,111 ---- _toAddresses.remove(object) self._toAddresses=tuple(_toAddresses) + + + + # Relationship: holidays + + def getHolidays(self): + "Returns the holidays relationship (toMany)" + self.willRead() + return self._holidays + + def addToHolidays(self,object): + "Add the holidays relationship (toMany)" + if object not in self._holidays: + self.willChange() + _holidays=list(self._holidays) + _holidays.append(object) + self._holidays=tuple(_holidays) + + def removeFromHolidays(self,object): + "Remove the holidays relationship (toMany)" + self.willChange() + _holidays=list(self._holidays) + _holidays.remove(object) + self._holidays=tuple(_holidays) Index: model_StoreEmployees.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/StoreEmployees/model_StoreEmployees.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** model_StoreEmployees.py 7 May 2003 11:27:10 -0000 1.5 --- model_StoreEmployees.py 25 Jul 2003 15:39:04 -0000 1.6 *************** *** 23,26 **** --- 23,29 ---- <join sourceAttribute='fkStoreId' destinationAttribute='id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Address' parentEntity='' moduleName='Address' className='Address' typeName='' externalName='ADDRESS'> *************** *** 50,53 **** --- 53,59 ---- <join sourceAttribute='fkStoreId' destinationAttribute='id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Executive' parentEntity='Employee' moduleName='Executive' className='Executive' typeName='' externalName='EXECUTIVE'> *************** *** 69,72 **** --- 75,81 ---- <join sourceAttribute='id' destinationAttribute='FK_Executive_id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Mark' parentEntity='' moduleName='Mark' className='Mark' typeName='' externalName='MARK'> *************** *** 80,84 **** </relation> </entity> </model> - """ --- 89,99 ---- </relation> </entity> + <entity isReadOnly='0' isAbstract='0' name='Holidays' parentEntity='' moduleName='Holidays' className='Holidays' typeName='' externalName='HOLIDAYS'> + <primaryKey attributeName='id'/> + <attribute isClassProperty='0' width='0' columnName='ID' isRequired='1' precision='0' defaultValue='None' externalType='INTEGER' name='id' scale='0' type='int' displayLabel=''/> + <attribute isClassProperty='1' width='0' columnName='START_DATE' isRequired='1' precision='0' defaultValue='None' externalType='TIMESTAMP' name='startDate' scale='0' type='DateTime' displayLabel=''/> + <attribute isClassProperty='1' width='0' columnName='END_DATE' isRequired='1' precision='0' defaultValue='None' externalType='TIMESTAMP' name='endDate' scale='0' type='DateTime' displayLabel=''/> + <attribute isClassProperty='0' width='0' columnName='FK_EMPLOYEE_ID' isRequired='0' precision='0' defaultValue='None' externalType='INTEGER' name='fkEmployeeId' scale='0' type='int' displayLabel=''/> + </entity> </model> """ Index: model_StoreEmployees.xml =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/StoreEmployees/model_StoreEmployees.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** model_StoreEmployees.xml 7 May 2003 11:27:11 -0000 1.5 --- model_StoreEmployees.xml 25 Jul 2003 15:39:04 -0000 1.6 *************** *** 23,26 **** --- 23,29 ---- <join sourceAttribute='fkStoreId' destinationAttribute='id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Address' parentEntity='' moduleName='Address' className='Address' typeName='' externalName='ADDRESS'> *************** *** 50,53 **** --- 53,59 ---- <join sourceAttribute='fkStoreId' destinationAttribute='id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Executive' parentEntity='Employee' moduleName='Executive' className='Executive' typeName='' externalName='EXECUTIVE'> *************** *** 69,72 **** --- 75,81 ---- <join sourceAttribute='id' destinationAttribute='FK_Executive_id'/> </relation> + <relation deleteRule='0' isClassProperty='1' multiplicityUpperBound='-1' multiplicityLowerBound='0' destinationEntity='Holidays' name='holidays' displayLabel='' joinSemantic='0'> + <join sourceAttribute='id' destinationAttribute='fkEmployeeId'/> + </relation> </entity> <entity isReadOnly='0' isAbstract='0' name='Mark' parentEntity='' moduleName='Mark' className='Mark' typeName='' externalName='MARK'> *************** *** 79,82 **** --- 88,98 ---- <join sourceAttribute='FK_Executive_id' destinationAttribute='id'/> </relation> + </entity> + <entity isReadOnly='0' isAbstract='0' name='Holidays' parentEntity='' moduleName='Holidays' className='Holidays' typeName='' externalName='HOLIDAYS'> + <primaryKey attributeName='id'/> + <attribute isClassProperty='0' width='0' columnName='ID' isRequired='1' precision='0' defaultValue='None' externalType='INTEGER' name='id' scale='0' type='int' displayLabel=''/> + <attribute isClassProperty='1' width='0' columnName='START_DATE' isRequired='1' precision='0' defaultValue='None' externalType='TIMESTAMP' name='startDate' scale='0' type='DateTime' displayLabel=''/> + <attribute isClassProperty='1' width='0' columnName='END_DATE' isRequired='1' precision='0' defaultValue='None' externalType='TIMESTAMP' name='endDate' scale='0' type='DateTime' displayLabel=''/> + <attribute isClassProperty='0' width='0' columnName='FK_EMPLOYEE_ID' isRequired='0' precision='0' defaultValue='None' externalType='INTEGER' name='fkEmployeeId' scale='0' type='int' displayLabel=''/> </entity> </model> Index: pymodel_StoreEmployees.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/StoreEmployees/pymodel_StoreEmployees.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pymodel_StoreEmployees.py 7 Jul 2003 14:57:15 -0000 1.2 --- pymodel_StoreEmployees.py 25 Jul 2003 15:39:04 -0000 1.3 *************** *** 58,62 **** AInteger('mark', isRequired=1), ] ! ) ] model.associations=[ --- 58,67 ---- AInteger('mark', isRequired=1), ] ! ), ! Entity('Holidays', ! properties=[ ADateTime('startDate', isRequired=1), ! ADateTime('endDate', isRequired=1), ! ] ! ), ] model.associations=[ *************** *** 74,77 **** --- 79,86 ---- delete=['nullify', 'deny'], keys=['fkStoreId', 'id']), + Association('Holidays', 'Employee', + relations=[None, 'holidays'], + delete=[None, 'cascade'], + keys=['fkEmployeeId', 'id']), ] |
From: <sbi...@us...> - 2003-07-26 06:21:55
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv5376 Modified Files: Relationship.py CHANGES Log Message: Added Relationship.anyInverseRelationship() --plus entity Holidays in test model StoreEmployees, with a toMany rel. Employee-->Holidays having no inverse. This is the first step towards the removal of the constraint on to-many relationships that should have an inverse toOne rel. for the moment being. Index: Relationship.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Relationship.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** Relationship.py 24 Jul 2003 17:02:34 -0000 1.13 --- Relationship.py 25 Jul 2003 15:39:03 -0000 1.14 *************** *** 382,385 **** --- 382,423 ---- self._joins=tuple(_joins) + def anyInverseRelationship(self): + """ + If self.inverseRelationship() exists, return that one, otherwise build + and return an inverse relationship for self + + See also: inverseRelationship() + """ + inverse=self.inverseRelationship() + if inverse: + return inverse + + # we need to make one + parents=self.entity().parentEntities() + parents.reverse() # from root to leaf (self) + parents.append(self.entity()) + rel_to_inverse=None + for parent in parents: + parent_rel=parent.relationshipNamed(self.name()) + if parent_rel: + rel_to_inverse=parent_rel + break + + #inverse_name='inverse_for_%s_%s'%(self.entity().name(), self.name()) + inverse_name='inverse_for_%s_%s'%(parent_rel.entity().name(), self.name()) + inverse_rel=SimpleRelationship(inverse_name) + if self.isToOne(): + inverse_rel.setMultiplicityUpperBound(-1) + else: + inverse_rel.setMultiplicityUpperBound(1) + + inverse_rel.setEntity(self.destinationEntity()) + for join in rel_to_inverse.joins(): + src=self.destinationEntity().attributeNamed(join.destinationAttribute().name()) + dst=rel_to_inverse.entity().attributeNamed(join.sourceAttribute().name()) + inv_join=Join(src, dst) + inverse_rel.addJoin(inv_join) + return inverse_rel + def clone(self, entity, name=None): """ *************** *** 455,458 **** --- 493,498 ---- Returns the inverse relationship in the destination entity, or None if it does not exist + + See also: anyInverseRelationship() """ #import pdb ; pdb.set_trace() *************** *** 481,485 **** # if you can't find an inverse on self.entity, we'd probably find one # in parent entities: ! self_rels=[e.relationshipNamed(self.name()) for e in src_entities] for self_rel in self_rels: --- 521,534 ---- # if you can't find an inverse on self.entity, we'd probably find one # in parent entities: ! # ! # Note: the following makes it possible to compute an inverseRelationship ! # for a relationship built by anyInverseRelationship() ! # The trick here is that such a relion is NOT added to ! # self.relationships(), so we need to explicitly add 'self' ! # instead of relying on self.entity().relationshipNamed() which in ! # this case returns None. ! self_rels=[self] ! self_rels.extend([e.relationshipNamed(self.name()) for e in src_entities ! if e != self]) for self_rel in self_rels: *************** *** 708,712 **** def __eq__(self, aRelationship): "Tests whether both relationship are equal" ! if aRelationship.isFlattened(): return 0 try: --- 757,761 ---- def __eq__(self, aRelationship): "Tests whether both relationship are equal" ! if aRelationship is None or aRelationship.isFlattened(): return 0 try: *************** *** 1135,1139 **** def __eq__(self, aRelationship): "Tests whether both relationship are equal" ! if not aRelationship.isFlattened(): return 0 try: --- 1184,1188 ---- def __eq__(self, aRelationship): "Tests whether both relationship are equal" ! if aRelationship is None or not aRelationship.isFlattened(): return 0 try: Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.135 retrieving revision 1.136 diff -C2 -d -r1.135 -r1.136 *** CHANGES 24 Jul 2003 17:02:34 -0000 1.135 --- CHANGES 25 Jul 2003 15:39:03 -0000 1.136 *************** *** 8,11 **** --- 8,17 ---- -------------------------------------------------------- + * Added Relationship.anyInverseRelationship() --plus entity Holidays in + test model StoreEmployees, with a toMany rel. Employee-->Holidays having + no inverse. This is the first step towards the removal of the constraint + on to-many relationships that should have an inverse toOne rel. for the + moment being. + * Fixed bug #776996: RelationshipManipulation methods misbehaving w/ inheritance. Implied fixing: Relationship.inverseRelationship(). Also |
From: <sbi...@us...> - 2003-07-24 17:51:32
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv11875/tests Modified Files: test_Model.py Log Message: misc. Index: test_Model.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_Model.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** test_Model.py 7 Jul 2003 14:57:14 -0000 1.4 --- test_Model.py 24 Jul 2003 16:46:36 -0000 1.5 *************** *** 36,40 **** "Minimum checking of model StoreEmployees" entities=('Store','Employee','Executive','SalesClerk','Mark','Address') ! self.failIf(len(model.entities()) != len(entities)) for e in entities: self.failIf(e not in model.entitiesNames(), "%s not in model"%e) --- 36,40 ---- "Minimum checking of model StoreEmployees" entities=('Store','Employee','Executive','SalesClerk','Mark','Address') ! self.assertEqual(len(model.entities()), len(entities)) for e in entities: self.failIf(e not in model.entitiesNames(), "%s not in model"%e) |
From: <sbi...@us...> - 2003-07-24 17:02:39
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv14424/tests Modified Files: test_Relationship.py test_RelationshipManipulation.py Log Message: Fixed bug #776996: RelationshipManipulation methods misbehaving w/ inheritance. Implied fixing: Relationship.inverseRelationship(). Also added: entity.parentEntities() Index: test_Relationship.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_Relationship.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** test_Relationship.py 10 Jan 2003 10:45:45 -0000 1.3 --- test_Relationship.py 24 Jul 2003 17:02:34 -0000 1.4 *************** *** 28,34 **** --- 28,36 ---- if __name__ == "__main__": import utils, sys + utils.disable_model_cache() utils.fixpath() from Modeling import ModelSet + import StoreEmployees # load the model *************** *** 117,123 **** --- 119,165 ---- rel_da.validateValue([A(), A(), A()]) + + + class TestRelationship_n_Inheritance(unittest.TestCase): + "Tests the relationships in inheritance " + model=ModelSet.defaultModelSet().modelNamed('StoreEmployees') + employee=model.entityNamed('Employee') + executive=model.entityNamed('Executive') + salesclerk=model.entityNamed('SalesClerk') + address=model.entityNamed('Address') + + def test_01_inverseRelationship(self): + "[Relationship/Inheritance] inverseRelationship" + ## Add PersonalAddress, stupid subentity for Address + from Modeling.Entity import externalNameForInternalName + paddress=self.address.clone('PersonalAddress', model) + self.address.addSubEntity(paddress) + paddress.setClassName('AuthorBooks.PersonalAddress') # does not exist + paddress.setExternalName(externalNameForInternalName('PersonalAddress')) + + ### + self.perso_address=model.entityNamed('PersonalAddress') + + emp_toAddr=self.employee.relationshipNamed('toAddresses') + ex_toAddr=self.executive.relationshipNamed('toAddresses') + sc_toAddr=self.salesclerk.relationshipNamed('toAddresses') + + addr_toEmp=self.address.relationshipNamed('toEmployee') + paddr_toEmp=self.perso_address.relationshipNamed('toEmployee') + + emp_toAddr_inverse=emp_toAddr.inverseRelationship() + self.failUnless(emp_toAddr_inverse) + self.assertEqual(ex_toAddr.inverseRelationship(), emp_toAddr_inverse) + self.assertEqual(sc_toAddr.inverseRelationship(), emp_toAddr_inverse) + + addr_toEmp_inverse=addr_toEmp.inverseRelationship() + paddr_toEmp_inverse=paddr_toEmp.inverseRelationship() + self.assertEqual(addr_toEmp_inverse, emp_toAddr) + self.assertEqual(paddr_toEmp_inverse, emp_toAddr) + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestRelationship, "test_")) + suite.addTest(unittest.makeSuite(TestRelationship_n_Inheritance, "test_")) return suite Index: test_RelationshipManipulation.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_RelationshipManipulation.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_RelationshipManipulation.py 10 Jan 2003 10:45:45 -0000 1.2 --- test_RelationshipManipulation.py 24 Jul 2003 17:02:34 -0000 1.3 *************** *** 286,292 **** --- 286,316 ---- + class TestRelationshipManipulation_n_Inheritance(unittest.TestCase): + "Tests for RelationshipManipulation in an inheritance environment" + def test_01_addToBothSideOfRelationshipWithKey_one_to_many(self): + "[RelationshipManipulation/Inheritance] addObjToBothSide() one-to-many" + from StoreEmployees import Employee, Executive, SalesClerk, Address + emp=Employee.Employee() + a=Address.Address() + emp.addObjectToBothSidesOfRelationshipWithKey(a, 'toAddresses') + self.failUnless(a in emp.getToAddresses()) + self.failUnless(emp == a.getToEmployee()) + + ex=Executive.Executive() + a=Address.Address() + ex.addObjectToBothSidesOfRelationshipWithKey(a, 'toAddresses') + self.failUnless(a in ex.getToAddresses()) + self.failUnless(ex == a.getToEmployee()) + + sc=SalesClerk.SalesClerk() + a=Address.Address() + sc.addObjectToBothSidesOfRelationshipWithKey(a, 'toAddresses') + self.failUnless(a in sc.getToAddresses()) + self.failUnless(sc == a.getToEmployee()) + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestRelationshipManipulation, "test_")) + suite.addTest(unittest.makeSuite(TestRelationshipManipulation_n_Inheritance, "test_")) return suite |
From: <sbi...@us...> - 2003-07-24 17:02:37
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv14424 Modified Files: CHANGES Entity.py Relationship.py Log Message: Fixed bug #776996: RelationshipManipulation methods misbehaving w/ inheritance. Implied fixing: Relationship.inverseRelationship(). Also added: entity.parentEntities() Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.134 retrieving revision 1.135 diff -C2 -d -r1.134 -r1.135 *** CHANGES 24 Jul 2003 13:34:06 -0000 1.134 --- CHANGES 24 Jul 2003 17:02:34 -0000 1.135 *************** *** 8,11 **** --- 8,15 ---- -------------------------------------------------------- + * Fixed bug #776996: RelationshipManipulation methods misbehaving w/ + inheritance. Implied fixing: Relationship.inverseRelationship(). Also + added: entity.parentEntities() + * Fixed bug #776592: was impossible to add raw '*' and '?' characters in a LIKE statement Index: Entity.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Entity.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** Entity.py 23 Jul 2003 12:17:41 -0000 1.15 --- Entity.py 24 Jul 2003 17:02:34 -0000 1.16 *************** *** 54,57 **** --- 54,58 ---- 'newOrOverriddenPythonProperties(), '\ 'newOrOverriddenPythonPropertiesNames(), parentEntity(), '\ + 'parentEntities(), '\ 'parentEntityName(), rootEntity(), removeSubEntity(), '\ 'subEntities()' *************** *** 568,571 **** --- 569,587 ---- return self._name + def parentEntities(self): + """Returns the parent entities (à la super-class, cf. inheritance) + + The returned set is ordered: it begins with the direct parent, and ends + with the rootEntity(). + + See also: %(inheritance_methods)s + """ + parents=[] + parent=self.parentEntity() + while parent: + parents.append(parent) + parent=parent.parentEntity() + return parents + def parentEntity(self): """Returns the parent entity (à la super-class, cf. inheritance) Index: Relationship.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Relationship.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** Relationship.py 24 Jul 2003 11:13:27 -0000 1.12 --- Relationship.py 24 Jul 2003 17:02:34 -0000 1.13 *************** *** 457,485 **** """ #import pdb ; pdb.set_trace() ! myDestEntity=self.destinationEntity() ! sameDestination=lambda rel, dst=self.entity(): rel.destinationEntity()==dst ! possibleInverse=filter(sameDestination, myDestEntity.relationships()) if not possibleInverse: return None # Check all possible relationships ! for inverseRel in possibleInverse: ! _self_joins=list(self.joins()) ! _inverse_joins=list(inverseRel.joins()) ! if len(_self_joins)!=len(_inverse_joins): continue ! isInverse=1 ! index=0 ! while _inverse_joins: ! #for index in range(0, len(_inverse_joins)): ! # Test each join of the relation against the set of joins in self ! reciprocical=map(lambda j, join=_inverse_joins[index]: \ ! j.isReciprocicalToJoin(join), ! _self_joins) ! isInverse=reduce(lambda a,b:a+b, reciprocical) ! if not isInverse: break # cannot be reciprocical ! del _self_joins[reciprocical.index(1)] ! del _inverse_joins[index] ! index+=1 ! if isInverse: ! return inverseRel return None #if not self.destinationEntity(): return None --- 457,507 ---- """ #import pdb ; pdb.set_trace() ! search_in_entities=[] ! ! ! # Search all possible relationships, i.e. relationships in the ! # destinationEntity() pointing to self.entity() or to one of its ! # parent entities: ! src_entities=self.entity().parentEntities() ! src_entities.insert(0, self.entity()) ! sameDestination=lambda rel, src=src_entities: rel.destinationEntity() in src ! #dest_entities=self.destinationEntity().parentEntities() ! dest_entities=[] ! dest_entities.insert(0, self.destinationEntity()) ! ! possibleInverse=[] ! for destEntity in dest_entities: ! l=filter(sameDestination, destEntity.relationships()) ! possibleInverse.extend(l) if not possibleInverse: return None # Check all possible relationships ! #import pdb ; pdb.set_trace() ! ! # if you can't find an inverse on self.entity, we'd probably find one ! # in parent entities: ! self_rels=[e.relationshipNamed(self.name()) for e in src_entities] ! ! for self_rel in self_rels: ! if self_rel is None: continue ! for inverseRel in possibleInverse: ! _self_joins=list(self_rel.joins()) ! _inverse_joins=list(inverseRel.joins()) ! if len(_self_joins)!=len(_inverse_joins): continue ! isInverse=1 ! index=0 ! while _inverse_joins: ! #for index in range(0, len(_inverse_joins)): ! # Test each join of the relation against the set of joins in self ! reciprocical=map(lambda j, join=_inverse_joins[index]: \ ! j.isReciprocicalToJoin(join), ! _self_joins) ! isInverse=reduce(lambda a,b:a+b, reciprocical) ! if not isInverse: break # cannot be reciprocical ! del _self_joins[reciprocical.index(1)] ! del _inverse_joins[index] ! index+=1 ! if isInverse: ! return inverseRel return None #if not self.destinationEntity(): return None |
From: <sbi...@us...> - 2003-07-24 16:45:57
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/AuthorBooks In directory sc8-pr-cvs1:/tmp/cvs-serv11763/tests/testPackages/AuthorBooks Modified Files: pymodel_AuthorBooks.py Log Message: Fixed: columnName were not correct wrt the xml model Index: pymodel_AuthorBooks.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/pymodel_AuthorBooks.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** pymodel_AuthorBooks.py 9 Jul 2003 11:41:15 -0000 1.3 --- pymodel_AuthorBooks.py 24 Jul 2003 16:45:50 -0000 1.4 *************** *** 8,11 **** --- 8,12 ---- from Modeling.PyModel import * + raise 'do not use' ## *************** *** 33,38 **** # Entity('Book', ! properties=[ APrimaryKey('id', isClassProperty=1), ! AString('title', isRequired=1), AFloat('price'), ], ), --- 34,40 ---- # Entity('Book', ! properties=[ APrimaryKey('id', isClassProperty=1, ! columnName='id'), ! AString('title', isRequired=1, columnName='title'), AFloat('price'), ], ), |
From: <sbi...@us...> - 2003-07-24 13:34:10
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide In directory sc8-pr-cvs1:/tmp/cvs-serv10262/doc/UserGuide Modified Files: EnvironmentVariables.tex Log Message: Added documentation for MDL_ENABLE_SIMPLE_METHOD_CACHE Index: EnvironmentVariables.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide/EnvironmentVariables.tex,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** EnvironmentVariables.tex 4 Jul 2003 17:46:31 -0000 1.9 --- EnvironmentVariables.tex 24 Jul 2003 13:34:06 -0000 1.10 *************** *** 1,2 **** --- 1,4 ---- + \newcommand{\inlineverb}[1]{\hspace*{1cm}\code{#1}\newline} + \chapter{Environment Variables\label{env-vars}} *************** *** 20,26 **** model, like this:\newline \newline ! \hspace*{1cm}\code{[<ModelName>]}\newline ! \hspace*{1cm}\code{user: <username>}\newline ! \hspace*{1cm}\code{password: <passwd>}\newline \newline Then, simply assign to the env. variable \code{MDL_DB_CONNECTIONS_CFG} --- 22,28 ---- model, like this:\newline \newline ! \inlineverb{[<ModelName>]} ! \inlineverb{user: <username>} ! \inlineverb{password: <passwd>} \newline Then, simply assign to the env. variable \code{MDL_DB_CONNECTIONS_CFG} *************** *** 45,48 **** --- 47,87 ---- \hline \newpage + \lineiii{MDL_ENABLE_SIMPLE_METHOD_CACHE}{}{} + \lineiii{}{When this variable is set to any non-empty string, the framework + automatically caches the simple methods of models and class description (by + simple methods, we mean methods taking \code{self} as their only + argument). Since both of these objects are heavily used at runtime (because + model introspection is needed at various stages), enabling this cache speeds + up the simple operations (for example, the inverse relationship for a given + relation is computed once, then it is cached). + \newline + There are situations, however, where you do not want to enable this. For + example, if after loading your model you need to change anything in it (such + as modifying the connection string, changing an attribute's external type, + adding a relationship, etc.), this shouldn't be enabled; if it is, the changes + won't have any effect on the model themselves: e.g. you can set the conection + dictionary but \method{connectionDictionary()} will keep returning its initial + value. In such situations, you can either: + \begin{itemize} + \item not enable this cache for the whole application, + \item or enable it after all changes have been made, by executing the + following code:\newline~\newline + {\small + \inlineverb{import os} + \inlineverb{from Modeling.ModelSet import defaultModelSet} + \inlineverb{os.environ['MDL\_ENABLE\_SIMPLE\_METHOD\_CACHE']='Y'} + \inlineverb{for model in defaultModelSet().models():} + \inlineverb{~~model.cacheSimpleMethods()} + }\newline + %\end{verbatim} + Attention: once the caching mechanism has been enabled, it cannot be disabled + (so no more changes can be made to your models) + \end{itemize} + Note: The environment variable \code{MDL_DB_CONNECTIONS_CFG} is taken into + account to update a model's properties before it is cached, no particular + action needs to be taken in this case.} + {e.g. '1', 'YES' (plus the empty string for de-activation)} + + \hline \lineiii{MDL_PERMANENT_DB_CONNECTION}{}{} \lineiii{}{By default, the database connection is closed each time the last *************** *** 63,66 **** --- 102,106 ---- \end{longtableiii} + \newpage \section{Postgresql specific\label{env-vars-postgresql}} |
From: <sbi...@us...> - 2003-07-24 13:34:10
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv10262 Modified Files: CHANGES Log Message: Added documentation for MDL_ENABLE_SIMPLE_METHOD_CACHE Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.133 retrieving revision 1.134 diff -C2 -d -r1.133 -r1.134 *** CHANGES 24 Jul 2003 12:07:25 -0000 1.133 --- CHANGES 24 Jul 2003 13:34:06 -0000 1.134 *************** *** 12,18 **** * Simple methods for models, entities, attributes, relationships and ! ClassDescriptions are now automatically cached. This speeds up operations ! where model introspection is needed (when saving changes, when using ! RelationshipManipulation interface, etc.) * Module RelationshipManipulation has been optimized and is now about 1.2x --- 12,19 ---- * Simple methods for models, entities, attributes, relationships and ! ClassDescriptions can now be automatically cached, This speeds up ! operations where model introspection is needed (when saving changes, when ! using RelationshipManipulation interface, etc.). See Appendix A.1, ! "Environment variables / Core" in the User's Guide for details. * Module RelationshipManipulation has been optimized and is now about 1.2x |
From: <sbi...@us...> - 2003-07-24 12:14:07
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv30794 Modified Files: PyModel.py Log Message: Fixed pb. with Attribute.setType(). See also: note about this in TODO Index: PyModel.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/PyModel.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PyModel.py 7 Jul 2003 14:57:13 -0000 1.2 --- PyModel.py 24 Jul 2003 12:14:04 -0000 1.3 *************** *** 954,958 **** # or we won't take advantage of custom logic defined in some # setters (like in 'Attribute.setType()') ! object.component.takeValueForKey(v,k) ## --- 954,961 ---- # or we won't take advantage of custom logic defined in some # setters (like in 'Attribute.setType()') ! if k=='type': ! object.component.setType(v, check=0) ! else: ! object.component.takeStoredValueForKey(v,k) ## |
From: <sbi...@us...> - 2003-07-24 12:12:35
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv30526 Modified Files: TODO Log Message: Updated Index: TODO =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/TODO,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** TODO 18 Jul 2003 14:30:45 -0000 1.14 --- TODO 24 Jul 2003 12:12:33 -0000 1.15 *************** *** 89,93 **** - These classes are the oldest of the framework ; their implementation began ! w/ the first version of the framework (never release, and so was the second refactor of the framework). They are in general poorly documented and some of their code is not very readable ; all this needs to be --- 89,93 ---- - These classes are the oldest of the framework ; their implementation began ! w/ the first version of the framework (never released, and so was the second refactor of the framework). They are in general poorly documented and some of their code is not very readable ; all this needs to be *************** *** 103,108 **** manipulation of a model) ! After the support for Pymodels are released, the refactoring might be more easily done. - Attribute: accepts both 'string' and 'str' for internalType(). This is --- 103,116 ---- manipulation of a model) ! After the support for PyModels are released, the refactoring might be more easily done. + + Related to this: Attribute.setType() has a 'check=1' default argument + which converts the Attribute.defaultValue into the right type. This is + "necessary" for the ZModeler and loading an xmlmodel as well; however, + this interacts badly with the PyModel themselves (see the test k=='type' + at the end of PyModel.updateComponent()). This should be rmeoved, and + explictely called when needed (i.e. in the ZModeler and when loading xml), + rather than maintaining that side-effect. - Attribute: accepts both 'string' and 'str' for internalType(). This is |
From: <sbi...@us...> - 2003-07-24 12:07:31
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv29656 Modified Files: SQLExpression.py CHANGES Log Message: Fixed bug #776592: was impossible to add raw '*' and '?' characters in a LIKE statement Index: SQLExpression.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/SQLExpression.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** SQLExpression.py 10 Jul 2003 11:57:54 -0000 1.18 --- SQLExpression.py 24 Jul 2003 12:07:25 -0000 1.19 *************** *** 65,68 **** --- 65,80 ---- NumericType=3 + # for use by SQLExpression.sqlPatternFromShellPatternWithEscapeCharacter + esc_question_tmp_replct='MDL_ESCAPED_QUESTION_MARK_MDL' + esc_star_tmp_replct='MDL_ESCAPED_STAR_MDL' + star=re.compile('\*') + escaped_star=re.compile(r'\\\*') + question_mark=re.compile('\?') + escaped_question_mark=re.compile(r'\\\?') + percent=re.compile('%') + underscore=re.compile('_') + anti_escaped_star=re.compile(esc_star_tmp_replct) + anti_esc_question_mark=re.compile(esc_question_tmp_replct) + class InvalidSQLTypeError(ValueError): """ *************** *** 910,924 **** Details: '%' in 'pattern' becomes '\%', '_' becomes '\_', ! '*' becomes '%' and '?' becomes '_'. """ - star=re.compile('\*') - question_mark=re.compile('\?') - percent=re.compile('%') - underscore=re.compile('_') - pattern=percent.sub('\\%', pattern) pattern=underscore.sub('\_', pattern) pattern=question_mark.sub('_', pattern) pattern=star.sub('%', pattern) return pattern --- 922,936 ---- Details: '%' in 'pattern' becomes '\%', '_' becomes '\_', ! '\*' becomes '*', '*' becomes '%', '\?' becomes '?' and ! '?' becomes '_'. """ pattern=percent.sub('\\%', pattern) pattern=underscore.sub('\_', pattern) + pattern=escaped_question_mark.sub(esc_question_tmp_replct, pattern) pattern=question_mark.sub('_', pattern) + pattern=escaped_star.sub(esc_star_tmp_replct, pattern) pattern=star.sub('%', pattern) + pattern=anti_escaped_star.sub('*', pattern) + pattern=anti_esc_question_mark.sub('?', pattern) return pattern Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.132 retrieving revision 1.133 diff -C2 -d -r1.132 -r1.133 *** CHANGES 23 Jul 2003 21:09:25 -0000 1.132 --- CHANGES 24 Jul 2003 12:07:25 -0000 1.133 *************** *** 8,11 **** --- 8,14 ---- -------------------------------------------------------- + * Fixed bug #776592: was impossible to add raw '*' and '?' characters in a + LIKE statement + * Simple methods for models, entities, attributes, relationships and ClassDescriptions are now automatically cached. This speeds up operations |