modeling-users Mailing List for Object-Relational Bridge for python (Page 35)
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(3) |
Oct
|
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(19) |
Feb
(55) |
Mar
(54) |
Apr
(48) |
May
(41) |
Jun
(40) |
Jul
(156) |
Aug
(56) |
Sep
(90) |
Oct
(14) |
Nov
(41) |
Dec
(32) |
2004 |
Jan
(6) |
Feb
(57) |
Mar
(38) |
Apr
(23) |
May
(3) |
Jun
(40) |
Jul
(39) |
Aug
(82) |
Sep
(31) |
Oct
(14) |
Nov
|
Dec
(9) |
2005 |
Jan
|
Feb
(4) |
Mar
(13) |
Apr
|
May
(5) |
Jun
(2) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
2006 |
Jan
(1) |
Feb
(1) |
Mar
(9) |
Apr
(1) |
May
|
Jun
(1) |
Jul
(5) |
Aug
|
Sep
(5) |
Oct
(1) |
Nov
|
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
(1) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Sebastien B. <sbi...@us...> - 2003-05-27 16:11:07
|
Yannick Gingras <ygi...@yg...> wrote: > On Monday 26 May 2003 21:14, Sebastien Bigaret wrote: > > Thanks a lot Yannick, nice job indeed. Now I know what a experienced > > xml-developper can do :) >=20 > You're mistaking me for someone else ; ) >=20 > I just happen to have a pro C++ friend. I really had to find a way to > reduce my parsing time... Hey, and is it quick enough now to stop a pro-C++ to argue?! > The no-xpath patch works perfectly on our model. Fine. BTW: I'm currently reviewing all of the dependencies for the framework and I wonder *why* on earth 4Suite was needed. I /think/ that I've now removed it from everywhere on my system and everything seems to run fine, however does anyone else here know for sure that 4Suite is NOT installed and that the framework behaves correctly? I'd prefer to be sure before removing it from the dependencies. Someone please correct me: everything in 4Suite installs itself in python package Ft, doesn't it? -- S=E9bastien. |
From: Yannick G. <ygi...@yg...> - 2003-05-27 02:13:46
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 26 May 2003 21:14, Sebastien Bigaret wrote: > Thanks a lot Yannick, nice job indeed. Now I know what a experienced > xml-developper can do :) You're mistaking me for someone else ; ) I just happen to have a pro C++ friend. I really had to find a way to reduce my parsing time... The no-xpath patch works perfectly on our model. : D - -- Yannick Gingras Coder for OBB : Oscan-speaking Bistred Blain http://OpenBeatBox.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+0snVrhy5Fqn/MRARAq6rAJ9pic23FS7Sb1BlH6nWWHwGY/ktSACdH+M1 xQwZr2SSo4J2aSYiRaoV8mg= =1Gpo -----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-05-27 01:16:11
|
Yannick Gingras <yan...@sa...> wrote: > After tweaking on my side to find a better implementation of DOM in > terms of performance I found that xml.dom.minidom.parseString() is > near 3 times faster than Sax2.Reader().fromStream().=20 >=20 > Since Modeling uses Sax2 in ModelSet to parse the XML model you might > want to try this patch :=20 [snipped] Wooho, great! My measures show that it makes loading a xml-model more than 2x faster. [measure made w/: t0=3Dtime.time() for i in range(10): ms=3DModelSet.ModelSet() ms.addModelFromXML({'file': 'xmlmodels/model_StoreEmployees.xml'}) t1=3Dtime.time() print t1-t0 ] Know what? It seems you stopped just a few seconds before the (x)path ends ;) > + _attrNames =3D map(lambda attrPair:attrPair[0], _attrNode.items()) > + for attributeName in _attrNames: > attrType=3Dself.xmlAttributeType(attributeName) > set=3Dself.xmlSetAttribute(attributeName) > value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')',=20 --> aNode.attributes.items() is exactly what we are looking for: names and corresponding values, hence we can also get rid of most of the xpath.Evaluate() as well... and now I can observe a performance boost of more than 6x ! If some of you could also apply the patch and test it against their models (it passes the tests) this will be integrated in cvs for the next release. I'd like to hear about the performance gain you observed as well, if possible. Thanks a lot Yannick, nice job indeed. Now I know what a experienced xml-developper can do :) -- S=E9bastien. Index: Attribute.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Attribute.py,v retrieving revision 1.12 diff -u -r1.12 Attribute.py --- Attribute.py 22 Apr 2003 09:31:56 -0000 1.12 +++ Attribute.py 27 May 2003 00:49:48 -0000 @@ -532,24 +532,20 @@ Initializes a model with the supplied xml.dom.node. =20 """ - _attrDict=3Dself.xmlAttributesDict() - _attrNode=3DaNode.attributes - attributes=3D[attr.name for attr in aNode.attributes] - + k_v=3DaNode.attributes.items() # Now we must make sure that the type is initialized BEFORE the default # value is set --> we simply make sure that this will be the first one # to be initialized try: - t=3D[a for a in attributes if a=3D=3D'type'][0] #IndexError - attributes.remove(t) - attributes=3D[t]+attributes + t=3D[a for a in k_v if a[0]=3D=3D'type'][0] #IndexError + k_v.remove(t) + k_v=3D[t]+k_v except IndexError: pass =20=20=20=20=20 - for attributeName in attributes: + for attributeName, value in k_v: # Iterate on attributes declared in node attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) - value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')', contextNode= =3DaNode) if attrType=3D=3D'string': value=3DunicodeToStr(value, encoding) set(value) =20 Index: Entity.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Entity.py,v retrieving revision 1.11 diff -u -r1.11 Entity.py --- Entity.py 22 Apr 2003 09:31:56 -0000 1.11 +++ Entity.py 27 May 2003 00:50:14 -0000 @@ -1258,13 +1258,12 @@ raise XMLImportError, "Cannot initialize a non-empty entity"=20 if phase not in (1,2): raise ValueError, 'Ooops, parameter phase should be 1 or 2!' - _attrDict=3Dself.xmlAttributesDict() - _attrNode=3DaNode.attributes - for attributeName in [attr.name for attr in aNode.attributes]: + + k_v=3DaNode.attributes.items() + for attributeName, value in k_v: # Iterate on attributes which are in the xml attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) - value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')', contextNode= =3DaNode) if attrType=3D=3D'string': value=3DunicodeToStr(value, encoding) set(value) =20=20=20=20=20=20=20 Index: Model.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Model.py,v retrieving revision 1.4 diff -u -r1.4 Model.py --- Model.py 22 Apr 2003 09:31:56 -0000 1.4 +++ Model.py 27 May 2003 00:50:14 -0000 @@ -240,12 +240,11 @@ """ if self.entities(): raise XMLImportError, "Cannot initialize a non-empty model"=20 - _attrDict=3Dself.xmlAttributesDict() - _attrNode=3DaNode.attributes - for attributeName in [attr.name for attr in aNode.attributes]: + + k_v=3DaNode.attributes.items() + for attributeName, value in k_v: attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) - value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')', contextNode= =3DaNode) if attrType=3D=3D'string': value=3DunicodeToStr(value, encoding) set(value) =20 Index: ModelSet.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelSet.py,v retrieving revision 1.7 diff -u -r1.7 ModelSet.py --- ModelSet.py 7 May 2003 11:28:45 -0000 1.7 +++ ModelSet.py 27 May 2003 00:50:14 -0000 @@ -54,6 +54,7 @@ NC=3DNotificationCenter import ClassDescription import types +from xml.dom.minidom import parseString =20 from logging import error, warn =20 @@ -220,14 +221,12 @@ #import pdb; pdb.set_trace() if xmlSource.has_key('string'): encoding=3DautoDetectXMLEncoding(xmlSource['string']) - reader=3DSax2.Reader() - xmldoc=3Dreader.fromString(xmlSource['string']) + xmldoc=3DparseString(xmlSource['string']) elif xmlSource.has_key('file'): f=3Dopen(xmlSource['file'], 'rb') encoding=3DautoDetectXMLEncoding(f.read()) f.close() - reader=3DSax2.Reader() - xmldoc=3Dreader.fromStream(xmlSource['file']) + xmldoc=3DparseString(open(xmlSource['file']).read()) else: raise AttributeError, "xmlSource parameter has no key 'string' or 'f= ile'" # Do we have only one model? _TBD: a DTD should be responsible for thi= s! Index: Relationship.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/Relationship.py,v retrieving revision 1.8 diff -u -r1.8 Relationship.py --- Relationship.py 22 Apr 2003 09:31:56 -0000 1.8 +++ Relationship.py 27 May 2003 00:50:23 -0000 @@ -242,14 +242,13 @@ """ Initializes a relationship with the supplied xml.dom.node. """ - _attrDict=3Dself.xmlAttributesDict() - _attrNode=3DaNode.attributes - for attributeName in [attr.name for attr in aNode.attributes]: + k_v=3DaNode.attributes.items() + for attributeName, value in k_v: # Iterate on attributes declared in node attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) - value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')', contextNode= =3DaNode) if attrType=3D=3D'string': value=3DunicodeToStr(value, encoding) + if attrType=3D=3D'number': value=3Dint(value) set(value) =20=20=20=20=20=20=20 return Index: XMLutils.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/XMLutils.py,v retrieving revision 1.3 diff -u -r1.3 XMLutils.py --- XMLutils.py 14 Mar 2003 11:40:10 -0000 1.3 +++ XMLutils.py 27 May 2003 00:50:24 -0000 @@ -50,11 +50,6 @@ pass =20 try: - from xml.dom.ext.reader import Sax2 - from xml.dom.ext.reader.Sax import FromXmlStream -except: - raise 'ImportError', 'PyXML is not installed' -try: from xml import xpath except: raise 'ImportError', 'XPath is not installed' |
From: Yannick G. <yan...@sa...> - 2003-05-26 18:37:35
|
=2D----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 After tweaking on my side to find a better implementation of DOM in terms of performance I found that xml.dom.minidom.parseString() is near 3 times faster than Sax2.Reader().fromStream().=20 Since Modeling uses Sax2 in ModelSet to parse the XML model you might want to try this patch :=20 diff -u -r ModelingCore-0.9-pre-7.1/Modeling/Attribute.py=20 ModelingCore-minidom/Modeling/Attribute.py =2D --- ModelingCore-0.9-pre-7.1/Modeling/Attribute.py 2003-04-22=20 05:31:56.000000000 -0400 +++ ModelingCore-minidom/Modeling/Attribute.py 2003-05-26 14:32:08.00000000= 0=20 =2D -0400 @@ -534,7 +534,7 @@ """ _attrDict=3Dself.xmlAttributesDict() _attrNode=3DaNode.attributes =2D - attributes=3D[attr.name for attr in aNode.attributes] + attributes=3Dmap(lambda attrPair:attrPair[0], _attrNode.items()) =20 # Now we must make sure that the type is initialized BEFORE the default # value is set --> we simply make sure that this will be the first one diff -u -r ModelingCore-0.9-pre-7.1/Modeling/Entity.py=20 ModelingCore-minidom/Modeling/Entity.py =2D --- ModelingCore-0.9-pre-7.1/Modeling/Entity.py 2003-04-22 05:31:56.000= 000000=20 =2D -0400 +++ ModelingCore-minidom/Modeling/Entity.py 2003-05-26 14:31:19.000000000=20 =2D -0400 @@ -1260,8 +1260,10 @@ raise ValueError, 'Ooops, parameter phase should be 1 or 2!' _attrDict=3Dself.xmlAttributesDict() _attrNode=3DaNode.attributes =2D - for attributeName in [attr.name for attr in aNode.attributes]: + + _attrNames =3D map(lambda attrPair:attrPair[0], _attrNode.items()) + for attributeName in _attrNames: # Iterate on attributes which are in the xml attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) =20 diff -u -r ModelingCore-0.9-pre-7.1/Modeling/Model.py=20 ModelingCore-minidom/Modeling/Model.py =2D --- ModelingCore-0.9-pre-7.1/Modeling/Model.py 2003-04-22 05:31:56.0000= 00000=20 =2D -0400 +++ ModelingCore-minidom/Modeling/Model.py 2003-05-26 14:30:38.000000000 -0= 400 @@ -242,7 +242,9 @@ raise XMLImportError, "Cannot initialize a non-empty model"=20 _attrDict=3Dself.xmlAttributesDict() _attrNode=3DaNode.attributes =2D - for attributeName in [attr.name for attr in aNode.attributes]: + + _attrNames =3D map(lambda attrPair:attrPair[0], _attrNode.items()) + for attributeName in _attrNames: attrType=3Dself.xmlAttributeType(attributeName) set=3Dself.xmlSetAttribute(attributeName) value=3Dxpath.Evaluate(attrType+'(@'+attributeName+')',=20 contextNode=3DaNode) diff -u -r ModelingCore-0.9-pre-7.1/Modeling/ModelSet.py=20 ModelingCore-minidom/Modeling/ModelSet.py =2D --- ModelingCore-0.9-pre-7.1/Modeling/ModelSet.py 2003-02-28=20 18:21:26.000000000 -0500 +++ ModelingCore-minidom/Modeling/ModelSet.py 2003-05-26 14:11:26.000000000= =20 =2D -0400 @@ -54,6 +54,7 @@ NC=3DNotificationCenter import ClassDescription import types +from xml.dom.minidom import parseString =20 from logging import error =20 @@ -143,14 +144,13 @@ #import pdb; pdb.set_trace() if xmlSource.has_key('string'): encoding=3DautoDetectXMLEncoding(xmlSource['string']) =2D - reader=3DSax2.Reader() =2D - xmldoc=3Dreader.fromString(xmlSource['string']) + xmldoc=3DparseString(xmlSource['string']) elif xmlSource.has_key('file'): f=3Dopen(xmlSource['file'], 'rb') encoding=3DautoDetectXMLEncoding(f.read()) f.close() =2D - reader=3DSax2.Reader() =2D - xmldoc=3Dreader.fromStream(xmlSource['file']) + print xmlSource['file'] + xmldoc=3DparseString(open(xmlSource['file']).read()) else: raise AttributeError, "xmlSource parameter has no key 'string' or=20 'file'" # Do we have only one model? _TBD: a DTD should be responsible for thi= s! diff -u -r ModelingCore-0.9-pre-7.1/Modeling/XMLutils.py=20 ModelingCore-minidom/Modeling/XMLutils.py =2D --- ModelingCore-0.9-pre-7.1/Modeling/XMLutils.py 2003-03-14=20 06:40:10.000000000 -0500 +++ ModelingCore-minidom/Modeling/XMLutils.py 2003-05-26 14:07:49.000000000= =20 =2D -0400 @@ -50,11 +50,6 @@ pass =20 try: =2D - from xml.dom.ext.reader import Sax2 =2D - from xml.dom.ext.reader.Sax import FromXmlStream =2D -except: =2D - raise 'ImportError', 'PyXML is not installed' =2D -try: from xml import xpath except: raise 'ImportError', 'XPath is not installed' =2D --=20 Yannick Gingras Byte Gardener, Savoir-faire Linux inc. (514) 276-5468 =2D----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQE+0l+Irhy5Fqn/MRARAs+tAJ4kl5i0Mb39egSO4MlWxsb+wEUqXgCeNcrX 9LwzMZtbamAuUv0XWppEGrw=3D =3DJ7Rj =2D----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-05-26 13:25:39
|
Hi Kodi and all, Kodi wrote: > I've tested the new feature and it is possible now to add an observer > with different methods for different Notifications. > But it should be pointed out that one has to define a value for the > key 'NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER' in the > environment, in order to enable the new behaviour. Well, yes, that was a terse announcement. However the documentation was updated --I've just updated it a bit more so that it's clear where the reference documentation stands, e.g. in module NotificationCenter cf. http://modeling.sourceforge.net/API/Notification-API/index.html I also forgot to mention that there is a new script tests/compare_perfs.py for comparing the performance of the framework when the new feature is en-/dis-abled. It is ~2.4x slower on my machine when enabled (the modeling framework does not need it to be activated, but of course behaves well when it is). I wrote: > > This release fixes two important bugs implying: > > - addObserver() not reporting when an object tries to register two or > > more different callbacks, > > - postNotification() copying the observers back to its own list, > > making it grow and causing degradation of performance each time it > > is called. > > The modeling framework itself is not affected by these changes and > > did not even triggered the bugs. However and since it may take > > advantages of these changes in the future, you'll probably want to > > upgrade your local copy. Sorry but I was a bit distracted when writing this: on the contrary the MDL is likely to trigger the second bug. It is revealed when a given notification is listened by both generic and specific observers, which is at least the case for MDL's GlobalIDChangedNotification (listened by EditingContext [generic] and DatabaseContext [specific]). Hence it is now *strongly recommended* that you upgrade your local copy with v0.5. Sorry for the wrong comment. Cheers, -- S=E9bastien. |
From: Thorsten K. <tk...@co...> - 2003-05-26 10:35:54
|
Hello, first of all I would like to thank Sebastien for his work on the nice frameworks. I've tested the new feature and it is possible now to add an observer with different methods for different Notifications. But it should be pointed out that one has to define a value for the key 'NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER' in the environment, in order to enable the new behaviour. Sebastien, thanks again for the fast response to the feature request, Have a nice day, yours kodi Sebastien Bigaret wrote: > Hi all, > > The NotificationFramework is a python implementation of the "Observer" > Design Pattern, allowing one-to-many dependency between objects even when > they have no idea of who and where the other objects live. > > This release fixes two important bugs implying: > > - addObserver() not reporting when an object tries to register two or > more different callbacks, > > - postNotification() copying the observers back to its own list, > making it grow and causing degradation of performance each time it > is called. > > It also offers an implementation for RFE#742511 allowing multiple > callbacks per observer. > > The modeling framework itself is not affected by these changes and did > not even triggered the bugs. However and since it may take advantages > of these changes in the future, you'll probably want to upgrade your > local copy. > > > -- Sébastien. > > > > ------------------------------------------------------- > This SF.net email is sponsored by: ObjectStore. > If flattening out C++ or Java code to make your application fit in a > relational database is painful, don't do it! Check out ObjectStore. > Now part of Progress Software. http://www.objectstore.net/sourceforge > _______________________________________________ > Modeling-users mailing list > Mod...@li... > https://lists.sourceforge.net/lists/listinfo/modeling-users > |
From: Sebastien B. <sbi...@us...> - 2003-05-25 19:40:49
|
Hi all, The NotificationFramework is a python implementation of the "Observer" Design Pattern, allowing one-to-many dependency between objects even when they have no idea of who and where the other objects live. This release fixes two important bugs implying: - addObserver() not reporting when an object tries to register two or more different callbacks, =20=20 - postNotification() copying the observers back to its own list, making it grow and causing degradation of performance each time it is called. It also offers an implementation for RFE#742511 allowing multiple callbacks per observer. The modeling framework itself is not affected by these changes and did not even triggered the bugs. However and since it may take advantages of these changes in the future, you'll probably want to upgrade your local copy. -- S=E9bastien.=20 |
From: Cash4models.com <tal...@ca...> - 2003-05-25 15:15:19
|
Don't miss this great opportunity. Free Portfolio, Free Classifieds, Free Listing. Click here for Cash4Models.com Remove. This is a one time invitation, your email will automatically be removed form the system. Please save and bookmark for future reference. |
From: Sebastien B. <sbi...@us...> - 2003-05-19 11:18:56
|
Hi, Mario Ruggier <ma...@ru...> wrote: [snip] > I like the Association idea -- it makes the model more clear and concise. > However, I feel there could be some confusion generated with the > interplay of Associations and Relationships, particularly in how defaults > are determined. In the implementation, associations use defaults from > the appropriate Relationship class. Does this mean that when using > Association one has to set defaults on Relationships, or can one simply > set the defaults on Association? (Also in the sample PyModel some of > the rel defaults are not needed.). Namely, would we be able to replace > the R defaults: >=20 > RToOne.defaults['delete'] =3D 'nullify' > RToOne.defaults['multiplicity'] =3D [0,1] > #RToOne.defaults['sourceAttribute'] =3D RToOne.attNameFromRel # > 'fk'+destEnt+destAtt+count > #RToOne.defaults['destinationAttribute'] =3D 'id' >=20 > RToMany.defaults['delete'] =3D 'cascade' > RToMany.defaults['multiplicity'] =3D [0,None] > #RToMany.defaults['sourceAttribute'] =3D 'id' > #RToMany.defaults['destinationAttribute'] =3D RToMany.attNameFromRel # > fk+destEnt+sourceAtt+count >=20 > simply with: >=20 > Association.defaults['delete'] =3D ['nullify', 'cascade'] You're right in a certain way: by construction Associations take their defaults from RToOne and RToMany. BUT: this is done when the module Modeling.PyModel is instanciated, hence any defaults set on RToOne and RToMany within the pymodel itself *do not influence* the way Associations are built. I understand this is confusing (only if you read the code, though ;) Maybe I'll remove the way Associations' defaults are set in the code, this would help clarify the way... they do not interact! For the sake of clarity: in the pymodel for StoreEmployees I posted, RToOne and RToMany defaults have *no* impact at all on the way relations beneath associations are built. They should be removed (done on CVS) and replaced by Association.defaults just as you said. > Is there a difference in doing this? The fact that Assocs use defaults f= rom > Rels, > but that Rels do not use defaults from Assocs should not be a problem -- > the idea to use Assocs is to simplify how to state Rels, and in the > same model it would be better not to require that stuff is set on Rels > to use Associations? Sure. About interdependencies: I do not think that defaults which are in common should be propagated between Rels and Associations. And I do not really want it either: they should be considered different. Yet another precision even when I'm sure you meant it right :) > BTW, you said earlier that you want to keep RToOne/RToMany > classes, to stay compatible with the current XML model -- this is a > good thing of course.=20 It's more than compatibility w/ the xml model: we need to be able to express any configurations supported by the framework. For example: - an Association won't let you specify that a FK should be a class property, unles you explicitly declare the AForeignKey, - you cannot design an uni-directional association Entity_1-->Entity_2 (with no inverse) with a PyModel.Association, here you need RToOne or RToMany to do the job. > But, when this design settles down, would adding > the Association construct to the XML model not be appropriate? I would say no, just because I consider the xml file to be the *exact* representation for a E-R model. It has no defaults, every single property is listed along with its value. XML files are the way models persists. BTW you might have noticed that I added a special property 'version' on PyModel; this is mainly because PyModels can heavily depend on the defaults. These defaults could be changed from time to time and when this happens we really want the user to know about this so that he can review the changes and adapt the PyModel if needed. Back on integrating Associations in xml models: I can see two more reasons why /I/ think this is probably not a good idea: - Associations depends on more defaults than other, e.g. in the way keys (source and destination attributes for relationships) are generated when they are unspecified. - There is no Association in the modeling layer (model, entity, attribute, relationship and join). This is intended and considered out of the scope of the E-R model; quoted from the TODO list: | a real (UML) Association class is needed -- Relationships (and | Joins) can be instanciated from them, and this would make it | possible to have a real object model and an 'physical' model. To | be continued. | | More generally this would be a good idea to have a real UML | model, being mapped on a E-R model for the physical (DB) | layer. Well, this is in fact outside the scope of the framework, | which will always need a model as it is (i.e. a description on | how to cross the bridge between the OO-world and the | Relational-world), but this would be a real enhancement in the | way the models are designed. This also suggests another remark: while PyModels offer a lot of facilities to quickly design models (in fact, they offer the same than the ZModeler already does), I would not recommend deploying a application with a pymodel using Association or any other implicit declaration of attributes (such as automatic FK creation, applying defaults, etc.): - most properties influences the framework at runtime. I did my best to make the PyModel's implicit mechanisms predictable, but I wont rely on this for a production environment, definitely (or we'll need to proove the predictability and this is too much work) - ''explicit is better than implicit'' ;) When pymodels are integrated in the framework's core I plan to change the python-code generation so that it also drops in the generated package a pymodel (derived from a pymodel or directly from an xml file) expressing all properties explicitly (this would make it an exact equivalent for the xml file). I say that because of the reasons stated above, plus because I also suggest that pymodels become the default for loading models (they are much, much faster than parsing xml). Note: xml files are used by some people (e.g. Yannick said here that he generates them from the xml produced by another tool). I'd like to restate here that xml models won't be deprecated. > Will PyModels interact with the 4 utility scripts (mdl_compile_model.py, > mdl_generate_DB_schema.py, mdl_generate_python_code.py, > mdl_validate_model.py) in the same way as XML models? Absolutely, even if it's not done yet --but that's the easy part! -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-05-19 09:52:50
|
hi, On dimanche, mai 18, 2003, at 18:25 Europe/Amsterdam, Sebastien Bigaret wrote: > Hi, > > A little more on the current choices and implementation for PyModels. > >> Association('E1', 'E2', >> multiplicity = [ [0,1], [0,None] ], # optional or >> mandatory? >> relations = [ 'toE2', 'toE1s' ], # optional >> keys = [ 'fkE2', 'id' ], # optional >> delete = [ 'nullify', 'nullify' ], # optional >> isClassProperty = [ 1, 1 ], # optional >> joinSemantic = [ 0, 0 ], # optional >> displayLabel = [ '', '' ], # optional >> doc= ['to one', 'to many' ], # optional >> ) > > Branch brch-0_9pre7-1-PyModel now fully implements this API for > associations. The multiplicity is *optional*, this means that: > >> Another thing I must stress is that Association currently associates >> E1 --> E2, w/ E1:toOne-->E2 and E2:toMany-->E1 > > is still correct. OK with this. >> [About modeling the StoreEmployees model] > Mario> > Nice. Version with Associations and no Relationships? > > The StoreEmployees model is also fully implemented with Associations > only and can be found at > http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/modeling/ > ProjectModeling/Modeling/tests/testPackages/StoreEmployees/Attic/ > pymodel_StoreEmployees.py?rev=1.1.2.2&only_with_tag=brch-0_9pre7-1- > PyModel&content-type=text/vnd.viewcvs-markup I like the Association idea -- it makes the model more clear and concise. However, I feel there could be some confusion generated with the interplay of Associations and Relationships, particularly in how defaults are determined. In the implementation, associations use defaults from the appropriate Relationship class. Does this mean that when using Association one has to set defaults on Relationships, or can one simply set the defaults on Association? (Also in the sample PyModel some of the rel defaults are not needed.). Namely, would we be able to replace the R defaults: RToOne.defaults['delete'] = 'nullify' RToOne.defaults['multiplicity'] = [0,1] #RToOne.defaults['sourceAttribute'] = RToOne.attNameFromRel # 'fk'+destEnt+destAtt+count #RToOne.defaults['destinationAttribute'] = 'id' RToMany.defaults['delete'] = 'cascade' RToMany.defaults['multiplicity'] = [0,None] #RToMany.defaults['sourceAttribute'] = 'id' #RToMany.defaults['destinationAttribute'] = RToMany.attNameFromRel # fk+destEnt+sourceAtt+count simply with: Association.defaults['delete'] = ['nullify', 'cascade'] (For multiplicity, srcAtt, dstAtt, these are already the "stock" defaults, so we do not need to restate them, except if we just want to make things explicit.) Is there a difference in doing this? The fact that Assocs use defaults from Rels, but that Rels do not use defaults from Assocs should not be a problem -- the idea to use Assocs is to simplify how to state Rels, and in the same model it would be better not to require that stuff is set on Rels to use Associations? BTW, you said earlier that you want to keep RToOne/RToMany classes, to stay compatible with the current XML model -- this is a good thing of course. But, when this design settles down, would adding the Association construct to the XML model not be appropriate? Will PyModels interact with the 4 utility scripts (mdl_compile_model.py, mdl_generate_DB_schema.py, mdl_generate_python_code.py, mdl_validate_model.py) in the same way as XML models? > > It passes the framework's tests (cf. > test_Editing_Global_Inheritance). > > Last (off-topic but it will be integrated in the next release): I > changed the way delete rules are stored for relationships: instead of > integers, they are now stored as plain strings ('nullify', 'deny', > 'cascade'): this makes things clearer. Of course, you can count on > backward compatibility and your (xml)models storing the delete rules as > integers are still loadable. OK, to be updated in the user guide. mario |
From: Sebastien B. <sbi...@us...> - 2003-05-18 16:25:36
|
Hi, A little more on the current choices and implementation for PyModels. > Association('E1', 'E2', > multiplicity =3D [ [0,1], [0,None] ], # optional or mandato= ry? > relations =3D [ 'toE2', 'toE1s' ], # optional=20 > keys =3D [ 'fkE2', 'id' ], # optional > delete =3D [ 'nullify', 'nullify' ], # optional > isClassProperty =3D [ 1, 1 ], # optional > joinSemantic =3D [ 0, 0 ], # optional > displayLabel =3D [ '', '' ], # optional > doc=3D ['to one', 'to many' ], # optional > ) Branch brch-0_9pre7-1-PyModel now fully implements this API for associations. The multiplicity is *optional*, this means that: > Another thing I must stress is that Association currently associates > E1 --> E2, w/ E1:toOne-->E2 and E2:toMany-->E1 is still correct. > [About modeling the StoreEmployees model] Mario> > Nice. Version with Associations and no Relationships? The StoreEmployees model is also fully implemented with Associations only and can be found at http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/modeling/ProjectModeling/Mod= eling/tests/testPackages/StoreEmployees/Attic/pymodel_StoreEmployees.py?rev= =3D1.1.2.2&only_with_tag=3Dbrch-0_9pre7-1-PyModel&content-type=3Dtext/vnd.v= iewcvs-markup It passes the framework's tests (cf. test_Editing_Global_Inheritance). Last (off-topic but it will be integrated in the next release): I changed the way delete rules are stored for relationships: instead of integers, they are now stored as plain strings ('nullify', 'deny', 'cascade'): this makes things clearer. Of course, you can count on backward compatibility and your (xml)models storing the delete rules as integers are still loadable. Again, it is not because implementation has begun that things cannot be changed; it's there so that those of you who want to play w/ it can make some experimentations. However and still, you do not need to download the code to comment the sample PyModel for StoreEmployees. Regards, -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-05-16 14:19:07
|
Hi all, I'd like to share some thoughts about the mailing-list's current usage. As it is exposed in the sourceforge project's page, this ml is primarily dedicated to users' queries (modeling_users: For users: questions, support, announcements, etc.) Some of us (including me) started discussing here about future features, including: - PyModels =20=20=20=20 - fetching objects within a certain range (SQL LIMIT/OFFSET), =20=20=20=20 - a new scheme for python-code generation (isolating all the specific modeling-code into a sub-package), etc. =20=20=20=20 - etc. Although nobody complained (yet), it can be that some of you get the feeling that this list is not for their questions. If this happens, *please* tell me either privately or on the ml, and I'll immediately create the appropriate modeling-dev mailing-list. This list is normally dedicated to users' support (framework general usage, specific problems, how-to-do-this questions, etc.). If for *any* reasons you feel uncomfortable about receiving development-related threads in your mail box, drop me a mail. If you already restrained yourself for asking sth. because you thought it was not the right place to ask for it, I'd like to know. Really! Cheers & happy modeling ;) -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-05-16 13:52:16
|
Mario Ruggier <ma...@ru...> wrote: [...] > > > > I expose here the points that were raised when trying it: > > > > - model & entity declarations: nothing has changed, except that I added > > the possibility to declare 'associations' in an entity (see below) >=20 > Like the idea a lot. It is better than using relationships because it > encapsulates the info about both ends in one place. > Can it replace Relationships (in client models) entirely? Well, if we want to make this possible we need to find a way to declare directional associations, i.e. when only E1-->E2 is neede (and not the inverse).=20 Another thing I must stress is that Association currently associates E1 --> E2, w/ E1:toOne-->E2 and E2:toMany-->E1 So: - either we keep this as-is (this allows Association('Employee', 'Store')) - or we drop the constraint (toOne e1->e2) but in that case the multiplicity parameter is mandatory for both > > - defaults: > > > > i. the way calculated defaults are declared needed to be > > changed, example: > > > > model.defaults=3D{ 'packageName': MP(identity, 'name'), } > > > > where MP is a special class for this (MP: Method/Parameters) > > identity is the method to be called (here identity=3Dlambda = x:x) > > 'name' is the name of the object's (model's) attribute to p= ass > > as an attribute (it should be an object's attribute) > > > > When multiple parameters are needed: > > MP(function,'param1','param2') >=20 > OK for me. My only question is that (frequently used) functions to be > passed to MP should be included in MP, or close by, as helper > functions, They can be loaded within the PyModel namespace (since we import *), no problem. > > - relationships: there are two different ways to declare them: > > > > a. fully qualified rels i.e. when source and destination key are > > specified such as in: > > > > Entity('Employee', > > AForeignKey('fkStore'), > > properties=3D[RToOne('toStore','Store',src=3D'fkStore',ds= t=3D'id')] > > ) > > > > b. unqualified rels, such as in: > > > > Entity('Employee', properties=3D[ RToOne('toStore', 'Store') ] ) > > > > When using such a scheme, you need to identify the inverse > > relationship, if any, by the keyword 'inverse'; it can be specifi= ed > > in either relationships, or in both. Example: > > > > Entity('Employee', properties=3D[ RToOne('toStore', 'Store', > > inverse=3D'toEmployees') = ] ) > > > > Both a. and b. are implemented. > > In case b. the foreign key is created in the source (resp. > > destination) entity for a RToOne (resp. RToMany) relationship >=20 > I suggest there should be (at least as recommendation) only one way. > I would prefer (b), as it is more expressive. But, as mentioned above, > this may all be pushed further down, and client model code should > only deal with Associations? Okay, now I know why I do not want to remove the RToOne/RToMany classes: we earlier decided that one of the pre-requisite is that the PyModel should be able to express *anything* that can be expressed in a xml-model (and in Modeling.Model,Entity, etc.) --> only dealing w/ associations makes it almost impossible to explicitely declare a ForeignKey with parameters !=3D from the defaults (or the Association's parameters set becomes to be really complicated) > > - new object: Association > > > > Association objects make it easier to quickly design a relationship > > and its inverse. Proposed usage: > > > > model.entities =3D [ > > Entity('Employee'), > > Entity('SalesClerk', parent=3D'Employee'), > > Entity('Mark'), > > Entity('Store'), > > ] > > model.associations =3D [ > > Association('Employee', 'Store'), > > Association('Mark', 'Employee'), > > ] > > > > (this is the StoreEmployee test model without the attributes) >=20 > This is nice. Compact and expressive. > Have you already mapped (in full, taking out relationships) the > StoreEmp model to using Associations? Not yet, but a basic implementation for associations is exposed in the dev-brch PyModel.py. I was waiting for ideas on the init API before going any further. > > Another full usage could be: > > > > # [...] > > model.associations =3D [ > > Association('Employee: toStore', 'Store: toEmployees', > > [0,1], # Employee -----> Store > > [0,None], # Store ---->> Employee > > ) > > ] > > > > (Implementation note: for the moment Association('E1', 'E2') > > builds a toOne E1--->E2 and a toMany E2--->E1) > > > > =3D> this is where I'm not clear at all. It seems to me that we should > > be able to specify: > > - the source and destination entity (mandatory) > > - the multiplicity for both relationships (optional) > > - the names of the toOne rel. and of the toMany rel. (optional) > > - maybe extra parameters for each rels, something like: > > > > model.associations =3D [ > > Association('Employee: toStore', 'Store: toEmployees', > > [0,1], # Employee -----> Store > > [0,None], # Store ---->> Employee > > { 'doc': 'toOne: Employee to Store' }, # Emp.to= Store > > { 'doc': 'toMany: Store to Employee' }, # Store.= toEmp. > > ) > > ] > > > > I'm not sure this looks pretty, so if you have ideas they are > > welcome ;) >=20 > One point I would like to stress is that there should be no bizarre > variations between how a parameter is specified in one > object or another. Thus Associations should try to follow as much > as possible the same semantics as the others -- which is that > required parameters are not named, and al other optional parameters > are named and have defaults. Introducing a dictionary param will > break that consistency... Anyway, how about: >=20 > Association('E1','E2', > rel =3D ['toE2', 'toE1' ] > multiplicity=3D [ [0,1], [0,None] ], > doc =3D ['to one', 'to many' ], > ... > ) >=20 > Defaults will be handled identically to other classes. Fine, it sounds consistent. Let's summarize this (w/ the defaults): Association('E1', 'E2', multiplicity =3D [ [0,1], [0,None] ], # optional or mandatory? relations =3D [ 'toE2', 'toE1s' ], # optional=20 keys =3D [ 'fkE2', 'id' ], # optional delete =3D [ 'nullify', 'nullify' ], # optional isClassProperty =3D [ 0, 0 ], # optional joinSemantic =3D [ 0, 0 ], # optional displayLabel =3D [ '', '' ], # optional doc=3D ['to one', 'to many' ], # optional ) > > Enclosed is a (working) version of sample_PyModel_5.py >=20 > Nice. Version with Associations and no Relationships? > Also, it may be a good idea to include the new way how to > handle conndict info, even in these examples. The new way of handling the connection dictionary (RFE #726839) only relies on a environment variable (MDL_DB_CONNECTIONS_CFG) being set and pointing to a specific file --> no python code needed. But we can include a comment in the code to indicate that. > Plus, see minor comment below. [...] > > Entity('Mark', > > properties=3D[ AInteger('month', isRequired=3D1), > > AInteger('mark', isRequired=3D1), > > AForeignKey('toExecutive', isClassProperty=3D0), >=20 > *** given your changes, is this needed (AForeignKey toExecutive) ? [...] Ok, let me clarify this. For RTone/RToMany: - if relations specify src & dst keys, these keys *must* be explicitly defined (for the moment being I mean, this is not an implementation issue) =20=20=20=20 - if not, they are automatically declared. In the sample code, entities get a PK by default, hence only FK needs to be declared explicitly, when applicable. -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-05-16 12:18:33
|
On jeudi, mai 15, 2003, at 20:50 Europe/Amsterdam, Sebastien Bigaret =20 wrote: > Hi there, > > More comments about PyModels --we need it in release 0.9 for the 1 > page tutorial to be really efficient. Great! > I started to implement things, I needed to play with some pymodels to > make up my mind on some specific stuff (esp. on declaring > relationships). Obviously the starting point was made of version 4 of > PyModel and sample_PyModel, I must admit that having these two modules > made it possible to code a first sketch for PyModel quite quickly > --thanks all for your comments. > > NB:For the curious that want to play with it to, I've committed a =20 > first > implementation in CVS branch brch-0_9pre7-1-PyModel (directory > Modeling/, where PyModel.py and tests/test_PyModel.py are added, > plus the following modules that were slightly changed: Model, > Entity, Attribute and Relationships. > > Obviously you do NOT need to check this out to participate to the > discussion! > > > I expose here the points that were raised when trying it: > > - model & entity declarations: nothing has changed, except that I = added > the possibility to declare 'associations' in an entity (see below) Like the idea a lot. It is better than using relationships because it encapsulates the info about both ends in one place. Can it replace Relationships (in client models) entirely? > - defaults: > > i. the way calculated defaults are declared needed to be > changed, example: > > model.defaults=3D{ 'packageName': MP(identity, 'name'), } > > where MP is a special class for this (MP: Method/Parameters) > identity is the method to be called (here identity=3Dlambda = =20 > x:x) > 'name' is the name of the object's (model's) attribute to =20= > pass > as an attribute (it should be an object's attribute) > > When multiple parameters are needed: > MP(function,'param1','param2') OK for me. My only question is that (frequently used) functions to be =20= passed to MP should be included in MP, or close by, as helper funtions, > ii. sample_PyModel_4 said: > > Entity('Employee', > properties=3D[ # [...] > AForeignKey(Attribute.fk('Store'), > isClassProperty=3D0), > ] ) > > --> Attribute.fk('<destEntity>') was not a good idea, it's even =20= > not > feasible. So: either you declare (and name) the foreign key, > or you rely on the initialization of a relationship to = create > it. OK. > - attributes: nothing changed > > - relationships: there are two different ways to declare them: > > a. fully qualified rels i.e. when source and destination key are > specified such as in: > > Entity('Employee', > AForeignKey('fkStore'), > =20 > properties=3D[RToOne('toStore','Store',src=3D'fkStore',dst=3D'id')] > ) > > b. unqualified rels, such as in: > > Entity('Employee', properties=3D[ RToOne('toStore', 'Store') ] ) > > When using such a scheme, you need to identify the inverse > relationship, if any, by the keyword 'inverse'; it can be =20 > specified > in either relationships, or in both. Example: > > Entity('Employee', properties=3D[ RToOne('toStore', 'Store', > inverse=3D'toEmployees') = ] =20 > ) > > Both a. and b. are implemented. > In case b. the foreign key is created in the source (resp. > destination) entity for a RToOne (resp. RToMany) relationship I suggest there should be (at least as recommendation) only one way. I would prefer (b), as it is more expressive. But, as mentioned above, this may all be pushed further down, and client model code should only deal with Associations? > - new object: Association > > Association objects make it easier to quickly design a relationship > and its inverse. Proposed usage: > > model.entities =3D [ > Entity('Employee'), > Entity('SalesClerk', parent=3D'Employee'), > Entity('Mark'), > Entity('Store'), > ] > model.associations =3D [ > Association('Employee', 'Store'), > Association('Mark', 'Employee'), > ] > > (this is the StoreEmployee test model without the attributes) This is nice. Compact and expressive. Have you already mapped (in full, taking out relationships) the StoreEmp model to using Associations? > > Another full usage could be: > > # [...] > model.associations =3D [ > Association('Employee: toStore', 'Store: toEmployees', > [0,1], # Employee -----> Store > [0,None], # Store ---->> Employee > ) > ] > > (Implementation note: for the moment Association('E1', 'E2') > builds a toOne E1--->E2 and a toMany E2--->E1) > > =3D> this is where I'm not clear at all. It seems to me that we = should > be able to specify: > - the source and destination entity (mandatory) > - the multiplicity for both relationships (optional) > - the names of the toOne rel. and of the toMany rel. (optional) > - maybe extra parameters for each rels, something like: > > model.associations =3D [ > Association('Employee: toStore', 'Store: toEmployees', > [0,1], # Employee -----> Store > [0,None], # Store ---->> Employee > { 'doc': 'toOne: Employee to Store' }, # =20 > Emp.toStore > { 'doc': 'toMany: Store to Employee' }, # =20 > Store.toEmp. > ) > ] > > I'm not sure this looks pretty, so if you have ideas they are > welcome ;) One point I would like to stress is that there should be no bizarre variations between how a parameter is specified in one object or another. Thus Associations should try to follow as much as possible the same semantics as the others -- which is that required parameters are not named, and al other optional parameters are named and have defaults. Introducing a dictionary param will break that consistency... Anyway, how about: Association('E1','E2', rel =3D ['toE2', 'toE1' ] multiplicity=3D [ [0,1], [0,None] ], doc =3D ['to one', 'to many' ], ... ) Defaults will be handled identically to other classes. > Now for the details: > > * multiplicity: unconstrained upper bound can be -1, '*' or None > > * I choose 'required' instead of 'allowsNone' for attributes/rels. OK for me. > Enclosed is a (working) version of sample_PyModel_5.py Nice. Version with Associations and no Relationships? Also, it may be a good idea to include the new way how to handle conndict info, even in these examples. Plus, see minor comment below. mario > As usual, your comments and critics are appreciated. A PyModel = *will* > be integrated in 0.9, I'd like it to meet *your* needs ;) > > Cheers, > > > -- S=E9bastien. > > = -----------------------------------------------------------------------=20= > - > ''' > sample_PyModel_5.py > A sample Pythonic OO-RDB Model > (re-expressing testPackages/StoreEmployees/model_StoreEmployees.xml) = -- > A PyModel must define a global variable called 'model', that is of =20 > type Model > ''' > > from PyModel import * > > ## > # Set preferred defaults for this model (when different from > # standard defaults, or if we want to make things explicit) > > AFloat.defaults['precision'] =3D 10 > AFloat.defaults['scale'] =3D 10 > AString.defaults['width'] =3D 20 > > RToOne.defaults['delete'] =3D 2 #'cascade' > RToOne.defaults['multiplicity'] =3D [0,1] > #RToOne.defaults['sourceAttribute'] =3D RToOne.attNameFromRel # =20 > 'fk'+destEnt+destAtt+count > #RToOne.defaults['destinationAttribute'] =3D 'id' > > RToMany.defaults['delete'] =3D 1 # 'deny' # this is temporary, final =20= > version > # will say =20 > 'deny'/'cascade'/'nullify' > # as expected > RToMany.defaults['multiplicity'] =3D [0,None] > #RToMany.defaults['sourceAttribute'] =3D 'id' > #RToMany.defaults['destinationAttribute'] =3D RToMany.attNameFromRel # = =20 > fk+destEnt+sourceAtt+count > > # Note that Relation.attNameFromRel is a callable, that calculates the = =20 > att > # name from the indicated pieces (where count to distinguish between =20= > multiple > # relations between same source and target > > Entity.defaults['properties'] =3D [ > APrimaryKey('id', isClassProperty=3D0, isRequired=3D1, doc=3D'Primary = =20 > key!') > ] > > ## > > _connDict =3D {} > model =3D =20 > Model('StoreEmployees',adaptorName=3D'Postgresql',connDict=3D_connDict) > model.doc =3D ' ... ' > model.version=3D'0.1' > model.entities =3D [ > > # > Entity('Store', > properties=3D[ AString('corporateName', isRequired=3D1), > RToMany('employees', 'Employee', =20 > inverse=3D'toStore') > ], > doc =3D 'The Store object ...' > ), > > # Employee and its subclasses SalesClerk and Executive > Entity('Employee', > properties=3D[ AString('lastName', isRequired=3D1, =20 > usedForLocking=3D1), > AString('firstName', isRequired=3D1, width=3D50, > usedForLocking=3D1), > RToMany('toAddresses', 'Address', =20 > delete=3D2),#'cascade'), > RToOne('toStore', 'Store') > ] > ), > > Entity('SalesClerk', parent=3D'Employee', > properties=3D[ AString('storeArea') > ] > ), > > Entity('Executive', parent=3D'Employee', > properties=3D[ AString('officeLocation', width=3D5), > RToMany('marks', 'Mark', delete=3D2, #'cascade' > inverse=3D'executive') > ] > ), > > # > Entity('Address', > properties=3D[ AString('street', width=3D80), > AString('zipCode'), > AString('town', width=3D80), > RToOne('toEmployee', 'Employee', = delete=3D1,#'deny' > inverse=3D'toAddresses') > ] > ), > > # > Entity('Mark', > properties=3D[ AInteger('month', isRequired=3D1), > AInteger('mark', isRequired=3D1), > AForeignKey('toExecutive', isClassProperty=3D0), *** given your changes, is this needed (AForeignKey toExecutive) ? > RToOne('executive', 'Executive', > src=3D'toExecutive', dst=3D'id', > inverse=3D'marks'), > ] > ) > > ] > > if __name__ =3D=3D '__main__': > model.build() > #print model.validate() > #print model.toXML() > # plus whatever ... > > ## > = -----------------------------------------------------------------------=20= > - |
From: Sebastien B. <sbi...@us...> - 2003-05-16 11:44:53
|
Hi all, I wrote: > [...] > I've just finished a first proposal for this and committed it under the > branch tagged brch-0_9pre6-1. It solves the problem as long as a class > does not share the same module than one of its (direct or indirect) > subclasses. >=20 > This constraint is not implemented yet. >=20 > To retrieve the branch: in directory ModelMasons, directly type: >=20 > $ cvs update -r brch-0_9pre6-1-ModelMasons_base_generation_scheme >=20 >=20 > I successfully applied this on models AuthorBooks and StoreEmployees, > it would be cool if sb. could check that on his own projects. I also > did not pay a very close attention to the generated code (I just made > sure it works out-of-the-box wrt the tests), hence there can be > repetitions, useless portion of codes, etc. in the generated modules. The constraint for 'base' generation scheme is now implemented in the branch. If nobody has more comments/requests/critics on this, this will be integrated into the main trunk today or tomorrow and the brch will be closed. > BTW: Mario proposed that the generated class initializer could be: > > def __init__(self,att1=3DNone,att2=3DNone): > instead of > > def __init__(self): >=20 > Are we ok we go for it? I'm too lazy to change this now; Mario also posted an alternate: > But, how about this little compromise, as a utility function that > can be used only when needed: >=20 > def updateCustomObject(co,**kwargs): > for k in kwargs.keys(): > co.setValueForKey(kwargs[k],k) > return co -> still needs to be done. Maybe this can be a FAQ entry in the meantime. -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-05-15 18:49:52
|
Hi there, More comments about PyModels --we need it in release 0.9 for the 1 page tutorial to be really efficient. I started to implement things, I needed to play with some pymodels to make up my mind on some specific stuff (esp. on declaring relationships). Obviously the starting point was made of version 4 of PyModel and sample_PyModel, I must admit that having these two modules made it possible to code a first sketch for PyModel quite quickly --thanks all for your comments. NB:For the curious that want to play with it to, I've committed a first implementation in CVS branch brch-0_9pre7-1-PyModel (directory Modeling/, where PyModel.py and tests/test_PyModel.py are added, plus the following modules that were slightly changed: Model, Entity, Attribute and Relationships. Obviously you do NOT need to check this out to participate to the discussion! I expose here the points that were raised when trying it: - model & entity declarations: nothing has changed, except that I added the possibility to declare 'associations' in an entity (see below) - defaults:=20 i. the way calculated defaults are declared needed to be changed, example: model.defaults=3D{ 'packageName': MP(identity, 'name'), } where MP is a special class for this (MP: Method/Parameters) identity is the method to be called (here identity=3Dlambda x:x) 'name' is the name of the object's (model's) attribute to pass as an attribute (it should be an object's attribute) When multiple parameters are needed: MP(function,'param1','param2') ii. sample_PyModel_4 said: Entity('Employee', properties=3D[ # [...] AForeignKey(Attribute.fk('Store'),=20 isClassProperty=3D0), ] ) --> Attribute.fk('<destEntity>') was not a good idea, it's even not feasible. So: either you declare (and name) the foreign key, or you rely on the initialization of a relationship to create it. =20=20=20=20=20=20=20=20=20=20 - attributes: nothing changed - relationships: there are two different ways to declare them: a. fully qualified rels i.e. when source and destination key are specified such as in: Entity('Employee',=20 AForeignKey('fkStore'), properties=3D[RToOne('toStore','Store',src=3D'fkStore',dst=3D'= id')] ) =20=20=20=20=20=20=20=20 b. unqualified rels, such as in: Entity('Employee', properties=3D[ RToOne('toStore', 'Store') ] ) When using such a scheme, you need to identify the inverse relationship, if any, by the keyword 'inverse'; it can be specified in either relationships, or in both. Example: Entity('Employee', properties=3D[ RToOne('toStore', 'Store',=20 inverse=3D'toEmployees') ] ) Both a. and b. are implemented.=20 In case b. the foreign key is created in the source (resp. destination) entity for a RToOne (resp. RToMany) relationship Note: the default for trelationships, such as in: RToOne.defaults['sourceAttribute'] =3D RToOne.attNameFromRel #'fk'+destEnt+= destAtt+count is not implemented but it will. For the moment being it's hard-coded. - new object: Association Association objects make it easier to quickly design a relationship and its inverse. Proposed usage: model.entities =3D [ Entity('Employee'), Entity('SalesClerk', parent=3D'Employee'), Entity('Mark'), Entity('Store'), ] model.associations =3D [ Association('Employee', 'Store'), Association('Mark', 'Employee'), ] (this is the StoreEmployee test model without the attributes) Another full usage could be: # [...] model.associations =3D [ Association('Employee: toStore', 'Store: toEmployees', [0,1], # Employee -----> Store [0,None], # Store ---->> Employee ) ] (Implementation note: for the moment Association('E1', 'E2') builds a toOne E1--->E2 and a toMany E2--->E1) =3D> this is where I'm not clear at all. It seems to me that we should be able to specify: - the source and destination entity (mandatory) - the multiplicity for both relationships (optional) - the names of the toOne rel. and of the toMany rel. (optional) - maybe extra parameters for each rels, something like: model.associations =3D [ Association('Employee: toStore', 'Store: toEmployees', [0,1], # Employee -----> Store [0,None], # Store ---->> Employee { 'doc': 'toOne: Employee to Store' }, # Emp.toStore { 'doc': 'toMany: Store to Employee' }, # Store.toEmp. ) ] I'm not sure this looks pretty, so if you have ideas they are welcome ;) Now for the details: * multiplicity: unconstrained upper bound can be -1, '*' or None * I choose 'required' instead of 'allowsNone' for attributes/rels. Enclosed is a (working) version of sample_PyModel_5.py As usual, your comments and critics are appreciated. A PyModel *will* be integrated in 0.9, I'd like it to meet *your* needs ;) Cheers, -- S=E9bastien. ------------------------------------------------------------------------ ''' sample_PyModel_5.py A sample Pythonic OO-RDB Model=20 (re-expressing testPackages/StoreEmployees/model_StoreEmployees.xml) -- A PyModel must define a global variable called 'model', that is of type Mod= el ''' from PyModel import * ## # Set preferred defaults for this model (when different from=20 # standard defaults, or if we want to make things explicit) AFloat.defaults['precision'] =3D 10 AFloat.defaults['scale'] =3D 10 AString.defaults['width'] =3D 20 RToOne.defaults['delete'] =3D 2 #'cascade' RToOne.defaults['multiplicity'] =3D [0,1]=20 #RToOne.defaults['sourceAttribute'] =3D RToOne.attNameFromRel # 'fk'+destEn= t+destAtt+count #RToOne.defaults['destinationAttribute'] =3D 'id' RToMany.defaults['delete'] =3D 1 # 'deny' # this is temporary, final version # will say 'deny'/'cascade'/'nullif= y' # as expected RToMany.defaults['multiplicity'] =3D [0,None] #RToMany.defaults['sourceAttribute'] =3D 'id' #RToMany.defaults['destinationAttribute'] =3D RToMany.attNameFromRel # fk+d= estEnt+sourceAtt+count # Note that Relation.attNameFromRel is a callable, that calculates the att # name from the indicated pieces (where count to distinguish between multip= le # relations between same source and target Entity.defaults['properties'] =3D [ APrimaryKey('id', isClassProperty=3D0, isRequired=3D1, doc=3D'Primary key= !') ] ## _connDict =3D {} model =3D Model('StoreEmployees',adaptorName=3D'Postgresql',connDict=3D_con= nDict) model.doc =3D ' ... ' model.version=3D'0.1' model.entities =3D [ # Entity('Store', properties=3D[ AString('corporateName', isRequired=3D1), RToMany('employees', 'Employee', inverse=3D'toStore')= =20 ], doc =3D 'The Store object ...' ), # Employee and its subclasses SalesClerk and Executive Entity('Employee', properties=3D[ AString('lastName', isRequired=3D1, usedForLocking= =3D1),=20 AString('firstName', isRequired=3D1, width=3D50, usedForLocking=3D1), RToMany('toAddresses', 'Address', delete=3D2),#'casca= de'),=20 RToOne('toStore', 'Store')=20 ] ), Entity('SalesClerk', parent=3D'Employee', properties=3D[ AString('storeArea')=20 ] ), Entity('Executive', parent=3D'Employee', properties=3D[ AString('officeLocation', width=3D5), RToMany('marks', 'Mark', delete=3D2, #'cascade' inverse=3D'executive') ] ), =20=20 # Entity('Address', properties=3D[ AString('street', width=3D80),=20 AString('zipCode'),=20 AString('town', width=3D80), RToOne('toEmployee', 'Employee', delete=3D1,#'deny' inverse=3D'toAddresses')=20 ] ), =20=20 # Entity('Mark', properties=3D[ AInteger('month', isRequired=3D1),=20 AInteger('mark', isRequired=3D1), AForeignKey('toExecutive', isClassProperty=3D0), RToOne('executive', 'Executive', src=3D'toExecutive', dst=3D'id', inverse=3D'marks'), ] ) =20=20 ] if __name__ =3D=3D '__main__': model.build() #print model.validate() #print model.toXML() # plus whatever ... =20=20 ## ------------------------------------------------------------------------ |
From: Sebastien B. <sbi...@us...> - 2003-05-08 22:14:52
|
Yannick Gingras <yan...@sa...> writes: > Sounds like mdl_compile_model.py has not made it's way in the tarball... >=20 > $ python setup.py install > [...] > copying and adjusting Modeling/scripts/mdl_generate_python_code.py ->=20 > build/scripts-2.2 > copying and adjusting Modeling/scripts/mdl_validate_model.py ->=20 > build/scripts-2.2 > error: file 'Modeling/scripts/mdl_compile_model.py' does not exist >=20 >=20 > : \ >=20 Sorry, my fault -- forgot to update the MANIFEST. Thanks for reporting. 0.9pre7.1 corrects this. If you do not want to download the whole tarball again, simply download the script from: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/modeling/ProjectM= odeling/Modeling/scripts/mdl_validate_model.py?rev=3DHEAD&only_with_tag=3Dr= elease-0_9pre7&content-type=3Dtext/x-python and copy it in directory Modeling/scripts/ -- S=E9bastien. |
From: Yannick G. <yan...@sa...> - 2003-05-08 18:50:20
|
=2D----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Sounds like mdl_compile_model.py has not made it's way in the tarball... $ python setup.py install [...] copying and adjusting Modeling/scripts/mdl_generate_python_code.py ->=20 build/scripts-2.2 copying and adjusting Modeling/scripts/mdl_validate_model.py ->=20 build/scripts-2.2 error: file 'Modeling/scripts/mdl_compile_model.py' does not exist : \ =2D --=20 Yannick Gingras Byte Gardener, Savoir-faire Linux inc. (514) 276-5468 =2D----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQE+uqbqrhy5Fqn/MRARAhbwAKCSz9WhGhozPFBvyBZ+/h42dycvGACdEVmM 5KcbdTRHq0VWe5rPGGp5by8=3D =3DMLDI =2D----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-05-07 11:39:32
|
Hi, Mario Ruggier <ma...@ru...> writes: [...] > > I suggest a env. variable poiting to a specific init-file read by > > ConfigParser and changing the models' connection dictionary when they > > are loaded --see tests.utils.parseConfigFile_and_updateModel() and > > tests/test.cfg for an example of this technique. > > > > Does it sound reasonable? This can be easily done, and it will meet > > the exact requirements you're pointing out. I guess we can make it > > happen for 0.9. >=20 > Would be wonderful way to go. This case will also make encrypting > of password less necessary. Okay, this is now available from the main trunk in CVS, will be in next release. Usage: set the environment variable MDL_DB_CONNECTIONS_CFG to the path of a configuration file, say /full/path/to/mydbconf.cfg This is an ini-like file, parsed by ConfigParser, like: --------------- [DEFAULT] host: localhost =20=20=20=20 [ModelName_1] user: user_1 password: pwd_1 =20=20=20=20 [ModelName_2] adaptor: MySQL user: user_2 password: pwd_2 --------------- Now you can remove the user & password from your model (ie the .xml/.py/ pickled one), and instead put them in a single file. The special field 'adaptor' can be used to override the model's adaptorName. Last, it is an error to set this env.var. when the file does not exist. Enjoy! Cheers, -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-05-06 17:03:00
|
Hi all, Time for a new release, until requirements for 0.9 are met --it's been too much time since the last one to wait for 0.9. =20=20 This release is made of fixes for various bugs discovered on the long road to v0.9, mainly: - possible failure when fetching in a multi-threaded environment (e.g. Zope), - objects declaring PKs as class properties did not get the PK's value right after insertion into the DB, - corrections for the python-code generation script A new script: mdl_compile_model.py generates a pickled version of a model to be loaded *much* faster than the xml-file at runtime; the python-code generation has been refactored and is now more flexible, plus it builds an __init__.py using the pickled model if available. Last, the models & ZModeler were changed to accept comments for the model's components. All these changes were announced/discussed in previous threads. As usual all changes since last public release (0.9pre4) are enclosed at the end of the mail. Cheers, -- S=E9bastien. ------------------------------------------------------------------------ 0.9-pre-7 (2003/05/06) --------- * Fixed DatabaseChannel.fetchObject(): it was not MT-safe wrt Database snapshots' caching in some circumstances (see comments in the code for further details) * Added scripts/mdl_compile_model.py and update the __init__.py generated= by mdl_generate_DB_schema.py so that it automatically tries to load the pickled model. Using the pickled model is *much* faster than loading the model from its xml description. * Fixed AbstractDBAPI2Adaptor.create/dropDatabaseWithAdmin.Conn.Dict.(): under some circumstances it was possible that createDB() fails when cal= led just after the drop, fails (see comments in the code for details) * Fixed mdl_generate_DB_schema: some options ('-t -p -s -f -F) were silen= tly ignored * Added a field 'comment' for Model, Entity, Attribute & Relationship, af= ter a suggestion by Yannick Gingras 0.9-pre-6 (2003/04/22) Project milestone -- no public release --------- * ModelMasons: added a new generation scheme. The existing one is named 'compact', the new one, 'base'. The latter generates two different modu= les for a given entity, in modules <className> (which is not overwritten wh= en re-generating) and <className>Base (which IS overwritten upon regeneration) * Refactored ModelMasons: ModelMason and PyModelMason are now clearer than they used to be. See PyModelMason for an example of use.=20 Fixed: bug #710817 Fixed Python_bricks/module.tmpl: do not generate e.g. setId() if 'id' i= s a primary key marked as a class property =20 * Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext Default behaviour is now set with EditingContext.invalidatesObjectsWhenFinalized_default * Fixed: an newly inserted object with a PK, say, 'id', marked as class property did not get its value after EditingContext.saveChanges(). [Details in: EditingContext.handleNotification()] Thanks to soif <Jer...@fi...> for identifying and reporting the pb. * Fixed SQLExpression.sqlStringForAttributeNamed(): now raises ValueError with an explicit message when it receives an invalid attribute's name 0.9-pre-5 (2003/03/17) Project milestone -- no public release --------- * Attribute: fixed defaultValueAsPythonStatement() and convertStringToAttributeType(): they were failing to operate properly under python2.2 (StringType.__name__ is 'string' for py2.1, 'str' for py2.2) * Fixed Entity.objectsPathForKeyPath(): under some circumstances it did n= ot raise ValueError as expected for an invalid keypath * scripts/mdl_validate_model.py fixed: ValueError could be raised when no messages were issued at the INFO level * Fixed ModelValidation.validateEntity_internals(): now iterates on all primary keys, and correctly report an error when a PK is set to be a cl= ass property but does not have a default value set to integer zero (this is now enforced since when the default value is None, we get an erroneous error message at EC.saveChanges(): the validation mechanism fails on validating the PK --thanks to Yannick Gingras for reporting the problem) * Fixed Attribute.initWithXMLDOMNode(): it was possible that the defaultValue was set prior to the attribute's type, hence it didn't get the right value (e.g. a default value being string '0' instead of integ= er 0 for a type=3D=3D'int') ------------------------------------------------------------------------ |
From: Sebastien B. <sbi...@us...> - 2003-04-27 14:39:34
|
Hi, so...@la... wrote: > On Thu, Mar 20, 2003 at 02:53:28PM +0100, so...@la... wrote: >=20 > Ansering myself, >=20 > I found the way to avoid this issue by using=20 > ec.lock() and ec.unlock() at each web app request. > (not really usefull for a threaded web app !!)=20 >=20 >=20 > But i really think the doc, isn't clear about this=20 > point. In fact i think that all operation on a=20 > ec should be locked, even fetching ( !=3D the doc ). > Cause if you don't, you will get some strange=20 > behaviours meanly in the database adapator, that > cause a segfault in the mysql one. Did you only get segfaults? Or maybe python tracebacks as well? I can't find your original post on this problem. Do you have a test for this, or any useful info. making it possible to reproduce the bug? I can't reproduce it here. -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-04-25 18:44:14
|
Hi, I've just checked-in (CVS HEAD) the script mdl_compile_model.py. It generates two modules: model_<modelName> and model_<modelName>_pickled. The former is the one already generated by mdl_generate_python_code.py, the latter one contains a pickled version of the model. Why a pickle model? Loading the pickle is really *much* faster than loading the xml file. I also updated the code generation so that the generated __init__.py tries to find and load the pickled model. -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-04-25 11:25:45
|
Mario Ruggier <ma...@ru...> writes: > >> A propos de previous post on KeyValueCoding names -- this proposition > >> lacks a minor thing, and that is inside the __init__ body, the > >> attribute values should be set using KeyValueCoding, not to bypass any > >> custom code in the get/set methods for each attribute. > > > > That's questionable. KVC mechanisms are handy, but > > time-consuming. Moreover, I'd like to keep as little modeling-specific > > things in the generated code as possible --for the moment being there > > are Modeling.CustomObject in the inheritance tree, and > > willRead()/willChange() methods [1]. > > > > I'd recommend self.setAtt1(att1) in __init__() rather than > > self.takeValueForKey(att1, 'att1') in this case. >=20 > Yes, you are right ;) >=20 > Since last night, i've rethought my little proposal, and I would > now be against it because of (a) if it is done this way, custom property > logic should not be bypassed in my opinion, and (b) if a KVC loop > is to be performed each time any CustomObj is initialised, the > performance price is too high. >=20 > But, how about this little compromise, as a utility function that > can be used only when needed: >=20 > def updateCustomObject(co,**kwargs): > for k in kwargs.keys(): > co.setValueForKey(kwargs[k],k) > return co >=20 > It receives an instance =3D=3D>> can be used on new objects > (instantiated on the call) as well as existing instances. No problem w/ this. We just have to decide where it should be put! (module CustomObject?) [snip] > I had not realised that __slots__ implied also these other things. > So this can be put on hold, for possible future consideration. BTW if someone on this list uses new-style classes and slots regularly plea= se email me privately, I have some questions about it --I'll summarize the situation here afterwards. > > [1] I'm currently working on a integrating the framework w/ the ZODB > > framework. In this configuration willRead/willChange methods > > disappears, and CustomObject inherits from ZODB's Persistent class. > > I'll make a branch and an alpha release as soon as possible. >=20 > Any implications for those not using ZODB? Not in a near future, no need to worry. The goals underneath are: - use ZODB.Persistent, because of the (C) extension class is *much* faster = wrt detecting that an object has changed (additionally, it make it possible to transparently detect this, no willChange() needed anymore), - bind the framework (esp. the EC fonctionalities) to the ZODB's transaction machinery. After release, the two versions will be maintained in parallel, and as far as I'm concerned the current version won't be deprecated unless we reach = the point where noone uses it! I'll make all this clearer in the long-term planning that Soif requested = and that I'll try to submit here soon. Cheers, -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-04-25 10:49:12
|
On vendredi, avr 25, 2003, at 12:17 Europe/Amsterdam, Sebastien Bigaret=20= wrote: > Mario Ruggier <ma...@ru...> writes: >> On mardi, avr 22, 2003, at 15:15 Europe/Amsterdam, Mario Ruggier=20 >> wrote: >>> On mardi, avr 22, 2003, at 14:07 Europe/Amsterdam, Sebastien Bigaret=20= >>> wrote: >>>>>>> def __init__(self,att1=3DNone,att2=3DNone): >>>>>> instead of >>>>>>> def __init__(self): >>>>>> >>>>>> Are we ok we go for it? >> >> A propos de previous post on KeyValueCoding names -- this proposition >> lacks a minor thing, and that is inside the __init__ body, the >> attribute values should be set using KeyValueCoding, not to bypass = any >> custom code in the get/set methods for each attribute. > > That's questionable. KVC mechanisms are handy, but > time-consuming. Moreover, I'd like to keep as little modeling-specific > things in the generated code as possible --for the moment being there > are Modeling.CustomObject in the inheritance tree, and > willRead()/willChange() methods [1]. > > I'd recommend self.setAtt1(att1) in __init__() rather than > self.takeValueForKey(att1, 'att1') in this case. Yes, you are right ;) Since last night, i've rethought my little proposal, and I would now be against it because of (a) if it is done this way, custom property logic should not be bypassed in my opinion, and (b) if a KVC loop is to be performed each time any CustomObj is initialised, the performance price is too high. But, how about this little compromise, as a utility function that can be used only when needed: def updateCustomObject(co,**kwargs): for k in kwargs.keys(): co.setValueForKey(kwargs[k],k) return co It receives an instance =3D=3D>> can be used on new objects (instantiated on the call) as well as existing instances. >> Additional proposal ;) >> How about adding __slots__ to all custom objects? >> It seems to me that this is exactly the kind of usage that this was >> intended for, and will reduce memory usage for cases of *many* >> instances of custom objects. Works only for 2.2, but if present = should >> not affect 2.1 instances in any way. > > Could you be more specific? I can't see how slots reduce the memory > footprint. > > More on slots: the framework cannot handle them out-of-the-box right > now, I can see the following problems: > > a. when an EC records an object (either insert or fetch), it = weakrefs > itself and assigns the weakref to the object (see > EC.recordObject()) --> this implies that CustomObject must be > turned into a new-style class in py2.2, defining __slots__ as=20 > well. > > b. Such an object cannot be weakly references, unless CustomObject > adds '__weakref__' in its slots. > > c. An object using slots has no __dict__ > > [See also: http://www.python.org/2.2.2/descrintro.html for a complete > discussion on csqs. of using slots] > > a. and b. can be easily solved. However c. is more problematic; this = is > an issue that should carefully examined (the impact is on KVC, = mainly], > I'm not clear at all on this by now (I've never used new style classes > until now). You are right, again ;) I had not realised that __slots__ implied also these other things. So this can be put on hold, for possible future consideration. > -- S=E9bastien. > > > [1] I'm currently working on a integrating the framework w/ the ZODB > framework. In this configuration willRead/willChange methods > disappears, and CustomObject inherits from ZODB's Persistent = class. > I'll make a branch and an alpha release as soon as possible. Any implications for those not using ZODB? mario |
From: Sebastien B. <sbi...@us...> - 2003-04-25 10:17:31
|
Mario Ruggier <ma...@ru...> writes: > On mardi, avr 22, 2003, at 15:15 Europe/Amsterdam, Mario Ruggier wrote: > > On mardi, avr 22, 2003, at 14:07 Europe/Amsterdam, Sebastien Bigaret wr= ote: > >> Mario Ruggier <ma...@ru...> writes: >=20 > [snip] >=20 > >>>> BTW: Mario proposed that the generated class initializer could be: > >>>>> def __init__(self,att1=3DNone,att2=3DNone): > >>>> instead of > >>>>> def __init__(self): > >>>> > >>>> Are we ok we go for it? >=20 > A propos de previous post on KeyValueCoding names -- this proposition > lacks a minor thing, and that is inside the __init__ body, the > attribute values should be set using KeyValueCoding, not to bypass any > custom code in the get/set methods for each attribute. That's questionable. KVC mechanisms are handy, but time-consuming. Moreover, I'd like to keep as little modeling-specific things in the generated code as possible --for the moment being there are Modeling.CustomObject in the inheritance tree, and willRead()/willChange() methods [1]. I'd recommend self.setAtt1(att1) in __init__() rather than self.takeValueForKey(att1, 'att1') in this case. > Additional proposal ;) > How about adding __slots__ to all custom objects? > It seems to me that this is exactly the kind of usage that this was > intended for, and will reduce memory usage for cases of *many* > instances of custom objects. Works only for 2.2, but if present should > not affect 2.1 instances in any way. Could you be more specific? I can't see how slots reduce the memory footprint. More on slots: the framework cannot handle them out-of-the-box right now, I can see the following problems: a. when an EC records an object (either insert or fetch), it weakrefs itself and assigns the weakref to the object (see EC.recordObject()) --> this implies that CustomObject must be turned into a new-style class in py2.2, defining __slots__ as well. =20=20 b. Such an object cannot be weakly references, unless CustomObject adds '__weakref__' in its slots. =20=20 c. An object using slots has no __dict__ [See also: http://www.python.org/2.2.2/descrintro.html for a complete discussion on csqs. of using slots] a. and b. can be easily solved. However c. is more problematic; this is an issue that should carefully examined (the impact is on KVC, mainly], I'm not clear at all on this by now (I've never used new style classes until now). -- S=E9bastien. [1] I'm currently working on a integrating the framework w/ the ZODB framework. In this configuration willRead/willChange methods disappears, and CustomObject inherits from ZODB's Persistent class. I'll make a branch and an alpha release as soon as possible. |