This repository has been archived by the owner on Mar 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlocking.txt
164 lines (120 loc) · 4.13 KB
/
locking.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
=======
Locking
=======
The acutual locking is done via WebDAV.
Setup
=====
Mock a connector:
>>> import zeit.connector.interfaces
>>> import zeit.connector.resource
>>> class Connector(object):
... who = None
... until = None
... mylock = True
... def locked(self, id):
... return self.who, self.until, self.mylock
... def lock(self, obj_id, principal_id, until):
... if obj_id == 'alreadylocked':
... raise zeit.connector.interfaces.LockingError(obj_id)
... print "Locking %s for %s until %s" % (obj_id, principal_id, until)
... def unlock(self, id):
... print "Unlocking", id
... def __getitem__(self, key):
... mod = 'justnow'
... if key == 'doesnotexist':
... mod = None
... return zeit.connector.resource.Resource(
... key, 'aname', 'type', None,
... properties={('getlastmodified', 'DAV:'): mod})
...
...
>>> import zope.component
>>> gsm = zope.component.getGlobalSiteManager()
>>> connector = Connector()
>>> gsm.registerUtility(
... connector, zeit.connector.interfaces.IConnector)
Create a fake content object:
>>> import zeit.cms.interfaces
>>> class Content(object):
... zope.interface.implements(zeit.cms.interfaces.ICMSContent)
... uniqueId = 'foo'
LockStorage
===========
The lockstorage object is the mediator between Zope and the connector.
>>> import zeit.cms.locking.locking
>>> lock_storage = zeit.cms.locking.locking.LockStorage()
Its `getLock` method return an Lockinfo object when the resource is locked,
None when it's not:
>>> content = Content()
>>> lock_storage.getLock(content) is None
True
When who or until is not None we'll get a lock info:
>>> connector.who = 'bastard locker from hell'
>>> info = lock_storage.getLock(content)
>>> info.principal_id
'bastard locker from hell'
When the connector tells us that it is not us who locked but a different system
the lock owner will be prefixed by "othersystem.":
>>> connector.mylock = False
>>> info = lock_storage.getLock(content)
>>> info.principal_id
'othersystem.bastard locker from hell'
Set until:
>>> import datetime
>>> import pytz
>>> connector.who = None
>>> connector.until = datetime.datetime.now(pytz.UTC) + datetime.timedelta(
... days=1)
>>> connector.mylock = True
>>> info = lock_storage.getLock(content)
>>> info.principal_id
u'zeit.cms.unknown-dav-locker'
>>> isinstance(info.timeout, float)
True
Getting a lock for a non-cms object also returns None:
>>> lock_storage.getLock(object()) is None
True
Setting a lock for a non-cms object raises an error:
>>> lock_storage.setLock(object(), info)
Traceback (most recent call last):
...
ValueError: Non CMS objects cannot be locked.
Deleting a lock for a non-cms object does nothing because it cannot be locked
anyway:
>>> lock_storage.delLock(object())
Setting an allowed lock calls the lock method of the connector:
>>> info.principal_id = u'cms.gandalf'
>>> lock_storage.setLock(content, info)
Locking foo for cms.gandalf until ...
Locking again doesn't harm:
>>> lock_storage.setLock(content, info)
Locking foo for cms.gandalf until ...
An ``timeout`` value of None is also passed to the connector:
>>> info.timeout = None
>>> lock_storage.setLock(content, info)
Locking foo for cms.gandalf until None
When we try to lock an object where the connector raises a
zeit.connector.interfaces.LockingError, the setLock method raises an
zope.app.locking.interfaces.LockingError:
>>> content.uniqueId = 'alreadylocked'
>>> lock_storage.setLock(content, info)
Traceback (most recent call last):
...
LockingError: alreadylocked
We *really* got the one from zope.app.locking:
>>> try:
... lock_storage.setLock(content, info)
... except Exception, e:
... print e.__module__
zope.app.locking.interfaces
Note that it is not possible to create locks for resources which do not exist:
>>> content.uniqueId = 'doesnotexist'
>>> lock_storage.setLock(content, info)
Traceback (most recent call last):
...
LockingError: ('doesnotexist', 'Object does not exist.')
Clean up
========
>>> gsm.unregisterUtility(
... connector, zeit.connector.interfaces.IConnector)
True