1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 __docformat__ = 'reStructuredText'
20
21 import copy
22
24
25 """
26 States what attributes to delegate, and to which target attributes.
27
28 Instance methods:
29
30 - `has_readable`: Check for read-access mapping of attribute
31 - `has_writable`: Check for read-access mapping of attribute
32 - `has_deletable`: Check for read-access mapping of attribute
33 - `get_readable`: Get read-access mapping for attribute
34 - `get_writable`: Get read-access mapping for attribute
35 - `get_deletable`: Get read-access mapping for attribute
36 - `remove_mappings`: Remove attribute mappings
37 - `add_mappings`: Add attribute mappings
38
39 Operators:
40
41 self |= b::Profile
42 union of this profile and the other
43
44 self | b::Profile
45 union of this profile and the other
46
47 self &= b::Profile
48 intersection of this profile and the other
49
50 self & b::Profile
51 intersection of this profile and the other
52
53 self - b::Profile
54 difference of this profile and the other
55
56 self -= b::Profile
57 difference of this profile and the other
58
59 self ^ b::Profile
60 symetric difference of this profile and the other
61
62 self ^= b::Profile
63 symetric difference of this profile and the other
64 """
65
67 self.__readables = {}
68 self.__writables = {}
69 self.__deletables = {}
70
72 """
73 Check for read-access mapping of attribute
74
75 Returns True if the mapping exists
76 """
77 return attribute in self.__readables
78
80 """
81 Check for write-access mapping of attribute
82
83 Returns True if the mapping exists
84 """
85 return attribute in self.__writables
86
88 """
89 Check for delete-access mapping of attribute
90
91 Returns True if the mapping exists
92 """
93 return attribute in self.__deletables
94
96 """
97 Get the mapped value of a readable attribute
98
99 Returns ::string
100 """
101 return self.__readables[attribute]
102
104 """
105 Get the mapped value of a writable attribute
106
107 Returns ::string
108 """
109 return self.__writables[attribute]
110
112 """
113 Get the mapped value of a deletable attribute
114
115 Returns ::string
116 """
117 return self.__deletables[attribute]
118
120 '''
121 Returns True if mappings of self don't conflict with those of other
122 '''
123
124
125
126
127
128
129 return reduce(lambda x, y: x and y,
130 (reduce(lambda x,y: x and y,
131 (a[key] == b[key]
132 for key
133 in set(a.iterkeys()) & set(b.iterkeys())),
134 True)
135 for a, b
136 in zip((self.__readables, self.__writables,
137 self.__deletables),
138 (other.__readables, other.__writables,
139 other.__deletables))),
140 True)
141
142
144 '''See __ior__'''
145 p = self.copy()
146 p |= other
147 return p
148
150 """
151 union of this profile and the other
152
153 Parameters:
154
155 - `other` :: Profile
156 the other profile
157
158 Preconditions:
159 1. The mappings of the two profiles musn't conflict. Two profiles
160 conflict when they have at least one mapping with the same source
161 name, but a different target name.
162 """
163 assert self.__are_conflict_free(other), \
164 "Profiles have conflicting mappings, can't take union"
165
166
167 self.__readables.update(other.__readables)
168 self.__writables.update(other.__writables)
169 self.__deletables.update(other.__deletables)
170 return self
171
173 p = self.copy()
174 p &= other
175 return p
176
178 """
179 intersection of this profile and the other
180
181 Parameters:
182
183 - `other` :: Profile
184 the other profile
185
186 Preconditions:
187 1. The mappings of the two profiles musn't conflict. Two profiles
188 conflict when they have at least one mapping with the same source
189 name, but a different target name.
190 """
191
192 assert self.__are_conflict_free(other), \
193 "Profiles have conflicting mappings, can't take union"
194
195
196 for a, b in zip(
197 (self.__readables, self.__writables, self.__deletables),
198 (other.__readables, other.__writables, other.__deletables)):
199 for key in a.keys():
200 if key not in b:
201 del a[key]
202
203 return self
204
205
207 p = self.copy()
208 p -= other
209 return p
210
212 """
213 difference of this profile and the other
214
215 Parameters:
216
217 - `other` :: Profile
218 the other profile
219 """
220
221 for a, b in zip(
222 (self.__readables, self.__writables, self.__deletables),
223 (other.__readables, other.__writables, other.__deletables)):
224 for key in a.keys():
225 if key in b:
226 del a[key]
227
228 return self
229
230
232 p = self.copy()
233 p ^= other
234 return p
235
237 """
238 symetric difference of this profile and the other
239
240 Parameters:
241
242 - `other` :: Profile
243 the other profile
244 """
245
246
247 inter_readables = set(self.__readables.iterkeys()) \
248 & set(other.__readables.iterkeys())
249 inter_writables = set(self.__writables.iterkeys()) \
250 & set(other.__writables.iterkeys())
251 inter_deletables = set(self.__deletables.iterkeys()) \
252 & set(other.__deletables.iterkeys())
253
254
255 self.__readables.update(other.__readables)
256 self.__writables.update(other.__writables)
257 self.__deletables.update(other.__deletables)
258
259
260 for a, b in zip(
261 (self.__readables, self.__writables, self.__deletables),
262 (inter_readables, inter_writables, inter_deletables)):
263 for key in a.keys():
264 if key in b:
265 del a[key]
266
267 return self
268
270 """
271 Remove attribute mappings
272
273 Parameters:
274
275 `modifiers` :: string
276 the types of delegation access to the target to remove. Valid
277 modifiers are combinations of:
278
279 - `r`: read
280 - `w`: write
281 - `d`: delete
282
283 `names` :: (source_name::string...)
284 names of source_name parts of, the mappings to remove
285 """
286
287 for name in names:
288 assert isinstance(name, basestring), \
289 "Invalid arguments: names should be list of strings: %s" \
290 % (names)
291
292 for name in names:
293 if "r" in modifiers:
294 self.__readables.pop(name)
295
296 if "w" in modifiers:
297 self.__writables.pop(name)
298
299 if "d" in modifiers:
300 self.__deletables.pop(name)
301
302
304 """
305 Map source to target attribute names, for delegation.
306
307 Parameters:
308
309 `modifiers` :: string
310 the types of delegation access to the target. Valid modifiers
311 are combinations of:
312
313 - `r`: read
314 - `w`: write
315 - `d`: delete
316
317 `names` :: (source_name::string...)
318 names of the attribute names to delegate. The target attribute
319 name is the same as `source_name`. This is the same as adding a
320 {source_name : source_name} mapping, using the mapped_names
321 argument.
322
323 `mapped_names` :: {source_name::string : target_name::string ...}
324 names of source and target attributes to map and delegate.
325
326 `target_name`s will be mangled if they have a __ prefix.
327 Mangling will occur every time it is delegated to, so you can
328 change the target object any time.
329 """
330 for name in names:
331 assert isinstance(name, basestring), (
332 "Invalid arguments: names should be list of strings. Got: %s" %
333 names)
334
335 for key, name in mapped_names.iteritems():
336 assert isinstance(key, basestring) and \
337 isinstance(name, basestring), \
338 "Invalid arguments: mapped_names should be dict of " + \
339 "string:string. Got: %s" % mapped_names
340
341 if "r" in modifiers:
342 self.__readables.update(zip(names, names), **mapped_names)
343
344 if "w" in modifiers:
345 self.__writables.update(zip(names, names), **mapped_names)
346
347 if "d" in modifiers:
348 self.__deletables.update(zip(names, names), **mapped_names)
349
351 return copy.deepcopy(self)
352