|
@@ -10,11 +10,15 @@ import importlib
|
10
|
10
|
import re
|
11
|
11
|
import copy
|
12
|
12
|
|
13
|
|
-## @file fieldtypes.py
|
14
|
|
-# This file contains classes about SQL column (EmFieldType)
|
15
|
|
-# and their values (EmFieldValue)
|
16
|
|
-# For the moment the code is in quick & dirty version and is
|
17
|
|
-# more like a proof of concept
|
|
13
|
+## @namespace EditorialModel.fieldtypes
|
|
14
|
+# @brief This file contains classes about SQL column (EmFieldType) and their values (EmFieldValue)
|
|
15
|
+#
|
|
16
|
+# The underlying concept is to handle two differents objects, one for handling an SQL column definition (EmFieldType)
|
|
17
|
+# and another one to handle values (EmFieldValue). This organisation allows to have large, flexible and powerfull mains objects and to
|
|
18
|
+# specialise them by inheritance ( EmFieldType -> EmField_char -> EmField_MlString ) ( EmFieldValue -> EmFieldValue_int )
|
|
19
|
+#
|
|
20
|
+# @note For the moment the code is a bit in quick and dirty mode.
|
|
21
|
+#
|
18
|
22
|
|
19
|
23
|
## @brief Handles SQL types
|
20
|
24
|
# This class handles SQL types and their options.
|
|
@@ -89,13 +93,23 @@ class EmFieldSQLType(object):
|
89
|
93
|
return cl._names[name]['sql'](**kwargs)
|
90
|
94
|
|
91
|
95
|
|
92
|
|
-
|
|
96
|
+## @brief Characterise fields for LeObject and EmComponent
|
|
97
|
+# This class handles values rules for LeObject and EmComponents.
|
|
98
|
+#
|
|
99
|
+# It allows to EmFieldValue classes family to have rules to cast, validate and save values.
|
|
100
|
+#
|
|
101
|
+# There is exposed methods that allows LeObject and EmType to run a save sequence. This methods are :
|
|
102
|
+# - EmFieldType.to_value() That cast a value to an EmFieldType internal storage
|
|
103
|
+# - EmFieldType.is_valid() That indicates wether or not a value is valid
|
|
104
|
+# - EmFieldType.pre_save() That returns weighted SQL request that must be run before any value save @ref EditorialModel::types::EmType.save_values()
|
|
105
|
+# - EmFieldType.to_sql() That returns a value that can be inserted in database.
|
|
106
|
+# - EmFieldType.post_save() That returns weighted SQL request that must be run after any value save @ref EditorialModel::types::EmType.save_values()
|
|
107
|
+#
|
93
|
108
|
class EmFieldType(object):
|
94
|
109
|
|
95
|
110
|
## Stores options and default value for EmFieldType
|
96
|
111
|
# options list :
|
97
|
112
|
# - type (str|None) : if None will make an 'abstract' fieldtype (with no value assignement possible)
|
98
|
|
- # - size (int) : The size for this type
|
99
|
113
|
# - nullable (bool) : tell whether or not a fieldType accept NULL value
|
100
|
114
|
# - default (mixed) : The default value for a FieldType
|
101
|
115
|
# - primarykey (bool) : If true the fieldType represent a PK
|
|
@@ -105,11 +119,11 @@ class EmFieldType(object):
|
105
|
119
|
# - doc (str) : FieldType documentation
|
106
|
120
|
# - onupdate (callable) : A callback to call on_update
|
107
|
121
|
# - valueobject (EmFieldValue or childs) : An object that represent values for this fieldType
|
108
|
|
- # - type_* (mixed) : Use to construct an options dictinnary for a type (exemple : type_length => nnewColumn(lenght= [type_lenght VALUE] ))
|
|
122
|
+ # - type_* (mixed) : Use to construct an options dictinnary for a type (exemple : type_length => nnewColumn(lenght= [type_lenght VALUE] )) @ref EmFieldSQLType
|
|
123
|
+ #
|
109
|
124
|
_opt = {
|
110
|
125
|
'name' : None,
|
111
|
126
|
'type' : None,
|
112
|
|
- 'size': None,
|
113
|
127
|
'nullable': True,
|
114
|
128
|
'default' : None,
|
115
|
129
|
'primarykey': False,
|
|
@@ -124,6 +138,7 @@ class EmFieldType(object):
|
124
|
138
|
|
125
|
139
|
## Instanciate an EmFieldType
|
126
|
140
|
# For arguments see @ref EmFieldType::_opt
|
|
141
|
+ # @see EmFieldType::_opt
|
127
|
142
|
def __init__(self, **kwargs):
|
128
|
143
|
self._init(kwargs)
|
129
|
144
|
self.type_options = dict()
|
|
@@ -246,6 +261,30 @@ class EmFieldType(object):
|
246
|
261
|
raise NotImplementedError("This EmFieldType is abstract")
|
247
|
262
|
return value
|
248
|
263
|
|
|
264
|
+ ## Return wether or not a value is valid for this EmFieldType
|
|
265
|
+ # @note This function always return True and is here for being overloaded by childs objects
|
|
266
|
+ # @return A boolean, True if valid else False
|
|
267
|
+ def is_valid(self, value):
|
|
268
|
+ if self.abstract:
|
|
269
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
270
|
+ return True
|
|
271
|
+
|
|
272
|
+ ## @brief Return a list of (priority, SqlRequest) tuples designed to be executed before saving values in Db
|
|
273
|
+ # @note This function return an empty array and is here for being overloaded by childs objects
|
|
274
|
+ # @return A list of (priority, SqlRequest) tuples
|
|
275
|
+ def pre_save(self):
|
|
276
|
+ if self.abstract:
|
|
277
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
278
|
+ return []
|
|
279
|
+
|
|
280
|
+ ## @brief Return a list of (priority, SqlRequest) tuples designed to be executed after values were saved in Db
|
|
281
|
+ # @note This function return an empty array and is here for being overloaded by childs objects
|
|
282
|
+ # @return A list of (priority, SqlRequest) tuples
|
|
283
|
+ def post_save(self):
|
|
284
|
+ if self.abstract:
|
|
285
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
286
|
+ return []
|
|
287
|
+
|
249
|
288
|
@classmethod
|
250
|
289
|
## Function designed to be called by child class to enforce a type
|
251
|
290
|
# @param args dict: The kwargs argument of __init__
|
|
@@ -280,6 +319,9 @@ class EmFieldType(object):
|
280
|
319
|
return args
|
281
|
320
|
|
282
|
321
|
|
|
322
|
+## @brief Handles EmFieldType values
|
|
323
|
+# This class is designed to be linked with an EmFieldType and to handles values according to the linked EmFieldType rules
|
|
324
|
+# @see EmFieldType
|
283
|
325
|
class EmFieldValue(object):
|
284
|
326
|
|
285
|
327
|
## Instanciate a EmFieldValue
|
|
@@ -346,7 +388,7 @@ class EmFieldValue(object):
|
346
|
388
|
return super(EmFieldValue, self).__getattribute__(name)
|
347
|
389
|
|
348
|
390
|
|
349
|
|
- ## @brief Return an sql valid value
|
|
391
|
+ ## @brief Return a valid SQL value
|
350
|
392
|
#
|
351
|
393
|
# Can be used to convert any value (giving one positionnal argument) or to return the current value
|
352
|
394
|
# @param *value list: If a positionnal argument is given return it and not the instance value
|
|
@@ -358,7 +400,7 @@ class EmFieldValue(object):
|
358
|
400
|
return self.fieldtype.to_sql(value[0])
|
359
|
401
|
return self.fieldtype.to_sql(self.value)
|
360
|
402
|
|
361
|
|
-## @brief Designed to handle values that has common arithmetic operations
|
|
403
|
+## @brief Represents values with common arithmetic operations
|
362
|
404
|
class EmFieldValue_int(EmFieldValue):
|
363
|
405
|
|
364
|
406
|
def __int__(self):
|
|
@@ -394,16 +436,20 @@ class EmFieldValue_int(EmFieldValue):
|
394
|
436
|
def __idiv__(self, other):
|
395
|
437
|
self.value = int(self.value / other)
|
396
|
438
|
return self
|
397
|
|
-
|
|
439
|
+
|
|
440
|
+## @brief Handles integer fields
|
|
441
|
+# @note Enforcing type to be int
|
|
442
|
+# @note Default name is 'integer' and default 'valueobject' is EmFieldValue_int
|
398
|
443
|
class EmField_integer(EmFieldType):
|
399
|
444
|
def __init__(self, **kwargs):
|
400
|
445
|
self._init(kwargs)
|
401
|
446
|
#Default name
|
402
|
447
|
kwargs = self.__class__._argDefault(kwargs, 'name', 'integer')
|
|
448
|
+ #Default value object
|
|
449
|
+ kwargs = self.__class__._argDefault(kwargs, 'valueobject', EmFieldValue_int)
|
403
|
450
|
#Type enforcing
|
404
|
451
|
kwargs = self.__class__._setType(kwargs, 'int')
|
405
|
452
|
super(EmField_integer, self).__init__(**kwargs)
|
406
|
|
- self.valueobject = EmFieldValue_int
|
407
|
453
|
pass
|
408
|
454
|
##
|
409
|
455
|
# @todo catch cast error ?
|
|
@@ -415,9 +461,9 @@ class EmField_integer(EmFieldType):
|
415
|
461
|
return super(EmField_integer, self).to_value(value)
|
416
|
462
|
return int(value)
|
417
|
463
|
|
418
|
|
-## EmField_boolean (Class)
|
419
|
|
-#
|
420
|
|
-# Boolean field type
|
|
464
|
+## @brief Handles boolean fields
|
|
465
|
+# @note Enforce type to be 'boolean'
|
|
466
|
+# @note Default name is 'boolean'
|
421
|
467
|
class EmField_boolean(EmFieldType):
|
422
|
468
|
def __init__(self, **kwargs):
|
423
|
469
|
self._init(kwargs)
|
|
@@ -435,9 +481,10 @@ class EmField_boolean(EmFieldType):
|
435
|
481
|
self.value = bool(value)
|
436
|
482
|
return self.value
|
437
|
483
|
|
438
|
|
-## EmField_char (Class)
|
439
|
|
-#
|
440
|
|
-# Varchar field type
|
|
484
|
+## @brief Handles string fields
|
|
485
|
+# @note Enforce type to be (varchar)
|
|
486
|
+# @note Default 'name' is 'char'
|
|
487
|
+# @note Default 'type_length' is 76
|
441
|
488
|
class EmField_char(EmFieldType):
|
442
|
489
|
default_length = 76
|
443
|
490
|
def __init__(self, **kwargs):
|
|
@@ -449,7 +496,8 @@ class EmField_char(EmFieldType):
|
449
|
496
|
super(EmField_char, self).__init__(**kwargs)
|
450
|
497
|
def to_sql(self, value):
|
451
|
498
|
return str(value)
|
452
|
|
-##
|
|
499
|
+## @brief Handles date fields
|
|
500
|
+# @note Enforce type to be 'datetime'
|
453
|
501
|
# @todo rename to EmField_datetime
|
454
|
502
|
# @todo timezones support
|
455
|
503
|
class EmField_date(EmFieldType):
|
|
@@ -472,6 +520,7 @@ class EmField_date(EmFieldType):
|
472
|
520
|
if isinstance(value, datetime.datetime):
|
473
|
521
|
return value
|
474
|
522
|
|
|
523
|
+## @brief Handles strings with translations
|
475
|
524
|
class EmField_mlstring(EmField_char):
|
476
|
525
|
|
477
|
526
|
def __init__(self, **kwargs):
|
|
@@ -491,6 +540,7 @@ class EmField_mlstring(EmField_char):
|
491
|
540
|
return value
|
492
|
541
|
raise TypeError("<class str> or <class MlString> excepted. But got "+str(type(value)))
|
493
|
542
|
|
|
543
|
+## @brief Handles lodel uid fields
|
494
|
544
|
class EmField_uid(EmField_integer):
|
495
|
545
|
def __init__(self, **kwargs):
|
496
|
546
|
self._init(kwargs)
|