modeling-users Mailing List for Object-Relational Bridge for python (Page 38)
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(3) |
Oct
|
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(19) |
Feb
(55) |
Mar
(54) |
Apr
(48) |
May
(41) |
Jun
(40) |
Jul
(156) |
Aug
(56) |
Sep
(90) |
Oct
(14) |
Nov
(41) |
Dec
(32) |
2004 |
Jan
(6) |
Feb
(57) |
Mar
(38) |
Apr
(23) |
May
(3) |
Jun
(40) |
Jul
(39) |
Aug
(82) |
Sep
(31) |
Oct
(14) |
Nov
|
Dec
(9) |
2005 |
Jan
|
Feb
(4) |
Mar
(13) |
Apr
|
May
(5) |
Jun
(2) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
2006 |
Jan
(1) |
Feb
(1) |
Mar
(9) |
Apr
(1) |
May
|
Jun
(1) |
Jul
(5) |
Aug
|
Sep
(5) |
Oct
(1) |
Nov
|
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
(1) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Brad B. <br...@bb...> - 2003-03-26 23:11:50
|
Hello, I sent this message to Sebastien who in his current busy state didn't have much time to provide a complete answer today, but in the meantime recommended I forward it on to the readers of the list. Feel free to comment! :) ----- Forwarded message from Brad Bollenbach <br...@bb...> ----- Date: Wed, 26 Mar 2003 13:55:23 -0600 From: Brad Bollenbach <br...@bb...> To: sbi...@us... Subject: Customizing autogenerated classes Hi Sebastien, First off, the obligatory praise for giving the Modeling framework to the Open Source community. It's not only cool and useful, but the code is immensely instructive and well-written (IMHO)...so thanks. :) Now, onto my question: How do I customize the business logic validation routines without my customizations getting blown away the next time I autogenerate the Python package (e.g. when I decide two months down the line that the app needs to be extended and five more tables need to be added)? I've read through many of your unit tests, and a few relevant bits of the code and come up with what I see being the four realistic options: 1. The obvious one: add code directly to autogenerated Python code. The problem here though, is that it's difficult to do the whole backup-and-merge dance when I autogenerate again in the future. It's also tedious to take the other route of only exporting the XML model every time, and maintaining the classes (and/or adding new ones, if applicable) to keep up with it. 2. Write an adoption utility function, e.g. def adoptByClass(adopter, entities) that will iterate over a list of entities (e.g. those fetched from an editing context) and map them to the class specified as the "adopter". The "adopter" could be a class that I've created that inherits from one of the auto-generated classes and overrides its validation methods with my custom logic. It's good because I can autogenerate again and again, but it's bad because then I'm always making calls to adoptByClass. 3. Manually validate (e.g. using MySQLdb directly). This would ignore a significant piece of functionality that's already been created as part of the Modeling framework, so this isn't reasonable. 4. Change an Entity's description so that it can have, perhaps both a baseclass *and* class attribute, where the baseclass attribute is the one that will get autogenerated and the class attribute is the only that I will code myself, overriding and extending the baseclass's methods as necessary. From the point of view of the person that designed this framework, what do you think of each of these options? Have I missed any? ----- End forwarded message ----- -- Brad Bollenbach BBnet.ca |
From: Sebastien B. <sbi...@us...> - 2003-03-26 21:23:08
|
soif> Is there a way to do a partial dispose. In fact soif> I have a problem with my EditingContext, as : soif> - The EC is never disposed to avoid fetching objects soif> at each web application request. (better performance) soif> - The only way to stop this is to call a ec.dispose() soif> but this drop all objects. soif> soif> After severals searches, I think the best for me, is soif> to do a partial dispose . Let's say object that are soif> in EC older than 10 minutes should be forget. soif> soif> Is there any plans to support things like this ? mario> I think Sebastien is waiting for real requests for this todo mario> item, to bump up its priority ;) Look at section 6.3.1 in the mario> users guide... Mario answered for me ;) soif> I tried to call ec.forgetObject(object) if object soif> is older than X min, but i get some really strange soif> AttributeError when i try to access objects that soif> i have forget. Woo-oo, you didn't read forgetObject()'s docstring, did you ?) It shouldn't be called. What you need is refaultObject() for which you'll find a patch at the end of the message. This is a somewhat dirty implementation, especially in DBContext.refaultObject(), but it works in a simple test also included at the end of the mail. Instruction of use: - do NOT call DabaseContext.refaultObject(), just ec.refaultObject - do NOT try to call it on inserted, updated or deleted objects, API: either ec.refaultObject(obj) or ec.refaultObject(anObject=obj) or ec.refaultObject(aGlobalID=gid) Last, when refaulting an object, all its properties are cleared (__init__ is called), hence you should not expect to find any attribute after it's been refaulted. This will probably not stay as-is, this is rude and dirty ; please experiment and tell what you think. BTW this is the first step towards what is exposed at the end of section 6.3.1 -- Sebastien. Index: EditingContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/EditingContext.py,v retrieving revision 1.21 diff -c -r1.21 EditingContext.py *** EditingContext.py 12 Mar 2003 15:45:54 -0000 1.21 --- EditingContext.py 26 Mar 2003 21:01:31 -0000 *************** *** 1013,1019 **** except AttributeError: return 0 ! def faultForGlobalID(self, aGlobalID, anEditingContext): """ Searches for an object registered within the EditingContext with the supplied GlobalID, and returns it if it is found. If not, forwards the --- 1013,1019 ---- except AttributeError: return 0 ! def faultForGlobalID(self, aGlobalID, anEditingContext=None): """ Searches for an object registered within the EditingContext with the supplied GlobalID, and returns it if it is found. If not, forwards the *************** *** 1021,1026 **** --- 1021,1029 ---- If anEditingContext is a child of self, """ + if anEditingContext is None: + anEditingContext=self + if anEditingContext.isaChildOf(self): # One of our child ECs forwarded the message if aGlobalID.isTemporary(): *************** *** 1215,1220 **** --- 1218,1252 ---- """ return self.parentObjectStore().ownsObject(anObject) + def refaultObject(self, anObject=None, aGlobalID=None, ec=None): + "TBD docstring refaultObject" + if ec is None: ec=self + + if ec is not self: + return self.parentObjectStore().refaultObject(anObject, aGlobalID, ec) + + obj=anObject ; gid=aGlobalID + if ( obj is None and gid is None ) or \ + ( obj is not None and gid is not None ): + raise ValueError, "Either parameter 'anObject' or 'aGlobalID' should be provided --not both" + if obj is None: + obj=self.objectForGlobalID(gid) + else: + gid=self.globalIDForObject(obj) + + if gid is None: + raise ObjectNotRegisteredError + if gid.isTemporary(): + raise ValueError, 'Cannot refault an newly created/inserted object' + + if gid in self._pendingUpdatedObjects+self._updatedObjects: + raise ValueError, 'Cannot refault a modified object' + if gid in self._pendingDeletedObjects+self._deletedObjects: + raise ValueError, 'Cannot refault a deleted object' + + #self.forgetObject(obj) + return self.parentObjectStore().refaultObject(obj, gid, self) + def saveChangesInEditingContext(self, anEditingContext): """ Called on the parent EditingContext when a child EditingContext saves *************** *** 1360,1365 **** --- 1392,1404 ---- self.recordObject(obj, key_gid) db=self.rootObjectStore().objectStoreForObject(obj).database() db.incrementSnapshotCountForGlobalID(key_gid) + # time to update object's PK if a PK is set as class properties + from ModelSet import defaultModelSet + entity=defaultModelSet().entityNamed(obj.entityName()) + pk_values=key_gid.keyValues() + for pk in entity.primaryKeyAttributes(): + if pk.isClassProperty(): + obj.takeStoredValueForKey(pk_values[pk.name()], pk.name()) else: obj=self.objectForGlobalID(gid) new_gid=notification.userInfo().get(gid) Index: ObjectStoreCoordinator.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ObjectStoreCoordinator.py,v retrieving revision 1.9 diff -c -r1.9 ObjectStoreCoordinator.py *** ObjectStoreCoordinator.py 14 Mar 2003 11:40:09 -0000 1.9 --- ObjectStoreCoordinator.py 26 Mar 2003 21:01:34 -0000 *************** *** 486,492 **** self.lock() try: store=self.objectStoreForObject(anObject) ! store.refaultObject(anObject, aGlobalID, anEditingContext) finally: self.unlock() --- 486,492 ---- self.lock() try: store=self.objectStoreForObject(anObject) ! return store.refaultObject(anObject, aGlobalID, anEditingContext) finally: self.unlock() Index: DatabaseContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseContext.py,v retrieving revision 1.14 diff -c -r1.14 DatabaseContext.py *** DatabaseContext.py 14 Mar 2003 11:40:07 -0000 1.14 --- DatabaseContext.py 26 Mar 2003 21:01:52 -0000 *************** *** 1489,1496 **** def refaultObject(self, aDatabaseObject, aGlobalID, anEditingContext): """ """ ! self.__unimplemented__() def rootObjectStore(self): """ --- 1489,1524 ---- def refaultObject(self, aDatabaseObject, aGlobalID, anEditingContext): """ + Do not call by hand -- please call EditingContext.refaultObject() + instead """ ! ## TBD roughly copy/pasted from faultForGlobalID() ! ## TBD It should be fixed -- we do not check anything wrt the ec and ! ## TBD Should we also really clear properties? We'll see ! try: ! entityName=aGlobalID.entityName() ! except AttributeError: ! raise ValueError, \ ! "Parameter aGlobalID does not responds to message 'entityName()'" ! cd=ClassDescription.classDescriptionForName(entityName) ! ! cd_root=cd.rootClassDescription() ! root_keyGlobalID=KeyGlobalID(cd_root.entityName(), aGlobalID.keyValues()) ! ! anEditingContext.forgetObject(aDatabaseObject) ! faultHandler=AccessFaultHandler(root_keyGlobalID, self, ! anEditingContext) ! #aDatabaseObject.clearProperties() ! aDatabaseObject.__init__() ! aDatabaseObject.turnIntoFault(faultHandler) ! trace('Registering fault w/ GlobalID: %s'%str(root_keyGlobalID)) ! anEditingContext.recordObject(aDatabaseObject, root_keyGlobalID) ! # inheritance support ! trace('Adding ec as an observer for GlobalIDChangedNotification & GlobalID: %s'%root_keyGlobalID) ! NC.addObserver(anEditingContext, EditingContext.handleNotification, ! GlobalIDChangedNotification, root_keyGlobalID) ! return aDatabaseObject ! def rootObjectStore(self): """ ------------------------------------------------------------------------ Optionally, add this to tests/test_EditingContext_Global.py def test_19_refaultObject(self): "[EditingContext] refaultObject()" ec=EditingContext() qualifier=qualifierWithQualifierFormat('lastName=="Rabelais"') fetchSpec=FetchSpecification(entityName='Writer', qualifier=qualifier) rabelais=ec.objectsWithFetchSpecification(fetchSpec)[0] db=ec.rootObjectStore().objectStoreForObject(rabelais).database() gid=ec.globalIDForObject(rabelais) lastName=rabelais.getLastName() # trigger fault self.failIf(rabelais.isFault()) self.failUnless(db.snapshotForGlobalID(gid)) ec.refaultObject(rabelais) self.failUnless(rabelais.isFault()) self.failIf(db.snapshotForGlobalID(gid)) lastName=rabelais.getLastName() # trigger fault again self.failIf(rabelais.isFault()) ------------------------------------------------------------------------ |
From: Sebastien <sbi...@us...> - 2003-03-26 20:14:01
|
Hi, so...@la... wrote: > I think S=E9bastien is busy right now, and I hope he > find clear this point. Alas, sorry for not being more reactive, but that's right, I'm really busy these days. > Ansering myself, >=20 > I found the way to avoid this issue by using=20 > ec.lock() and ec.unlock() at each web app request. > (not really usefull for a threaded web app !!)=20 >=20 >=20 > But i really think the doc, isn't clear about this=20 > point. In fact i think that all operation on a=20 > ec should be locked, even fetching ( !=3D the doc ). > Cause if you don't, you will get some strange=20 > behaviours meanly in the database adapator, that > cause a segfault in the mysql one. You're right indeed. Here is the problem: >>> import MySQLdb >>> MySQLdb.threadsafety 1 Quoted from http://www.python.org/topics/database/DatabaseAPI-2.0.html: threadsafety Integer constant stating the level of thread safety the interface supports. Possible values are: 0 =3D Threads may not share the module. 1 =3D Threads may share the module, but not connections. 2 =3D Threads may share the module and connections. 3 =3D Threads may share the module, connections and cursors. Hence the problem, because the framework shares a single connection among threads. And you're right when you say that the documentation is not clear on that point. In fact, I wrote it with psycopg in mind (threadsafety=3D=3D2) and it is definitely *wrong* as far as MySQLdb is concerned; same for pgdb and pypgsql, btw --all but psycopg in fact ): However, as usual ;) the behaviour you reveal is a bug, not a feature. The framework should either: - automatically lock/unlock the shared connection --this solution would be equivalent to your ec.lock/unlock(), but the period of locking will be somehow smaller than when locking the ec - or use a different connection for each thread -- I expect this to=20 be longer to implement than the first solution. Could you please fill in a bug report (category: core) ? I'll try to have a look at it and propose a solution in the next two weeks, but I cannot promise since I've very little time at the moment. In the meantime, your solution is correct, and it's the only one. Cheers, -- S=E9bastien. |
From: Mario R. <ma...@ru...> - 2003-03-26 17:19:20
|
I think Sebastien is waiting for real requests for this todo item, to bump up its priority ;) Look at section 6.3.1 in the users guide... mario > > Is there a way to do a partial dispose. In fact > I have a problem with my EditingContext, as : > - The EC is never disposed to avoid fetching objects > at each web application request. (better performance) > - The only way to stop this is to call a ec.dispose() > but this drop all objects. > > After severals searches, I think the best for me, is > to do a partial dispose . Let's say object that are > in EC older than 10 minutes should be forget. > > Is there any plans to support things like this ? > > I tried to call ec.forgetObject(object) if object > is older than X min, but i get some really strange > AttributeError when i try to access objects that > i have forget. > > > > Thanks for any help :) |
From: <so...@la...> - 2003-03-26 16:13:50
|
On Thu, Mar 20, 2003 at 02:53:28PM +0100, so...@la... wrote: Ansering myself, I found the way to avoid this issue by using=20 ec.lock() and ec.unlock() at each web app request. (not really usefull for a threaded web app !!)=20 But i really think the doc, isn't clear about this=20 point. In fact i think that all operation on a=20 ec should be locked, even fetching ( !=3D the doc ). Cause if you don't, you will get some strange=20 behaviours meanly in the database adapator, that cause a segfault in the mysql one. I think S=E9bastien is busy right now, and I hope he find clear this point. -- |
From: <so...@la...> - 2003-03-26 16:04:01
|
Is there a way to do a partial dispose. In fact I have a problem with my EditingContext, as : - The EC is never disposed to avoid fetching objects at each web application request. (better performance) - The only way to stop this is to call a ec.dispose() but this drop all objects. After severals searches, I think the best for me, is to do a partial dispose . Let's say object that are in EC older than 10 minutes should be forget. Is there any plans to support things like this ? I tried to call ec.forgetObject(object) if object is older than X min, but i get some really strange AttributeError when i try to access objects that i have forget. Thanks for any help :) |
From: <so...@la...> - 2003-03-20 13:53:37
|
Is get a strange problem on heavy stress, while using MySQL. In short, I have some servlet (several thread) working on the same EC. When i do several request at the same time (no insertObject/saveChanges() ) the Adapator storage raise a exception : 'Connection Lost to the MySQL server'. Perhaps i miss something in the documentation. From the doc: "the framework is supposed to ensure that any operations made on an EditingContext is safe in a multi-threaded environment (given that the EditingContext is not shared between threads, obviously)." So how should I use the EC in threading env without sharing an ec ? |
From: Sebastien B. <sbi...@us...> - 2003-03-18 01:39:51
|
I wrote: > You then just have to request ec.faultForGlobalID() with the gid and > you get your object back. >=20 > This does not work with temporary GlobalIDs, but if you're not going > to use any sessioning mechanism as stated in your first message then > you'll probably do not need to refer to inserted but unsaved > objects! And this would maybe appear more straightforward than having to build a FetchSpec based on the id, wouldn't it?-) soif> Hy all, so this is for big take a look at http://larsen-b.com=20 soif> As you can see, i got modeling working well :)=20 That's nice. I roamed a bit around the cvsweb ; now you can get rid of Article.getID() and its ugly docstring ;) More seriously what I said in the previous msg. about using GlobalIDs would make it possible to serve objects from a single generic manager, rather than from a dedicated one for each ''type'' of id (such as in ArticlesManager.getArticleWithID()). My .02.=20 This should also appear in a FAQ I guess. Now time to sleep! Cheers, -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-03-18 01:22:49
|
[snip] > >=20 > > You are using getId() (returning article._id) instead of getID() > > (returning the PK value stored in its GlobalID) ! > >=20 > >=20 > > However, we have a bug here: Article's PK did not get its value. >=20 >=20 > Yeah you got it :)=20 > If don't use the id as classProperty as said in the doc, and use=20 > the getID() helper sent before on the list it works well :)=20 I included a small patch at the end of the message to solve this issue --I'll make the unittest tomorrow and will correct this on the cvs rep. Now article._id should get its value as expected after ec.saveChanges(), if it's set as a class property. > I guess I win one more point in my debugging level :)=20 . The Evil Bug is struck down by a Mighty Patch=20 . You find an Inquisition Helmet +22 in the Evil Bug's treasure room ;) Thanks for the report, hopefully everything is ok now. BTW and back to your original question, why don't you use GlobalIDs rather than raw id number? This needs some pre- and post-processing if you need to pass them as strings in a http POST e.g., but you'll gain a generic scheme then. I remember using this transformation you might find handy: KeyGlobalID -> '<entityName>#<pk1name>#<pk1value>[#...]' and back (splitting with '#') i.e. something like that: def gid_to_str(gid): if gid.isTemporary(): raise ValueError, 'TemporaryGlobalIDs are not supported' gid_str=3Dgid.entityName() for pk,value in gid.keyValues().items(): gid_str+=3D'#%s#%s'%(pk, value) return gid_str =20=20=20=20=20=20 def str_to_gid(str): import string l=3Dstring.split(gid_str, '#') l.reverse() d=3D{} name=3Dl.pop() while l: d.setdefault(l.pop(), int(l.pop())) from Modeling.GlobalID import KeyGlobalID return KeyGlobalID(name, d) You then just have to request ec.faultForGlobalID() with the gid and you = get your object back. This does not work with temporary GlobalIDs, but if you're not going to use any sessioning mechanism as stated in your first message then you'll probably do not need to refer to inserted but unsaved objects! -- S=E9bastien. ------------------------------------------------------------------------ Index: EditingContext.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/EditingContext.py,v retrieving revision 1.21 diff -c -r1.21 EditingContext.py *** EditingContext.py 12 Mar 2003 15:45:54 -0000 1.21 --- EditingContext.py 18 Mar 2003 00:29:39 -0000 *************** *** 1360,1365 **** --- 1360,1372 ---- self.recordObject(obj, key_gid) db=3Dself.rootObjectStore().objectStoreForObject(obj).database() db.incrementSnapshotCountForGlobalID(key_gid) + # time to update the object if a PK is set as class properties + from ModelSet import defaultModelSet + entity=3DdefaultModelSet().entityNamed(obj.entityName()) + pk_values=3Dkey_gid.keyValues() + for pk in entity.primaryKeyAttributes(): + if pk.isClassProperty(): + obj.takeStoredValueForKey(pk_values[pk.name()], pk.name()) else: obj=3Dself.objectForGlobalID(gid) new_gid=3Dnotification.userInfo().get(gid) ------------------------------------------------------------------------ |
From: <so...@la...> - 2003-03-17 23:49:58
|
On Tue, Mar 18, 2003 at 12:33:32AM +0000, Sebastien Bigaret wrote: > > so...@la... wrote: > > On Mon, Mar 17, 2003 at 07:24:04PM +0100, so...@la... wrote: > > > That is really strange. I just made the very same thing with one of the > framework's testPackage and everything seems all right: > > >>> from Modeling.EditingContext import EditingContext > >>> from Modeling.FetchSpecification import FetchSpecification > >>> from testPackages.AuthorBooks.Book import Book > >>> b=Book() > >>> b.setTitle('blah') > >>> ec=EditingContext() > >>> ec.insertObject(b) > >>> ec.saveChanges() > >>> ec.globalIDForObject(b).keyValues()['id'] > 63L > > > ...wait... Oh, ok, now I see: > > >>> from Modeling.EditingContext import EditingContext > >>> from Modeling.FetchSpecification import FetchSpecification > >>> from testPackages.AuthorBooks.Book import Book > >>> b=Book() > >>> b.setTitle('blah') > >>> ec=EditingContext() > >>> ec.insertObject(b) > >>> ec.saveChanges() > >>> ec.globalIDForObject(b).keyValues()['id'] > 64L > >>> b._id > 0 > > You are using getId() (returning article._id) instead of getID() > (returning the PK value stored in its GlobalID) ! > > > However, we have a bug here: Article's PK did not get its value. Yeah you got it :) If don't use the id as classProperty as said in the doc, and use the getID() helper sent before on the list it works well :) I guess I win one more point in my debugging level :) |
From: Sebastien B. <sbi...@us...> - 2003-03-17 23:33:12
|
so...@la... wrote: > On Mon, Mar 17, 2003 at 07:24:04PM +0100, so...@la... wrote: > >=20 > >=20 > > I get one question:=20 > > how could i get the id for an object (I ever see this=20 > > on the list, but i miss it). cause while working on=20 > > web using real objects (read between two transaction) > > is impossible without using user session, so i think=20 > > working on id is a nice way to solve this for me.=20 > > I know that working on id is a bad habit but ..=20 >=20 > Answering myself. The doc says : > "you shouldn't need to expose the PK values as class' attributes. But, > ok, if you really want to do that, that is to say, if you declare them > as class properties, "=20 >=20 > That 's what i did, but this is wrong too, let read this=20 > snapshot: >=20 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > from mortal.Objects.Article import Article > from Modeling.EditingContext import EditingContext > from Modeling.FetchSpecification import FetchSpecification >=20 > # creating a new object > ec =3D EditingContext() > article =3D Article() > article.setText('Oups') > article.setTitle('Again') > ec.insertObject(article) > ec.saveChanges() >=20 > # fetching the last inserted=20 > fetchSpec=3DFetchSpecification(entityName=3D'Article') > ec.objectsWithFetchSpecification(fetchSpec)[-1] > <mortal.Objects.Article.Article instance at 0x85cfd44> > ec.objectsWithFetchSpecification(fetchSpec)[-1].getId() > # <---> the id is 0 cause the fetch isn't done here. > 0=20 > ec.dispose() > # <--> after a dispose it's work .=20 > ec.objectsWithFetchSpecification(fetchSpec)[-1].getId() > 26L > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D That is really strange. I just made the very same thing with one of the framework's testPackage and everything seems all right: >>> from Modeling.EditingContext import EditingContext >>> from Modeling.FetchSpecification import FetchSpecification >>> from testPackages.AuthorBooks.Book import Book >>> b=3DBook() >>> b.setTitle('blah') >>> ec=3DEditingContext() >>> ec.insertObject(b) >>> ec.saveChanges() >>> ec.globalIDForObject(b).keyValues()['id'] 63L ...wait... Oh, ok, now I see: >>> from Modeling.EditingContext import EditingContext >>> from Modeling.FetchSpecification import FetchSpecification >>> from testPackages.AuthorBooks.Book import Book >>> b=3DBook() >>> b.setTitle('blah') >>> ec=3DEditingContext() >>> ec.insertObject(b) >>> ec.saveChanges() >>> ec.globalIDForObject(b).keyValues()['id'] 64L >>> b._id 0 You are using getId() (returning article._id) instead of getID() (returning the PK value stored in its GlobalID) ! --> using getID() will probably make it. However, we have a bug here: Article's PK did not get its value. > 2) for an unknow reason right now, (perhaps i'll debug that)=20 > even calling dispose() on my ec don't force a re-fecht > in a real application I must check that, this is not a normal behaviour at all. article._id should have received its value. I'll check that. Seems you find one again ;) -- S=E9bastien. |
From: <so...@la...> - 2003-03-17 22:07:08
|
On Mon, Mar 17, 2003 at 07:24:04PM +0100, so...@la... wrote: > > > I get one question: > how could i get the id for an object (I ever see this > on the list, but i miss it). cause while working on > web using real objects (read between two transaction) > is impossible without using user session, so i think > working on id is a nice way to solve this for me. > I know that working on id is a bad habit but .. Answering myself. The doc says : "you shouldn't need to expose the PK values as class' attributes. But, ok, if you really want to do that, that is to say, if you declare them as class properties, " That 's what i did, but this is wrong too, let read this snapshot: =========================================================== from mortal.Objects.Article import Article from Modeling.EditingContext import EditingContext from Modeling.FetchSpecification import FetchSpecification # creating a new object ec = EditingContext() article = Article() article.setText('Oups') article.setTitle('Again') ec.insertObject(article) ec.saveChanges() # fetching the last inserted fetchSpec=FetchSpecification(entityName='Article') ec.objectsWithFetchSpecification(fetchSpec)[-1] <mortal.Objects.Article.Article instance at 0x85cfd44> ec.objectsWithFetchSpecification(fetchSpec)[-1].getId() # <---> the id is 0 cause the fetch isn't done here. 0 ec.dispose() # <--> after a dispose it's work . ec.objectsWithFetchSpecification(fetchSpec)[-1].getId() 26L ========================================================== 1) first i don't want to dispose each time i insert a new object cause this can really be time consumming 2) for an unknow reason right now, (perhaps i'll debug that) even calling dispose() on my ec don't force a re-fecht in a real application So do you have any idea on how shoud i try ? |
From: <so...@la...> - 2003-03-17 19:00:39
|
Hy all, so this is for big take a look at http://larsen-b.com As you can see, i got modeling working well :) I get one question: how could i get the id for an object (I ever see this on the list, but i miss it). cause while working on web using real objects (read between two transaction) is impossible without using user session, so i think working on id is a nice way to solve this for me. I know that working on id is a bad habit but .. Should i use something like ? ================================================================= class Article(CustomObject): [snip of generated] def getID(self): self.editingContext().globalIDForObject(o).keyValues()['id'] ================================================================= |
From: Sebastien B. <sbi...@us...> - 2003-03-17 14:50:34
|
Hi all, I've created a new branch today at noon, containing a first implementation for: - sorting objects w/ FetchSpecification.sortOrderings() at the SQL level =20=20=20=20 - limiting the number of objects fetched by EC.objectsWithFetchSpecification() after the different comments and requests that were submitted here. It is available for the postgresql and mysql adaptor layers. Status of the proposal: ----------------------- The sorting mechanism and the slicing scheme are for the moment proof-of-concept implementation. They both suffer from different drawbacks (described below) that needs to be eliminated before this is merged in the main trunk. They will both probably needs more use-cases and trial-and-errors before we get to the final implementation. How it works ------------ Examples of use are given in tests/test_EditingContext_Global.py, methods test_17_fetchSpecWithSortOrderings() and test_18_fetchSpecWithFetchLimit(), from which the following examples are extracted. IMPORTANT NOTE: the test-db for Author_Books needs to be cleaned and --------------- repopulated with new values for the new tests to pass. Simply execute './test_EditingContext_Global.py -r' and you'll be fine. * Ordering Basically, ordering a result consists in building one or more SortOrdering and giving it to the FetchSpecification: q=3DqualifierWithQualifierFormat('author.lastName !=3D NULL"') fs=3DFetchSpecification('Book', q) from Modeling.SortOrdering import \ SortOrdering, compareDescending, compareCaseInsensitiveAscending so0=3DSortOrdering('author.lastName', compareDescending) so1=3DSortOrdering('price', compareDescending) so2=3DSortOrdering('title', compareCaseInsensitiveAscending) fs.setSortOrderings([so0, so1, so2]) ec=3DEditingContext() objs=3Dec.objectsWithFetchSpecification(fs) Orderings are applied in the given order. * Fetch limit / slicing FetchSpecification now comes with an enhanced API, with the following methods: - setFetchSlice(limit, offset=3D0, page=3D1) Parameters offset and page are mutually _exclusive_ and they should be self explicative. Please note: offset starts at zero (0), page at one (1) - fetchSlice(): returns a mapping with keys 'limit' and 'offset' - fetchLimit(limit): alias for setFetchSlice(limit, offset=3D0) - getNext/PreviousSlice(): only available if setFetchSlice() was previously called w/ parameter 'page' Raises ValueError otherwise, or if you request the previous page when you already are at page 1. It simply recalcultes the offset, given the current limit.=20 Example of use --for full details cf.test_18_fetchSpecWithFetchLimit q=3DqualifierWithQualifierFormat('author.lastName !=3D NULL"') fs=3DFetchSpecification('Book', q) so1=3DSortOrdering('id', compareAscending) fs.setSortOrderings([so1]) ## !!! Important: see below !!! fs.setFetchSlice(2, page=3D1) objs=3Dec.objectsWithFetchSpecification(fs) # first page # [...] fs.getNextSlice() objs=3Dec.objectsWithFetchSpecification(fs) # second page # etc. You know that you reached the last page when you get zero objects. EC.objectsCountWithFetchSpecification() will give you an idea of how many pages you can possibly get. =20=20=20=20 Known problems / possible evolutions / open questions ----------------------------------------------------- - defining a SortOrdering this way seems a bit painful. I wonder whether we should design a little parser in FS.setSortOrderings() for supplying them as strings, maybe something like: "author.lastName asc, price desc, title iasc" - there is no default order applied to the result set when using fetchSlice(); it is your responsability to specify a specific order [such as: SortOrdering('id', compareAscending)] to your FetchSpecification before requesting a first batch and the subsequents ones, or you'll probably get inconsistent subsets. This might change in the future. E.g. a default ordering on the primary key will probably be added if no other orderings is specified, or maybe it could be added to any existing orderings as well. - Sorting does NOT work when inheritance is taken into account, i.e. if you set FetchSpecification's 'isDeep' flag to true --you'll get n*limit results in each batch, n being the number of subclasses(+1) of the current Entity. Moreover the batches will not be sorted as a whole, but they will be made of sorted subsets coming from the different sub-entities. - if you fetch slices against an EC that has some inserted and/or deleted objects (for the entity you're fetching): - deleted objects will not appear, so you may get less objects than expected, - inserted objects will appear in each batch. This is a problem in itself, and a second one because in that case, you'll *never* get zero object after e.g. fs.getNextSlice() The last two problems (inheritance & inserted objects) are real problems, not easy to solve. I can vaguely see some different way to solve them but this would require a big refactor of the fetching process, or a second fetching scheme for slicing fetches only. For the moment I'm not positively sure that this is worth the effort ; however I'm also reluctant in leaving that as-is since it would mean two different semantics for ec.objectsWithFetchSpecification() depending on the FetchSpecification itself. How to get it: ------------- I won't make any public release for this, please use cvs. To check-out a new copy of this branch, you'll have to: $ cvs -d:pserver:ano...@cv...:/cvsroot/modeling login (empty password) $ cvs -d:pserver:ano...@cv...:/cvsroot/modeling checkout -= r brch-0_9pre5-SQL_SortOrdering_and_LIMIT ProjectModeling or use 'cvs update -r brch-0_9pre5-SQL_SortOrdering_and_LIMIT' in your working copy if you've already checked out the main trunk. Future ------ I'll probably not work on this until I get some feedbacks. BTW none of these features will be integrated before 0.9 is released (feature-freeze until then!). Please share any questions/critics/comments/proposals/etc. this proposal inspires you --even if you do not have the time to actually test it, you may have interesting comments for the discussion :) Enjoy sorting & happy slicing! -- S=E9bastien. |
From: Jerome K. <Jer...@fi...> - 2003-03-14 12:13:01
|
On Fri, Mar 14, 2003 at 10:18:07AM +0100, Sebastien Bigaret wrote: > > > > So next step for me is to fix a bug in performsChanges, about > > a unkown externalType: TEXT > > > > I just cut/paste the traceback here, i gonna check this closely > > Hey, it seems that the TEXT sql datatype is very popular w/ ya mysql folks! Ho yes, cause MySQL doesn't support VARCHAR > 255 so using TEXT is a nice way to solve this. > It's been reported a few days ago by Yannick (see the archives) and it has > been corrected against MySQLSQLExpression v1.5 > > http://sourceforge.net/mailarchive/forum.php?thread_id=1791045&forum_id=10674 > http://sourceforge.net/mailarchive/forum.php?thread_id=1791817&forum_id=10674 > http://sourceforge.net/mailarchive/forum.php?thread_id=1794342&forum_id=10674 Ho i miss that. Tomorow i will buy some glasses, it might help . > (BTW and OT if someone has an idea on why my replies never get > archived within the same thread than the message I'm replying to, > I'll be grateful) Perhaps check that your mailer don't drop the In-Reply-To: <874...@bi...h> in the mail header |
From: Sebastien B. <sbi...@us...> - 2003-03-14 10:52:39
|
Hi all, I've just released 0.9-pre-4, the second release candidate for 0.9. Both packages modeling-core and ZModeling are concerned; as usual the changelog is included at the end of the message. It contains fixes for bugs triggered by a basic use of nested EditingContext configuration, along with corrections made to the MySQL Adaptor Layer which is now fully functional (and supports TEXT :) A new Zope product is also introduced and documented, making it possible to get an EditingContext on a per-session basis: ZEditingContextSessioning. Last, a new chapter has been added to the User's Guide, ''Integration in an application'', which contains important informations on how the framework can be integrated in different software architecture (such as: in single- or multi-threaded environments, in pure-python apps or in app-servers like Zope). You'll also notice that the web-site has been reviewed and changed, thanks to Mario. I decided to make a second release candidate because there were quite a lot of bug-fixes checked-in after the last release; I thought it would be preferable to package them now and make an official release rather then waiting for 0.9 final. Before 0.9 final is released, some documentation still needs to be written and/or enhanced (projet's status, contributors). Enjoy! -- S=E9bastien. ------------------------------------------------------------------------ 0.9-pre-4 (2002/03/14) Second release candidate for 0.9 --------- * Documentation: - The web-site has been reviewed and re-organized, thanks Mario! - Added chapter ''Integration in an application'' to the User's Guide * EditingContext + saveChangesInEditingContext(): now locks 'self' before proceeding, so that two nested \class{EditingContext} which have the same parent and are managed by two different threads can concurrently save their changes to their parent without explictly locking it. (this is logical since a EC is supposed to perform any of its operations safely in a multi-threaded environment --given that it's not shared between threads, obviously) + Fixed objectsWithFetchSpecification(): when a nested EC asks for objects, the result set now correctly includes objects that are inserted in its parent (or grand-parent, etc.) and objects that are marked as deleted in the parent are excluded. See also: tests.test_EditingContext_ParentChild, test_10_child_gets_newly_inserted_objects() and test_11_child_doesnt_get_deleted_objects() * Added Modeling.utilities.EditingContextSessioning * Changed _invalidatesObjectsWhenFinalized to invalidatesObjectsWhenFinalized, and made it a class member. Added documentation on this, see the User's Guide, section ''Discarding changes: details on the destruction process of an EditingContext'' (doc/UserGuide/ManipulatingGraphOfObjects.tex) * Added 'TEXT' as a valid sql datatype for the MySQL adaptor * Proposed a fix for bug #614261: because of mysql having a strict syntax for sql statements containg JOINs, the default statement produced by SQLExpression led to a syntax error as soon as the supplied qualifier contained a keypath referencing two or more entities, such as in 'pygmalion.books.title'. The bug-item is not closed, waiting for people using the mysql adaptor to confirm it behaves as expected. See also: test_EditingContext_Global.test_14_qualifierWithNullValue= () & test_11_allQualifierOperators() * Bug #699046: when an invalid sql data type is encountered at runtime, the message is now much more informative than it used to be (i.e. it now indicates clearly where the error comes from) cf. SQLExpression v1.14 * Bug #699272: Fixed DBChannel.selectCountObjectsWithFetchSpecification: was not closing the underlying adaptorChannel when finished Related tests added: in test_EditingContext_Global.py, test_01c_objectsWithFetchSpecification_closes_adaptorChannel() test_13b_objectsCountWithFetchSpecification_closes_channel() Note: this made a bug triggered in psycopg when two threads are using the same cursor more likely to happen (when used in Zope e.g.) See discussion at http://lists.initd.org/pipermail/psycopg/2003-March/001885.ht= ml ------------------------------------------------------------------------ |
From: Sebastien B. <sbi...@us...> - 2003-03-14 09:17:13
|
=20=20=20=20=20=20=20=20 > So next step for me is to fix a bug in performsChanges, about=20 > a unkown externalType: TEXT >=20 > I just cut/paste the traceback here, i gonna check this closely Hey, it seems that the TEXT sql datatype is very popular w/ ya mysql fo= lks! It's been reported a few days ago by Yannick (see the archives) and it = has been corrected against MySQLSQLExpression v1.5 http://sourceforge.net/mailarchive/forum.php?thread_id=3D1791045&forum_= id=3D10674 http://sourceforge.net/mailarchive/forum.php?thread_id=3D1791817&forum_= id=3D10674 http://sourceforge.net/mailarchive/forum.php?thread_id=3D1794342&forum_= id=3D10674 (BTW and OT if someone has an idea on why my replies never get archived= within the same thread than the message I'm replying to, I'll be grateful) > Seb: Do you still call me bug-hunter ? > Baby one more time :) (c)Britney Spears C'mon... Seems you did it again! Cheers & happy TEXTing -- S=E9bastien. |
From: Jerome K. <Jer...@fi...> - 2003-03-14 00:32:00
|
On Fri, Mar 14, 2003 at 01:07:16AM +0100, so...@la... wrote: Answering to myself :) So i just discover that Modeling doesn't support TEXT type as externalType. It sound strange but, i haven't read the doc about a couple of months so perhaps i will find that somewhere. Anyway i managed to made it work by just adding 'text': CharacterType in MySQLSQLExpression.py and this works fine. Seb could you explain ? Anyway it works nice :) Merci Seb ! |
From: <so...@la...> - 2003-03-14 00:08:21
|
So, i'm back from my modeling test on MySQL. First, Modeling is still a paintfull to install, mainly the ZModeling cause i have to recompile - MySQLdb - mxDateTime - 4Suite & PyXML cause the current python on Zope is the 2.1. Anyway, after a bit of compiling, i get all working fine, and this is pretty kool ! So next step for me is to fix a bug in performsChanges, about a unkown externalType: TEXT I just cut/paste the traceback here, i gonna check this closely =============================================================== File "/home/soif/lib/python2.2/site-packages/Modeling/EditingContext.py", line 680, in saveChanges self.parentObjectStore().saveChangesInEditingContext(self) File"/home/soif/lib/python2.2/site-packages/Modeling/ObjectStoreCoordinator.py",line 559, in saveChangesInEditingContext raise RuntimeError, _error RuntimeError: performChanges() failed on <Modeling.DatabaseContext.DatabaseContext instance at 0x85314e4>: exceptions.ValueError:Unknown value type: None for externalType: TEXT (attribute: Article.text) =============================================================== Changing from a TEXT to VARCHAR works. Seb: Do you still call me bug-hunter ? Baby one more time :) (c)Britney Spears |
From: Yannick G. <ygi...@yg...> - 2003-03-08 14:01:34
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Saturday 08 March 2003 08:44, Yannick Gingras wrote: > OK it's really confusing because it alway talk about Acromynes wich > is a mistake Ehh I mean Anagrams... - -- Yannick Gingras Coder for OBB : Ornamented Bibliothecal Blackfish http://OpenBeatBox.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+afY3rhy5Fqn/MRARAk6GAJ9r0uWpnad/pIhBfItsqFZ5ynB0WgCcCtOi hAIj8cSnzOEKSJFwTHeJoAs= =ocoD -----END PGP SIGNATURE----- |
From: Yannick G. <ygi...@yg...> - 2003-03-08 13:44:41
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Saturday 08 March 2003 07:47, Sebastien Bigaret wrote: > > On Friday 07 March 2003 03:34 pm, Mario Ruggier wrote: > > > After looking at the Modeling sourceforge page so many times, the > > > initials of MORBY (approximately), for Modeling OR-Bridge for Python, > > > start to stand-out... but, this could be not such a bad unique name (in > > > lowercase, of course) for the framework. However, this also makes > > > other, cuter, names come to mind, such as Morfy (where the bridge > > > becomes a framework) that in turn brings to mind the action of > > > morphing (relational data to objects, and back), which points to > > > another possible name, Morphy, for Modeling, Object-Relational > > > Phramework for Python ;-) Which, in turn, would beg that an > > > OR model be called a MetaMorphy... Hmmn, mario > > > > I really like Morphy ! > > Guys, this seems a good idea! I like it too, it has a great resonance. > After letting my brain wandering on that while drinking coffees, I came to > Morph, Morpheus, and ten minutes later: Morphia, for something like: > ''Morphia: an Object-Relational Philter of Addiction'' --then I guess I > must admit that I have a weakness for auto-referent/recursive acronyms :). > > My .02c! I have the feeling that these wanderings may eventually find a > cool name for the fr... oops, phramework ;) How about ORCHYDE: Object-Relational Class HierarachY Definitive Ecosystem I also have this small script that we use on the OBB website for generating random but coherant acronymes. OK it's really confusing because it alway talk about Acromynes wich is a mistake but the script was already finished when I realised... It support fetching word from a dict server (which is really too slow) and from a worldnet database that should be extracted in ./wndict . It works best with short (3 or 4 letters) words. Typical usage : $ python OBBAnagramer.py updatewn $ python OBBAnagramer.py generate Anyway, here it is : #!/usr/bin/python # Copyright (C) 2002 Yannick Gingras <ygi...@yg...> # This file is part of Open Beat Box. # Open Beat Box is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # Open Beat Box is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with Open Beat Box; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import re import sys import traceback import thread from pickle import Pickler, Unpickler import time from random import Random import os import os.path #SERVER = "dict.org" #SERVER = "www.hyperdictionary.com" SERVER = "localhost" WN_DIR = "wndict" WORDS_FILE = "obb_words.ana" NB_THREAD = 5 V = "v." N = "n." ADJ = "a." ADV = "adv." O = "o" B = "b" MAX_ACRONYMES = 20000 #WORD = (O, B, B) WORD = ("b", "i", "t", "c", "h") #LETTERS = (O, B) LETTERS = WORD """ ANAGRAM_TYPES = [ (ADV, ADJ, N), # ( N, ADV, ADJ), (ADJ, ADJ, N), # ( N, V, N), # (ADJ, N, N), # (ADJ, N, ADJ) ] """ ANAGRAM_TYPES = [ (ADV, ADJ, ADJ, ADJ, N), (ADJ, ADV, ADJ, ADJ, N), (ADJ, ADJ, ADV, ADJ, N), (ADJ, ADJ, ADJ, ADV, N), (ADV, ADJ, ADV, ADJ, N), ] WORD_TYPE_REGEXES = { V: re.compile('.*\\, %s ' % V ), N: re.compile('.*\\, %s ' % N ), ADJ: re.compile('.*\\, %s ' % ADJ ), ADV: re.compile('.*\\, %s ' % ADV ) } WN_TYPE_INDEXES = { V: "index.verb", N: "index.noun", ADJ: "index.adj", ADV: "index.adv" } words = { V: [], N: [], ADV: [], ADJ: [] } # get words from a dict server def getRawWords(): from dictclient import Connection, TemporarilyUnavailable # 1st, get a list of the words print "Matching..." conn = Connection(SERVER) # restore corupted connection words = {} for letter in LETTERS: words[letter] = {} defs = conn.match("web1913", "prefix", letter) cnt = 0 for definition in defs: cnt += 1 try: detail = definition.getdefstr() word = definition.getword() words[letter][word] = detail print "Retreiving %4d of %d : %s" % (cnt, len(defs), word) except IndexError: conn = Connection(SERVER) # restore corupted connection except ValueError: conn = Connection(SERVER) # restore corupted connection except Exception, e: if str(e).find("Unknown code") != 1: conn = Connection(SERVER) # restore corupted connection else: raise return words def analyseWords(words): print "Analysing..." wordMap = {} for letter in words.keys(): wordMap[letter] = {} cnt = 0 # initialize the map for type in WORD_TYPE_REGEXES.keys(): wordMap[letter][type] = [] for word in words[letter].keys(): cnt += 1 print "Analysing %4d of %d : %s" % ( cnt, len(words[letter].keys()), word ) for type in WORD_TYPE_REGEXES.keys(): if WORD_TYPE_REGEXES[type].search(words[letter][word]): wordMap[letter][type].append(word) return wordMap # get the words from a World Net database # unlike with the dict servers, the WN DBs are well organised and it # eassy to know wich word is a noun, a verb... def getRawWordsWN(): # some init print "Matching..." words = {} for letter in LETTERS: words[letter] = {} for type in WN_TYPE_INDEXES.keys(): words[letter][type] = [] # reverse order from what we do with a dictd for type in WN_TYPE_INDEXES.keys(): typeIndex = open(os.path.join(WN_DIR, WN_TYPE_INDEXES[type])) record = typeIndex.readline() while record: letter = record[0].lower() if letter in LETTERS: word = record[:record.find(" ")] # skip the words with underscores if word.find("_") == -1: words[letter][type].append(word) record = typeIndex.readline() return words def printStats(wordMap): for letter in wordMap.keys(): print "%s:" % letter for type in wordMap[letter].keys(): print "%6s : %4d" % (type, len(wordMap[letter][type])) def genAnagram(wordMap): usageMap = {} # some init stuff for letter in WORD: usageMap[letter] = [] random = Random(time.time()) for anaType in ANAGRAM_TYPES: print "#" * 65 print "#\n" * 10, print "# Type : %s" % str(anaType) print "#\n" * 10, print "#" * 65 # we do not process all the possible possibilities, # when we generate a few already generated anagrams, # we have enough of them ; ) # we do this to spare us the job of shufeling the resulting list # (and maybe some time too...) nbClash = 0 nbAna = 0 maxClash = 5 anagrams = {} # hash are faster and we have a lot of records while nbClash < maxClash and nbAna < MAX_ACRONYMES: #for j in range(1000): anagram = () for i in range(len(WORD)): curType = anaType[i] curWordList = wordMap[WORD[i]][curType] anagram += (curWordList[random.randrange(len(curWordList))], ) if not anagrams.has_key(anagram): anagrams[anagram] = "" nbAna += 1 for i in range(len(WORD)): print "%s%s" % ( anagram[i][:1].upper(), anagram[i][1:].lower() ), print "" else: nbClash += 1 if sys.argv[1] == "update": wordList = getRawWords() wordMap = analyseWords(wordList) Pickler(open(WORDS_FILE, "w")).dump(wordMap) elif sys.argv[1] == "updatewn": wordMap = getRawWordsWN() Pickler(open(WORDS_FILE, "w")).dump(wordMap) elif sys.argv[1] == "check": print "Counting..." wordMap = Unpickler(open(WORDS_FILE)).load() printStats(wordMap) elif sys.argv[1] == "generate": wordMap = Unpickler(open(WORDS_FILE)).load() genAnagram(wordMap) else: print "USAGE : OBBAnagramer.py update|updatewn|check|generate" # # The END ! # - -- Yannick Gingras Coder for OBB : Organically Bimillenial Bob http://OpenBeatBox.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+afPDrhy5Fqn/MRARAoQyAJ9jNGvJkByG1L0xGe0qRJnjmARGOQCfRHJ/ 73SqSARor672EufWrz/oqls= =W4Va -----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-03-08 11:46:39
|
> On Friday 07 March 2003 03:34 pm, Mario Ruggier wrote: > > After looking at the Modeling sourceforge page so many times, the > > initials of MORBY (approximately), for Modeling OR-Bridge for Pytho= n, > > start to stand-out... but, this could be not such a bad unique name= (in > > lowercase, of course) for the framework. However, this also makes > > other, cuter, names come to mind, such as Morfy (where the bridge > > becomes a framework) that in turn brings to mind the action of > > morphing (relational data to objects, and back), which points to > > another possible name, Morphy, for Modeling, Object-Relational > > Phramework for Python ;-) Which, in turn, would beg that an > > OR model be called a MetaMorphy... Hmmn, mario >=20 > I really like Morphy ! Guys, this seems a good idea! I like it too, it has a great resonance. = After letting my brain wandering on that while drinking coffees, I came to Mo= rph, Morpheus, and ten minutes later: Morphia, for something like: ''Morphia= : an Object-Relational Philter of Addiction'' --then I guess I must admit th= at I have a weakness for auto-referent/recursive acronyms :). My .02c! I have the feeling that these wanderings may eventually find= a cool name for the fr... oops, phramework ;) -- S=E9bastien. |
From: Sebastien B. <sbi...@us...> - 2003-03-08 11:19:31
|
Jerome Kerdreux <Jer...@fi...> writes: > On Fri, Mar 07, 2003 at 10:53:08AM +0100, Sebastien Bigaret wrote: > >=20 > > It seems that the problem is triggered when the same psycopg cursor= is > > used in two different threads. >=20 >=20 > This is really sound strange as, i know zope use medusa asyncore, and= =20 > this avoid the use of thread (for the http..) so how could you achieve > to have several thread using the same db connection. ?=20 >=20 You made me doubt about this, but I checked and Zope does use threads indeed. I included at the end the short list of modules I visited to make sure: Zope uses the asyncore to dispatch its request (and, right, the dispatch itself is done without forking & w/ no thread, but with select()), and these requests are then handled by a dedicated number of threads. There's also a nice explanation of this mechanism at http://lists.initd.org/pipermail/psycopg/2003-March/001906.html but beware! There is a guru wearing a warm cloak of invisibility (+2) roaming around! ;) > Is there someone else using modeling over zope ? cause i read severals > post over last weeks about the lack on this kind of things in zope=20 > (mainly #plone ) and the zope community seems to try different ways > as CMFTypes and Adaptable Storage.=20 I'm using it, but that you already know. And yes, the way the framework can be used along w/ zope is still to be documented. > /Soaf which is going to test modeling over mysql :)=20 Great! I'll wait for your reports then. Cheers, -- S=E9bastien. ------------------------------------------------------------------------ Zope uses threads (possible errors of interpretation of code are all mine): z2.py from ZServer import setNumberOfThreads setNumberOfThreads(NUMBER_OF_THREADS) [...] if HTTP_PORT: [...] hs =3D zhttp_server( [...] ZServer/HTTPServer.py:=20 zhttp_server derives from http_server, and uses zhttp_channel for its channel_class zhttp_channel itself derives from http_channel, and uses ZServer.PubCore.handle in its work() method Last, ZServer.PubCore.__init__ declares handle as ZRendezvous.ZRendevous(_n).handle, where ZRendeVous is declared in ZServer.PubCore.ZRendezvous and creates a pool of threads: (and where _n is assigned by setNumberOfThreads() above in z2.py for option '-t n': "The number of threads to use, if ZODB3 is used.") class ZRendevous: def __init__(self, n=3D1): [...] while n > 0: l=3Dthread.allocate_lock() l.acquire() pool.append(l) thread.start_new_thread(ZServerPublisher,=20 (self.accept,)) ------------------------------------------------------------------------ |
From: Jerome K. <Jer...@fi...> - 2003-03-07 21:01:38
|
On Fri, Mar 07, 2003 at 10:53:08AM +0100, Sebastien Bigaret wrote: > > It seems that the problem is triggered when the same psycopg cursor is > used in two different threads. This is really sound strange as, i know zope use medusa asyncore, and this avoid the use of thread (for the http..) so how could you achieve to have several thread using the same db connection. ? Is there someone else using modeling over zope ? cause i read severals post over last weeks about the lack on this kind of things in zope (mainly #plone ) and the zope community seems to try different ways as CMFTypes and Adaptable Storage. /Soaf which is going to test modeling over mysql :) |
From: Yannick G. <yan...@sa...> - 2003-03-07 20:56:49
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 07 March 2003 03:34 pm, Mario Ruggier wrote: > After looking at the Modeling sourceforge page so many times, the > initials of MORBY (approximately), for Modeling OR-Bridge for Python, > start to stand-out... but, this could be not such a bad unique name (in > lowercase, of course) for the framework. However, this also makes > other, cuter, names come to mind, such as Morfy (where the bridge > becomes a framework) that in turn brings to mind the action of > morphing (relational data to objects, and back), which points to > another possible name, Morphy, for Modeling, Object-Relational > Phramework for Python ;-) Which, in turn, would beg that an > OR model be called a MetaMorphy... Hmmn, mario I really like Morphy ! - -- Yannick Gingras Byte Gardener, Savoir-faire Linux inc. (514) 276-5468 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE+aQePrhy5Fqn/MRARAtUDAJ9iaWwQSFvsV5+e0+py7VBKR9hSEgCZAe+Z JcMS6Y+JIJIS/vnZOZIFaDs= =xE6m -----END PGP SIGNATURE----- |