1 """Field properties based on Archetypes schema
2 """
3
4 from zope.app.component.hooks import getSite
5
7 """Field properties based on Archetypes schema
8
9 These properties can only be used on Archetypes objects. They delegate
10 to schema.getField(fieldname).get() and set().
11
12 You can use it in your type as follows. The name of the field does
13 not need to conincide with the field-property name, but this is probably
14 sensible. However, AttributeStorage will interfere here, so we explicitly
15 use annoation storage.
16
17 >>> import string
18 >>> from Products.Archetypes.atapi import *
19 >>> from icsemantic.core.fieldproperty import ATFieldProperty
20
21 >>> class MyContent(BaseObject):
22 ... portal_type = meta_type = 'MyContent'
23 ... schema = Schema((
24 ... StringField('some_field', storage=AnnotationStorage()),
25 ... StringField('_other_field'),
26 ... ))
27 ...
28 ... some_field = ATFieldProperty('some_field')
29 ... other_field = ATFieldProperty('_other_field')
30 ... upper_lower = ATFieldProperty('_other_field',
31 ... get_transform=string.upper, set_transform=string.lower)
32
33 >>> registerType(MyContent, 'Archetypes')
34
35 Now, get and set operations on the fieldproperty behave the same way as
36 the mutator and accessor.
37
38 >>> foo = MyContent('foo')
39 >>> foo.some_field
40 ''
41 >>> foo.some_field = "Bar"
42 >>> foo.some_field
43 'Bar'
44 >>> foo.getField('some_field').get(foo)
45 'Bar'
46
47 The old-style mutator and accessors still work, of course
48
49 >>> foo.getSome_field()
50 'Bar'
51
52 >>> foo.setSome_field("Baz")
53 >>> foo.some_field
54 'Baz'
55
56 Here is an example using the default AttributeStorage. In this case, we
57 need different names for the AT field name and the properity, because
58 AttributeStorage will use the field name as the attribute name. If
59 you don't do this, you may get infinite recursion!
60
61 >>> foo.other_field = "Hello"
62 >>> foo.other_field
63 'Hello'
64 >>> foo.get_other_field()
65 'Hello'
66 >>> foo.set_other_field("Good bye")
67 >>> foo.other_field
68 'Good bye'
69
70 Finally, the get_transform and set_transform arguments can be used to
71 perform transformations on the retrieved value and the value before it
72 is set, respectively. The field upper_lower uses string.upper() on the
73 way out and string.lower() on the way in.
74
75 >>> foo.upper_lower = "MiXeD"
76 >>> foo.upper_lower
77 'MIXED'
78 >>> foo.get_other_field()
79 'mixed'
80 >>> foo.set_other_field('UpPeRaNdLoWeR')
81 >>> foo.upper_lower
82 'UPPERANDLOWER'
83
84 A less frivolous example of this functionality can be seen in the
85 ATDateTimeFieldProperty class below.
86 """
87
88 - def __init__(self, name, get_transform=None, set_transform=None):
89 self._name = name
90 self._get_transform = get_transform
91 self._set_transform = set_transform
92
94 if inst is None:
95 return self
96 field = inst.getField(self._name)
97 if field is None:
98 raise KeyError("Cannot find field with name %s" % self._name)
99 value = field.get(inst)
100 if self._get_transform is not None:
101 value = self._get_transform(value)
102 return value
103
105 field = inst.getField(self._name)
106 if field is None:
107 raise KeyError("Cannot find field with name %s" % self._name)
108 if self._set_transform is not None:
109 value = self._set_transform(value)
110 field.set(inst, value)
111
170
172 """A more friendly/use-case-specific name for ATReferenceFieldProperty.
173 """
174
176 """Field properties based on Archetypes schema
177
178 These properties can only be used on Archetypes objects. They delegate
179 to schema.getField(fieldname).get() and set().
180
181 You can use it in your type as follows. The name of the field does
182 not need to conincide with the field-property name, but this is probably
183 sensible. However, AttributeStorage will interfere here, so we explicitly
184 use annoation storage.
185
186 >>> import string
187 >>> from Products.Archetypes.atapi import *
188 >>> from icsemantic.core.fieldproperty import ATFieldProperty
189
190 >>> class MyContent(BaseObject):
191 ... portal_type = meta_type = 'MyContent'
192 ... schema = Schema((
193 ... StringField('some_field', storage=AnnotationStorage()),
194 ... StringField('_other_field'),
195 ... ))
196 ...
197 ... some_field = ATFieldProperty('some_field')
198 ... other_field = ATFieldProperty('_other_field')
199 ... upper_lower = ATFieldProperty('_other_field',
200 ... get_transform=string.upper, set_transform=string.lower)
201
202 >>> registerType(MyContent, 'Archetypes')
203
204 Now, get and set operations on the fieldproperty behave the same way as
205 the mutator and accessor.
206
207 >>> foo = MyContent('foo')
208 >>> foo.some_field
209 ''
210 >>> foo.some_field = "Bar"
211 >>> foo.some_field
212 'Bar'
213 >>> foo.getField('some_field').get(foo)
214 'Bar'
215
216 The old-style mutator and accessors still work, of course
217
218 >>> foo.getSome_field()
219 'Bar'
220
221 >>> foo.setSome_field("Baz")
222 >>> foo.some_field
223 'Baz'
224
225 Here is an example using the default AttributeStorage. In this case, we
226 need different names for the AT field name and the properity, because
227 AttributeStorage will use the field name as the attribute name. If
228 you don't do this, you may get infinite recursion!
229
230 >>> foo.other_field = "Hello"
231 >>> foo.other_field
232 'Hello'
233 >>> foo.get_other_field()
234 'Hello'
235 >>> foo.set_other_field("Good bye")
236 >>> foo.other_field
237 'Good bye'
238
239 Finally, the get_transform and set_transform arguments can be used to
240 perform transformations on the retrieved value and the value before it
241 is set, respectively. The field upper_lower uses string.upper() on the
242 way out and string.lower() on the way in.
243
244 >>> foo.upper_lower = "MiXeD"
245 >>> foo.upper_lower
246 'MIXED'
247 >>> foo.get_other_field()
248 'mixed'
249 >>> foo.set_other_field('UpPeRaNdLoWeR')
250 >>> foo.upper_lower
251 'UPPERANDLOWER'
252
253 A less frivolous example of this functionality can be seen in the
254 ATDateTimeFieldProperty class below.
255 """
256
257 - def __init__(self, name, get_transform=None, set_transform=None):
258 self._name = name
259 self._get_transform = get_transform
260 self._set_transform = set_transform
261
263 if inst is None:
264 return self
265 field = inst.getField(self._name)
266 if field is None:
267 raise KeyError("Cannot find field with name %s" % self._name)
268 value = field.get(inst)
269 if not value:
270 es_inst = inst.getTranslations()['es'][0]
271 field = es_inst.getField(self._name)
272 if field is None:
273 raise KeyError("Cannot find field with name %s" % self._name)
274 value = field.get(es_inst)
275 if self._get_transform is not None:
276 value = self._get_transform(value)
277 return value
278
280 field = inst.getField(self._name)
281 if field is None:
282 raise KeyError("Cannot find field with name %s" % self._name)
283 if self._set_transform is not None:
284 value = self._set_transform(value)
285 field.set(inst, value)
286
287 _marker = object()
288
362