Package couchdbkit :: Package schema :: Module properties_proxy
[hide private]
[frames] | no frames]

Source Code for Module couchdbkit.schema.properties_proxy

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of couchdbkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  5   
  6  """ Meta properties """ 
  7   
  8  from calendar import timegm 
  9  import datetime 
 10  import decimal 
 11  import time 
 12   
 13  from ..exceptions import BadValueError  
 14   
 15  from .base import DocumentSchema, ALLOWED_PROPERTY_TYPES 
 16  from .properties import Property 
 17   
 18  __all__ = ['SchemaProperty', 'SchemaListProperty', 'SchemaDictProperty'] 
 19   
20 -class SchemaProperty(Property):
21 """ Schema property. It allows you add a DocumentSchema instance 22 a member of a Document object. It returns a 23 `schemaDocumentSchema` object. 24 25 Exemple : 26 27 >>> from couchdbkit import * 28 >>> class Blog(DocumentSchema): 29 ... title = StringProperty() 30 ... author = StringProperty(default="me") 31 ... 32 >>> class Entry(Document): 33 ... title = StringProperty() 34 ... body = StringProperty() 35 ... blog = SchemaProperty(Blog()) 36 ... 37 >>> test = Entry() 38 >>> test._doc 39 {'body': None, 'doc_type': 'Entry', 'title': None, 'blog': {'doc_type': 'Blog', 'author': u'me', 'title': None}} 40 >>> test.blog.title = "Mon Blog" 41 >>> test._doc 42 {'body': None, 'doc_type': 'Entry', 'title': None, 'blog': {'doc_type': 'Blog', 'author': u'me', 'title': u'Mon Blog'}} 43 >>> test.blog.title 44 u'Mon Blog' 45 >>> from couchdbkit import Server 46 >>> s = Server() 47 >>> db = s.create_db('couchdbkit_test') 48 >>> Entry._db = db 49 >>> test.save() 50 >>> doc = Entry.objects.get(test.id) 51 >>> doc.blog.title 52 u'Mon Blog' 53 >>> del s['simplecouchdb_test'] 54 55 """ 56
57 - def __init__(self, schema, verbose_name=None, name=None, 58 required=False, validators=None, default=None):
59 60 Property.__init__(self, verbose_name=None, 61 name=None, required=False, validators=None) 62 63 use_instance = True 64 if isinstance(schema, type): 65 use_instance = False 66 67 elif not isinstance(schema, DocumentSchema): 68 raise TypeError('schema should be a DocumentSchema instance') 69 70 elif schema.__class__.__name__ == 'DocumentSchema': 71 use_instance = False 72 properties = schema._dynamic_properties.copy() 73 schema = DocumentSchema.build(**properties) 74 75 self._use_instance = use_instance 76 self._schema = schema
77
78 - def default_value(self):
79 if not self._use_instance: 80 return self._schema() 81 return self._schema.clone()
82
83 - def empty(self, value):
84 if not hasattr(value, '_doc'): 85 return True 86 if not value._doc or value._doc is None: 87 return True 88 return False
89
90 - def validate(self, value, required=True):
91 value.validate(required=required) 92 value = super(SchemaProperty, self).validate(value) 93 94 if value is None: 95 return value 96 97 if not isinstance(value, DocumentSchema): 98 raise BadValueError( 99 'Property %s must be DocumentSchema instance, not a %s' % (self.name, 100 type(value).__name__)) 101 102 return value
103
104 - def to_python(self, value):
105 if not self._use_instance: 106 schema = self._schema() 107 else: 108 schema = self._schema.clone() 109 110 if not self._use_instance: 111 schema = self._schema 112 else: 113 schema = self._schema.__class__ 114 return schema.wrap(value)
115
116 - def to_json(self, value):
117 if not isinstance(value, DocumentSchema): 118 if not self._use_instance: 119 schema = self._schema() 120 else: 121 schema = self._schema.clone() 122 123 if not isinstance(value, dict): 124 raise BadValueError("%s is not a dict" % str(value)) 125 value = schema(**value) 126 127 return value._doc
128
129 -class SchemaListProperty(Property):
130 """A property that stores a list of things. 131 132 """
133 - def __init__(self, schema, verbose_name=None, default=None, 134 required=False, **kwds):
135 136 Property.__init__(self, verbose_name, default=default, 137 required=required, **kwds) 138 139 use_instance = True 140 if isinstance(schema, type): 141 use_instance = False 142 143 elif not isinstance(schema, DocumentSchema): 144 raise TypeError('schema should be a DocumentSchema instance') 145 146 elif schema.__class__.__name__ == 'DocumentSchema': 147 use_instance = False 148 properties = schema._dynamic_properties.copy() 149 schema = DocumentSchema.build(**properties) 150 151 self._use_instance = use_instance 152 self._schema = schema
153
154 - def validate(self, value, required=True):
155 value = super(SchemaListProperty, self).validate(value, required=required) 156 if value and value is not None: 157 if not isinstance(value, list): 158 raise BadValueError('Property %s must be a list' % self.name) 159 value = self.validate_list_schema(value, required=required) 160 return value
161
162 - def validate_list_schema(self, value, required=True):
163 for v in value: 164 v.validate(required=required) 165 return value
166
167 - def default_value(self):
168 return []
169
170 - def to_python(self, value):
171 return LazySchemaList(value, self._schema, self._use_instance)
172
173 - def to_json(self, value):
174 return [svalue_to_json(v, self._schema, self._use_instance) for v in value]
175 176
177 -class LazySchemaList(list):
178
179 - def __init__(self, doc, schema, use_instance, init_vals=None):
180 list.__init__(self) 181 182 self.schema = schema 183 self.use_instance = use_instance 184 self.doc = doc 185 if init_vals is None: 186 # just wrap the current values 187 self._wrap() 188 else: 189 # initialize this list and the underlying list 190 # with the values given. 191 del self.doc[:] 192 for item in init_vals: 193 self.append(item)
194
195 - def _wrap(self):
196 for v in self.doc: 197 if not self.use_instance: 198 schema = self.schema() 199 else: 200 schema = self.schema.clone() 201 202 value = schema.wrap(v) 203 list.append(self, value)
204
205 - def __delitem__(self, index):
206 del self.doc[index] 207 list.__delitem__(self, index)
208
209 - def __setitem__(self, index, value):
210 self.doc[index] = svalue_to_json(value, self.schema, 211 self.use_instance) 212 list.__setitem__(self, index, value)
213
214 - def append(self, *args, **kwargs):
215 if args: 216 assert len(args) == 1 217 value = args[0] 218 else: 219 value = kwargs 220 221 index = len(self) 222 self.doc.append(svalue_to_json(value, self.schema, 223 self.use_instance)) 224 super(LazySchemaList, self).append(value)
225 226
227 -class SchemaDictProperty(Property):
228 """A property that stores a dict of things. 229 230 """
231 - def __init__(self, schema, verbose_name=None, default=None, 232 required=False, **kwds):
233 234 Property.__init__(self, verbose_name, default=default, 235 required=required, **kwds) 236 237 use_instance = True 238 if isinstance(schema, type): 239 use_instance = False 240 241 elif not isinstance(schema, DocumentSchema): 242 raise TypeError('schema should be a DocumentSchema instance') 243 244 elif schema.__class__.__name__ == 'DocumentSchema': 245 use_instance = False 246 properties = schema._dynamic_properties.copy() 247 schema = DocumentSchema.build(**properties) 248 249 self._use_instance = use_instance 250 self._schema = schema
251
252 - def validate(self, value, required=True):
253 value = super(SchemaDictProperty, self).validate(value, required=required) 254 if value and value is not None: 255 if not isinstance(value, dict): 256 raise BadValueError('Property %s must be a dict' % self.name) 257 value = self.validate_dict_schema(value, required=required) 258 return value
259
260 - def validate_dict_schema(self, value, required=True):
261 for v in value.values(): 262 v.validate(required=required) 263 return value
264
265 - def default_value(self):
266 return {}
267
268 - def to_python(self, value):
269 return LazySchemaDict(value, self._schema, self._use_instance)
270
271 - def to_json(self, value):
272 return dict([(k, svalue_to_json(v, self._schema, self._use_instance)) for k, v in value.items()])
273 274
275 -class LazySchemaDict(dict):
276
277 - def __init__(self, doc, schema, use_instance, init_vals=None):
278 dict.__init__(self) 279 280 self.schema = schema 281 self.use_instance = use_instance 282 self.doc = doc 283 if init_vals is None: 284 # just wrap the current values 285 self._wrap() 286 else: 287 # initialize this dict and the underlying dict 288 # with the values given. 289 del self.doc[:] 290 for k, v in init_vals: 291 self[k] = self._wrap(v)
292
293 - def _wrap(self):
294 for k, v in self.doc.items(): 295 if not self.use_instance: 296 schema = self.schema() 297 else: 298 schema = self.schema.clone() 299 300 value = schema.wrap(v) 301 dict.__setitem__(self, k, value)
302
303 - def __delitem__(self, index):
304 index = str(index) 305 del self.doc[index] 306 dict.__delitem__(self, index)
307
308 - def __getitem__(self, index):
309 index = str(index) 310 return dict.__getitem__(self, index)
311
312 - def __setitem__(self, index, value):
313 index = str(index) 314 self.doc[index] = svalue_to_json(value, self.schema, 315 self.use_instance) 316 dict.__setitem__(self, index, value)
317 318
319 -def svalue_to_json(value, schema, use_instance):
320 if not isinstance(value, DocumentSchema): 321 if not use_instance: 322 schema = schema() 323 else: 324 schema = schema.clone() 325 326 if not isinstance(value, dict): 327 raise BadValueError("%s is not a dict" % str(value)) 328 value = schema(**value) 329 return value._doc
330