[Checkins] SVN: zope.webdav/trunk/src/zope/webdav/ Emit an
ObjectModifiedEvent on successfully modifying a property with
Michael Kerrin
michael.kerrin at openapp.biz
Mon Feb 19 17:03:25 EST 2007
Log message for revision 72694:
Emit an ObjectModifiedEvent on successfully modifying a property with
the proppatch method.
Changed:
U zope.webdav/trunk/src/zope/webdav/ftests/test_proppatch.py
U zope.webdav/trunk/src/zope/webdav/proppatch.py
U zope.webdav/trunk/src/zope/webdav/tests/test_proppatch.py
-=-
Modified: zope.webdav/trunk/src/zope/webdav/ftests/test_proppatch.py
===================================================================
--- zope.webdav/trunk/src/zope/webdav/ftests/test_proppatch.py 2007-02-19 21:16:17 UTC (rev 72693)
+++ zope.webdav/trunk/src/zope/webdav/ftests/test_proppatch.py 2007-02-19 22:03:24 UTC (rev 72694)
@@ -39,7 +39,7 @@
self.assert_(
"All PROPPATCH requests needs a XML body" in response.getBody())
- def test_invalidxml(self):
+ def test_invalidxml_nopropertyupdate_elem(self):
body = """<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
<D:prop />
@@ -55,7 +55,7 @@
self.assertEqual(response.getBody(), "")
def test_setdisplayname_unauthorized(self):
- file = self.addResource("/r", "some content", title = u"Test Resource")
+ self.addResource("/r", "some content", title = u"Test Resource")
body = """<?xml version="1.0" encoding="utf-8" ?>
<D:propertyupdate xmlns:D="DAV:" xmlns="DAV:">
<D:set><D:prop>
@@ -77,7 +77,7 @@
def test_setdisplayname(self):
set_properties = "<D:displayname>Test File</D:displayname>"
- file = self.addResource("/r", "some content", title = u"Test Resource")
+ self.addResource("/r", "some content", title = u"Test Resource")
httpresponse, xmlbody = self.checkProppatch(
"/r", basic = "mgr:mgrpw", set_properties = set_properties)
@@ -93,8 +93,7 @@
def test_readonly_property(self):
set_properties = "<D:getcontentlength>10</D:getcontentlength>"
- file = self.addResource("/r", "some file content",
- title = u"Test Resource")
+ self.addResource("/r", "some file content", title = u"Test Resource")
httpresponse, xmlbody = self.checkProppatch(
"/r", basic = "mgr:mgrpw", set_properties = set_properties)
@@ -109,25 +108,6 @@
self.assertMSPropertyValue(response, "{DAV:}getcontentlength",
status = 403)
-## def test_property_notfound(self):
-## set_properties = """
-## <E:notfound xmlns:E="example:">Not Existent Prop</E:notfound>
-## """
-## file = self.addFile("/testfile", "some file content", "text/plain")
-
-## httpresponse, xmlbody = self.checkProppatch(
-## "/testfile", basic = "mgr:mgrpw", set_properties = set_properties)
-
-## responses = xmlbody.findall("{DAV:}response")
-## self.assertEqual(len(responses), 1)
-## response = responses[0]
-## hrefs = response.findall("{DAV:}href")
-## self.assertEqual(len(hrefs), 1)
-## self.assertEqual(hrefs[0].text, "http://localhost/testfile")
-
-## self.assertMSPropertyValue(response, "{example:}notfound",
-## status = 404)
-
def test_badinput(self):
set_properties = """
<E:exampleintprop xmlns:E="DAVtest:">BAD INT</E:exampleintprop>
@@ -226,7 +206,7 @@
def test_unicode_title(self):
teststr = u"copyright \xa9 me"
set_properties = "<D:displayname>%s</D:displayname>" % teststr
- file = self.addResource("/r", "some content", title = u"Test Resource")
+ self.addResource("/r", "some content", title = u"Test Resource")
httpresponse, xmlbody = self.checkProppatch(
"/r", basic = "mgr:mgrpw", set_properties = set_properties)
@@ -296,8 +276,8 @@
def test_setting_unicode_title(self):
teststr = u"copyright \xa9 me"
- file = self.addResource(u"/" + teststr, "some file content",
- title = u"Old title")
+ self.addResource(u"/" + teststr, "some file content",
+ title = u"Old title")
httpresponse, xmlbody = self.checkProppatch(
"/" + teststr.encode("utf-8"), basic = "mgr:mgrpw",
Modified: zope.webdav/trunk/src/zope/webdav/proppatch.py
===================================================================
--- zope.webdav/trunk/src/zope/webdav/proppatch.py 2007-02-19 21:16:17 UTC (rev 72693)
+++ zope.webdav/trunk/src/zope/webdav/proppatch.py 2007-02-19 22:03:24 UTC (rev 72694)
@@ -20,8 +20,10 @@
"""
__docformat__ = 'restructuredtext'
+import zope.event
from zope import interface
from zope import component
+from zope.lifecycleevent import ObjectModifiedEvent
import zope.webdav.utils
import zope.webdav.interfaces
@@ -54,13 +56,13 @@
etree = component.getUtility(IEtree)
- # isError - an error occurred during the processing of the request.
- isError = False
# propErrors - list of (property tag, error). error is None if no
# error occurred in setting / removing the property.
propErrors = []
# properties - list of all the properties that we handled correctly.
properties = []
+ # changed - boolean indicating whether any content changed or not.
+ changed = False
for update in xmldata:
if update.tag not in ("{DAV:}set", "{DAV:}remove"):
continue
@@ -74,21 +76,20 @@
for prop in props:
try:
if update.tag == "{DAV:}set":
- self.handleSet(prop)
- else:
- self.handleRemove(prop)
+ changed |= self.handleSet(prop)
+ else: # update.tag == "{DAV:}remove"
+ changed |= self.handleRemove(prop)
except Unauthorized:
# If the use doesn't have the correct permission to modify
# a property then we need to re-raise the Unauthorized
# exception in order to ask the user to log in.
raise
except Exception, error:
- isError = True
propErrors.append((prop.tag, error))
else:
properties.append(prop.tag)
- if isError:
+ if propErrors:
errors = zope.webdav.interfaces.WebDAVPropstatErrors(self.context)
for prop, error in propErrors:
@@ -100,6 +101,9 @@
raise errors # this kills the current transaction.
+ if changed:
+ zope.event.notify(ObjectModifiedEvent(self.context))
+
url = zope.webdav.utils.getObjectURL(self.context, self.request)
response = zope.webdav.utils.Response(url)
propstat = response.getPropstat(200)
@@ -133,6 +137,8 @@
if field.get(adapter) != value:
field.set(adapter, value)
+ return True
+ return False
def handleRemove(self, prop):
davprop = component.queryUtility(
@@ -151,3 +157,5 @@
self.context, prop.tag, message = u"property doesn't exist")
deadproperties.removeProperty(prop.tag)
+
+ return True
Modified: zope.webdav/trunk/src/zope/webdav/tests/test_proppatch.py
===================================================================
--- zope.webdav/trunk/src/zope/webdav/tests/test_proppatch.py 2007-02-19 21:16:17 UTC (rev 72693)
+++ zope.webdav/trunk/src/zope/webdav/tests/test_proppatch.py 2007-02-19 22:03:24 UTC (rev 72694)
@@ -22,12 +22,14 @@
import unittest
from cStringIO import StringIO
+from zope import event
from zope import interface
from zope import component
from zope import schema
import zope.schema.interfaces
from zope.traversing.browser.interfaces import IAbsoluteURL
from zope.security.interfaces import Unauthorized
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
import zope.webdav.proppatch
import zope.webdav.publisher
@@ -98,8 +100,6 @@
path += "/" + self.context.__name__
elif IResource.providedBy(self.context):
path += "/resource"
-## elif ICollection.providedBy(self.context):
-## path += "/collection"
else:
raise ValueError("unknown context type")
@@ -118,9 +118,11 @@
def handleSet(self, prop):
self.setprops.append(prop.tag)
+ return True
def handleRemove(self, prop):
self.removeprops.append(prop.tag)
+ return True
class PROPPATCHXmlParsing(unittest.TestCase):
@@ -340,11 +342,6 @@
exampletextprop = schema.Text(
title = u"Example Text Property")
-class IExtraPropertyStorage(interface.Interface):
-
- extratextprop = schema.Text(
- title = u"Property with no storage")
-
class IUnauthorizedPropertyStorage(interface.Interface):
unauthprop = schema.TextLine(
@@ -354,8 +351,6 @@
"{DAVtest:}exampleintprop", IExamplePropertyStorage)
exampleTextProperty = zope.webdav.properties.DAVProperty(
"{DAVtest:}exampletextprop", IExamplePropertyStorage)
-extraTextProperty = zope.webdav.properties.DAVProperty(
- "{DAVtest:}extratextprop", IExtraPropertyStorage)
unauthProperty = zope.webdav.properties.DAVProperty(
"{DAVtest:}unauthprop", IUnauthorizedPropertyStorage)
unauthProperty.restricted = True
@@ -397,6 +392,9 @@
class PROPPATCHHandlePropertyModification(unittest.TestCase):
+ def eventLog(self, event):
+ self.events.append(event)
+
def setUp(self):
etreeSetup()
@@ -409,9 +407,6 @@
name = "{DAVtest:}exampletextprop",
provided = zope.webdav.interfaces.IDAVProperty)
exampleTextProperty.field.readonly = False
- gsm.registerUtility(extraTextProperty,
- name = "{DAVtest:}extratextprop",
- provided = zope.webdav.interfaces.IDAVProperty)
gsm.registerUtility(unauthProperty, name = "{DAVtest:}unauthprop")
gsm.registerAdapter(ExamplePropertyStorage,
@@ -421,10 +416,19 @@
(IResource, zope.webdav.interfaces.IWebDAVRequest),
provided = IUnauthorizedPropertyStorage)
+ gsm.registerAdapter(zope.webdav.widgets.IntDAVInputWidget,
+ (zope.schema.interfaces.IInt,
+ zope.webdav.interfaces.IWebDAVRequest))
gsm.registerAdapter(zope.webdav.widgets.TextDAVInputWidget,
(zope.schema.interfaces.IText,
zope.webdav.interfaces.IWebDAVRequest))
+ gsm.registerAdapter(DummyResourceURL,
+ (IResource, zope.webdav.interfaces.IWebDAVRequest))
+
+ self.events = []
+ zope.event.subscribers.append(self.eventLog)
+
def tearDown(self):
etreeTearDown()
@@ -436,9 +440,6 @@
gsm.unregisterUtility(exampleTextProperty,
name = "{DAVtest:}exampletextprop",
provided = zope.webdav.interfaces.IDAVProperty)
- gsm.unregisterUtility(extraTextProperty,
- name = "{DAVtest:}extratextprop",
- provided = zope.webdav.interfaces.IDAVProperty)
gsm.unregisterUtility(unauthProperty, name = "{DAVtest:}unauthprop")
gsm.unregisterAdapter(ExamplePropertyStorage,
@@ -450,10 +451,20 @@
zope.webdav.interfaces.IWebDAVRequest),
provided = IUnauthorizedPropertyStorage)
+ gsm.unregisterAdapter(zope.webdav.widgets.IntDAVInputWidget,
+ (zope.schema.interfaces.IInt,
+ zope.webdav.interfaces.IWebDAVRequest))
gsm.unregisterAdapter(zope.webdav.widgets.TextDAVInputWidget,
(zope.schema.interfaces.IText,
zope.webdav.interfaces.IWebDAVRequest))
+ gsm.unregisterAdapter(DummyResourceURL,
+ (IResource,
+ zope.webdav.interfaces.IWebDAVRequest))
+
+ self.events = []
+ zope.event.subscribers.remove(self.eventLog)
+
def test_handleSetProperty(self):
etree = component.getUtility(IEtree)
propel = etree.Element("{DAVtest:}exampletextprop")
@@ -464,10 +475,22 @@
resource = Resource("Text Prop", 10)
propp = zope.webdav.proppatch.PROPPATCH(resource, request)
- propp.handleSet(propel)
-
+ self.assertEqual(propp.handleSet(propel), True)
self.assertEqual(resource.text, "Example Text Prop")
+ def test_handleSetProperty_samevalue(self):
+ etree = component.getUtility(IEtree)
+ propel = etree.Element("{DAVtest:}exampletextprop")
+ propel.text = "Text Prop"
+
+ request = TestRequest(
+ set_properties = """<Dt:exampletextprop xmlns:Dt="DAVtest:">Text Prop</Dt:exampletextprop>""")
+ resource = Resource("Text Prop", 10)
+
+ propp = zope.webdav.proppatch.PROPPATCH(resource, request)
+ self.assertEqual(propp.handleSet(propel), False)
+ self.assertEqual(resource.text, "Text Prop")
+
def test_handleSet_forbidden_property(self):
etree = component.getUtility(IEtree)
propel = etree.Element("{DAVtest:}exampletextprop")
@@ -538,7 +561,48 @@
propp.handleRemove,
propel)
+ def test_event_onsetProperty(self):
+ request = TestRequest(
+ set_properties = """<Dt:exampletextprop xmlns:Dt="DAVtest:">Example Text Prop</Dt:exampletextprop>""")
+ resource = Resource("Text Prop", 10)
+ propp = zope.webdav.proppatch.PROPPATCH(resource, request)
+ propp.PROPPATCH()
+
+ self.assertEqual(resource.text, "Example Text Prop") # property modified
+ self.assertEqual(len(self.events), 1)
+ self.assert_(IObjectModifiedEvent.providedBy(self.events[0]))
+ self.assertEqual(self.events[0].object, resource)
+
+ def test_event_onsetProperty_sameValue(self):
+ request = TestRequest(
+ set_properties = """<Dt:exampletextprop xmlns:Dt="DAVtest:">Text Prop</Dt:exampletextprop>""")
+ resource = Resource("Text Prop", 10)
+
+ propp = zope.webdav.proppatch.PROPPATCH(resource, request)
+ propp.PROPPATCH()
+
+ self.assertEqual(resource.text, "Text Prop")
+ self.assertEqual(len(self.events), 0)
+
+ def test_event_multipleProperty(self):
+ request = TestRequest(
+ set_properties = """
+<Dt:exampletextprop xmlns:Dt="DAVtest:">Text Prop</Dt:exampletextprop>
+<Dt:exampleintprop xmlns:Dt="DAVtest:">14</Dt:exampleintprop>
+""")
+ resource = Resource("Text Prop", 10)
+
+ propp = zope.webdav.proppatch.PROPPATCH(resource, request)
+ propp.PROPPATCH()
+
+ self.assertEqual(resource.text, "Text Prop")
+ self.assertEqual(resource.intprop, 14)
+ self.assertEqual(len(self.events), 1)
+ self.assertEqual(IObjectModifiedEvent.providedBy(self.events[0]), True)
+ self.assertEqual(self.events[0].object, resource)
+
+
class DEADProperties(object):
interface.implements(zope.webdav.interfaces.IOpaquePropertyStorage)
@@ -564,6 +628,9 @@
class PROPPATCHHandlePropertyRemoveDead(unittest.TestCase):
+ def eventLog(self, event):
+ self.events.append(event)
+
def setUp(self):
etreeSetup()
@@ -571,6 +638,12 @@
gsm.registerAdapter(DEADProperties, (IResource,))
+ gsm.registerAdapter(DummyResourceURL,
+ (IResource, zope.webdav.interfaces.IWebDAVRequest))
+
+ self.events = []
+ zope.event.subscribers.append(self.eventLog)
+
def tearDown(self):
etreeTearDown()
@@ -578,6 +651,13 @@
gsm.unregisterAdapter(DEADProperties, (IResource,))
+ gsm.unregisterAdapter(DummyResourceURL,
+ (IResource,
+ zope.webdav.interfaces.IWebDAVRequest))
+
+ self.events = []
+ zope.event.subscribers.remove(self.eventLog)
+
def test_remove_no_storage(self):
etree = component.getUtility(IEtree)
propel = etree.Element("{example:}exampledeadprop")
@@ -605,6 +685,7 @@
self.assertRaises(zope.webdav.interfaces.ConflictError,
propp.handleRemove,
propel)
+ self.assertEqual(self.events, [])
def test_remove_prop(self):
etree = component.getUtility(IEtree)
@@ -624,11 +705,29 @@
propp = zope.webdav.proppatch.PROPPATCH(resource, request)
- propp.handleRemove(propel)
+ self.assertEqual(propp.handleRemove(propel), True)
+ self.assertEqual(deadprops.hasProperty(testprop), False)
+ def test_event_on_remove_property(self):
+ request = TestRequest(
+ remove_properties = """<Dt:exampledeadprop xmlns:Dt="example:">Example Text Prop</Dt:exampledeadprop>""")
+
+ testprop = "{example:}exampledeadprop"
+
+ resource = Resource("Text Prop", 10)
+ deadprops = DEADProperties(resource)
+ deadprops.setProperty(testprop, "Example Text Prop")
+
+ propp = zope.webdav.proppatch.PROPPATCH(resource, request)
+ propp.PROPPATCH()
+
self.assertEqual(deadprops.hasProperty(testprop), False)
+ self.assertEqual(len(self.events), 1)
+ self.assertEqual(IObjectModifiedEvent.providedBy(self.events[0]), True)
+ self.assertEqual(self.events[0].object, resource)
+
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(PROPPATCHXmlParsing),
More information about the Checkins
mailing list