Re: [Zope-dev] ZPatterns AttributeProvider question
Christian Scholz wrote: So what I do now as workaround is dtml method 1: - creates new object via newItem() - redirects to dtml method 2 dtml method 2: - retrieves the newly created object with getItem() - calls manage_changeProperties on that object This is working. Putting the manage_changeProperties directly after the newItem() is not working. I've also tried retrieving the new object directly after newItem() and calling manage_changeProperties on that but this also did not work. (so it is named correctly as otherwise it wouldn't be called either in dtml method 2). So the main problem is: SetAttributeFor() is not called (and also _objectChanging() is not called) in the same request cycle after creating a new object. They're called however in the "next" request after retrieving it with getItem(). As a simpler workaround, you can use your_object.commitSubtransaction() instead of redirecting to a new page. A few Zope versions ago, that could conceivably cause problems with certain database adapters. With some of the recent fixes to Zope, you should be ok using subtransactions even with DAs that don't support them. Check this out before you use it for important stuff though :-) You really should be able to create a new object and set its attributes in the same transaction. The status of the object (_v_status in DataSkin.py) will be ChangedStatus, if you're adding and changing in the same transaction. That's a good place to look for where the problem is. -- Steve Alexander Software Engineer Cat-Box limited ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
At 03:07 PM 4/22/01 +0100, Steve Alexander wrote: As a simpler workaround, you can use your_object.commitSubtransaction() instead of redirecting to a new page. Um, this shouldn't be the issue here. _SetAttributeFor() should be called when the attribute is set; it's not transaction-driven. Something weird is happening with Christian's situation that I haven't investigated yet. You really should be able to create a new object and set its attributes in the same transaction. The status of the object (_v_status in DataSkin.py) will be ChangedStatus, if you're adding and changing in the same transaction. That's a good place to look for where the problem is. Actually, the status should be AddedStatus, and it should stay that way throughout the transaction, unless the object gets deleted in the same transaction. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
Phillip J. Eby wrote: Steve Alexander wrote: As a simpler workaround, you can use your_object.commitSubtransaction() instead of redirecting to a new page. Um, this shouldn't be the issue here. _SetAttributeFor() should be called when the attribute is set; it's not transaction-driven. Something weird is happening with Christian's situation that I haven't investigated yet. I agree. However, if Christian's problem can be worked-around by redirecting before setting attributes, then it should also be workaroundable by calling commitSubtransaction. Actually, the status should be AddedStatus, and it should stay that way throughout the transaction, unless the object gets deleted in the same transaction. That's what I'd originally thought. Then I (mis-?)read the code again... The __set_attr__ method of DataSkins.py says: self._objectChanging(name) The _objectChanging method says: if self._v_status_ is not ChangedStatus: d[_v_dm_]._objectChanging(self) d[_v_status_] = ChangedStatus I don't see an exception for if _v_status is already AddedStatus. -- Steve Alexander Software Engineer Cat-Box limited ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
Hi! A little update.. Actually I was mistaken and SetAttributeFor() is called. Just _objectChanged() is not called in that case.. and thus my attributes are not stored to the database. Also commit() is not called at all in this case. It get's called once when the subtranscation is committed but not after some data has changed (which happens after that). Printing _v_status_ in SetAttributeFor() also gives me "Changed", thus this seems right. Maybe some more code will help (just the important pieces): def _objectAdded(self,client): """ store cached data in database """ ... here we do an sql query to insert things in database ... def _objectChanged(self,client): """ store cached data in database """ ... here we do an sql query to update things in database ... def _objectAdding(self,client, _tmap={ None:AddedStatus, DeletedStatus:ChangedStatus, ChangedStatus:AddedStatus } ): t = client._getTokenFor(self) s = t.status t.status = _tmap.get(s,s) # we need to do a commit here in order to store the record into the database! # and we need to have it stored as an AttributeFor() of the primary key will # return None otherwise (as this also just makes a query). client.commitSubtransaction() def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" # attribs stores the attributes we care about if name in self._attribs.keys(): client._getCache()[name]=value client.__dict__[name]=value; client._p_changed = 1 return 1 return None So _objectChanging() is not overridden, the rest I have ommitted.. So as you also can see I already do a subtransaction commit but it does not seem to help for this problem.. regards, Christian PS: It might also be that I am simply blind ;-) But somehow ZPatterns always confuses me, especially the inner workings ;-) -- COM.lounge http://comlounge.net/ communication design [EMAIL PROTECTED] ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] pydoc for Zope - another great documentation finding tool
I installed Python 2.1 and checked what great new things are there: they are numerous! As you know, I am a fan of documentation - reliable documentation, if possible directly extracted from the source. Therefore, the new Python documenter "pydoc" was very attractive for me. I had to tweak "Zope" and "pydoc" a bit such that they work nicely together: * "pydoc" imports the modules to find out about its content. Zope does not like to be imported, when another Zope process is running. Solved by calling "FileStorage.FileStorage" with the "read_only" parameter in "Zope.__init__", if instructed by an environment variable * "pydoc" is slightly confused by some of Zope's extension classes: it wants any class to have a "__module__" attribute. Zope's extension classes do not have it. Solved by wrapping pydoc's "__module__" access in an "try except". * "inspect" does not understand "Python Methods" (and other Zope methods). Correspondingly, Zope class documentation was almost empty. Solved by defining "implementsMethodInterface" and replacing "inspect.ismethod" by this function (at runtime). After these tweaks, "pydoc" can document Zope code. It is a bit overwhelming: The "pydoc" authors decided to document inherited methods with the class itself. As a consequence, for each Zope class, hundreds of mostly irrelevant methods are documented. But it should be easy to change this to get something similar to "javadoc": summary information for inherited methods. Already in the current state, I think, it is a great help for Zope developpers. If there is interest, I can post my changes. Dieter ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] pydoc for Zope - another great documentation finding tool
Zopista writes: Yes please, I want to integrate pydoc in to the SourceCodeBrowser which is at zopezen.org and I'm just to about to release as a product. The (minor) modification to let "pydoc" work with Zope can be found via URL:http://www.dieter.handshake.de/pyprojects/zope/pydoc.html "pydoc" requires installation and use of Python2.1. It seems that Zope need not be run with Python2.1 just "pydoc". But I made no thourough tests for this. Dieter ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
At 08:29 PM 4/22/01 +0200, Christian Scholz wrote: Hi! A little update.. Actually I was mistaken and SetAttributeFor() is called. Just _objectChanged() is not called in that case.. and thus my attributes are not stored to the database. When an object is newly added, only _objectAdded() is called. _objectAdded(), _objectChanged(), and _objectDeleted() are mutually exclusive within a given transaction. That is, only one of them occurs in a given transaction. See more below. Maybe some more code will help (just the important pieces): def _objectAdded(self,client): """ store cached data in database """ ... here we do an sql query to insert things in database ... def _objectChanged(self,client): """ store cached data in database """ ... here we do an sql query to update things in database ... def _objectAdding(self,client, _tmap={ None:AddedStatus, DeletedStatus:ChangedStatus, ChangedStatus:AddedStatus } ): t = client._getTokenFor(self) s = t.status t.status = _tmap.get(s,s) # we need to do a commit here in order to store the record into the database! # and we need to have it stored as an AttributeFor() of the primary key will # return None otherwise (as this also just makes a query). client.commitSubtransaction() This is broken. Don't do this! commitSubtransaction() is an application-level operation. Only. If you have to use it inside of provider-level code or code called from SkinScript, chances are that you are doing something horribly wrong. You run the risk of causing a recursive commit operation in the Zope transaction machinery. Don't do this! def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" # attribs stores the attributes we care about if name in self._attribs.keys(): client._getCache()[name]=value client.__dict__[name]=value; client._p_changed = 1 return 1 return None This also looks broken to me. Why are you changing both the cache and the persistent state? There's no reason to do both. So _objectChanging() is not overridden, the rest I have ommitted.. So as you also can see I already do a subtransaction commit but it does not seem to help for this problem.. I think you're seriously over-engineering this. I don't see anything that you're doing here that couldn't be done more easily with SkinScript statements. If all you want to do is store the data in an SQL database, a few SkinScript triggers would suffice. Now, if you're trying to get a row to be inserted in an SQL database at the actual time of the newItem() call, there is a trick you can use to do that from SkinScript also. Do this: INITIALIZE OBJECT WITH someAttr1=default1, someAttr2=default2,...,dummyAttributeName=myInsertQuery(primaryKey=self.id) Where myInsertQuery() is an SQL insert query that takes primaryKey as a parameter, and dummyAttributeName is some attribute name you don't care about. You should also set any default values for fields that will be inserted. Your insert query will be called, initializing the row in the database, and then use something like this: WHEN OBJECT ADDED,CHANGED STORE foo,bar,baz USING UpdateMethod(widget_id=self.id, foo_field=self.foo, wbar=self.bar) To update the data at transaction commit time. Voila. No need to make any custom attribute providers just to do this. Just to clarify the event sequence that should take place: 1. newItem() is called, which fires an _objectCreating() event 1.1. The SkinScript INITIALIZE OBJECT statement is triggered by the _objectCreating() event, and calls myInsertQuery() to insert a row in the database, with default values for everything but the primary key. 1.2. newItem() fires an _objectAdding() event, which does nothing except flag the object as "AddedStatus" and pass the event back to the DataManager (Rack). 1.3. The Rack passes the _objectAdding() event to all appropriately registered providers. The WHEN OBJECT ADDED,CHANGED statement is such a provider, so it receives the message and notes that the DataSkin was added, but does not act on it yet. Instead, it registers a proxy for itself with the Zope transaction object so that it will be notified of transaction commit. 2. newItem() returns a new DataSkin to your application, bearing the contents set up by the INITIALIZE OBJECT WITH statement. 3. Your application calls manage_changeProperties, to change an attribute. 3.1. The DataSkin fires an _objectChanging() event, which flags the object as "ChangedStatus", and the event is propagated to all registered providers in the Rack. (Such as the WHEN OBJECT statement) 3.2. The WHEN OBJECT statement ignores the _objectChanging() event, because from its point of view the object is in AddedStatus. 3.3. The DataSkin calls
Re: [Zope-dev] ZPatterns AttributeProvider question
At 08:29 PM 4/22/01 +0200, Christian Scholz wrote: Hi! A little update.. Actually I was mistaken and SetAttributeFor() is called. Just _objectChanged() is not called in that case.. and thus my attributes are not stored to the database. When an object is newly added, only _objectAdded() is called. _objectAdded(), _objectChanged(), and _objectDeleted() are mutually exclusive within a given transaction. That is, only one of them occurs in a given transaction. See more below. Maybe some more code will help (just the important pieces): def _objectAdded(self,client): """ store cached data in database """ ... here we do an sql query to insert things in database ... def _objectChanged(self,client): """ store cached data in database """ ... here we do an sql query to update things in database ... def _objectAdding(self,client, _tmap={ None:AddedStatus, DeletedStatus:ChangedStatus, ChangedStatus:AddedStatus } ): t = client._getTokenFor(self) s = t.status t.status = _tmap.get(s,s) # we need to do a commit here in order to store the record into the database! # and we need to have it stored as an AttributeFor() of the primary key will # return None otherwise (as this also just makes a query). client.commitSubtransaction() This is broken. Don't do this! commitSubtransaction() is an application-level operation. Only. If you have to use it inside of provider-level code or code called from SkinScript, chances are that you are doing something horribly wrong. You run the risk of causing a recursive commit operation in the Zope transaction machinery. Don't do this! def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" # attribs stores the attributes we care about if name in self._attribs.keys(): client._getCache()[name]=value client.__dict__[name]=value; client._p_changed = 1 return 1 return None This also looks broken to me. Why are you changing both the cache and the persistent state? There's no reason to do both. So _objectChanging() is not overridden, the rest I have ommitted.. So as you also can see I already do a subtransaction commit but it does not seem to help for this problem.. I think you're seriously over-engineering this. I don't see anything that you're doing here that couldn't be done more easily with SkinScript statements. If all you want to do is store the data in an SQL database, a few SkinScript triggers would suffice. Now, if you're trying to get a row to be inserted in an SQL database at the actual time of the newItem() call, there is a trick you can use to do that from SkinScript also. Do this: INITIALIZE OBJECT WITH someAttr1=default1, someAttr2=default2,...,dummyAttributeName=myInsertQuery(primaryKey=self.id) Where myInsertQuery() is an SQL insert query that takes primaryKey as a parameter, and dummyAttributeName is some attribute name you don't care about. You should also set any default values for fields that will be inserted. Your insert query will be called, initializing the row in the database, and then use something like this: WHEN OBJECT ADDED,CHANGED STORE foo,bar,baz USING UpdateMethod(widget_id=self.id, foo_field=self.foo, wbar=self.bar) To update the data at transaction commit time. Voila. No need to make any custom attribute providers just to do this. Just to clarify the event sequence that should take place: 1. newItem() is called, which fires an _objectCreating() event 1.1. The SkinScript INITIALIZE OBJECT statement is triggered by the _objectCreating() event, and calls myInsertQuery() to insert a row in the database, with default values for everything but the primary key. 1.2. newItem() fires an _objectAdding() event, which does nothing except flag the object as "AddedStatus" and pass the event back to the DataManager (Rack). 1.3. The Rack passes the _objectAdding() event to all appropriately registered providers. The WHEN OBJECT ADDED,CHANGED statement is such a provider, so it receives the message and notes that the DataSkin was added, but does not act on it yet. Instead, it registers a proxy for itself with the Zope transaction object so that it will be notified of transaction commit. 2. newItem() returns a new DataSkin to your application, bearing the contents set up by the INITIALIZE OBJECT WITH statement. 3. Your application calls manage_changeProperties, to change an attribute. 3.1. The DataSkin fires an _objectChanging() event, which flags the object as "ChangedStatus", and the event is propagated to all registered providers in the Rack. (Such as the WHEN OBJECT statement) 3.2. The WHEN OBJECT statement ignores the _objectChanging() event, because from its point of view the object is in AddedStatus. 3.3. The DataSkin calls
Re: [Zope-dev] ZPatterns AttributeProvider question
Hi! Just a quick note as it's quite late already (more tomorrow): In the early days of ZPatterns, I assumed that I would create SQL providers, LDAP providers, and suchlike gizmos. Later, it became clear that it was more useful to have a simple "glue" language to allow harnessing the full power of Zope in the context of events happening to objects. I still toy with the idea of making an "SQL attribute provider", however, that would be based on the ZSQLMethod object and add some ZPatterns hooks to it, but it's not a big priority. Its main value would be to cut down on some repetitive typing between one's SQL statements and SkinScript statements. Well, exactly this was the intention of programming this as I was a bit bored by all this typing, exactly when the attribute lists are getting longer. So right now I define it once in the ZClass, press the "Read ZCLass propsheet" button and the my attribute provider sets everything up itself.. (it also saves me from typing errors..) Actually I did it with SkinScript before but thought some simple plugin would be nicer.. But thanks for explaining the inner workings in some more detail (maybe I should put this into some howto or so? or it might be put into the ZPatterns wiki..), as this really should help (not only me I guess :) I will comment more on this tomorrow.. (at least I got some idea how I might solve my problem... though I thought this some times before already.. ;-) And the other possible option would be (as Steve suggested once on IRC) to create some wizard which sets up all the SkinScript methods and ZSQL methods in one go.. Anyway, more about it tomorrow. good nite.. Christian -- COM.lounge http://comlounge.net/ communication design [EMAIL PROTECTED] ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] .zexp's
Just ran into a problem with a newbie where they couldnt figure out where to import the zexp, if its a product it should go in /Control_Panel/Products, if not it should go in the ZODB. I couldn't think of an obvious way to tell, so I just had a look in the zexp and came up with this: file = open(infile, 'r') if string.find(file.readline(), 'App.Product') = 0: print "%s is a product zexp, go to Control_Panel" % infile Can anyone think of a better way? It would be figure out where to stick this in ExportImport.py so it would give nicer error messages... Cheers -- Andy McKay ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] [] vs () in dtml-in: is this a bug ?
Hi, please try this as a DTML Method: dtml-let l=[[1, 2], [3, 4]] dtml-in l dtml-var _['sequence-item']br /dtml-in /dtml-let dtml-let l=[(1, 2), (3, 4)] dtml-in l dtml-var _['sequence-item']br /dtml-in /dtml-let Why should the two results differ ? S. -- Stéfane Fermigier, Tel: 06 63 04 12 77 (mobile). http://nuxeo.com/ http://portalux.com/ http://aful.org/ Amazon: we patent the dot in .com ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] [] vs () in dtml-in: is this a bug ?
Stefane Fermigier wrote: Hi, please try this as a DTML Method: dtml-let l=[[1, 2], [3, 4]] dtml-in l dtml-var _['sequence-item']br /dtml-in /dtml-let dtml-let l=[(1, 2), (3, 4)] dtml-in l dtml-var _['sequence-item']br /dtml-in /dtml-let Why should the two results differ ? This is a designed-in feature of dtml-in. When you call an items() method on a dictionary-like object, you get back a list of two-tuples: [(key1,value1), (key2,value2, ...] It is often nice to iterate through such a list in dtml, so, dtml-in detects that the next item in the iteration is a two-tuple, and puts the elements of the tuple in sequence-key and sequence-item. If you look throughthe zope-dev list archives, you'll find a number of arguments on each side as to whether this is a bug or a feature. -- Steve Alexander Software Engineer Cat-Box limited ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] [] vs () in dtml-in: is this a bug ?
On Sun, Apr 22, 2001 at 01:16:57PM +0100, Steve Alexander wrote: If you look throughthe zope-dev list archives, you'll find a number of arguments on each side as to whether this is a bug or a feature. Thanks. I definitely call that a bug. S. -- Stéfane Fermigier, Tel: +33 (0)6 63 04 12 77 (mobile). http://nuxeo.com/ http://portalux.com/ http://aful.org/ Amazon: we patent the dot in .com ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )