Thread: [Modeling-users] Pythonic, and non-XML, Model description
Status: Abandoned
Brought to you by:
sbigaret
From: Mario R. <ma...@ru...> - 2003-02-24 23:29:07
|
Hello, following comments about the XML model (on and off the list) and how it can be improved or redone altogether, i started thinking about it... And (to be able to get it out of my mind and get to some other work ;-) here is a proposal for a pure python description of the model. It follows the XML closely, and in fact may always retain compatibility (at least generation of XML from the python model, which will be trivial). The behaviour in gnereal would stay the same as the XML way of doing things, namely form this model you would generate the classes and the db schemas. Some differences are choice of default values, and that key and locking attributes are defined on attributes and relations rather than entities ;) As an exercise, I have taken the sample model in the distribution: testPackages/StoreEmployees/model_StoreEmployees.xml and re-expressed it in this pythonic way. Apart from readability and losing of some verbosity, other gains are "executability" and dynamicity -- it could be very easy to modify a model at runtime, if you would ever want to do that. Also, given that a model now becomes a module in and of itself, it gains from what modules have to offer, such as self-tests. And, speed of course, as i see no reason why this model object would also not serve as the model object in memory at runtime (but that's for Sebastien to confirm) -- thus loading the model is equivalent to "from MyModel import model". Can you please take a look at the 2 linked files below (as temporary URLs, as to attach they are too big); - PyModel.py -- defines the classes (signatures for) for, and documents the rules for, a PyModel instance - sample_PyModel.py -- re-expresses the StoreEmployees model What does everyone think? mario http://ruggier.dyndns.org:8080/PyModel/PyModel.py http://ruggier.dyndns.org:8080/PyModel/sample_PyModel.py |
From: Mario R. <ma...@ru...> - 2003-02-24 22:57:24
|
Hello, following comments about the XML model (on and off the list) and how it can be improved or redone altogether, i started thinking about it... And (to be able to get it out of my mind and get to some other work ;-) here is a proposal for a pure python description of the model. It follows the XML closely, and in fact may always retain compatibility (at least generation of XML from the python model, which will be trivial). The behaviour in gnereal would stay the same as the XML way of doing things, namely form this model you would generate the classes and the db schemas. Some differences are choice of default values, and that key and locking attributes are defined on attributes and relations rather than entities ;) As an exercise, I have taken the sample model in the distribution: testPackages/StoreEmployees/model_StoreEmployees.xml and re-expressed it in this pythonic way. Apart from readability and losing of some verbosity, other gains are "executability" and dynamicity -- it could be very easy to modify a model at runtime, if you would ever want to do that. Also, given that a model now becomes a module in and of itself, it gains from what modules have to offer, such as self-tests. And, speed of course, as i see no reason why this model object would also not serve as the model object in memory at runtime (but that's for Sebastien to confirm) -- thus loading the model is equivalent to "from MyModel import model". Can you please take a look at the attached 2 files; PyModel.py -- defines the classes (signatures for) for, and documents the rules for, a PyModel instance sample_PyModel.py -- re-expresses the StoreEmployees model What does everyone think? mario |
From: Sebastien B. <sbi...@us...> - 2003-02-25 08:06:25
|
Hi, Please excuse the re-sent message with attached files -- I did not see that Mario found an other way to share its files and I approved its former post real too quickly. *My fault*, not his, I guess I should not do any administrative tasks before being completely waken up :/ However I need to review sourceforge's policy to check whether posts that are bigger than 40Kb are strongly advised against, and advertised as such ; if receiving such a big post really annoys/annoyed you, please email & flame me directly. My apologies to all, again. -- S=E9bastien. |
From: Yannick G. <ygi...@yg...> - 2003-02-25 12:15:25
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 24 February 2003 17:57, Mario Ruggier wrote: > Can you please take a look at the attached 2 files; > PyModel.py -- defines the classes (signatures for) for, and documents > the rules for, a PyModel instance > sample_PyModel.py -- re-expresses the StoreEmployees model One thing that is a big win for Modeling is the ability to import a XML model. We make our models with Data Designer (http://www.danny.cz/datadesigner.en.html) and convert the XML to a format that Modeling can easily crunch. The performance boost of the python model is a big win but the ability to import, convert, compile, ... a XML model should be kept. I mean, we'd like to see it in future releases. : ) Regards, - -- Yannick Gingras Coder for OBB : Offstage Broad-headed Bitterweed http://OpenBeatBox.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+W15Yrhy5Fqn/MRARAruzAJsH9Glm0bOfo1tsXhQ3attFh4S/cwCdE5V9 lyHNxLYYsp4vMSqD1xbVnDE= =OHo7 -----END PGP SIGNATURE----- |
From: Mario R. <ma...@ru...> - 2003-02-26 00:33:16
|
Hello Yannick, thanks for the remark. I think there is nothing to worry about here -- the XML model is not likely to ever disappear... and even if some other model might eventually be preferred for the runtime, whatever that model will be it will be easy to have a to-and-fro transform between it and the XML. Cheers, mario > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Monday 24 February 2003 17:57, Mario Ruggier wrote: >> Can you please take a look at the attached 2 files; >> PyModel.py -- defines the classes (signatures for) for, and documents >> the rules for, a PyModel instance >> sample_PyModel.py -- re-expresses the StoreEmployees model > > One thing that is a big win for Modeling is the ability to import a > XML model. > We make our models with Data Designer > (http://www.danny.cz/datadesigner.en.html) and convert the XML to a > format > that Modeling can easily crunch. The performance boost of the python > model > is a big win but the ability to import, convert, compile, ... a XML > model > should be kept. > > I mean, we'd like to see it in future releases. > > : ) > > Regards, > > - -- > Yannick Gingras > Coder for OBB : Offstage Broad-headed Bitterweed > http://OpenBeatBox.org > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.0.7 (GNU/Linux) > > iD8DBQE+W15Yrhy5Fqn/MRARAruzAJsH9Glm0bOfo1tsXhQ3attFh4S/cwCdE5V9 > lyHNxLYYsp4vMSqD1xbVnDE= > =OHo7 > -----END PGP SIGNATURE----- > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > Modeling-users mailing list > Mod...@li... > https://lists.sourceforge.net/lists/listinfo/modeling-users |
From: Sebastien B. <sbi...@us...> - 2003-02-26 19:28:29
|
Hi, A quick notes about that: > > Can you please take a look at the attached 2 files; > > PyModel.py -- defines the classes (signatures for) for, and documen= ts > > the rules for, a PyModel instance > > sample_PyModel.py -- re-expresses the StoreEmployees model >=20 > One thing that is a big win for Modeling is the ability to import a X= ML > model. We make our models with Data Designer > (http://www.danny.cz/datadesigner.en.html) and convert the XML to a f= ormat > that Modeling can easily crunch. The performance boost of the python > model is a big win but the ability to import, convert, compile, ... a= XML > model should be kept. >=20 > I mean, we'd like to see it in future releases.=20 As Mario already said, there's nothing to worry about. Moreover, this i= s a very valuable information that you gave us ; I did not succeed in linki= ng the db schema designer yet /: (I get a bunch of warnings about wx stuff being undefined references) but the screenshots make me think it might = me a modeler really worth a try. It might be the modeler I'm looking for. Would you mind sharing your conversion scripts from db-designer to xml-modeling? I'm thinking of adding a few notes on this tool in the framework's documentation, and having the conversion script would be really handy. I also agree with Mario saying that two (or more!) different models can co-exist with no problem. That said it is possible that a python model,= if defined, will be preferred for run-time initialization (loading the mod= el) since it is likely to load far quicker than parsing the xml... Whatever the changes, you can count on a bridge between the model formats. Last: Mario, I have not found the time yet to study your proposal but= I will for sure. Cheers, -- S=E9bastien. |
From: Yannick G. <yan...@sa...> - 2003-02-27 14:25:47
Attachments:
dd2pm.py
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 26 February 2003 03:28 pm, Sebastien Bigaret wrote: > Would you mind sharing your conversion scripts from db-designer to > xml-modeling? I'm thinking of adding a few notes on this tool in the > framework's documentation, and having the conversion script would be > really handy. The script is really sketchy at the moment with a lot of default values hard-coded but it would not be hard to modularize it enough to make it useful for the general public. I let you look at it, tell me how we could make it more general and I'll see what we can do. Fell free to ask questions about the implementation. - -- Yannick Gingras Byte Gardener, Savoir-faire Linux inc. (514) 276-5468 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+Xh/orhy5Fqn/MRARAtilAJ4hyfFM/WBv813kkLd7LyvC+FqShwCdFeIl mwraNTZ++vl/QD65S9c0hhY= =Y/SP -----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-02-27 23:49:56
|
Hi Yannick, Thanks for the script. I've not played a lot with db designer, but re= ad your code with a db-designer model at hand and converted a simple model. That inspired me the following comments: - about the tool itself: it is really focused on db-schemas ; it has so= me features I cannot understand, such as the 'type' of a relation (identifying, identifying or informational), or the referential integ= rity properties for the child/destinationEntity (insert/update props). May= be you can comment on these? The most annoying problem I see is the complete lack of inheritance -- there seem to be no way to model it. Okay this is quite normal for a = tool dedicated to db-schema, but we'll need it somehow. - about the script: yes, there are some default values, but they are ea= sily identified hence this is not really a problem changing these (I notic= ed you really want to have your primary key as class properties :) I was really surprised by the way relations are mapped to relationships. If I'm not wrong, you're mapping them to 'to-one' relationship, unconditionally. However, when I tried the tool, I came= to the opposite opinion, because of the 2nd screenshot: http://www.danny.cz/screenshots/datadesigner1.jpg Given that "firmy" has an attribute "forma_id" which is also the PK of entity "forma" and that the former entity has a relation to the latte= r, my first conclusion was that the relations were intended to model to-many relationships... But czech is greek to me ;) so this is nothing more = than an intuition. Can you explain your practices wrt the relations? Do you design to relations, one being the inverse of the other, when you design a model with the db-designer, and edit the xml file afterwards to change one = of these from to-one to to-many? - Unused stuff in relations' props that might be used when mapping a mo= del: - Parent (source entity) & Child (destination entity) props: mandatory/non-mandatory: this can be used to set the lower multiplicity bound to 1 or 0, respectively. - In 'Referential Integrity': it seems that parent's delete policies 'none', 'restrict', 'cascade' & 'set NULL' maps to DELETE_NOACTIO= N, DELETE_DENY, DELETE_CASCADE and DELETE_NULLIFY, respectively. I do not fully understand what are for: parent's update policy, as well as child's insert & update policy. If someone could bring in= a light... - misc.: - on db-designer 0.4, there's a 'default' for attribute that can be u= sed for defaultValue --to be added to mutateEntAttrType(). 'int' and 'integer' expected by the scripts seem to have disappeared and repl= aced by int2, int4 and int8 (same for float -> float4 & float8) -- to be updated in DD_PM_TYPE_MAP - 'class ModelingDDImporter:' simply not making it derive from 'objec= t' makes the script available for py2.1 as well. - defaults in mutateEntity() & mutateEntAttr() are directly defined as dictionaries, while 'mutateRelation()' uses makeDefaults() Any comments from your experience will be helpful to fully appreciate t= he db-designer. Some features could be added easily (such as a checkbox for isClassProperty in attributes and relations), other would be more diffi= cult (such as a support for inheritance). Are you by any chance in contact w= ith the maintainers? Another tool that may be useful is PyDBDesigner at http://pydbdesigner.sourceforge.net/ (thank you Soaf for the link) It's python-based, only at an alpha stage for the moment but definite= ly worth a try. I currently do not have any time to study both of these = tools in details but if anyone feels like doing it I'll be interested in th= eir comments. Having a stand-alone modeler (i.e. out of zope) is a real concern as far as I'm concerned and since time is a concern as well |= : I would for sure prefer using or may be forking an existing project, if possible, rather than coding it from scratch. Last, just curiosity: was the zmodeler not an option for you because of= zope itself or do you find/use more of the db-designer xml file that the zmo= deler (and/or the modeling framework's model xml file) does not offer? Cheers, -- S=E9bastien. Yannick Gingras <yan...@sa...> wrote: > On Wednesday 26 February 2003 03:28 pm, Sebastien Bigaret wrote: > > Would you mind sharing your conversion scripts from db-designer to > > xml-modeling? I'm thinking of adding a few notes on this tool in the > > framework's documentation, and having the conversion script would be > > really handy. >=20 > The script is really sketchy at the moment with a lot of default > values hard-coded but it would not be hard to modularize it enough to > make it useful for the general public. >=20 > I let you look at it, tell me how we could make it more general and > I'll see what we can do. >=20 > Fell free to ask questions about the implementation. >=20 > --=20 > Yannick Gingras > Byte Gardener, Savoir-faire Linux inc. > (514) 276-5468 |
From: Sebastien B. <sbi...@us...> - 2003-03-01 11:54:50
|
Replying to my message: > I was really surprised by the way relations are mapped to > relationships. If I'm not wrong, you're mapping them to 'to-one' > relationship, unconditionally. However, when I tried the tool, I ca= me to > the opposite opinion, because of the 2nd screenshot: > http://www.danny.cz/screenshots/datadesigner1.jpg >=20 > Given that "firmy" has an attribute "forma_id" which is also the PK= of > entity "forma" and that the former entity has a relation to the lat= ter, my > first conclusion was that the relations were intended to model to-m= any > relationships... But czech is greek to me ;) so this is nothing mor= e than > an intuition. Did I really write that ?-: Now I'm surprised again... Looks like my br= ain was in stanby-mode for this one. Just forget the stupid remark: my fir= st conclusion should have been "relations model to-one rels", just as expe= cted given the DB-schema described here. -- S=E9bastien. |
From: Yannick G. <ygi...@yg...> - 2003-03-01 15:01:56
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 27 February 2003 19:50, Sebastien Bigaret wrote: > - about the tool itself: it is really focused on db-schemas ; it has some > features I cannot understand, such as the 'type' of a relation > (identifying, identifying or informational), or the referential integrity > properties for the child/destinationEntity (insert/update props). May be > you can comment on these? Referential Integrity: cascade the delete with references on foreign keys, don't allow inserts with a non-existing foreign key. Or something close to that... I simply ignore those informations in the conversion for now. > The most annoying problem I see is the complete lack of inheritance -- > there seem to be no way to model it. Okay this is quite normal for a tool > dedicated to db-schema, but we'll need it somehow. I confirm that I saw no way to model it, it could simply become a specialized form of relation. > - about the script: yes, there are some default values, but they are easily > identified hence this is not really a problem changing these (I noticed > you really want to have your primary key as class properties :) We could load customs defaults from a .dd2pmrc or allow a command line argument. As I said in a former email, we need to cross a XML-RPC bridge and the only way I see to keep objects identity is through primary key. I found the snapshot() method quite useful > I was really surprised by the way relations are mapped to > relationships. If I'm not wrong, you're mapping them to 'to-one' > relationship, unconditionally. However, when I tried the tool, I came to > the opposite opinion, because of the 2nd screenshot: > http://www.danny.cz/screenshots/datadesigner1.jpg > > Can you explain your practices wrt the relations? Do you design to > relations, one being the inverse of the other, when you design a model > with the db-designer, and edit the xml file afterwards to change one of > these from to-one to to-many? To date I only used to-one but to-many can be modeled and should not pose any problems to convert. > I do not fully understand what are for: parent's update policy, as > well as child's insert & update policy. If someone could bring in a > light... I can't... > - on db-designer 0.4, there's a 'default' for attribute that can be used > for defaultValue --to be added to mutateEntAttrType(). 'int' and > 'integer' expected by the scripts seem to have disappeared and replaced > by int2, int4 and int8 (same for float -> float4 & float8) -- to be > updated in DD_PM_TYPE_MAP No Problem. > - 'class ModelingDDImporter:' simply not making it derive from 'object' > makes the script available for py2.1 as well. No Problem either. When is Zope going to support Python 2.2 ? > - defaults in mutateEntity() & mutateEntAttr() are directly defined as > dictionaries, while 'mutateRelation()' uses makeDefaults() I got tired of quoting dict keys so I used a quick hack I saw in the Python Cookbook. I agree that we should use only one way to do it all across the script, which one do you find cleaner ? I prefer makeDefaults() > Any comments from your experience will be helpful to fully appreciate the > db-designer. Some features could be added easily (such as a checkbox for > isClassProperty in attributes and relations), other would be more difficult > (such as a support for inheritance). Are you by any chance in contact with > the maintainers? There are some part of the interface that are a bit annoying. You can't edit an attribute by double-clicking on it from the entity-tree and minor stuff like that. A really nice feature is that you can put remarks everywhere. > > Another tool that may be useful is PyDBDesigner at > http://pydbdesigner.sourceforge.net/ (thank you Soaf for the link) > > It's python-based, only at an alpha stage for the moment but definitely > worth a try. I currently do not have any time to study both of these > tools in details but if anyone feels like doing it I'll be interested in > their comments. Having a stand-alone modeler (i.e. out of zope) is a real > concern as far as I'm concerned and since time is a concern as well |: I > would for sure prefer using or may be forking an existing project, if > possible, rather than coding it from scratch. Ehhh... this tool is far from being mature... By the way how do you achieve this funny indentation ? > Last, just curiosity: was the zmodeler not an option for you because of > zope itself or do you find/use more of the db-designer xml file that the > zmodeler (and/or the modeling framework's model xml file) does not offer? Zope was not a problem since we already had a Zope up and running but I'm not sure if we would have installed one just to test the framework. The main problem with the ZModeler is the lack of support for various comments but also the lack of visual presentation of the model. We tried data-designer and it happened to be really easy to import the schema into a model, easier that fixing the ZModeler so we opted for an external editor. - -- Yannick Gingras Byte Gardener, Savoir-faire Linux inc. (514) 276-5468 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+YMterhy5Fqn/MRARAvNEAJ9OhsDDVR0J9k87S3iSCyfJzuECUwCfYaRD mjgxDd0aH3KMZr/XAuv1shQ= =iW8w -----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-03-02 21:13:49
|
Hi, > > The most annoying problem I see is the complete lack of inheritan= ce -- > > there seem to be no way to model it. Okay this is quite normal fo= r a tool > > dedicated to db-schema, but we'll need it somehow. >=20 > I confirm that I saw no way to model it, it could simply become a > specialized form of relation. Oh, well, this should be changed, somehow, if at some point we want to = point to this tool for use by the framework's users. > > - about the script: yes, there are some default values, but they are > > easily identified hence this is not really a problem changing these= (I > > noticed you really want to have your primary key as class propertie= s :) >=20 > We could load customs defaults from a .dd2pmrc or allow a command line > argument. As I said in a former email, we need to cross a XML-RPC br= idge > and the only way I see to keep objects identity is through primary ke= y. I > found the snapshot() method quite useful Ok, I see. Have you considered using the informations enclosed within e= very GlobalID? The GlobalID of an object is its identifier within the framework ; yo= u can get it from an EditingContext by using the message 'objectForGlobalID= '. Every object that exists in the database is assigned a unique KeyGlob= alID, whose keyValues() method returns a dictionary mapping the primary key= 's name with its value. > > I was really surprised by the way relations are mapped to > > relationships. If I'm not wrong, you're mapping them to 'to-one' > > relationship, unconditionally. However, when I tried the tool, I = came to > > the opposite opinion, because of the 2nd screenshot: > > http://www.danny.cz/screenshots/datadesigner1.jpg > > > > Can you explain your practices wrt the relations? Do you design to > > relations, one being the inverse of the other, when you design a = model > > with the db-designer, and edit the xml file afterwards to change = one of > > these from to-one to to-many? >=20 > To date I only used to-one but to-many can be modeled and should not > pose any problems to convert. Ok. > When is Zope going to support Python 2.2 ? I think 2.7 will officially support 2.2, but I've not checked. I've read that 2.6 already (but not officially) supports py2.2. > > - defaults in mutateEntity() & mutateEntAttr() are directly defin= ed as > > dictionaries, while 'mutateRelation()' uses makeDefaults() >=20 > I got tired of quoting dict keys so I used a quick hack I saw in the > Python Cookbook. I agree that we should use only one way to do it all > across the script, which one do you find cleaner ? >=20 > I prefer makeDefaults() So do I, and I'll remember that idiom for sure, really handy. About PyDBDesigner: > Ehhh... this tool is far from being mature... Unfortunately, yes... > By the way how do you achieve this funny indentation ? Well, emacs almost does all the work! (M-q, fill-paragraph) > > Last, just curiosity: was the zmodeler not an option for you becaus= e of > > zope itself or do you find/use more of the db-designer xml file tha= t the > > zmodeler (and/or the modeling framework's model xml file) does not > > offer? >=20 > Zope was not a problem since we already had a Zope up and running but= I'm > not sure if we would have installed one just to test the framework. = The > main problem with the ZModeler is the lack of support for various com= ments > but also the lack of visual presentation of the model. I'm afraid there's nothing useful to be done as far as the ZModeler a= nd its lack of visual presentation are concerned. Your other remark abou= t the possibility to add comments is interesting. Where would you ideally a= dd these comments in the model? Regards, -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-02-28 00:16:18
|
Hi Mario, > following comments about the XML model (on and off the list) and > how it can be improved or redone altogether, i started thinking about= =20 > it... > And (to be able to get it out of my mind and get to some other work ;= -) > here is a proposal for a pure python description of the model. It=20 > follows > the XML closely, and in fact may always retain compatibility (at least > generation of XML from the python model, which will be trivial). I agree: the pymodel must have the same power of expression than the existing xml-file, i.e. every properties for Entities, Attributes etc. should be settable in the py-model just like they are in the xml.= =20=20 Your proposal holds the complete kick-off material. > The behaviour in general would stay the same as the XML way of > doing things, namely form this model you would generate the classes > and the db schemas. These features are available for any Modeling.Model object, so the "onl= y" thing to do is build it from the py-model, just like it goes for the xm= l. (same for generating an xml-model, thus mapping a py-model to an xml-mo= del will be straightforward --cf. ModelSet.getXMLDOMForModelNamed() and getXMLStreamForModelNamed()) > Some differences are choice of default values, and that key and locki= ng > attributes are defined on attributes and relations rather than entiti= es=20 > ;) Ok, I guess we won't argue any further on this by now ;) > As an exercise, I have taken the sample model in the distribution: > testPackages/StoreEmployees/model_StoreEmployees.xml and re-expressed= it > in this pythonic way. Thanks, this made things even clearer. > Apart from readability and losing of some verbosity, other gains are > "executability" and dynamicity -- it could be very easy to modify a m= odel > at runtime, if you would ever want to do that. Oh oh, I can't believe you said that! Models' mutability at runtime is = an other subject we'd better discuss apart from this thread. It *is* possi= ble, under some conditions I certainly need to gather before answering. If y= ou need this sort of feature in short-term, you'd better picked me on wild= ly!! > Also, given that a model now becomes a module in and of itself, it g= ains > from what modules have to offer, such as self-tests. Ok. > And, speed of course, as i see no reason why this model object would = also > not serve as the model object in memory at runtime (but that's for > Sebastien to confirm) -- thus loading the model is equivalent to "from > MyModel import model". Well, it will need a few more lines of code to actually load the model = into the so-called defaultModelSet (cf. Modeling.ModelSet and the generated __init__.py), but that's it. > Can you please take a look at the 2 linked files below (as temporary > URLs, as to attach they are too big); > - PyModel.py -- defines the classes (signatures for) for, and > documents the rules for, a PyModel instance > - sample_PyModel.py -- re-expresses the StoreEmployees model Ok, now let's take a look at the big stuff ;) Your python code is sound and clear. My first comments are: - maybe we'll gain more readability if relationships' multiplicity lo= wer- and upper bounds where encoded in strings, such as: '0-1', '1-1', '= 0-*' or '2-16'. =20=20 - Same for external type's width, precision and scale, such as in: 'NUMERIC(12,2)' or 'VARCHAR(200)' - Again, same for an entity's parent which could be specified along w= ith the entity's name: 'Executive(Employee)' - What about the possibility to add a '*' to an attribute's name when= it's required? (may be same for a relationship, equivalent to lower boun= d=3D=3D1) - Allow litterals instead of the equivalent integers in the xml: 'CAS= CADE' for the delete rule is more explicit than int(2)! - I think I would have made 'name' instead 'columnName' the default f= or displayLabel :) Now that I get used to the idea of a python-model, I'm also thinking of= some extents to your proposal: - We could have subclasses for your Attribute: PrimaryKey, ForeignKey (defaults for both would be: int, not class property, etc.), String (with a default external size/width), Integer, Numeric, ... You get= the idea. - Relation can also be sub-classed to 'ToOne' and 'ToMany' (default w= ould be '0-*' for the latter) Last, I'm thinking of some automatic processing which is already coded = in the zmodeler and that could be done at model-time to reduce verbosity i= n a significant manner: - have a primary key 'id' automatically declared if not set, - have foreign keys automatically set for relationships, using the sa= me defaults the zmodeler already uses (e.g. FKEmployeeId for a to-many relationship pointing to the entity Employee). It would need some additional checks but it's definitely possible. This could be as handy as the feature you submitted in your proposal: automatic definition parent properties which are not overriden in sub-entities. I wrote all these items with something in mind, actually. You know, I'm basically lazing, most of the time I do not take about DB-Schemas detai= ls, and I will be delighted if it was possible to write the same StoreEmplo= yee model really simply. This is a good illustration of the automatic proce= ssing I described above because this model (like every test models) were desi= gned using the zmodeler and its functionalities. In fact, I'm thinking that something simple like that could be writte= n: (this would imply some changes to your proposed API, such as making 'destinationEntity' the second argument for the Relationship's initial= izer). -----------------------------------------------------------------------= ----- from PyModel import Attribute,Relation,Entity,Model _connDict =3D {} model =3D Model('StoreEmployees',connDict=3D_connDict) model.entities =3D [ Entity('Store', attributes=3D[ String('corporateName *', width=3D30) ], relations=3D[ ToMany('employees', 'Employee', delete=3D'deny') ]) # Employee and its subclasses SalesClerk and Executive Entity('Employee', attributes=3D[ String('lastName *', width=3D20, isUsedForLocking= =3D1 ],=20 String['firstName *', width=3D50, isUsedForLocking= =3D1 ], ], relations=3D[ ToMany('toAddresses', 'Address', delete=3D'cascad= e' ],=20 ToOne('toStore', 'Store') ]) Entity('SalesClerk(Employee)',=20 attributes=3D[ String('storeArea', width=3D20) ]), Entity('Executive(Employee)', ## width declared in external= Type attributes=3D[ String('officeLocation', externalType=3D'VARCHAR(= 5)') ], relations=3D[ ToMany('marks', 'Mark', delete=3D'cascade' ]), # Entity('Address', attributes=3D[ String('street', width=3D80),=20 String('zipCode', width=3D80),=20 String('town', width=3D80), ], relations=3D[ ToMany('toEmployee', 'Employee', delete=3D'deny') ]= ), # Entity('Mark', attributes=3D[ Integer('month *'),=20 Integer('mark *'), ], relations=3D[ ToOne('executive', 'Executive' ] ]) ] if __name__ =3D=3D '__main__': print model.validate() print model.toXML() -----------------------------------------------------------------------= ----- (this example was written with the intention of being strictly equiva= lent to the original one)=20 Of course this would need some additional cpu-time to load a model, but= I bet it would be far quicker than parsing the xml! This of course still needs to be discussed and refined. I did not hav= e any time to try & implement my proposal, but I guess that at some point of = the discussion we'll need to see the words take shape --at this point this = could naturally be made in a dev-branch if several of us are on this. I really have the feeling that we will succeed in designing a very ni= ce python model. Let's go for it now that Mario brought some light on the path! Cheers, -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-02-28 11:32:17
|
Hello, thanks for the detailed feedback, and I like most of it very much. I comment on each point (needing comment) below... ... >> The behaviour in general would stay the same as the XML way of >> doing things, namely form this model you would generate the classes >> and the db schemas. > > These features are available for any Modeling.Model object, so the > "only" > thing to do is build it from the py-model, just like it goes for the > xml. > > (same for generating an xml-model, thus mapping a py-model to an > xml-model > will be straightforward --cf. ModelSet.getXMLDOMForModelNamed() and > getXMLStreamForModelNamed()) Yes, should be the same idea, except that there'd be no need to have methods with "forModelNamed" in their name, as this would be implied by the object on which the method is called: modelset.getXML() modelset.getXMLDOM() model.getXML() entity.getXML() ... The ModelSet concept is not yet included in the PyModel description (mostly becuase it is not fully clear to me how it is used). How would you extend this description to include it? >> Some differences are choice of default values, and that key and >> locking >> attributes are defined on attributes and relations rather than >> entities >> ;) > > Ok, I guess we won't argue any further on this by now ;) But, see how it makes things easier! You declare a key on an att, you use the att, defining also teh key on the using entity -- makes things consistent, and less wordy. If you want that an id in one entity is a key but not in another, then you are forced to define 2 different id 'types', which helps make the difference obvious to anyone looking in. >> As an exercise, I have taken the sample model in the distribution: >> testPackages/StoreEmployees/model_StoreEmployees.xml and re-expressed >> it >> in this pythonic way. > > Thanks, this made things even clearer. >> >> Apart from readability and losing of some verbosity, other gains are >> "executability" and dynamicity -- it could be very easy to modify a >> model >> at runtime, if you would ever want to do that. > > Oh oh, I can't believe you said that! Models' mutability at runtime is > an > other subject we'd better discuss apart from this thread. It *is* > possible, > under some conditions I certainly need to gather before answering. If > you > need this sort of feature in short-term, you'd better picked me on > wildly!! In general this is not what anyone woudl want to do, and I was trying to think of times when this would be useful. Can't really, but i *suspect* it might come in handy. But, in fact, imagine some application that is stocking lots of incoming unknown data into a db... let's say the data is XML, but each XML data-schema is unknown a priori. You can create a py model to correspond, at runtime (but saved for subsequent accessing), create the tables, and stock the unknown XML in the db directly as real db tables.... >> Also, given that a model now becomes a module in and of itself, it >> gains >> from what modules have to offer, such as self-tests. > > Ok. > >> And, speed of course, as i see no reason why this model object would >> also >> not serve as the model object in memory at runtime (but that's for >> Sebastien to confirm) -- thus loading the model is equivalent to "from >> MyModel import model". > > Well, it will need a few more lines of code to actually load the model > into > the so-called defaultModelSet (cf. Modeling.ModelSet and the generated > __init__.py), but that's it. Yes, but i was leaving all that to you ;) But, details of how such a py model would integrate with the rest of the framework are all to be decided, and please point out any problems that only you can foresee! >> Can you please take a look at the 2 linked files below (as temporary >> URLs, as to attach they are too big); >> - PyModel.py -- defines the classes (signatures for) for, and >> documents the rules for, a PyModel instance >> - sample_PyModel.py -- re-expresses the StoreEmployees model > > Ok, now let's take a look at the big stuff ;) > > Your python code is sound and clear. My first comments are: A general comment to the comments below -- in general i do not like 'special format strings' as values to things. This adds possible errors, requires special documentation, makes checking more difficult, and in general is less pythonic... I think keeping the info units separate would be easier to work with, and clearer. The overhead of having to specify the same parameters many times over can be reduced by standard defaults and the possibility to set defaults only for this model (see new sample...) > - maybe we'll gain more readability if relationships' multiplicity > lower- > and upper bounds where encoded in strings, such as: '0-1', '1-1', > '0-*' > or '2-16'. Yes, but not as strings. What is wrong with a python list? multiplicity = [0,1] multiplicity = [1,-1] > - Same for external type's width, precision and scale, such as in: > 'NUMERIC(12,2)' or 'VARCHAR(200)' Same thing here. This would also make it difficult to provide defaults separately for dbtype, and for width or precision. So, I would vote to keep them separate (and tyo change the name of externalType to dbType). I think it will be easier to work with, and clearer for everyone. > - Again, same for an entity's parent which could be specified along > with > the entity's name: 'Executive(Employee)' Same. I vote to keep separate, and to rename parentEntity to isAlso, e.g. Entity('Executive', isAlso='Employee', ... > - What about the possibility to add a '*' to an attribute's name > when it's > required? (may be same for a relationship, equivalent to lower > bound==1) Same for adding '*' to att name, but definately yes to have constraints forced down as a result from relations, e.g. if a one-to-one relation is required, then the related attributes must also be required -- but this is automatic and taken into account by the validation. > - Allow litterals instead of the equivalent integers in the xml: > 'CASCADE' > for the delete rule is more explicit than int(2)! Definately. Also, in lowercase! (Hate being screamed at, which is what uppercase seems to be always doing \-) > - I think I would have made 'name' instead 'columnName' the default > for > displayLabel :) Yes, it is probably better. > Now that I get used to the idea of a python-model, I'm also thinking > of some > extents to your proposal: > > - We could have subclasses for your Attribute: PrimaryKey, ForeignKey > (defaults for both would be: int, not class property, etc.), String > (with a default external size/width), Integer, Numeric, ... You > get the > idea. Great! There could be some standard sub-classes, but a user is ofcourse allowed to make his own. What about the naming scheme propoes by the example below, that Att subs start with the letter 'A' and rel subs start with the letter 'R' ? (to avoid unnecessarily long names) > - Relation can also be sub-classed to 'ToOne' and 'ToMany' (default > would > be '0-*' for the latter) Yes. Also, all defaults may be set for a specific model as necessary... > Last, I'm thinking of some automatic processing which is already coded > in > the zmodeler and that could be done at model-time to reduce verbosity > in a > significant manner: > > - have a primary key 'id' automatically declared if not set, In general "magical" behaviour is more trouble than gain... how about if we have the possibility to define a default attribute on an Entity description class? > - have foreign keys automatically set for relationships, using the > same > defaults the zmodeler already uses (e.g. FKEmployeeId for a to-many > relationship pointing to the entity Employee). It would need some > additional checks but it's definitely possible. Again, I like simplifying the management of all this, but i do not like being forced to accept decisions imposed by the framework, such as the names of my columns (what if I want to provide a model for an existing db?) So, providing a default scheme, that the user may redefine (or not use at all), seems more reasonable to me. See the defaults for sourceAttribute and destinationAttribute in RToOne and RToMany... Also, see the explicit declaration of the foreign keys (with the possibility of automatic the name for it). > This could be as handy as the feature you submitted in your proposal: > automatic definition parent properties which are not overriden in > sub-entities. Yes. Auto generation of foreign keys from a relationship definition does make sense in fact... but the possibility to declare them explicitly (with the desired values for their attributes) should always be there. Since such explicit declaration can be very simple, I prefer to leave it as must be explicit. > I wrote all these items with something in mind, actually. You know, I'm > basically lazing, most of the time I do not take about DB-Schemas > details, > and I will be delighted if it was possible to write the same > StoreEmployee > model really simply. This is a good illustration of the automatic > processing > I described above because this model (like every test models) were > designed > using the zmodeler and its functionalities. > > In fact, I'm thinking that something simple like that could be > written: > (this would imply some changes to your proposed API, such as making > 'destinationEntity' the second argument for the Relationship's > initializer). Ah, very good -- destinationEntity must in fact be specified everytime, so this is better this way. I have taken your simplified model, and evolved it to correspond to my comments above. Correspondingly, i have also updated the PyModel module to indicate how it would change to support these changes. I have put the two files (PyModel_3_mr.py and sample_ PyModel_3_mr.py) at: http://ruggier.dyndns.org:8080/PyModel/ But for convenience, I am also pasting below the sample model... Oh, and some other changes I have not mentioned here are listed in the top of PyModel_3_mr.py, but mostly name changes, and having entities have only one list, that mixes attributes and relations... (your opinion?). > Of course this would need some additional cpu-time to load a model, > but I > bet it would be far quicker than parsing the xml! > > This of course still needs to be discussed and refined. I did not > have any > time to try & implement my proposal, but I guess that at some point of > the > discussion we'll need to see the words take shape --at this point this > could > naturally be made in a dev-branch if several of us are on this. OK. > I really have the feeling that we will succeed in designing a very > nice > python model. Let's go for it now that Mario brought some light on > the > path! That would not be XPath, would it ;-? Cheers, mario ps: sample_ PyModel_3_mr.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 type Model ''' from PyModel import * ## # Set preferred defaults for this model (when different from # standard defaults, or if we want to make things explicit) AInteger.defaults['precision'] = 10 AString.defaults['width'] = 20 RToOne.defaults['delete'] = 'cascade' RToOne.defaults['multiplicity'] = [0,1] RToOne.defaults['sourceAttribute'] = RToOne.attNameFromRel # 'fk'+destEnt+destAtt+count RToOne.defaults['destinationAttribute'] = 'id' RToMany.defaults['delete'] = 'deny' RToMany.defaults['multiplicity'] = [0,*] RToMany.defaults['sourceAttribute'] = 'id' RToMany.defaults['destinationAttribute'] = RToMany.attNameFromRel # fk+destEnt+sourceAtt+count # Note that Relation.attNameFromRel is a callable, that calculates the att name # from the indicated pieces (where count to distinguish between multiple relations # between same source and target Entity.defaults['attributes'] = [ AInteger('id', key=1, isClassProperty=0, isRequired=1) ] ## _connDict = {} model = Model('StoreEmployees',connDict=_connDict) model.entities = [ # Entity('Store', attributes=[ AString('corporateName', isRequired=1), RToMany('employees', 'Employee') ] ) # Employee and its subclasses SalesClerk and Executive Entity('Employee', attributes=[ AString('lastName', isRequired=1, usedForLocking=1), AString('firstName', isRequired=1, width=50, usedForLocking=1), AForeignKey(Attribute.fk('Store'), isClassProperty=0), RToMany('toAddresses', 'Address', delete='cascade'), RToOne('toStore', 'Store') ] ) Entity('SalesClerk', isAlso='Employee', attributes=[ AString('storeArea') ] ), Entity('Executive', isAlso='Employee', attributes=[ AString('officeLocation', width=5), RToMany('marks', 'Mark', delete='cascade') ] ), # Entity('Address', attributes=[ AString('street', width=80), AString('zipCode'), AString('town', width=80), AForeignKey(Attribute.fk('Employee'), isClassProperty=1), RToMany('toEmployee', 'Employee', delete='deny') ] ), # Entity('Mark', attributes=[ AInteger('month', isRequired=1), AInteger('mark', isRequired=1), AForeignKey(Attribute.fk('Executive'), isClassProperty=1), RToOne('executive', 'Executive' ] ] ) ] if __name__ == '__main__': print model.validate() print model.toXML() # plus whatever ... ## |
From: Sebastien B. <sbi...@us...> - 2003-03-01 16:00:48
|
Hi, > > (same for generating an xml-model, thus mapping a py-model to an=20 > > xml-model > > will be straightforward --cf. ModelSet.getXMLDOMForModelNamed() and > > getXMLStreamForModelNamed()) >=20 > Yes, should be the same idea, except that there'd be no need to have > methods with "forModelNamed" in their name, as this would be implied > by the object on which the method is called: >=20 > modelset.getXML() > modelset.getXMLDOM() > model.getXML() > entity.getXML() > ... Yes, we're meaning the same thing here. I just wanted to point out where it was implemented. And it was stupid, I should have pointed the existing methods Model.getXMLDOM() and .saveModelAsXMLFile() instead. > The ModelSet concept is not yet included in the PyModel description > (mostly becuase it is not fully clear to me how it is used).=20 I'm afraid there's no real documentation on that. Let's go for a short one: the framework can only deal with one ModelSet at a time, the one returned by defaultModelSet() in module ModelSet. The module & class main responsabilities are: 1. making sure that all the entities defined in a ModelSet instance h= ave distinct names: a ModelSet identifies its models and entities by n= ame. Hence, object defaultModelSet() can be asked at runtime for models= and entities, given their names 2. registering the object returned by defaultModelSet() as the default receiver for the notification ClassDescriptionNeededForEntityNameNotification posted by classDescriptionForName() in module ClassDescription. (I added this to the module's docstring) > How would you extend this description to include it? I won't ;! Since the framework only deals with one ModelSet at a time, I can't see any reason to add it in the model (there's no model set in the xml model either). About: key&locking attrs defined on atts and rels rather than entities > [...] But, see how it makes things easier [and] consistent [...] I saw ;) and I'm convinced. About: Models' being mutable at runtime > In general this is not what anyone woudl want to do, and I was trying > to think of times when this would be useful. Can't really, but i > *suspect* it might come in handy. But, in fact, imagine some > application that is stocking lots of incoming unknown data into a > db... let's say the data is XML, but each XML data-schema is unknown a > priori. You can create a py model to correspond, at runtime (but saved > for subsequent accessing), create the tables, and stock the unknown > XML in the db directly as real db tables.... Okay, I now can be more precise here: adding an entity at runtime is definitely not a problem. But mutating an entity (changing its attributes for example, or its name), or removing an entity should *not* be done after an object of the corresponding class has been registered within an EditingContext. (this should be a FAQ) > >> And, speed of course, as i see no reason why this model object > >> would also not serve as the model object in memory at runtime (but > >> that's for Sebastien to confirm) -- thus loading the model is > >> equivalent to "from MyModel import model". > > > > Well, it will need a few more lines of code to actually load the > > model into the so-called defaultModelSet (cf. Modeling.ModelSet and > > the generated __init__.py), but that's it. >=20 > Yes, but i was leaving all that to you ;) No problem! > But, details of how such a py model would integrate with the rest of > the framework are all to be decided, and please point out any problems > that only you can foresee! Integrating a py-model is just a matter of transforming a pymodel to a Modeling.Model. Hence, all possible problems are really conversion problems. And I keep my eyes opened! > in general i do not like 'special format strings' as values to > things. This adds possible errors, requires special documentation, > makes checking more difficult, and in general is less pythonic... I > think keeping the info units separate would be easier to work with, > and clearer. The overhead of having to specify the same parameters > many times over can be reduced by standard defaults and the > possibility to set defaults only for this model (see new sample...) >=20 > > - maybe we'll gain more readability if relationships' multiplicity > > lower- and upper bounds where encoded in strings, such as: '0-1= ', > > '1-1', '0-*' or '2-16'. >=20 > Yes, but not as strings. What is wrong with a python list? > multiplicity =3D [0,1] > multiplicity =3D [1,-1] Well, I understand your point quite well and I'm ok with a list. [1,-1] seems however obscure, if we go for a python list what do you think of [0,'*'] or maybe better: [0,] ? > > - Same for external type's width, precision and scale, such as in: > > 'NUMERIC(12,2)' or 'VARCHAR(200)' >=20 > Same thing here. This would also make it difficult to provide defaults > separately for dbtype, and for width or precision. I disagree: default would be treated exactly the same way: if the width or precision/scale cannot be found in the parsed string then the defaul= ts apply.=20 > So, I would vote to keep them separate (and tyo change the name of > externalType to dbType). I think it will be easier to work with, > and clearer for everyone. I'd really like to keep the former possibility, though. It can co-exist with yours, I've no problem with that. I won't however go crazy if we do not support it ! I suggest we forget about my proposal for 'VARCHAR(20)' and that we only consider explicit parameters width/precision/scale. Since it's not a hard thing to add, we can safely forget it for the moment and add it later if this reveals to be a users' request. Now that I think of it, there's an underlying point that should be discussed for clarification. For example a string/VARCHAR won't get any defaults in the conversion process, unless explicitly stated in the model itself (yours AString.default['width']) --same for NUMERIC, etc. This way it makes it clear that a String requires a width, that a float requires precision and scale, etc., since we would get an error if neither a default nor an explicit parameter is provided. What do you think about this? In fact, I do not even know what a good default for width, scale or precision can be. Different DB have different defaults, and I don't think it's worth registering/tracking them. > > - Again, same for an entity's parent which could be specified > > along with the entity's name: 'Executive(Employee)' >=20 > Same. I vote to keep separate, and to rename parentEntity to isAlso, > e.g. Entity('Executive', isAlso=3D'Employee', ... I know this is a detail, but I would have sponteanously shortened it to 'parent'. 'isAlso' vaguely recalls me something, but I don't know what... It sounds familiar. Is this UML jargon? > > - What about the possibility to add a '*' to an attribute's name= =20 > > when it's > > required? (may be same for a relationship, equivalent to lower= =20 > > bound=3D=3D1) >=20 > Same for adding '*' to att name Ok, again, let's forget it, I added it for completeness but didn't really like it either. The explicit parameter 'required' is enough. Speaking of this term, maybe it's not clear enough: I observed people being surprised that '' (empty string) is a valid value for a field that is required because they misunderstood it, while it only tells whether the attribute can be None (python) / NULL (SQL). In the Attribute API there's also the counterpart 'allowsNone', what do you think? > but definately yes to have constraints forced down as a result from > relations, e.g. if a one-to-one relation is required, then the related > attributes must also be required -- but this is automatic and taken > into account by the validation. Currently designing one-to-one is not possible, but we can automatically make a choice on which entity the foreign key should be dropped in. For one-to-many this is straightforward (almost, see below comments on FK names) > > - Allow litterals instead of the equivalent integers in the xml: > > 'CASCADE' for the delete rule is more explicit than int(2)! >=20 > Definately. Also, in lowercase! (Hate being screamed at, which is what > uppercase seems to be always doing \-) This is an old habit for declaring constants I inherited from the years where I was a C programmer! So lowercase, ok. > > Now that I get used to the idea of a python-model, I'm also thinking > > of some extents to your proposal: > > > > - We could have subclasses for your Attribute: PrimaryKey, Foreig= nKey > > (defaults for both would be: int, not class property, etc.), St= ring > > (with a default external size/width), Integer, Numeric, ... You= =20 > > get the idea. > >=20=20=20=20=20 >=20 > Great! There could be some standard sub-classes, but a user is > ofcourse allowed to make his own. What about the naming scheme propoes > by the example below, that Att subs start with the letter 'A' and rel > subs start with the letter 'R' ? (to avoid unnecessarily long names) I easily got used to it, if there's no other objections let's keep it > > Last, I'm thinking of some automatic processing which is already > > coded in the zmodeler and that could be done at model-time to reduce > > verbosity in a significant manner: > > > > - have a primary key 'id' automatically declared if not set, >=20 > In general "magical" behaviour is more trouble than gain... how about > if we have the possibility to define a default attribute on an Entity > description class? Fine, we then have standard defaults along with the ability to specify specific default for a model, all in one. +1 on this, definitely. > > - have foreign keys automatically set for relationships, using the > > same defaults the zmodeler already uses (e.g. FKEmployeeId for a > > to-many relationship pointing to the entity Employee). It would > > need some additional checks but it's definitely possible. >=20 > Again, I like simplifying the management of all this, but i do not > like being forced to accept decisions imposed by the framework, such > as the names of my columns (what if I want to provide a model for an > existing db?) > So, providing a default scheme, that the user may redefine (or not > use at all), seems more reasonable to me.=20 Ok -- what I wrote was not clear enough, I meant that too. > See the defaults for sourceAttribute and destinationAttribute in > RToOne and RToMany... Also, see the explicit declaration of the > foreign keys (with the possibility of automatic the name for it). I'm afraid the naming scheme you propose won't make it. In fact, I was thinking of automating the simple case, where only one association exists between two entities. In this case, the foreign key only needs to be named 'fk<destinationEntityName>' ; this makes it easy for one relationship and its possible inverse to actually refer to the same source/destination attributes in their joins. Now a more complex example: suppose you want to model something like this: A <------->> B <------->> (this comes from a "real-life" example, two relationships from A to B having a different semantics) Suppose we first process A's relationships: this will create two different FK in B pointing to A's PK. Now we process entity B: there is no way to identify which relationship coming from A is the inverse of a toOne from B. Hence, this can be automated *if and only if* we also have the keyword 'inverse' in the declaration of a relationship. BTW, this is where I think automation will not be a real gain and will not be worth the effort, because that sort of model is really not showing up frequently, and because when it shows up you usually want to have names for foreign keys more explicit than fk<destinationEntityName><count> (You stated: fk<destinationEntityName><destinationAttributeName><count> but since the destAttr. will always be the same for a given dest. entity (the PK), I removed it here) > > This could be as handy as the feature you submitted in your proposa= l: > > automatic definition parent properties which are not overriden in > > sub-entities. >=20 > Yes. Auto generation of foreign keys from a relationship definition d= oes > make sense in fact... but the possibility to declare them explicitly= =20 > (with > the desired values for their attributes) should always be there. Since > such explicit declaration can be very simple, I prefer to leave it as > must be explicit. My opinion here is: - make it possible to automate the simple case (PK and FK), as explained above, - always keep the possibility to explicitly write every single properties in models, entities, etc. You might think that I'm definitely reluctant to impose explicit declarations (such as for the FK). I think I am but it's not a religion ;)=20 In fact, it's really a matter of usual practices in E-R modeling. This is not only /my/ practice, but the way most people seem to deal with entity-relationship modeling --they do not care about the db-schema PK/FK details unless they need to, for example when defining a model for an existing model, or when some complex design is required (just like the one I described above). Obviously this observation was not made on that framework (there are still not enough people using it for such an observation), but it is what I observed from the community using the original Apple's Enterprise Object Framework(tm). I'm possibly wrong and maybe I just think that people do not care because most of the times *I* usually don't care. In the ZModeler I added the ability to make the two relationships necessary for a one-to-many association at a single-click reach for that very reason: it's a valuable feature to my own eyes, and I think it may be for other's. Last comment on this: I do not really like the idea of imposing the FK to be declared while having a implicit default for the PK, it sounds inconsistent to me. Please do not misunderstand what I'm saying here, my english is not good enough to be subtle. I'm just trying to make my opinions and positions clearer by being more explicit :) > I have taken your simplified model, and evolved it to correspond to my > comments above. Correspondingly, i have also updated the PyModel > module to indicate how it would change to support these changes. > [...] > Oh, and some other changes I have not mentioned here are listed in > the top of PyModel_3_mr.py, but mostly name changes, and having > entities have only one list, that mixes attributes and relations...=20 > (your opinion?). * deleteRule -> delete: ok * multiplicity lower/upper bound -> multiplicity as a python list: ok * entity only has attributes that may also be relations: I'm ok for the principle, however i would prefer an distinct term for this, relations being attributes could be a source of confusion. Maybe 'properties' ? More comment on this: having attributes and relations mixed in a common list will require extra-checks when analysing the model to perform the possibly needed automated steps. This is because we will need to have all the entities and their attributes loaded and processed before we can make a decision on whether a declared relation needs automatic generation of FK. We will need to separate attributes from relations anyway.=20 I do not mean this is complex: it's not. However I'm not sure this enhance readability. In the sample model your clearly first declared attributes, than relationships, and I bet everyone will do it that way, because it would be a real mess to have some attrs, than rels, than attrs, etc. * misc.: at some point in the discussion the FK were made class properties in the py-model, but they should not! Regarding PyModel_3_mr.py: - I'm not sure we want a default for entity.adaptorName - I'd add a APrimaryKey subclass of Attribute > > I really have the feeling that we will succeed in designing a very > > nice python model. Let's go for it now that Mario brought some light > > on the path! >=20 > That would not be XPath, would it ;-? Ooooh no, it wouldn't ;! Cheers, -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-03-03 00:40:33
|
Hi, Thanks for the ModelSet clarification. Further comments below... > About: Models' being mutable at runtime >> In general this is not what anyone woudl want to do, and I was trying >> to think of times when this would be useful. Can't really, but i >> *suspect* it might come in handy. But, in fact, imagine some >> application that is stocking lots of incoming unknown data into a >> db... let's say the data is XML, but each XML data-schema is unknown a >> priori. You can create a py model to correspond, at runtime (but saved >> for subsequent accessing), create the tables, and stock the unknown >> XML in the db directly as real db tables.... > > Okay, I now can be more precise here: adding an entity at runtime is > definitely not a problem. But mutating an entity (changing its > attributes for example, or its name), or removing an entity should > *not* > be done after an object of the corresponding class has been registered > within an EditingContext. > > (this should be a FAQ) OK, understood, and probbaly a good idea to mention it as an FAQ. ... >> What is wrong with a python list? >> multiplicity = [0,1] >> multiplicity = [1,-1] > > Well, I understand your point quite well and I'm ok with a list. [1,-1] > seems however obscure, if we go for a python list what do you think of > [0,'*'] or maybe better: [0,] ? Absolutely fine with me (used -1 to keep it as an integer.) I think i prefer the None version of this, which could also be explicit, i.e [1,None] >>> - Same for external type's width, precision and scale, such as in: >>> 'NUMERIC(12,2)' or 'VARCHAR(200)' >> >> Same thing here. This would also make it difficult to provide defaults >> separately for dbtype, and for width or precision. > > I disagree: default would be treated exactly the same way: if the width > or precision/scale cannot be found in the parsed string then the > defaults > apply. Ah, so you mean that assignem,ent will just map such an initial value onto the concerned properties, and then work with the separated value sfrom then on. Well, OK. But may lead to confusion if you for the value of type, and get something else than what you specified (e.g. only 'NUMERIC' without the qualifiers). >> So, I would vote to keep them separate (and tyo change the name of >> externalType to dbType). I think it will be easier to work with, >> and clearer for everyone. > > I'd really like to keep the former possibility, though. It can co-exist > with yours, I've no problem with that. > > I won't however go crazy if we do not support it ! I suggest we forget > about my proposal for 'VARCHAR(20)' and that we only consider explicit > parameters width/precision/scale. Since it's not a hard thing to add, > we > can safely forget it for the moment and add it later if this reveals to > be a users' request. I would agree with proceeding this way. > Now that I think of it, there's an underlying point that should be > discussed for clarification. For example a string/VARCHAR won't get > any defaults in the conversion process, unless explicitly stated in > the model itself (yours AString.default['width']) --same for NUMERIC, > etc. This way it makes it clear that a String requires a width, that > a > float requires precision and scale, etc., since we would get an > error if neither a default nor an explicit parameter is provided. Yes, this syntax will make that association clearer. But the validation should also point out if these are missing. > What do you think about this? In fact, I do not even know what a good > default for width, scale or precision can be. Different DB have > different defaults, and I don't think it's worth registering/tracking > them. Have no idea what reasonable defaults should be... I feel their main purpose is to make things less error-prone, especially in the beginning. Programs should probably specify them anyway, when they know what is best for the program (and, should probably not rely on default values set by the framework.) >>> - Again, same for an entity's parent which could be specified >>> along with the entity's name: 'Executive(Employee)' >> >> Same. I vote to keep separate, and to rename parentEntity to isAlso, >> e.g. Entity('Executive', isAlso='Employee', ... > > I know this is a detail, but I would have sponteanously shortened it to > 'parent'. 'isAlso' vaguely recalls me something, but I don't know > what... It sounds familiar. Is this UML jargon? Not UML -- it is just what i think of (isAlso) when i think of inheritance... But parent is just fine. >>> - What about the possibility to add a '*' to an attribute's name >>> when it's >>> required? (may be same for a relationship, equivalent to lower >>> bound==1) >> >> Same for adding '*' to att name > > Ok, again, let's forget it, I added it for completeness but didn't > really like it either. The explicit parameter 'required' is enough. > > Speaking of this term, maybe it's not clear enough: I observed people > being surprised that '' (empty string) is a valid value for a field > that > is required because they misunderstood it, while it only tells whether > the attribute can be None (python) / NULL (SQL). In the Attribute API > there's also the counterpart 'allowsNone', what do you think? Hmmn, i feel isRequired is more logical, while allowsNone is more implementation-oriented -- but quite clear. The problem with it is that it is a double negative (required => allowsNone = No) which i always find irritating. Plus, should one day a formal expression of what values are allowed for an attribute are also specified in the model, then isRequired will lose the confusion potential you mention, e.g. if the model supports a regexp for an attribute (to which all values must match) then isRequired will clearly mean that a value respecting this constraint must be present. Which is a good opportunity to propose the feature request of being able to specify a regexp for an attribute, against which the framework will validate all values to be assigned to the attribute (and which does not exclude providing other declarations to use for data validation for any attribute, such as type). ... >> See the defaults for sourceAttribute and destinationAttribute in >> RToOne and RToMany... Also, see the explicit declaration of the >> foreign keys (with the possibility of automatic the name for it). > > I'm afraid the naming scheme you propose won't make it. In fact, I was > thinking of automating the simple case, where only one association > exists between two entities. In this case, the foreign key only needs > to > be named 'fk<destinationEntityName>' ; this makes it easy for one > relationship and its possible inverse to actually refer to the same > source/destination attributes in their joins. > > Now a more complex example: suppose you want to model something like > this: > > A <------->> B > <------->> > > (this comes from a "real-life" example, two relationships from A to B > having a different semantics) > > Suppose we first process A's relationships: this will create two > different FK in B pointing to A's PK. Now we process entity B: there is > no way to identify which relationship coming from A is the inverse of a > toOne from B. Hence, this can be automated *if and only if* we also > have > the keyword 'inverse' in the declaration of a relationship. > > BTW, this is where I think automation will not be a real gain and > will > not be worth the effort, because that sort of model is really not > showing up frequently, and because when it shows up you usually want > to have names for foreign keys more explicit than > fk<destinationEntityName><count> > > (You stated: > fk<destinationEntityName><destinationAttributeName><count> but since > the destAttr. will always be the same for a given dest. entity (the > PK), I removed it here) > >>> This could be as handy as the feature you submitted in your proposal: >>> automatic definition parent properties which are not overriden in >>> sub-entities. >> >> Yes. Auto generation of foreign keys from a relationship definition >> does >> make sense in fact... but the possibility to declare them explicitly >> (with >> the desired values for their attributes) should always be there. Since >> such explicit declaration can be very simple, I prefer to leave it as >> must be explicit. > > My opinion here is: > > - make it possible to automate the simple case (PK and FK), as > explained above, > > - always keep the possibility to explicitly write every single > properties in models, entities, etc. Here i think the second point is more important than the first, and will not limit unneccessarily what the framework can handle. The first point is nice, maybe, but since these would be so simple to declare, there is not so much to gain. > You might think that I'm definitely reluctant to impose explicit > declarations (such as for the FK). I think I am but it's not a > religion ;) Well, i can understand that in an ideal world the "db details" are all handled automatically, and inded you cannot get to them. But unless full automation can be guaranteed, then going this route may cause more problems than it solves. And, will not handle existent databases. "Optional automation" is OK, but i feel one should always be able to override it. On the same line, i also feel that an object id should optionally be manually set by the client code.In 90% (or more) of the time you just want it automatic, but sometimes you may want to control it (for db optimization or whatever other reasons). > In fact, it's really a matter of usual practices in E-R modeling. This > is not only /my/ practice, but the way most people seem to deal with > entity-relationship modeling --they do not care about the db-schema > PK/FK details unless they need to, for example when defining a model > for > an existing model, or when some complex design is required (just like > the one I described above). > > Obviously this observation was not made on that framework (there are > still not enough people using it for such an observation), but it is > what I observed from the community using the original Apple's > Enterprise > Object Framework(tm). > > I'm possibly wrong and maybe I just think that people do not care > because most of the times *I* usually don't care. In the ZModeler I > added the ability to make the two relationships necessary for a > one-to-many association at a single-click reach for that very reason: > it's a valuable feature to my own eyes, and I think it may be for > other's. I agree that *most* of the time you want all these things to be managed automatically. But, again, as long as full automation cannot be guaranteed, one should always allow the possibility to do whatever the db allows you to, as long as one takes responsibility for it. This is also similar to python's way of doing things (that of not "forcing" that variables are private for example) and has turned out to be one of the strong points of the language (that whatever unforeseen situation may arise, you are not locked in). > Last comment on this: I do not really like the idea of imposing the > FK > to be declared while having a implicit default for the PK, it sounds > inconsistent to me. Yes, here i agree. I am fine with not requiring that FKs are declared explicitly, and the framework handles their definition automatically. But the framework should also recognize if the FKs are declared and and create them accordingly. ... >> Oh, and some other changes I have not mentioned here are listed in >> the top of PyModel_3_mr.py, but mostly name changes, and having >> entities have only one list, that mixes attributes and relations... >> (your opinion?). > > * deleteRule -> delete: ok > > * multiplicity lower/upper bound -> multiplicity as a python list: ok > > * entity only has attributes that may also be relations: I'm ok for the > principle, however i would prefer an distinct term for this, > relations > being attributes could be a source of confusion. Maybe 'properties' ? OK for me. > More comment on this: having attributes and relations mixed in a > common list will require extra-checks when analysing the model to > perform the possibly needed automated steps. This is because we > will > need to have all the entities and their attributes loaded and > processed before we can make a decision on whether a declared > relation needs automatic generation of FK. We will need to separate > attributes from relations anyway. When processing atts and rels, the logic would be to assign them to 2 different arrays, and work with those arrays. > I do not mean this is complex: it's not. However I'm not sure this > enhance readability. In the sample model your clearly first declared > attributes, than relationships, and I bet everyone will do it that > way, because it would be a real mess to have some attrs, than rels, > than attrs, etc. Well, some may prefer to group in some other logical way than by type... But, my main reason for this is that have to deal with extra list brackets inside the Entity constructor may be avoided, making the code a little more readable. > * misc.: at some point in the discussion the FK were made class > properties in the py-model, but they should not! Ooops, mistake. > > Regarding PyModel_3_mr.py: > > - I'm not sure we want a default for entity.adaptorName You mean model? OK, no problem. > - I'd add a APrimaryKey subclass of Attribute OK. The updated sample (4) is below, but you can also get to it, along with the new PyModel version (4) from http://ruggier.dyndns.org:8080/PyModel/ Cheers, mario ''' 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 type Model ''' from PyModel import * ## # Set preferred defaults for this model (when different from # standard defaults, or if we want to make things explicit) AInteger.defaults['precision'] = 10 AString.defaults['width'] = 20 RToOne.defaults['delete'] = 'cascade' RToOne.defaults['multiplicity'] = [0,1] RToOne.defaults['sourceAttribute'] = RToOne.attNameFromRel # 'fk'+destEnt+destAtt+count RToOne.defaults['destinationAttribute'] = 'id' RToMany.defaults['delete'] = 'deny' RToMany.defaults['multiplicity'] = [0,None] RToMany.defaults['sourceAttribute'] = 'id' RToMany.defaults['destinationAttribute'] = RToMany.attNameFromRel # fk+destEnt+sourceAtt+count # Note that Relation.attNameFromRel is a callable, that calculates the att name # from the indicated pieces (where count to distinguish between multiple relations # between same source and target Entity.defaults['properties'] = [ APrimaryKey('id', isClassProperty=0, isRequired=1) ] ## _connDict = {} model = Model('StoreEmployees',connDict=_connDict) model.entities = [ # Entity('Store', properties=[ AString('corporateName', isRequired=1), RToMany('employees', 'Employee') ] ) # Employee and its subclasses SalesClerk and Executive Entity('Employee', properties=[ AString('lastName', isRequired=1, usedForLocking=1), AString('firstName', isRequired=1, width=50, usedForLocking=1), AForeignKey(Attribute.fk('Store'), isClassProperty=0), RToMany('toAddresses', 'Address', delete='cascade'), RToOne('toStore', 'Store') ] ) Entity('SalesClerk', parent='Employee', properties=[ AString('storeArea') ] ), Entity('Executive', parent='Employee', properties=[ AString('officeLocation', width=5), RToMany('marks', 'Mark', delete='cascade') ] ), # Entity('Address', properties=[ AString('street', width=80), AString('zipCode'), AString('town', width=80), AForeignKey(Attribute.fk('Employee'), isClassProperty=0), RToMany('toEmployee', 'Employee', delete='deny') ] ), # Entity('Mark', properties=[ AInteger('month', isRequired=1), AInteger('mark', isRequired=1), AForeignKey(Attribute.fk('Executive'), isClassProperty=0), RToOne('executive', 'Executive' ] ] ) ] if __name__ == '__main__': print model.validate() print model.toXML() # plus whatever ... ## |
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: 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 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: 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: 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-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. |