Commit 32e8dea3 authored by Hanno Schlichting's avatar Hanno Schlichting

Move IWriteLock from webdav into OFS.

The locking concept is generally useful and used outside of
the webdav context.
parent 35fe223b
......@@ -31,7 +31,6 @@ from App.Common import rfc1123_date
from App.special_dtml import DTMLFile
from DateTime.DateTime import DateTime
from Persistence import Persistent
from webdav.interfaces import IWriteLock
from ZPublisher import HTTPRangeSupport
from ZPublisher.HTTPRequest import FileUpload
from zExceptions import Redirect, ResourceLockedError
......@@ -40,6 +39,7 @@ from zope.interface import implementedBy
from zope.interface import implements
from OFS.Cache import Cacheable
from OFS.interfaces import IWriteLock
from OFS.PropertyManager import PropertyManager
from OFS.role import RoleManager
from OFS.SimpleItem import Item_w__name__
......
......@@ -66,14 +66,10 @@ from OFS.XMLExportImport import magic
try:
from webdav.Collection import Collection
from webdav.NullResource import NullResource
except ImportError:
NullResource = None
class Collection(object):
pass
# Constants: __replaceable__ flags:
NOT_REPLACEABLE = 0
REPLACEABLE = 1
......@@ -778,10 +774,14 @@ class ObjectManager(CopyContainer,
request = getattr(self, 'REQUEST', None)
if not isinstance(request, (str, NoneType)):
method = request.get('REQUEST_METHOD', 'GET')
if (NullResource is not None and
request.maybe_webdav_client and
if (request.maybe_webdav_client and
method not in ('GET', 'POST')):
return NullResource(self, key, request).__of__(self)
try:
from webdav.NullResource import NullResource
except ImportError:
pass
else:
return NullResource(self, key, request).__of__(self)
raise KeyError(key)
def __setitem__(self, key, value):
......
......@@ -28,16 +28,6 @@ from App.interfaces import INavigation
from App.interfaces import IUndoSupport
from persistent.interfaces import IPersistent
try:
from webdav.interfaces import IDAVCollection
from webdav.interfaces import IDAVResource
except ImportError:
class IDAVCollection(Interface):
pass
class IDAVResource(Interface):
pass
class IOrderedContainer(Interface):
......@@ -331,10 +321,80 @@ class IManageable(Interface):
"""
class IWriteLock(Interface):
"""Basic protocol needed to support the write lock machinery.
It must be able to answer the questions:
o Is the object locked?
o Is the lock owned by the current user?
o What lock tokens are associated with the current object?
o What is their state (how long until they're supposed to time out?,
what is their depth? what type are they?
And it must be able to do the following:
o Grant a write lock on the object to a specified user.
- *If lock depth is infinite, this must also grant locks on **all**
subobjects, or fail altogether*
o Revoke a lock on the object.
- *If lock depth is infinite, this must also revoke locks on all
subobjects*
**All methods in the WriteLock interface that deal with checking valid
locks MUST check the timeout values on the lockitem (ie, by calling
'lockitem.isValid()'), and DELETE the lock if it is no longer valid**
"""
def wl_lockItems(killinvalids=0):
""" Returns (key, value) pairs of locktoken, lock.
if 'killinvalids' is true, invalid locks (locks whose timeout
has been exceeded) will be deleted"""
def wl_lockValues(killinvalids=0):
""" Returns a sequence of locks. if 'killinvalids' is true,
invalid locks will be deleted"""
def wl_lockTokens(killinvalids=0):
""" Returns a sequence of lock tokens. if 'killinvalids' is true,
invalid locks will be deleted"""
def wl_hasLock(token, killinvalids=0):
""" Returns true if the lock identified by the token is attached
to the object. """
def wl_isLocked():
""" Returns true if 'self' is locked at all. If invalid locks
still exist, they should be deleted."""
def wl_setLock(locktoken, lock):
""" Store the LockItem, 'lock'. The locktoken will be used to fetch
and delete the lock. If the lock exists, this MUST
overwrite it if all of the values except for the 'timeout' on the
old and new lock are the same. """
def wl_getLock(locktoken):
""" Returns the locktoken identified by the locktokenuri """
def wl_delLock(locktoken):
""" Deletes the locktoken identified by the locktokenuri """
def wl_clearLocks():
""" Deletes ALL locks on the object - should only be called
by lock management machinery. """
# XXX: might contain non-API methods and outdated comments;
# not synced with ZopeBook API Reference;
# based on OFS.SimpleItem.Item
class IItem(IZopeObject, IManageable, IFTPAccess, IDAVResource,
class IItem(IZopeObject, IManageable, IFTPAccess,
ICopySource, ITraversable, IOwned, IUndoSupport):
__name__ = BytesLine(
......@@ -477,7 +537,7 @@ class ICopyContainer(Interface):
# not synced with ZopeBook API Reference;
# based on OFS.ObjectManager.ObjectManager
class IObjectManager(IZopeObject, ICopyContainer, INavigation, IManageable,
IAcquirer, IPersistent, IDAVCollection, ITraversable,
IAcquirer, IPersistent, ITraversable,
IPossibleSite, IContainer):
"""Generic object manager
......@@ -819,7 +879,7 @@ class IPropertyManager(Interface):
# XXX: based on OFS.Folder.Folder
class IFolder(IObjectManager, IPropertyManager, IRoleManager,
IDAVCollection, IItem, IFindSupport):
IItem, IFindSupport):
"""Folders are basic container objects that provide a standard
interface for object management. Folder objects also implement a
......
import unittest
try:
from webdav.NullResource import NullResource
except ImportError:
NullResource = None
class ApplicationTests(unittest.TestCase):
......@@ -95,18 +90,25 @@ class ApplicationTests(unittest.TestCase):
request = {'REQUEST_METHOD': 'GET'}
self.assertRaises(KeyError, app.__bobo_traverse__, request, 'NONESUCH')
if NullResource is not None:
def test___bobo_traverse__attribute_key_miss_R_M_not_GET_POST(self):
from Acquisition import aq_inner, aq_parent
def test___bobo_traverse__attribute_key_miss_R_M_not_GET_POST(self):
try:
from webdav.NullResource import NullResource
except ImportError:
NullResource = None
if NullResource is None:
return
from Acquisition import aq_inner, aq_parent
app = self._makeOne()
app._getOb = _noWay
request = {'REQUEST_METHOD': 'GOOFY'}
app = self._makeOne()
app._getOb = _noWay
request = {'REQUEST_METHOD': 'GOOFY'}
result = app.__bobo_traverse__(request, 'OTHER')
result = app.__bobo_traverse__(request, 'OTHER')
self.assertTrue(isinstance(result, NullResource))
self.assertTrue(aq_parent(aq_inner(result)) is app)
self.assertTrue(isinstance(result, NullResource))
self.assertTrue(aq_parent(aq_inner(result)) is app)
def _noWay(self, key, default=None):
......
......@@ -313,7 +313,7 @@ class FileTests(unittest.TestCase):
def test_interfaces(self):
from zope.interface.verify import verifyClass
from OFS.Image import File
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
from ZPublisher.HTTPRangeSupport import HTTPRangeInterface
verifyClass(HTTPRangeInterface, File)
......@@ -361,7 +361,7 @@ class ImageTests(FileTests):
def test_interfaces(self):
from zope.interface.verify import verifyClass
from OFS.Image import Image
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
verifyClass(IWriteLock, Image)
......
......@@ -6,7 +6,7 @@ class TestFolder(unittest.TestCase):
def test_interfaces(self):
from OFS.Folder import Folder
from OFS.interfaces import IFolder
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
from zope.interface.verify import verifyClass
verifyClass(IFolder, Folder)
......
......@@ -6,8 +6,8 @@ class TestOrderedFolder(unittest.TestCase):
def test_interfaces(self):
from OFS.interfaces import IOrderedContainer
from OFS.interfaces import IOrderedFolder
from OFS.interfaces import IWriteLock
from OFS.OrderedFolder import OrderedFolder
from webdav.interfaces import IWriteLock
from zope.interface.verify import verifyClass
verifyClass(IOrderedContainer, OrderedFolder)
......
......@@ -12,7 +12,7 @@ class DTMLDocumentTests(unittest.TestCase):
def test_class_conforms_to_IWriteLock(self):
from zope.interface.verify import verifyClass
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
verifyClass(IWriteLock, self._getTargetClass())
......
......@@ -12,7 +12,7 @@ class DTMLMethodTests(unittest.TestCase):
def test_class_conforms_to_IWriteLock(self):
from zope.interface.verify import verifyClass
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
verifyClass(IWriteLock, self._getTargetClass())
def test_edit_taintedstring(self):
......
......@@ -241,7 +241,7 @@ class ZopePageTemplateFileTests(ZopeTestCase):
def test_class_conforms_to_IWriteLock(self):
from zope.interface.verify import verifyClass
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
verifyClass(IWriteLock, ZopePageTemplate)
def testPT_RenderWithAscii(self):
......
......@@ -28,6 +28,7 @@ from Acquisition import Implicit
from App.special_dtml import DTMLFile
from Persistence import Persistent
from OFS.CopySupport import CopyError
from OFS.interfaces import IWriteLock
from OFS.SimpleItem import Item_w__name__
from zExceptions import BadRequest
from zExceptions import Forbidden
......@@ -44,7 +45,6 @@ from webdav.common import tokenFinder
from webdav.common import UnsupportedMediaType
from webdav.davcmds import Lock
from webdav.davcmds import Unlock
from webdav.interfaces import IWriteLock
from webdav.Resource import Resource
from zope.contenttype import guess_content_type
......
......@@ -18,11 +18,11 @@ from AccessControl.class_init import InitializeClass
from AccessControl.SecurityManagement import getSecurityManager
from App.Common import iso8601_date
from App.Common import rfc1123_date
from OFS.interfaces import IWriteLock
from OFS.PropertySheets import Virtual, PropertySheet, View
from webdav.common import isDavCollection
from webdav.common import urlbase
from webdav.interfaces import IWriteLock
if sys.version_info >= (3, 0):
basestring = str
......
......@@ -34,6 +34,7 @@ from Acquisition import aq_parent
from ExtensionClass import Base
from OFS.event import ObjectClonedEvent
from OFS.event import ObjectWillBeMovedEvent
from OFS.interfaces import IWriteLock
from OFS.subscribers import compatibilityCall
from zExceptions import BadRequest
from zExceptions import Forbidden
......@@ -63,7 +64,6 @@ from webdav.common import tokenFinder
from webdav.common import urlbase
from webdav.common import urlfix
from webdav.interfaces import IDAVResource
from webdav.interfaces import IWriteLock
ms_dav_agent = re.compile("Microsoft.*Internet Publishing.*")
......
......@@ -22,7 +22,7 @@ from AccessControl.Permissions import delete_objects
from AccessControl.SecurityManagement import getSecurityManager
from Acquisition import aq_base
from Acquisition import aq_parent
from OFS.PropertySheets import DAVProperties
from OFS.interfaces import IWriteLock
from zExceptions import BadRequest
from zExceptions import Forbidden
......@@ -33,8 +33,8 @@ from webdav.common import PreconditionFailed
from webdav.common import urlbase
from webdav.common import urlfix
from webdav.common import urljoin
from webdav.interfaces import IWriteLock
from webdav.LockItem import LockItem
from webdav.PropertySheets import DAVProperties
from webdav.xmltools import XmlParser
......
......@@ -16,6 +16,8 @@
from zope.interface import Interface
from zope.schema import Bool, Tuple
from OFS.interfaces import IWriteLock
class ILockItem(Interface):
......@@ -144,77 +146,6 @@ class ILockItem(Interface):
used when returning the value of a newly created lock. """
class IWriteLock(Interface):
"""Basic protocol needed to support the write lock machinery.
It must be able to answer the questions:
o Is the object locked?
o Is the lock owned by the current user?
o What lock tokens are associated with the current object?
o What is their state (how long until they're supposed to time out?,
what is their depth? what type are they?
And it must be able to do the following:
o Grant a write lock on the object to a specified user.
- *If lock depth is infinite, this must also grant locks on **all**
subobjects, or fail altogether*
o Revoke a lock on the object.
- *If lock depth is infinite, this must also revoke locks on all
subobjects*
**All methods in the WriteLock interface that deal with checking valid
locks MUST check the timeout values on the lockitem (ie, by calling
'lockitem.isValid()'), and DELETE the lock if it is no longer valid**
"""
def wl_lockItems(killinvalids=0):
""" Returns (key, value) pairs of locktoken, lock.
if 'killinvalids' is true, invalid locks (locks whose timeout
has been exceeded) will be deleted"""
def wl_lockValues(killinvalids=0):
""" Returns a sequence of locks. if 'killinvalids' is true,
invalid locks will be deleted"""
def wl_lockTokens(killinvalids=0):
""" Returns a sequence of lock tokens. if 'killinvalids' is true,
invalid locks will be deleted"""
def wl_hasLock(token, killinvalids=0):
""" Returns true if the lock identified by the token is attached
to the object. """
def wl_isLocked():
""" Returns true if 'self' is locked at all. If invalid locks
still exist, they should be deleted."""
def wl_setLock(locktoken, lock):
""" Store the LockItem, 'lock'. The locktoken will be used to fetch
and delete the lock. If the lock exists, this MUST
overwrite it if all of the values except for the 'timeout' on the
old and new lock are the same. """
def wl_getLock(locktoken):
""" Returns the locktoken identified by the locktokenuri """
def wl_delLock(locktoken):
""" Deletes the locktoken identified by the locktokenuri """
def wl_clearLocks():
""" Deletes ALL DAV locks on the object - should only be called
by lock management machinery. """
# XXX: might contain non-API methods and outdated comments;
# not synced with ZopeBook API Reference;
# based on webdav.Resource.Resource
......
......@@ -17,7 +17,7 @@ class TestUtilFunctions(unittest.TestCase):
lockable = LockableResource(locked=False)
self.assertTrue(wl_isLockable(lockable))
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
from zope.interface import implements
class LockableResource:
......
......@@ -4,7 +4,7 @@ import unittest
class TestLockNullResource(unittest.TestCase):
def test_interfaces(self):
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
from webdav.NullResource import LockNullResource
from zope.interface.verify import verifyClass
......@@ -21,7 +21,7 @@ class TestNullResource(unittest.TestCase):
return self._getTargetClass()(parent, name, **kw)
def test_interfaces(self):
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
from zope.interface.verify import verifyClass
verifyClass(IWriteLock, self._getTargetClass())
......
......@@ -98,8 +98,8 @@ class TestResource(unittest.TestCase):
setSecurityPolicy(self._oldPolicy)
def test_interfaces(self):
from OFS.interfaces import IWriteLock
from webdav.interfaces import IDAVResource
from webdav.interfaces import IWriteLock
from zope.interface.verify import verifyClass
verifyClass(IDAVResource, self._getTargetClass())
......@@ -149,8 +149,8 @@ class TestResource(unittest.TestCase):
inst.restrictedTraverse = lambda *arg: app
inst.getId = lambda *arg: '123'
inst._dav_writelocks = {'a':DummyLock()}
from OFS.interfaces import IWriteLock
from zope.interface import directlyProvides
from webdav.interfaces import IWriteLock
directlyProvides(inst, IWriteLock)
from webdav.common import Locked
self.assertRaises(Locked, inst.MOVE, request, response)
......@@ -172,8 +172,8 @@ class TestResource(unittest.TestCase):
{'If':ifhdr})
response = DummyResponse()
inst = self._makeOne()
from OFS.interfaces import IWriteLock
from zope.interface import directlyProvides
from webdav.interfaces import IWriteLock
directlyProvides(inst, IWriteLock)
from webdav.common import PreconditionFailed
self.assertRaises(PreconditionFailed, inst.dav__simpleifhandler,
......@@ -198,8 +198,8 @@ class TestResource(unittest.TestCase):
response = DummyResponse()
inst = self._makeOne()
inst._dav_writelocks = {'a':DummyLock()}
from OFS.interfaces import IWriteLock
from zope.interface import directlyProvides
from webdav.interfaces import IWriteLock
directlyProvides(inst, IWriteLock)
from webdav.common import Locked
self.assertRaises(Locked, inst.dav__simpleifhandler, request, response)
......
......@@ -15,7 +15,7 @@ class _DummySecurityPolicy(object):
class _DummyContent(object):
from webdav.interfaces import IWriteLock
from OFS.interfaces import IWriteLock
implements(IWriteLock)
def __init__(self, token=None):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment