[Checkins] SVN: zope.app.form/trunk/ Added changelog and refactored applyChanges() to set up the location for newly

Christian Theune ct at gocept.com
Sat Jul 7 05:48:12 EDT 2007


Log message for revision 77562:
  Added changelog and refactored applyChanges() to set up the location for newly
  created objects.
  

Changed:
  A   zope.app.form/trunk/CHANGES.txt
  U   zope.app.form/trunk/src/zope/app/form/browser/objectwidget.py
  U   zope.app.form/trunk/src/zope/app/form/browser/objectwidget.txt
  U   zope.app.form/trunk/src/zope/app/form/browser/tests/test_objectwidget.py

-=-
Added: zope.app.form/trunk/CHANGES.txt
===================================================================
--- zope.app.form/trunk/CHANGES.txt	                        (rev 0)
+++ zope.app.form/trunk/CHANGES.txt	2007-07-07 09:48:11 UTC (rev 77562)
@@ -0,0 +1,17 @@
+=======
+Changes
+=======
+
+After 3.4.0b1
+=============
+
+ - Made the object widget set up location for objects that are instanciated by
+   the object widget itself. (#98287)
+
+
+Before 3.4
+==========
+
+This package was part of the Zope 3 distribution and did not have its own
+CHANGES.txt. For earlier changes please refer to either our subversion log or
+the CHANGES.txt of earlier Zope 3 releases.


Property changes on: zope.app.form/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.app.form/trunk/src/zope/app/form/browser/objectwidget.py
===================================================================
--- zope.app.form/trunk/src/zope/app/form/browser/objectwidget.py	2007-07-07 09:47:47 UTC (rev 77561)
+++ zope.app.form/trunk/src/zope/app/form/browser/objectwidget.py	2007-07-07 09:48:11 UTC (rev 77562)
@@ -17,6 +17,8 @@
 """
 __docformat__ = 'restructuredtext'
 
+import zope.location.interfaces
+import zope.location.location
 from zope import component
 from zope.interface import implements
 from zope.schema import getFieldNamesInOrder
@@ -148,27 +150,29 @@
 
         return content
 
-
     def applyChanges(self, content):
         field = self.context
-
-        # create our new object value
-        value = field.query(content, None)
-        if value is None:
+        obj = field.query(content, None)
+        if obj is None:
+            # The object doesn't exist yet, so we create a new one. Existing
+            # objects are updated, not re-created.
+            obj = self.factory()
             # TODO: ObjectCreatedEvent here would be nice
-            value = self.factory()
 
-        # apply sub changes, see if there *are* any changes
-        # TODO: ObjectModifiedEvent here would be nice
-        changes = applyWidgetsChanges(self, field.schema, target=value,
+            # Locate the new object
+            if not zope.location.interfaces.ILocation.providedBy(obj):
+                obj = zope.location.location.LocationProxy(obj)
+            obj.__parent__ = content
+            obj.__name__ = field.__name__
+
+        # Apply the actual changes to the object. 
+        changes = applyWidgetsChanges(self, field.schema, target=obj,
                                       names=self.names)
-
-        # if there's changes, then store the new value on the content
         if changes:
-            field.set(content, value)
-        # TODO: If value implements ILocation, set name to field name and
-        # parent to content
-
+          # Store the object on the content.  We do this both in the case of
+          # newly created as well as updated objects because field.set runs
+          # some more validation on the schema-conformance.
+          field.set(content, obj)
         return changes
 
     def hasInput(self):

Modified: zope.app.form/trunk/src/zope/app/form/browser/objectwidget.txt
===================================================================
--- zope.app.form/trunk/src/zope/app/form/browser/objectwidget.txt	2007-07-07 09:47:47 UTC (rev 77561)
+++ zope.app.form/trunk/src/zope/app/form/browser/objectwidget.txt	2007-07-07 09:48:11 UTC (rev 77562)
@@ -74,7 +74,7 @@
   >>> IPerson.providedBy(family.father)
   True
 
-Let's define a dummy class which doesn't implements IPerson:
+Let's define a dummy class which doesn't implement IPerson:
 
   >>> class Dummy(object):
   ...     """Dummy class."""
@@ -147,3 +147,62 @@
 
 So, now you know my mothers and fathers name. I hope it's also clear how to 
 use the Object field and the ObjectWidget.
+
+
+Locating objects from the object field
+======================================
+
+Objects that are created through the object field are located automatically.
+If they do not implement the ILocation interface, they will be wrapped with a
+location proxy. We need to do this to make location-based security work
+correctly.
+
+Read carefully (again): Only when the objects are created through the object
+field, they will be located by the object field. If you create the objects
+yourself, you're responsible for setting up any location that is required.
+
+Let's start with a new family. The existing Person class doesn't implement
+ILocation, but it still receives a parent and a name. This is done by using a
+location proxy:
+
+  >>> family = Family()
+  >>> widget.applyChanges(family)
+  True
+  >>> from zope.location.interfaces import ILocation
+  >>> ILocation.implementedBy(family.mother.__class__)
+  False
+  >>> family.mother.__parent__
+  <Family object at 0x...>
+  >>> family.mother.__name__
+  'mother'
+  >>> type(family.mother)
+  <class 'zope.location.location.LocationProxy'>
+
+To demonstrate this with a class that implements ILocation, we derive Person
+to a LocatedPerson, and we start with a fresh family to force the widget to
+re-create the object:
+
+  >>> from zope.location.location import Location
+  >>> class LocatedPerson(Location, Person):
+  ...     pass
+  >>> family = Family()
+
+We create a widget that uses this class as the factory, apply the request
+again, and see that this time, the object is not wrapped by a location proxy:
+
+  >>> factory = LocatedPerson
+  >>> request.form['field.mother.name'] = u'Isabel Ineichen'
+  >>> widget = ObjectWidget(mother_field, request, factory)
+  >>> widget.applyChanges(family)
+  True
+
+  >>> ILocation.implementedBy(family.mother.__class__)
+  True
+  >>> family.mother.__parent__
+  <Family object at 0x...>
+  >>> family.mother.__name__
+  'mother'
+  >>> family.mother
+  <LocatedPerson object at 0x...>
+  >>> type(family.mother)
+  <class 'LocatedPerson'>

Modified: zope.app.form/trunk/src/zope/app/form/browser/tests/test_objectwidget.py
===================================================================
--- zope.app.form/trunk/src/zope/app/form/browser/tests/test_objectwidget.py	2007-07-07 09:47:47 UTC (rev 77561)
+++ zope.app.form/trunk/src/zope/app/form/browser/tests/test_objectwidget.py	2007-07-07 09:48:11 UTC (rev 77562)
@@ -126,7 +126,8 @@
         unittest.makeSuite(ObjectWidgetTest),
         doctest.DocFileSuite('../objectwidget.txt',
                              setUp=setup.placelessSetUp,
-                             tearDown=setup.placelessTearDown),
+                             tearDown=setup.placelessTearDown,
+                             optionflags=doctest.ELLIPSIS),
         doctest.DocTestSuite(),
         ))
 



More information about the Checkins mailing list