Adding __setitem__ to a formulator field?
there are __getitem__() and get_value() methods for formulator fields. I'd like to experiment with __setitem__ and set_value(). The error message from my naive implementation in field.py is as follows: security.declareProtected('Access contents information', '__setitem__') def __setitem__(self, key, value): self[key] = value self._p_set_changed(1) return value
app.Formulator.myForm.stringfield1.__setitem__('required',1) Traceback (most recent call last): File "<interactive input>", line 1, in ? AttributeError: __setitem__
Does anyone know what I need to do to add __setitem__ (and later on, set_value()) to formulator fields? Thanks.
Jeff Kowalczyk wrote:
there are __getitem__() and get_value() methods for formulator fields. I'd like to experiment with __setitem__ and set_value(). The error message from my naive implementation in field.py is as follows:
security.declareProtected('Access contents information', '__setitem__') def __setitem__(self, key, value): self[key] = value self._p_set_changed(1) return value
This approach should work for 'set_value', but '__setitem__' is a horse of a different kettle of fish. With explicit methods, such as 'get_value' and 'set_value', name-based access control is sufficient, since there's no way to trigger them implicitly. Since 'x[1] = 2' will implicitly access x's '__setitem__', you need to take one of two steps: 1. If you were willing to have uncontrolled write access to your objects, including setting and deletion of attributes, you could simply add _guarded_writes = 1 to the class. 2. For fine-grained control, add the following method to the class: def __guarded_setitem__(self, index, value): if getSecurityManager().checkPermission( 'Access contents information', self): self[index] = value else: raise Unauthorized('__setitem__') Cheers, Evan @ 4-am
What mechanism maps __guarded_setitem to the [key] syntax? I removed __setitem__ from my formulator field class and replaced it with the add_guarded_writes attribute and this method (note the absence of security.declareProtected()) add_guarded_writes = 1 def __guarded_setitem__(self, index, value): if getSecurityManager().checkPermission( 'Access contents information', self): self[index] = value else: raise Unauthorized('__setitem__') But I don't seem to have it hooked up right...
import Zope, Products, ZEO, ZODB storage = ZEO.ClientStorage.ClientStorage(('localhost', 8800)) db = ZODB.DB(storage) conn = db.open() dbroot = conn.root() app = dbroot.get('Application') app.Formulator.form3.str1['required'] = 0 Traceback (most recent call last): File "<interactive input>", line 1, in ? AttributeError: __setitem__
FWIW, that problem with "AttributeError: __setitem__" was that my console (PythonWin connected via ZEO) isn't aware of product refreshes. I'm kind of in uncharted territory here (for me), but what should I be doing to get the python console to recognize the updated python product code when I run a refresh from the ZEO-connected Zope ZMI? Here's a sample console problem demonstrating the symptoms, and some of the things I've tried to avoid closing out the python console each time I change python code in a product. Thanks for any help anyone can offer. This is probing how to get the console to recognize that __setitem__'s implementation has changed from 'print test1' to 'print test2' after the first call. PythonWin 2.1.3 (#35, Apr 8 2002, 17:47:50) [MSC 32 bit (Intel)] on win32. Portions Copyright 1994-2001 Mark Hammond (mhammond@skippinet.com.au)
import Zope, Products, ZEO, ZODB storage = ZEO.ClientStorage.ClientStorage(('localhost', 8800)) db = ZODB.DB(storage) conn = db.open() dbroot = conn.root() app = dbroot.get('Application') app.Formulator.form3.str1['required'] = 0 test1 app.Formulator.form3.str1['required'] = 0 # Prod refresh in ZMI, expecting 'test2' test1 storage.close() storage = ZEO.ClientStorage.ClientStorage(('localhost', 8800)) db = ZODB.DB(storage) conn = db.open() dbroot = conn.root() app = dbroot.get('Application') app.Formulator.form3.str1['required'] = 0 # looking for 'test2' test1 reimport Products.Formulator.Form app.Formulator.form3.str1['required'] = 0 # looking for 'test2' test1 reload(Products.Formulator) <module 'Products.Formulator' from 'C:\PROGRA~1\Zope\lib\python\Products\Formulator\__init__.pyc'> app.Formulator.form3.str1['required'] = 0 # expecting 'test2' test1 Zope.ZPublisher.Zope('/Control_Panel/Products/Formulator/manage_performRefresh', u='Username:password') Status: 200 OK (snip) app.Formulator.form3.str1['required'] = 0 # looking for 'test2' test1
participants (2)
-
Evan Simpson -
Jeff Kowalczyk