[Checkins] SVN: Products.Five/trunk/form/ Some fixes for add/edit forms to ensure that events are fired as expected.

Alec Mitchell apm13 at columbia.edu
Tue May 2 14:30:58 EDT 2006


Log message for revision 67845:
  Some fixes for add/edit forms to ensure that events are fired as expected.
  

Changed:
  U   Products.Five/trunk/form/__init__.py
  U   Products.Five/trunk/form/tests/configure.zcml
  U   Products.Five/trunk/form/tests/forms.txt
  U   Products.Five/trunk/form/tests/schemacontent.py

-=-
Modified: Products.Five/trunk/form/__init__.py
===================================================================
--- Products.Five/trunk/form/__init__.py	2006-05-02 17:56:17 UTC (rev 67844)
+++ Products.Five/trunk/form/__init__.py	2006-05-02 18:30:57 UTC (rev 67845)
@@ -22,6 +22,7 @@
 import transaction
 from zope.event import notify
 from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
+from zope.lifecycleevent import Attributes
 from zope.location.interfaces import ILocation
 from zope.location import LocationProxy
 from zope.schema.interfaces import ValidationError
@@ -100,9 +101,16 @@
                 changed = applyWidgetsChanges(self, self.schema,
                     target=content, names=self.fieldNames)
                 # We should not generate events when an adapter is used.
-                # That's the adapter's job.
-                if changed and self.context is self.adapted:
-                    notify(ObjectModifiedEvent(content))
+                # That's the adapter's job.  We need to unwrap the objects to
+                # compare them, as they are wrapped differently.
+                # Additionally, we can't use Acquisition.aq_base() because
+                # it strangely returns different objects for these two even
+                # when they are identical.  In particular
+                # aq_base(self.adapted) != self.adapted.aq_base :-(
+                if changed and getattr(self.context, 'aq_base', self.context)\
+                            is getattr(self.adapted, 'aq_base', self.adapted):
+                    description = Attributes(self.schema, *self.fieldNames)
+                    notify(ObjectModifiedEvent(content, description))
             except WidgetsError, errors:
                 self.errors = errors
                 status = _("An error occurred.")
@@ -158,7 +166,9 @@
     def create(self, *args, **kw):
         """Do the actual instantiation."""
         # hack to please typical Zope 2 factories, which expect id and title
-        args = ('tmp_id', 'Temporary title') + args
+        # Any sane schema will use a unicode title, and may fail on a
+        # non-unicode one.
+        args = ('tmp_id', u'Temporary title') + args
         return self._factory(*args, **kw)
 
     def createAndAdd(self, data):
@@ -198,7 +208,6 @@
         notify(ObjectCreatedEvent(content))
 
         content = self.add(content)
-
         adapted = self.schema(content)
 
         if self._set_after_add:
@@ -209,6 +218,10 @@
                         field.set(adapted, data[name])
                     except ValidationError:
                         errors.append(sys.exc_info()[1])
+            # We have modified the object, so we need to publish an
+            # object-modified event:
+            description = Attributes(self.schema, *self._set_after_add)
+            notify(ObjectModifiedEvent(content, description))
 
         if errors:
             raise WidgetsError(*errors)

Modified: Products.Five/trunk/form/tests/configure.zcml
===================================================================
--- Products.Five/trunk/form/tests/configure.zcml	2006-05-02 17:56:17 UTC (rev 67844)
+++ Products.Five/trunk/form/tests/configure.zcml	2006-05-02 18:30:57 UTC (rev 67845)
@@ -62,7 +62,8 @@
      schema=".schemacontent.IFieldContent"
      content_factory=".schemacontent.FieldContent"
      name="addwidgetoverride.html"
-     permission="zope2.Public">
+     permission="zope2.Public"
+     set_before_add="title description somenumber somelist">
 
      <widget
          field="description"
@@ -78,6 +79,18 @@
      permission="zope2.ViewManagementScreens"
      />
 
+  <subscriber
+      for=".schemacontent.IFieldContent
+           zope.lifecycleevent.interfaces.IObjectModifiedEvent"
+      handler=".schemacontent.modifiedSubscriber"
+      />
+
+  <subscriber
+      for=".schemacontent.IFieldContent
+           zope.lifecycleevent.interfaces.IObjectCreatedEvent"
+      handler=".schemacontent.createdSubscriber"
+      />
+
   <i18n:registerTranslations directory="locales"/>
 
 </configure>

Modified: Products.Five/trunk/form/tests/forms.txt
===================================================================
--- Products.Five/trunk/form/tests/forms.txt	2006-05-02 17:56:17 UTC (rev 67844)
+++ Products.Five/trunk/form/tests/forms.txt	2006-05-02 18:30:57 UTC (rev 67845)
@@ -77,7 +77,20 @@
   u'title'
   >>> edittest.description #XXX shouldn't we get a u'' here???
 
+We can also verify that the IObjectCreatedEvent was fired, and the test
+subscriber we registered set a flag indicating such:
 
+  >>> edittest._created_flag
+  True
+
+Because the process of adding an object often sets attributes after the
+object is created and added, and IObjectModified event should also have been
+fired:
+
+  >>> edittest._modified_flag
+  True
+  >>> del edittest._modified_flag
+
 Edit forms
 ----------
 
@@ -104,6 +117,8 @@
   >>> edittest.title
   u'title'
   >>> edittest.description #XXX shouldn't we get a u'' here???
+  >>> getattr(edittest, '_modified_flag', False)
+  False
 
 However, when we specify the correct fields:
 
@@ -124,7 +139,70 @@
   >>> edittest.description
   u'FooDescription'
 
+And that the event has been fired:
 
+  >>> edittest._modified_flag
+  True
+  >>> del edittest._modified_flag
+
+Widget Overrides
+----------------
+
+We have an alternate add form for IFieldContent which uses a TextArea widget
+via and override in the zcml.  Let's ensure that that works:
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/ftf/+/addwidgetoverride.html HTTP/1.1
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  ...
+  ...<textarea
+  ...
+
+  >>> print http(r"""
+  ... POST /test_folder_1_/ftf/+/addwidgetoverride.html HTTP/1.1
+  ... Authorization: Basic manager:r00t
+  ... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
+  ... Content-Length: 527
+  ...
+  ... -----------------------------968064918930967154199105236
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... title2
+  ... -----------------------------968064918930967154199105236
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ... Blah
+  ... -----------------------------968064918930967154199105236
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------968064918930967154199105236
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... edittest2
+  ... -----------------------------968064918930967154199105236--
+  ... """, handle_errors=False)
+  HTTP/1.1 302 Moved Temporarily
+  ...
+  Location: http://localhost/test_folder_1_/ftf/manage_main
+  ...
+
+We also indicated that all fields for this view should be set before adding
+the content, this means that no IObjectModified event should have been fired
+
+  >>> edittest2 = self.folder.ftf.edittest2
+  >>> edittest2.title
+  u'title2'
+  >>> edittest2.description
+  u'Blah'
+  >>> edittest2._created_flag
+  True
+
+  >>> getattr(edittest2, '_modified_flag', False)
+  False
+
+
 Unicode-safety of forms
 -----------------------
 

Modified: Products.Five/trunk/form/tests/schemacontent.py
===================================================================
--- Products.Five/trunk/form/tests/schemacontent.py	2006-05-02 17:56:17 UTC (rev 67844)
+++ Products.Five/trunk/form/tests/schemacontent.py	2006-05-02 18:30:57 UTC (rev 67845)
@@ -106,3 +106,11 @@
     """Add the complex schema content"""
     id = self._setObject(id, ComplexSchemaContent(id))
     return ''
+
+def modifiedSubscriber(content, ev):
+    """A simple event handler, which sets a flag on the object"""
+    content._modified_flag = True
+
+def createdSubscriber(content,ev):
+    """A simple event handler, which sets a flag on the object"""
+    content._created_flag = True



More information about the Checkins mailing list