paula: removed empty dirs
[paula.git] / paula.proputil / trunk / src / paula / proputil / utils.py
blobc15a6235044ad0e3257ea2fbafce9986db197586
1 # Copyright (c) 2008 by Florian Friesdorf
3 # GNU Affero General Public License (AGPL)
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation; either version 3 of the
8 # License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
15 # You should have received a copy of the GNU Affero General Public
16 # License along with this program. If not, see
17 # <http://www.gnu.org/licenses/>.
18 """
19 """
20 __author__ = "Florian Friesdorf <flo@chaoflow.net>"
21 __docformat__ = "plaintext"
23 from BTrees import OOBTree
25 from persistent import Persistent
26 from persistent.list import PersistentList
28 from zope.app.container.contained import Contained
30 from zope.component import queryUtility
31 from zope.component.interfaces import IFactory
33 from zope.interface import implements
35 from paula.properties.interfaces import IPropertyProvider
36 from paula.proputil.interfaces import IRWPropertyProviders
39 class RWPropertyProviders(Persistent, Contained):
40 """Utility delivering IPropertyProviders for principal ids
42 IPropertyProvider objects are generated by dynamic adapter lookup from
43 IPropertyProviderAdaptable objects, which are retrieved from an internal
44 mapping. Objects enter/leave the mapping through register/unregister.
46 Currently we do not support modification of principal id for registered
47 objects; before doing anything that modifies the prinicipal id of an object,
48 you need to unregister and reregister the object.
50 This utility could be registered globally and works outside of an
51 application server. However, the adapter lookup for IPropertyProvider
52 needs to be supported.
55 Mappings are empty, for a new utility
57 >>> ppu = RWPropertyProviders()
58 >>> len(ppu._objs)
61 Suitable objects end up in the mapping, strings work as id
63 >>> a = Mock(id = '1')
64 >>> alsoProvides(a, IPropertyProvider)
65 >>> ppu.register(a)
66 >>> len(ppu._objs['1'])
68 >>> ppu._objs['1'][0] is a
69 True
71 Object with same id is appended to the same list
73 >>> b = Mock(id = '1')
74 >>> alsoProvides(b, IPropertyProvider)
75 >>> ppu.register(b)
76 >>> len(ppu._objs['1'])
78 >>> ppu._objs['1'][0] is a
79 True
80 >>> ppu._objs['1'][1] is b
81 True
83 Unsuitable object triggers TypeError
85 >>> c = Mock(id = '2')
86 >>> ppu.register(c) # doctest: +IGNORE_EXCEPTION_DETAIL
87 Traceback (most recent call last):
88 blah
89 TypeError: blah
91 Object with different id enters new list
93 >>> c = Mock(id = '2')
94 >>> alsoProvides(c, IPropertyProvider)
95 >>> ppu.register(c)
96 >>> len(ppu._objs['2'])
98 >>> ppu._objs['2'][0] is c
99 True
101 Objects are retrieved correctly
103 >>> ppu['1'][0] is a
104 True
105 >>> ppu['1'][1] is b
106 True
107 >>> ppu['2'][0] is c
108 True
110 has_key is working
112 >>> ppu.has_key('1')
113 True
114 >>> ppu.has_key('0')
115 False
117 in operator is working
119 >>> '1' in ppu
120 True
121 >>> '0' in ppu
122 False
124 list of all keys can be given
126 >>> ppu.keys()
127 ['1', '2']
129 len() is working and contains the number of ids, we have providers for
131 >>> len(ppu)
134 implements(IRWPropertyProviders)
136 def __init__(self):
139 self._objs = queryUtility(IFactory, 'OOBTree', OOBTree.OOBTree)()
141 def __contains__(self, id):
142 return self.has_key(id)
144 def __getitem__(self, id):
145 """retrieve IPropertyProvider list for principal id
147 pps = [IPropertyProvider(x) for x in self._objs[id]]
148 return pps
150 def __len__(self):
151 return self._objs.__len__()
153 def has_key(self, id):
154 # I currently consider this a broken BTree
155 return bool(self._objs.has_key(id))
157 def keys(self):
158 # I currently consider this a broken BTree
159 return list(self._objs.keys())
161 def register(self, obj):
162 """Register an object.
164 It is assumed that an adapter lookup for IPropertyProvider succeeds.
166 id = IPropertyProvider(obj).id
167 try:
168 objs = self._objs[id]
169 except KeyError:
170 self._objs[id] = PersistentList()
171 objs = self._objs[id]
172 else:
173 if obj in objs:
174 return
175 self._objs[id].append(obj)
177 def unregister(self, obj):
178 """Unregister an object.
180 Fails with ValueError, if the object is not registered.
182 id = IPropertyProvider(obj).id
183 self._objs[id].remove(obj)